master/fsm.c
changeset 251 c1d0b63a9302
parent 246 0bf7c769de06
child 254 986afccca9ea
equal deleted inserted replaced
250:440ae5f6d2c3 251:c1d0b63a9302
    46 
    46 
    47 #define EC_CAT_MEM 0x100
    47 #define EC_CAT_MEM 0x100
    48 
    48 
    49 /*****************************************************************************/
    49 /*****************************************************************************/
    50 
    50 
       
    51 const ec_code_msg_t al_status_messages[];
       
    52 
       
    53 /*****************************************************************************/
       
    54 
    51 void ec_fsm_master_start(ec_fsm_t *);
    55 void ec_fsm_master_start(ec_fsm_t *);
    52 void ec_fsm_master_wait(ec_fsm_t *);
    56 void ec_fsm_master_wait(ec_fsm_t *);
    53 void ec_fsm_master_slave(ec_fsm_t *);
    57 void ec_fsm_master_scan(ec_fsm_t *);
    54 void ec_fsm_master_calc(ec_fsm_t *);
    58 void ec_fsm_master_conf(ec_fsm_t *);
    55 void ec_fsm_master_finished(ec_fsm_t *);
    59 
    56 
    60 void ec_fsm_slave_start_reading(ec_fsm_t *);
    57 void ec_fsm_slave_start(ec_fsm_t *);
       
    58 void ec_fsm_slave_read_base(ec_fsm_t *);
    61 void ec_fsm_slave_read_base(ec_fsm_t *);
    59 void ec_fsm_slave_read_dl(ec_fsm_t *);
    62 void ec_fsm_slave_read_dl(ec_fsm_t *);
    60 void ec_fsm_slave_prepare_sii(ec_fsm_t *);
    63 void ec_fsm_slave_prepare_sii(ec_fsm_t *);
    61 void ec_fsm_slave_read_sii(ec_fsm_t *);
    64 void ec_fsm_slave_read_sii(ec_fsm_t *);
    62 void ec_fsm_slave_categories(ec_fsm_t *);
       
    63 void ec_fsm_slave_category_header(ec_fsm_t *);
    65 void ec_fsm_slave_category_header(ec_fsm_t *);
    64 void ec_fsm_slave_category_data(ec_fsm_t *);
    66 void ec_fsm_slave_category_data(ec_fsm_t *);
    65 void ec_fsm_slave_finished(ec_fsm_t *);
    67 void ec_fsm_slave_conf(ec_fsm_t *);
       
    68 void ec_fsm_slave_end(ec_fsm_t *);
       
    69 
       
    70 void ec_fsm_slave_conf(ec_fsm_t *);
       
    71 void ec_fsm_slave_sync(ec_fsm_t *);
       
    72 void ec_fsm_slave_preop(ec_fsm_t *);
       
    73 void ec_fsm_slave_fmmu(ec_fsm_t *);
       
    74 void ec_fsm_slave_saveop(ec_fsm_t *);
       
    75 void ec_fsm_slave_op(ec_fsm_t *);
       
    76 void ec_fsm_slave_op2(ec_fsm_t *);
    66 
    77 
    67 void ec_fsm_sii_start_reading(ec_fsm_t *);
    78 void ec_fsm_sii_start_reading(ec_fsm_t *);
    68 void ec_fsm_sii_check(ec_fsm_t *);
    79 void ec_fsm_sii_check(ec_fsm_t *);
    69 void ec_fsm_sii_fetch(ec_fsm_t *);
    80 void ec_fsm_sii_fetch(ec_fsm_t *);
    70 void ec_fsm_sii_finished(ec_fsm_t *);
    81 void ec_fsm_sii_finished(ec_fsm_t *);
    71 void ec_fsm_sii_error(ec_fsm_t *);
    82 void ec_fsm_sii_error(ec_fsm_t *);
    72 
    83 
       
    84 void ec_fsm_change_start(ec_fsm_t *);
       
    85 void ec_fsm_change_check(ec_fsm_t *);
       
    86 void ec_fsm_change_status(ec_fsm_t *);
       
    87 void ec_fsm_change_code(ec_fsm_t *);
       
    88 void ec_fsm_change_ack(ec_fsm_t *);
       
    89 void ec_fsm_change_ack2(ec_fsm_t *);
       
    90 void ec_fsm_change_end(ec_fsm_t *);
       
    91 void ec_fsm_change_error(ec_fsm_t *);
       
    92 
    73 /*****************************************************************************/
    93 /*****************************************************************************/
    74 
    94 
    75 int ec_fsm_init(ec_fsm_t *fsm, ec_master_t *master)
    95 int ec_fsm_init(ec_fsm_t *fsm, ec_master_t *master)
    76 {
    96 {
    77     fsm->master = master;
    97     fsm->master = master;
   116 void ec_fsm_execute(ec_fsm_t *fsm)
   136 void ec_fsm_execute(ec_fsm_t *fsm)
   117 {
   137 {
   118     fsm->master_state(fsm);
   138     fsm->master_state(fsm);
   119 }
   139 }
   120 
   140 
   121 /*****************************************************************************/
       
   122 
       
   123 int ec_fsm_idle(const ec_fsm_t *fsm)
       
   124 {
       
   125     return (fsm->master_state == ec_fsm_master_start ||
       
   126             fsm->master_state == ec_fsm_master_wait ||
       
   127             fsm->master_state == ec_fsm_master_finished);
       
   128 }
       
   129 
       
   130 /******************************************************************************
   141 /******************************************************************************
   131  *  master state machine
   142  *  master state machine
   132  *****************************************************************************/
   143  *****************************************************************************/
   133 
   144 
   134 /**
   145 /**
   147 /*****************************************************************************/
   158 /*****************************************************************************/
   148 
   159 
   149 void ec_fsm_master_wait(ec_fsm_t *fsm)
   160 void ec_fsm_master_wait(ec_fsm_t *fsm)
   150 {
   161 {
   151     ec_command_t *command = &fsm->command;
   162     ec_command_t *command = &fsm->command;
   152     unsigned int first, topology_change, i;
   163     unsigned int topology_change, i, eoe_slaves_active;
   153     ec_slave_t *slave;
   164     ec_slave_t *slave;
   154 
   165 
   155     if (command->state != EC_CMD_RECEIVED) {
   166     if (command->state != EC_CMD_RECEIVED) {
   156         fsm->master_state = ec_fsm_master_start;
   167         fsm->master_state = ec_fsm_master_start;
   157         fsm->master_state(fsm); // execute immediately
   168         fsm->master_state(fsm); // execute immediately
   158         return;
   169         return;
   159     }
   170     }
   160 
   171 
   161     if (command->working_counter == fsm->master_slaves_responding &&
   172     if (command->working_counter == fsm->master_slaves_responding &&
   162         command->data[0] == fsm->master_slave_states) {
   173         command->data[0] == fsm->master_slave_states)
       
   174     {
       
   175         // check if any slaves are not in the state, they're supposed to be
       
   176         list_for_each_entry(slave, &fsm->master->slaves, list) {
       
   177             if (slave->state_error ||
       
   178                 slave->requested_state == EC_SLAVE_STATE_UNKNOWN ||
       
   179                 slave->current_state == slave->requested_state) continue;
       
   180 
       
   181             EC_INFO("Changing state of slave %i from ", slave->ring_position);
       
   182             ec_print_states(slave->current_state);
       
   183             printk(" to ");
       
   184             ec_print_states(slave->requested_state);
       
   185             printk(".\n");
       
   186 
       
   187             fsm->slave = slave;
       
   188             fsm->slave_state = ec_fsm_slave_conf;
       
   189 
       
   190             fsm->change_new = EC_SLAVE_STATE_INIT;
       
   191             fsm->change_state = ec_fsm_change_start;
       
   192 
       
   193             fsm->master_state = ec_fsm_master_conf;
       
   194             fsm->master_state(fsm); // execute immediately
       
   195             return;
       
   196         }
       
   197 
       
   198         // nothing to configure...
       
   199         eoe_slaves_active = 0;
       
   200         list_for_each_entry(slave, &fsm->master->slaves, list) {
       
   201             if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
       
   202                 eoe_slaves_active++;
       
   203             }
       
   204         }
       
   205 
       
   206         if (eoe_slaves_active && !list_empty(&fsm->master->eoe_handlers))
       
   207             ec_master_eoe_start(fsm->master);
       
   208 
   163         fsm->master_state = ec_fsm_master_start;
   209         fsm->master_state = ec_fsm_master_start;
   164         fsm->master_state(fsm); // execute immediately
   210         fsm->master_state(fsm); // execute immediately
   165         return;
   211         return;
   166     }
   212     }
   167 
   213 
   171     fsm->master_slaves_responding = command->working_counter;
   217     fsm->master_slaves_responding = command->working_counter;
   172     fsm->master_slave_states = command->data[0];
   218     fsm->master_slave_states = command->data[0];
   173 
   219 
   174     EC_INFO("FSM: %i slave%s responding (", fsm->master_slaves_responding,
   220     EC_INFO("FSM: %i slave%s responding (", fsm->master_slaves_responding,
   175             fsm->master_slaves_responding == 1 ? "" : "s");
   221             fsm->master_slaves_responding == 1 ? "" : "s");
   176 
   222     ec_print_states(fsm->master_slave_states);
   177     first = 1;
       
   178     if (fsm->master_slave_states & EC_SLAVE_STATE_INIT) {
       
   179         printk("INIT");
       
   180         first = 0;
       
   181     }
       
   182     if (fsm->master_slave_states & EC_SLAVE_STATE_PREOP) {
       
   183         if (!first) printk(", ");
       
   184         printk("PREOP");
       
   185         first = 0;
       
   186     }
       
   187     if (fsm->master_slave_states & EC_SLAVE_STATE_SAVEOP) {
       
   188         if (!first) printk(", ");
       
   189         printk("SAVEOP");
       
   190         first = 0;
       
   191     }
       
   192     if (fsm->master_slave_states & EC_SLAVE_STATE_OP) {
       
   193         if (!first) printk(", ");
       
   194         printk("OP");
       
   195     }
       
   196     printk(")\n");
   223     printk(")\n");
   197 
   224 
   198     if (!topology_change || fsm->master->mode == EC_MASTER_MODE_RUNNING) {
   225     if (!topology_change || fsm->master->mode == EC_MASTER_MODE_RUNNING) {
   199         fsm->master_state = ec_fsm_master_start;
   226         fsm->master_state = ec_fsm_master_start;
   200         fsm->master_state(fsm); // execute immediately
   227         fsm->master_state(fsm); // execute immediately
   201         return;
   228         return;
   202     }
   229     }
   203 
   230 
   204     // topology change!
   231     EC_INFO("Topology change detected - Scanning bus.\n");
       
   232 
       
   233     ec_master_eoe_stop(fsm->master);
   205     ec_master_clear_slaves(fsm->master);
   234     ec_master_clear_slaves(fsm->master);
   206 
   235 
   207     if (!fsm->master_slaves_responding) {
   236     if (!fsm->master_slaves_responding) {
   208         // no slaves present -> finish state machine.
   237         // no slaves present -> finish state machine.
   209         fsm->master_state = ec_fsm_master_start;
   238         fsm->master_state = ec_fsm_master_start;
   214     // init slaves
   243     // init slaves
   215     for (i = 0; i < fsm->master_slaves_responding; i++) {
   244     for (i = 0; i < fsm->master_slaves_responding; i++) {
   216         if (!(slave =
   245         if (!(slave =
   217               (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_ATOMIC))) {
   246               (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_ATOMIC))) {
   218             EC_ERR("FSM failed to allocate slave %i!\n", i);
   247             EC_ERR("FSM failed to allocate slave %i!\n", i);
   219             fsm->master_state = ec_fsm_master_finished;
   248             fsm->master_state = ec_fsm_master_start;
   220             return;
   249             return;
   221         }
   250         }
   222 
   251 
   223         if (ec_slave_init(slave, fsm->master, i, i + 1)) {
   252         if (ec_slave_init(slave, fsm->master, i, i + 1)) {
   224             fsm->master_state = ec_fsm_master_finished;
   253             fsm->master_state = ec_fsm_master_start;
   225             return;
   254             return;
   226         }
   255         }
   227 
   256 
   228         if (kobject_add(&slave->kobj)) {
   257         if (kobject_add(&slave->kobj)) {
   229             EC_ERR("FSM failed to add kobject.\n");
   258             EC_ERR("FSM failed to add kobject.\n");
   230             kobject_put(&slave->kobj); // free
   259             kobject_put(&slave->kobj); // free
   231             fsm->master_state = ec_fsm_master_finished;
   260             fsm->master_state = ec_fsm_master_start;
   232             return;
   261             return;
   233         }
   262         }
   234 
   263 
   235         list_add_tail(&slave->list, &fsm->master->slaves);
   264         list_add_tail(&slave->list, &fsm->master->slaves);
   236     }
   265     }
   237 
   266 
   238     // begin scanning of slaves
   267     // begin scanning of slaves
   239     fsm->slave = list_entry(fsm->master->slaves.next,
   268     fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list);
   240                             ec_slave_t, list);
   269     fsm->slave_state = ec_fsm_slave_start_reading;
   241     fsm->slave_state = ec_fsm_slave_start;
   270 
   242 
   271     fsm->master_state = ec_fsm_master_scan;
   243     fsm->master_state = ec_fsm_master_slave;
       
   244     fsm->master_state(fsm); // execute immediately
   272     fsm->master_state(fsm); // execute immediately
   245 }
   273 }
   246 
   274 
   247 /*****************************************************************************/
   275 /*****************************************************************************/
   248 
   276 
   249 /**
   277 /**
   250    State: Get Slave.
   278    State: Get Slave.
   251    Executes the sub-statemachine of a slave.
   279    Executes the sub-statemachine of a slave.
   252 */
   280 */
   253 
   281 
   254 void ec_fsm_master_slave(ec_fsm_t *fsm)
   282 void ec_fsm_master_scan(ec_fsm_t *fsm)
   255 {
   283 {
   256     ec_master_t *master = fsm->master;
   284     ec_master_t *master = fsm->master;
       
   285     ec_slave_t *slave = fsm->slave;
   257 
   286 
   258     fsm->slave_state(fsm); // execute slave state machine
   287     fsm->slave_state(fsm); // execute slave state machine
   259 
   288 
   260     if (fsm->slave_state != ec_fsm_slave_finished) return;
   289     if (fsm->slave_state != ec_fsm_slave_end) return;
   261 
   290 
   262     // have all slaves been fetched?
   291     // have all slaves been fetched?
   263     if (fsm->slave->list.next == &master->slaves) {
   292     if (slave->list.next == &master->slaves)
   264         fsm->master_state = ec_fsm_master_calc;
   293     {
       
   294         uint16_t coupler_index, coupler_subindex;
       
   295         uint16_t reverse_coupler_index, current_coupler_index;
       
   296         ec_slave_t *slave;
       
   297         ec_slave_ident_t *ident;
       
   298 
       
   299         EC_INFO("Bus scanning completed.\n");
       
   300 
       
   301         // identify all slaves and calculate coupler addressing
       
   302 
       
   303         coupler_index = 0;
       
   304         reverse_coupler_index = 0xFFFF;
       
   305         current_coupler_index = 0x3FFF;
       
   306         coupler_subindex = 0;
       
   307 
       
   308         list_for_each_entry(slave, &master->slaves, list)
       
   309         {
       
   310             // search for identification in "database"
       
   311             ident = slave_idents;
       
   312             while (ident->type) {
       
   313                 if (ident->vendor_id == slave->sii_vendor_id
       
   314                     && ident->product_code == slave->sii_product_code) {
       
   315                     slave->type = ident->type;
       
   316                     break;
       
   317                 }
       
   318                 ident++;
       
   319             }
       
   320 
       
   321             if (!slave->type) {
       
   322                 EC_WARN("FSM: Unknown slave device (vendor 0x%08X,"
       
   323                         " code 0x%08X) at position %i.\n",
       
   324                         slave->sii_vendor_id, slave->sii_product_code,
       
   325                         slave->ring_position);
       
   326             }
       
   327             else {
       
   328                 // if the slave is a bus coupler, change adressing base
       
   329                 if (slave->type->special == EC_TYPE_BUS_COUPLER) {
       
   330                     if (slave->sii_alias)
       
   331                         current_coupler_index = reverse_coupler_index--;
       
   332                     else
       
   333                         current_coupler_index = coupler_index++;
       
   334                     coupler_subindex = 0;
       
   335                 }
       
   336             }
       
   337 
       
   338             // determine initial state.
       
   339             if ((slave->type && slave->type->special == EC_TYPE_BUS_COUPLER)) {
       
   340                 slave->requested_state = EC_SLAVE_STATE_OP;
       
   341             }
       
   342             else {
       
   343                 if (master->mode == EC_MASTER_MODE_RUNNING)
       
   344                     slave->requested_state = EC_SLAVE_STATE_PREOP;
       
   345                 else
       
   346                     slave->requested_state = EC_SLAVE_STATE_INIT;
       
   347             }
       
   348 
       
   349             // calculate coupler-based slave address
       
   350             slave->coupler_index = current_coupler_index;
       
   351             slave->coupler_subindex = coupler_subindex;
       
   352             coupler_subindex++;
       
   353         }
       
   354 
       
   355         fsm->master_state = ec_fsm_master_start;
   265         fsm->master_state(fsm); // execute immediately
   356         fsm->master_state(fsm); // execute immediately
   266         return;
   357         return;
   267     }
   358     }
   268 
   359 
   269     // process next slave
   360     // process next slave
   270     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   361     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   271     fsm->slave_state = ec_fsm_slave_start;
   362     fsm->slave_state = ec_fsm_slave_start_reading;
   272     fsm->slave_state(fsm); // execute immediately
   363     fsm->slave_state(fsm); // execute immediately
   273 }
   364 }
   274 
   365 
   275 /*****************************************************************************/
   366 /*****************************************************************************/
   276 
   367 
   277 /**
   368 /**
   278    Free-Run state: Calc.
   369    Free-Run state: Configure slaves.
   279 */
   370 */
   280 
   371 
   281 void ec_fsm_master_calc(ec_fsm_t *fsm)
   372 void ec_fsm_master_conf(ec_fsm_t *fsm)
   282 {
   373 {
   283     uint16_t coupler_index, coupler_subindex;
   374     ec_master_t *master = fsm->master;
   284     uint16_t reverse_coupler_index, current_coupler_index;
       
   285     ec_slave_t *slave;
   375     ec_slave_t *slave;
   286     ec_slave_ident_t *ident;
   376 
   287     ec_master_t *master = fsm->master;
   377     fsm->slave_state(fsm); // execute slave's state machine
   288 
   378 
   289     coupler_index = 0;
   379     if (fsm->slave_state != ec_fsm_slave_end) return;
   290     reverse_coupler_index = 0xFFFF;
   380 
   291     current_coupler_index = 0x3FFF;
   381     // check if any slaves are not in the state, they're supposed to be
   292     coupler_subindex = 0;
   382     list_for_each_entry(slave, &master->slaves, list) {
   293 
   383         if (slave->state_error ||
   294     // for every slave on the bus
   384             slave->requested_state == EC_SLAVE_STATE_UNKNOWN ||
   295     list_for_each_entry(slave, &master->slaves, list)
   385             slave->current_state == slave->requested_state) continue;
   296     {
   386 
   297         // search for identification in "database"
   387         EC_INFO("Changing state of slave %i from ", slave->ring_position);
   298         ident = slave_idents;
   388         ec_print_states(slave->current_state);
   299         while (ident->type) {
   389         printk(" to ");
   300             if (unlikely(ident->vendor_id == slave->sii_vendor_id
   390         ec_print_states(slave->requested_state);
   301                          && ident->product_code == slave->sii_product_code)) {
   391         printk(".\n");
   302                 slave->type = ident->type;
   392 
   303                 break;
   393         fsm->slave = slave;
   304             }
   394         fsm->slave_state = ec_fsm_slave_conf;
   305             ident++;
   395 
   306         }
   396         fsm->change_new = EC_SLAVE_STATE_INIT;
   307 
   397         fsm->change_state = ec_fsm_change_start;
   308         if (!slave->type) {
   398 
   309             EC_WARN("FSM: Unknown slave device (vendor 0x%08X, code 0x%08X) at"
   399         fsm->master_state = ec_fsm_master_conf;
   310                     " position %i.\n", slave->sii_vendor_id,
   400         fsm->master_state(fsm); // execute immediately
   311                     slave->sii_product_code, slave->ring_position);
   401         return;
   312         }
       
   313         else if (slave->type->special == EC_TYPE_BUS_COUPLER) {
       
   314             if (slave->sii_alias)
       
   315                 current_coupler_index = reverse_coupler_index--;
       
   316             else
       
   317                 current_coupler_index = coupler_index++;
       
   318             coupler_subindex = 0;
       
   319         }
       
   320 
       
   321         slave->coupler_index = current_coupler_index;
       
   322         slave->coupler_subindex = coupler_subindex;
       
   323         coupler_subindex++;
       
   324     }
   402     }
   325 
   403 
   326     fsm->master_state = ec_fsm_master_start;
   404     fsm->master_state = ec_fsm_master_start;
   327     fsm->master_state(fsm); // execute immediately
   405     fsm->master_state(fsm); // execute immediately
   328 }
       
   329 
       
   330 /*****************************************************************************/
       
   331 
       
   332 /**
       
   333    Free-Run state: Finished.
       
   334    End state of the state machine. Does nothing.
       
   335 */
       
   336 
       
   337 void ec_fsm_master_finished(ec_fsm_t *fsm)
       
   338 {
       
   339 }
   406 }
   340 
   407 
   341 /******************************************************************************
   408 /******************************************************************************
   342  *  slave state machine
   409  *  slave state machine
   343  *****************************************************************************/
   410  *****************************************************************************/
   346    Slave state: Start.
   413    Slave state: Start.
   347    First state of the slave state machine. Writes the station address to the
   414    First state of the slave state machine. Writes the station address to the
   348    slave, according to its ring position.
   415    slave, according to its ring position.
   349 */
   416 */
   350 
   417 
   351 void ec_fsm_slave_start(ec_fsm_t *fsm)
   418 void ec_fsm_slave_start_reading(ec_fsm_t *fsm)
   352 {
   419 {
   353     ec_command_t *command = &fsm->command;
   420     ec_command_t *command = &fsm->command;
   354 
   421 
   355     // write station address
   422     // write station address
   356     ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
   423     ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
   370     ec_command_t *command = &fsm->command;
   437     ec_command_t *command = &fsm->command;
   371 
   438 
   372     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   439     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   373         EC_ERR("FSM failed to write station address of slave %i.\n",
   440         EC_ERR("FSM failed to write station address of slave %i.\n",
   374                fsm->slave->ring_position);
   441                fsm->slave->ring_position);
   375         fsm->slave_state = ec_fsm_slave_finished;
   442         fsm->slave_state = ec_fsm_slave_end;
   376         return;
   443         return;
   377     }
   444     }
   378 
   445 
   379     // read base data
   446     // read base data
   380     ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6);
   447     ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6);
   394     ec_slave_t *slave = fsm->slave;
   461     ec_slave_t *slave = fsm->slave;
   395 
   462 
   396     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   463     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   397         EC_ERR("FSM failed to read base data of slave %i.\n",
   464         EC_ERR("FSM failed to read base data of slave %i.\n",
   398                slave->ring_position);
   465                slave->ring_position);
   399         fsm->slave_state = ec_fsm_slave_finished;
   466         fsm->slave_state = ec_fsm_slave_end;
   400         return;
   467         return;
   401     }
   468     }
   402 
   469 
   403     slave->base_type       = EC_READ_U8 (command->data);
   470     slave->base_type       = EC_READ_U8 (command->data);
   404     slave->base_revision   = EC_READ_U8 (command->data + 1);
   471     slave->base_revision   = EC_READ_U8 (command->data + 1);
   429     unsigned int i;
   496     unsigned int i;
   430 
   497 
   431     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   498     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   432         EC_ERR("FSM failed to read DL status of slave %i.\n",
   499         EC_ERR("FSM failed to read DL status of slave %i.\n",
   433                slave->ring_position);
   500                slave->ring_position);
   434         fsm->slave_state = ec_fsm_slave_finished;
   501         fsm->slave_state = ec_fsm_slave_end;
   435         return;
   502         return;
   436     }
   503     }
   437 
   504 
   438     dl_status = EC_READ_U16(command->data);
   505     dl_status = EC_READ_U16(command->data);
   439 
   506 
   462 
   529 
   463     // execute SII state machine
   530     // execute SII state machine
   464     fsm->sii_state(fsm);
   531     fsm->sii_state(fsm);
   465 
   532 
   466     if (fsm->sii_state == ec_fsm_sii_error) {
   533     if (fsm->sii_state == ec_fsm_sii_error) {
   467         fsm->slave_state = ec_fsm_slave_finished;
   534         fsm->slave_state = ec_fsm_slave_end;
   468         EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n",
   535         EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n",
   469                fsm->sii_offset, slave->ring_position);
   536                fsm->sii_offset, slave->ring_position);
   470         return;
   537         return;
   471     }
   538     }
   472 
   539 
   503             slave->sii_tx_mailbox_size = fsm->sii_result >> 16;
   570             slave->sii_tx_mailbox_size = fsm->sii_result >> 16;
   504             fsm->sii_offset = 0x001C;
   571             fsm->sii_offset = 0x001C;
   505             break;
   572             break;
   506         case 7:
   573         case 7:
   507             slave->sii_mailbox_protocols = fsm->sii_result & 0xFFFF;
   574             slave->sii_mailbox_protocols = fsm->sii_result & 0xFFFF;
   508             fsm->slave_state = ec_fsm_slave_categories;
   575 
       
   576             fsm->slave_cat_offset = 0x0040;
       
   577 
       
   578             if (fsm->slave_cat_data) {
       
   579                 EC_INFO("FSM freeing old category data on slave %i...\n",
       
   580                         fsm->slave->ring_position);
       
   581                 kfree(fsm->slave_cat_data);
       
   582             }
       
   583 
       
   584             if (!(fsm->slave_cat_data =
       
   585                   (uint8_t *) kmalloc(EC_CAT_MEM, GFP_ATOMIC))) {
       
   586                 EC_ERR("FSM Failed to allocate category data.\n");
       
   587                 fsm->slave_state = ec_fsm_slave_end;
       
   588                 return;
       
   589             }
       
   590 
       
   591             // start reading first category header
       
   592             fsm->sii_offset = fsm->slave_cat_offset;
       
   593             fsm->sii_state = ec_fsm_sii_start_reading;
       
   594 
       
   595             fsm->slave_state = ec_fsm_slave_category_header;
   509             fsm->slave_state(fsm); // execute state immediately
   596             fsm->slave_state(fsm); // execute state immediately
   510             return;
   597             return;
   511     }
   598     }
   512 
   599 
   513     fsm->slave_sii_num++;
   600     fsm->slave_sii_num++;
   516 }
   603 }
   517 
   604 
   518 /*****************************************************************************/
   605 /*****************************************************************************/
   519 
   606 
   520 /**
   607 /**
   521    Slave state: Categories.
       
   522 */
       
   523 
       
   524 void ec_fsm_slave_categories(ec_fsm_t *fsm)
       
   525 {
       
   526     fsm->slave_cat_offset = 0x0040;
       
   527 
       
   528     if (fsm->slave_cat_data) {
       
   529         EC_INFO("FSM freeing old category data on slave %i...\n",
       
   530                 fsm->slave->ring_position);
       
   531         kfree(fsm->slave_cat_data);
       
   532     }
       
   533 
       
   534     if (!(fsm->slave_cat_data = (uint8_t *) kmalloc(EC_CAT_MEM, GFP_ATOMIC))) {
       
   535         EC_ERR("FSM Failed to allocate category data.\n");
       
   536         fsm->slave_state = ec_fsm_slave_finished;
       
   537         return;
       
   538     }
       
   539 
       
   540     // start reading first category header
       
   541     fsm->sii_offset = fsm->slave_cat_offset;
       
   542     fsm->sii_state = ec_fsm_sii_start_reading;
       
   543 
       
   544     fsm->slave_state = ec_fsm_slave_category_header;
       
   545     fsm->slave_state(fsm); // execute state immediately
       
   546 }
       
   547 
       
   548 /*****************************************************************************/
       
   549 
       
   550 /**
       
   551    Slave state: Read categories.
   608    Slave state: Read categories.
   552    Start reading categories.
   609    Start reading categories.
   553 */
   610 */
   554 
   611 
   555 void ec_fsm_slave_category_header(ec_fsm_t *fsm)
   612 void ec_fsm_slave_category_header(ec_fsm_t *fsm)
   558     fsm->sii_state(fsm);
   615     fsm->sii_state(fsm);
   559 
   616 
   560     if (fsm->sii_state == ec_fsm_sii_error) {
   617     if (fsm->sii_state == ec_fsm_sii_error) {
   561         kfree(fsm->slave_cat_data);
   618         kfree(fsm->slave_cat_data);
   562         fsm->slave_cat_data = NULL;
   619         fsm->slave_cat_data = NULL;
   563         fsm->slave_state = ec_fsm_slave_finished;
   620         fsm->slave_state = ec_fsm_slave_end;
   564         EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n",
   621         EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n",
   565                fsm->slave_cat_offset, fsm->slave->ring_position);
   622                fsm->slave_cat_offset, fsm->slave->ring_position);
   566         return;
   623         return;
   567     }
   624     }
   568 
   625 
   570 
   627 
   571     // last category?
   628     // last category?
   572     if ((fsm->sii_result & 0xFFFF) == 0xFFFF) {
   629     if ((fsm->sii_result & 0xFFFF) == 0xFFFF) {
   573         kfree(fsm->slave_cat_data);
   630         kfree(fsm->slave_cat_data);
   574         fsm->slave_cat_data = NULL;
   631         fsm->slave_cat_data = NULL;
   575         fsm->slave_state = ec_fsm_slave_finished;
   632         fsm->slave_state = ec_fsm_slave_end;
   576         return;
   633         return;
   577     }
   634     }
   578 
   635 
   579     fsm->slave_cat_type = fsm->sii_result & 0x7FFF;
   636     fsm->slave_cat_type = fsm->sii_result & 0x7FFF;
   580     fsm->slave_cat_words = (fsm->sii_result >> 16) & 0xFFFF;
   637     fsm->slave_cat_words = (fsm->sii_result >> 16) & 0xFFFF;
   581 
   638 
   582     if (fsm->slave_cat_words > EC_CAT_MEM * 2) {
   639     if (fsm->slave_cat_words > EC_CAT_MEM * 2) {
   583         EC_ERR("FSM category memory too small! %i words needed.\n",
   640         EC_ERR("FSM category memory too small! %i words needed.\n",
   584                fsm->slave_cat_words);
   641                fsm->slave_cat_words);
   585         fsm->slave_state = ec_fsm_slave_finished;
   642         fsm->slave_state = ec_fsm_slave_end;
   586         return;
   643         return;
   587     }
   644     }
   588 
   645 
   589     // start reading category data
   646     // start reading category data
   590     fsm->slave_cat_data_offset = 0;
   647     fsm->slave_cat_data_offset = 0;
   608     fsm->sii_state(fsm);
   665     fsm->sii_state(fsm);
   609 
   666 
   610     if (fsm->sii_state == ec_fsm_sii_error) {
   667     if (fsm->sii_state == ec_fsm_sii_error) {
   611         kfree(fsm->slave_cat_data);
   668         kfree(fsm->slave_cat_data);
   612         fsm->slave_cat_data = NULL;
   669         fsm->slave_cat_data = NULL;
   613         fsm->slave_state = ec_fsm_slave_finished;
   670         fsm->slave_state = ec_fsm_slave_end;
   614         EC_ERR("FSM failed to read category 0x%02X data at 0x%04X"
   671         EC_ERR("FSM failed to read category 0x%02X data at 0x%04X"
   615                " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset,
   672                " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset,
   616                fsm->slave->ring_position);
   673                fsm->slave->ring_position);
   617         return;
   674         return;
   618     }
   675     }
   688     return;
   745     return;
   689 
   746 
   690  out_free:
   747  out_free:
   691     kfree(fsm->slave_cat_data);
   748     kfree(fsm->slave_cat_data);
   692     fsm->slave_cat_data = NULL;
   749     fsm->slave_cat_data = NULL;
   693     fsm->slave_state = ec_fsm_slave_finished;
   750     fsm->slave_state = ec_fsm_slave_end;
   694 }
   751 }
   695 
   752 
   696 /*****************************************************************************/
   753 /*****************************************************************************/
   697 
   754 
   698 /**
   755 /**
   699    Slave state: Finished.
   756    Slave state: Start configuring.
       
   757 */
       
   758 
       
   759 void ec_fsm_slave_conf(ec_fsm_t *fsm)
       
   760 {
       
   761     ec_slave_t *slave = fsm->slave;
       
   762     ec_master_t *master = fsm->master;
       
   763     ec_command_t *command = &fsm->command;
       
   764 
       
   765     fsm->change_state(fsm); // execute state change state machine
       
   766 
       
   767     if (fsm->change_state == ec_fsm_change_error) {
       
   768         fsm->slave_state = ec_fsm_slave_end;
       
   769         return;
       
   770     }
       
   771 
       
   772     if (fsm->change_state != ec_fsm_change_end) return;
       
   773 
       
   774     // slave is now in INIT
       
   775     if (slave->current_state == slave->requested_state) {
       
   776         fsm->slave_state = ec_fsm_slave_end;
       
   777         return;
       
   778     }
       
   779 
       
   780     // check for slave registration
       
   781     if (!slave->type) {
       
   782         EC_WARN("Slave %i has unknown type!\n", slave->ring_position);
       
   783     }
       
   784 
       
   785     // check and reset CRC fault counters
       
   786     //ec_slave_check_crc(slave);
       
   787 
       
   788     if (!slave->base_fmmu_count) { // no fmmus
       
   789         fsm->slave_state = ec_fsm_slave_sync;
       
   790         fsm->slave_state(fsm); // execute immediately
       
   791         return;
       
   792     }
       
   793 
       
   794     // reset FMMUs
       
   795     ec_command_npwr(command, slave->station_address, 0x0600,
       
   796                     EC_FMMU_SIZE * slave->base_fmmu_count);
       
   797     memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
       
   798     ec_master_queue_command(master, command);
       
   799     fsm->slave_state = ec_fsm_slave_sync;
       
   800 }
       
   801 
       
   802 /*****************************************************************************/
       
   803 
       
   804 /**
       
   805    Slave state: Configure sync managers.
       
   806 */
       
   807 
       
   808 void ec_fsm_slave_sync(ec_fsm_t *fsm)
       
   809 {
       
   810     ec_command_t *command = &fsm->command;
       
   811     ec_slave_t *slave = fsm->slave;
       
   812     unsigned int j;
       
   813     const ec_sync_t *sync;
       
   814     ec_eeprom_sync_t *eeprom_sync, mbox_sync;
       
   815 
       
   816     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   817         EC_ERR("FSM failed to reset FMMUs of slave %i.\n",
       
   818                slave->ring_position);
       
   819         fsm->slave_state = ec_fsm_slave_end;
       
   820         return;
       
   821     }
       
   822 
       
   823     if (!slave->base_sync_count) { // no sync managers
       
   824         fsm->slave_state = ec_fsm_slave_preop;
       
   825         fsm->slave_state(fsm); // execute immediately
       
   826         return;
       
   827     }
       
   828 
       
   829     // configure sync managers
       
   830     ec_command_npwr(command, slave->station_address, 0x0800,
       
   831                     EC_SYNC_SIZE * slave->base_sync_count);
       
   832     memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
       
   833 
       
   834     // known slave type, take type's SM information
       
   835     if (slave->type) {
       
   836         for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
       
   837             sync = slave->type->sync_managers[j];
       
   838             ec_sync_config(sync, command->data + EC_SYNC_SIZE * j);
       
   839         }
       
   840     }
       
   841 
       
   842     // unknown type, but slave has mailbox
       
   843     else if (slave->sii_mailbox_protocols)
       
   844     {
       
   845         // does it supply sync manager configurations in its EEPROM?
       
   846         if (!list_empty(&slave->eeprom_syncs)) {
       
   847             list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
       
   848                 if (eeprom_sync->index >= slave->base_sync_count) {
       
   849                     EC_ERR("Invalid sync manager configuration found!");
       
   850                     fsm->slave_state = ec_fsm_slave_end;
       
   851                     return;
       
   852                 }
       
   853                 ec_eeprom_sync_config(eeprom_sync,
       
   854                                       command->data + EC_SYNC_SIZE
       
   855                                       * eeprom_sync->index);
       
   856             }
       
   857         }
       
   858 
       
   859         // no sync manager information; guess mailbox settings
       
   860         else {
       
   861             mbox_sync.physical_start_address =
       
   862                 slave->sii_rx_mailbox_offset;
       
   863             mbox_sync.length = slave->sii_rx_mailbox_size;
       
   864             mbox_sync.control_register = 0x26;
       
   865             mbox_sync.enable = 1;
       
   866             ec_eeprom_sync_config(&mbox_sync, command->data);
       
   867 
       
   868             mbox_sync.physical_start_address =
       
   869                 slave->sii_tx_mailbox_offset;
       
   870             mbox_sync.length = slave->sii_tx_mailbox_size;
       
   871             mbox_sync.control_register = 0x22;
       
   872             mbox_sync.enable = 1;
       
   873             ec_eeprom_sync_config(&mbox_sync,
       
   874                                   command->data + EC_SYNC_SIZE);
       
   875         }
       
   876 
       
   877         EC_INFO("Mailbox configured for unknown slave %i\n",
       
   878                 slave->ring_position);
       
   879     }
       
   880 
       
   881     ec_master_queue_command(fsm->master, command);
       
   882     fsm->slave_state = ec_fsm_slave_preop;
       
   883 }
       
   884 
       
   885 /*****************************************************************************/
       
   886 
       
   887 /**
       
   888    Slave state: Change slave state to PREOP.
       
   889 */
       
   890 
       
   891 void ec_fsm_slave_preop(ec_fsm_t *fsm)
       
   892 {
       
   893     ec_command_t *command = &fsm->command;
       
   894     ec_slave_t *slave = fsm->slave;
       
   895 
       
   896     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
   897         EC_ERR("FSM failed to set sync managers on slave %i.\n",
       
   898                slave->ring_position);
       
   899         fsm->slave_state = ec_fsm_slave_end;
       
   900         return;
       
   901     }
       
   902 
       
   903     fsm->change_new = EC_SLAVE_STATE_PREOP;
       
   904     fsm->change_state = ec_fsm_change_start;
       
   905 
       
   906     fsm->slave_state = ec_fsm_slave_fmmu;
       
   907 
       
   908     fsm->change_state(fsm); // execute immediately
       
   909 }
       
   910 
       
   911 /*****************************************************************************/
       
   912 
       
   913 /**
       
   914    Slave state: Configure FMMUs.
       
   915 */
       
   916 
       
   917 void ec_fsm_slave_fmmu(ec_fsm_t *fsm)
       
   918 {
       
   919     ec_slave_t *slave = fsm->slave;
       
   920     ec_master_t *master = fsm->master;
       
   921     ec_command_t *command = &fsm->command;
       
   922     unsigned int j;
       
   923 
       
   924     fsm->change_state(fsm); // execute state change state machine
       
   925 
       
   926     if (fsm->change_state == ec_fsm_change_error) {
       
   927         fsm->slave_state = ec_fsm_slave_end;
       
   928         return;
       
   929     }
       
   930 
       
   931     if (fsm->change_state != ec_fsm_change_end) return;
       
   932 
       
   933     // slave is now in PREOP
       
   934     if (slave->current_state == slave->requested_state) {
       
   935         fsm->slave_state = ec_fsm_slave_end;
       
   936         return;
       
   937     }
       
   938 
       
   939     // stop activation here for slaves without type
       
   940     if (!slave->type) {
       
   941         fsm->slave_state = ec_fsm_slave_end;
       
   942         return;
       
   943     }
       
   944 
       
   945 #if 0
       
   946     // slaves that are not registered are only brought into PREOP
       
   947     // state -> nice blinking and mailbox communication possible
       
   948     if (!slave->registered && !slave->type->special) {
       
   949         EC_WARN("Slave %i was not registered!\n", slave->ring_position);
       
   950         fsm->slave_state = ec_fsm_slave_end;
       
   951         return;
       
   952     }
       
   953 #endif
       
   954 
       
   955     if (!slave->base_fmmu_count) {
       
   956         fsm->slave_state = ec_fsm_slave_saveop;
       
   957         fsm->slave_state(fsm); // execute immediately
       
   958         return;
       
   959     }
       
   960 
       
   961     // configure FMMUs
       
   962     ec_command_npwr(command, slave->station_address,
       
   963                     0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
       
   964     memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
       
   965     for (j = 0; j < slave->fmmu_count; j++) {
       
   966         ec_fmmu_config(&slave->fmmus[j], command->data + EC_FMMU_SIZE * j);
       
   967     }
       
   968 
       
   969     ec_master_queue_command(master, command);
       
   970     fsm->slave_state = ec_fsm_slave_saveop;
       
   971 }
       
   972 
       
   973 /*****************************************************************************/
       
   974 
       
   975 /**
       
   976    Slave state: Set slave state to SAVEOP.
       
   977 */
       
   978 
       
   979 void ec_fsm_slave_saveop(ec_fsm_t *fsm)
       
   980 {
       
   981     ec_command_t *command = &fsm->command;
       
   982 
       
   983     if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED ||
       
   984                                         command->working_counter != 1)) {
       
   985         EC_ERR("FSM failed to set FMMUs on slave %i.\n",
       
   986                fsm->slave->ring_position);
       
   987         fsm->slave_state = ec_fsm_slave_end;
       
   988         return;
       
   989     }
       
   990 
       
   991     // set state to SAVEOP
       
   992     fsm->slave_state = ec_fsm_slave_op;
       
   993     fsm->change_new = EC_SLAVE_STATE_SAVEOP;
       
   994     fsm->change_state = ec_fsm_change_start;
       
   995     fsm->change_state(fsm); // execute immediately
       
   996 }
       
   997 
       
   998 /*****************************************************************************/
       
   999 
       
  1000 /**
       
  1001    Slave state: Set slave state to OP.
       
  1002 */
       
  1003 
       
  1004 void ec_fsm_slave_op(ec_fsm_t *fsm)
       
  1005 {
       
  1006     fsm->change_state(fsm); // execute state change state machine
       
  1007 
       
  1008     if (fsm->change_state == ec_fsm_change_error) {
       
  1009         fsm->slave_state = ec_fsm_slave_end;
       
  1010         return;
       
  1011     }
       
  1012 
       
  1013     if (fsm->change_state != ec_fsm_change_end) return;
       
  1014 
       
  1015     // slave is now in SAVEOP
       
  1016     if (fsm->slave->current_state == fsm->slave->requested_state) {
       
  1017         fsm->slave_state = ec_fsm_slave_end;
       
  1018         return;
       
  1019     }
       
  1020 
       
  1021     // set state to OP
       
  1022     fsm->slave_state = ec_fsm_slave_op2;
       
  1023     fsm->change_new = EC_SLAVE_STATE_OP;
       
  1024     fsm->change_state = ec_fsm_change_start;
       
  1025     fsm->change_state(fsm); // execute immediately
       
  1026 }
       
  1027 
       
  1028 /*****************************************************************************/
       
  1029 
       
  1030 /**
       
  1031    Slave state: Set slave state to OP.
       
  1032 */
       
  1033 
       
  1034 void ec_fsm_slave_op2(ec_fsm_t *fsm)
       
  1035 {
       
  1036     fsm->change_state(fsm); // execute state change state machine
       
  1037 
       
  1038     if (fsm->change_state == ec_fsm_change_error) {
       
  1039         fsm->slave_state = ec_fsm_slave_end;
       
  1040         return;
       
  1041     }
       
  1042 
       
  1043     if (fsm->change_state != ec_fsm_change_end) return;
       
  1044 
       
  1045     // slave is now in OP
       
  1046     fsm->slave_state = ec_fsm_slave_end;
       
  1047 }
       
  1048 
       
  1049 /*****************************************************************************/
       
  1050 
       
  1051 /**
       
  1052    Slave state: End.
   700    End state of the slave state machine.
  1053    End state of the slave state machine.
   701 */
  1054 */
   702 
  1055 
   703 void ec_fsm_slave_finished(ec_fsm_t *fsm)
  1056 void ec_fsm_slave_end(ec_fsm_t *fsm)
   704 {
  1057 {
   705 }
  1058 }
   706 
  1059 
   707 /******************************************************************************
  1060 /******************************************************************************
   708  *  SII state machine
  1061  *  SII state machine
   792 
  1145 
   793 void ec_fsm_sii_error(ec_fsm_t *fsm)
  1146 void ec_fsm_sii_error(ec_fsm_t *fsm)
   794 {
  1147 {
   795 }
  1148 }
   796 
  1149 
   797 /*****************************************************************************/
  1150 /******************************************************************************
       
  1151  *  state change state machine
       
  1152  *****************************************************************************/
       
  1153 
       
  1154 /**
       
  1155    State change state: Start.
       
  1156 */
       
  1157 
       
  1158 void ec_fsm_change_start(ec_fsm_t *fsm)
       
  1159 {
       
  1160     ec_command_t *command = &fsm->command;
       
  1161     ec_slave_t *slave = fsm->slave;
       
  1162 
       
  1163     // write new state to slave
       
  1164     ec_command_npwr(command, slave->station_address, 0x0120, 2);
       
  1165     EC_WRITE_U16(command->data, fsm->change_new);
       
  1166     ec_master_queue_command(fsm->master, command);
       
  1167     fsm->change_state = ec_fsm_change_check;
       
  1168 }
       
  1169 
       
  1170 /*****************************************************************************/
       
  1171 
       
  1172 /**
       
  1173    State change state: Check.
       
  1174 */
       
  1175 
       
  1176 void ec_fsm_change_check(ec_fsm_t *fsm)
       
  1177 {
       
  1178     ec_command_t *command = &fsm->command;
       
  1179     ec_slave_t *slave = fsm->slave;
       
  1180 
       
  1181     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
  1182         EC_ERR("FSM: Reception of state command failed.\n");
       
  1183         slave->state_error = 1;
       
  1184         fsm->change_state = ec_fsm_change_error;
       
  1185         return;
       
  1186     }
       
  1187 
       
  1188     //start = get_cycles();
       
  1189     //timeout = (cycles_t) 10 * cpu_khz; // 10ms
       
  1190 
       
  1191     // read AL status from slave
       
  1192     ec_command_nprd(command, slave->station_address, 0x0130, 2);
       
  1193     ec_master_queue_command(fsm->master, command);
       
  1194     fsm->change_state = ec_fsm_change_status;
       
  1195 }
       
  1196 
       
  1197 /*****************************************************************************/
       
  1198 
       
  1199 /**
       
  1200    State change state: Status.
       
  1201 */
       
  1202 
       
  1203 void ec_fsm_change_status(ec_fsm_t *fsm)
       
  1204 {
       
  1205     ec_command_t *command = &fsm->command;
       
  1206     ec_slave_t *slave = fsm->slave;
       
  1207 
       
  1208     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
  1209         EC_ERR("FSM: Reception of state check command failed.\n");
       
  1210         slave->state_error = 1;
       
  1211         fsm->change_state = ec_fsm_change_error;
       
  1212         return;
       
  1213     }
       
  1214 
       
  1215     slave->current_state = EC_READ_U8(command->data);
       
  1216 
       
  1217     if (slave->current_state & 0x10) { // state change error
       
  1218         EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
       
  1219                " (code 0x%02X)!\n", fsm->change_new, slave->ring_position,
       
  1220                slave->current_state);
       
  1221 
       
  1222         fsm->change_new = slave->current_state & 0x0F;
       
  1223 
       
  1224         // fetch AL status error code
       
  1225         ec_command_nprd(command, slave->station_address, 0x0134, 2);
       
  1226         ec_master_queue_command(fsm->master, command);
       
  1227         fsm->change_state = ec_fsm_change_code;
       
  1228         return;
       
  1229     }
       
  1230 
       
  1231     if (slave->current_state == fsm->change_new) {
       
  1232         fsm->change_state = ec_fsm_change_end;
       
  1233         return;
       
  1234     }
       
  1235 
       
  1236     EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n",
       
  1237            fsm->change_new, slave->ring_position);
       
  1238     slave->state_error = 1;
       
  1239     fsm->change_state = ec_fsm_change_error;
       
  1240 }
       
  1241 
       
  1242 /*****************************************************************************/
       
  1243 
       
  1244 /**
       
  1245    State change state: Code.
       
  1246 */
       
  1247 
       
  1248 void ec_fsm_change_code(ec_fsm_t *fsm)
       
  1249 {
       
  1250     ec_command_t *command = &fsm->command;
       
  1251     ec_slave_t *slave = fsm->slave;
       
  1252     uint32_t code;
       
  1253     const ec_code_msg_t *al_msg;
       
  1254 
       
  1255     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
  1256         EC_ERR("FSM: Reception of AL status code command failed.\n");
       
  1257         slave->state_error = 1;
       
  1258         fsm->change_state = ec_fsm_change_error;
       
  1259         return;
       
  1260     }
       
  1261 
       
  1262     if ((code = EC_READ_U16(command->data))) {
       
  1263         for (al_msg = al_status_messages; al_msg->code; al_msg++) {
       
  1264             if (al_msg->code != code) continue;
       
  1265             EC_ERR("AL status message 0x%04X: \"%s\".\n",
       
  1266                    al_msg->code, al_msg->message);
       
  1267             break;
       
  1268         }
       
  1269         if (!al_msg->code)
       
  1270             EC_ERR("Unknown AL status code 0x%04X.\n", code);
       
  1271     }
       
  1272 
       
  1273     // acknowledge "old" slave state
       
  1274     ec_command_npwr(command, slave->station_address, 0x0120, 2);
       
  1275     EC_WRITE_U16(command->data, slave->current_state);
       
  1276     ec_master_queue_command(fsm->master, command);
       
  1277     fsm->change_state = ec_fsm_change_ack;
       
  1278 }
       
  1279 
       
  1280 /*****************************************************************************/
       
  1281 
       
  1282 /**
       
  1283    State change state: Acknowledge.
       
  1284 */
       
  1285 
       
  1286 void ec_fsm_change_ack(ec_fsm_t *fsm)
       
  1287 {
       
  1288     ec_command_t *command = &fsm->command;
       
  1289     ec_slave_t *slave = fsm->slave;
       
  1290 
       
  1291     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
  1292         EC_ERR("FSM: Reception of state ack command failed.\n");
       
  1293         slave->state_error = 1;
       
  1294         fsm->change_state = ec_fsm_change_error;
       
  1295         return;
       
  1296     }
       
  1297 
       
  1298     // read new AL status
       
  1299     ec_command_nprd(command, slave->station_address, 0x0130, 2);
       
  1300     ec_master_queue_command(fsm->master, command);
       
  1301     fsm->change_state = ec_fsm_change_ack2;
       
  1302 }
       
  1303 
       
  1304 /*****************************************************************************/
       
  1305 
       
  1306 /**
       
  1307    State change state: Acknowledge 2.
       
  1308 */
       
  1309 
       
  1310 void ec_fsm_change_ack2(ec_fsm_t *fsm)
       
  1311 {
       
  1312     ec_command_t *command = &fsm->command;
       
  1313     ec_slave_t *slave = fsm->slave;
       
  1314 
       
  1315     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
       
  1316         EC_ERR("FSM: Reception of state ack check command failed.\n");
       
  1317         slave->state_error = 1;
       
  1318         fsm->change_state = ec_fsm_change_error;
       
  1319         return;
       
  1320     }
       
  1321 
       
  1322     slave->current_state = EC_READ_U8(command->data);
       
  1323 
       
  1324     if (slave->current_state == fsm->change_new) {
       
  1325         EC_INFO("Acknowleged state 0x%02X on slave %i.\n",
       
  1326                 slave->current_state, slave->ring_position);
       
  1327         slave->state_error = 1;
       
  1328         fsm->change_state = ec_fsm_change_error;
       
  1329         return;
       
  1330     }
       
  1331 
       
  1332     EC_WARN("Failed to acknowledge state 0x%02X on slave %i"
       
  1333             " - Timeout!\n", fsm->change_new, slave->ring_position);
       
  1334     slave->state_error = 1;
       
  1335     fsm->change_state = ec_fsm_change_error;
       
  1336 }
       
  1337 
       
  1338 /*****************************************************************************/
       
  1339 
       
  1340 /**
       
  1341    State change state: End.
       
  1342 */
       
  1343 
       
  1344 void ec_fsm_change_end(ec_fsm_t *fsm)
       
  1345 {
       
  1346 }
       
  1347 
       
  1348 /*****************************************************************************/
       
  1349 
       
  1350 /**
       
  1351    State change state: Error.
       
  1352 */
       
  1353 
       
  1354 void ec_fsm_change_error(ec_fsm_t *fsm)
       
  1355 {
       
  1356 }
       
  1357 
       
  1358 /*****************************************************************************/
       
  1359 
       
  1360 /**
       
  1361    Application layer status messages.
       
  1362 */
       
  1363 
       
  1364 const ec_code_msg_t al_status_messages[] = {
       
  1365     {0x0001, "Unspecified error"},
       
  1366     {0x0011, "Invalud requested state change"},
       
  1367     {0x0012, "Unknown requested state"},
       
  1368     {0x0013, "Bootstrap not supported"},
       
  1369     {0x0014, "No valid firmware"},
       
  1370     {0x0015, "Invalid mailbox configuration"},
       
  1371     {0x0016, "Invalid mailbox configuration"},
       
  1372     {0x0017, "Invalid sync manager configuration"},
       
  1373     {0x0018, "No valid inputs available"},
       
  1374     {0x0019, "No valid outputs"},
       
  1375     {0x001A, "Synchronisation error"},
       
  1376     {0x001B, "Sync manager watchdog"},
       
  1377     {0x0020, "Slave needs cold start"},
       
  1378     {0x0021, "Slave needs INIT"},
       
  1379     {0x0022, "Slave needs PREOP"},
       
  1380     {0x0023, "Slave needs SAVEOP"},
       
  1381     {}
       
  1382 };
       
  1383 
       
  1384 /*****************************************************************************/