145 #endif |
145 #endif |
146 } |
146 } |
147 |
147 |
148 /*****************************************************************************/ |
148 /*****************************************************************************/ |
149 |
149 |
150 /** |
150 /** Associate with net_device. |
151 Associate with net_device. |
151 */ |
152 */ |
152 void ec_device_attach( |
153 |
153 ec_device_t *device, /**< EtherCAT device */ |
154 void ec_device_attach(ec_device_t *device, /**< EtherCAT device */ |
|
155 struct net_device *net_dev, /**< net_device structure */ |
154 struct net_device *net_dev, /**< net_device structure */ |
156 ec_pollfunc_t poll, /**< pointer to device's poll function */ |
155 ec_pollfunc_t poll, /**< pointer to device's poll function */ |
157 struct module *module /**< the device's module */ |
156 struct module *module /**< the device's module */ |
158 ) |
157 ) |
159 { |
158 { |
194 device->tx_skb[i]->dev = NULL; |
193 device->tx_skb[i]->dev = NULL; |
195 } |
194 } |
196 |
195 |
197 /*****************************************************************************/ |
196 /*****************************************************************************/ |
198 |
197 |
199 /** |
198 /** Opens the EtherCAT device. |
200 Opens the EtherCAT device. |
199 * |
201 \return 0 in case of success, else < 0 |
200 * \return 0 in case of success, else < 0 |
202 */ |
201 */ |
203 |
202 int ec_device_open( |
204 int ec_device_open(ec_device_t *device /**< EtherCAT device */) |
203 ec_device_t *device /**< EtherCAT device */ |
|
204 ) |
205 { |
205 { |
206 if (!device->dev) { |
206 if (!device->dev) { |
207 EC_ERR("No net_device to open!\n"); |
207 EC_ERR("No net_device to open!\n"); |
208 return -1; |
208 return -1; |
209 } |
209 } |
222 return device->open ? 0 : -1; |
222 return device->open ? 0 : -1; |
223 } |
223 } |
224 |
224 |
225 /*****************************************************************************/ |
225 /*****************************************************************************/ |
226 |
226 |
227 /** |
227 /** Stops the EtherCAT device. |
228 Stops the EtherCAT device. |
228 * |
229 \return 0 in case of success, else < 0 |
229 * \return 0 in case of success, else < 0 |
230 */ |
230 */ |
231 |
231 int ec_device_close( |
232 int ec_device_close(ec_device_t *device /**< EtherCAT device */) |
232 ec_device_t *device /**< EtherCAT device */ |
|
233 ) |
233 { |
234 { |
234 if (!device->dev) { |
235 if (!device->dev) { |
235 EC_ERR("No device to close!\n"); |
236 EC_ERR("No device to close!\n"); |
236 return -1; |
237 return -1; |
237 } |
238 } |
246 return !device->open ? 0 : -1; |
247 return !device->open ? 0 : -1; |
247 } |
248 } |
248 |
249 |
249 /*****************************************************************************/ |
250 /*****************************************************************************/ |
250 |
251 |
251 /** |
252 /** Returns a pointer to the device's transmit memory. |
252 Returns a pointer to the device's transmit memory. |
253 * |
253 \return pointer to the TX socket buffer |
254 * \return pointer to the TX socket buffer |
254 */ |
255 */ |
255 |
256 uint8_t *ec_device_tx_data( |
256 uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT device */) |
257 ec_device_t *device /**< EtherCAT device */ |
|
258 ) |
257 { |
259 { |
258 /* cycle through socket buffers, because otherwise there is a race |
260 /* cycle through socket buffers, because otherwise there is a race |
259 * condition, if multiple frames are sent and the DMA is not scheduled in |
261 * condition, if multiple frames are sent and the DMA is not scheduled in |
260 * between. */ |
262 * between. */ |
261 device->tx_ring_index++; |
263 device->tx_ring_index++; |
263 return device->tx_skb[device->tx_ring_index]->data + ETH_HLEN; |
265 return device->tx_skb[device->tx_ring_index]->data + ETH_HLEN; |
264 } |
266 } |
265 |
267 |
266 /*****************************************************************************/ |
268 /*****************************************************************************/ |
267 |
269 |
268 /** |
270 /** Sends the content of the transmit socket buffer. |
269 Sends the content of the transmit socket buffer. |
271 * |
270 Cuts the socket buffer content to the (now known) size, and calls the |
272 * Cuts the socket buffer content to the (now known) size, and calls the |
271 start_xmit() function of the assigned net_device. |
273 * start_xmit() function of the assigned net_device. |
272 */ |
274 */ |
273 |
275 void ec_device_send( |
274 void ec_device_send(ec_device_t *device, /**< EtherCAT device */ |
276 ec_device_t *device, /**< EtherCAT device */ |
275 size_t size /**< number of bytes to send */ |
277 size_t size /**< number of bytes to send */ |
276 ) |
278 ) |
277 { |
279 { |
278 struct sk_buff *skb = device->tx_skb[device->tx_ring_index]; |
280 struct sk_buff *skb = device->tx_skb[device->tx_ring_index]; |
279 |
281 |
280 if (unlikely(!device->link_state)) // Link down |
282 if (unlikely(!device->link_state)) // Link down |
281 return; |
283 return; |
302 } |
304 } |
303 |
305 |
304 /*****************************************************************************/ |
306 /*****************************************************************************/ |
305 |
307 |
306 #ifdef EC_DEBUG_RING |
308 #ifdef EC_DEBUG_RING |
307 /** |
309 /** Appends frame data to the debug ring. |
308 * Appends frame data to the debug ring. |
310 */ |
309 */ |
|
310 |
|
311 void ec_device_debug_ring_append( |
311 void ec_device_debug_ring_append( |
312 ec_device_t *device, /**< EtherCAT device */ |
312 ec_device_t *device, /**< EtherCAT device */ |
313 ec_debug_frame_dir_t dir, /**< direction */ |
313 ec_debug_frame_dir_t dir, /**< direction */ |
314 const void *data, /**< frame data */ |
314 const void *data, /**< frame data */ |
315 size_t size /**< data size */ |
315 size_t size /**< data size */ |
374 } |
372 } |
375 #endif |
373 #endif |
376 |
374 |
377 /*****************************************************************************/ |
375 /*****************************************************************************/ |
378 |
376 |
379 /** |
377 /** Calls the poll function of the assigned net_device. |
380 Calls the poll function of the assigned net_device. |
378 * |
381 The master itself works without using interrupts. Therefore the processing |
379 * The master itself works without using interrupts. Therefore the processing |
382 of received data and status changes of the network device has to be |
380 * of received data and status changes of the network device has to be |
383 done by the master calling the ISR "manually". |
381 * done by the master calling the ISR "manually". |
384 */ |
382 */ |
385 |
383 void ec_device_poll( |
386 void ec_device_poll(ec_device_t *device /**< EtherCAT device */) |
384 ec_device_t *device /**< EtherCAT device */ |
|
385 ) |
387 { |
386 { |
388 device->cycles_poll = get_cycles(); |
387 device->cycles_poll = get_cycles(); |
389 device->jiffies_poll = jiffies; |
388 device->jiffies_poll = jiffies; |
390 #ifdef EC_DEBUG_RING |
389 #ifdef EC_DEBUG_RING |
391 do_gettimeofday(&device->timeval_poll); |
390 do_gettimeofday(&device->timeval_poll); |
395 |
394 |
396 /****************************************************************************** |
395 /****************************************************************************** |
397 * Device interface |
396 * Device interface |
398 *****************************************************************************/ |
397 *****************************************************************************/ |
399 |
398 |
400 /** |
399 /** Withdraws an EtherCAT device from the master. |
401 Accepts a received frame. |
400 * |
402 Forwards the received data to the master. The master will analyze the frame |
401 * The device is disconnected from the master and all device ressources |
403 and dispatch the received commands to the sending instances. |
402 * are freed. |
404 \ingroup DeviceInterface |
403 * |
405 */ |
404 * \attention Before calling this function, the ecdev_stop() function has |
406 |
405 * to be called, to be sure that the master does not use the device |
407 void ecdev_receive(ec_device_t *device, /**< EtherCAT device */ |
406 * any more. |
408 const void *data, /**< pointer to received data */ |
407 * \ingroup DeviceInterface |
409 size_t size /**< number of bytes received */ |
408 */ |
410 ) |
409 void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */) |
|
410 { |
|
411 ec_master_t *master = device->master; |
|
412 char str[20]; |
|
413 |
|
414 ec_mac_print(device->dev->dev_addr, str); |
|
415 EC_INFO("Master %u releasing main device %s.\n", master->index, str); |
|
416 |
|
417 down(&master->device_sem); |
|
418 ec_device_detach(device); |
|
419 up(&master->device_sem); |
|
420 } |
|
421 |
|
422 /*****************************************************************************/ |
|
423 |
|
424 /** Opens the network device and makes the master enter IDLE mode. |
|
425 * |
|
426 * \return 0 on success, else < 0 |
|
427 * \ingroup DeviceInterface |
|
428 */ |
|
429 int ecdev_open(ec_device_t *device /**< EtherCAT device */) |
|
430 { |
|
431 if (ec_device_open(device)) { |
|
432 EC_ERR("Failed to open device!\n"); |
|
433 return -1; |
|
434 } |
|
435 |
|
436 if (ec_master_enter_idle_mode(device->master)) { |
|
437 EC_ERR("Failed to enter idle mode!\n"); |
|
438 return -1; |
|
439 } |
|
440 |
|
441 return 0; |
|
442 } |
|
443 |
|
444 /*****************************************************************************/ |
|
445 |
|
446 /** Makes the master leave IDLE mode and closes the network device. |
|
447 * |
|
448 * \return 0 on success, else < 0 |
|
449 * \ingroup DeviceInterface |
|
450 */ |
|
451 void ecdev_close(ec_device_t *device /**< EtherCAT device */) |
|
452 { |
|
453 ec_master_leave_idle_mode(device->master); |
|
454 |
|
455 if (ec_device_close(device)) |
|
456 EC_WARN("Failed to close device!\n"); |
|
457 } |
|
458 |
|
459 /*****************************************************************************/ |
|
460 |
|
461 /** Accepts a received frame. |
|
462 * |
|
463 * Forwards the received data to the master. The master will analyze the frame |
|
464 * and dispatch the received commands to the sending instances. |
|
465 * |
|
466 * \ingroup DeviceInterface |
|
467 */ |
|
468 void ecdev_receive( |
|
469 ec_device_t *device, /**< EtherCAT device */ |
|
470 const void *data, /**< pointer to received data */ |
|
471 size_t size /**< number of bytes received */ |
|
472 ) |
411 { |
473 { |
412 const void *ec_data = data + ETH_HLEN; |
474 const void *ec_data = data + ETH_HLEN; |
413 size_t ec_size = size - ETH_HLEN; |
475 size_t ec_size = size - ETH_HLEN; |
414 device->rx_count++; |
476 device->rx_count++; |
415 |
477 |
428 ec_master_receive_datagrams(device->master, ec_data, ec_size); |
490 ec_master_receive_datagrams(device->master, ec_data, ec_size); |
429 } |
491 } |
430 |
492 |
431 /*****************************************************************************/ |
493 /*****************************************************************************/ |
432 |
494 |
433 /** |
495 /** Sets a new link state. |
434 Sets a new link state. |
496 * |
435 If the device notifies the master about the link being down, the master |
497 * If the device notifies the master about the link being down, the master |
436 will not try to send frames using this device. |
498 * will not try to send frames using this device. |
437 \ingroup DeviceInterface |
499 * |
438 */ |
500 * \ingroup DeviceInterface |
439 |
501 */ |
440 void ecdev_set_link(ec_device_t *device, /**< EtherCAT device */ |
502 void ecdev_set_link( |
|
503 ec_device_t *device, /**< EtherCAT device */ |
441 uint8_t state /**< new link state */ |
504 uint8_t state /**< new link state */ |
442 ) |
505 ) |
443 { |
506 { |
444 if (unlikely(!device)) { |
507 if (unlikely(!device)) { |
445 EC_WARN("ecdev_link_state: no device!\n"); |
508 EC_WARN("ecdev_set_link(): No device!\n"); |
446 return; |
509 return; |
447 } |
510 } |
448 |
511 |
449 if (likely(state != device->link_state)) { |
512 if (likely(state != device->link_state)) { |
450 device->link_state = state; |
513 device->link_state = state; |
452 } |
515 } |
453 } |
516 } |
454 |
517 |
455 /*****************************************************************************/ |
518 /*****************************************************************************/ |
456 |
519 |
457 /** |
520 /** Reads the link state. |
458 Reads the link state. |
521 * |
459 \ingroup DeviceInterface |
522 * \ingroup DeviceInterface |
460 */ |
523 */ |
461 |
524 uint8_t ecdev_get_link( |
462 uint8_t ecdev_get_link(ec_device_t *device /**< EtherCAT device */) |
525 const ec_device_t *device /**< EtherCAT device */ |
|
526 ) |
463 { |
527 { |
464 if (unlikely(!device)) { |
528 if (unlikely(!device)) { |
465 EC_WARN("ecdev_link_state: no device!\n"); |
529 EC_WARN("ecdev_get_link(): No device!\n"); |
466 return 0; |
530 return 0; |
467 } |
531 } |
468 |
532 |
469 return device->link_state; |
533 return device->link_state; |
470 } |
534 } |
471 |
535 |
472 /*****************************************************************************/ |
536 /*****************************************************************************/ |
473 |
537 |
474 /** \cond */ |
538 /** \cond */ |
475 |
539 |
|
540 EXPORT_SYMBOL(ecdev_withdraw); |
|
541 EXPORT_SYMBOL(ecdev_open); |
|
542 EXPORT_SYMBOL(ecdev_close); |
476 EXPORT_SYMBOL(ecdev_receive); |
543 EXPORT_SYMBOL(ecdev_receive); |
477 EXPORT_SYMBOL(ecdev_get_link); |
544 EXPORT_SYMBOL(ecdev_get_link); |
478 EXPORT_SYMBOL(ecdev_set_link); |
545 EXPORT_SYMBOL(ecdev_set_link); |
479 |
546 |
480 /** \endcond */ |
547 /** \endcond */ |