00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00034
00035
00036 #include "globals.h"
00037 #include "master.h"
00038 #include "mailbox.h"
00039 #include "slave_config.h"
00040
00041 #include "fsm_slave.h"
00042
00043
00044
00045 void ec_fsm_slave_state_idle(ec_fsm_slave_t *, ec_datagram_t *);
00046 void ec_fsm_slave_state_ready(ec_fsm_slave_t *, ec_datagram_t *);
00047 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *, ec_datagram_t *);
00048 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *, ec_datagram_t *);
00049 int ec_fsm_slave_action_process_reg(ec_fsm_slave_t *, ec_datagram_t *);
00050 void ec_fsm_slave_state_reg_request(ec_fsm_slave_t *, ec_datagram_t *);
00051 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *, ec_datagram_t *);
00052 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *, ec_datagram_t *);
00053 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *, ec_datagram_t *);
00054 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *, ec_datagram_t *);
00055
00056
00057
00060 void ec_fsm_slave_init(
00061 ec_fsm_slave_t *fsm,
00062 ec_slave_t *slave
00063 )
00064 {
00065 fsm->slave = slave;
00066 INIT_LIST_HEAD(&fsm->list);
00067
00068 fsm->state = ec_fsm_slave_state_idle;
00069 fsm->datagram = NULL;
00070 fsm->sdo_request = NULL;
00071 fsm->reg_request = NULL;
00072 fsm->foe_request = NULL;
00073 fsm->soe_request = NULL;
00074
00075
00076 ec_fsm_coe_init(&fsm->fsm_coe);
00077 ec_fsm_foe_init(&fsm->fsm_foe);
00078 ec_fsm_soe_init(&fsm->fsm_soe);
00079 }
00080
00081
00082
00085 void ec_fsm_slave_clear(
00086 ec_fsm_slave_t *fsm
00087 )
00088 {
00089
00090
00091 if (fsm->sdo_request) {
00092 fsm->sdo_request->state = EC_INT_REQUEST_FAILURE;
00093 wake_up_all(&fsm->slave->master->request_queue);
00094 }
00095
00096 if (fsm->reg_request) {
00097 fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
00098 wake_up_all(&fsm->slave->master->request_queue);
00099 }
00100
00101 if (fsm->foe_request) {
00102 fsm->foe_request->state = EC_INT_REQUEST_FAILURE;
00103 wake_up_all(&fsm->slave->master->request_queue);
00104 }
00105
00106 if (fsm->soe_request) {
00107 fsm->soe_request->state = EC_INT_REQUEST_FAILURE;
00108 wake_up_all(&fsm->slave->master->request_queue);
00109 }
00110
00111
00112 ec_fsm_coe_clear(&fsm->fsm_coe);
00113 ec_fsm_foe_clear(&fsm->fsm_foe);
00114 ec_fsm_soe_clear(&fsm->fsm_soe);
00115 }
00116
00117
00118
00123 int ec_fsm_slave_exec(
00124 ec_fsm_slave_t *fsm,
00125 ec_datagram_t *datagram
00126 )
00127 {
00128 int datagram_used;
00129
00130 fsm->state(fsm, datagram);
00131
00132 datagram_used = fsm->state != ec_fsm_slave_state_idle &&
00133 fsm->state != ec_fsm_slave_state_ready;
00134
00135 if (datagram_used) {
00136 fsm->datagram = datagram;
00137 } else {
00138 fsm->datagram = NULL;
00139 }
00140
00141 return datagram_used;
00142 }
00143
00144
00145
00148 void ec_fsm_slave_set_ready(
00149 ec_fsm_slave_t *fsm
00150 )
00151 {
00152 if (fsm->state == ec_fsm_slave_state_idle) {
00153 EC_SLAVE_DBG(fsm->slave, 1, "Ready for requests.\n");
00154 fsm->state = ec_fsm_slave_state_ready;
00155 }
00156 }
00157
00158
00159
00164 int ec_fsm_slave_is_ready(
00165 const ec_fsm_slave_t *fsm
00166 )
00167 {
00168 return fsm->state == ec_fsm_slave_state_ready;
00169 }
00170
00171
00172
00173
00174
00177 void ec_fsm_slave_state_idle(
00178 ec_fsm_slave_t *fsm,
00179 ec_datagram_t *datagram
00180 )
00181 {
00182
00183 }
00184
00185
00186
00189 void ec_fsm_slave_state_ready(
00190 ec_fsm_slave_t *fsm,
00191 ec_datagram_t *datagram
00192 )
00193 {
00194
00195 if (ec_fsm_slave_action_process_sdo(fsm, datagram)) {
00196 return;
00197 }
00198
00199
00200 if (ec_fsm_slave_action_process_reg(fsm, datagram)) {
00201 return;
00202 }
00203
00204
00205 if (ec_fsm_slave_action_process_foe(fsm, datagram)) {
00206 return;
00207 }
00208
00209
00210 if (ec_fsm_slave_action_process_soe(fsm, datagram)) {
00211 return;
00212 }
00213 }
00214
00215
00216
00221 int ec_fsm_slave_action_process_sdo(
00222 ec_fsm_slave_t *fsm,
00223 ec_datagram_t *datagram
00224 )
00225 {
00226 ec_slave_t *slave = fsm->slave;
00227 ec_sdo_request_t *request;
00228
00229 if (list_empty(&slave->sdo_requests)) {
00230 return 0;
00231 }
00232
00233
00234 request = list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
00235 list_del_init(&request->list);
00236
00237 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
00238 EC_SLAVE_WARN(slave, "Aborting SDO request,"
00239 " slave has error flag set.\n");
00240 request->state = EC_INT_REQUEST_FAILURE;
00241 wake_up_all(&slave->master->request_queue);
00242 fsm->state = ec_fsm_slave_state_idle;
00243 return 1;
00244 }
00245
00246 if (slave->current_state == EC_SLAVE_STATE_INIT) {
00247 EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
00248 request->state = EC_INT_REQUEST_FAILURE;
00249 wake_up_all(&slave->master->request_queue);
00250 fsm->state = ec_fsm_slave_state_idle;
00251 return 1;
00252 }
00253
00254 fsm->sdo_request = request;
00255 request->state = EC_INT_REQUEST_BUSY;
00256
00257
00258 EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
00259
00260
00261 fsm->state = ec_fsm_slave_state_sdo_request;
00262 ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
00263 ec_fsm_coe_exec(&fsm->fsm_coe, datagram);
00264 return 1;
00265 }
00266
00267
00268
00271 void ec_fsm_slave_state_sdo_request(
00272 ec_fsm_slave_t *fsm,
00273 ec_datagram_t *datagram
00274 )
00275 {
00276 ec_slave_t *slave = fsm->slave;
00277 ec_sdo_request_t *request = fsm->sdo_request;
00278
00279 if (ec_fsm_coe_exec(&fsm->fsm_coe, datagram)) {
00280 return;
00281 }
00282
00283 if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
00284 EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
00285 request->state = EC_INT_REQUEST_FAILURE;
00286 wake_up_all(&slave->master->request_queue);
00287 fsm->sdo_request = NULL;
00288 fsm->state = ec_fsm_slave_state_ready;
00289 return;
00290 }
00291
00292 EC_SLAVE_DBG(slave, 1, "Finished SDO request.\n");
00293
00294
00295 request->state = EC_INT_REQUEST_SUCCESS;
00296 wake_up_all(&slave->master->request_queue);
00297 fsm->sdo_request = NULL;
00298 fsm->state = ec_fsm_slave_state_ready;
00299 }
00300
00301
00302
00307 int ec_fsm_slave_action_process_reg(
00308 ec_fsm_slave_t *fsm,
00309 ec_datagram_t *datagram
00310 )
00311 {
00312 ec_slave_t *slave = fsm->slave;
00313 ec_reg_request_t *reg;
00314
00315 fsm->reg_request = NULL;
00316
00317 if (slave->config) {
00318
00319 list_for_each_entry(reg, &slave->config->reg_requests, list) {
00320 if (reg->state == EC_INT_REQUEST_QUEUED) {
00321 fsm->reg_request = reg;
00322 break;
00323 }
00324 }
00325 }
00326
00327 if (!fsm->reg_request && !list_empty(&slave->reg_requests)) {
00328
00329 fsm->reg_request =
00330 list_entry(slave->reg_requests.next, ec_reg_request_t, list);
00331 list_del_init(&fsm->reg_request->list);
00332 }
00333
00334 if (!fsm->reg_request) {
00335 return 0;
00336 }
00337
00338 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
00339 EC_SLAVE_WARN(slave, "Aborting register request,"
00340 " slave has error flag set.\n");
00341 fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
00342 wake_up_all(&slave->master->request_queue);
00343 fsm->reg_request = NULL;
00344 fsm->state = ec_fsm_slave_state_idle;
00345 return 1;
00346 }
00347
00348
00349 EC_SLAVE_DBG(slave, 1, "Processing register request...\n");
00350
00351 fsm->reg_request->state = EC_INT_REQUEST_BUSY;
00352
00353
00354 if (fsm->reg_request->dir == EC_DIR_INPUT) {
00355 ec_datagram_fprd(datagram, slave->station_address,
00356 fsm->reg_request->address, fsm->reg_request->transfer_size);
00357 ec_datagram_zero(datagram);
00358 } else {
00359 ec_datagram_fpwr(datagram, slave->station_address,
00360 fsm->reg_request->address, fsm->reg_request->transfer_size);
00361 memcpy(datagram->data, fsm->reg_request->data,
00362 fsm->reg_request->transfer_size);
00363 }
00364 datagram->device_index = slave->device_index;
00365 fsm->state = ec_fsm_slave_state_reg_request;
00366 return 1;
00367 }
00368
00369
00370
00373 void ec_fsm_slave_state_reg_request(
00374 ec_fsm_slave_t *fsm,
00375 ec_datagram_t *datagram
00376 )
00377 {
00378 ec_slave_t *slave = fsm->slave;
00379 ec_reg_request_t *reg = fsm->reg_request;
00380
00381 if (!reg) {
00382
00383 fsm->state = ec_fsm_slave_state_ready;
00384 fsm->reg_request = NULL;
00385 return;
00386 }
00387
00388 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00389 EC_SLAVE_ERR(slave, "Failed to receive register"
00390 " request datagram: ");
00391 ec_datagram_print_state(fsm->datagram);
00392 reg->state = EC_INT_REQUEST_FAILURE;
00393 wake_up_all(&slave->master->request_queue);
00394 fsm->reg_request = NULL;
00395 fsm->state = ec_fsm_slave_state_ready;
00396 return;
00397 }
00398
00399 if (fsm->datagram->working_counter == 1) {
00400 if (reg->dir == EC_DIR_INPUT) {
00401 memcpy(reg->data, fsm->datagram->data, reg->transfer_size);
00402 }
00403
00404 reg->state = EC_INT_REQUEST_SUCCESS;
00405 EC_SLAVE_DBG(slave, 1, "Register request successful.\n");
00406 } else {
00407 reg->state = EC_INT_REQUEST_FAILURE;
00408 ec_datagram_print_state(fsm->datagram);
00409 EC_SLAVE_ERR(slave, "Register request failed"
00410 " (working counter is %u).\n",
00411 fsm->datagram->working_counter);
00412 }
00413
00414 wake_up_all(&slave->master->request_queue);
00415 fsm->reg_request = NULL;
00416 fsm->state = ec_fsm_slave_state_ready;
00417 }
00418
00419
00420
00425 int ec_fsm_slave_action_process_foe(
00426 ec_fsm_slave_t *fsm,
00427 ec_datagram_t *datagram
00428 )
00429 {
00430 ec_slave_t *slave = fsm->slave;
00431 ec_foe_request_t *request;
00432
00433 if (list_empty(&slave->foe_requests)) {
00434 return 0;
00435 }
00436
00437
00438 request = list_entry(slave->foe_requests.next, ec_foe_request_t, list);
00439 list_del_init(&request->list);
00440
00441 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
00442 EC_SLAVE_WARN(slave, "Aborting FoE request,"
00443 " slave has error flag set.\n");
00444 request->state = EC_INT_REQUEST_FAILURE;
00445 wake_up_all(&slave->master->request_queue);
00446 fsm->state = ec_fsm_slave_state_idle;
00447 return 1;
00448 }
00449
00450 request->state = EC_INT_REQUEST_BUSY;
00451 fsm->foe_request = request;
00452
00453 EC_SLAVE_DBG(slave, 1, "Processing FoE request.\n");
00454
00455 fsm->state = ec_fsm_slave_state_foe_request;
00456 ec_fsm_foe_transfer(&fsm->fsm_foe, slave, request);
00457 ec_fsm_foe_exec(&fsm->fsm_foe, datagram);
00458 return 1;
00459 }
00460
00461
00462
00465 void ec_fsm_slave_state_foe_request(
00466 ec_fsm_slave_t *fsm,
00467 ec_datagram_t *datagram
00468 )
00469 {
00470 ec_slave_t *slave = fsm->slave;
00471 ec_foe_request_t *request = fsm->foe_request;
00472
00473 if (ec_fsm_foe_exec(&fsm->fsm_foe, datagram)) {
00474 return;
00475 }
00476
00477 if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
00478 EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n");
00479 request->state = EC_INT_REQUEST_FAILURE;
00480 wake_up_all(&slave->master->request_queue);
00481 fsm->foe_request = NULL;
00482 fsm->state = ec_fsm_slave_state_ready;
00483 return;
00484 }
00485
00486
00487 EC_SLAVE_DBG(slave, 1, "Successfully transferred %zu bytes of FoE"
00488 " data.\n", request->data_size);
00489
00490 request->state = EC_INT_REQUEST_SUCCESS;
00491 wake_up_all(&slave->master->request_queue);
00492 fsm->foe_request = NULL;
00493 fsm->state = ec_fsm_slave_state_ready;
00494 }
00495
00496
00497
00502 int ec_fsm_slave_action_process_soe(
00503 ec_fsm_slave_t *fsm,
00504 ec_datagram_t *datagram
00505 )
00506 {
00507 ec_slave_t *slave = fsm->slave;
00508 ec_soe_request_t *req;
00509
00510 if (list_empty(&slave->soe_requests)) {
00511 return 0;
00512 }
00513
00514
00515 req = list_entry(slave->soe_requests.next, ec_soe_request_t, list);
00516 list_del_init(&req->list);
00517
00518 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
00519 EC_SLAVE_WARN(slave, "Aborting SoE request,"
00520 " slave has error flag set.\n");
00521 req->state = EC_INT_REQUEST_FAILURE;
00522 wake_up_all(&slave->master->request_queue);
00523 fsm->state = ec_fsm_slave_state_idle;
00524 return 1;
00525 }
00526
00527 if (slave->current_state == EC_SLAVE_STATE_INIT) {
00528 EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n");
00529 req->state = EC_INT_REQUEST_FAILURE;
00530 wake_up_all(&slave->master->request_queue);
00531 fsm->state = ec_fsm_slave_state_idle;
00532 return 0;
00533 }
00534
00535 fsm->soe_request = req;
00536 req->state = EC_INT_REQUEST_BUSY;
00537
00538
00539 EC_SLAVE_DBG(slave, 1, "Processing SoE request...\n");
00540
00541
00542 fsm->state = ec_fsm_slave_state_soe_request;
00543 ec_fsm_soe_transfer(&fsm->fsm_soe, slave, req);
00544 ec_fsm_soe_exec(&fsm->fsm_soe, datagram);
00545 return 1;
00546 }
00547
00548
00549
00552 void ec_fsm_slave_state_soe_request(
00553 ec_fsm_slave_t *fsm,
00554 ec_datagram_t *datagram
00555 )
00556 {
00557 ec_slave_t *slave = fsm->slave;
00558 ec_soe_request_t *request = fsm->soe_request;
00559
00560 if (ec_fsm_soe_exec(&fsm->fsm_soe, datagram)) {
00561 return;
00562 }
00563
00564 if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
00565 EC_SLAVE_ERR(slave, "Failed to process SoE request.\n");
00566 request->state = EC_INT_REQUEST_FAILURE;
00567 wake_up_all(&slave->master->request_queue);
00568 fsm->soe_request = NULL;
00569 fsm->state = ec_fsm_slave_state_ready;
00570 return;
00571 }
00572
00573 EC_SLAVE_DBG(slave, 1, "Finished SoE request.\n");
00574
00575
00576 request->state = EC_INT_REQUEST_SUCCESS;
00577 wake_up_all(&slave->master->request_queue);
00578 fsm->soe_request = NULL;
00579 fsm->state = ec_fsm_slave_state_ready;
00580 }
00581
00582