96 /*****************************************************************************/ |
96 /*****************************************************************************/ |
97 |
97 |
98 /** EoE constructor. |
98 /** EoE constructor. |
99 * |
99 * |
100 * Initializes the EoE handler, creates a net_device and registers it. |
100 * Initializes the EoE handler, creates a net_device and registers it. |
|
101 * |
|
102 * \return Zero on success, otherwise a negative error code. |
101 */ |
103 */ |
102 int ec_eoe_init( |
104 int ec_eoe_init( |
103 ec_eoe_t *eoe, /**< EoE handler */ |
105 ec_eoe_t *eoe, /**< EoE handler */ |
104 ec_slave_t *slave /**< EtherCAT slave */ |
106 ec_slave_t *slave /**< EtherCAT slave */ |
105 ) |
107 ) |
109 char name[EC_DATAGRAM_NAME_SIZE]; |
111 char name[EC_DATAGRAM_NAME_SIZE]; |
110 |
112 |
111 eoe->slave = slave; |
113 eoe->slave = slave; |
112 |
114 |
113 ec_datagram_init(&eoe->datagram); |
115 ec_datagram_init(&eoe->datagram); |
114 ec_mbox_init(&eoe->mbox,&eoe->datagram); |
|
115 eoe->queue_datagram = 0; |
116 eoe->queue_datagram = 0; |
116 eoe->state = ec_eoe_state_rx_start; |
117 eoe->state = ec_eoe_state_rx_start; |
117 eoe->opened = 0; |
118 eoe->opened = 0; |
118 eoe->rx_skb = NULL; |
119 eoe->rx_skb = NULL; |
119 eoe->rx_expected_fragment = 0; |
120 eoe->rx_expected_fragment = 0; |
121 eoe->tx_frame = NULL; |
122 eoe->tx_frame = NULL; |
122 eoe->tx_queue_active = 0; |
123 eoe->tx_queue_active = 0; |
123 eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE; |
124 eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE; |
124 eoe->tx_queued_frames = 0; |
125 eoe->tx_queued_frames = 0; |
125 |
126 |
126 ec_mutex_init(&eoe->tx_queue_mutex); |
127 sema_init(&eoe->tx_queue_sem, 1); |
127 eoe->tx_frame_number = 0xFF; |
128 eoe->tx_frame_number = 0xFF; |
128 memset(&eoe->stats, 0, sizeof(struct net_device_stats)); |
129 memset(&eoe->stats, 0, sizeof(struct net_device_stats)); |
129 |
130 |
130 eoe->rx_counter = 0; |
131 eoe->rx_counter = 0; |
131 eoe->tx_counter = 0; |
132 eoe->tx_counter = 0; |
231 */ |
231 */ |
232 void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */) |
232 void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */) |
233 { |
233 { |
234 ec_eoe_frame_t *frame, *next; |
234 ec_eoe_frame_t *frame, *next; |
235 |
235 |
236 ec_mutex_lock(&eoe->tx_queue_mutex); |
236 down(&eoe->tx_queue_sem); |
237 |
237 |
238 list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) { |
238 list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) { |
239 list_del(&frame->queue); |
239 list_del(&frame->queue); |
240 dev_kfree_skb(frame->skb); |
240 dev_kfree_skb(frame->skb); |
241 kfree(frame); |
241 kfree(frame); |
242 } |
242 } |
243 eoe->tx_queued_frames = 0; |
243 eoe->tx_queued_frames = 0; |
244 |
244 |
245 ec_mutex_unlock(&eoe->tx_queue_mutex); |
245 up(&eoe->tx_queue_sem); |
246 } |
246 } |
247 |
247 |
248 /*****************************************************************************/ |
248 /*****************************************************************************/ |
249 |
249 |
250 /** Sends a frame or the next fragment. |
250 /** Sends a frame or the next fragment. |
|
251 * |
|
252 * \return Zero on success, otherwise a negative error code. |
251 */ |
253 */ |
252 int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */) |
254 int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */) |
253 { |
255 { |
254 size_t remaining_size, current_size, complete_offset; |
256 size_t remaining_size, current_size, complete_offset; |
255 unsigned int last_fragment; |
257 unsigned int last_fragment; |
294 } |
296 } |
295 } |
297 } |
296 printk("\n"); |
298 printk("\n"); |
297 #endif |
299 #endif |
298 |
300 |
299 data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->mbox, |
301 data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->datagram, |
300 0x02, current_size + 4); |
302 0x02, current_size + 4); |
301 if (IS_ERR(data)) |
303 if (IS_ERR(data)) |
302 return PTR_ERR(data); |
304 return PTR_ERR(data); |
303 |
305 |
304 EC_WRITE_U8 (data, 0x00); // eoe fragment req. |
306 EC_WRITE_U8 (data, 0x00); // eoe fragment req. |
323 { |
325 { |
324 if (!eoe->opened) |
326 if (!eoe->opened) |
325 return; |
327 return; |
326 |
328 |
327 // if the datagram was not sent, or is not yet received, skip this cycle |
329 // if the datagram was not sent, or is not yet received, skip this cycle |
328 if (eoe->queue_datagram || |
330 if (eoe->queue_datagram || eoe->datagram.state == EC_DATAGRAM_SENT) |
329 ec_mbox_is_datagram_state(&eoe->mbox, EC_DATAGRAM_QUEUED) || |
331 return; |
330 ec_mbox_is_datagram_state(&eoe->mbox, EC_DATAGRAM_SENT)) { |
|
331 return; |
|
332 } |
|
333 |
332 |
334 // call state function |
333 // call state function |
335 eoe->state(eoe); |
334 eoe->state(eoe); |
336 |
335 |
337 // update statistics |
336 // update statistics |
351 /** Queues the datagram, if necessary. |
350 /** Queues the datagram, if necessary. |
352 */ |
351 */ |
353 void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */) |
352 void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */) |
354 { |
353 { |
355 if (eoe->queue_datagram) { |
354 if (eoe->queue_datagram) { |
356 ec_master_mbox_queue_datagrams(eoe->slave->master, &eoe->mbox); |
355 ec_master_queue_datagram_ext(eoe->slave->master, &eoe->datagram); |
357 eoe->queue_datagram = 0; |
356 eoe->queue_datagram = 0; |
358 } |
357 } |
359 } |
358 } |
360 |
359 |
361 /*****************************************************************************/ |
360 /*****************************************************************************/ |
387 |
386 |
388 /** State: RX_START. |
387 /** State: RX_START. |
389 * |
388 * |
390 * Starts a new receiving sequence by queueing a datagram that checks the |
389 * Starts a new receiving sequence by queueing a datagram that checks the |
391 * slave's mailbox for a new EoE datagram. |
390 * slave's mailbox for a new EoE datagram. |
|
391 * |
|
392 * \todo Use both devices. |
392 */ |
393 */ |
393 void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) |
394 void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) |
394 { |
395 { |
395 if (eoe->slave->error_flag || |
396 if (eoe->slave->error_flag || |
396 !eoe->slave->master->main_device.link_state) { |
397 !eoe->slave->master->devices[EC_DEVICE_MAIN].link_state) { |
397 eoe->rx_idle = 1; |
398 eoe->rx_idle = 1; |
398 eoe->tx_idle = 1; |
399 eoe->tx_idle = 1; |
399 return; |
400 return; |
400 } |
401 } |
401 |
402 |
402 ec_slave_mbox_prepare_check(eoe->slave, &eoe->mbox); |
403 ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram); |
403 eoe->queue_datagram = 1; |
404 eoe->queue_datagram = 1; |
404 eoe->state = ec_eoe_state_rx_check; |
405 eoe->state = ec_eoe_state_rx_check; |
405 } |
406 } |
406 |
407 |
407 /*****************************************************************************/ |
408 /*****************************************************************************/ |
411 * Processes the checking datagram sent in RX_START and issues a receive |
412 * Processes the checking datagram sent in RX_START and issues a receive |
412 * datagram, if new data is available. |
413 * datagram, if new data is available. |
413 */ |
414 */ |
414 void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */) |
415 void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */) |
415 { |
416 { |
416 if (!ec_mbox_is_datagram_state(&eoe->mbox, EC_DATAGRAM_RECEIVED)) { |
417 if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) { |
417 eoe->stats.rx_errors++; |
418 eoe->stats.rx_errors++; |
418 #if EOE_DEBUG_LEVEL >= 1 |
419 #if EOE_DEBUG_LEVEL >= 1 |
419 EC_SLAVE_WARN(eoe->slave, "Failed to receive mbox" |
420 EC_SLAVE_WARN(eoe->slave, "Failed to receive mbox" |
420 " check datagram for %s.\n", eoe->dev->name); |
421 " check datagram for %s.\n", eoe->dev->name); |
421 #endif |
422 #endif |
422 eoe->state = ec_eoe_state_tx_start; |
423 eoe->state = ec_eoe_state_tx_start; |
423 return; |
424 return; |
424 } |
425 } |
425 |
426 |
426 if (!ec_slave_mbox_check(&eoe->mbox)) { |
427 if (!ec_slave_mbox_check(&eoe->datagram)) { |
427 eoe->rx_idle = 1; |
428 eoe->rx_idle = 1; |
428 eoe->state = ec_eoe_state_tx_start; |
429 eoe->state = ec_eoe_state_tx_start; |
429 return; |
430 return; |
430 } |
431 } |
431 |
432 |
432 eoe->rx_idle = 0; |
433 eoe->rx_idle = 0; |
433 ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->mbox); |
434 ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram); |
434 eoe->queue_datagram = 1; |
435 eoe->queue_datagram = 1; |
435 eoe->state = ec_eoe_state_rx_fetch; |
436 eoe->state = ec_eoe_state_rx_fetch; |
436 } |
437 } |
437 |
438 |
438 /*****************************************************************************/ |
439 /*****************************************************************************/ |
453 off_t offset; |
454 off_t offset; |
454 #if EOE_DEBUG_LEVEL >= 3 |
455 #if EOE_DEBUG_LEVEL >= 3 |
455 unsigned int i; |
456 unsigned int i; |
456 #endif |
457 #endif |
457 |
458 |
458 if (!ec_mbox_is_datagram_state(&eoe->mbox, EC_DATAGRAM_RECEIVED)) { |
459 if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) { |
459 eoe->stats.rx_errors++; |
460 eoe->stats.rx_errors++; |
460 #if EOE_DEBUG_LEVEL >= 1 |
461 #if EOE_DEBUG_LEVEL >= 1 |
461 EC_SLAVE_WARN(eoe->slave, "Failed to receive mbox" |
462 EC_SLAVE_WARN(eoe->slave, "Failed to receive mbox" |
462 " fetch datagram for %s.\n", eoe->dev->name); |
463 " fetch datagram for %s.\n", eoe->dev->name); |
463 #endif |
464 #endif |
464 eoe->state = ec_eoe_state_tx_start; |
465 eoe->state = ec_eoe_state_tx_start; |
465 return; |
466 return; |
466 } |
467 } |
467 |
468 |
468 data = ec_slave_mbox_fetch(eoe->slave, &eoe->mbox, |
469 data = ec_slave_mbox_fetch(eoe->slave, &eoe->datagram, |
469 &mbox_prot, &rec_size); |
470 &mbox_prot, &rec_size); |
470 if (IS_ERR(data)) { |
471 if (IS_ERR(data)) { |
471 eoe->stats.rx_errors++; |
472 eoe->stats.rx_errors++; |
472 #if EOE_DEBUG_LEVEL >= 1 |
473 #if EOE_DEBUG_LEVEL >= 1 |
473 EC_SLAVE_WARN(eoe->slave, "Invalid mailbox response for %s.\n", |
474 EC_SLAVE_WARN(eoe->slave, "Invalid mailbox response for %s.\n", |
510 #endif |
511 #endif |
511 |
512 |
512 #if EOE_DEBUG_LEVEL >= 2 |
513 #if EOE_DEBUG_LEVEL >= 2 |
513 EC_SLAVE_DBG(eoe->slave, 0, "EoE %s RX fragment %u%s, offset %u," |
514 EC_SLAVE_DBG(eoe->slave, 0, "EoE %s RX fragment %u%s, offset %u," |
514 " frame %u%s, %u octets\n", eoe->dev->name, fragment_number, |
515 " frame %u%s, %u octets\n", eoe->dev->name, fragment_number, |
515 last_fragment ? "" : "+", fragment_offset, frame_number, |
516 last_fragment ? "" : "+", fragment_offset, frame_number, |
516 time_appended ? ", + timestamp" : "", |
517 time_appended ? ", + timestamp" : "", |
517 time_appended ? rec_size - 8 : rec_size - 4); |
518 time_appended ? rec_size - 8 : rec_size - 4); |
518 #endif |
519 #endif |
519 |
520 |
520 #if EOE_DEBUG_LEVEL >= 3 |
521 #if EOE_DEBUG_LEVEL >= 3 |
614 |
615 |
615 /** State: TX START. |
616 /** State: TX START. |
616 * |
617 * |
617 * Starts a new transmit sequence. If no data is available, a new receive |
618 * Starts a new transmit sequence. If no data is available, a new receive |
618 * sequence is started instead. |
619 * sequence is started instead. |
|
620 * |
|
621 * \todo Use both devices. |
619 */ |
622 */ |
620 void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */) |
623 void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */) |
621 { |
624 { |
622 #if EOE_DEBUG_LEVEL >= 2 |
625 #if EOE_DEBUG_LEVEL >= 2 |
623 unsigned int wakeup = 0; |
626 unsigned int wakeup = 0; |
624 #endif |
627 #endif |
625 |
628 |
626 if (eoe->slave->error_flag || |
629 if (eoe->slave->error_flag || |
627 !eoe->slave->master->main_device.link_state) { |
630 !eoe->slave->master->devices[EC_DEVICE_MAIN].link_state) { |
628 eoe->rx_idle = 1; |
631 eoe->rx_idle = 1; |
629 eoe->tx_idle = 1; |
632 eoe->tx_idle = 1; |
630 return; |
633 return; |
631 } |
634 } |
632 |
635 |
633 ec_mutex_lock(&eoe->tx_queue_mutex); |
636 down(&eoe->tx_queue_sem); |
634 |
637 |
635 if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) { |
638 if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) { |
636 ec_mutex_unlock(&eoe->tx_queue_mutex); |
639 up(&eoe->tx_queue_sem); |
637 eoe->tx_idle = 1; |
640 eoe->tx_idle = 1; |
638 // no data available. |
641 // no data available. |
639 // start a new receive immediately. |
642 // start a new receive immediately. |
640 ec_eoe_state_rx_start(eoe); |
643 ec_eoe_state_rx_start(eoe); |
641 return; |
644 return; |
692 * Checks is the previous transmit datagram succeded and sends the next |
695 * Checks is the previous transmit datagram succeded and sends the next |
693 * fragment, if necessary. |
696 * fragment, if necessary. |
694 */ |
697 */ |
695 void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */) |
698 void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */) |
696 { |
699 { |
697 if (!ec_mbox_is_datagram_state(&eoe->mbox, EC_DATAGRAM_RECEIVED)) { |
700 if (eoe->datagram.state != EC_DATAGRAM_RECEIVED) { |
698 if (eoe->tries) { |
701 if (eoe->tries) { |
699 eoe->tries--; // try again |
702 eoe->tries--; // try again |
700 eoe->queue_datagram = 1; |
703 eoe->queue_datagram = 1; |
701 } else { |
704 } else { |
702 eoe->stats.tx_errors++; |
705 eoe->stats.tx_errors++; |
708 eoe->state = ec_eoe_state_rx_start; |
711 eoe->state = ec_eoe_state_rx_start; |
709 } |
712 } |
710 return; |
713 return; |
711 } |
714 } |
712 |
715 |
713 if (!ec_mbox_is_datagram_wc(&eoe->mbox, 1)) { |
716 if (eoe->datagram.working_counter != 1) { |
714 if (eoe->tries) { |
717 if (eoe->tries) { |
715 eoe->tries--; // try again |
718 eoe->tries--; // try again |
716 eoe->queue_datagram = 1; |
719 eoe->queue_datagram = 1; |
717 } else { |
720 } else { |
718 eoe->stats.tx_errors++; |
721 eoe->stats.tx_errors++; |
753 /****************************************************************************** |
756 /****************************************************************************** |
754 * NET_DEVICE functions |
757 * NET_DEVICE functions |
755 *****************************************************************************/ |
758 *****************************************************************************/ |
756 |
759 |
757 /** Opens the virtual network device. |
760 /** Opens the virtual network device. |
|
761 * |
|
762 * \return Always zero (success). |
758 */ |
763 */ |
759 int ec_eoedev_open(struct net_device *dev /**< EoE net_device */) |
764 int ec_eoedev_open(struct net_device *dev /**< EoE net_device */) |
760 { |
765 { |
761 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
766 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
762 ec_eoe_flush(eoe); |
767 ec_eoe_flush(eoe); |
773 } |
778 } |
774 |
779 |
775 /*****************************************************************************/ |
780 /*****************************************************************************/ |
776 |
781 |
777 /** Stops the virtual network device. |
782 /** Stops the virtual network device. |
|
783 * |
|
784 * \return Always zero (success). |
778 */ |
785 */ |
779 int ec_eoedev_stop(struct net_device *dev /**< EoE net_device */) |
786 int ec_eoedev_stop(struct net_device *dev /**< EoE net_device */) |
780 { |
787 { |
781 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
788 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
782 netif_stop_queue(dev); |
789 netif_stop_queue(dev); |
793 } |
800 } |
794 |
801 |
795 /*****************************************************************************/ |
802 /*****************************************************************************/ |
796 |
803 |
797 /** Transmits data via the virtual network device. |
804 /** Transmits data via the virtual network device. |
|
805 * |
|
806 * \return Zero on success, non-zero on failure. |
798 */ |
807 */ |
799 int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */ |
808 int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */ |
800 struct net_device *dev /**< EoE net_device */ |
809 struct net_device *dev /**< EoE net_device */ |
801 ) |
810 ) |
802 { |
811 { |
820 return 1; |
829 return 1; |
821 } |
830 } |
822 |
831 |
823 frame->skb = skb; |
832 frame->skb = skb; |
824 |
833 |
825 ec_mutex_lock(&eoe->tx_queue_mutex); |
834 down(&eoe->tx_queue_sem); |
826 list_add_tail(&frame->queue, &eoe->tx_queue); |
835 list_add_tail(&frame->queue, &eoe->tx_queue); |
827 eoe->tx_queued_frames++; |
836 eoe->tx_queued_frames++; |
828 if (eoe->tx_queued_frames == eoe->tx_queue_size) { |
837 if (eoe->tx_queued_frames == eoe->tx_queue_size) { |
829 netif_stop_queue(dev); |
838 netif_stop_queue(dev); |
830 eoe->tx_queue_active = 0; |
839 eoe->tx_queue_active = 0; |
831 } |
840 } |
832 ec_mutex_unlock(&eoe->tx_queue_mutex); |
841 up(&eoe->tx_queue_sem); |
833 |
842 |
834 #if EOE_DEBUG_LEVEL >= 2 |
843 #if EOE_DEBUG_LEVEL >= 2 |
835 EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame" |
844 EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame" |
836 " with %u octets (%u frames queued).\n", |
845 " with %u octets (%u frames queued).\n", |
837 eoe->dev->name, skb->len, eoe->tx_queued_frames); |
846 eoe->dev->name, skb->len, eoe->tx_queued_frames); |
843 } |
852 } |
844 |
853 |
845 /*****************************************************************************/ |
854 /*****************************************************************************/ |
846 |
855 |
847 /** Gets statistics about the virtual network device. |
856 /** Gets statistics about the virtual network device. |
|
857 * |
|
858 * \return Statistics. |
848 */ |
859 */ |
849 struct net_device_stats *ec_eoedev_stats( |
860 struct net_device_stats *ec_eoedev_stats( |
850 struct net_device *dev /**< EoE net_device */ |
861 struct net_device *dev /**< EoE net_device */ |
851 ) |
862 ) |
852 { |
863 { |