809 fsm->slave_state = ec_fsm_slave_end; |
794 fsm->slave_state = ec_fsm_slave_end; |
810 return; |
795 return; |
811 } |
796 } |
812 |
797 |
813 dl_status = EC_READ_U16(command->data); |
798 dl_status = EC_READ_U16(command->data); |
814 |
|
815 for (i = 0; i < 4; i++) { |
799 for (i = 0; i < 4; i++) { |
816 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
800 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; |
817 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
801 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; |
802 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
819 } |
803 } |
820 |
804 |
821 fsm->sii_offset = 0x0004; |
805 // Start fetching EEPROM size |
|
806 |
|
807 fsm->sii_offset = 0x0040; // first category header |
822 fsm->sii_mode = 1; |
808 fsm->sii_mode = 1; |
823 fsm->sii_state = ec_fsm_sii_start_reading; |
809 fsm->sii_state = ec_fsm_sii_start_reading; |
824 fsm->slave_sii_num = 0; |
810 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 |
811 fsm->slave_state(fsm); // execute state immediately |
827 } |
812 } |
828 |
813 |
829 /*****************************************************************************/ |
814 /*****************************************************************************/ |
830 |
815 |
831 /** |
816 /** |
832 Slave state: READ_SII. |
817 Slave state: FETCH_EEPROM. |
833 */ |
818 */ |
834 |
819 |
835 void ec_fsm_slave_read_sii(ec_fsm_t *fsm /**< finite state machine */) |
820 void ec_fsm_slave_fetch_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
836 { |
821 { |
837 ec_slave_t *slave = fsm->slave; |
822 ec_slave_t *slave = fsm->slave; |
|
823 uint16_t cat_type, cat_size; |
838 |
824 |
839 // execute SII state machine |
825 // execute SII state machine |
840 fsm->sii_state(fsm); |
826 fsm->sii_state(fsm); |
841 |
827 |
842 if (fsm->sii_state == ec_fsm_sii_error) { |
828 if (fsm->sii_state == ec_fsm_sii_error) { |
843 fsm->slave_state = ec_fsm_slave_end; |
829 fsm->slave_state = ec_fsm_slave_end; |
844 EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n", |
830 EC_ERR("Failed to read EEPROM size of slave %i.\n", |
845 fsm->sii_offset, slave->ring_position); |
831 slave->ring_position); |
846 return; |
832 return; |
847 } |
833 } |
848 |
834 |
849 if (fsm->sii_state != ec_fsm_sii_end) return; |
835 if (fsm->sii_state != ec_fsm_sii_end) return; |
850 |
836 |
851 switch (fsm->slave_sii_num) { |
837 cat_type = EC_READ_U16(fsm->sii_result); |
852 case 0: |
838 cat_size = EC_READ_U16(fsm->sii_result + 2); |
853 slave->sii_alias = fsm->sii_result & 0xFFFF; |
839 |
854 fsm->sii_offset = 0x0008; |
840 if (cat_type != 0xFFFF) { // not the last category |
855 break; |
841 fsm->sii_offset += cat_size + 2; |
856 case 1: |
842 fsm->sii_state = ec_fsm_sii_start_reading; |
857 slave->sii_vendor_id = fsm->sii_result; |
843 fsm->sii_state(fsm); // execute state immediately |
858 fsm->sii_offset = 0x000A; |
844 return; |
859 break; |
845 } |
860 case 2: |
846 |
861 slave->sii_product_code = fsm->sii_result; |
847 slave->eeprom_size = (fsm->sii_offset + 1) * 2; |
862 fsm->sii_offset = 0x000C; |
848 |
863 break; |
849 if (slave->eeprom_data) { |
864 case 3: |
850 EC_INFO("Freeing old EEPROM data on slave %i...\n", |
865 slave->sii_revision_number = fsm->sii_result; |
851 slave->ring_position); |
866 fsm->sii_offset = 0x000E; |
852 kfree(slave->eeprom_data); |
867 break; |
853 } |
868 case 4: |
854 |
869 slave->sii_serial_number = fsm->sii_result; |
855 if (!(slave->eeprom_data = |
870 fsm->sii_offset = 0x0018; |
856 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
871 break; |
857 EC_ERR("Failed to allocate EEPROM data on slave %i.\n", |
872 case 5: |
858 slave->ring_position); |
873 slave->sii_rx_mailbox_offset = fsm->sii_result & 0xFFFF; |
859 fsm->slave_state = ec_fsm_slave_end; |
874 slave->sii_rx_mailbox_size = fsm->sii_result >> 16; |
860 return; |
875 fsm->sii_offset = 0x001A; |
861 } |
876 break; |
862 |
877 case 6: |
863 // Start fetching EEPROM contents |
878 slave->sii_tx_mailbox_offset = fsm->sii_result & 0xFFFF; |
864 |
879 slave->sii_tx_mailbox_size = fsm->sii_result >> 16; |
865 fsm->sii_offset = 0x0000; |
880 fsm->sii_offset = 0x001C; |
866 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; |
867 fsm->sii_state = ec_fsm_sii_start_reading; |
|
868 fsm->slave_state = ec_fsm_slave_fetch_eeprom2; |
911 fsm->slave_state(fsm); // execute state immediately |
869 fsm->slave_state(fsm); // execute state immediately |
912 } |
870 } |
913 |
871 |
914 /*****************************************************************************/ |
872 /*****************************************************************************/ |
915 |
873 |
916 /** |
874 /** |
917 Slave state: CATEGORY_HEADER. |
875 Slave state: FETCH_EEPROM2. |
918 Start reading categories. |
876 */ |
919 */ |
877 |
920 |
878 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 */) |
879 { |
922 { |
880 ec_slave_t *slave = fsm->slave; |
|
881 uint16_t *cat_word, cat_type, cat_size; |
|
882 |
923 // execute SII state machine |
883 // execute SII state machine |
924 fsm->sii_state(fsm); |
884 fsm->sii_state(fsm); |
925 |
885 |
926 if (fsm->sii_state == ec_fsm_sii_error) { |
886 if (fsm->sii_state == ec_fsm_sii_error) { |
927 kfree(fsm->slave_cat_data); |
887 fsm->slave_state = ec_fsm_slave_end; |
928 fsm->slave_cat_data = NULL; |
888 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n", |
929 fsm->slave_state = ec_fsm_slave_end; |
889 slave->ring_position); |
930 EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n", |
|
931 fsm->slave_cat_offset, fsm->slave->ring_position); |
|
932 return; |
890 return; |
933 } |
891 } |
934 |
892 |
935 if (fsm->sii_state != ec_fsm_sii_end) return; |
893 if (fsm->sii_state != ec_fsm_sii_end) return; |
936 |
894 |
937 // last category? |
895 // 2 words fetched |
938 if ((fsm->sii_result & 0xFFFF) == 0xFFFF) { |
896 |
939 kfree(fsm->slave_cat_data); |
897 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
940 fsm->slave_cat_data = NULL; |
898 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_result, 4); |
941 fsm->slave_state = ec_fsm_slave_end; |
899 } |
942 return; |
900 else { // copy the last word |
943 } |
901 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_result, 2); |
944 |
902 } |
945 fsm->slave_cat_type = fsm->sii_result & 0x7FFF; |
903 |
946 fsm->slave_cat_words = (fsm->sii_result >> 16) & 0xFFFF; |
904 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
947 |
905 // fetch the next 2 words |
948 if (fsm->slave_cat_words > EC_CAT_MEM * 2) { |
906 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; |
907 fsm->sii_state = ec_fsm_sii_start_reading; |
1010 fsm->slave_state = ec_fsm_slave_category_data; |
908 fsm->sii_state(fsm); // execute state immediately |
1011 fsm->slave_state(fsm); // execute state immediately |
909 return; |
1012 return; |
910 } |
1013 } |
911 |
1014 |
912 // Evaluate EEPROM contents |
1015 // category data complete |
913 |
1016 switch (fsm->slave_cat_type) |
914 slave->sii_alias = |
1017 { |
915 EC_READ_U16(slave->eeprom_data + 2 * 0x0004); |
1018 case 0x000A: |
916 slave->sii_vendor_id = |
1019 if (ec_slave_fetch_strings(fsm->slave, fsm->slave_cat_data)) |
917 EC_READ_U32(slave->eeprom_data + 2 * 0x0008); |
1020 goto out_free; |
918 slave->sii_product_code = |
1021 break; |
919 EC_READ_U32(slave->eeprom_data + 2 * 0x000A); |
1022 case 0x001E: |
920 slave->sii_revision_number = |
1023 if (ec_slave_fetch_general(fsm->slave, fsm->slave_cat_data)) |
921 EC_READ_U32(slave->eeprom_data + 2 * 0x000C); |
1024 goto out_free; |
922 slave->sii_serial_number = |
1025 break; |
923 EC_READ_U32(slave->eeprom_data + 2 * 0x000E); |
1026 case 0x0028: |
924 slave->sii_rx_mailbox_offset = |
1027 break; |
925 EC_READ_U16(slave->eeprom_data + 2 * 0x0018); |
1028 case 0x0029: |
926 slave->sii_rx_mailbox_size = |
1029 if (ec_slave_fetch_sync(fsm->slave, fsm->slave_cat_data, |
927 EC_READ_U16(slave->eeprom_data + 2 * 0x0019); |
1030 fsm->slave_cat_words)) |
928 slave->sii_tx_mailbox_offset = |
1031 goto out_free; |
929 EC_READ_U16(slave->eeprom_data + 2 * 0x001A); |
1032 break; |
930 slave->sii_tx_mailbox_size = |
1033 case 0x0032: |
931 EC_READ_U16(slave->eeprom_data + 2 * 0x001B); |
1034 if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data, |
932 slave->sii_mailbox_protocols = |
1035 fsm->slave_cat_words, |
933 EC_READ_U16(slave->eeprom_data + 2 * 0x001C); |
1036 EC_TX_PDO)) |
934 |
1037 goto out_free; |
935 // evaluate category data |
1038 break; |
936 cat_word = (uint16_t *) slave->eeprom_data + 0x0040; |
1039 case 0x0033: |
937 while (EC_READ_U16(cat_word) != 0xFFFF) { |
1040 if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data, |
938 cat_type = EC_READ_U16(cat_word) & 0x7FFF; |
1041 fsm->slave_cat_words, |
939 cat_size = EC_READ_U16(cat_word + 1); |
1042 EC_RX_PDO)) |
940 |
1043 goto out_free; |
941 switch (cat_type) { |
1044 break; |
942 case 0x000A: |
1045 default: |
943 if (ec_slave_fetch_strings(slave, (uint8_t *) (cat_word + 2))) |
1046 EC_WARN("FSM: Unknown category type 0x%04X in slave %i.\n", |
944 goto end; |
1047 fsm->slave_cat_type, fsm->slave->ring_position); |
945 break; |
1048 } |
946 case 0x001E: |
1049 |
947 if (ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2))) |
1050 // start reading next category header |
948 goto end; |
1051 fsm->slave_cat_offset += 2 + fsm->slave_cat_words; |
949 break; |
1052 fsm->sii_offset = fsm->slave_cat_offset; |
950 case 0x0028: |
1053 fsm->sii_mode = 1; |
951 break; |
1054 fsm->sii_state = ec_fsm_sii_start_reading; |
952 case 0x0029: |
1055 fsm->slave_state = ec_fsm_slave_category_header; |
953 if (ec_slave_fetch_sync(slave, (uint8_t *) (cat_word + 2), |
1056 fsm->slave_state(fsm); // execute state immediately |
954 cat_size)) |
1057 return; |
955 goto end; |
1058 |
956 break; |
1059 out_free: |
957 case 0x0032: |
1060 kfree(fsm->slave_cat_data); |
958 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2), |
1061 fsm->slave_cat_data = NULL; |
959 cat_size, EC_TX_PDO)) |
|
960 goto end; |
|
961 break; |
|
962 case 0x0033: |
|
963 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2), |
|
964 cat_size, EC_RX_PDO)) |
|
965 goto end; |
|
966 break; |
|
967 default: |
|
968 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
|
969 cat_type, slave->ring_position); |
|
970 } |
|
971 |
|
972 cat_word += cat_size + 2; |
|
973 } |
|
974 |
|
975 end: |
1062 fsm->slave_state = ec_fsm_slave_end; |
976 fsm->slave_state = ec_fsm_slave_end; |
1063 } |
977 } |
1064 |
978 |
1065 /*****************************************************************************/ |
979 /*****************************************************************************/ |
1066 |
980 |