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 "fsm_coe.h"
00040 #include "slave_config.h"
00041
00042
00043
00046 #define EC_FSM_COE_DICT_TIMEOUT 1000
00047
00050 #define EC_COE_DOWN_REQ_HEADER_SIZE 10
00051
00054 #define EC_COE_DOWN_SEG_REQ_HEADER_SIZE 3
00055
00058 #define EC_COE_DOWN_SEG_MIN_DATA_SIZE 7
00059
00062 #define DEBUG_RETRIES 0
00063
00066 #define DEBUG_LONG 0
00067
00068
00069
00070 void ec_fsm_coe_dict_start(ec_fsm_coe_t *, ec_datagram_t *);
00071 void ec_fsm_coe_dict_request(ec_fsm_coe_t *, ec_datagram_t *);
00072 void ec_fsm_coe_dict_check(ec_fsm_coe_t *, ec_datagram_t *);
00073 void ec_fsm_coe_dict_response(ec_fsm_coe_t *, ec_datagram_t *);
00074 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *, ec_datagram_t *);
00075 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *, ec_datagram_t *);
00076 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *, ec_datagram_t *);
00077 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *, ec_datagram_t *);
00078 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *, ec_datagram_t *);
00079 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *, ec_datagram_t *);
00080
00081 void ec_fsm_coe_down_start(ec_fsm_coe_t *, ec_datagram_t *);
00082 void ec_fsm_coe_down_request(ec_fsm_coe_t *, ec_datagram_t *);
00083 void ec_fsm_coe_down_check(ec_fsm_coe_t *, ec_datagram_t *);
00084 void ec_fsm_coe_down_response(ec_fsm_coe_t *, ec_datagram_t *);
00085 void ec_fsm_coe_down_seg_check(ec_fsm_coe_t *, ec_datagram_t *);
00086 void ec_fsm_coe_down_seg_response(ec_fsm_coe_t *, ec_datagram_t *);
00087
00088 void ec_fsm_coe_up_start(ec_fsm_coe_t *, ec_datagram_t *);
00089 void ec_fsm_coe_up_request(ec_fsm_coe_t *, ec_datagram_t *);
00090 void ec_fsm_coe_up_check(ec_fsm_coe_t *, ec_datagram_t *);
00091 void ec_fsm_coe_up_response(ec_fsm_coe_t *, ec_datagram_t *);
00092 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *, ec_datagram_t *);
00093 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *, ec_datagram_t *);
00094 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *, ec_datagram_t *);
00095
00096 void ec_fsm_coe_end(ec_fsm_coe_t *, ec_datagram_t *);
00097 void ec_fsm_coe_error(ec_fsm_coe_t *, ec_datagram_t *);
00098
00099
00100
00107 const ec_code_msg_t sdo_abort_messages[] = {
00108 {0x05030000, "Toggle bit not changed"},
00109 {0x05040000, "SDO protocol timeout"},
00110 {0x05040001, "Client/Server command specifier not valid or unknown"},
00111 {0x05040005, "Out of memory"},
00112 {0x06010000, "Unsupported access to an object"},
00113 {0x06010001, "Attempt to read a write-only object"},
00114 {0x06010002, "Attempt to write a read-only object"},
00115 {0x06020000, "This object does not exist in the object directory"},
00116 {0x06040041, "The object cannot be mapped into the PDO"},
00117 {0x06040042, "The number and length of the objects to be mapped would"
00118 " exceed the PDO length"},
00119 {0x06040043, "General parameter incompatibility reason"},
00120 {0x06040047, "Gerneral internal incompatibility in device"},
00121 {0x06060000, "Access failure due to a hardware error"},
00122 {0x06070010, "Data type does not match, length of service parameter does"
00123 " not match"},
00124 {0x06070012, "Data type does not match, length of service parameter too"
00125 " high"},
00126 {0x06070013, "Data type does not match, length of service parameter too"
00127 " low"},
00128 {0x06090011, "Subindex does not exist"},
00129 {0x06090030, "Value range of parameter exceeded"},
00130 {0x06090031, "Value of parameter written too high"},
00131 {0x06090032, "Value of parameter written too low"},
00132 {0x06090036, "Maximum value is less than minimum value"},
00133 {0x08000000, "General error"},
00134 {0x08000020, "Data cannot be transferred or stored to the application"},
00135 {0x08000021, "Data cannot be transferred or stored to the application"
00136 " because of local control"},
00137 {0x08000022, "Data cannot be transferred or stored to the application"
00138 " because of the present device state"},
00139 {0x08000023, "Object dictionary dynamic generation fails or no object"
00140 " dictionary is present"},
00141 {}
00142 };
00143
00144
00145
00148 void ec_canopen_abort_msg(
00149 const ec_slave_t *slave,
00150 uint32_t abort_code
00151 )
00152 {
00153 const ec_code_msg_t *abort_msg;
00154
00155 for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) {
00156 if (abort_msg->code == abort_code) {
00157 EC_SLAVE_ERR(slave, "SDO abort message 0x%08X: \"%s\".\n",
00158 abort_msg->code, abort_msg->message);
00159 return;
00160 }
00161 }
00162
00163 EC_SLAVE_ERR(slave, "Unknown SDO abort code 0x%08X.\n", abort_code);
00164 }
00165
00166
00167
00170 void ec_fsm_coe_init(
00171 ec_fsm_coe_t *fsm
00172 )
00173 {
00174 fsm->state = NULL;
00175 fsm->datagram = NULL;
00176 }
00177
00178
00179
00182 void ec_fsm_coe_clear(
00183 ec_fsm_coe_t *fsm
00184 )
00185 {
00186 }
00187
00188
00189
00192 void ec_fsm_coe_dictionary(
00193 ec_fsm_coe_t *fsm,
00194 ec_slave_t *slave
00195 )
00196 {
00197 fsm->slave = slave;
00198 fsm->state = ec_fsm_coe_dict_start;
00199 }
00200
00201
00202
00205 void ec_fsm_coe_transfer(
00206 ec_fsm_coe_t *fsm,
00207 ec_slave_t *slave,
00208 ec_sdo_request_t *request
00209 )
00210 {
00211 fsm->slave = slave;
00212 fsm->request = request;
00213
00214 if (request->dir == EC_DIR_OUTPUT) {
00215 fsm->state = ec_fsm_coe_down_start;
00216 }
00217 else {
00218 fsm->state = ec_fsm_coe_up_start;
00219 }
00220 }
00221
00222
00223
00228 int ec_fsm_coe_exec(
00229 ec_fsm_coe_t *fsm,
00230 ec_datagram_t *datagram
00231 )
00232 {
00233 int datagram_used = 0;
00234
00235 if (fsm->datagram &&
00236 (fsm->datagram->state == EC_DATAGRAM_INIT ||
00237 fsm->datagram->state == EC_DATAGRAM_QUEUED ||
00238 fsm->datagram->state == EC_DATAGRAM_SENT)) {
00239
00240 return datagram_used;
00241 }
00242
00243 fsm->state(fsm, datagram);
00244
00245 datagram_used =
00246 fsm->state != ec_fsm_coe_end && fsm->state != ec_fsm_coe_error;
00247
00248 if (datagram_used) {
00249 fsm->datagram = datagram;
00250 } else {
00251 fsm->datagram = NULL;
00252 }
00253
00254 return datagram_used;
00255 }
00256
00257
00258
00262 int ec_fsm_coe_success(
00263 const ec_fsm_coe_t *fsm
00264 )
00265 {
00266 return fsm->state == ec_fsm_coe_end;
00267 }
00268
00269
00270
00277 int ec_fsm_coe_check_emergency(
00278 ec_fsm_coe_t *fsm,
00279 const uint8_t *data,
00280 size_t size
00281 )
00282 {
00283 if (size < 2 || ((EC_READ_U16(data) >> 12) & 0x0F) != 0x01)
00284 return 0;
00285
00286 if (size < 10) {
00287 EC_SLAVE_WARN(fsm->slave, "Received incomplete CoE Emergency"
00288 " request:\n");
00289 ec_print_data(data, size);
00290 return 1;
00291 }
00292
00293 {
00294 ec_slave_config_t *sc = fsm->slave->config;
00295 if (sc) {
00296 ec_coe_emerg_ring_push(&sc->emerg_ring, data + 2);
00297 }
00298 }
00299
00300 EC_SLAVE_WARN(fsm->slave, "CoE Emergency Request received:\n"
00301 "Error code 0x%04X, Error register 0x%02X, data:\n",
00302 EC_READ_U16(data + 2), EC_READ_U8(data + 4));
00303 ec_print_data(data + 5, 5);
00304 return 1;
00305 }
00306
00307
00308
00309
00310
00315 int ec_fsm_coe_prepare_dict(
00316 ec_fsm_coe_t *fsm,
00317 ec_datagram_t *datagram
00318 )
00319 {
00320 ec_slave_t *slave = fsm->slave;
00321 uint8_t *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8);
00322 if (IS_ERR(data)) {
00323 return PTR_ERR(data);
00324 }
00325
00326 EC_WRITE_U16(data, 0x8 << 12);
00327 EC_WRITE_U8 (data + 2, 0x01);
00328 EC_WRITE_U8 (data + 3, 0x00);
00329 EC_WRITE_U16(data + 4, 0x0000);
00330 EC_WRITE_U16(data + 6, 0x0001);
00331
00332 fsm->state = ec_fsm_coe_dict_request;
00333 return 0;
00334 }
00335
00336
00337
00340 void ec_fsm_coe_dict_start(
00341 ec_fsm_coe_t *fsm,
00342 ec_datagram_t *datagram
00343 )
00344 {
00345 ec_slave_t *slave = fsm->slave;
00346
00347 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
00348 EC_SLAVE_ERR(slave, "Slave does not support CoE!\n");
00349 fsm->state = ec_fsm_coe_error;
00350 return;
00351 }
00352
00353 if (slave->sii.has_general && !slave->sii.coe_details.enable_sdo_info) {
00354 EC_SLAVE_ERR(slave, "Slave does not support"
00355 " SDO information service!\n");
00356 fsm->state = ec_fsm_coe_error;
00357 return;
00358 }
00359
00360 fsm->retries = EC_FSM_RETRIES;
00361
00362 if (ec_fsm_coe_prepare_dict(fsm, datagram)) {
00363 fsm->state = ec_fsm_coe_error;
00364 }
00365 }
00366
00367
00368
00372 void ec_fsm_coe_dict_request(
00373 ec_fsm_coe_t *fsm,
00374 ec_datagram_t *datagram
00375 )
00376 {
00377 ec_slave_t *slave = fsm->slave;
00378
00379 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00380 if (ec_fsm_coe_prepare_dict(fsm, datagram)) {
00381 fsm->state = ec_fsm_coe_error;
00382 }
00383 return;
00384 }
00385
00386 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00387 fsm->state = ec_fsm_coe_error;
00388 EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary"
00389 " request datagram: ");
00390 ec_datagram_print_state(fsm->datagram);
00391 return;
00392 }
00393
00394 if (fsm->datagram->working_counter != 1) {
00395 fsm->state = ec_fsm_coe_error;
00396 EC_SLAVE_ERR(slave, "Reception of CoE dictionary request failed: ");
00397 ec_datagram_print_wc_error(fsm->datagram);
00398 return;
00399 }
00400
00401 fsm->jiffies_start = fsm->datagram->jiffies_sent;
00402
00403 ec_slave_mbox_prepare_check(slave, datagram);
00404 fsm->retries = EC_FSM_RETRIES;
00405 fsm->state = ec_fsm_coe_dict_check;
00406 }
00407
00408
00409
00412 void ec_fsm_coe_dict_check(
00413 ec_fsm_coe_t *fsm,
00414 ec_datagram_t *datagram
00415 )
00416 {
00417 ec_slave_t *slave = fsm->slave;
00418
00419 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00420 ec_slave_mbox_prepare_check(slave, datagram);
00421 return;
00422 }
00423
00424 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00425 fsm->state = ec_fsm_coe_error;
00426 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: ");
00427 ec_datagram_print_state(fsm->datagram);
00428 return;
00429 }
00430
00431 if (fsm->datagram->working_counter != 1) {
00432 fsm->state = ec_fsm_coe_error;
00433 EC_SLAVE_ERR(slave,"Reception of CoE mailbox check"
00434 " datagram failed: ");
00435 ec_datagram_print_wc_error(fsm->datagram);
00436 return;
00437 }
00438
00439 if (!ec_slave_mbox_check(fsm->datagram)) {
00440 unsigned long diff_ms =
00441 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
00442 1000 / HZ;
00443 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) {
00444 fsm->state = ec_fsm_coe_error;
00445 EC_SLAVE_ERR(slave, "Timeout while waiting for"
00446 " SDO dictionary list response.\n");
00447 return;
00448 }
00449
00450 ec_slave_mbox_prepare_check(slave, datagram);
00451 fsm->retries = EC_FSM_RETRIES;
00452 return;
00453 }
00454
00455
00456 ec_slave_mbox_prepare_fetch(slave, datagram);
00457 fsm->retries = EC_FSM_RETRIES;
00458 fsm->state = ec_fsm_coe_dict_response;
00459 }
00460
00461
00462
00467 int ec_fsm_coe_dict_prepare_desc(
00468 ec_fsm_coe_t *fsm,
00469 ec_datagram_t *datagram
00470 )
00471 {
00472 ec_slave_t *slave = fsm->slave;
00473 u8 *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8);
00474 if (IS_ERR(data)) {
00475 return PTR_ERR(data);
00476 }
00477
00478 EC_WRITE_U16(data, 0x8 << 12);
00479 EC_WRITE_U8 (data + 2, 0x03);
00480 EC_WRITE_U8 (data + 3, 0x00);
00481 EC_WRITE_U16(data + 4, 0x0000);
00482 EC_WRITE_U16(data + 6, fsm->sdo->index);
00483
00484 fsm->state = ec_fsm_coe_dict_desc_request;
00485 return 0;
00486 }
00487
00488
00489
00495 void ec_fsm_coe_dict_response(
00496 ec_fsm_coe_t *fsm,
00497 ec_datagram_t *datagram
00498 )
00499 {
00500 ec_slave_t *slave = fsm->slave;
00501 uint8_t *data, mbox_prot;
00502 size_t rec_size;
00503 unsigned int sdo_count, i;
00504 uint16_t sdo_index, fragments_left;
00505 ec_sdo_t *sdo;
00506 bool first_segment;
00507 size_t index_list_offset;
00508
00509 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00510 ec_slave_mbox_prepare_fetch(slave, datagram);
00511 return;
00512 }
00513
00514 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00515 fsm->state = ec_fsm_coe_error;
00516 EC_SLAVE_ERR(slave, "Failed to receive CoE dictionary"
00517 " response datagram: ");
00518 ec_datagram_print_state(fsm->datagram);
00519 return;
00520 }
00521
00522 if (fsm->datagram->working_counter != 1) {
00523 fsm->state = ec_fsm_coe_error;
00524 EC_SLAVE_ERR(slave, "Reception of CoE dictionary response failed: ");
00525 ec_datagram_print_wc_error(fsm->datagram);
00526 return;
00527 }
00528
00529 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
00530 if (IS_ERR(data)) {
00531 fsm->state = ec_fsm_coe_error;
00532 return;
00533 }
00534
00535 if (mbox_prot != 0x03) {
00536 EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
00537 mbox_prot);
00538 fsm->state = ec_fsm_coe_error;
00539 return;
00540 }
00541
00542 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
00543
00544 ec_slave_mbox_prepare_check(slave, datagram);
00545 fsm->retries = EC_FSM_RETRIES;
00546 fsm->state = ec_fsm_coe_dict_check;
00547 return;
00548 }
00549
00550 if (rec_size < 3) {
00551 EC_SLAVE_ERR(slave, "Received corrupted SDO dictionary response"
00552 " (size %zu).\n", rec_size);
00553 fsm->state = ec_fsm_coe_error;
00554 return;
00555 }
00556
00557 if (EC_READ_U16(data) >> 12 == 0x8 &&
00558 (EC_READ_U8(data + 2) & 0x7F) == 0x07) {
00559 EC_SLAVE_ERR(slave, "SDO information error response!\n");
00560 if (rec_size < 10) {
00561 EC_SLAVE_ERR(slave, "Incomplete SDO information"
00562 " error response:\n");
00563 ec_print_data(data, rec_size);
00564 } else {
00565 ec_canopen_abort_msg(slave, EC_READ_U32(data + 6));
00566 }
00567 fsm->state = ec_fsm_coe_error;
00568 return;
00569 }
00570
00571 if (EC_READ_U16(data) >> 12 != 0x8 ||
00572 (EC_READ_U8 (data + 2) & 0x7F) != 0x02) {
00573 if (fsm->slave->master->debug_level) {
00574 EC_SLAVE_DBG(slave, 1, "Invalid SDO list response!"
00575 " Retrying...\n");
00576 ec_print_data(data, rec_size);
00577 }
00578 ec_slave_mbox_prepare_check(slave, datagram);
00579 fsm->retries = EC_FSM_RETRIES;
00580 fsm->state = ec_fsm_coe_dict_check;
00581 return;
00582 }
00583
00584 first_segment = list_empty(&slave->sdo_dictionary) ? true : false;
00585 index_list_offset = first_segment ? 8 : 6;
00586
00587 if (rec_size < index_list_offset || rec_size % 2) {
00588 EC_SLAVE_ERR(slave, "Invalid data size %zu!\n", rec_size);
00589 ec_print_data(data, rec_size);
00590 fsm->state = ec_fsm_coe_error;
00591 return;
00592 }
00593
00594 sdo_count = (rec_size - index_list_offset) / 2;
00595
00596 for (i = 0; i < sdo_count; i++) {
00597 sdo_index = EC_READ_U16(data + index_list_offset + i * 2);
00598 if (!sdo_index) {
00599 EC_SLAVE_DBG(slave, 1, "SDO dictionary contains index 0x0000.\n");
00600 continue;
00601 }
00602
00603 if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) {
00604 EC_SLAVE_ERR(slave, "Failed to allocate memory for SDO!\n");
00605 fsm->state = ec_fsm_coe_error;
00606 return;
00607 }
00608
00609 ec_sdo_init(sdo, slave, sdo_index);
00610 list_add_tail(&sdo->list, &slave->sdo_dictionary);
00611 }
00612
00613 fragments_left = EC_READ_U16(data + 4);
00614 if (fragments_left) {
00615 EC_SLAVE_DBG(slave, 1, "SDO list fragments left: %u\n",
00616 fragments_left);
00617 }
00618
00619 if (EC_READ_U8(data + 2) & 0x80 || fragments_left) {
00620
00621 fsm->jiffies_start = fsm->datagram->jiffies_sent;
00622 ec_slave_mbox_prepare_check(slave, datagram);
00623 fsm->retries = EC_FSM_RETRIES;
00624 fsm->state = ec_fsm_coe_dict_check;
00625 return;
00626 }
00627
00628 if (list_empty(&slave->sdo_dictionary)) {
00629
00630 fsm->state = ec_fsm_coe_end;
00631 return;
00632 }
00633
00634
00635 fsm->sdo = list_entry(slave->sdo_dictionary.next, ec_sdo_t, list);
00636
00637 fsm->retries = EC_FSM_RETRIES;
00638 if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) {
00639 fsm->state = ec_fsm_coe_error;
00640 }
00641 }
00642
00643
00644
00650 void ec_fsm_coe_dict_desc_request(
00651 ec_fsm_coe_t *fsm,
00652 ec_datagram_t *datagram
00653 )
00654 {
00655 ec_slave_t *slave = fsm->slave;
00656
00657 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00658 if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) {
00659 fsm->state = ec_fsm_coe_error;
00660 }
00661 return;
00662 }
00663
00664 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00665 fsm->state = ec_fsm_coe_error;
00666 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO"
00667 " description request datagram: ");
00668 ec_datagram_print_state(fsm->datagram);
00669 return;
00670 }
00671
00672 if (fsm->datagram->working_counter != 1) {
00673 fsm->state = ec_fsm_coe_error;
00674 EC_SLAVE_ERR(slave, "Reception of CoE SDO description"
00675 " request failed: ");
00676 ec_datagram_print_wc_error(fsm->datagram);
00677 return;
00678 }
00679
00680 fsm->jiffies_start = fsm->datagram->jiffies_sent;
00681
00682 ec_slave_mbox_prepare_check(slave, datagram);
00683 fsm->retries = EC_FSM_RETRIES;
00684 fsm->state = ec_fsm_coe_dict_desc_check;
00685 }
00686
00687
00688
00693 void ec_fsm_coe_dict_desc_check(
00694 ec_fsm_coe_t *fsm,
00695 ec_datagram_t *datagram
00696 )
00697 {
00698 ec_slave_t *slave = fsm->slave;
00699
00700 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00701 ec_slave_mbox_prepare_check(slave, datagram);
00702 return;
00703 }
00704
00705 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00706 fsm->state = ec_fsm_coe_error;
00707 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: ");
00708 ec_datagram_print_state(fsm->datagram);
00709 return;
00710 }
00711
00712 if (fsm->datagram->working_counter != 1) {
00713 fsm->state = ec_fsm_coe_error;
00714 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check"
00715 " datagram failed: ");
00716 ec_datagram_print_wc_error(fsm->datagram);
00717 return;
00718 }
00719
00720 if (!ec_slave_mbox_check(fsm->datagram)) {
00721 unsigned long diff_ms =
00722 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
00723 1000 / HZ;
00724 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) {
00725 fsm->state = ec_fsm_coe_error;
00726 EC_SLAVE_ERR(slave, "Timeout while waiting for"
00727 " SDO 0x%04x object description response.\n",
00728 fsm->sdo->index);
00729 return;
00730 }
00731
00732 ec_slave_mbox_prepare_check(slave, datagram);
00733 fsm->retries = EC_FSM_RETRIES;
00734 return;
00735 }
00736
00737
00738 ec_slave_mbox_prepare_fetch(slave, datagram);
00739 fsm->retries = EC_FSM_RETRIES;
00740 fsm->state = ec_fsm_coe_dict_desc_response;
00741 }
00742
00743
00744
00749 int ec_fsm_coe_dict_prepare_entry(
00750 ec_fsm_coe_t *fsm,
00751 ec_datagram_t *datagram
00752 )
00753 {
00754 ec_slave_t *slave = fsm->slave;
00755 u8 *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10);
00756 if (IS_ERR(data)) {
00757 return PTR_ERR(data);
00758 }
00759
00760 EC_WRITE_U16(data, 0x8 << 12);
00761 EC_WRITE_U8 (data + 2, 0x05);
00762 EC_WRITE_U8 (data + 3, 0x00);
00763 EC_WRITE_U16(data + 4, 0x0000);
00764 EC_WRITE_U16(data + 6, fsm->sdo->index);
00765 EC_WRITE_U8 (data + 8, fsm->subindex);
00766 EC_WRITE_U8 (data + 9, 0x01);
00767
00768 fsm->state = ec_fsm_coe_dict_entry_request;
00769 return 0;
00770 }
00771
00772
00773
00779 void ec_fsm_coe_dict_desc_response(
00780 ec_fsm_coe_t *fsm,
00781 ec_datagram_t *datagram
00782 )
00783 {
00784 ec_slave_t *slave = fsm->slave;
00785 ec_sdo_t *sdo = fsm->sdo;
00786 uint8_t *data, mbox_prot;
00787 size_t rec_size, name_size;
00788
00789 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00790 ec_slave_mbox_prepare_fetch(slave, datagram);
00791 return;
00792 }
00793
00794 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00795 fsm->state = ec_fsm_coe_error;
00796 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO description"
00797 " response datagram: ");
00798 ec_datagram_print_state(fsm->datagram);
00799 return;
00800 }
00801
00802 if (fsm->datagram->working_counter != 1) {
00803 fsm->state = ec_fsm_coe_error;
00804 EC_SLAVE_ERR(slave, "Reception of CoE SDO description"
00805 " response failed: ");
00806 ec_datagram_print_wc_error(fsm->datagram);
00807 return;
00808 }
00809
00810 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
00811 if (IS_ERR(data)) {
00812 fsm->state = ec_fsm_coe_error;
00813 return;
00814 }
00815
00816 if (mbox_prot != 0x03) {
00817 EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
00818 mbox_prot);
00819 fsm->state = ec_fsm_coe_error;
00820 return;
00821 }
00822
00823 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
00824
00825 ec_slave_mbox_prepare_check(slave, datagram);
00826 fsm->retries = EC_FSM_RETRIES;
00827 fsm->state = ec_fsm_coe_dict_desc_check;
00828 return;
00829 }
00830
00831 if (rec_size < 3) {
00832 EC_SLAVE_ERR(slave, "Received corrupted SDO description response"
00833 " (size %zu).\n", rec_size);
00834 fsm->state = ec_fsm_coe_error;
00835 return;
00836 }
00837
00838 if (EC_READ_U16(data) >> 12 == 0x8 &&
00839 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) {
00840 EC_SLAVE_ERR(slave, "SDO information error response while"
00841 " fetching SDO 0x%04X!\n", sdo->index);
00842 ec_canopen_abort_msg(slave, EC_READ_U32(data + 6));
00843 fsm->state = ec_fsm_coe_error;
00844 return;
00845 }
00846
00847 if (rec_size < 8) {
00848 EC_SLAVE_ERR(slave, "Received corrupted SDO"
00849 " description response (size %zu).\n", rec_size);
00850 fsm->state = ec_fsm_coe_error;
00851 return;
00852 }
00853
00854 if (EC_READ_U16(data) >> 12 != 0x8 ||
00855 (EC_READ_U8 (data + 2) & 0x7F) != 0x04 ||
00856 EC_READ_U16(data + 6) != sdo->index) {
00857 if (fsm->slave->master->debug_level) {
00858 EC_SLAVE_DBG(slave, 1, "Invalid object description response while"
00859 " fetching SDO 0x%04X!\n", sdo->index);
00860 ec_print_data(data, rec_size);
00861 }
00862
00863 ec_slave_mbox_prepare_check(slave, datagram);
00864 fsm->retries = EC_FSM_RETRIES;
00865 fsm->state = ec_fsm_coe_dict_desc_check;
00866 return;
00867 }
00868
00869 if (rec_size < 12) {
00870 EC_SLAVE_ERR(slave, "Invalid data size!\n");
00871 ec_print_data(data, rec_size);
00872 fsm->state = ec_fsm_coe_error;
00873 return;
00874 }
00875
00876 sdo->max_subindex = EC_READ_U8(data + 10);
00877 sdo->object_code = EC_READ_U8(data + 11);
00878
00879 name_size = rec_size - 12;
00880 if (name_size) {
00881 if (!(sdo->name = kmalloc(name_size + 1, GFP_KERNEL))) {
00882 EC_SLAVE_ERR(slave, "Failed to allocate SDO name!\n");
00883 fsm->state = ec_fsm_coe_error;
00884 return;
00885 }
00886
00887 memcpy(sdo->name, data + 12, name_size);
00888 sdo->name[name_size] = 0;
00889 }
00890
00891 if (EC_READ_U8(data + 2) & 0x80) {
00892 EC_SLAVE_ERR(slave, "Fragment follows (not implemented)!\n");
00893 fsm->state = ec_fsm_coe_error;
00894 return;
00895 }
00896
00897
00898
00899 fsm->subindex = 0;
00900 fsm->retries = EC_FSM_RETRIES;
00901
00902 if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) {
00903 fsm->state = ec_fsm_coe_error;
00904 }
00905 }
00906
00907
00908
00914 void ec_fsm_coe_dict_entry_request(
00915 ec_fsm_coe_t *fsm,
00916 ec_datagram_t *datagram
00917 )
00918 {
00919 ec_slave_t *slave = fsm->slave;
00920
00921 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00922 if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) {
00923 fsm->state = ec_fsm_coe_error;
00924 }
00925 return;
00926 }
00927
00928 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00929 fsm->state = ec_fsm_coe_error;
00930 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO entry"
00931 " request datagram: ");
00932 ec_datagram_print_state(fsm->datagram);
00933 return;
00934 }
00935
00936 if (fsm->datagram->working_counter != 1) {
00937 fsm->state = ec_fsm_coe_error;
00938 EC_SLAVE_ERR(slave, "Reception of CoE SDO entry request failed: ");
00939 ec_datagram_print_wc_error(fsm->datagram);
00940 return;
00941 }
00942
00943 fsm->jiffies_start = fsm->datagram->jiffies_sent;
00944
00945 ec_slave_mbox_prepare_check(slave, datagram);
00946 fsm->retries = EC_FSM_RETRIES;
00947 fsm->state = ec_fsm_coe_dict_entry_check;
00948 }
00949
00950
00951
00956 void ec_fsm_coe_dict_entry_check(
00957 ec_fsm_coe_t *fsm,
00958 ec_datagram_t *datagram
00959 )
00960 {
00961 ec_slave_t *slave = fsm->slave;
00962
00963 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
00964 ec_slave_mbox_prepare_check(slave, datagram);
00965 return;
00966 }
00967
00968 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
00969 fsm->state = ec_fsm_coe_error;
00970 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: ");
00971 ec_datagram_print_state(fsm->datagram);
00972 return;
00973 }
00974
00975 if (fsm->datagram->working_counter != 1) {
00976 fsm->state = ec_fsm_coe_error;
00977 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check"
00978 " datagram failed: ");
00979 ec_datagram_print_wc_error(fsm->datagram);
00980 return;
00981 }
00982
00983 if (!ec_slave_mbox_check(fsm->datagram)) {
00984 unsigned long diff_ms =
00985 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
00986 1000 / HZ;
00987 if (diff_ms >= EC_FSM_COE_DICT_TIMEOUT) {
00988 fsm->state = ec_fsm_coe_error;
00989 EC_SLAVE_ERR(slave, "Timeout while waiting for"
00990 " SDO entry 0x%04x:%x description response.\n",
00991 fsm->sdo->index, fsm->subindex);
00992 return;
00993 }
00994
00995 ec_slave_mbox_prepare_check(slave, datagram);
00996 fsm->retries = EC_FSM_RETRIES;
00997 return;
00998 }
00999
01000
01001 ec_slave_mbox_prepare_fetch(slave, datagram);
01002 fsm->retries = EC_FSM_RETRIES;
01003 fsm->state = ec_fsm_coe_dict_entry_response;
01004 }
01005
01006
01007
01013 void ec_fsm_coe_dict_entry_response(
01014 ec_fsm_coe_t *fsm,
01015 ec_datagram_t *datagram
01016 )
01017 {
01018 ec_slave_t *slave = fsm->slave;
01019 ec_sdo_t *sdo = fsm->sdo;
01020 uint8_t *data, mbox_prot;
01021 size_t rec_size, data_size;
01022 ec_sdo_entry_t *entry;
01023 u16 word;
01024
01025 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01026 ec_slave_mbox_prepare_fetch(slave, datagram);
01027 return;
01028 }
01029
01030 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01031 fsm->state = ec_fsm_coe_error;
01032 EC_SLAVE_ERR(slave, "Failed to receive CoE SDO"
01033 " description response datagram: ");
01034 ec_datagram_print_state(fsm->datagram);
01035 return;
01036 }
01037
01038 if (fsm->datagram->working_counter != 1) {
01039 fsm->state = ec_fsm_coe_error;
01040 EC_SLAVE_ERR(slave, "Reception of CoE SDO description"
01041 " response failed: ");
01042 ec_datagram_print_wc_error(fsm->datagram);
01043 return;
01044 }
01045
01046 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
01047 if (IS_ERR(data)) {
01048 fsm->state = ec_fsm_coe_error;
01049 return;
01050 }
01051
01052 if (mbox_prot != 0x03) {
01053 EC_SLAVE_ERR(slave, "Received mailbox protocol"
01054 " 0x%02X as response.\n", mbox_prot);
01055 fsm->state = ec_fsm_coe_error;
01056 return;
01057 }
01058
01059 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
01060
01061 ec_slave_mbox_prepare_check(slave, datagram);
01062 fsm->retries = EC_FSM_RETRIES;
01063 fsm->state = ec_fsm_coe_dict_entry_check;
01064 return;
01065 }
01066
01067 if (rec_size < 3) {
01068 EC_SLAVE_ERR(slave, "Received corrupted SDO entry"
01069 " description response (size %zu).\n", rec_size);
01070 fsm->state = ec_fsm_coe_error;
01071 return;
01072 }
01073
01074 if (EC_READ_U16(data) >> 12 == 0x8 &&
01075 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) {
01076 EC_SLAVE_WARN(slave, "SDO information error response while"
01077 " fetching SDO entry 0x%04X:%02X!\n",
01078 sdo->index, fsm->subindex);
01079 ec_canopen_abort_msg(slave, EC_READ_U32(data + 6));
01080
01081
01082
01083
01084 } else {
01085
01086 if (rec_size < 9) {
01087 EC_SLAVE_ERR(slave, "Received corrupted SDO entry"
01088 " description response (size %zu).\n", rec_size);
01089 fsm->state = ec_fsm_coe_error;
01090 return;
01091 }
01092
01093 if (EC_READ_U16(data) >> 12 != 0x8 ||
01094 (EC_READ_U8(data + 2) & 0x7F) != 0x06 ||
01095 EC_READ_U16(data + 6) != sdo->index ||
01096 EC_READ_U8(data + 8) != fsm->subindex) {
01097 if (fsm->slave->master->debug_level) {
01098 EC_SLAVE_DBG(slave, 1, "Invalid entry description response"
01099 " while fetching SDO entry 0x%04X:%02X!\n",
01100 sdo->index, fsm->subindex);
01101 ec_print_data(data, rec_size);
01102 }
01103
01104 ec_slave_mbox_prepare_check(slave, datagram);
01105 fsm->retries = EC_FSM_RETRIES;
01106 fsm->state = ec_fsm_coe_dict_entry_check;
01107 return;
01108 }
01109
01110 if (rec_size < 16) {
01111 EC_SLAVE_ERR(slave, "Invalid data size %zu!\n", rec_size);
01112 ec_print_data(data, rec_size);
01113 fsm->state = ec_fsm_coe_error;
01114 return;
01115 }
01116
01117 data_size = rec_size - 16;
01118
01119 if (!(entry = (ec_sdo_entry_t *)
01120 kmalloc(sizeof(ec_sdo_entry_t), GFP_KERNEL))) {
01121 EC_SLAVE_ERR(slave, "Failed to allocate entry!\n");
01122 fsm->state = ec_fsm_coe_error;
01123 return;
01124 }
01125
01126 ec_sdo_entry_init(entry, sdo, fsm->subindex);
01127 entry->data_type = EC_READ_U16(data + 10);
01128 entry->bit_length = EC_READ_U16(data + 12);
01129
01130
01131 word = EC_READ_U16(data + 14);
01132 entry->read_access[EC_SDO_ENTRY_ACCESS_PREOP] = word & 0x0001;
01133 entry->read_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
01134 (word >> 1) & 0x0001;
01135 entry->read_access[EC_SDO_ENTRY_ACCESS_OP] = (word >> 2) & 0x0001;
01136 entry->write_access[EC_SDO_ENTRY_ACCESS_PREOP] = (word >> 3) & 0x0001;
01137 entry->write_access[EC_SDO_ENTRY_ACCESS_SAFEOP] =
01138 (word >> 4) & 0x0001;
01139 entry->write_access[EC_SDO_ENTRY_ACCESS_OP] = (word >> 5) & 0x0001;
01140
01141 if (data_size) {
01142 uint8_t *desc;
01143 if (!(desc = kmalloc(data_size + 1, GFP_KERNEL))) {
01144 EC_SLAVE_ERR(slave, "Failed to allocate SDO entry name!\n");
01145 fsm->state = ec_fsm_coe_error;
01146 return;
01147 }
01148 memcpy(desc, data + 16, data_size);
01149 desc[data_size] = 0;
01150 entry->description = desc;
01151 }
01152
01153 list_add_tail(&entry->list, &sdo->entries);
01154 }
01155
01156 if (fsm->subindex < sdo->max_subindex) {
01157
01158 fsm->subindex++;
01159 fsm->retries = EC_FSM_RETRIES;
01160
01161 if (ec_fsm_coe_dict_prepare_entry(fsm, datagram)) {
01162 fsm->state = ec_fsm_coe_error;
01163 }
01164
01165 return;
01166 }
01167
01168
01169 if (fsm->sdo->list.next != &slave->sdo_dictionary) {
01170
01171 fsm->sdo = list_entry(fsm->sdo->list.next, ec_sdo_t, list);
01172 fsm->retries = EC_FSM_RETRIES;
01173
01174 if (ec_fsm_coe_dict_prepare_desc(fsm, datagram)) {
01175 fsm->state = ec_fsm_coe_error;
01176 }
01177
01178 return;
01179 }
01180
01181 fsm->state = ec_fsm_coe_end;
01182 }
01183
01184
01185
01186
01187
01192 int ec_fsm_coe_prepare_down_start(
01193 ec_fsm_coe_t *fsm,
01194 ec_datagram_t *datagram
01195 )
01196 {
01197 u8 *data;
01198 ec_slave_t *slave = fsm->slave;
01199 ec_sdo_request_t *request = fsm->request;
01200 uint8_t data_set_size;
01201
01202 if (request->data_size <= 4) {
01203 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
01204 EC_COE_DOWN_REQ_HEADER_SIZE);
01205 if (IS_ERR(data)) {
01206 request->errno = PTR_ERR(data);
01207 return PTR_ERR(data);
01208 }
01209
01210 fsm->remaining = 0;
01211
01212 data_set_size = 4 - request->data_size;
01213
01214 EC_WRITE_U16(data, 0x2 << 12);
01215 EC_WRITE_U8 (data + 2, (0x3
01216 | data_set_size << 2
01217 | ((request->complete_access ? 1 : 0) << 4)
01218 | 0x1 << 5));
01219 EC_WRITE_U16(data + 3, request->index);
01220 EC_WRITE_U8 (data + 5,
01221 request->complete_access ? 0x00 : request->subindex);
01222 memcpy(data + 6, request->data, request->data_size);
01223 memset(data + 6 + request->data_size, 0x00, 4 - request->data_size);
01224
01225 if (slave->master->debug_level) {
01226 EC_SLAVE_DBG(slave, 1, "Expedited download request:\n");
01227 ec_print_data(data, EC_COE_DOWN_REQ_HEADER_SIZE);
01228 }
01229 }
01230 else {
01231 size_t data_size,
01232 max_data_size =
01233 slave->configured_rx_mailbox_size - EC_MBOX_HEADER_SIZE,
01234 required_data_size =
01235 EC_COE_DOWN_REQ_HEADER_SIZE + request->data_size;
01236
01237 if (max_data_size < required_data_size) {
01238
01239 data_size = max_data_size;
01240 } else {
01241 data_size = required_data_size;
01242 }
01243
01244 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
01245 data_size);
01246 if (IS_ERR(data)) {
01247 request->errno = PTR_ERR(data);
01248 return PTR_ERR(data);
01249 }
01250
01251 fsm->offset = 0;
01252 fsm->remaining = request->data_size;
01253
01254 EC_WRITE_U16(data, 0x2 << 12);
01255 EC_WRITE_U8(data + 2,
01256 0x1
01257 | ((request->complete_access ? 1 : 0) << 4)
01258 | 0x1 << 5);
01259 EC_WRITE_U16(data + 3, request->index);
01260 EC_WRITE_U8 (data + 5,
01261 request->complete_access ? 0x00 : request->subindex);
01262 EC_WRITE_U32(data + 6, request->data_size);
01263
01264 if (data_size > EC_COE_DOWN_REQ_HEADER_SIZE) {
01265 size_t segment_size = data_size - EC_COE_DOWN_REQ_HEADER_SIZE;
01266 memcpy(data + EC_COE_DOWN_REQ_HEADER_SIZE,
01267 request->data, segment_size);
01268 fsm->offset += segment_size;
01269 fsm->remaining -= segment_size;
01270 }
01271
01272 if (slave->master->debug_level) {
01273 EC_SLAVE_DBG(slave, 1, "Normal download request:\n");
01274 ec_print_data(data, data_size);
01275 }
01276 }
01277
01278 fsm->state = ec_fsm_coe_down_request;
01279 return 0;
01280 }
01281
01282
01283
01286 void ec_fsm_coe_down_start(
01287 ec_fsm_coe_t *fsm,
01288 ec_datagram_t *datagram
01289 )
01290 {
01291 ec_slave_t *slave = fsm->slave;
01292 ec_sdo_request_t *request = fsm->request;
01293
01294 if (fsm->slave->master->debug_level) {
01295 char subidxstr[10];
01296 if (request->complete_access) {
01297 subidxstr[0] = 0x00;
01298 } else {
01299 sprintf(subidxstr, ":%02X", request->subindex);
01300 }
01301 EC_SLAVE_DBG(slave, 1, "Downloading SDO 0x%04X%s.\n",
01302 request->index, subidxstr);
01303 ec_print_data(request->data, request->data_size);
01304 }
01305
01306 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
01307 EC_SLAVE_ERR(slave, "Slave does not support CoE!\n");
01308 request->errno = EPROTONOSUPPORT;
01309 fsm->state = ec_fsm_coe_error;
01310 return;
01311 }
01312
01313 if (slave->configured_rx_mailbox_size <
01314 EC_MBOX_HEADER_SIZE + EC_COE_DOWN_REQ_HEADER_SIZE) {
01315 EC_SLAVE_ERR(slave, "Mailbox too small!\n");
01316 request->errno = EOVERFLOW;
01317 fsm->state = ec_fsm_coe_error;
01318 return;
01319 }
01320
01321
01322 fsm->request->jiffies_sent = jiffies;
01323 fsm->retries = EC_FSM_RETRIES;
01324
01325 if (ec_fsm_coe_prepare_down_start(fsm, datagram)) {
01326 fsm->state = ec_fsm_coe_error;
01327 }
01328 }
01329
01330
01331
01337 void ec_fsm_coe_down_request(
01338 ec_fsm_coe_t *fsm,
01339 ec_datagram_t *datagram
01340 )
01341 {
01342 ec_slave_t *slave = fsm->slave;
01343 unsigned long diff_ms;
01344
01345 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01346 if (ec_fsm_coe_prepare_down_start(fsm, datagram)) {
01347 fsm->state = ec_fsm_coe_error;
01348 }
01349 return;
01350 }
01351
01352 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01353 fsm->request->errno = EIO;
01354 fsm->state = ec_fsm_coe_error;
01355 EC_SLAVE_ERR(slave, "Failed to receive CoE download"
01356 " request datagram: ");
01357 ec_datagram_print_state(fsm->datagram);
01358 return;
01359 }
01360
01361 diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
01362
01363 if (fsm->datagram->working_counter != 1) {
01364 if (!fsm->datagram->working_counter) {
01365 if (diff_ms < fsm->request->response_timeout) {
01366 #if DEBUG_RETRIES
01367 EC_SLAVE_DBG(slave, 1, "Slave did not respond to SDO"
01368 " download request. Retrying after %lu ms...\n",
01369 diff_ms);
01370 #endif
01371
01372 if (ec_fsm_coe_prepare_down_start(fsm, datagram)) {
01373 fsm->state = ec_fsm_coe_error;
01374 }
01375 return;
01376 }
01377 }
01378 fsm->request->errno = EIO;
01379 fsm->state = ec_fsm_coe_error;
01380 EC_SLAVE_ERR(slave, "Reception of CoE download request"
01381 " for SDO 0x%04x:%x failed with timeout after %lu ms: ",
01382 fsm->request->index, fsm->request->subindex, diff_ms);
01383 ec_datagram_print_wc_error(fsm->datagram);
01384 return;
01385 }
01386
01387 #if DEBUG_LONG
01388 if (diff_ms > 200) {
01389 EC_SLAVE_WARN(slave, "SDO 0x%04x:%x download took %lu ms.\n",
01390 fsm->request->index, fsm->request->subindex, diff_ms);
01391 }
01392 #endif
01393
01394 fsm->jiffies_start = fsm->datagram->jiffies_sent;
01395
01396 ec_slave_mbox_prepare_check(slave, datagram);
01397 fsm->retries = EC_FSM_RETRIES;
01398 fsm->state = ec_fsm_coe_down_check;
01399 }
01400
01401
01402
01405 void ec_fsm_coe_down_check(
01406 ec_fsm_coe_t *fsm,
01407 ec_datagram_t *datagram
01408 )
01409 {
01410 ec_slave_t *slave = fsm->slave;
01411
01412 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01413 ec_slave_mbox_prepare_check(slave, datagram);
01414 return;
01415 }
01416
01417 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01418 fsm->request->errno = EIO;
01419 fsm->state = ec_fsm_coe_error;
01420 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check"
01421 " datagram: ");
01422 ec_datagram_print_state(fsm->datagram);
01423 return;
01424 }
01425
01426 if (fsm->datagram->working_counter != 1) {
01427 fsm->request->errno = EIO;
01428 fsm->state = ec_fsm_coe_error;
01429 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check"
01430 " datagram failed: ");
01431 ec_datagram_print_wc_error(fsm->datagram);
01432 return;
01433 }
01434
01435 if (!ec_slave_mbox_check(fsm->datagram)) {
01436 unsigned long diff_ms =
01437 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
01438 1000 / HZ;
01439 if (diff_ms >= fsm->request->response_timeout) {
01440 fsm->request->errno = EIO;
01441 fsm->state = ec_fsm_coe_error;
01442 EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting"
01443 " for SDO 0x%04x:%x download response.\n", diff_ms,
01444 fsm->request->index, fsm->request->subindex);
01445 return;
01446 }
01447
01448 ec_slave_mbox_prepare_check(slave, datagram);
01449 fsm->retries = EC_FSM_RETRIES;
01450 return;
01451 }
01452
01453
01454 ec_slave_mbox_prepare_fetch(slave, datagram);
01455 fsm->retries = EC_FSM_RETRIES;
01456 fsm->state = ec_fsm_coe_down_response;
01457 }
01458
01459
01460
01463 void ec_fsm_coe_down_prepare_segment_request(
01464 ec_fsm_coe_t *fsm,
01465 ec_datagram_t *datagram
01466 )
01467 {
01468 ec_slave_t *slave = fsm->slave;
01469 ec_sdo_request_t *request = fsm->request;
01470 size_t max_segment_size =
01471 slave->configured_rx_mailbox_size
01472 - EC_MBOX_HEADER_SIZE
01473 - EC_COE_DOWN_SEG_REQ_HEADER_SIZE;
01474 size_t data_size;
01475 uint8_t last_segment, seg_data_size, *data;
01476
01477 if (fsm->remaining > max_segment_size) {
01478 fsm->segment_size = max_segment_size;
01479 last_segment = 0;
01480 } else {
01481 fsm->segment_size = fsm->remaining;
01482 last_segment = 1;
01483 }
01484
01485 if (fsm->segment_size > EC_COE_DOWN_SEG_MIN_DATA_SIZE) {
01486 seg_data_size = 0x00;
01487 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE + fsm->segment_size;
01488 } else {
01489 seg_data_size = EC_COE_DOWN_SEG_MIN_DATA_SIZE - fsm->segment_size;
01490 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE
01491 + EC_COE_DOWN_SEG_MIN_DATA_SIZE;
01492 }
01493
01494 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
01495 data_size);
01496 if (IS_ERR(data)) {
01497 request->errno = PTR_ERR(data);
01498 fsm->state = ec_fsm_coe_error;
01499 return;
01500 }
01501
01502 EC_WRITE_U16(data, 0x2 << 12);
01503 EC_WRITE_U8(data + 2, (last_segment ? 1 : 0)
01504 | (seg_data_size << 1)
01505 | (fsm->toggle << 4)
01506 | (0x00 << 5));
01507 memcpy(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE,
01508 request->data + fsm->offset, fsm->segment_size);
01509 if (fsm->segment_size < EC_COE_DOWN_SEG_MIN_DATA_SIZE) {
01510 memset(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE + fsm->segment_size,
01511 0x00, EC_COE_DOWN_SEG_MIN_DATA_SIZE - fsm->segment_size);
01512 }
01513
01514 if (slave->master->debug_level) {
01515 EC_SLAVE_DBG(slave, 1, "Download segment request:\n");
01516 ec_print_data(data, data_size);
01517 }
01518
01519 fsm->state = ec_fsm_coe_down_seg_check;
01520 }
01521
01522
01523
01529 void ec_fsm_coe_down_response(
01530 ec_fsm_coe_t *fsm,
01531 ec_datagram_t *datagram
01532 )
01533 {
01534 ec_slave_t *slave = fsm->slave;
01535 uint8_t *data, mbox_prot;
01536 size_t rec_size;
01537 ec_sdo_request_t *request = fsm->request;
01538
01539 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01540 ec_slave_mbox_prepare_fetch(slave, datagram);
01541 return;
01542 }
01543
01544 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01545 request->errno = EIO;
01546 fsm->state = ec_fsm_coe_error;
01547 EC_SLAVE_ERR(slave, "Failed to receive CoE download"
01548 " response datagram: ");
01549 ec_datagram_print_state(fsm->datagram);
01550 return;
01551 }
01552
01553 if (fsm->datagram->working_counter != 1) {
01554 request->errno = EIO;
01555 fsm->state = ec_fsm_coe_error;
01556 EC_SLAVE_ERR(slave, "Reception of CoE download response failed: ");
01557 ec_datagram_print_wc_error(fsm->datagram);
01558 return;
01559 }
01560
01561 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
01562 if (IS_ERR(data)) {
01563 request->errno = PTR_ERR(data);
01564 fsm->state = ec_fsm_coe_error;
01565 return;
01566 }
01567
01568 if (mbox_prot != 0x03) {
01569 request->errno = EIO;
01570 fsm->state = ec_fsm_coe_error;
01571 EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
01572 mbox_prot);
01573 return;
01574 }
01575
01576 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
01577
01578 ec_slave_mbox_prepare_check(slave, datagram);
01579 fsm->retries = EC_FSM_RETRIES;
01580 fsm->state = ec_fsm_coe_down_check;
01581 return;
01582 }
01583
01584 if (slave->master->debug_level) {
01585 EC_SLAVE_DBG(slave, 1, "Download response:\n");
01586 ec_print_data(data, rec_size);
01587 }
01588
01589 if (rec_size < 6) {
01590 request->errno = EIO;
01591 fsm->state = ec_fsm_coe_error;
01592 EC_SLAVE_ERR(slave, "Received data are too small (%zu bytes):\n",
01593 rec_size);
01594 ec_print_data(data, rec_size);
01595 return;
01596 }
01597
01598 if (EC_READ_U16(data) >> 12 == 0x2 &&
01599 EC_READ_U8 (data + 2) >> 5 == 0x4) {
01600 char subidxstr[10];
01601 request->errno = EIO;
01602 fsm->state = ec_fsm_coe_error;
01603 if (request->complete_access) {
01604 subidxstr[0] = 0x00;
01605 } else {
01606 sprintf(subidxstr, ":%02X", request->subindex);
01607 }
01608 EC_SLAVE_ERR(slave, "SDO download 0x%04X%s (%zu bytes) aborted.\n",
01609 request->index, subidxstr, request->data_size);
01610 if (rec_size < 10) {
01611 EC_SLAVE_ERR(slave, "Incomplete abort command:\n");
01612 ec_print_data(data, rec_size);
01613 } else {
01614 fsm->request->abort_code = EC_READ_U32(data + 6);
01615 ec_canopen_abort_msg(slave, fsm->request->abort_code);
01616 }
01617 return;
01618 }
01619
01620 if (EC_READ_U16(data) >> 12 != 0x3 ||
01621 EC_READ_U8 (data + 2) >> 5 != 0x3 ||
01622 EC_READ_U16(data + 3) != request->index ||
01623 EC_READ_U8 (data + 5) != request->subindex) {
01624 if (slave->master->debug_level) {
01625 EC_SLAVE_DBG(slave, 1, "Invalid SDO download response!"
01626 " Retrying...\n");
01627 ec_print_data(data, rec_size);
01628 }
01629
01630 ec_slave_mbox_prepare_check(slave, datagram);
01631 fsm->retries = EC_FSM_RETRIES;
01632 fsm->state = ec_fsm_coe_down_check;
01633 return;
01634 }
01635
01636 if (fsm->remaining) {
01637 fsm->toggle = 0;
01638 ec_fsm_coe_down_prepare_segment_request(fsm, datagram);
01639 } else {
01640 fsm->state = ec_fsm_coe_end;
01641 }
01642 }
01643
01644
01645
01650 void ec_fsm_coe_down_seg_check(
01651 ec_fsm_coe_t *fsm,
01652 ec_datagram_t *datagram
01653 )
01654 {
01655 ec_slave_t *slave = fsm->slave;
01656
01657 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
01658 return;
01659
01660 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01661 fsm->request->errno = EIO;
01662 fsm->state = ec_fsm_coe_error;
01663 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: ");
01664 ec_datagram_print_state(fsm->datagram);
01665 return;
01666 }
01667
01668 if (fsm->datagram->working_counter != 1) {
01669 fsm->request->errno = EIO;
01670 fsm->state = ec_fsm_coe_error;
01671 EC_SLAVE_ERR(slave, "Reception of CoE mailbox segment check"
01672 " datagram failed: ");
01673 ec_datagram_print_wc_error(fsm->datagram);
01674 return;
01675 }
01676
01677 if (!ec_slave_mbox_check(fsm->datagram)) {
01678 unsigned long diff_ms =
01679 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
01680 1000 / HZ;
01681 if (diff_ms >= fsm->request->response_timeout) {
01682 fsm->request->errno = EIO;
01683 fsm->state = ec_fsm_coe_error;
01684 EC_SLAVE_ERR(slave, "Timeout while waiting for SDO download"
01685 " segment response.\n");
01686 return;
01687 }
01688
01689 ec_slave_mbox_prepare_check(slave, datagram);
01690 fsm->retries = EC_FSM_RETRIES;
01691 return;
01692 }
01693
01694
01695 ec_slave_mbox_prepare_fetch(slave, datagram);
01696 fsm->retries = EC_FSM_RETRIES;
01697 fsm->state = ec_fsm_coe_down_seg_response;
01698 }
01699
01700
01701
01707 void ec_fsm_coe_down_seg_response(
01708 ec_fsm_coe_t *fsm,
01709 ec_datagram_t *datagram
01710 )
01711 {
01712 ec_slave_t *slave = fsm->slave;
01713 uint8_t *data, mbox_prot;
01714 size_t rec_size;
01715 ec_sdo_request_t *request = fsm->request;
01716
01717 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01718 ec_slave_mbox_prepare_fetch(slave, datagram);
01719 return;
01720 }
01721
01722 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01723 request->errno = EIO;
01724 fsm->state = ec_fsm_coe_error;
01725 EC_SLAVE_ERR(slave, "Failed to receive CoE download response"
01726 " datagram: ");
01727 ec_datagram_print_state(fsm->datagram);
01728 return;
01729 }
01730
01731 if (fsm->datagram->working_counter != 1) {
01732 request->errno = EIO;
01733 fsm->state = ec_fsm_coe_error;
01734 EC_SLAVE_ERR(slave, "Reception of CoE download response failed: ");
01735 ec_datagram_print_wc_error(fsm->datagram);
01736 return;
01737 }
01738
01739 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
01740 if (IS_ERR(data)) {
01741 request->errno = PTR_ERR(data);
01742 fsm->state = ec_fsm_coe_error;
01743 return;
01744 }
01745
01746 if (mbox_prot != 0x03) {
01747 request->errno = EIO;
01748 fsm->state = ec_fsm_coe_error;
01749 EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
01750 mbox_prot);
01751 return;
01752 }
01753
01754 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
01755
01756 ec_slave_mbox_prepare_check(slave, datagram);
01757 fsm->retries = EC_FSM_RETRIES;
01758 fsm->state = ec_fsm_coe_down_check;
01759 return;
01760 }
01761
01762 if (slave->master->debug_level) {
01763 EC_SLAVE_DBG(slave, 1, "Download response:\n");
01764 ec_print_data(data, rec_size);
01765 }
01766
01767 if (rec_size < 6) {
01768 request->errno = EIO;
01769 fsm->state = ec_fsm_coe_error;
01770 EC_SLAVE_ERR(slave, "Received data are too small (%zu bytes):\n",
01771 rec_size);
01772 ec_print_data(data, rec_size);
01773 return;
01774 }
01775
01776 if (EC_READ_U16(data) >> 12 == 0x2 &&
01777 EC_READ_U8 (data + 2) >> 5 == 0x4) {
01778 char subidxstr[10];
01779 request->errno = EIO;
01780 fsm->state = ec_fsm_coe_error;
01781 if (request->complete_access) {
01782 subidxstr[0] = 0x00;
01783 } else {
01784 sprintf(subidxstr, ":%02X", request->subindex);
01785 }
01786 EC_SLAVE_ERR(slave, "SDO download 0x%04X%s (%zu bytes) aborted.\n",
01787 request->index, subidxstr, request->data_size);
01788 if (rec_size < 10) {
01789 EC_SLAVE_ERR(slave, "Incomplete abort command:\n");
01790 ec_print_data(data, rec_size);
01791 } else {
01792 fsm->request->abort_code = EC_READ_U32(data + 6);
01793 ec_canopen_abort_msg(slave, fsm->request->abort_code);
01794 }
01795 return;
01796 }
01797
01798 if (EC_READ_U16(data) >> 12 != 0x3 ||
01799 ((EC_READ_U8(data + 2) >> 5) != 0x01)) {
01800 if (slave->master->debug_level) {
01801 EC_SLAVE_DBG(slave, 1, "Invalid SDO download response!"
01802 " Retrying...\n");
01803 ec_print_data(data, rec_size);
01804 }
01805
01806 ec_slave_mbox_prepare_check(slave, datagram);
01807 fsm->retries = EC_FSM_RETRIES;
01808 fsm->state = ec_fsm_coe_down_seg_check;
01809 return;
01810 }
01811
01812 if (((EC_READ_U8(data + 2) >> 4) & 0x01) != fsm->toggle) {
01813 EC_SLAVE_ERR(slave, "Invalid toggle received during"
01814 " segmented download:\n");
01815 ec_print_data(data, rec_size);
01816 request->errno = EIO;
01817 fsm->state = ec_fsm_coe_error;
01818 return;
01819 }
01820
01821 fsm->offset += fsm->segment_size;
01822 fsm->remaining -= fsm->segment_size;
01823
01824 if (fsm->remaining) {
01825 fsm->toggle = !fsm->toggle;
01826 ec_fsm_coe_down_prepare_segment_request(fsm, datagram);
01827 } else {
01828 fsm->state = ec_fsm_coe_end;
01829 }
01830 }
01831
01832
01833
01838 int ec_fsm_coe_prepare_up(
01839 ec_fsm_coe_t *fsm,
01840 ec_datagram_t *datagram
01841 )
01842 {
01843 ec_slave_t *slave = fsm->slave;
01844 ec_sdo_request_t *request = fsm->request;
01845 ec_master_t *master = slave->master;
01846
01847 u8 *data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10);
01848 if (IS_ERR(data)) {
01849 request->errno = PTR_ERR(data);
01850 return PTR_ERR(data);
01851 }
01852
01853 EC_WRITE_U16(data, 0x2 << 12);
01854 EC_WRITE_U8 (data + 2, 0x2 << 5);
01855 EC_WRITE_U16(data + 3, request->index);
01856 EC_WRITE_U8 (data + 5, request->subindex);
01857 memset(data + 6, 0x00, 4);
01858
01859 if (master->debug_level) {
01860 EC_SLAVE_DBG(slave, 1, "Upload request:\n");
01861 ec_print_data(data, 10);
01862 }
01863
01864 fsm->state = ec_fsm_coe_up_request;
01865 return 0;
01866 }
01867
01868
01869
01874 void ec_fsm_coe_up_start(
01875 ec_fsm_coe_t *fsm,
01876 ec_datagram_t *datagram
01877 )
01878 {
01879 ec_slave_t *slave = fsm->slave;
01880 ec_sdo_request_t *request = fsm->request;
01881
01882 EC_SLAVE_DBG(slave, 1, "Uploading SDO 0x%04X:%02X.\n",
01883 request->index, request->subindex);
01884
01885 if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
01886 EC_SLAVE_ERR(slave, "Slave does not support CoE!\n");
01887 request->errno = EPROTONOSUPPORT;
01888 fsm->state = ec_fsm_coe_error;
01889 return;
01890 }
01891
01892 fsm->retries = EC_FSM_RETRIES;
01893 fsm->request->jiffies_sent = jiffies;
01894
01895 if (ec_fsm_coe_prepare_up(fsm, datagram)) {
01896 fsm->state = ec_fsm_coe_error;
01897 }
01898 }
01899
01900
01906 void ec_fsm_coe_up_request(
01907 ec_fsm_coe_t *fsm,
01908 ec_datagram_t *datagram
01909 )
01910 {
01911 ec_slave_t *slave = fsm->slave;
01912 unsigned long diff_ms;
01913
01914 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01915 if (ec_fsm_coe_prepare_up(fsm, datagram)) {
01916 fsm->state = ec_fsm_coe_error;
01917 }
01918 return;
01919 }
01920
01921 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01922 fsm->request->errno = EIO;
01923 fsm->state = ec_fsm_coe_error;
01924 EC_SLAVE_ERR(slave, "Failed to receive CoE upload request: ");
01925 ec_datagram_print_state(fsm->datagram);
01926 return;
01927 }
01928
01929 diff_ms = (jiffies - fsm->request->jiffies_sent) * 1000 / HZ;
01930
01931 if (fsm->datagram->working_counter != 1) {
01932 if (!fsm->datagram->working_counter) {
01933 if (diff_ms < fsm->request->response_timeout) {
01934 #if DEBUG_RETRIES
01935 EC_SLAVE_DBG(slave, 1, "Slave did not respond to"
01936 " SDO upload request. Retrying after %lu ms...\n",
01937 diff_ms);
01938 #endif
01939
01940 if (ec_fsm_coe_prepare_up(fsm, datagram)) {
01941 fsm->state = ec_fsm_coe_error;
01942 }
01943 return;
01944 }
01945 }
01946 fsm->request->errno = EIO;
01947 fsm->state = ec_fsm_coe_error;
01948 EC_SLAVE_ERR(slave, "Reception of CoE upload request for"
01949 " SDO 0x%04x:%x failed with timeout after %lu ms: ",
01950 fsm->request->index, fsm->request->subindex, diff_ms);
01951 ec_datagram_print_wc_error(fsm->datagram);
01952 return;
01953 }
01954
01955 #if DEBUG_LONG
01956 if (diff_ms > 200) {
01957 EC_SLAVE_WARN(slave, "SDO 0x%04x:%x upload took %lu ms.\n",
01958 fsm->request->index, fsm->request->subindex, diff_ms);
01959 }
01960 #endif
01961
01962 fsm->jiffies_start = fsm->datagram->jiffies_sent;
01963
01964 ec_slave_mbox_prepare_check(slave, datagram);
01965 fsm->retries = EC_FSM_RETRIES;
01966 fsm->state = ec_fsm_coe_up_check;
01967 }
01968
01969
01970
01975 void ec_fsm_coe_up_check(
01976 ec_fsm_coe_t *fsm,
01977 ec_datagram_t *datagram
01978 )
01979 {
01980 ec_slave_t *slave = fsm->slave;
01981
01982 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
01983 ec_slave_mbox_prepare_check(slave, datagram);
01984 return;
01985 }
01986
01987 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
01988 fsm->request->errno = EIO;
01989 fsm->state = ec_fsm_coe_error;
01990 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check datagram: ");
01991 ec_datagram_print_state(fsm->datagram);
01992 return;
01993 }
01994
01995 if (fsm->datagram->working_counter != 1) {
01996 fsm->request->errno = EIO;
01997 fsm->state = ec_fsm_coe_error;
01998 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check"
01999 " datagram failed: ");
02000 ec_datagram_print_wc_error(fsm->datagram);
02001 return;
02002 }
02003
02004 if (!ec_slave_mbox_check(fsm->datagram)) {
02005 unsigned long diff_ms =
02006 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
02007 1000 / HZ;
02008 if (diff_ms >= fsm->request->response_timeout) {
02009 fsm->request->errno = EIO;
02010 fsm->state = ec_fsm_coe_error;
02011 EC_SLAVE_ERR(slave, "Timeout after %lu ms while waiting for"
02012 " SDO 0x%04x:%x upload response.\n", diff_ms,
02013 fsm->request->index, fsm->request->subindex);
02014 return;
02015 }
02016
02017 ec_slave_mbox_prepare_check(slave, datagram);
02018 fsm->retries = EC_FSM_RETRIES;
02019 return;
02020 }
02021
02022
02023 ec_slave_mbox_prepare_fetch(slave, datagram);
02024 fsm->retries = EC_FSM_RETRIES;
02025 fsm->state = ec_fsm_coe_up_response;
02026 }
02027
02028
02029
02032 void ec_fsm_coe_up_prepare_segment_request(
02033 ec_fsm_coe_t *fsm,
02034 ec_datagram_t *datagram
02035 )
02036 {
02037 uint8_t *data =
02038 ec_slave_mbox_prepare_send(fsm->slave, datagram, 0x03, 10);
02039 if (IS_ERR(data)) {
02040 fsm->request->errno = PTR_ERR(data);
02041 fsm->state = ec_fsm_coe_error;
02042 return;
02043 }
02044
02045 EC_WRITE_U16(data, 0x2 << 12);
02046 EC_WRITE_U8 (data + 2, (fsm->toggle << 4
02047 | 0x3 << 5));
02048 memset(data + 3, 0x00, 7);
02049
02050 if (fsm->slave->master->debug_level) {
02051 EC_SLAVE_DBG(fsm->slave, 1, "Upload segment request:\n");
02052 ec_print_data(data, 10);
02053 }
02054 }
02055
02056
02057
02063 void ec_fsm_coe_up_response(
02064 ec_fsm_coe_t *fsm,
02065 ec_datagram_t *datagram
02066 )
02067 {
02068 ec_slave_t *slave = fsm->slave;
02069 ec_master_t *master = slave->master;
02070 uint16_t rec_index;
02071 uint8_t *data, mbox_prot, rec_subindex;
02072 size_t rec_size, data_size;
02073 ec_sdo_request_t *request = fsm->request;
02074 unsigned int expedited, size_specified;
02075 int ret;
02076
02077 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
02078 ec_slave_mbox_prepare_fetch(slave, datagram);
02079 return;
02080 }
02081
02082 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
02083 request->errno = EIO;
02084 fsm->state = ec_fsm_coe_error;
02085 EC_SLAVE_ERR(slave, "Failed to receive CoE upload response"
02086 " datagram: ");
02087 ec_datagram_print_state(fsm->datagram);
02088 return;
02089 }
02090
02091 if (fsm->datagram->working_counter != 1) {
02092 request->errno = EIO;
02093 fsm->state = ec_fsm_coe_error;
02094 EC_SLAVE_ERR(slave, "Reception of CoE upload response failed: ");
02095 ec_datagram_print_wc_error(fsm->datagram);
02096 return;
02097 }
02098
02099 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
02100 if (IS_ERR(data)) {
02101 request->errno = PTR_ERR(data);
02102 fsm->state = ec_fsm_coe_error;
02103 return;
02104 }
02105
02106 if (master->debug_level) {
02107 EC_SLAVE_DBG(slave, 1, "Upload response:\n");
02108 ec_print_data(data, rec_size);
02109 }
02110
02111 if (mbox_prot != 0x03) {
02112 request->errno = EIO;
02113 fsm->state = ec_fsm_coe_error;
02114 EC_SLAVE_WARN(slave, "Received mailbox protocol 0x%02X"
02115 " as response.\n", mbox_prot);
02116 return;
02117 }
02118
02119 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
02120
02121 ec_slave_mbox_prepare_check(slave, datagram);
02122 fsm->retries = EC_FSM_RETRIES;
02123 fsm->state = ec_fsm_coe_up_check;
02124 return;
02125 }
02126
02127 if (rec_size < 6) {
02128 request->errno = EIO;
02129 fsm->state = ec_fsm_coe_error;
02130 EC_SLAVE_ERR(slave, "Received currupted SDO upload response"
02131 " (%zu bytes)!\n", rec_size);
02132 ec_print_data(data, rec_size);
02133 return;
02134 }
02135
02136 if (EC_READ_U16(data) >> 12 == 0x2 &&
02137 EC_READ_U8(data + 2) >> 5 == 0x4) {
02138 EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X aborted.\n",
02139 request->index, request->subindex);
02140 if (rec_size >= 10) {
02141 request->abort_code = EC_READ_U32(data + 6);
02142 ec_canopen_abort_msg(slave, request->abort_code);
02143 } else {
02144 EC_SLAVE_ERR(slave, "No abort message.\n");
02145 }
02146 request->errno = EIO;
02147 fsm->state = ec_fsm_coe_error;
02148 return;
02149 }
02150
02151 if (EC_READ_U16(data) >> 12 != 0x3 ||
02152 EC_READ_U8(data + 2) >> 5 != 0x2) {
02153 EC_SLAVE_ERR(slave, "Received unknown response while"
02154 " uploading SDO 0x%04X:%02X.\n",
02155 request->index, request->subindex);
02156 ec_print_data(data, rec_size);
02157 request->errno = EIO;
02158 fsm->state = ec_fsm_coe_error;
02159 return;
02160 }
02161
02162 rec_index = EC_READ_U16(data + 3);
02163 rec_subindex = EC_READ_U8(data + 5);
02164
02165 if (rec_index != request->index || rec_subindex != request->subindex) {
02166 EC_SLAVE_ERR(slave, "Received upload response for wrong SDO"
02167 " (0x%04X:%02X, requested: 0x%04X:%02X).\n",
02168 rec_index, rec_subindex, request->index, request->subindex);
02169 ec_print_data(data, rec_size);
02170
02171
02172 ec_slave_mbox_prepare_check(slave, datagram);
02173 fsm->retries = EC_FSM_RETRIES;
02174 fsm->state = ec_fsm_coe_up_check;
02175 return;
02176 }
02177
02178
02179 expedited = EC_READ_U8(data + 2) & 0x02;
02180
02181 if (expedited) {
02182 size_specified = EC_READ_U8(data + 2) & 0x01;
02183 if (size_specified) {
02184 fsm->complete_size = 4 - ((EC_READ_U8(data + 2) & 0x0C) >> 2);
02185 } else {
02186 fsm->complete_size = 4;
02187 }
02188
02189 if (rec_size < 6 + fsm->complete_size) {
02190 request->errno = EIO;
02191 fsm->state = ec_fsm_coe_error;
02192 EC_SLAVE_ERR(slave, "Received corrupted SDO expedited upload"
02193 " response (only %zu bytes)!\n", rec_size);
02194 ec_print_data(data, rec_size);
02195 return;
02196 }
02197
02198 ret = ec_sdo_request_copy_data(request, data + 6, fsm->complete_size);
02199 if (ret) {
02200 request->errno = -ret;
02201 fsm->state = ec_fsm_coe_error;
02202 return;
02203 }
02204 } else {
02205 if (rec_size < 10) {
02206 request->errno = EIO;
02207 fsm->state = ec_fsm_coe_error;
02208 EC_SLAVE_ERR(slave, "Received currupted SDO normal upload"
02209 " response (only %zu bytes)!\n", rec_size);
02210 ec_print_data(data, rec_size);
02211 return;
02212 }
02213
02214 data_size = rec_size - 10;
02215 fsm->complete_size = EC_READ_U32(data + 6);
02216
02217 if (!fsm->complete_size) {
02218 request->errno = EIO;
02219 fsm->state = ec_fsm_coe_error;
02220 EC_SLAVE_ERR(slave, "No complete size supplied!\n");
02221 ec_print_data(data, rec_size);
02222 return;
02223 }
02224
02225 ret = ec_sdo_request_alloc(request, fsm->complete_size);
02226 if (ret) {
02227 request->errno = -ret;
02228 fsm->state = ec_fsm_coe_error;
02229 return;
02230 }
02231
02232 ret = ec_sdo_request_copy_data(request, data + 10, data_size);
02233 if (ret) {
02234 request->errno = -ret;
02235 fsm->state = ec_fsm_coe_error;
02236 return;
02237 }
02238
02239 fsm->toggle = 0;
02240
02241 if (data_size < fsm->complete_size) {
02242 EC_SLAVE_DBG(slave, 1, "SDO data incomplete (%zu / %u)."
02243 " Segmenting...\n", data_size, fsm->complete_size);
02244 ec_fsm_coe_up_prepare_segment_request(fsm, datagram);
02245 fsm->retries = EC_FSM_RETRIES;
02246 fsm->state = ec_fsm_coe_up_seg_request;
02247 return;
02248 }
02249 }
02250
02251 if (master->debug_level) {
02252 EC_SLAVE_DBG(slave, 1, "Uploaded data:\n");
02253 ec_print_data(request->data, request->data_size);
02254 }
02255
02256 fsm->state = ec_fsm_coe_end;
02257 }
02258
02259
02260
02266 void ec_fsm_coe_up_seg_request(
02267 ec_fsm_coe_t *fsm,
02268 ec_datagram_t *datagram
02269 )
02270 {
02271 ec_slave_t *slave = fsm->slave;
02272
02273 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
02274 ec_fsm_coe_up_prepare_segment_request(fsm, datagram);
02275 return;
02276 }
02277
02278 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
02279 fsm->request->errno = EIO;
02280 fsm->state = ec_fsm_coe_error;
02281 EC_SLAVE_ERR(slave, "Failed to receive CoE upload segment"
02282 " request datagram: ");
02283 ec_datagram_print_state(fsm->datagram);
02284 return;
02285 }
02286
02287 if (fsm->datagram->working_counter != 1) {
02288 fsm->request->errno = EIO;
02289 fsm->state = ec_fsm_coe_error;
02290 EC_SLAVE_ERR(slave, "Reception of CoE upload segment"
02291 " request failed: ");
02292 ec_datagram_print_wc_error(fsm->datagram);
02293 return;
02294 }
02295
02296 fsm->jiffies_start = fsm->datagram->jiffies_sent;
02297
02298 ec_slave_mbox_prepare_check(slave, datagram);
02299 fsm->retries = EC_FSM_RETRIES;
02300 fsm->state = ec_fsm_coe_up_seg_check;
02301 }
02302
02303
02304
02309 void ec_fsm_coe_up_seg_check(
02310 ec_fsm_coe_t *fsm,
02311 ec_datagram_t *datagram
02312 )
02313 {
02314 ec_slave_t *slave = fsm->slave;
02315
02316 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
02317 ec_slave_mbox_prepare_check(slave, datagram);
02318 return;
02319 }
02320
02321 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
02322 fsm->request->errno = EIO;
02323 fsm->state = ec_fsm_coe_error;
02324 EC_SLAVE_ERR(slave, "Failed to receive CoE mailbox check"
02325 " datagram: ");
02326 ec_datagram_print_state(fsm->datagram);
02327 return;
02328 }
02329
02330 if (fsm->datagram->working_counter != 1) {
02331 fsm->request->errno = EIO;
02332 fsm->state = ec_fsm_coe_error;
02333 EC_SLAVE_ERR(slave, "Reception of CoE mailbox check datagram"
02334 " failed: ");
02335 ec_datagram_print_wc_error(fsm->datagram);
02336 return;
02337 }
02338
02339 if (!ec_slave_mbox_check(fsm->datagram)) {
02340 unsigned long diff_ms =
02341 (fsm->datagram->jiffies_received - fsm->jiffies_start) *
02342 1000 / HZ;
02343 if (diff_ms >= fsm->request->response_timeout) {
02344 fsm->request->errno = EIO;
02345 fsm->state = ec_fsm_coe_error;
02346 EC_SLAVE_ERR(slave, "Timeout while waiting for SDO upload"
02347 " segment response.\n");
02348 return;
02349 }
02350
02351 ec_slave_mbox_prepare_check(slave, datagram);
02352 fsm->retries = EC_FSM_RETRIES;
02353 return;
02354 }
02355
02356
02357 ec_slave_mbox_prepare_fetch(slave, datagram);
02358 fsm->retries = EC_FSM_RETRIES;
02359 fsm->state = ec_fsm_coe_up_seg_response;
02360 }
02361
02362
02363
02369 void ec_fsm_coe_up_seg_response(
02370 ec_fsm_coe_t *fsm,
02371 ec_datagram_t *datagram
02372 )
02373 {
02374 ec_slave_t *slave = fsm->slave;
02375 ec_master_t *master = slave->master;
02376 uint8_t *data, mbox_prot;
02377 size_t rec_size, data_size;
02378 ec_sdo_request_t *request = fsm->request;
02379 unsigned int last_segment;
02380
02381 if (fsm->datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
02382 ec_slave_mbox_prepare_fetch(slave, datagram);
02383 return;
02384 }
02385
02386 if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
02387 request->errno = EIO;
02388 fsm->state = ec_fsm_coe_error;
02389 EC_SLAVE_ERR(slave, "Failed to receive CoE upload segment"
02390 " response datagram: ");
02391 ec_datagram_print_state(fsm->datagram);
02392 return;
02393 }
02394
02395 if (fsm->datagram->working_counter != 1) {
02396 request->errno = EIO;
02397 fsm->state = ec_fsm_coe_error;
02398 EC_SLAVE_ERR(slave, "Reception of CoE upload segment"
02399 " response failed: ");
02400 ec_datagram_print_wc_error(fsm->datagram);
02401 return;
02402 }
02403
02404 data = ec_slave_mbox_fetch(slave, fsm->datagram, &mbox_prot, &rec_size);
02405 if (IS_ERR(data)) {
02406 request->errno = PTR_ERR(data);
02407 fsm->state = ec_fsm_coe_error;
02408 return;
02409 }
02410
02411 if (master->debug_level) {
02412 EC_SLAVE_DBG(slave, 1, "Upload segment response:\n");
02413 ec_print_data(data, rec_size);
02414 }
02415
02416 if (mbox_prot != 0x03) {
02417 EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
02418 mbox_prot);
02419 request->errno = EIO;
02420 fsm->state = ec_fsm_coe_error;
02421 return;
02422 }
02423
02424 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) {
02425
02426 ec_slave_mbox_prepare_check(slave, datagram);
02427 fsm->retries = EC_FSM_RETRIES;
02428 fsm->state = ec_fsm_coe_up_seg_check;
02429 return;
02430 }
02431
02432 if (rec_size < 10) {
02433 EC_SLAVE_ERR(slave, "Received currupted SDO upload"
02434 " segment response!\n");
02435 ec_print_data(data, rec_size);
02436 request->errno = EIO;
02437 fsm->state = ec_fsm_coe_error;
02438 return;
02439 }
02440
02441 if (EC_READ_U16(data) >> 12 == 0x2 &&
02442 EC_READ_U8 (data + 2) >> 5 == 0x4) {
02443 EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X aborted.\n",
02444 request->index, request->subindex);
02445 request->abort_code = EC_READ_U32(data + 6);
02446 ec_canopen_abort_msg(slave, request->abort_code);
02447 request->errno = EIO;
02448 fsm->state = ec_fsm_coe_error;
02449 return;
02450 }
02451
02452 if (EC_READ_U16(data) >> 12 != 0x3 ||
02453 EC_READ_U8 (data + 2) >> 5 != 0x0) {
02454 if (fsm->slave->master->debug_level) {
02455 EC_SLAVE_DBG(slave, 1, "Invalid SDO upload segment response!\n");
02456 ec_print_data(data, rec_size);
02457 }
02458
02459 ec_slave_mbox_prepare_check(slave, datagram);
02460 fsm->retries = EC_FSM_RETRIES;
02461 fsm->state = ec_fsm_coe_up_seg_check;
02462 return;
02463 }
02464
02465 data_size = rec_size - 3;
02466
02467 if (rec_size == 10) {
02468 uint8_t seg_size = (EC_READ_U8(data + 2) & 0xE) >> 1;
02469 data_size -= seg_size;
02470 }
02471
02472 if (request->data_size + data_size > fsm->complete_size) {
02473 EC_SLAVE_ERR(slave, "SDO upload 0x%04X:%02X failed: Fragment"
02474 " exceeding complete size!\n",
02475 request->index, request->subindex);
02476 request->errno = EOVERFLOW;
02477 fsm->state = ec_fsm_coe_error;
02478 return;
02479 }
02480
02481 memcpy(request->data + request->data_size, data + 3, data_size);
02482 request->data_size += data_size;
02483
02484 last_segment = EC_READ_U8(data + 2) & 0x01;
02485 if (!last_segment) {
02486 fsm->toggle = !fsm->toggle;
02487 ec_fsm_coe_up_prepare_segment_request(fsm, datagram);
02488 fsm->retries = EC_FSM_RETRIES;
02489 fsm->state = ec_fsm_coe_up_seg_request;
02490 return;
02491 }
02492
02493 if (request->data_size != fsm->complete_size) {
02494 EC_SLAVE_WARN(slave, "SDO upload 0x%04X:%02X: Assembled data"
02495 " size (%zu) does not match complete size (%u)!\n",
02496 request->index, request->subindex,
02497 request->data_size, fsm->complete_size);
02498 }
02499
02500 if (master->debug_level) {
02501 EC_SLAVE_DBG(slave, 1, "Uploaded data:\n");
02502 ec_print_data(request->data, request->data_size);
02503 }
02504
02505 fsm->state = ec_fsm_coe_end;
02506 }
02507
02508
02509
02514 void ec_fsm_coe_error(
02515 ec_fsm_coe_t *fsm,
02516 ec_datagram_t *datagram
02517 )
02518 {
02519 }
02520
02521
02522
02527 void ec_fsm_coe_end(
02528 ec_fsm_coe_t *fsm,
02529 ec_datagram_t *datagram
02530 )
02531 {
02532 }
02533
02534