master/fsm.c
changeset 238 b4960499098f
child 246 0bf7c769de06
equal deleted inserted replaced
237:7b3126cf6dab 238:b4960499098f
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it
       
    10  *  and/or modify it under the terms of the GNU General Public License
       
    11  *  as published by the Free Software Foundation; version 2 of the License.
       
    12  *
       
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be
       
    14  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    16  *  GNU General Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License
       
    19  *  along with the IgH EtherCAT Master; if not, write to the Free Software
       
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    21  *
       
    22  *****************************************************************************/
       
    23 
       
    24 /**
       
    25    \file
       
    26    EtherCAT finite state machines.
       
    27 */
       
    28 
       
    29 /*****************************************************************************/
       
    30 
       
    31 #include "globals.h"
       
    32 #include "fsm.h"
       
    33 #include "master.h"
       
    34 
       
    35 /*****************************************************************************/
       
    36 
       
    37 #define EC_CAT_MEM 0x100
       
    38 
       
    39 /*****************************************************************************/
       
    40 
       
    41 void ec_fsm_master_start(ec_fsm_t *);
       
    42 void ec_fsm_master_wait(ec_fsm_t *);
       
    43 void ec_fsm_master_slave(ec_fsm_t *);
       
    44 void ec_fsm_master_calc(ec_fsm_t *);
       
    45 void ec_fsm_master_finished(ec_fsm_t *);
       
    46 
       
    47 void ec_fsm_slave_start(ec_fsm_t *);
       
    48 void ec_fsm_slave_read_base(ec_fsm_t *);
       
    49 void ec_fsm_slave_read_dl(ec_fsm_t *);
       
    50 void ec_fsm_slave_prepare_sii(ec_fsm_t *);
       
    51 void ec_fsm_slave_read_sii(ec_fsm_t *);
       
    52 void ec_fsm_slave_categories(ec_fsm_t *);
       
    53 void ec_fsm_slave_category_header(ec_fsm_t *);
       
    54 void ec_fsm_slave_category_data(ec_fsm_t *);
       
    55 void ec_fsm_slave_finished(ec_fsm_t *);
       
    56 
       
    57 void ec_fsm_sii_start_reading(ec_fsm_t *);
       
    58 void ec_fsm_sii_check(ec_fsm_t *);
       
    59 void ec_fsm_sii_fetch(ec_fsm_t *);
       
    60 void ec_fsm_sii_finished(ec_fsm_t *);
       
    61 void ec_fsm_sii_error(ec_fsm_t *);
       
    62 
       
    63 /*****************************************************************************/
       
    64 
       
    65 int ec_fsm_init(ec_fsm_t *fsm, ec_master_t *master)
       
    66 {
       
    67     fsm->master = master;
       
    68     fsm->master_state = ec_fsm_master_start;
       
    69     fsm->master_slaves_responding = 0;
       
    70     fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
       
    71     fsm->slave_cat_data = NULL;
       
    72 
       
    73     ec_command_init(&fsm->command);
       
    74     if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) {
       
    75         EC_ERR("FSM failed to allocate FSM command.\n");
       
    76         return -1;
       
    77     }
       
    78 
       
    79     return 0;
       
    80 }
       
    81 
       
    82 /*****************************************************************************/
       
    83 
       
    84 void ec_fsm_clear(ec_fsm_t *fsm)
       
    85 {
       
    86     if (fsm->slave_cat_data) kfree(fsm->slave_cat_data);
       
    87     ec_command_clear(&fsm->command);
       
    88 }
       
    89 
       
    90 /*****************************************************************************/
       
    91 
       
    92 void ec_fsm_reset(ec_fsm_t *fsm)
       
    93 {
       
    94     fsm->master_state = ec_fsm_master_start;
       
    95     fsm->master_slaves_responding = 0;
       
    96     fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
       
    97 
       
    98     if (fsm->slave_cat_data) {
       
    99         kfree(fsm->slave_cat_data);
       
   100         fsm->slave_cat_data = NULL;
       
   101     }
       
   102 }
       
   103 
       
   104 /*****************************************************************************/
       
   105 
       
   106 void ec_fsm_execute(ec_fsm_t *fsm)
       
   107 {
       
   108     fsm->master_state(fsm);
       
   109 }
       
   110 
       
   111 /*****************************************************************************/
       
   112 
       
   113 int ec_fsm_idle(const ec_fsm_t *fsm)
       
   114 {
       
   115     return (fsm->master_state == ec_fsm_master_start ||
       
   116             fsm->master_state == ec_fsm_master_wait ||
       
   117             fsm->master_state == ec_fsm_master_finished);
       
   118 }
       
   119 
       
   120 /******************************************************************************
       
   121  *  master state machine
       
   122  *****************************************************************************/
       
   123 
       
   124 /**
       
   125    State: Start.
       
   126    Starts with getting slave count and slave states.
       
   127 */
       
   128 
       
   129 void ec_fsm_master_start(ec_fsm_t *fsm)
       
   130 {
       
   131     ec_command_brd(&fsm->command, 0x0130, 2);
       
   132     ec_master_queue_command(fsm->master, &fsm->command);
       
   133 
       
   134     fsm->master_state = ec_fsm_master_wait;
       
   135 }
       
   136 
       
   137 /*****************************************************************************/
       
   138 
       
   139 void ec_fsm_master_wait(ec_fsm_t *fsm)
       
   140 {
       
   141     ec_command_t *command = &fsm->command;
       
   142     unsigned int first, topology_change, i;
       
   143     ec_slave_t *slave;
       
   144 
       
   145     if (command->state != EC_CMD_RECEIVED) {
       
   146         fsm->master_state = ec_fsm_master_start;
       
   147         fsm->master_state(fsm); // execute immediately
       
   148         return;
       
   149     }
       
   150 
       
   151     if (command->working_counter == fsm->master_slaves_responding &&
       
   152         command->data[0] == fsm->master_slave_states) {
       
   153         fsm->master_state = ec_fsm_master_start;
       
   154         fsm->master_state(fsm); // execute immediately
       
   155         return;
       
   156     }
       
   157 
       
   158     topology_change = command->working_counter !=
       
   159         fsm->master_slaves_responding;
       
   160 
       
   161     fsm->master_slaves_responding = command->working_counter;
       
   162     fsm->master_slave_states = command->data[0];
       
   163 
       
   164     EC_INFO("FSM: %i slave%s responding (", fsm->master_slaves_responding,
       
   165             fsm->master_slaves_responding == 1 ? "" : "s");
       
   166 
       
   167     first = 1;
       
   168     if (fsm->master_slave_states & EC_SLAVE_STATE_INIT) {
       
   169         printk("INIT");
       
   170         first = 0;
       
   171     }
       
   172     if (fsm->master_slave_states & EC_SLAVE_STATE_PREOP) {
       
   173         if (!first) printk(", ");
       
   174         printk("PREOP");
       
   175         first = 0;
       
   176     }
       
   177     if (fsm->master_slave_states & EC_SLAVE_STATE_SAVEOP) {
       
   178         if (!first) printk(", ");
       
   179         printk("SAVEOP");
       
   180         first = 0;
       
   181     }
       
   182     if (fsm->master_slave_states & EC_SLAVE_STATE_OP) {
       
   183         if (!first) printk(", ");
       
   184         printk("OP");
       
   185     }
       
   186     printk(")\n");
       
   187 
       
   188     if (!topology_change || fsm->master->mode == EC_MASTER_MODE_RUNNING) {
       
   189         fsm->master_state = ec_fsm_master_start;
       
   190         fsm->master_state(fsm); // execute immediately
       
   191         return;
       
   192     }
       
   193 
       
   194     // topology change!
       
   195     ec_master_clear_slaves(fsm->master);
       
   196 
       
   197     if (!fsm->master_slaves_responding) {
       
   198         // no slaves present -> finish state machine.
       
   199         fsm->master_state = ec_fsm_master_start;
       
   200         fsm->master_state(fsm); // execute immediately
       
   201         return;
       
   202     }
       
   203 
       
   204     // init slaves
       
   205     for (i = 0; i < fsm->master_slaves_responding; i++) {
       
   206         if (!(slave =
       
   207               (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_ATOMIC))) {
       
   208             EC_ERR("FSM failed to allocate slave %i!\n", i);
       
   209             fsm->master_state = ec_fsm_master_finished;
       
   210             return;
       
   211         }
       
   212 
       
   213         if (ec_slave_init(slave, fsm->master, i, i + 1)) {
       
   214             fsm->master_state = ec_fsm_master_finished;
       
   215             return;
       
   216         }
       
   217 
       
   218         if (kobject_add(&slave->kobj)) {
       
   219             EC_ERR("FSM failed to add kobject.\n");
       
   220             kobject_put(&slave->kobj); // free
       
   221             fsm->master_state = ec_fsm_master_finished;
       
   222             return;
       
   223         }
       
   224 
       
   225         list_add_tail(&slave->list, &fsm->master->slaves);
       
   226     }
       
   227 
       
   228     // begin scanning of slaves
       
   229     fsm->slave = list_entry(fsm->master->slaves.next,
       
   230                             ec_slave_t, list);
       
   231     fsm->slave_state = ec_fsm_slave_start;
       
   232 
       
   233     fsm->master_state = ec_fsm_master_slave;
       
   234     fsm->master_state(fsm); // execute immediately
       
   235 }
       
   236 
       
   237 /*****************************************************************************/
       
   238 
       
   239 /**
       
   240    State: Get Slave.
       
   241    Executes the sub-statemachine of a slave.
       
   242 */
       
   243 
       
   244 void ec_fsm_master_slave(ec_fsm_t *fsm)
       
   245 {
       
   246     ec_master_t *master = fsm->master;
       
   247 
       
   248     fsm->slave_state(fsm); // execute slave state machine
       
   249 
       
   250     if (fsm->slave_state != ec_fsm_slave_finished) return;
       
   251 
       
   252     // have all slaves been fetched?
       
   253     if (fsm->slave->list.next == &master->slaves) {
       
   254         fsm->master_state = ec_fsm_master_calc;
       
   255         fsm->master_state(fsm); // execute immediately
       
   256         return;
       
   257     }
       
   258 
       
   259     // process next slave
       
   260     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
       
   261     fsm->slave_state = ec_fsm_slave_start;
       
   262     fsm->slave_state(fsm); // execute immediately
       
   263 }
       
   264 
       
   265 /*****************************************************************************/
       
   266 
       
   267 /**
       
   268    Free-Run state: Calc.
       
   269 */
       
   270 
       
   271 void ec_fsm_master_calc(ec_fsm_t *fsm)
       
   272 {
       
   273     uint16_t coupler_index, coupler_subindex;
       
   274     uint16_t reverse_coupler_index, current_coupler_index;
       
   275     ec_slave_t *slave;
       
   276     ec_slave_ident_t *ident;
       
   277     ec_master_t *master = fsm->master;
       
   278 
       
   279     coupler_index = 0;
       
   280     reverse_coupler_index = 0xFFFF;
       
   281     current_coupler_index = 0x3FFF;
       
   282     coupler_subindex = 0;
       
   283 
       
   284     // for every slave on the bus
       
   285     list_for_each_entry(slave, &master->slaves, list)
       
   286     {
       
   287         // search for identification in "database"
       
   288         ident = slave_idents;
       
   289         while (ident->type) {
       
   290             if (unlikely(ident->vendor_id == slave->sii_vendor_id
       
   291                          && ident->product_code == slave->sii_product_code)) {
       
   292                 slave->type = ident->type;
       
   293                 break;
       
   294             }
       
   295             ident++;
       
   296         }
       
   297 
       
   298         if (!slave->type) {
       
   299             EC_WARN("FSM: Unknown slave device (vendor 0x%08X, code 0x%08X) at"
       
   300                     " position %i.\n", slave->sii_vendor_id,
       
   301                     slave->sii_product_code, slave->ring_position);
       
   302         }
       
   303         else if (slave->type->special == EC_TYPE_BUS_COUPLER) {
       
   304             if (slave->sii_alias)
       
   305                 current_coupler_index = reverse_coupler_index--;
       
   306             else
       
   307                 current_coupler_index = coupler_index++;
       
   308             coupler_subindex = 0;
       
   309         }
       
   310 
       
   311         slave->coupler_index = current_coupler_index;
       
   312         slave->coupler_subindex = coupler_subindex;
       
   313         coupler_subindex++;
       
   314     }
       
   315 
       
   316     fsm->master_state = ec_fsm_master_start;
       
   317     fsm->master_state(fsm); // execute immediately
       
   318 }
       
   319 
       
   320 /*****************************************************************************/
       
   321 
       
   322 /**
       
   323    Free-Run state: Finished.
       
   324    End state of the state machine. Does nothing.
       
   325 */
       
   326 
       
   327 void ec_fsm_master_finished(ec_fsm_t *fsm)
       
   328 {
       
   329 }
       
   330 
       
   331 /******************************************************************************
       
   332  *  slave state machine
       
   333  *****************************************************************************/
       
   334 
       
   335 /**
       
   336    Slave state: Start.
       
   337    First state of the slave state machine. Writes the station address to the
       
   338    slave, according to its ring position.
       
   339 */
       
   340 
       
   341 void ec_fsm_slave_start(ec_fsm_t *fsm)
       
   342 {
       
   343     ec_command_t *command = &fsm->command;
       
   344 
       
   345     // write station address
       
   346     ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
       
   347     EC_WRITE_U16(command->data, fsm->slave->station_address);
       
   348     ec_master_queue_command(fsm->master, command);
       
   349     fsm->slave_state = ec_fsm_slave_read_base;
       
   350 }
       
   351 
       
   352 /*****************************************************************************/
       
   353 
       
   354 /**
       
   355    Slave state: Read base.
       
   356 */
       
   357 
       
   358 void ec_fsm_slave_read_base(ec_fsm_t *fsm)
       
   359 {
       
   360     ec_command_t *command = &fsm->command;
       
   361 
       
   362     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   363         EC_ERR("FSM failed to write station address of slave %i.\n",
       
   364                fsm->slave->ring_position);
       
   365         fsm->slave_state = ec_fsm_slave_finished;
       
   366         return;
       
   367     }
       
   368 
       
   369     // read base data
       
   370     ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6);
       
   371     ec_master_queue_command(fsm->master, command);
       
   372     fsm->slave_state = ec_fsm_slave_read_dl;
       
   373 }
       
   374 
       
   375 /*****************************************************************************/
       
   376 
       
   377 /**
       
   378    Slave state: Read DL.
       
   379 */
       
   380 
       
   381 void ec_fsm_slave_read_dl(ec_fsm_t *fsm)
       
   382 {
       
   383     ec_command_t *command = &fsm->command;
       
   384     ec_slave_t *slave = fsm->slave;
       
   385 
       
   386     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   387         EC_ERR("FSM failed to read base data of slave %i.\n",
       
   388                slave->ring_position);
       
   389         fsm->slave_state = ec_fsm_slave_finished;
       
   390         return;
       
   391     }
       
   392 
       
   393     slave->base_type       = EC_READ_U8 (command->data);
       
   394     slave->base_revision   = EC_READ_U8 (command->data + 1);
       
   395     slave->base_build      = EC_READ_U16(command->data + 2);
       
   396     slave->base_fmmu_count = EC_READ_U8 (command->data + 4);
       
   397     slave->base_sync_count = EC_READ_U8 (command->data + 5);
       
   398 
       
   399     if (slave->base_fmmu_count > EC_MAX_FMMUS)
       
   400         slave->base_fmmu_count = EC_MAX_FMMUS;
       
   401 
       
   402     // read data link status
       
   403     ec_command_nprd(command, slave->station_address, 0x0110, 2);
       
   404     ec_master_queue_command(slave->master, command);
       
   405     fsm->slave_state = ec_fsm_slave_prepare_sii;
       
   406 }
       
   407 
       
   408 /*****************************************************************************/
       
   409 
       
   410 /**
       
   411    Slave state: Prepare SII.
       
   412 */
       
   413 
       
   414 void ec_fsm_slave_prepare_sii(ec_fsm_t *fsm)
       
   415 {
       
   416     ec_command_t *command = &fsm->command;
       
   417     ec_slave_t *slave = fsm->slave;
       
   418     uint16_t dl_status;
       
   419     unsigned int i;
       
   420 
       
   421     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   422         EC_ERR("FSM failed to read DL status of slave %i.\n",
       
   423                slave->ring_position);
       
   424         fsm->slave_state = ec_fsm_slave_finished;
       
   425         return;
       
   426     }
       
   427 
       
   428     dl_status = EC_READ_U16(command->data);
       
   429 
       
   430     for (i = 0; i < 4; i++) {
       
   431         slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
       
   432         slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
       
   433         slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
       
   434     }
       
   435 
       
   436     fsm->sii_offset = 0x0004;
       
   437     fsm->sii_state = ec_fsm_sii_start_reading;
       
   438     fsm->slave_sii_num = 0;
       
   439     fsm->slave_state = ec_fsm_slave_read_sii;
       
   440     fsm->slave_state(fsm); // execute state immediately
       
   441 }
       
   442 
       
   443 /*****************************************************************************/
       
   444 
       
   445 /**
       
   446    Slave state: Read SII.
       
   447 */
       
   448 
       
   449 void ec_fsm_slave_read_sii(ec_fsm_t *fsm)
       
   450 {
       
   451     ec_slave_t *slave = fsm->slave;
       
   452 
       
   453     // execute SII state machine
       
   454     fsm->sii_state(fsm);
       
   455 
       
   456     if (fsm->sii_state == ec_fsm_sii_error) {
       
   457         fsm->slave_state = ec_fsm_slave_finished;
       
   458         EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n",
       
   459                fsm->sii_offset, slave->ring_position);
       
   460         return;
       
   461     }
       
   462 
       
   463     if (fsm->sii_state != ec_fsm_sii_finished) return;
       
   464 
       
   465     switch (fsm->slave_sii_num) {
       
   466         case 0:
       
   467             slave->sii_alias = fsm->sii_result & 0xFFFF;
       
   468             fsm->sii_offset = 0x0008;
       
   469             break;
       
   470         case 1:
       
   471             slave->sii_vendor_id = fsm->sii_result;
       
   472             fsm->sii_offset = 0x000A;
       
   473             break;
       
   474         case 2:
       
   475             slave->sii_product_code = fsm->sii_result;
       
   476             fsm->sii_offset = 0x000C;
       
   477             break;
       
   478         case 3:
       
   479             slave->sii_revision_number = fsm->sii_result;
       
   480             fsm->sii_offset = 0x000E;
       
   481             break;
       
   482         case 4:
       
   483             slave->sii_serial_number = fsm->sii_result;
       
   484             fsm->sii_offset = 0x0018;
       
   485             break;
       
   486         case 5:
       
   487             slave->sii_rx_mailbox_offset = fsm->sii_result & 0xFFFF;
       
   488             slave->sii_rx_mailbox_size = fsm->sii_result >> 16;
       
   489             fsm->sii_offset = 0x001A;
       
   490             break;
       
   491         case 6:
       
   492             slave->sii_tx_mailbox_offset = fsm->sii_result & 0xFFFF;
       
   493             slave->sii_tx_mailbox_size = fsm->sii_result >> 16;
       
   494             fsm->sii_offset = 0x001C;
       
   495             break;
       
   496         case 7:
       
   497             slave->sii_mailbox_protocols = fsm->sii_result & 0xFFFF;
       
   498             fsm->slave_state = ec_fsm_slave_categories;
       
   499             fsm->slave_state(fsm); // execute state immediately
       
   500             return;
       
   501     }
       
   502 
       
   503     fsm->slave_sii_num++;
       
   504     fsm->sii_state = ec_fsm_sii_start_reading;
       
   505     fsm->slave_state(fsm); // execute state immediately
       
   506 }
       
   507 
       
   508 /*****************************************************************************/
       
   509 
       
   510 /**
       
   511    Slave state: Categories.
       
   512 */
       
   513 
       
   514 void ec_fsm_slave_categories(ec_fsm_t *fsm)
       
   515 {
       
   516     fsm->slave_cat_offset = 0x0040;
       
   517 
       
   518     if (fsm->slave_cat_data) {
       
   519         EC_INFO("FSM freeing old category data on slave %i...\n",
       
   520                 fsm->slave->ring_position);
       
   521         kfree(fsm->slave_cat_data);
       
   522     }
       
   523 
       
   524     if (!(fsm->slave_cat_data = (uint8_t *) kmalloc(EC_CAT_MEM, GFP_ATOMIC))) {
       
   525         EC_ERR("FSM Failed to allocate category data.\n");
       
   526         fsm->slave_state = ec_fsm_slave_finished;
       
   527         return;
       
   528     }
       
   529 
       
   530     // start reading first category header
       
   531     fsm->sii_offset = fsm->slave_cat_offset;
       
   532     fsm->sii_state = ec_fsm_sii_start_reading;
       
   533 
       
   534     fsm->slave_state = ec_fsm_slave_category_header;
       
   535     fsm->slave_state(fsm); // execute state immediately
       
   536 }
       
   537 
       
   538 /*****************************************************************************/
       
   539 
       
   540 /**
       
   541    Slave state: Read categories.
       
   542    Start reading categories.
       
   543 */
       
   544 
       
   545 void ec_fsm_slave_category_header(ec_fsm_t *fsm)
       
   546 {
       
   547     // execute SII state machine
       
   548     fsm->sii_state(fsm);
       
   549 
       
   550     if (fsm->sii_state == ec_fsm_sii_error) {
       
   551         kfree(fsm->slave_cat_data);
       
   552         fsm->slave_cat_data = NULL;
       
   553         fsm->slave_state = ec_fsm_slave_finished;
       
   554         EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n",
       
   555                fsm->slave_cat_offset, fsm->slave->ring_position);
       
   556         return;
       
   557     }
       
   558 
       
   559     if (fsm->sii_state != ec_fsm_sii_finished) return;
       
   560 
       
   561     // last category?
       
   562     if ((fsm->sii_result & 0xFFFF) == 0xFFFF) {
       
   563         kfree(fsm->slave_cat_data);
       
   564         fsm->slave_cat_data = NULL;
       
   565         fsm->slave_state = ec_fsm_slave_finished;
       
   566         return;
       
   567     }
       
   568 
       
   569     fsm->slave_cat_type = fsm->sii_result & 0x7FFF;
       
   570     fsm->slave_cat_words = (fsm->sii_result >> 16) & 0xFFFF;
       
   571 
       
   572     if (fsm->slave_cat_words > EC_CAT_MEM * 2) {
       
   573         EC_ERR("FSM category memory too small! %i words needed.\n",
       
   574                fsm->slave_cat_words);
       
   575         fsm->slave_state = ec_fsm_slave_finished;
       
   576         return;
       
   577     }
       
   578 
       
   579     // start reading category data
       
   580     fsm->slave_cat_data_offset = 0;
       
   581     fsm->sii_offset = (fsm->slave_cat_offset + 2 +
       
   582                        fsm->slave_cat_data_offset);
       
   583     fsm->sii_state = ec_fsm_sii_start_reading;
       
   584     fsm->slave_state = ec_fsm_slave_category_data;
       
   585     fsm->slave_state(fsm); // execute state immediately
       
   586 }
       
   587 
       
   588 /*****************************************************************************/
       
   589 
       
   590 /**
       
   591    Slave state: Category data.
       
   592    Reads category data.
       
   593 */
       
   594 
       
   595 void ec_fsm_slave_category_data(ec_fsm_t *fsm)
       
   596 {
       
   597     // execute SII state machine
       
   598     fsm->sii_state(fsm);
       
   599 
       
   600     if (fsm->sii_state == ec_fsm_sii_error) {
       
   601         kfree(fsm->slave_cat_data);
       
   602         fsm->slave_cat_data = NULL;
       
   603         fsm->slave_state = ec_fsm_slave_finished;
       
   604         EC_ERR("FSM failed to read category 0x%02X data at 0x%04X"
       
   605                " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset,
       
   606                fsm->slave->ring_position);
       
   607         return;
       
   608     }
       
   609 
       
   610     if (fsm->sii_state != ec_fsm_sii_finished) return;
       
   611 
       
   612     fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] =
       
   613         fsm->sii_result & 0xFF;
       
   614     fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] =
       
   615         (fsm->sii_result >> 8) & 0xFF;
       
   616 
       
   617     // read second word "on the fly"
       
   618     if (fsm->slave_cat_data_offset + 1 < fsm->slave_cat_words) {
       
   619         fsm->slave_cat_data_offset++;
       
   620         fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] =
       
   621             (fsm->sii_result >> 16) & 0xFF;
       
   622         fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] =
       
   623             (fsm->sii_result >> 24) & 0xFF;
       
   624     }
       
   625 
       
   626     fsm->slave_cat_data_offset++;
       
   627 
       
   628     if (fsm->slave_cat_data_offset < fsm->slave_cat_words) {
       
   629         fsm->sii_offset = (fsm->slave_cat_offset + 2 +
       
   630                            fsm->slave_cat_data_offset);
       
   631         fsm->sii_state = ec_fsm_sii_start_reading;
       
   632         fsm->slave_state = ec_fsm_slave_category_data;
       
   633         fsm->slave_state(fsm); // execute state immediately
       
   634         return;
       
   635     }
       
   636 
       
   637     // category data complete
       
   638     switch (fsm->slave_cat_type)
       
   639     {
       
   640         case 0x000A:
       
   641             if (ec_slave_fetch_strings(fsm->slave, fsm->slave_cat_data))
       
   642                 goto out_free;
       
   643             break;
       
   644         case 0x001E:
       
   645             if (ec_slave_fetch_general(fsm->slave, fsm->slave_cat_data))
       
   646                 goto out_free;
       
   647             break;
       
   648         case 0x0028:
       
   649             break;
       
   650         case 0x0029:
       
   651             if (ec_slave_fetch_sync(fsm->slave, fsm->slave_cat_data,
       
   652                                     fsm->slave_cat_words))
       
   653                 goto out_free;
       
   654             break;
       
   655         case 0x0032:
       
   656             if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data,
       
   657                                    fsm->slave_cat_words,
       
   658                                    EC_TX_PDO))
       
   659                 goto out_free;
       
   660             break;
       
   661         case 0x0033:
       
   662             if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data,
       
   663                                    fsm->slave_cat_words,
       
   664                                    EC_RX_PDO))
       
   665                 goto out_free;
       
   666             break;
       
   667         default:
       
   668             EC_WARN("FSM: Unknown category type 0x%04X in slave %i.\n",
       
   669                     fsm->slave_cat_type, fsm->slave->ring_position);
       
   670     }
       
   671 
       
   672     // start reading next category header
       
   673     fsm->slave_cat_offset += 2 + fsm->slave_cat_words;
       
   674     fsm->sii_offset = fsm->slave_cat_offset;
       
   675     fsm->sii_state = ec_fsm_sii_start_reading;
       
   676     fsm->slave_state = ec_fsm_slave_category_header;
       
   677     fsm->slave_state(fsm); // execute state immediately
       
   678     return;
       
   679 
       
   680  out_free:
       
   681     kfree(fsm->slave_cat_data);
       
   682     fsm->slave_cat_data = NULL;
       
   683     fsm->slave_state = ec_fsm_slave_finished;
       
   684 }
       
   685 
       
   686 /*****************************************************************************/
       
   687 
       
   688 /**
       
   689    Slave state: Finished.
       
   690    End state of the slave state machine.
       
   691 */
       
   692 
       
   693 void ec_fsm_slave_finished(ec_fsm_t *fsm)
       
   694 {
       
   695 }
       
   696 
       
   697 /******************************************************************************
       
   698  *  SII state machine
       
   699  *****************************************************************************/
       
   700 
       
   701 /**
       
   702    Slave SII state: Start reading.
       
   703    Starts reading the slave information interface.
       
   704 */
       
   705 
       
   706 void ec_fsm_sii_start_reading(ec_fsm_t *fsm)
       
   707 {
       
   708     ec_command_t *command = &fsm->command;
       
   709 
       
   710     // initiate read operation
       
   711     ec_command_npwr(command, fsm->slave->station_address, 0x502, 6);
       
   712     EC_WRITE_U8 (command->data,     0x00); // read-only access
       
   713     EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
       
   714     EC_WRITE_U32(command->data + 2, fsm->sii_offset);
       
   715     ec_master_queue_command(fsm->master, command);
       
   716     fsm->sii_state = ec_fsm_sii_check;
       
   717 }
       
   718 
       
   719 /*****************************************************************************/
       
   720 
       
   721 /**
       
   722    Slave SII state: Check.
       
   723    Checks, if the SII-read-command has been sent and issues a fetch command.
       
   724 */
       
   725 
       
   726 void ec_fsm_sii_check(ec_fsm_t *fsm)
       
   727 {
       
   728     ec_command_t *command = &fsm->command;
       
   729 
       
   730     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   731         EC_ERR("FSM SII: Reception of check command failed.\n");
       
   732         fsm->sii_state = ec_fsm_sii_error;
       
   733         return;
       
   734     }
       
   735 
       
   736     ec_command_nprd(command, fsm->slave->station_address, 0x502, 10);
       
   737     ec_master_queue_command(fsm->master, command);
       
   738     fsm->sii_state = ec_fsm_sii_fetch;
       
   739 }
       
   740 
       
   741 /*****************************************************************************/
       
   742 
       
   743 /**
       
   744    Slave SII state: Fetch.
       
   745    Fetches the result of an SII-read command.
       
   746 */
       
   747 
       
   748 void ec_fsm_sii_fetch(ec_fsm_t *fsm)
       
   749 {
       
   750     ec_command_t *command = &fsm->command;
       
   751 
       
   752     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   753         EC_ERR("FSM SII: Reception of fetch command failed.\n");
       
   754         fsm->sii_state = ec_fsm_sii_error;
       
   755         return;
       
   756     }
       
   757 
       
   758     // check "busy bit"
       
   759     if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
       
   760         fsm->sii_result = EC_READ_U32(command->data + 6);
       
   761         fsm->sii_state = ec_fsm_sii_finished;
       
   762     }
       
   763 }
       
   764 
       
   765 /*****************************************************************************/
       
   766 
       
   767 /**
       
   768    Slave SII state: Finished.
       
   769    End state of the slave SII state machine.
       
   770 */
       
   771 
       
   772 void ec_fsm_sii_finished(ec_fsm_t *fsm)
       
   773 {
       
   774 }
       
   775 
       
   776 /*****************************************************************************/
       
   777 
       
   778 /**
       
   779    Slave SII state: Error.
       
   780    End state of the slave SII state machine.
       
   781 */
       
   782 
       
   783 void ec_fsm_sii_error(ec_fsm_t *fsm)
       
   784 {
       
   785 }
       
   786 
       
   787 /*****************************************************************************/