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