master/fsm.c
branchstable-1.0
changeset 1621 4bbe090553f7
parent 1619 0d4119024f55
child 1623 05622513f627
equal deleted inserted replaced
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 /**