75 /*****************************************************************************/ |
75 /*****************************************************************************/ |
76 |
76 |
77 /** Constructor. |
77 /** Constructor. |
78 */ |
78 */ |
79 void ec_fsm_soe_init( |
79 void ec_fsm_soe_init( |
80 ec_fsm_soe_t *fsm, /**< finite state machine */ |
80 ec_fsm_soe_t *fsm, /**< finite state machine */ |
81 ec_datagram_t *datagram /**< datagram */ |
81 ec_datagram_t *datagram /**< datagram */ |
82 ) |
82 ) |
83 { |
83 { |
84 fsm->state = NULL; |
84 fsm->state = NULL; |
85 fsm->datagram = datagram; |
85 fsm->datagram = datagram; |
86 } |
86 } |
87 |
87 |
88 /*****************************************************************************/ |
88 /*****************************************************************************/ |
89 |
89 |
90 /** Destructor. |
90 /** Destructor. |
91 */ |
91 */ |
92 void ec_fsm_soe_clear( |
92 void ec_fsm_soe_clear( |
93 ec_fsm_soe_t *fsm /**< finite state machine */ |
93 ec_fsm_soe_t *fsm /**< finite state machine */ |
94 ) |
94 ) |
95 { |
95 { |
96 } |
96 } |
97 |
97 |
98 /*****************************************************************************/ |
98 /*****************************************************************************/ |
99 |
99 |
252 } |
252 } |
253 |
253 |
254 if (datagram->working_counter != 1) { |
254 if (datagram->working_counter != 1) { |
255 fsm->state = ec_fsm_soe_error; |
255 fsm->state = ec_fsm_soe_error; |
256 EC_ERR("Reception of SoE mailbox check datagram failed on slave %u: ", |
256 EC_ERR("Reception of SoE mailbox check datagram failed on slave %u: ", |
257 slave->ring_position); |
257 slave->ring_position); |
258 ec_datagram_print_wc_error(datagram); |
258 ec_datagram_print_wc_error(datagram); |
259 return; |
259 return; |
260 } |
260 } |
261 |
261 |
262 if (!ec_slave_mbox_check(datagram)) { |
262 if (!ec_slave_mbox_check(datagram)) { |
332 } |
332 } |
333 |
333 |
334 if (rec_size < EC_SOE_READ_RESPONSE_SIZE) { |
334 if (rec_size < EC_SOE_READ_RESPONSE_SIZE) { |
335 fsm->state = ec_fsm_soe_error; |
335 fsm->state = ec_fsm_soe_error; |
336 EC_ERR("Received currupted SoE read response (%zu bytes)!\n", |
336 EC_ERR("Received currupted SoE read response (%zu bytes)!\n", |
337 rec_size); |
337 rec_size); |
338 ec_print_data(data, rec_size); |
338 ec_print_data(data, rec_size); |
339 return; |
339 return; |
340 } |
340 } |
341 |
341 |
342 header = EC_READ_U8(data); |
342 header = EC_READ_U8(data); |
343 opcode = header & 0x7; |
343 opcode = header & 0x7; |
344 incomplete = (header >> 3) & 1; |
344 incomplete = (header >> 3) & 1; |
345 error_flag = (header >> 4) & 1; |
345 error_flag = (header >> 4) & 1; |
346 |
346 |
347 if (opcode != EC_SOE_OPCODE_READ_RESPONSE) { |
347 if (opcode != EC_SOE_OPCODE_READ_RESPONSE) { |
348 EC_ERR("Received no read response (opcode %x).\n", opcode); |
348 EC_ERR("Received no read response (opcode %x).\n", opcode); |
349 ec_print_data(data, rec_size); |
349 ec_print_data(data, rec_size); |
350 fsm->state = ec_fsm_soe_error; |
350 fsm->state = ec_fsm_soe_error; |
351 return; |
351 return; |
352 } |
352 } |
353 |
353 |
354 if (error_flag) { |
354 if (error_flag) { |
355 req->error_code = EC_READ_U16(data + rec_size - 2); |
355 req->error_code = EC_READ_U16(data + rec_size - 2); |
356 EC_ERR("Received error response: 0x%04x.\n", |
356 EC_ERR("Received error response: 0x%04x.\n", |
357 req->error_code); |
357 req->error_code); |
358 fsm->state = ec_fsm_soe_error; |
358 fsm->state = ec_fsm_soe_error; |
359 return; |
359 return; |
360 } else { |
360 } else { |
361 req->error_code = 0x0000; |
361 req->error_code = 0x0000; |
362 } |
362 } |
363 |
363 |
364 value_included = (EC_READ_U8(data + 1) >> 6) & 1; |
364 value_included = (EC_READ_U8(data + 1) >> 6) & 1; |
365 if (!value_included) { |
365 if (!value_included) { |
366 EC_ERR("No value included!\n"); |
366 EC_ERR("No value included!\n"); |
367 fsm->state = ec_fsm_soe_error; |
367 fsm->state = ec_fsm_soe_error; |
368 return; |
368 return; |
369 } |
369 } |
370 |
370 |
371 data_size = rec_size - EC_SOE_READ_RESPONSE_SIZE; |
371 data_size = rec_size - EC_SOE_READ_RESPONSE_SIZE; |
372 if (ec_soe_request_append_data(req, |
372 if (ec_soe_request_append_data(req, |
373 data + EC_SOE_READ_RESPONSE_SIZE, data_size)) { |
373 data + EC_SOE_READ_RESPONSE_SIZE, data_size)) { |
374 fsm->state = ec_fsm_soe_error; |
374 fsm->state = ec_fsm_soe_error; |
375 return; |
375 return; |
376 } |
376 } |
377 |
377 |
378 if (incomplete) { |
378 if (incomplete) { |
379 if (master->debug_level) { |
379 if (master->debug_level) { |
380 EC_DBG("SoE data incomplete. Waiting for fragment" |
380 EC_DBG("SoE data incomplete. Waiting for fragment" |
381 " at offset %zu.\n", req->data_size); |
381 " at offset %zu.\n", req->data_size); |
428 if (remaining_size % fragment_size) { |
428 if (remaining_size % fragment_size) { |
429 fragments_left++; |
429 fragments_left++; |
430 } |
430 } |
431 |
431 |
432 data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE, |
432 data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_SOE, |
433 EC_SOE_WRITE_REQUEST_SIZE + fragment_size); |
433 EC_SOE_WRITE_REQUEST_SIZE + fragment_size); |
434 if (IS_ERR(data)) { |
434 if (IS_ERR(data)) { |
435 fsm->state = ec_fsm_soe_error; |
435 fsm->state = ec_fsm_soe_error; |
436 return; |
436 return; |
437 } |
437 } |
438 |
438 |
439 EC_WRITE_U8(data, EC_SOE_OPCODE_WRITE_REQUEST | incomplete << 3); |
439 EC_WRITE_U8(data, EC_SOE_OPCODE_WRITE_REQUEST | incomplete << 3); |
440 EC_WRITE_U8(data + 1, 1 << 6); // only value included |
440 EC_WRITE_U8(data + 1, 1 << 6); // only value included |
441 EC_WRITE_U16(data + 2, incomplete ? fragments_left : req->idn); |
441 EC_WRITE_U16(data + 2, incomplete ? fragments_left : req->idn); |
442 memcpy(data + 4, req->data + fsm->offset, fragment_size); |
442 memcpy(data + 4, req->data + fsm->offset, fragment_size); |
443 fsm->offset += fragment_size; |
443 fsm->offset += fragment_size; |
444 |
444 |
445 if (master->debug_level) { |
445 if (master->debug_level) { |
446 EC_DBG("SCC write request:\n"); |
446 EC_DBG("SCC write request:\n"); |
447 ec_print_data(data, EC_SOE_WRITE_REQUEST_SIZE + fragment_size); |
447 ec_print_data(data, EC_SOE_WRITE_REQUEST_SIZE + fragment_size); |
544 } |
544 } |
545 |
545 |
546 if (datagram->working_counter != 1) { |
546 if (datagram->working_counter != 1) { |
547 fsm->state = ec_fsm_soe_error; |
547 fsm->state = ec_fsm_soe_error; |
548 EC_ERR("Reception of SoE write request datagram failed on slave %u: ", |
548 EC_ERR("Reception of SoE write request datagram failed on slave %u: ", |
549 slave->ring_position); |
549 slave->ring_position); |
550 ec_datagram_print_wc_error(datagram); |
550 ec_datagram_print_wc_error(datagram); |
551 return; |
551 return; |
552 } |
552 } |
553 |
553 |
554 if (fsm->offset < req->data_size) { |
554 if (fsm->offset < req->data_size) { |
586 ec_datagram_t *datagram = fsm->datagram; |
586 ec_datagram_t *datagram = fsm->datagram; |
587 ec_slave_t *slave = fsm->slave; |
587 ec_slave_t *slave = fsm->slave; |
588 ec_master_t *master = slave->master; |
588 ec_master_t *master = slave->master; |
589 ec_soe_request_t *req = fsm->request; |
589 ec_soe_request_t *req = fsm->request; |
590 uint8_t *data, mbox_prot, opcode, error_flag; |
590 uint8_t *data, mbox_prot, opcode, error_flag; |
591 uint16_t idn; |
591 uint16_t idn; |
592 size_t rec_size; |
592 size_t rec_size; |
593 |
593 |
594 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
594 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
595 return; // FIXME: request again? |
595 return; // FIXME: request again? |
596 |
596 |
628 } |
628 } |
629 |
629 |
630 if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE) { |
630 if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE) { |
631 fsm->state = ec_fsm_soe_error; |
631 fsm->state = ec_fsm_soe_error; |
632 EC_ERR("Received currupted SoE write response (%zu bytes)!\n", |
632 EC_ERR("Received currupted SoE write response (%zu bytes)!\n", |
633 rec_size); |
633 rec_size); |
634 ec_print_data(data, rec_size); |
634 ec_print_data(data, rec_size); |
635 return; |
635 return; |
636 } |
636 } |
637 |
637 |
638 opcode = EC_READ_U8(data) & 0x7; |
638 opcode = EC_READ_U8(data) & 0x7; |
639 if (opcode != EC_SOE_OPCODE_WRITE_RESPONSE) { |
639 if (opcode != EC_SOE_OPCODE_WRITE_RESPONSE) { |
640 EC_ERR("Received no write response (opcode %x).\n", opcode); |
640 EC_ERR("Received no write response (opcode %x).\n", opcode); |
641 ec_print_data(data, rec_size); |
641 ec_print_data(data, rec_size); |
642 fsm->state = ec_fsm_soe_error; |
642 fsm->state = ec_fsm_soe_error; |
643 return; |
643 return; |
644 } |
644 } |
645 |
645 |
646 idn = EC_READ_U16(data + 2); |
646 idn = EC_READ_U16(data + 2); |
647 if (idn != req->idn) { |
647 if (idn != req->idn) { |
648 EC_ERR("Received response for wrong IDN 0x%04x.\n", idn); |
648 EC_ERR("Received response for wrong IDN 0x%04x.\n", idn); |
649 ec_print_data(data, rec_size); |
649 ec_print_data(data, rec_size); |
650 fsm->state = ec_fsm_soe_error; |
650 fsm->state = ec_fsm_soe_error; |
651 return; |
651 return; |
652 } |
652 } |
653 |
653 |
654 error_flag = (EC_READ_U8(data) >> 4) & 1; |
654 error_flag = (EC_READ_U8(data) >> 4) & 1; |
655 if (error_flag) { |
655 if (error_flag) { |
656 if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE + 2) { |
656 if (rec_size < EC_SOE_WRITE_RESPONSE_SIZE + 2) { |
657 EC_ERR("Received corrupted error response - error flag set," |
657 EC_ERR("Received corrupted error response - error flag set," |
658 " but received size is %zu.\n", rec_size); |
658 " but received size is %zu.\n", rec_size); |
659 } else { |
659 } else { |
660 req->error_code = EC_READ_U16(data + EC_SOE_WRITE_RESPONSE_SIZE); |
660 req->error_code = EC_READ_U16(data + EC_SOE_WRITE_RESPONSE_SIZE); |
661 EC_ERR("Received error response: 0x%04x.\n", |
661 EC_ERR("Received error response: 0x%04x.\n", |
662 req->error_code); |
662 req->error_code); |
663 } |
663 } |
664 ec_print_data(data, rec_size); |
664 ec_print_data(data, rec_size); |
665 fsm->state = ec_fsm_soe_error; |
665 fsm->state = ec_fsm_soe_error; |
666 return; |
666 return; |
667 } else { |
667 } else { |
668 req->error_code = 0x0000; |
668 req->error_code = 0x0000; |
669 } |
669 } |
670 |
670 |
671 fsm->state = ec_fsm_soe_end; // success |
671 fsm->state = ec_fsm_soe_end; // success |
672 } |
672 } |
673 |
673 |
674 /*****************************************************************************/ |
674 /*****************************************************************************/ |