master/fsm_slave.c
branchstable-1.5
changeset 2498 9cdd7669dc0b
parent 2467 74ede087bc85
child 2522 ec403cf308eb
equal deleted inserted replaced
2497:505cf41488a4 2498:9cdd7669dc0b
    40 
    40 
    41 #include "fsm_slave.h"
    41 #include "fsm_slave.h"
    42 
    42 
    43 /*****************************************************************************/
    43 /*****************************************************************************/
    44 
    44 
    45 void ec_fsm_slave_state_idle(ec_fsm_slave_t *);
    45 void ec_fsm_slave_state_idle(ec_fsm_slave_t *, ec_datagram_t *);
    46 void ec_fsm_slave_state_ready(ec_fsm_slave_t *);
    46 void ec_fsm_slave_state_ready(ec_fsm_slave_t *, ec_datagram_t *);
    47 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *);
    47 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *, ec_datagram_t *);
    48 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *);
    48 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *, ec_datagram_t *);
    49 int ec_fsm_slave_action_process_reg(ec_fsm_slave_t *);
    49 int ec_fsm_slave_action_process_reg(ec_fsm_slave_t *, ec_datagram_t *);
    50 void ec_fsm_slave_state_reg_request(ec_fsm_slave_t *);
    50 void ec_fsm_slave_state_reg_request(ec_fsm_slave_t *, ec_datagram_t *);
    51 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *);
    51 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *, ec_datagram_t *);
    52 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *);
    52 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *, ec_datagram_t *);
    53 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *);
    53 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *, ec_datagram_t *);
    54 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *);
    54 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *, ec_datagram_t *);
    55 
    55 
    56 /*****************************************************************************/
    56 /*****************************************************************************/
    57 
    57 
    58 /** Constructor.
    58 /** Constructor.
    59  */
    59  */
    60 void ec_fsm_slave_init(
    60 void ec_fsm_slave_init(
    61         ec_fsm_slave_t *fsm, /**< Slave state machine. */
    61         ec_fsm_slave_t *fsm, /**< Slave state machine. */
    62         ec_slave_t *slave, /**< EtherCAT slave. */
    62         ec_slave_t *slave /**< EtherCAT slave. */
    63         ec_datagram_t *datagram /**< Datagram object to use. */
       
    64         )
    63         )
    65 {
    64 {
    66     fsm->slave = slave;
    65     fsm->slave = slave;
    67     fsm->datagram = datagram;
    66     INIT_LIST_HEAD(&fsm->list); // mark as unlisted
    68     fsm->datagram->data_size = 0;
       
    69 
       
    70     EC_SLAVE_DBG(slave, 1, "Init FSM.\n");
       
    71 
    67 
    72     fsm->state = ec_fsm_slave_state_idle;
    68     fsm->state = ec_fsm_slave_state_idle;
    73 
    69     fsm->datagram = NULL;
    74     // init sub-state-machines
    70     fsm->sdo_request = NULL;
    75     ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
    71     fsm->reg_request = NULL;
    76     ec_fsm_foe_init(&fsm->fsm_foe, fsm->datagram);
    72     fsm->foe_request = NULL;
    77     ec_fsm_soe_init(&fsm->fsm_soe, fsm->datagram);
    73     fsm->soe_request = NULL;
       
    74 
       
    75     // Init sub-state-machines
       
    76     ec_fsm_coe_init(&fsm->fsm_coe);
       
    77     ec_fsm_foe_init(&fsm->fsm_foe);
       
    78     ec_fsm_soe_init(&fsm->fsm_soe);
    78 }
    79 }
    79 
    80 
    80 /*****************************************************************************/
    81 /*****************************************************************************/
    81 
    82 
    82 /** Destructor.
    83 /** Destructor.
    83  */
    84  */
    84 void ec_fsm_slave_clear(
    85 void ec_fsm_slave_clear(
    85         ec_fsm_slave_t *fsm /**< Master state machine. */
    86         ec_fsm_slave_t *fsm /**< Master state machine. */
    86         )
    87         )
    87 {
    88 {
       
    89     // signal requests that are currently in operation
       
    90 
       
    91     if (fsm->sdo_request) {
       
    92         fsm->sdo_request->state = EC_INT_REQUEST_FAILURE;
       
    93         wake_up_all(&fsm->slave->master->request_queue);
       
    94     }
       
    95 
       
    96     if (fsm->reg_request) {
       
    97         fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
       
    98         wake_up_all(&fsm->slave->master->request_queue);
       
    99     }
       
   100 
       
   101     if (fsm->foe_request) {
       
   102         fsm->foe_request->state = EC_INT_REQUEST_FAILURE;
       
   103         wake_up_all(&fsm->slave->master->request_queue);
       
   104     }
       
   105 
       
   106     if (fsm->soe_request) {
       
   107         fsm->soe_request->state = EC_INT_REQUEST_FAILURE;
       
   108         wake_up_all(&fsm->slave->master->request_queue);
       
   109     }
       
   110 
    88     // clear sub-state machines
   111     // clear sub-state machines
    89     ec_fsm_coe_clear(&fsm->fsm_coe);
   112     ec_fsm_coe_clear(&fsm->fsm_coe);
    90     ec_fsm_foe_clear(&fsm->fsm_foe);
   113     ec_fsm_foe_clear(&fsm->fsm_foe);
    91     ec_fsm_soe_clear(&fsm->fsm_soe);
   114     ec_fsm_soe_clear(&fsm->fsm_soe);
    92 }
   115 }
    93 
   116 
    94 /*****************************************************************************/
   117 /*****************************************************************************/
    95 
   118 
    96 /** Executes the current state of the state machine.
   119 /** Executes the current state of the state machine.
    97  *
   120  *
    98  * If the state machine's datagram is not sent or received yet, the execution
   121  * \return 1 if \a datagram was used, else 0.
    99  * of the state machine is delayed to the next cycle.
   122  */
   100  */
   123 int ec_fsm_slave_exec(
   101 void ec_fsm_slave_exec(
   124         ec_fsm_slave_t *fsm, /**< Slave state machine. */
   102         ec_fsm_slave_t *fsm /**< Slave state machine. */
   125         ec_datagram_t *datagram /**< New datagram to use. */
   103         )
   126         )
   104 {
   127 {
   105     if (fsm->datagram->state == EC_DATAGRAM_SENT
   128     int datagram_used;
   106         || fsm->datagram->state == EC_DATAGRAM_QUEUED) {
   129 
   107         // datagram was not sent or received yet.
   130     fsm->state(fsm, datagram);
   108         return;
   131 
   109     }
   132     datagram_used = fsm->state != ec_fsm_slave_state_idle &&
   110 
   133         fsm->state != ec_fsm_slave_state_ready;
   111     fsm->state(fsm);
   134 
   112 
   135     if (datagram_used) {
   113     ec_datagram_output_stats(fsm->datagram);
   136         fsm->datagram = datagram;
       
   137     } else {
       
   138         fsm->datagram = NULL;
       
   139     }
       
   140 
       
   141     return datagram_used;
   114 }
   142 }
   115 
   143 
   116 /*****************************************************************************/
   144 /*****************************************************************************/
   117 
   145 
   118 /** Sets the current state of the state machine to READY
   146 /** Sets the current state of the state machine to READY
   119  */
   147  */
   120 void ec_fsm_slave_ready(
   148 void ec_fsm_slave_set_ready(
   121         ec_fsm_slave_t *fsm /**< Slave state machine. */
   149         ec_fsm_slave_t *fsm /**< Slave state machine. */
   122         )
   150         )
   123 {
   151 {
   124     if (fsm->state == ec_fsm_slave_state_idle) {
   152     if (fsm->state == ec_fsm_slave_state_idle) {
   125         EC_SLAVE_DBG(fsm->slave, 1, "Ready for requests.\n");
   153         EC_SLAVE_DBG(fsm->slave, 1, "Ready for requests.\n");
   126         fsm->state = ec_fsm_slave_state_ready;
   154         fsm->state = ec_fsm_slave_state_ready;
   127     }
   155     }
   128 }
   156 }
   129 
   157 
       
   158 /*****************************************************************************/
       
   159 
       
   160 /** Returns, if the FSM is currently not busy and ready to execute.
       
   161  */
       
   162 int ec_fsm_slave_is_ready(
       
   163         const ec_fsm_slave_t *fsm /**< Slave state machine. */
       
   164         )
       
   165 {
       
   166     return fsm->state == ec_fsm_slave_state_ready;
       
   167 }
       
   168 
   130 /******************************************************************************
   169 /******************************************************************************
   131  * Slave state machine
   170  * Slave state machine
   132  *****************************************************************************/
   171  *****************************************************************************/
   133 
   172 
   134 /** Slave state: IDLE.
   173 /** Slave state: IDLE.
   135  */
   174  */
   136 void ec_fsm_slave_state_idle(
   175 void ec_fsm_slave_state_idle(
   137         ec_fsm_slave_t *fsm /**< Slave state machine. */
   176         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   177         ec_datagram_t *datagram /**< Datagram to use. */
   138         )
   178         )
   139 {
   179 {
   140     // do nothing
   180     // do nothing
   141 }
   181 }
   142 
   182 
   143 /*****************************************************************************/
   183 /*****************************************************************************/
   144 
   184 
   145 /** Slave state: READY.
   185 /** Slave state: READY.
   146  */
   186  */
   147 void ec_fsm_slave_state_ready(
   187 void ec_fsm_slave_state_ready(
   148         ec_fsm_slave_t *fsm /**< Slave state machine. */
   188         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   189         ec_datagram_t *datagram /**< Datagram to use. */
   149         )
   190         )
   150 {
   191 {
   151     // Check for pending external SDO requests
   192     // Check for pending external SDO requests
   152     if (ec_fsm_slave_action_process_sdo(fsm)) {
   193     if (ec_fsm_slave_action_process_sdo(fsm, datagram)) {
   153         return;
   194         return;
   154     }
   195     }
   155 
   196 
   156     // Check for pending external register requests
   197     // Check for pending external register requests
   157     if (ec_fsm_slave_action_process_reg(fsm)) {
   198     if (ec_fsm_slave_action_process_reg(fsm, datagram)) {
   158         return;
   199         return;
   159     }
   200     }
   160 
   201 
   161     // Check for pending FoE requests
   202     // Check for pending FoE requests
   162     if (ec_fsm_slave_action_process_foe(fsm)) {
   203     if (ec_fsm_slave_action_process_foe(fsm, datagram)) {
   163         return;
   204         return;
   164     }
   205     }
   165 
   206 
   166     // Check for pending SoE requests
   207     // Check for pending SoE requests
   167     if (ec_fsm_slave_action_process_soe(fsm)) {
   208     if (ec_fsm_slave_action_process_soe(fsm, datagram)) {
   168         return;
   209         return;
   169     }
   210     }
   170 }
   211 }
   171 
   212 
   172 /*****************************************************************************/
   213 /*****************************************************************************/
   174 /** Check for pending SDO requests and process one.
   215 /** Check for pending SDO requests and process one.
   175  *
   216  *
   176  * \return non-zero, if an SDO request is processed.
   217  * \return non-zero, if an SDO request is processed.
   177  */
   218  */
   178 int ec_fsm_slave_action_process_sdo(
   219 int ec_fsm_slave_action_process_sdo(
   179         ec_fsm_slave_t *fsm /**< Slave state machine. */
   220         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   221         ec_datagram_t *datagram /**< Datagram to use. */
   180         )
   222         )
   181 {
   223 {
   182     ec_slave_t *slave = fsm->slave;
   224     ec_slave_t *slave = fsm->slave;
   183     ec_sdo_request_t *request;
   225     ec_sdo_request_t *request;
   184 
   226 
   192 
   234 
   193     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   235     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   194         EC_SLAVE_WARN(slave, "Aborting SDO request,"
   236         EC_SLAVE_WARN(slave, "Aborting SDO request,"
   195                 " slave has error flag set.\n");
   237                 " slave has error flag set.\n");
   196         request->state = EC_INT_REQUEST_FAILURE;
   238         request->state = EC_INT_REQUEST_FAILURE;
   197         wake_up(&slave->master->request_queue);
   239         wake_up_all(&slave->master->request_queue);
   198         fsm->state = ec_fsm_slave_state_idle;
   240         fsm->state = ec_fsm_slave_state_idle;
   199         return 1;
   241         return 1;
   200     }
   242     }
   201 
   243 
   202     if (slave->current_state == EC_SLAVE_STATE_INIT) {
   244     if (slave->current_state == EC_SLAVE_STATE_INIT) {
   203         EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
   245         EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
   204         request->state = EC_INT_REQUEST_FAILURE;
   246         request->state = EC_INT_REQUEST_FAILURE;
   205         wake_up(&slave->master->request_queue);
   247         wake_up_all(&slave->master->request_queue);
   206         fsm->state = ec_fsm_slave_state_idle;
   248         fsm->state = ec_fsm_slave_state_idle;
   207         return 1;
   249         return 1;
   208     }
   250     }
   209 
   251 
       
   252     fsm->sdo_request = request;
   210     request->state = EC_INT_REQUEST_BUSY;
   253     request->state = EC_INT_REQUEST_BUSY;
   211 
   254 
   212     // Found pending SDO request. Execute it!
   255     // Found pending SDO request. Execute it!
   213     EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
   256     EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
   214 
   257 
   215     // Start SDO transfer
   258     // Start SDO transfer
   216     fsm->sdo_request = request;
       
   217     fsm->state = ec_fsm_slave_state_sdo_request;
   259     fsm->state = ec_fsm_slave_state_sdo_request;
   218     ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
   260     ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
   219     ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
   261     ec_fsm_coe_exec(&fsm->fsm_coe, datagram); // execute immediately
   220     ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   221     return 1;
   262     return 1;
   222 }
   263 }
   223 
   264 
   224 /*****************************************************************************/
   265 /*****************************************************************************/
   225 
   266 
   226 /** Slave state: SDO_REQUEST.
   267 /** Slave state: SDO_REQUEST.
   227  */
   268  */
   228 void ec_fsm_slave_state_sdo_request(
   269 void ec_fsm_slave_state_sdo_request(
   229         ec_fsm_slave_t *fsm /**< Slave state machine. */
   270         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   271         ec_datagram_t *datagram /**< Datagram to use. */
   230         )
   272         )
   231 {
   273 {
   232     ec_slave_t *slave = fsm->slave;
   274     ec_slave_t *slave = fsm->slave;
   233     ec_sdo_request_t *request = fsm->sdo_request;
   275     ec_sdo_request_t *request = fsm->sdo_request;
   234 
   276 
   235     if (ec_fsm_coe_exec(&fsm->fsm_coe)) {
   277     if (ec_fsm_coe_exec(&fsm->fsm_coe, datagram)) {
   236         ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   237         return;
   278         return;
   238     }
   279     }
   239 
   280 
   240     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
   281     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
   241         EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
   282         EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
   242         request->state = EC_INT_REQUEST_FAILURE;
   283         request->state = EC_INT_REQUEST_FAILURE;
   243         wake_up(&slave->master->request_queue);
   284         wake_up_all(&slave->master->request_queue);
   244         fsm->sdo_request = NULL;
   285         fsm->sdo_request = NULL;
   245         fsm->state = ec_fsm_slave_state_ready;
   286         fsm->state = ec_fsm_slave_state_ready;
   246         return;
   287         return;
   247     }
   288     }
   248 
   289 
   249     EC_SLAVE_DBG(slave, 1, "Finished SDO request.\n");
   290     EC_SLAVE_DBG(slave, 1, "Finished SDO request.\n");
   250 
   291 
   251     // SDO request finished
   292     // SDO request finished
   252     request->state = EC_INT_REQUEST_SUCCESS;
   293     request->state = EC_INT_REQUEST_SUCCESS;
   253     wake_up(&slave->master->request_queue);
   294     wake_up_all(&slave->master->request_queue);
   254     fsm->sdo_request = NULL;
   295     fsm->sdo_request = NULL;
   255     fsm->state = ec_fsm_slave_state_ready;
   296     fsm->state = ec_fsm_slave_state_ready;
   256 }
   297 }
   257 
   298 
   258 /*****************************************************************************/
   299 /*****************************************************************************/
   260 /** Check for pending register requests and process one.
   301 /** Check for pending register requests and process one.
   261  *
   302  *
   262  * \return non-zero, if a register request is processed.
   303  * \return non-zero, if a register request is processed.
   263  */
   304  */
   264 int ec_fsm_slave_action_process_reg(
   305 int ec_fsm_slave_action_process_reg(
   265         ec_fsm_slave_t *fsm /**< Slave state machine. */
   306         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   307         ec_datagram_t *datagram /**< Datagram to use. */
   266         )
   308         )
   267 {
   309 {
   268     ec_slave_t *slave = fsm->slave;
   310     ec_slave_t *slave = fsm->slave;
   269     ec_reg_request_t *reg;
   311     ec_reg_request_t *reg;
   270 
   312 
   293 
   335 
   294     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   336     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   295         EC_SLAVE_WARN(slave, "Aborting register request,"
   337         EC_SLAVE_WARN(slave, "Aborting register request,"
   296                 " slave has error flag set.\n");
   338                 " slave has error flag set.\n");
   297         fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
   339         fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
   298         wake_up(&slave->master->request_queue);
   340         wake_up_all(&slave->master->request_queue);
   299         fsm->reg_request = NULL;
   341         fsm->reg_request = NULL;
   300         fsm->state = ec_fsm_slave_state_idle;
   342         fsm->state = ec_fsm_slave_state_idle;
   301         return 1;
   343         return 1;
   302     }
   344     }
   303 
   345 
   306 
   348 
   307     fsm->reg_request->state = EC_INT_REQUEST_BUSY;
   349     fsm->reg_request->state = EC_INT_REQUEST_BUSY;
   308 
   350 
   309     // Start register access
   351     // Start register access
   310     if (fsm->reg_request->dir == EC_DIR_INPUT) {
   352     if (fsm->reg_request->dir == EC_DIR_INPUT) {
   311         ec_datagram_fprd(fsm->datagram, slave->station_address,
   353         ec_datagram_fprd(datagram, slave->station_address,
   312                 fsm->reg_request->address, fsm->reg_request->transfer_size);
   354                 fsm->reg_request->address, fsm->reg_request->transfer_size);
   313         ec_datagram_zero(fsm->datagram);
   355         ec_datagram_zero(datagram);
   314     } else {
   356     } else {
   315         ec_datagram_fpwr(fsm->datagram, slave->station_address,
   357         ec_datagram_fpwr(datagram, slave->station_address,
   316                 fsm->reg_request->address, fsm->reg_request->transfer_size);
   358                 fsm->reg_request->address, fsm->reg_request->transfer_size);
   317         memcpy(fsm->datagram->data, fsm->reg_request->data,
   359         memcpy(datagram->data, fsm->reg_request->data,
   318                 fsm->reg_request->transfer_size);
   360                 fsm->reg_request->transfer_size);
   319     }
   361     }
   320     fsm->datagram->device_index = slave->device_index;
   362     datagram->device_index = slave->device_index;
   321     ec_master_queue_external_datagram(slave->master, fsm->datagram);
       
   322     fsm->state = ec_fsm_slave_state_reg_request;
   363     fsm->state = ec_fsm_slave_state_reg_request;
   323     return 1;
   364     return 1;
   324 }
   365 }
   325 
   366 
   326 /*****************************************************************************/
   367 /*****************************************************************************/
   327 
   368 
   328 /** Slave state: Register request.
   369 /** Slave state: Register request.
   329  */
   370  */
   330 void ec_fsm_slave_state_reg_request(
   371 void ec_fsm_slave_state_reg_request(
   331         ec_fsm_slave_t *fsm /**< Slave state machine. */
   372         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   373         ec_datagram_t *datagram /**< Datagram to use. */
   332         )
   374         )
   333 {
   375 {
   334     ec_slave_t *slave = fsm->slave;
   376     ec_slave_t *slave = fsm->slave;
   335     ec_reg_request_t *reg = fsm->reg_request;
   377     ec_reg_request_t *reg = fsm->reg_request;
   336 
   378 
   337     if (!reg) {
   379     if (!reg) {
   338         // configuration was cleared in the meantime
   380         // configuration was cleared in the meantime
   339         fsm->state = ec_fsm_slave_state_ready;
   381         fsm->state = ec_fsm_slave_state_ready;
       
   382         fsm->reg_request = NULL;
   340         return;
   383         return;
   341     }
   384     }
   342 
   385 
   343     if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
   386     if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
   344         EC_SLAVE_ERR(slave, "Failed to receive register"
   387         EC_SLAVE_ERR(slave, "Failed to receive register"
   345                 " request datagram: ");
   388                 " request datagram: ");
   346         ec_datagram_print_state(fsm->datagram);
   389         ec_datagram_print_state(fsm->datagram);
   347         reg->state = EC_INT_REQUEST_FAILURE;
   390         reg->state = EC_INT_REQUEST_FAILURE;
   348         wake_up(&slave->master->request_queue);
   391         wake_up_all(&slave->master->request_queue);
   349         fsm->reg_request = NULL;
   392         fsm->reg_request = NULL;
   350         fsm->state = ec_fsm_slave_state_ready;
   393         fsm->state = ec_fsm_slave_state_ready;
   351         return;
   394         return;
   352     }
   395     }
   353 
   396 
   364         EC_SLAVE_ERR(slave, "Register request failed"
   407         EC_SLAVE_ERR(slave, "Register request failed"
   365                 " (working counter is %u).\n",
   408                 " (working counter is %u).\n",
   366                 fsm->datagram->working_counter);
   409                 fsm->datagram->working_counter);
   367     }
   410     }
   368 
   411 
   369     wake_up(&slave->master->request_queue);
   412     wake_up_all(&slave->master->request_queue);
   370     fsm->reg_request = NULL;
   413     fsm->reg_request = NULL;
   371     fsm->state = ec_fsm_slave_state_ready;
   414     fsm->state = ec_fsm_slave_state_ready;
   372 }
   415 }
   373 
   416 
   374 /*****************************************************************************/
   417 /*****************************************************************************/
   376 /** Check for pending FoE requests and process one.
   419 /** Check for pending FoE requests and process one.
   377  *
   420  *
   378  * \return non-zero, if an FoE request is processed.
   421  * \return non-zero, if an FoE request is processed.
   379  */
   422  */
   380 int ec_fsm_slave_action_process_foe(
   423 int ec_fsm_slave_action_process_foe(
   381         ec_fsm_slave_t *fsm /**< Slave state machine. */
   424         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   425         ec_datagram_t *datagram /**< Datagram to use. */
   382         )
   426         )
   383 {
   427 {
   384     ec_slave_t *slave = fsm->slave;
   428     ec_slave_t *slave = fsm->slave;
   385     ec_foe_request_t *request;
   429     ec_foe_request_t *request;
   386 
   430 
   394 
   438 
   395     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   439     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   396         EC_SLAVE_WARN(slave, "Aborting FoE request,"
   440         EC_SLAVE_WARN(slave, "Aborting FoE request,"
   397                 " slave has error flag set.\n");
   441                 " slave has error flag set.\n");
   398         request->state = EC_INT_REQUEST_FAILURE;
   442         request->state = EC_INT_REQUEST_FAILURE;
   399         wake_up(&slave->master->request_queue);
   443         wake_up_all(&slave->master->request_queue);
   400         fsm->state = ec_fsm_slave_state_idle;
   444         fsm->state = ec_fsm_slave_state_idle;
   401         return 1;
   445         return 1;
   402     }
   446     }
   403 
   447 
   404     request->state = EC_INT_REQUEST_BUSY;
   448     request->state = EC_INT_REQUEST_BUSY;
       
   449     fsm->foe_request = request;
   405 
   450 
   406     EC_SLAVE_DBG(slave, 1, "Processing FoE request.\n");
   451     EC_SLAVE_DBG(slave, 1, "Processing FoE request.\n");
   407 
   452 
   408     fsm->foe_request = request;
       
   409     fsm->state = ec_fsm_slave_state_foe_request;
   453     fsm->state = ec_fsm_slave_state_foe_request;
   410     ec_fsm_foe_transfer(&fsm->fsm_foe, slave, request);
   454     ec_fsm_foe_transfer(&fsm->fsm_foe, slave, request);
   411     ec_fsm_foe_exec(&fsm->fsm_foe);
   455     ec_fsm_foe_exec(&fsm->fsm_foe, datagram);
   412     ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   413     return 1;
   456     return 1;
   414 }
   457 }
   415 
   458 
   416 /*****************************************************************************/
   459 /*****************************************************************************/
   417 
   460 
   418 /** Slave state: FOE REQUEST.
   461 /** Slave state: FOE REQUEST.
   419  */
   462  */
   420 void ec_fsm_slave_state_foe_request(
   463 void ec_fsm_slave_state_foe_request(
   421         ec_fsm_slave_t *fsm /**< Slave state machine. */
   464         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   465         ec_datagram_t *datagram /**< Datagram to use. */
   422         )
   466         )
   423 {
   467 {
   424     ec_slave_t *slave = fsm->slave;
   468     ec_slave_t *slave = fsm->slave;
   425     ec_foe_request_t *request = fsm->foe_request;
   469     ec_foe_request_t *request = fsm->foe_request;
   426 
   470 
   427     if (ec_fsm_foe_exec(&fsm->fsm_foe)) {
   471     if (ec_fsm_foe_exec(&fsm->fsm_foe, datagram)) {
   428         ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   429         return;
   472         return;
   430     }
   473     }
   431 
   474 
   432     if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
   475     if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
   433         EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n");
   476         EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n");
   434         request->state = EC_INT_REQUEST_FAILURE;
   477         request->state = EC_INT_REQUEST_FAILURE;
   435         wake_up(&slave->master->request_queue);
   478         wake_up_all(&slave->master->request_queue);
   436         fsm->foe_request = NULL;
   479         fsm->foe_request = NULL;
   437         fsm->state = ec_fsm_slave_state_ready;
   480         fsm->state = ec_fsm_slave_state_ready;
   438         return;
   481         return;
   439     }
   482     }
   440 
   483 
   441     // finished transferring FoE
   484     // finished transferring FoE
   442     EC_SLAVE_DBG(slave, 1, "Successfully transferred %zu bytes of FoE"
   485     EC_SLAVE_DBG(slave, 1, "Successfully transferred %zu bytes of FoE"
   443             " data.\n", request->data_size);
   486             " data.\n", request->data_size);
   444 
   487 
   445     request->state = EC_INT_REQUEST_SUCCESS;
   488     request->state = EC_INT_REQUEST_SUCCESS;
   446     wake_up(&slave->master->request_queue);
   489     wake_up_all(&slave->master->request_queue);
   447     fsm->foe_request = NULL;
   490     fsm->foe_request = NULL;
   448     fsm->state = ec_fsm_slave_state_ready;
   491     fsm->state = ec_fsm_slave_state_ready;
   449 }
   492 }
   450 
   493 
   451 /*****************************************************************************/
   494 /*****************************************************************************/
   453 /** Check for pending SoE requests and process one.
   496 /** Check for pending SoE requests and process one.
   454  *
   497  *
   455  * \return non-zero, if a request is processed.
   498  * \return non-zero, if a request is processed.
   456  */
   499  */
   457 int ec_fsm_slave_action_process_soe(
   500 int ec_fsm_slave_action_process_soe(
   458         ec_fsm_slave_t *fsm /**< Slave state machine. */
   501         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   502         ec_datagram_t *datagram /**< Datagram to use. */
   459         )
   503         )
   460 {
   504 {
   461     ec_slave_t *slave = fsm->slave;
   505     ec_slave_t *slave = fsm->slave;
   462     ec_soe_request_t *req;
   506     ec_soe_request_t *req;
   463 
   507 
   471 
   515 
   472     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   516     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
   473         EC_SLAVE_WARN(slave, "Aborting SoE request,"
   517         EC_SLAVE_WARN(slave, "Aborting SoE request,"
   474                 " slave has error flag set.\n");
   518                 " slave has error flag set.\n");
   475         req->state = EC_INT_REQUEST_FAILURE;
   519         req->state = EC_INT_REQUEST_FAILURE;
   476         wake_up(&slave->master->request_queue);
   520         wake_up_all(&slave->master->request_queue);
   477         fsm->state = ec_fsm_slave_state_idle;
   521         fsm->state = ec_fsm_slave_state_idle;
   478         return 1;
   522         return 1;
   479     }
   523     }
   480 
   524 
   481     if (slave->current_state == EC_SLAVE_STATE_INIT) {
   525     if (slave->current_state == EC_SLAVE_STATE_INIT) {
   482         EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n");
   526         EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n");
   483         req->state = EC_INT_REQUEST_FAILURE;
   527         req->state = EC_INT_REQUEST_FAILURE;
   484         wake_up(&slave->master->request_queue);
   528         wake_up_all(&slave->master->request_queue);
   485         fsm->state = ec_fsm_slave_state_idle;
   529         fsm->state = ec_fsm_slave_state_idle;
   486         return 0;
   530         return 0;
   487     }
   531     }
   488 
   532 
       
   533     fsm->soe_request = req;
   489     req->state = EC_INT_REQUEST_BUSY;
   534     req->state = EC_INT_REQUEST_BUSY;
   490 
   535 
   491     // Found pending request. Execute it!
   536     // Found pending request. Execute it!
   492     EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n");
   537     EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n");
   493 
   538 
   494     // Start SoE transfer
   539     // Start SoE transfer
   495     fsm->soe_request = req;
       
   496     fsm->state = ec_fsm_slave_state_soe_request;
   540     fsm->state = ec_fsm_slave_state_soe_request;
   497     ec_fsm_soe_transfer(&fsm->fsm_soe, slave, req);
   541     ec_fsm_soe_transfer(&fsm->fsm_soe, slave, req);
   498     ec_fsm_soe_exec(&fsm->fsm_soe); // execute immediately
   542     ec_fsm_soe_exec(&fsm->fsm_soe, datagram); // execute immediately
   499     ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   500     return 1;
   543     return 1;
   501 }
   544 }
   502 
   545 
   503 /*****************************************************************************/
   546 /*****************************************************************************/
   504 
   547 
   505 /** Slave state: SOE_REQUEST.
   548 /** Slave state: SOE_REQUEST.
   506  */
   549  */
   507 void ec_fsm_slave_state_soe_request(
   550 void ec_fsm_slave_state_soe_request(
   508         ec_fsm_slave_t *fsm /**< Slave state machine. */
   551         ec_fsm_slave_t *fsm, /**< Slave state machine. */
       
   552         ec_datagram_t *datagram /**< Datagram to use. */
   509         )
   553         )
   510 {
   554 {
   511     ec_slave_t *slave = fsm->slave;
   555     ec_slave_t *slave = fsm->slave;
   512     ec_soe_request_t *request = fsm->soe_request;
   556     ec_soe_request_t *request = fsm->soe_request;
   513 
   557 
   514     if (ec_fsm_soe_exec(&fsm->fsm_soe)) {
   558     if (ec_fsm_soe_exec(&fsm->fsm_soe, datagram)) {
   515         ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
       
   516         return;
   559         return;
   517     }
   560     }
   518 
   561 
   519     if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
   562     if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
   520         EC_SLAVE_ERR(slave, "Failed to process SoE request.\n");
   563         EC_SLAVE_ERR(slave, "Failed to process SoE request.\n");
   521         request->state = EC_INT_REQUEST_FAILURE;
   564         request->state = EC_INT_REQUEST_FAILURE;
   522         wake_up(&slave->master->request_queue);
   565         wake_up_all(&slave->master->request_queue);
   523         fsm->soe_request = NULL;
   566         fsm->soe_request = NULL;
   524         fsm->state = ec_fsm_slave_state_ready;
   567         fsm->state = ec_fsm_slave_state_ready;
   525         return;
   568         return;
   526     }
   569     }
   527 
   570 
   528     EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n");
   571     EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n");
   529 
   572 
   530     // SoE request finished
   573     // SoE request finished
   531     request->state = EC_INT_REQUEST_SUCCESS;
   574     request->state = EC_INT_REQUEST_SUCCESS;
   532     wake_up(&slave->master->request_queue);
   575     wake_up_all(&slave->master->request_queue);
   533     fsm->soe_request = NULL;
   576     fsm->soe_request = NULL;
   534     fsm->state = ec_fsm_slave_state_ready;
   577     fsm->state = ec_fsm_slave_state_ready;
   535 }
   578 }
   536 
   579 
   537 /*****************************************************************************/
   580 /*****************************************************************************/