changeset 900 | f8b5c6d21705 |
parent 880 | f6212c54a5e3 |
child 904 | ba6f222aa06e |
899:e82e2e4cdc9b | 900:f8b5c6d21705 |
---|---|
52 |
52 |
53 void ec_fsm_master_state_start(ec_fsm_master_t *); |
53 void ec_fsm_master_state_start(ec_fsm_master_t *); |
54 void ec_fsm_master_state_broadcast(ec_fsm_master_t *); |
54 void ec_fsm_master_state_broadcast(ec_fsm_master_t *); |
55 void ec_fsm_master_state_read_states(ec_fsm_master_t *); |
55 void ec_fsm_master_state_read_states(ec_fsm_master_t *); |
56 void ec_fsm_master_state_acknowledge(ec_fsm_master_t *); |
56 void ec_fsm_master_state_acknowledge(ec_fsm_master_t *); |
57 void ec_fsm_master_state_validate_vendor(ec_fsm_master_t *); |
|
58 void ec_fsm_master_state_validate_product(ec_fsm_master_t *); |
|
59 void ec_fsm_master_state_rewrite_addresses(ec_fsm_master_t *); |
|
60 void ec_fsm_master_state_configure_slave(ec_fsm_master_t *); |
57 void ec_fsm_master_state_configure_slave(ec_fsm_master_t *); |
61 void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *); |
58 void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *); |
62 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *); |
59 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *); |
63 void ec_fsm_master_state_write_sii(ec_fsm_master_t *); |
60 void ec_fsm_master_state_write_sii(ec_fsm_master_t *); |
64 void ec_fsm_master_state_sdodict(ec_fsm_master_t *); |
61 void ec_fsm_master_state_sdodict(ec_fsm_master_t *); |
82 fsm->state = ec_fsm_master_state_start; |
79 fsm->state = ec_fsm_master_state_start; |
83 fsm->idle = 0; |
80 fsm->idle = 0; |
84 fsm->slaves_responding = 0; |
81 fsm->slaves_responding = 0; |
85 fsm->topology_change_pending = 0; |
82 fsm->topology_change_pending = 0; |
86 fsm->slave_states = EC_SLAVE_STATE_UNKNOWN; |
83 fsm->slave_states = EC_SLAVE_STATE_UNKNOWN; |
87 fsm->validate = 0; |
|
88 fsm->tainted = 0; |
|
89 |
84 |
90 // init sub-state-machines |
85 // init sub-state-machines |
91 ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram); |
86 ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram); |
92 ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram, |
87 ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram, |
93 &fsm->fsm_slave_config, &fsm->fsm_coe_map); |
88 &fsm->fsm_slave_config, &fsm->fsm_coe_map); |
210 fsm->slaves_responding = datagram->working_counter; |
205 fsm->slaves_responding = datagram->working_counter; |
211 |
206 |
212 EC_INFO("%u slave%s responding.\n", |
207 EC_INFO("%u slave%s responding.\n", |
213 fsm->slaves_responding, |
208 fsm->slaves_responding, |
214 fsm->slaves_responding == 1 ? "" : "s"); |
209 fsm->slaves_responding == 1 ? "" : "s"); |
215 |
|
216 if (master->mode == EC_MASTER_MODE_OPERATION) { |
|
217 if (fsm->slaves_responding == master->slave_count) { |
|
218 fsm->validate = 1; // start validation later |
|
219 } |
|
220 else { |
|
221 EC_WARN("Invalid slave count. Bus in tainted state.\n"); |
|
222 fsm->tainted = 1; |
|
223 } |
|
224 } |
|
225 } |
210 } |
226 |
211 |
227 // slave states changed? |
212 // slave states changed? |
228 if (EC_READ_U8(datagram->data) != fsm->slave_states) { |
213 if (EC_READ_U8(datagram->data) != fsm->slave_states) { |
229 char states[EC_STATE_STRING_SIZE]; |
214 char states[EC_STATE_STRING_SIZE]; |
234 |
219 |
235 if (fsm->topology_change_pending) { |
220 if (fsm->topology_change_pending) { |
236 down(&master->scan_sem); |
221 down(&master->scan_sem); |
237 if (!master->allow_scan) { |
222 if (!master->allow_scan) { |
238 up(&master->scan_sem); |
223 up(&master->scan_sem); |
239 } |
224 } else { |
240 else { |
225 master->scan_busy = 1; |
241 master->scan_state = EC_REQUEST_BUSY; |
|
242 up(&master->scan_sem); |
226 up(&master->scan_sem); |
243 |
227 |
244 // topology change when scan is allowed: |
228 // topology change when scan is allowed: |
245 // clear all slaves and scan the bus |
229 // clear all slaves and scan the bus |
246 fsm->topology_change_pending = 0; |
230 fsm->topology_change_pending = 0; |
247 fsm->tainted = 0; |
|
248 fsm->idle = 0; |
231 fsm->idle = 0; |
249 fsm->scan_jiffies = jiffies; |
232 fsm->scan_jiffies = jiffies; |
250 |
233 |
251 #ifdef EC_EOE |
234 #ifdef EC_EOE |
252 ec_master_eoe_stop(master); |
235 ec_master_eoe_stop(master); |
256 |
239 |
257 master->slave_count = datagram->working_counter; |
240 master->slave_count = datagram->working_counter; |
258 |
241 |
259 if (!master->slave_count) { |
242 if (!master->slave_count) { |
260 // no slaves present -> finish state machine. |
243 // no slaves present -> finish state machine. |
261 master->scan_state = EC_REQUEST_SUCCESS; |
244 master->scan_busy = 0; |
262 wake_up_interruptible(&master->scan_queue); |
245 wake_up_interruptible(&master->scan_queue); |
263 fsm->state = ec_fsm_master_state_end; |
246 fsm->state = ec_fsm_master_state_end; |
264 return; |
247 return; |
265 } |
248 } |
266 |
249 |
268 for (i = 0; i < master->slave_count; i++) { |
251 for (i = 0; i < master->slave_count; i++) { |
269 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
252 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
270 GFP_ATOMIC))) { |
253 GFP_ATOMIC))) { |
271 EC_ERR("Failed to allocate slave %i!\n", i); |
254 EC_ERR("Failed to allocate slave %i!\n", i); |
272 ec_master_destroy_slaves(master); |
255 ec_master_destroy_slaves(master); |
273 master->scan_state = EC_REQUEST_FAILURE; |
256 master->scan_busy = 0; |
274 wake_up_interruptible(&master->scan_queue); |
257 wake_up_interruptible(&master->scan_queue); |
275 fsm->state = ec_fsm_master_state_error; |
258 fsm->state = ec_fsm_master_state_error; |
276 return; |
259 return; |
277 } |
260 } |
278 |
261 |
279 if (ec_slave_init(slave, master, i, i + 1)) { |
262 if (ec_slave_init(slave, master, i, i + 1)) { |
280 // freeing of "slave" already done |
263 // freeing of "slave" already done |
281 ec_master_destroy_slaves(master); |
264 ec_master_destroy_slaves(master); |
282 master->scan_state = EC_REQUEST_FAILURE; |
265 master->scan_busy = 0; |
283 wake_up_interruptible(&master->scan_queue); |
266 wake_up_interruptible(&master->scan_queue); |
284 fsm->state = ec_fsm_master_state_error; |
267 fsm->state = ec_fsm_master_state_error; |
285 return; |
268 return; |
286 } |
269 } |
287 |
270 |
502 ec_fsm_slave_config_start(&fsm->fsm_slave_config, slave); |
485 ec_fsm_slave_config_start(&fsm->fsm_slave_config, slave); |
503 ec_fsm_slave_config_exec(&fsm->fsm_slave_config); // execute immediately |
486 ec_fsm_slave_config_exec(&fsm->fsm_slave_config); // execute immediately |
504 return 1; |
487 return 1; |
505 } |
488 } |
506 |
489 |
507 if (fsm->config_error) |
490 master->config_busy = 0; |
508 master->config_state = EC_REQUEST_FAILURE; |
|
509 else |
|
510 master->config_state = EC_REQUEST_SUCCESS; |
|
511 wake_up_interruptible(&master->config_queue); |
491 wake_up_interruptible(&master->config_queue); |
512 return 0; |
492 return 0; |
513 } |
493 } |
514 |
494 |
515 /*****************************************************************************/ |
495 /*****************************************************************************/ |
524 ) |
504 ) |
525 { |
505 { |
526 ec_master_t *master = fsm->master; |
506 ec_master_t *master = fsm->master; |
527 ec_slave_t *slave; |
507 ec_slave_t *slave; |
528 |
508 |
509 // Start slave configuration, if it is allowed. |
|
529 down(&master->config_sem); |
510 down(&master->config_sem); |
530 if (!master->allow_config) { |
511 if (!master->allow_config) { |
531 up(&master->config_sem); |
512 up(&master->config_sem); |
532 } else { |
513 } else { |
533 master->config_state = EC_REQUEST_BUSY; |
514 master->config_busy = 1; |
534 fsm->config_error = 0; |
|
535 up(&master->config_sem); |
515 up(&master->config_sem); |
536 |
516 |
537 // check for pending slave configurations |
517 // check for pending slave configurations |
538 if (ec_fsm_master_action_configure(fsm)) |
518 if (ec_fsm_master_action_configure(fsm)) |
539 return; |
519 return; |
601 fsm->state = ec_fsm_master_state_read_states; |
581 fsm->state = ec_fsm_master_state_read_states; |
602 return; |
582 return; |
603 } |
583 } |
604 |
584 |
605 // all slave states read |
585 // all slave states read |
606 |
|
607 // check, if a bus validation has to be done |
|
608 if (fsm->validate) { |
|
609 fsm->validate = 0; |
|
610 list_for_each_entry(slave, &master->slaves, list) { |
|
611 if (slave->online_state == EC_SLAVE_ONLINE) continue; |
|
612 |
|
613 // At least one slave is offline. validate! |
|
614 EC_INFO("Validating bus.\n"); |
|
615 fsm->idle = 0; |
|
616 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
617 fsm->state = ec_fsm_master_state_validate_vendor; |
|
618 ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, |
|
619 EC_FSM_SII_USE_INCREMENT_ADDRESS); |
|
620 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately |
|
621 return; |
|
622 } |
|
623 } |
|
624 |
|
625 ec_fsm_master_action_process_states(fsm); |
586 ec_fsm_master_action_process_states(fsm); |
626 } |
587 } |
627 |
588 |
628 /*****************************************************************************/ |
589 /*****************************************************************************/ |
629 |
590 |
697 } |
658 } |
698 |
659 |
699 /*****************************************************************************/ |
660 /*****************************************************************************/ |
700 |
661 |
701 /** |
662 /** |
702 Master state: VALIDATE_VENDOR. |
|
703 Validates the vendor ID of a slave. |
|
704 */ |
|
705 |
|
706 void ec_fsm_master_state_validate_vendor(ec_fsm_master_t *fsm /**< master state machine */) |
|
707 { |
|
708 ec_slave_t *slave = fsm->slave; |
|
709 |
|
710 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return; |
|
711 |
|
712 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
|
713 fsm->slave->error_flag = 1; |
|
714 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
|
715 slave->ring_position); |
|
716 fsm->state = ec_fsm_master_state_error; |
|
717 return; |
|
718 } |
|
719 |
|
720 if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii.vendor_id) { |
|
721 EC_ERR("Slave %i has an invalid vendor ID!\n", slave->ring_position); |
|
722 fsm->state = ec_fsm_master_state_error; |
|
723 return; |
|
724 } |
|
725 |
|
726 // vendor ID is ok. check product code. |
|
727 fsm->state = ec_fsm_master_state_validate_product; |
|
728 ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x000A, |
|
729 EC_FSM_SII_USE_INCREMENT_ADDRESS); |
|
730 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately |
|
731 } |
|
732 |
|
733 /*****************************************************************************/ |
|
734 |
|
735 /** |
|
736 Master action: ADDRESS. |
|
737 Looks for slave, that have lost their configuration and writes |
|
738 their station address, so that they can be reconfigured later. |
|
739 */ |
|
740 |
|
741 void ec_fsm_master_action_addresses(ec_fsm_master_t *fsm /**< master state machine */) |
|
742 { |
|
743 ec_datagram_t *datagram = fsm->datagram; |
|
744 |
|
745 while (fsm->slave->online_state == EC_SLAVE_ONLINE) { |
|
746 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
|
747 fsm->state = ec_fsm_master_state_end; |
|
748 return; |
|
749 } |
|
750 // check next slave |
|
751 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
752 } |
|
753 |
|
754 if (fsm->master->debug_level) |
|
755 EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position); |
|
756 |
|
757 // write station address |
|
758 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2); |
|
759 EC_WRITE_U16(datagram->data, fsm->slave->station_address); |
|
760 fsm->retries = EC_FSM_RETRIES; |
|
761 fsm->state = ec_fsm_master_state_rewrite_addresses; |
|
762 } |
|
763 |
|
764 /*****************************************************************************/ |
|
765 |
|
766 /** |
|
767 Master state: VALIDATE_PRODUCT. |
|
768 Validates the product ID of a slave. |
|
769 */ |
|
770 |
|
771 void ec_fsm_master_state_validate_product(ec_fsm_master_t *fsm /**< master state machine */) |
|
772 { |
|
773 ec_slave_t *slave = fsm->slave; |
|
774 |
|
775 if (ec_fsm_sii_exec(&fsm->fsm_sii)) return; |
|
776 |
|
777 if (!ec_fsm_sii_success(&fsm->fsm_sii)) { |
|
778 fsm->slave->error_flag = 1; |
|
779 EC_ERR("Failed to validate product code of slave %i.\n", |
|
780 slave->ring_position); |
|
781 fsm->state = ec_fsm_master_state_error; |
|
782 return; |
|
783 } |
|
784 |
|
785 if (EC_READ_U32(fsm->fsm_sii.value) != slave->sii.product_code) { |
|
786 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
|
787 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii.product_code, |
|
788 EC_READ_U32(fsm->fsm_sii.value)); |
|
789 fsm->state = ec_fsm_master_state_error; |
|
790 return; |
|
791 } |
|
792 |
|
793 // have all states been validated? |
|
794 if (slave->list.next == &fsm->master->slaves) { |
|
795 fsm->topology_change_pending = 0; |
|
796 fsm->tainted = 0; |
|
797 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); |
|
798 // start writing addresses to offline slaves |
|
799 ec_fsm_master_action_addresses(fsm); |
|
800 return; |
|
801 } |
|
802 |
|
803 // validate next slave |
|
804 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
805 fsm->state = ec_fsm_master_state_validate_vendor; |
|
806 ec_fsm_sii_read(&fsm->fsm_sii, slave, 0x0008, |
|
807 EC_FSM_SII_USE_INCREMENT_ADDRESS); |
|
808 ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately |
|
809 } |
|
810 |
|
811 /*****************************************************************************/ |
|
812 |
|
813 /** |
|
814 Master state: REWRITE ADDRESS. |
|
815 Checks, if the new station address has been written to the slave. |
|
816 */ |
|
817 |
|
818 void ec_fsm_master_state_rewrite_addresses(ec_fsm_master_t *fsm |
|
819 /**< master state machine */ |
|
820 ) |
|
821 { |
|
822 ec_slave_t *slave = fsm->slave; |
|
823 ec_datagram_t *datagram = fsm->datagram; |
|
824 |
|
825 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
|
826 return; |
|
827 |
|
828 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
|
829 EC_ERR("Failed to receive address datagram for slave %i" |
|
830 " (datagram state %i).\n", |
|
831 slave->ring_position, datagram->state); |
|
832 fsm->state = ec_fsm_master_state_error; |
|
833 return; |
|
834 } |
|
835 |
|
836 if (datagram->working_counter != 1) { |
|
837 EC_ERR("Failed to write station address of slave %i: ", |
|
838 slave->ring_position); |
|
839 ec_datagram_print_wc_error(datagram); |
|
840 fsm->state = ec_fsm_master_state_error; |
|
841 return; |
|
842 } |
|
843 |
|
844 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
|
845 fsm->state = ec_fsm_master_state_end; |
|
846 return; |
|
847 } |
|
848 |
|
849 // check next slave |
|
850 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
851 // Write new station address to slave |
|
852 ec_fsm_master_action_addresses(fsm); |
|
853 } |
|
854 |
|
855 /*****************************************************************************/ |
|
856 |
|
857 /** |
|
858 * Master state: CLEAR ADDRESSES. |
663 * Master state: CLEAR ADDRESSES. |
859 */ |
664 */ |
860 |
665 |
861 void ec_fsm_master_state_clear_addresses( |
666 void ec_fsm_master_state_clear_addresses( |
862 ec_fsm_master_t *fsm /**< master state machine */ |
667 ec_fsm_master_t *fsm /**< master state machine */ |
869 return; |
674 return; |
870 |
675 |
871 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
676 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
872 EC_ERR("Failed to receive address clearing datagram (state %i).\n", |
677 EC_ERR("Failed to receive address clearing datagram (state %i).\n", |
873 datagram->state); |
678 datagram->state); |
874 master->scan_state = EC_REQUEST_FAILURE; |
679 master->scan_busy = 0; |
875 wake_up_interruptible(&master->scan_queue); |
680 wake_up_interruptible(&master->scan_queue); |
876 fsm->state = ec_fsm_master_state_error; |
681 fsm->state = ec_fsm_master_state_error; |
877 return; |
682 return; |
878 } |
683 } |
879 |
684 |
913 // create EoE handler for this slave |
718 // create EoE handler for this slave |
914 ec_eoe_t *eoe; |
719 ec_eoe_t *eoe; |
915 if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { |
720 if (!(eoe = kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { |
916 EC_ERR("Failed to allocate EoE handler memory for slave %u!\n", |
721 EC_ERR("Failed to allocate EoE handler memory for slave %u!\n", |
917 slave->ring_position); |
722 slave->ring_position); |
918 } |
723 } else if (ec_eoe_init(eoe, slave)) { |
919 else if (ec_eoe_init(eoe, slave)) { |
|
920 EC_ERR("Failed to init EoE handler for slave %u!\n", |
724 EC_ERR("Failed to init EoE handler for slave %u!\n", |
921 slave->ring_position); |
725 slave->ring_position); |
922 kfree(eoe); |
726 kfree(eoe); |
923 } |
727 } else { |
924 else { |
|
925 list_add_tail(&eoe->list, &master->eoe_handlers); |
728 list_add_tail(&eoe->list, &master->eoe_handlers); |
926 } |
729 } |
927 } |
730 } |
928 #endif |
731 #endif |
929 |
732 |
936 } |
739 } |
937 |
740 |
938 EC_INFO("Bus scanning completed in %u ms.\n", |
741 EC_INFO("Bus scanning completed in %u ms.\n", |
939 (u32) (jiffies - fsm->scan_jiffies) * 1000 / HZ); |
742 (u32) (jiffies - fsm->scan_jiffies) * 1000 / HZ); |
940 |
743 |
744 master->scan_busy = 0; |
|
745 wake_up_interruptible(&master->scan_queue); |
|
746 |
|
941 // Attach slave configurations |
747 // Attach slave configurations |
942 ec_master_attach_slave_configs(master); |
748 ec_master_attach_slave_configs(master); |
943 |
749 |
944 #ifdef EC_EOE |
750 #ifdef EC_EOE |
945 // check if EoE processing has to be started |
751 // check if EoE processing has to be started |
946 ec_master_eoe_start(master); |
752 ec_master_eoe_start(master); |
947 #endif |
753 #endif |
948 |
754 |
949 master->scan_state = EC_REQUEST_SUCCESS; |
|
950 wake_up_interruptible(&master->scan_queue); |
|
951 |
|
952 fsm->state = ec_fsm_master_state_end; |
755 fsm->state = ec_fsm_master_state_end; |
953 } |
756 } |
954 |
757 |
955 /*****************************************************************************/ |
758 /*****************************************************************************/ |
956 |
759 |
964 ) |
767 ) |
965 { |
768 { |
966 if (ec_fsm_slave_config_exec(&fsm->fsm_slave_config)) // execute slave's state machine |
769 if (ec_fsm_slave_config_exec(&fsm->fsm_slave_config)) // execute slave's state machine |
967 return; |
770 return; |
968 |
771 |
969 if (!ec_fsm_slave_config_success(&fsm->fsm_slave_config)) |
772 if (!ec_fsm_slave_config_success(&fsm->fsm_slave_config)) { |
970 fsm->config_error = 1; |
773 // TODO: mark slave_config as failed. |
774 } |
|
971 |
775 |
972 // configure next slave, if necessary |
776 // configure next slave, if necessary |
973 if (ec_fsm_master_action_configure(fsm)) |
777 if (ec_fsm_master_action_configure(fsm)) |
974 return; |
778 return; |
975 |
779 |