44 #include "ethernet.h" |
44 #include "ethernet.h" |
45 |
45 |
46 /*****************************************************************************/ |
46 /*****************************************************************************/ |
47 |
47 |
48 void ec_master_freerun(unsigned long); |
48 void ec_master_freerun(unsigned long); |
49 void ec_master_run_eoe(void *); |
49 void ec_master_run_eoe(unsigned long); |
50 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
50 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
51 void ec_master_process_watch_command(ec_master_t *); |
51 void ec_master_process_watch_command(ec_master_t *); |
52 |
52 |
53 /*****************************************************************************/ |
53 /*****************************************************************************/ |
54 |
54 |
111 // init freerun timer |
111 // init freerun timer |
112 init_timer(&master->freerun_timer); |
112 init_timer(&master->freerun_timer); |
113 master->freerun_timer.function = ec_master_freerun; |
113 master->freerun_timer.function = ec_master_freerun; |
114 master->freerun_timer.data = (unsigned long) master; |
114 master->freerun_timer.data = (unsigned long) master; |
115 |
115 |
116 master->eoe_wq = NULL; |
116 // init eoe timer |
117 INIT_WORK(&master->eoe_work, ec_master_run_eoe, master); |
117 init_timer(&master->eoe_timer); |
|
118 master->eoe_timer.function = ec_master_run_eoe; |
|
119 master->eoe_timer.data = (unsigned long) master; |
118 |
120 |
119 ec_command_init(&master->simple_command); |
121 ec_command_init(&master->simple_command); |
120 ec_command_init(&master->watch_command); |
122 ec_command_init(&master->watch_command); |
121 |
123 |
122 ec_master_reset(master); |
124 ec_master_reset(master); |
135 { |
137 { |
136 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
138 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
137 |
139 |
138 EC_INFO("Clearing master %i...\n", master->index); |
140 EC_INFO("Clearing master %i...\n", master->index); |
139 |
141 |
|
142 del_timer_sync(&master->eoe_timer); |
140 del_timer_sync(&master->freerun_timer); |
143 del_timer_sync(&master->freerun_timer); |
141 |
144 |
142 ec_master_reset(master); |
145 ec_master_reset(master); |
143 |
146 |
144 if (master->device) { |
147 if (master->device) { |
146 kfree(master->device); |
149 kfree(master->device); |
147 } |
150 } |
148 |
151 |
149 ec_command_clear(&master->simple_command); |
152 ec_command_clear(&master->simple_command); |
150 ec_command_clear(&master->watch_command); |
153 ec_command_clear(&master->watch_command); |
151 |
|
152 if (master->eoe_wq) destroy_workqueue(master->eoe_wq); |
|
153 |
154 |
154 EC_INFO("Master %i cleared.\n", master->index); |
155 EC_INFO("Master %i cleared.\n", master->index); |
155 } |
156 } |
156 |
157 |
157 /*****************************************************************************/ |
158 /*****************************************************************************/ |
168 ec_command_t *command, *next_c; |
169 ec_command_t *command, *next_c; |
169 ec_domain_t *domain, *next_d; |
170 ec_domain_t *domain, *next_d; |
170 ec_eoe_t *eoe, *next_eoe; |
171 ec_eoe_t *eoe, *next_eoe; |
171 |
172 |
172 // stop EoE processing |
173 // stop EoE processing |
173 if (master->eoe_wq && !cancel_delayed_work(&master->eoe_work)) { |
174 del_timer_sync(&master->eoe_timer); |
174 flush_workqueue(master->eoe_wq); |
175 |
175 } |
176 // stop free-run mode |
176 |
|
177 ec_master_freerun_stop(master); |
177 ec_master_freerun_stop(master); |
178 |
178 |
179 // remove all slaves |
179 // remove all slaves |
180 list_for_each_entry_safe(slave, next_s, &master->slaves, list) { |
180 list_for_each_entry_safe(slave, next_s, &master->slaves, list) { |
181 list_del(&slave->list); |
181 list_del(&slave->list); |
262 { |
262 { |
263 ec_command_t *command; |
263 ec_command_t *command; |
264 size_t command_size; |
264 size_t command_size; |
265 uint8_t *frame_data, *cur_data; |
265 uint8_t *frame_data, *cur_data; |
266 void *follows_word; |
266 void *follows_word; |
267 cycles_t start = 0, end; |
267 cycles_t t_start, t_end; |
268 unsigned int frame_count, more_commands_waiting; |
268 unsigned int frame_count, more_commands_waiting; |
269 |
269 |
270 frame_count = 0; |
270 frame_count = 0; |
271 |
271 t_start = get_cycles(); |
272 if (unlikely(master->debug_level > 0)) { |
272 |
|
273 if (unlikely(master->debug_level > 0)) |
273 EC_DBG("ec_master_send_commands\n"); |
274 EC_DBG("ec_master_send_commands\n"); |
274 start = get_cycles(); |
|
275 } |
|
276 |
275 |
277 do { |
276 do { |
278 // fetch pointer to transmit socket buffer |
277 // fetch pointer to transmit socket buffer |
279 frame_data = ec_device_tx_data(master->device); |
278 frame_data = ec_device_tx_data(master->device); |
280 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
279 cur_data = frame_data + EC_FRAME_HEADER_SIZE; |
292 more_commands_waiting = 1; |
291 more_commands_waiting = 1; |
293 break; |
292 break; |
294 } |
293 } |
295 |
294 |
296 command->state = EC_CMD_SENT; |
295 command->state = EC_CMD_SENT; |
|
296 command->t_sent = t_start; |
297 command->index = master->command_index++; |
297 command->index = master->command_index++; |
298 |
298 |
299 if (unlikely(master->debug_level > 0)) |
299 if (unlikely(master->debug_level > 0)) |
300 EC_DBG("adding command 0x%02X\n", command->index); |
300 EC_DBG("adding command 0x%02X\n", command->index); |
301 |
301 |
343 frame_count++; |
343 frame_count++; |
344 } |
344 } |
345 while (more_commands_waiting); |
345 while (more_commands_waiting); |
346 |
346 |
347 if (unlikely(master->debug_level > 0)) { |
347 if (unlikely(master->debug_level > 0)) { |
348 end = get_cycles(); |
348 t_end = get_cycles(); |
349 EC_DBG("ec_master_send_commands sent %i frames in %ius.\n", |
349 EC_DBG("ec_master_send_commands sent %i frames in %ius.\n", |
350 frame_count, (u32) (end - start) * 1000 / cpu_khz); |
350 frame_count, (u32) (t_end - t_start) * 1000 / cpu_khz); |
351 } |
351 } |
352 } |
352 } |
353 |
353 |
354 /*****************************************************************************/ |
354 /*****************************************************************************/ |
355 |
355 |
842 |
842 |
843 /** |
843 /** |
844 Does the Ethernet-over-EtherCAT processing. |
844 Does the Ethernet-over-EtherCAT processing. |
845 */ |
845 */ |
846 |
846 |
847 void ec_master_run_eoe(void *data /**< work data (= master pointer) */) |
847 void ec_master_run_eoe(unsigned long data /**< master pointer */) |
848 { |
848 { |
849 ec_master_t *master = (ec_master_t *) data; |
849 ec_master_t *master = (ec_master_t *) data; |
850 |
|
851 #if 0 |
|
852 ec_eoe_t *eoe; |
850 ec_eoe_t *eoe; |
853 |
851 |
|
852 if (!master->request_cb(master->cb_data)) goto restart_timer; |
|
853 |
|
854 ecrt_master_async_receive(master); |
854 list_for_each_entry(eoe, &master->eoe_slaves, list) { |
855 list_for_each_entry(eoe, &master->eoe_slaves, list) { |
855 ec_eoe_run(eoe); |
856 ec_eoe_run(eoe); |
856 } |
857 } |
857 #endif |
858 ecrt_master_async_send(master); |
858 |
859 |
859 queue_delayed_work(master->eoe_wq, &master->eoe_work, HZ); |
860 master->release_cb(master->cb_data); |
|
861 |
|
862 restart_timer: |
|
863 master->eoe_timer.expires += HZ / 4; |
|
864 add_timer(&master->eoe_timer); |
860 } |
865 } |
861 |
866 |
862 /****************************************************************************** |
867 /****************************************************************************** |
863 * Realtime interface |
868 * Realtime interface |
864 *****************************************************************************/ |
869 *****************************************************************************/ |
1230 */ |
1235 */ |
1231 |
1236 |
1232 void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) |
1237 void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */) |
1233 { |
1238 { |
1234 ec_command_t *command, *next; |
1239 ec_command_t *command, *next; |
|
1240 cycles_t t_received, t_timeout; |
1235 |
1241 |
1236 ec_device_call_isr(master->device); |
1242 ec_device_call_isr(master->device); |
|
1243 |
|
1244 t_received = get_cycles(); |
|
1245 t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); |
1237 |
1246 |
1238 // dequeue all received commands |
1247 // dequeue all received commands |
1239 list_for_each_entry_safe(command, next, &master->command_queue, queue) |
1248 list_for_each_entry_safe(command, next, &master->command_queue, queue) |
1240 if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); |
1249 if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); |
1241 |
1250 |
1242 // dequeue all remaining commands |
1251 // dequeue all commands that timed out |
1243 list_for_each_entry_safe(command, next, &master->command_queue, queue) { |
1252 list_for_each_entry_safe(command, next, &master->command_queue, queue) { |
1244 switch (command->state) { |
1253 switch (command->state) { |
1245 case EC_CMD_SENT: |
1254 case EC_CMD_SENT: |
1246 case EC_CMD_QUEUED: |
1255 case EC_CMD_QUEUED: |
1247 command->state = EC_CMD_TIMEOUT; |
1256 if (t_received - command->t_sent > t_timeout) { |
1248 master->stats.timeouts++; |
1257 list_del_init(&command->queue); |
1249 ec_master_output_stats(master); |
1258 command->state = EC_CMD_TIMEOUT; |
|
1259 master->stats.timeouts++; |
|
1260 ec_master_output_stats(master); |
|
1261 } |
1250 break; |
1262 break; |
1251 default: |
1263 default: |
1252 break; |
1264 break; |
1253 } |
1265 } |
1254 list_del_init(&command->queue); |
|
1255 } |
1266 } |
1256 } |
1267 } |
1257 |
1268 |
1258 /*****************************************************************************/ |
1269 /*****************************************************************************/ |
1259 |
1270 |
1463 if (list_empty(&master->eoe_slaves)) { |
1474 if (list_empty(&master->eoe_slaves)) { |
1464 EC_WARN("start_eoe: no EoE-capable slaves present.\n"); |
1475 EC_WARN("start_eoe: no EoE-capable slaves present.\n"); |
1465 return 0; |
1476 return 0; |
1466 } |
1477 } |
1467 |
1478 |
1468 // create the EoE workqueue, if necessary |
|
1469 if (!master->eoe_wq) { |
|
1470 if (!(master->eoe_wq = create_singlethread_workqueue("eoework"))) { |
|
1471 EC_ERR("Failed to create EoE workqueue!\n"); |
|
1472 return -1; |
|
1473 } |
|
1474 } |
|
1475 |
|
1476 // start EoE processing |
1479 // start EoE processing |
1477 queue_work(master->eoe_wq, &master->eoe_work); |
1480 master->eoe_timer.expires = jiffies + 10; |
|
1481 add_timer(&master->eoe_timer); |
1478 return 0; |
1482 return 0; |
1479 } |
1483 } |
1480 |
1484 |
1481 /*****************************************************************************/ |
1485 /*****************************************************************************/ |
1482 |
1486 |