429 if (!(slave->eeprom_data = |
429 if (!(slave->eeprom_data = |
430 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
430 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) { |
431 slave->eeprom_size = 0; |
431 slave->eeprom_size = 0; |
432 slave->error_flag = 1; |
432 slave->error_flag = 1; |
433 fsm->state = ec_fsm_slave_state_error; |
433 fsm->state = ec_fsm_slave_state_error; |
434 EC_ERR("Failed to allocate EEPROM data on slave %i.\n", |
434 EC_ERR("Failed to allocate EEPROM data for slave %u.\n", |
435 slave->ring_position); |
435 slave->ring_position); |
436 return; |
436 return; |
437 } |
437 } |
438 |
438 |
439 // Start fetching EEPROM contents |
439 // Start fetching EEPROM contents |
465 return; |
465 return; |
466 } |
466 } |
467 |
467 |
468 // 2 words fetched |
468 // 2 words fetched |
469 |
469 |
470 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
470 if (fsm->sii_offset + 2 <= eeprom_word_size) { // 2 words fit |
471 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
471 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
472 fsm->fsm_sii.value, 4); |
472 fsm->fsm_sii.value, 4); |
473 } |
473 } |
474 else { // copy the last word |
474 else { // copy the last word |
475 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
475 memcpy(slave->eeprom_data + fsm->sii_offset * 2, |
476 fsm->fsm_sii.value, 2); |
476 fsm->fsm_sii.value, 2); |
477 } |
477 } |
478 |
478 |
479 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
479 if (fsm->sii_offset + 2 < eeprom_word_size) { |
480 // fetch the next 2 words |
480 // fetch the next 2 words |
481 fsm->sii_offset += 2; |
481 fsm->sii_offset += 2; |
482 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
482 ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset, |
483 EC_FSM_SII_NODE); |
483 EC_FSM_SII_NODE); |
484 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
484 ec_fsm_sii_exec(&fsm->fsm_sii); // execute state immediately |
506 slave->sii_tx_mailbox_size = |
506 slave->sii_tx_mailbox_size = |
507 EC_READ_U16(slave->eeprom_data + 2 * 0x001B); |
507 EC_READ_U16(slave->eeprom_data + 2 * 0x001B); |
508 slave->sii_mailbox_protocols = |
508 slave->sii_mailbox_protocols = |
509 EC_READ_U16(slave->eeprom_data + 2 * 0x001C); |
509 EC_READ_U16(slave->eeprom_data + 2 * 0x001C); |
510 |
510 |
|
511 if (eeprom_word_size < EC_FIRST_EEPROM_CATEGORY_OFFSET + 1) { |
|
512 EC_ERR("Unexpected end of EEPROM data in slave %u.\n", |
|
513 slave->ring_position); |
|
514 goto end; |
|
515 } |
|
516 |
511 // evaluate category data |
517 // evaluate category data |
512 cat_word = (uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
518 cat_word = |
|
519 (uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
513 while (EC_READ_U16(cat_word) != 0xFFFF) { |
520 while (EC_READ_U16(cat_word) != 0xFFFF) { |
|
521 |
|
522 // type and size words must fit |
|
523 if (cat_word + 2 - (uint16_t *) slave->eeprom_data |
|
524 > eeprom_word_size) { |
|
525 EC_ERR("Unexpected end of EEPROM data in slave %u.\n", |
|
526 slave->ring_position); |
|
527 goto end; |
|
528 } |
|
529 |
514 cat_type = EC_READ_U16(cat_word) & 0x7FFF; |
530 cat_type = EC_READ_U16(cat_word) & 0x7FFF; |
515 cat_size = EC_READ_U16(cat_word + 1); |
531 cat_size = EC_READ_U16(cat_word + 1); |
|
532 cat_word += 2; |
|
533 |
|
534 if (cat_word + cat_size - (uint16_t *) slave->eeprom_data |
|
535 > eeprom_word_size) { |
|
536 EC_WARN("Unexpected end of EEPROM data in slave %u.\n", |
|
537 slave->ring_position); |
|
538 goto end; |
|
539 } |
516 |
540 |
517 switch (cat_type) { |
541 switch (cat_type) { |
518 case 0x000A: |
542 case 0x000A: |
519 if (ec_slave_fetch_sii_strings( |
543 if (ec_slave_fetch_sii_strings(slave, (uint8_t *) cat_word, |
520 slave, (uint8_t *) (cat_word + 2))) |
544 cat_size * 2)) |
521 goto end; |
545 goto end; |
522 break; |
546 break; |
523 case 0x001E: |
547 case 0x001E: |
524 ec_slave_fetch_sii_general( |
548 if (ec_slave_fetch_sii_general(slave, (uint8_t *) cat_word, |
525 slave, (uint8_t *) (cat_word + 2)); |
549 cat_size * 2)) |
|
550 goto end; |
526 break; |
551 break; |
527 case 0x0028: |
552 case 0x0028: |
528 break; |
553 break; |
529 case 0x0029: |
554 case 0x0029: |
530 if (ec_slave_fetch_sii_syncs( |
555 if (ec_slave_fetch_sii_syncs(slave, (uint8_t *) cat_word, |
531 slave, (uint8_t *) (cat_word + 2), cat_size)) |
556 cat_size * 2)) |
532 goto end; |
557 goto end; |
533 break; |
558 break; |
534 case 0x0032: |
559 case 0x0032: |
535 if (ec_slave_fetch_sii_pdos( |
560 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word, |
536 slave, (uint8_t *) (cat_word + 2), |
561 cat_size * 2, EC_TX_PDO)) |
537 cat_size, EC_TX_PDO)) |
|
538 goto end; |
562 goto end; |
539 break; |
563 break; |
540 case 0x0033: |
564 case 0x0033: |
541 if (ec_slave_fetch_sii_pdos( |
565 if (ec_slave_fetch_sii_pdos( slave, (uint8_t *) cat_word, |
542 slave, (uint8_t *) (cat_word + 2), |
566 cat_size * 2, EC_RX_PDO)) |
543 cat_size, EC_RX_PDO)) |
|
544 goto end; |
567 goto end; |
545 break; |
568 break; |
546 default: |
569 default: |
547 if (fsm->slave->master->debug_level) |
570 if (fsm->slave->master->debug_level) |
548 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
571 EC_WARN("Unknown category type 0x%04X in slave %i.\n", |
549 cat_type, slave->ring_position); |
572 cat_type, slave->ring_position); |
550 } |
573 } |
551 |
574 |
552 cat_word += cat_size + 2; |
575 cat_word += cat_size; |
|
576 if (cat_word - (uint16_t *) slave->eeprom_data >= eeprom_word_size) { |
|
577 EC_WARN("Unexpected end of EEPROM data in slave %u.\n", |
|
578 slave->ring_position); |
|
579 goto end; |
|
580 } |
553 } |
581 } |
554 |
582 |
555 fsm->state = ec_fsm_slave_state_end; |
583 fsm->state = ec_fsm_slave_state_end; |
556 return; |
584 return; |
557 |
585 |