branch | stable-1.0 |
changeset 1621 | 4bbe090553f7 |
parent 1619 | 0d4119024f55 |
child 1623 | 05622513f627 |
1620:9d7453c16ade | 1621:4bbe090553f7 |
---|---|
42 #include "fsm.h" |
42 #include "fsm.h" |
43 #include "master.h" |
43 #include "master.h" |
44 |
44 |
45 /*****************************************************************************/ |
45 /*****************************************************************************/ |
46 |
46 |
47 /** |
|
48 Size of memory to allocate while reading categories. |
|
49 */ |
|
50 |
|
51 #define EC_CAT_MEM 0x100 |
|
52 |
|
53 /*****************************************************************************/ |
|
54 |
|
55 const ec_code_msg_t al_status_messages[]; |
47 const ec_code_msg_t al_status_messages[]; |
56 |
48 |
57 /*****************************************************************************/ |
49 /*****************************************************************************/ |
58 |
50 |
59 void ec_fsm_master_start(ec_fsm_t *); |
51 void ec_fsm_master_start(ec_fsm_t *); |
64 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
56 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
65 void ec_fsm_master_validate_product(ec_fsm_t *); |
57 void ec_fsm_master_validate_product(ec_fsm_t *); |
66 void ec_fsm_master_reconfigure(ec_fsm_t *); |
58 void ec_fsm_master_reconfigure(ec_fsm_t *); |
67 void ec_fsm_master_address(ec_fsm_t *); |
59 void ec_fsm_master_address(ec_fsm_t *); |
68 void ec_fsm_master_conf(ec_fsm_t *); |
60 void ec_fsm_master_conf(ec_fsm_t *); |
61 void ec_fsm_master_eeprom(ec_fsm_t *); |
|
69 |
62 |
70 void ec_fsm_slave_start_reading(ec_fsm_t *); |
63 void ec_fsm_slave_start_reading(ec_fsm_t *); |
71 void ec_fsm_slave_read_status(ec_fsm_t *); |
64 void ec_fsm_slave_read_status(ec_fsm_t *); |
72 void ec_fsm_slave_read_base(ec_fsm_t *); |
65 void ec_fsm_slave_read_base(ec_fsm_t *); |
73 void ec_fsm_slave_read_dl(ec_fsm_t *); |
66 void ec_fsm_slave_read_dl(ec_fsm_t *); |
74 void ec_fsm_slave_prepare_sii(ec_fsm_t *); |
67 void ec_fsm_slave_eeprom_size(ec_fsm_t *); |
75 void ec_fsm_slave_read_sii(ec_fsm_t *); |
68 void ec_fsm_slave_fetch_eeprom(ec_fsm_t *); |
76 void ec_fsm_slave_category_header(ec_fsm_t *); |
69 void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *); |
77 void ec_fsm_slave_category_data(ec_fsm_t *); |
|
78 void ec_fsm_slave_end(ec_fsm_t *); |
70 void ec_fsm_slave_end(ec_fsm_t *); |
79 |
71 |
80 void ec_fsm_slave_conf(ec_fsm_t *); |
72 void ec_fsm_slave_conf(ec_fsm_t *); |
81 void ec_fsm_slave_sync(ec_fsm_t *); |
73 void ec_fsm_slave_sync(ec_fsm_t *); |
82 void ec_fsm_slave_preop(ec_fsm_t *); |
74 void ec_fsm_slave_preop(ec_fsm_t *); |
84 void ec_fsm_slave_saveop(ec_fsm_t *); |
76 void ec_fsm_slave_saveop(ec_fsm_t *); |
85 void ec_fsm_slave_op(ec_fsm_t *); |
77 void ec_fsm_slave_op(ec_fsm_t *); |
86 void ec_fsm_slave_op2(ec_fsm_t *); |
78 void ec_fsm_slave_op2(ec_fsm_t *); |
87 |
79 |
88 void ec_fsm_sii_start_reading(ec_fsm_t *); |
80 void ec_fsm_sii_start_reading(ec_fsm_t *); |
89 void ec_fsm_sii_check(ec_fsm_t *); |
81 void ec_fsm_sii_read_check(ec_fsm_t *); |
90 void ec_fsm_sii_fetch(ec_fsm_t *); |
82 void ec_fsm_sii_read_fetch(ec_fsm_t *); |
83 void ec_fsm_sii_start_writing(ec_fsm_t *); |
|
84 void ec_fsm_sii_write_check(ec_fsm_t *); |
|
85 void ec_fsm_sii_write_check2(ec_fsm_t *); |
|
91 void ec_fsm_sii_end(ec_fsm_t *); |
86 void ec_fsm_sii_end(ec_fsm_t *); |
92 void ec_fsm_sii_error(ec_fsm_t *); |
87 void ec_fsm_sii_error(ec_fsm_t *); |
93 |
88 |
94 void ec_fsm_change_start(ec_fsm_t *); |
89 void ec_fsm_change_start(ec_fsm_t *); |
95 void ec_fsm_change_check(ec_fsm_t *); |
90 void ec_fsm_change_check(ec_fsm_t *); |
113 fsm->master = master; |
108 fsm->master = master; |
114 fsm->master_state = ec_fsm_master_start; |
109 fsm->master_state = ec_fsm_master_start; |
115 fsm->master_slaves_responding = 0; |
110 fsm->master_slaves_responding = 0; |
116 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
111 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
117 fsm->master_validation = 0; |
112 fsm->master_validation = 0; |
118 fsm->slave_cat_data = NULL; |
|
119 |
113 |
120 ec_command_init(&fsm->command); |
114 ec_command_init(&fsm->command); |
121 if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { |
115 if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { |
122 EC_ERR("FSM failed to allocate FSM command.\n"); |
116 EC_ERR("FSM failed to allocate FSM command.\n"); |
123 return -1; |
117 return -1; |
132 Destructor. |
126 Destructor. |
133 */ |
127 */ |
134 |
128 |
135 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
129 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
136 { |
130 { |
137 if (fsm->slave_cat_data) kfree(fsm->slave_cat_data); |
|
138 ec_command_clear(&fsm->command); |
131 ec_command_clear(&fsm->command); |
139 } |
132 } |
140 |
133 |
141 /*****************************************************************************/ |
134 /*****************************************************************************/ |
142 |
135 |
147 void ec_fsm_reset(ec_fsm_t *fsm /**< finite state machine */) |
140 void ec_fsm_reset(ec_fsm_t *fsm /**< finite state machine */) |
148 { |
141 { |
149 fsm->master_state = ec_fsm_master_start; |
142 fsm->master_state = ec_fsm_master_start; |
150 fsm->master_slaves_responding = 0; |
143 fsm->master_slaves_responding = 0; |
151 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
144 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
152 |
|
153 if (fsm->slave_cat_data) { |
|
154 kfree(fsm->slave_cat_data); |
|
155 fsm->slave_cat_data = NULL; |
|
156 } |
|
157 } |
145 } |
158 |
146 |
159 /*****************************************************************************/ |
147 /*****************************************************************************/ |
160 |
148 |
161 /** |
149 /** |
420 fsm->master_state = ec_fsm_master_conf; |
408 fsm->master_state = ec_fsm_master_conf; |
421 fsm->master_state(fsm); // execute immediately |
409 fsm->master_state(fsm); // execute immediately |
422 return; |
410 return; |
423 } |
411 } |
424 |
412 |
425 // nothing to configure. restart master state machine. |
413 if (master->mode == EC_MASTER_MODE_FREERUN) { |
414 // nothing to configure. check for pending EEPROM write operations. |
|
415 list_for_each_entry(slave, &master->slaves, list) { |
|
416 if (!slave->new_eeprom_data) continue; |
|
417 |
|
418 // found pending EEPROM write operation. execute it! |
|
419 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); |
|
420 fsm->sii_offset = 0x0000; |
|
421 memcpy(fsm->sii_value, slave->new_eeprom_data, 2); |
|
422 fsm->sii_mode = 1; |
|
423 fsm->sii_state = ec_fsm_sii_start_writing; |
|
424 fsm->slave = slave; |
|
425 fsm->master_state = ec_fsm_master_eeprom; |
|
426 fsm->master_state(fsm); // execute immediately |
|
427 return; |
|
428 } |
|
429 } |
|
430 |
|
431 // nothing to do. restart master state machine. |
|
426 fsm->master_state = ec_fsm_master_start; |
432 fsm->master_state = ec_fsm_master_start; |
427 fsm->master_state(fsm); // execute immediately |
433 fsm->master_state(fsm); // execute immediately |
428 } |
434 } |
429 |
435 |
430 /*****************************************************************************/ |
436 /*****************************************************************************/ |
448 return; |
454 return; |
449 } |
455 } |
450 |
456 |
451 if (fsm->sii_state != ec_fsm_sii_end) return; |
457 if (fsm->sii_state != ec_fsm_sii_end) return; |
452 |
458 |
453 if (fsm->sii_result != slave->sii_vendor_id) { |
459 if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) { |
454 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
460 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
455 fsm->master_state = ec_fsm_master_start; |
461 fsm->master_state = ec_fsm_master_start; |
456 fsm->master_state(fsm); // execute immediately |
462 fsm->master_state(fsm); // execute immediately |
457 return; |
463 return; |
458 } |
464 } |
486 return; |
492 return; |
487 } |
493 } |
488 |
494 |
489 if (fsm->sii_state != ec_fsm_sii_end) return; |
495 if (fsm->sii_state != ec_fsm_sii_end) return; |
490 |
496 |
491 if (fsm->sii_result != slave->sii_product_code) { |
497 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
492 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
498 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
493 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
499 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
494 fsm->sii_result); |
500 EC_READ_U32(fsm->sii_value)); |
495 fsm->master_state = ec_fsm_master_start; |
501 fsm->master_state = ec_fsm_master_start; |
496 fsm->master_state(fsm); // execute immediately |
502 fsm->master_state(fsm); // execute immediately |
497 return; |
503 return; |
498 } |
504 } |
499 |
505 |
680 if (fsm->slave_state != ec_fsm_slave_end) return; |
686 if (fsm->slave_state != ec_fsm_slave_end) return; |
681 fsm->master_state = ec_fsm_master_proc_states; |
687 fsm->master_state = ec_fsm_master_proc_states; |
682 fsm->master_state(fsm); // execute immediately |
688 fsm->master_state(fsm); // execute immediately |
683 } |
689 } |
684 |
690 |
691 /*****************************************************************************/ |
|
692 |
|
693 /** |
|
694 Master state: EEPROM. |
|
695 */ |
|
696 |
|
697 void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
|
698 { |
|
699 ec_slave_t *slave = fsm->slave; |
|
700 |
|
701 fsm->sii_state(fsm); // execute SII state machine |
|
702 |
|
703 if (fsm->sii_state == ec_fsm_sii_error) { |
|
704 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
|
705 slave->ring_position); |
|
706 kfree(slave->new_eeprom_data); |
|
707 slave->new_eeprom_data = NULL; |
|
708 fsm->master_state = ec_fsm_master_start; |
|
709 fsm->master_state(fsm); // execute immediately |
|
710 return; |
|
711 } |
|
712 |
|
713 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
714 |
|
715 fsm->sii_offset++; |
|
716 if (fsm->sii_offset < slave->new_eeprom_size) { |
|
717 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2); |
|
718 fsm->sii_state = ec_fsm_sii_start_writing; |
|
719 fsm->sii_state(fsm); // execute immediately |
|
720 return; |
|
721 } |
|
722 |
|
723 // finished writing EEPROM |
|
724 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
|
725 kfree(slave->new_eeprom_data); |
|
726 slave->new_eeprom_data = NULL; |
|
727 |
|
728 // restart master state machine. |
|
729 fsm->master_state = ec_fsm_master_start; |
|
730 fsm->master_state(fsm); // execute immediately |
|
731 return; |
|
732 } |
|
733 |
|
685 /****************************************************************************** |
734 /****************************************************************************** |
686 * slave state machine |
735 * slave state machine |
687 *****************************************************************************/ |
736 *****************************************************************************/ |
688 |
737 |
689 /** |
738 /** |
785 slave->base_fmmu_count = EC_MAX_FMMUS; |
834 slave->base_fmmu_count = EC_MAX_FMMUS; |
786 |
835 |
787 // read data link status |
836 // read data link status |
788 ec_command_nprd(command, slave->station_address, 0x0110, 2); |
837 ec_command_nprd(command, slave->station_address, 0x0110, 2); |
789 ec_master_queue_command(slave->master, command); |
838 ec_master_queue_command(slave->master, command); |
790 fsm->slave_state = ec_fsm_slave_prepare_sii; |
839 fsm->slave_state = ec_fsm_slave_eeprom_size; |
791 } |
840 } |
792 |
841 |
793 /*****************************************************************************/ |
842 /*****************************************************************************/ |
794 |
843 |
795 /** |
844 /** |
796 Slave state: PREPARE_SII. |
845 Slave state: EEPROM_SIZE. |
797 */ |
846 Read the actual size of the EEPROM to allocate the EEPROM image. |
798 |
847 */ |
799 void ec_fsm_slave_prepare_sii(ec_fsm_t *fsm /**< finite state machine */) |
848 |
849 void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */) |
|
800 { |
850 { |
801 ec_command_t *command = &fsm->command; |
851 ec_command_t *command = &fsm->command; |
802 ec_slave_t *slave = fsm->slave; |
852 ec_slave_t *slave = fsm->slave; |
803 uint16_t dl_status; |
853 uint16_t dl_status; |
804 unsigned int i; |
854 unsigned int i; |
809 fsm->slave_state = ec_fsm_slave_end; |
859 fsm->slave_state = ec_fsm_slave_end; |
810 return; |
860 return; |
811 } |
861 } |
812 |
862 |
813 dl_status = EC_READ_U16(command->data); |
863 dl_status = EC_READ_U16(command->data); |
814 |
|
815 for (i = 0; i < 4; i++) { |
864 for (i = 0; i < 4; i++) { |
816 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
865 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
817 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
866 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
818 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
867 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
819 } |
868 } |
820 |
869 |
821 fsm->sii_offset = 0x0004; |
870 // Start fetching EEPROM size |
871 |
|
872 fsm->sii_offset = 0x0040; // first category header |
|
822 fsm->sii_mode = 1; |
873 fsm->sii_mode = 1; |
823 fsm->sii_state = ec_fsm_sii_start_reading; |
874 fsm->sii_state = ec_fsm_sii_start_reading; |
824 fsm->slave_sii_num = 0; |
875 fsm->slave_state = ec_fsm_slave_fetch_eeprom; |
825 fsm->slave_state = ec_fsm_slave_read_sii; |
|
826 fsm->slave_state(fsm); // execute state immediately |
876 fsm->slave_state(fsm); // execute state immediately |
827 } |
877 } |
828 |
878 |
829 /*****************************************************************************/ |
879 /*****************************************************************************/ |
830 |
880 |
831 /** |
881 /** |
832 Slave state: READ_SII. |
882 Slave state: FETCH_EEPROM. |
833 */ |
883 */ |
834 |
884 |
835 void ec_fsm_slave_read_sii(ec_fsm_t *fsm /**< finite state machine */) |
885 void ec_fsm_slave_fetch_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
836 { |
886 { |
837 ec_slave_t *slave = fsm->slave; |
887 ec_slave_t *slave = fsm->slave; |
888 uint16_t cat_type, cat_size; |
|
838 |
889 |
839 // execute SII state machine |
890 // execute SII state machine |
840 fsm->sii_state(fsm); |
891 fsm->sii_state(fsm); |
841 |
892 |
842 if (fsm->sii_state == ec_fsm_sii_error) { |
893 if (fsm->sii_state == ec_fsm_sii_error) { |
843 fsm->slave_state = ec_fsm_slave_end; |
894 fsm->slave_state = ec_fsm_slave_end; |
844 EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n", |
895 EC_ERR("Failed to read EEPROM size of slave %i.\n", |
845 fsm->sii_offset, slave->ring_position); |
896 slave->ring_position); |
846 return; |
897 return; |
847 } |
898 } |
848 |
899 |
849 if (fsm->sii_state != ec_fsm_sii_end) return; |
900 if (fsm->sii_state != ec_fsm_sii_end) return; |
850 |
901 |
851 switch (fsm->slave_sii_num) { |
902 cat_type = EC_READ_U16(fsm->sii_value); |
852 case 0: |
903 cat_size = EC_READ_U16(fsm->sii_value + 2); |
853 slave->sii_alias = fsm->sii_result & 0xFFFF; |
904 |
854 fsm->sii_offset = 0x0008; |
905 if (cat_type != 0xFFFF) { // not the last category |
855 break; |
906 fsm->sii_offset += cat_size + 2; |
856 case 1: |
907 fsm->sii_state = ec_fsm_sii_start_reading; |
857 slave->sii_vendor_id = fsm->sii_result; |
908 fsm->sii_state(fsm); // execute state immediately |
858 fsm->sii_offset = 0x000A; |
909 return; |
859 break; |
910 } |
860 case 2: |
911 |
861 slave->sii_product_code = fsm->sii_result; |
912 slave->eeprom_size = (fsm->sii_offset + 1) * 2; |
862 fsm->sii_offset = 0x000C; |
913 |
863 break; |
914 if (slave->eeprom_data) { |
864 case 3: |
915 EC_INFO("Freeing old EEPROM data on slave %i...\n", |
865 slave->sii_revision_number = fsm->sii_result; |
916 slave->ring_position); |
866 fsm->sii_offset = 0x000E; |
917 kfree(slave->eeprom_data); |
867 break; |
918 } |
868 case 4: |
919 |
869 slave->sii_serial_number = fsm->sii_result; |
920 if (!(slave->eeprom_data = |
870 fsm->sii_offset = 0x0018; |
921 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
871 break; |
922 EC_ERR("Failed to allocate EEPROM data on slave %i.\n", |
872 case 5: |
923 slave->ring_position); |
873 slave->sii_rx_mailbox_offset = fsm->sii_result & 0xFFFF; |
924 fsm->slave_state = ec_fsm_slave_end; |
874 slave->sii_rx_mailbox_size = fsm->sii_result >> 16; |
925 return; |
875 fsm->sii_offset = 0x001A; |
926 } |
876 break; |
927 |
877 case 6: |
928 // Start fetching EEPROM contents |
878 slave->sii_tx_mailbox_offset = fsm->sii_result & 0xFFFF; |
929 |
879 slave->sii_tx_mailbox_size = fsm->sii_result >> 16; |
930 fsm->sii_offset = 0x0000; |
880 fsm->sii_offset = 0x001C; |
931 fsm->sii_mode = 1; |
881 break; |
|
882 case 7: |
|
883 slave->sii_mailbox_protocols = fsm->sii_result & 0xFFFF; |
|
884 |
|
885 fsm->slave_cat_offset = 0x0040; |
|
886 |
|
887 if (fsm->slave_cat_data) { |
|
888 EC_INFO("FSM freeing old category data on slave %i...\n", |
|
889 fsm->slave->ring_position); |
|
890 kfree(fsm->slave_cat_data); |
|
891 } |
|
892 |
|
893 if (!(fsm->slave_cat_data = |
|
894 (uint8_t *) kmalloc(EC_CAT_MEM, GFP_ATOMIC))) { |
|
895 EC_ERR("FSM Failed to allocate category data.\n"); |
|
896 fsm->slave_state = ec_fsm_slave_end; |
|
897 return; |
|
898 } |
|
899 |
|
900 // start reading first category header |
|
901 fsm->sii_offset = fsm->slave_cat_offset; |
|
902 fsm->sii_state = ec_fsm_sii_start_reading; |
|
903 |
|
904 fsm->slave_state = ec_fsm_slave_category_header; |
|
905 fsm->slave_state(fsm); // execute state immediately |
|
906 return; |
|
907 } |
|
908 |
|
909 fsm->slave_sii_num++; |
|
910 fsm->sii_state = ec_fsm_sii_start_reading; |
932 fsm->sii_state = ec_fsm_sii_start_reading; |
933 fsm->slave_state = ec_fsm_slave_fetch_eeprom2; |
|
911 fsm->slave_state(fsm); // execute state immediately |
934 fsm->slave_state(fsm); // execute state immediately |
912 } |
935 } |
913 |
936 |
914 /*****************************************************************************/ |
937 /*****************************************************************************/ |
915 |
938 |
916 /** |
939 /** |
917 Slave state: CATEGORY_HEADER. |
940 Slave state: FETCH_EEPROM2. |
918 Start reading categories. |
941 */ |
919 */ |
942 |
920 |
943 void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *fsm /**< finite state machine */) |
921 void ec_fsm_slave_category_header(ec_fsm_t *fsm /**< finite state machine */) |
944 { |
922 { |
945 ec_slave_t *slave = fsm->slave; |
946 uint16_t *cat_word, cat_type, cat_size; |
|
947 |
|
923 // execute SII state machine |
948 // execute SII state machine |
924 fsm->sii_state(fsm); |
949 fsm->sii_state(fsm); |
925 |
950 |
926 if (fsm->sii_state == ec_fsm_sii_error) { |
951 if (fsm->sii_state == ec_fsm_sii_error) { |
927 kfree(fsm->slave_cat_data); |
|
928 fsm->slave_cat_data = NULL; |
|
929 fsm->slave_state = ec_fsm_slave_end; |
952 fsm->slave_state = ec_fsm_slave_end; |
930 EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n", |
953 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", |
931 fsm->slave_cat_offset, fsm->slave->ring_position); |
954 slave->ring_position); |
932 return; |
955 return; |
933 } |
956 } |
934 |
957 |
935 if (fsm->sii_state != ec_fsm_sii_end) return; |
958 if (fsm->sii_state != ec_fsm_sii_end) return; |
936 |
959 |
937 // last category? |
960 // 2 words fetched |
938 if ((fsm->sii_result & 0xFFFF) == 0xFFFF) { |
961 |
939 kfree(fsm->slave_cat_data); |
962 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
940 fsm->slave_cat_data = NULL; |
963 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4); |
941 fsm->slave_state = ec_fsm_slave_end; |
964 } |
942 return; |
965 else { // copy the last word |
943 } |
966 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2); |
944 |
967 } |
945 fsm->slave_cat_type = fsm->sii_result & 0x7FFF; |
968 |
946 fsm->slave_cat_words = (fsm->sii_result >> 16) & 0xFFFF; |
969 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
947 |
970 // fetch the next 2 words |
948 if (fsm->slave_cat_words > EC_CAT_MEM * 2) { |
971 fsm->sii_offset += 2; |
949 EC_ERR("FSM category memory too small! %i words needed.\n", |
|
950 fsm->slave_cat_words); |
|
951 fsm->slave_state = ec_fsm_slave_end; |
|
952 return; |
|
953 } |
|
954 |
|
955 // start reading category data |
|
956 fsm->slave_cat_data_offset = 0; |
|
957 fsm->sii_offset = (fsm->slave_cat_offset + 2 + |
|
958 fsm->slave_cat_data_offset); |
|
959 fsm->sii_mode = 1; |
|
960 fsm->sii_state = ec_fsm_sii_start_reading; |
|
961 fsm->slave_state = ec_fsm_slave_category_data; |
|
962 fsm->slave_state(fsm); // execute state immediately |
|
963 } |
|
964 |
|
965 /*****************************************************************************/ |
|
966 |
|
967 /** |
|
968 Slave state: CATEGORY_DATA. |
|
969 Reads category data. |
|
970 */ |
|
971 |
|
972 void ec_fsm_slave_category_data(ec_fsm_t *fsm /**< finite state machine */) |
|
973 { |
|
974 // execute SII state machine |
|
975 fsm->sii_state(fsm); |
|
976 |
|
977 if (fsm->sii_state == ec_fsm_sii_error) { |
|
978 kfree(fsm->slave_cat_data); |
|
979 fsm->slave_cat_data = NULL; |
|
980 fsm->slave_state = ec_fsm_slave_end; |
|
981 EC_ERR("FSM failed to read category 0x%02X data at 0x%04X" |
|
982 " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset, |
|
983 fsm->slave->ring_position); |
|
984 return; |
|
985 } |
|
986 |
|
987 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
988 |
|
989 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] = |
|
990 fsm->sii_result & 0xFF; |
|
991 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] = |
|
992 (fsm->sii_result >> 8) & 0xFF; |
|
993 |
|
994 // read second word "on the fly" |
|
995 if (fsm->slave_cat_data_offset + 1 < fsm->slave_cat_words) { |
|
996 fsm->slave_cat_data_offset++; |
|
997 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] = |
|
998 (fsm->sii_result >> 16) & 0xFF; |
|
999 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] = |
|
1000 (fsm->sii_result >> 24) & 0xFF; |
|
1001 } |
|
1002 |
|
1003 fsm->slave_cat_data_offset++; |
|
1004 |
|
1005 if (fsm->slave_cat_data_offset < fsm->slave_cat_words) { |
|
1006 fsm->sii_offset = (fsm->slave_cat_offset + 2 + |
|
1007 fsm->slave_cat_data_offset); |
|
1008 fsm->sii_mode = 1; |
|
1009 fsm->sii_state = ec_fsm_sii_start_reading; |
972 fsm->sii_state = ec_fsm_sii_start_reading; |
1010 fsm->slave_state = ec_fsm_slave_category_data; |
973 fsm->sii_state(fsm); // execute state immediately |
1011 fsm->slave_state(fsm); // execute state immediately |
974 return; |
1012 return; |
975 } |
1013 } |
976 |
1014 |
977 // Evaluate EEPROM contents |
1015 // category data complete |
978 |
1016 switch (fsm->slave_cat_type) |
979 slave->sii_alias = |
1017 { |
980 EC_READ_U16(slave->eeprom_data + 2 * 0x0004); |
1018 case 0x000A: |
981 slave->sii_vendor_id = |
1019 if (ec_slave_fetch_strings(fsm->slave, fsm->slave_cat_data)) |
982 EC_READ_U32(slave->eeprom_data + 2 * 0x0008); |
1020 goto out_free; |
983 slave->sii_product_code = |
1021 break; |
984 EC_READ_U32(slave->eeprom_data + 2 * 0x000A); |
1022 case 0x001E: |
985 slave->sii_revision_number = |
1023 if (ec_slave_fetch_general(fsm->slave, fsm->slave_cat_data)) |
986 EC_READ_U32(slave->eeprom_data + 2 * 0x000C); |
1024 goto out_free; |
987 slave->sii_serial_number = |
1025 break; |
988 EC_READ_U32(slave->eeprom_data + 2 * 0x000E); |
1026 case 0x0028: |
989 slave->sii_rx_mailbox_offset = |
1027 break; |
990 EC_READ_U16(slave->eeprom_data + 2 * 0x0018); |
1028 case 0x0029: |
991 slave->sii_rx_mailbox_size = |
1029 if (ec_slave_fetch_sync(fsm->slave, fsm->slave_cat_data, |
992 EC_READ_U16(slave->eeprom_data + 2 * 0x0019); |
1030 fsm->slave_cat_words)) |
993 slave->sii_tx_mailbox_offset = |
1031 goto out_free; |
994 EC_READ_U16(slave->eeprom_data + 2 * 0x001A); |
1032 break; |
995 slave->sii_tx_mailbox_size = |
1033 case 0x0032: |
996 EC_READ_U16(slave->eeprom_data + 2 * 0x001B); |
1034 if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data, |
997 slave->sii_mailbox_protocols = |
1035 fsm->slave_cat_words, |
998 EC_READ_U16(slave->eeprom_data + 2 * 0x001C); |
1036 EC_TX_PDO)) |
999 |
1037 goto out_free; |
1000 // evaluate category data |
1038 break; |
1001 cat_word = (uint16_t *) slave->eeprom_data + 0x0040; |
1039 case 0x0033: |
1002 while (EC_READ_U16(cat_word) != 0xFFFF) { |
1040 if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data, |
1003 cat_type = EC_READ_U16(cat_word) & 0x7FFF; |
1041 fsm->slave_cat_words, |
1004 cat_size = EC_READ_U16(cat_word + 1); |
1042 EC_RX_PDO)) |
1005 |
1043 goto out_free; |
1006 switch (cat_type) { |
1044 break; |
1007 case 0x000A: |
1045 default: |
1008 if (ec_slave_fetch_strings(slave, (uint8_t *) (cat_word + 2))) |
1046 EC_WARN("FSM: Unknown category type 0x%04X in slave %i.\n", |
1009 goto end; |
1047 fsm->slave_cat_type, fsm->slave->ring_position); |
1010 break; |
1048 } |
1011 case 0x001E: |
1049 |
1012 if (ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2))) |
1050 // start reading next category header |
1013 goto end; |
1051 fsm->slave_cat_offset += 2 + fsm->slave_cat_words; |
1014 break; |
1052 fsm->sii_offset = fsm->slave_cat_offset; |
1015 case 0x0028: |
1053 fsm->sii_mode = 1; |
1016 break; |
1054 fsm->sii_state = ec_fsm_sii_start_reading; |
1017 case 0x0029: |
1055 fsm->slave_state = ec_fsm_slave_category_header; |
1018 if (ec_slave_fetch_sync(slave, (uint8_t *) (cat_word + 2), |
1056 fsm->slave_state(fsm); // execute state immediately |
1019 cat_size)) |
1057 return; |
1020 goto end; |
1058 |
1021 break; |
1059 out_free: |
1022 case 0x0032: |
1060 kfree(fsm->slave_cat_data); |
1023 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2), |
1061 fsm->slave_cat_data = NULL; |
1024 cat_size, EC_TX_PDO)) |
1025 goto end; |
|
1026 break; |
|
1027 case 0x0033: |
|
1028 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2), |
|
1029 cat_size, EC_RX_PDO)) |
|
1030 goto end; |
|
1031 break; |
|
1032 default: |
|
1033 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
|
1034 cat_type, slave->ring_position); |
|
1035 } |
|
1036 |
|
1037 cat_word += cat_size + 2; |
|
1038 } |
|
1039 |
|
1040 end: |
|
1062 fsm->slave_state = ec_fsm_slave_end; |
1041 fsm->slave_state = ec_fsm_slave_end; |
1063 } |
1042 } |
1064 |
1043 |
1065 /*****************************************************************************/ |
1044 /*****************************************************************************/ |
1066 |
1045 |
1147 |
1126 |
1148 // known slave type, take type's SM information |
1127 // known slave type, take type's SM information |
1149 if (slave->type) { |
1128 if (slave->type) { |
1150 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1129 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) { |
1151 sync = slave->type->sync_managers[j]; |
1130 sync = slave->type->sync_managers[j]; |
1152 ec_sync_config(sync, command->data + EC_SYNC_SIZE * j); |
1131 ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j); |
1153 } |
1132 } |
1154 } |
1133 } |
1155 |
1134 |
1156 // unknown type, but slave has mailbox |
1135 // unknown type, but slave has mailbox |
1157 else if (slave->sii_mailbox_protocols) |
1136 else if (slave->sii_mailbox_protocols) |
1266 // configure FMMUs |
1245 // configure FMMUs |
1267 ec_command_npwr(command, slave->station_address, |
1246 ec_command_npwr(command, slave->station_address, |
1268 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); |
1247 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count); |
1269 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1248 memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); |
1270 for (j = 0; j < slave->fmmu_count; j++) { |
1249 for (j = 0; j < slave->fmmu_count; j++) { |
1271 ec_fmmu_config(&slave->fmmus[j], command->data + EC_FMMU_SIZE * j); |
1250 ec_fmmu_config(&slave->fmmus[j], slave, |
1251 command->data + EC_FMMU_SIZE * j); |
|
1272 } |
1252 } |
1273 |
1253 |
1274 ec_master_queue_command(master, command); |
1254 ec_master_queue_command(master, command); |
1275 fsm->slave_state = ec_fsm_slave_saveop; |
1255 fsm->slave_state = ec_fsm_slave_saveop; |
1276 } |
1256 } |
1389 |
1369 |
1390 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1370 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1391 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1371 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1392 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1372 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1393 ec_master_queue_command(fsm->master, command); |
1373 ec_master_queue_command(fsm->master, command); |
1394 fsm->sii_state = ec_fsm_sii_check; |
1374 fsm->sii_state = ec_fsm_sii_read_check; |
1395 } |
1375 } |
1396 |
1376 |
1397 /*****************************************************************************/ |
1377 /*****************************************************************************/ |
1398 |
1378 |
1399 /** |
1379 /** |
1400 SII state: CHECK. |
1380 SII state: READ_CHECK. |
1401 Checks, if the SII-read-command has been sent and issues a fetch command. |
1381 Checks, if the SII-read-command has been sent and issues a fetch command. |
1402 */ |
1382 */ |
1403 |
1383 |
1404 void ec_fsm_sii_check(ec_fsm_t *fsm /**< finite state machine */) |
1384 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
1405 { |
1385 { |
1406 ec_command_t *command = &fsm->command; |
1386 ec_command_t *command = &fsm->command; |
1407 |
1387 |
1408 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1388 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1409 EC_ERR("SII: Reception of read command failed.\n"); |
1389 EC_ERR("SII: Reception of read command failed.\n"); |
1420 else { |
1400 else { |
1421 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1401 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1422 } |
1402 } |
1423 |
1403 |
1424 ec_master_queue_command(fsm->master, command); |
1404 ec_master_queue_command(fsm->master, command); |
1425 fsm->sii_state = ec_fsm_sii_fetch; |
1405 fsm->sii_state = ec_fsm_sii_read_fetch; |
1426 } |
1406 } |
1427 |
1407 |
1428 /*****************************************************************************/ |
1408 /*****************************************************************************/ |
1429 |
1409 |
1430 /** |
1410 /** |
1431 SII state: FETCH. |
1411 SII state: READ_FETCH. |
1432 Fetches the result of an SII-read command. |
1412 Fetches the result of an SII-read command. |
1433 */ |
1413 */ |
1434 |
1414 |
1435 void ec_fsm_sii_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1415 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1436 { |
1416 { |
1437 ec_command_t *command = &fsm->command; |
1417 ec_command_t *command = &fsm->command; |
1438 |
1418 |
1439 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1419 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1440 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1420 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1475 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
1455 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
1476 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
1456 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
1477 #endif |
1457 #endif |
1478 |
1458 |
1479 // SII value received. |
1459 // SII value received. |
1480 fsm->sii_result = EC_READ_U32(command->data + 6); |
1460 memcpy(fsm->sii_value, command->data + 6, 4); |
1481 fsm->sii_state = ec_fsm_sii_end; |
1461 fsm->sii_state = ec_fsm_sii_end; |
1462 } |
|
1463 |
|
1464 /*****************************************************************************/ |
|
1465 |
|
1466 /** |
|
1467 SII state: START_WRITING. |
|
1468 Starts reading the slave information interface. |
|
1469 */ |
|
1470 |
|
1471 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
|
1472 { |
|
1473 ec_command_t *command = &fsm->command; |
|
1474 |
|
1475 // initiate write operation |
|
1476 ec_command_npwr(command, fsm->slave->station_address, 0x502, 8); |
|
1477 EC_WRITE_U8 (command->data, 0x01); // enable write access |
|
1478 EC_WRITE_U8 (command->data + 1, 0x02); // request write operation |
|
1479 EC_WRITE_U32(command->data + 2, fsm->sii_offset); |
|
1480 memcpy(command->data + 6, fsm->sii_value, 2); |
|
1481 ec_master_queue_command(fsm->master, command); |
|
1482 fsm->sii_state = ec_fsm_sii_write_check; |
|
1483 } |
|
1484 |
|
1485 /*****************************************************************************/ |
|
1486 |
|
1487 /** |
|
1488 SII state: WRITE_CHECK. |
|
1489 */ |
|
1490 |
|
1491 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
|
1492 { |
|
1493 ec_command_t *command = &fsm->command; |
|
1494 |
|
1495 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
1496 EC_ERR("SII: Reception of write command failed.\n"); |
|
1497 fsm->sii_state = ec_fsm_sii_error; |
|
1498 return; |
|
1499 } |
|
1500 |
|
1501 fsm->sii_start = get_cycles(); |
|
1502 |
|
1503 // issue check/fetch command |
|
1504 ec_command_nprd(command, fsm->slave->station_address, 0x502, 2); |
|
1505 ec_master_queue_command(fsm->master, command); |
|
1506 fsm->sii_state = ec_fsm_sii_write_check2; |
|
1507 } |
|
1508 |
|
1509 /*****************************************************************************/ |
|
1510 |
|
1511 /** |
|
1512 SII state: WRITE_CHECK2. |
|
1513 */ |
|
1514 |
|
1515 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
|
1516 { |
|
1517 ec_command_t *command = &fsm->command; |
|
1518 |
|
1519 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
1520 EC_ERR("SII: Reception of write check command failed.\n"); |
|
1521 fsm->sii_state = ec_fsm_sii_error; |
|
1522 return; |
|
1523 } |
|
1524 |
|
1525 if (EC_READ_U8(command->data + 1) & 0x82) { |
|
1526 // still busy... timeout? |
|
1527 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
|
1528 EC_ERR("SII: Write timeout.\n"); |
|
1529 fsm->sii_state = ec_fsm_sii_error; |
|
1530 } |
|
1531 |
|
1532 // issue check/fetch command again |
|
1533 ec_master_queue_command(fsm->master, command); |
|
1534 } |
|
1535 else if (EC_READ_U8(command->data + 1) & 0x40) { |
|
1536 EC_ERR("SII: Write operation failed!\n"); |
|
1537 fsm->sii_state = ec_fsm_sii_error; |
|
1538 } |
|
1539 else { // success |
|
1540 fsm->sii_state = ec_fsm_sii_end; |
|
1541 } |
|
1482 } |
1542 } |
1483 |
1543 |
1484 /*****************************************************************************/ |
1544 /*****************************************************************************/ |
1485 |
1545 |
1486 /** |
1546 /** |