401 |
401 |
402 cat_type = EC_READ_U16(fsm->fsm_sii.value); |
402 cat_type = EC_READ_U16(fsm->fsm_sii.value); |
403 cat_size = EC_READ_U16(fsm->fsm_sii.value + 2); |
403 cat_size = EC_READ_U16(fsm->fsm_sii.value + 2); |
404 |
404 |
405 if (cat_type != 0xFFFF) { // not the last category |
405 if (cat_type != 0xFFFF) { // not the last category |
406 fsm->sii_offset += cat_size + 2; |
406 off_t next_offset = 2UL + fsm->sii_offset + cat_size; |
407 if (fsm->sii_offset >= EC_MAX_EEPROM_SIZE) { |
407 if (next_offset >= EC_MAX_EEPROM_SIZE) { |
408 EC_WARN("EEPROM size of slave %i exceeds" |
408 EC_WARN("EEPROM size of slave %i exceeds" |
409 " %i words (0xffff limiter missing?).\n", |
409 " %u words (0xffff limiter missing?).\n", |
410 slave->ring_position, EC_MAX_EEPROM_SIZE); |
410 slave->ring_position, EC_MAX_EEPROM_SIZE); |
411 slave->eeprom_size = EC_FIRST_EEPROM_CATEGORY_OFFSET * 2; |
411 slave->eeprom_size = EC_FIRST_EEPROM_CATEGORY_OFFSET * 2; |
412 goto alloc_eeprom; |
412 goto alloc_eeprom; |
413 } |
413 } |
|
414 fsm->sii_offset = next_offset; |
414 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
415 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
415 EC_FSM_SII_NODE); |
416 EC_FSM_SII_NODE); |
416 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
417 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
417 return; |
418 return; |
418 } |
419 } |
419 |
420 |
420 slave->eeprom_size = (fsm->sii_offset + 1) * 2; |
421 slave->eeprom_size = (fsm->sii_offset + 1) * 2; |
421 |
422 |
422 alloc_eeprom: |
423 alloc_eeprom: |
423 if (slave->eeprom_data) { |
424 if (slave->eeprom_data) { |
424 EC_INFO("Freeing old EEPROM data on slave %i...\n", |
425 EC_WARN("Freeing old EEPROM data on slave %i...\n", |
425 slave->ring_position); |
426 slave->ring_position); |
426 kfree(slave->eeprom_data); |
427 kfree(slave->eeprom_data); |
427 } |
428 } |
428 |
429 |
429 if (!(slave->eeprom_data = |
430 if (!(slave->eeprom_data = |
430 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
431 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
431 fsm->slave->error_flag = 1; |
432 EC_ERR("Failed to allocate %u bytes of EEPROM data for slave %u.\n", |
432 fsm->state = ec_fsm_slave_state_error; |
433 slave->eeprom_size, slave->ring_position); |
433 EC_ERR("Failed to allocate EEPROM data on slave %i.\n", |
434 slave->eeprom_size = 0; |
434 slave->ring_position); |
435 slave->error_flag = 1; |
|
436 fsm->state = ec_fsm_slave_state_error; |
435 return; |
437 return; |
436 } |
438 } |
437 |
439 |
438 // Start fetching EEPROM contents |
440 // Start fetching EEPROM contents |
439 |
441 |
464 return; |
466 return; |
465 } |
467 } |
466 |
468 |
467 // 2 words fetched |
469 // 2 words fetched |
468 |
470 |
469 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
471 if (fsm->sii_offset + 2 <= eeprom_word_size) { // 2 words fit |
470 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
472 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
471 fsm->fsm_sii.value, 4); |
473 fsm->fsm_sii.value, 4); |
472 } |
474 } |
473 else { // copy the last word |
475 else { // copy the last word |
474 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
476 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
475 fsm->fsm_sii.value, 2); |
477 fsm->fsm_sii.value, 2); |
476 } |
478 } |
477 |
479 |
478 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
480 if (fsm->sii_offset + 2 < eeprom_word_size) { |
479 // fetch the next 2 words |
481 // fetch the next 2 words |
480 fsm->sii_offset += 2; |
482 fsm->sii_offset += 2; |
481 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
483 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
482 EC_FSM_SII_NODE); |
484 EC_FSM_SII_NODE); |
483 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
485 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
505 slave->sii_tx_mailbox_size = |
507 slave->sii_tx_mailbox_size = |
506 EC_READ_U16(slave->eeprom_data + 2 * 0x001B); |
508 EC_READ_U16(slave->eeprom_data + 2 * 0x001B); |
507 slave->sii_mailbox_protocols = |
509 slave->sii_mailbox_protocols = |
508 EC_READ_U16(slave->eeprom_data + 2 * 0x001C); |
510 EC_READ_U16(slave->eeprom_data + 2 * 0x001C); |
509 |
511 |
|
512 if (eeprom_word_size < EC_FIRST_EEPROM_CATEGORY_OFFSET + 1) { |
|
513 EC_ERR("Unexpected end of EEPROM data in slave %u:" |
|
514 " First category header missing.\n", |
|
515 slave->ring_position); |
|
516 goto end; |
|
517 } |
|
518 |
510 // evaluate category data |
519 // evaluate category data |
511 cat_word = (uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
520 cat_word = |
|
521 (uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
512 while (EC_READ_U16(cat_word) != 0xFFFF) { |
522 while (EC_READ_U16(cat_word) != 0xFFFF) { |
|
523 |
|
524 // type and size words must fit |
|
525 if (cat_word + 2 - (uint16_t *) slave->eeprom_data |
|
526 > eeprom_word_size) { |
|
527 EC_ERR("Unexpected end of EEPROM data in slave %u:" |
|
528 " Category header incomplete.\n", |
|
529 slave->ring_position); |
|
530 goto end; |
|
531 } |
|
532 |
513 cat_type = EC_READ_U16(cat_word) & 0x7FFF; |
533 cat_type = EC_READ_U16(cat_word) & 0x7FFF; |
514 cat_size = EC_READ_U16(cat_word + 1); |
534 cat_size = EC_READ_U16(cat_word + 1); |
|
535 cat_word += 2; |
|
536 |
|
537 if (cat_word + cat_size - (uint16_t *) slave->eeprom_data |
|
538 > eeprom_word_size) { |
|
539 EC_WARN("Unexpected end of EEPROM data in slave %u:" |
|
540 " Category data incomplete.\n", |
|
541 slave->ring_position); |
|
542 goto end; |
|
543 } |
515 |
544 |
516 switch (cat_type) { |
545 switch (cat_type) { |
517 case 0x000A: |
546 case 0x000A: |
518 if (ec_slave_fetch_sii_strings( |
547 if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word, |
519 slave, (uint8_t *) (cat_word + 2))) |
548 cat_size * 2)) |
520 goto end; |
549 goto end; |
521 break; |
550 break; |
522 case 0x001E: |
551 case 0x001E: |
523 ec_slave_fetch_sii_general( |
552 if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word, |
524 slave, (uint8_t *) (cat_word + 2)); |
553 cat_size * 2)) |
|
554 goto end; |
525 break; |
555 break; |
526 case 0x0028: |
556 case 0x0028: |
527 break; |
557 break; |
528 case 0x0029: |
558 case 0x0029: |
529 if (ec_slave_fetch_sii_syncs( |
559 if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word, |
530 slave, (uint8_t *) (cat_word + 2), cat_size)) |
560 cat_size * 2)) |
531 goto end; |
561 goto end; |
532 break; |
562 break; |
533 case 0x0032: |
563 case 0x0032: |
534 if (ec_slave_fetch_sii_pdos( |
564 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word, |
535 slave, (uint8_t *) (cat_word + 2), |
565 cat_size * 2, EC_TX_PDO)) |
536 cat_size, EC_TX_PDO)) |
|
537 goto end; |
566 goto end; |
538 break; |
567 break; |
539 case 0x0033: |
568 case 0x0033: |
540 if (ec_slave_fetch_sii_pdos( |
569 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word, |
541 slave, (uint8_t *) (cat_word + 2), |
570 cat_size * 2, EC_RX_PDO)) |
542 cat_size, EC_RX_PDO)) |
|
543 goto end; |
571 goto end; |
544 break; |
572 break; |
545 default: |
573 default: |
546 if (fsm->slave->master->debug_level) |
574 if (fsm->slave->master->debug_level) |
547 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
575 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
548 cat_type, slave->ring_position); |
576 cat_type, slave->ring_position); |
549 } |
577 } |
550 |
578 |
551 cat_word += cat_size + 2; |
579 cat_word += cat_size; |
|
580 if (cat_word - (uint16_t *) slave->eeprom_data >= eeprom_word_size) { |
|
581 EC_WARN("Unexpected end of EEPROM data in slave %u:" |
|
582 " Next category header missing.\n", |
|
583 slave->ring_position); |
|
584 goto end; |
|
585 } |
552 } |
586 } |
553 |
587 |
554 fsm->state = ec_fsm_slave_state_end; |
588 fsm->state = ec_fsm_slave_state_end; |
555 return; |
589 return; |
556 |
590 |
681 slave->ring_position); |
717 slave->ring_position); |
682 } |
718 } |
683 return; |
719 return; |
684 } |
720 } |
685 |
721 |
686 if (!slave->sii_mailbox_protocols || slave->sii_sync_count < 2) { |
722 if (!slave->sii_mailbox_protocols) { |
687 // no mailbox sync managers to be configured |
723 // no mailbox protocols supported |
|
724 if (master->debug_level) |
|
725 EC_DBG("Slave %i does not support mailbox communication.\n", |
|
726 slave->ring_position); |
688 ec_fsm_slave_conf_enter_preop(fsm); |
727 ec_fsm_slave_conf_enter_preop(fsm); |
689 return; |
728 return; |
690 } |
729 } |
691 |
730 |
692 if (master->debug_level) { |
731 if (master->debug_level) { |
693 EC_DBG("Configuring mailbox sync managers of slave %i.\n", |
732 EC_DBG("Configuring mailbox sync managers of slave %i.\n", |
694 slave->ring_position); |
733 slave->ring_position); |
695 } |
734 } |
696 |
735 |
697 // configure sync managers |
736 if (slave->sii_sync_count >= 2) { |
698 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
737 // configure sync managers |
699 EC_SYNC_SIZE * slave->sii_sync_count); |
738 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
700 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->sii_sync_count); |
739 EC_SYNC_SIZE * slave->sii_sync_count); |
701 |
740 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->sii_sync_count); |
702 for (i = 0; i < 2; i++) { |
741 |
703 ec_sync_config(&slave->sii_syncs[i], |
742 for (i = 0; i < 2; i++) { |
704 datagram->data + EC_SYNC_SIZE * i); |
743 ec_sync_config(&slave->sii_syncs[i], |
|
744 datagram->data + EC_SYNC_SIZE * i); |
|
745 } |
|
746 } else { // no mailbox sync manager configurations provided |
|
747 ec_sync_t sync; |
|
748 |
|
749 if (master->debug_level) |
|
750 EC_DBG("Slave %i does not provide" |
|
751 " mailbox sync manager configurations.\n", |
|
752 slave->ring_position); |
|
753 |
|
754 ec_datagram_npwr(datagram, slave->station_address, 0x0800, |
|
755 EC_SYNC_SIZE * 2); |
|
756 memset(datagram->data, 0x00, EC_SYNC_SIZE * 2); |
|
757 |
|
758 ec_sync_init(&sync, slave, 0); |
|
759 sync.physical_start_address = slave->sii_rx_mailbox_offset; |
|
760 sync.length = slave->sii_rx_mailbox_size; |
|
761 sync.control_register = 0x26; |
|
762 sync.enable = 1; |
|
763 ec_sync_config(&sync, datagram->data + EC_SYNC_SIZE * sync.index); |
|
764 |
|
765 ec_sync_init(&sync, slave, 1); |
|
766 sync.physical_start_address = slave->sii_tx_mailbox_offset; |
|
767 sync.length = slave->sii_tx_mailbox_size; |
|
768 sync.control_register = 0x22; |
|
769 sync.enable = 1; |
|
770 ec_sync_config(&sync, datagram->data + EC_SYNC_SIZE * sync.index); |
705 } |
771 } |
706 |
772 |
707 fsm->retries = EC_FSM_RETRIES; |
773 fsm->retries = EC_FSM_RETRIES; |
708 fsm->state = ec_fsm_slave_conf_state_mbox_sync; |
774 fsm->state = ec_fsm_slave_conf_state_mbox_sync; |
709 } |
775 } |