133 * manager is covered. Seperate FMMUs are configured for each domain. If the |
133 * manager is covered. Seperate FMMUs are configured for each domain. If the |
134 * FMMU configuration is already prepared, the function does nothing and |
134 * FMMU configuration is already prepared, the function does nothing and |
135 * returns with success. |
135 * returns with success. |
136 * |
136 * |
137 * \retval >=0 Success, logical offset byte address. |
137 * \retval >=0 Success, logical offset byte address. |
138 * \retval -1 Error, FMMU limit reached. |
138 * \retval <0 Error code. |
139 */ |
139 */ |
140 int ec_slave_config_prepare_fmmu( |
140 int ec_slave_config_prepare_fmmu( |
141 ec_slave_config_t *sc, /**< Slave configuration. */ |
141 ec_slave_config_t *sc, /**< Slave configuration. */ |
142 ec_domain_t *domain, /**< Domain. */ |
142 ec_domain_t *domain, /**< Domain. */ |
143 uint8_t sync_index, /**< Sync manager index. */ |
143 uint8_t sync_index, /**< Sync manager index. */ |
190 if (!(slave = ec_master_find_slave( |
188 if (!(slave = ec_master_find_slave( |
191 sc->master, sc->alias, sc->position))) { |
189 sc->master, sc->alias, sc->position))) { |
192 if (sc->master->debug_level) |
190 if (sc->master->debug_level) |
193 EC_DBG("Failed to find slave for configuration %u:%u.\n", |
191 EC_DBG("Failed to find slave for configuration %u:%u.\n", |
194 sc->alias, sc->position); |
192 sc->alias, sc->position); |
195 return -1; |
193 return -ENOENT; |
196 } |
194 } |
197 |
195 |
198 if (slave->config) { |
196 if (slave->config) { |
199 if (sc->master->debug_level) |
197 if (sc->master->debug_level) |
200 EC_DBG("Failed to attach slave configuration %u:%u. Slave %u" |
198 EC_DBG("Failed to attach slave configuration %u:%u. Slave %u" |
201 " already has a configuration!\n", sc->alias, |
199 " already has a configuration!\n", sc->alias, |
202 sc->position, slave->ring_position); |
200 sc->position, slave->ring_position); |
203 return -2; |
201 return -EEXIST; |
204 } |
202 } |
205 |
203 |
206 if (slave->sii.vendor_id != sc->vendor_id |
204 if (slave->sii.vendor_id != sc->vendor_id |
207 || slave->sii.product_code != sc->product_code) { |
205 || slave->sii.product_code != sc->product_code) { |
208 if (sc->master->debug_level) |
206 if (sc->master->debug_level) |
209 EC_DBG("Slave %u has an invalid type (0x%08X/0x%08X) for" |
207 EC_DBG("Slave %u has an invalid type (0x%08X/0x%08X) for" |
210 " configuration %u:%u (0x%08X/0x%08X).\n", |
208 " configuration %u:%u (0x%08X/0x%08X).\n", |
211 slave->ring_position, slave->sii.vendor_id, |
209 slave->ring_position, slave->sii.vendor_id, |
212 slave->sii.product_code, sc->alias, sc->position, |
210 slave->sii.product_code, sc->alias, sc->position, |
213 sc->vendor_id, sc->product_code); |
211 sc->vendor_id, sc->product_code); |
214 return -3; |
212 return -EINVAL; |
215 } |
213 } |
216 |
214 |
217 // attach slave |
215 // attach slave |
218 slave->config = sc; |
216 slave->config = sc; |
219 sc->slave = slave; |
217 sc->slave = slave; |
397 EC_DBG("ecrt_slave_config_sync_manager(sc = 0x%x, sync_index = %u, " |
395 EC_DBG("ecrt_slave_config_sync_manager(sc = 0x%x, sync_index = %u, " |
398 "dir = %u)\n", (u32) sc, sync_index, dir); |
396 "dir = %u)\n", (u32) sc, sync_index, dir); |
399 |
397 |
400 if (sync_index >= EC_MAX_SYNC_MANAGERS) { |
398 if (sync_index >= EC_MAX_SYNC_MANAGERS) { |
401 EC_ERR("Invalid sync manager index %u!\n", sync_index); |
399 EC_ERR("Invalid sync manager index %u!\n", sync_index); |
402 return -1; |
400 return -ENOENT; |
403 } |
401 } |
404 |
402 |
405 if (dir != EC_DIR_OUTPUT && dir != EC_DIR_INPUT) { |
403 if (dir != EC_DIR_OUTPUT && dir != EC_DIR_INPUT) { |
406 EC_ERR("Invalid direction %u!\n", (u32) dir); |
404 EC_ERR("Invalid direction %u!\n", (u32) dir); |
407 return -1; |
405 return -EINVAL; |
408 } |
406 } |
409 |
407 |
410 sync_config = &sc->sync_configs[sync_index]; |
408 sync_config = &sc->sync_configs[sync_index]; |
411 sync_config->dir = dir; |
409 sync_config->dir = dir; |
412 return 0; |
410 return 0; |
423 EC_DBG("ecrt_slave_config_pdo_assign_add(sc = 0x%x, sync_index = %u, " |
421 EC_DBG("ecrt_slave_config_pdo_assign_add(sc = 0x%x, sync_index = %u, " |
424 "pdo_index = 0x%04X)\n", (u32) sc, sync_index, pdo_index); |
422 "pdo_index = 0x%04X)\n", (u32) sc, sync_index, pdo_index); |
425 |
423 |
426 if (sync_index >= EC_MAX_SYNC_MANAGERS) { |
424 if (sync_index >= EC_MAX_SYNC_MANAGERS) { |
427 EC_ERR("Invalid sync manager index %u!\n", sync_index); |
425 EC_ERR("Invalid sync manager index %u!\n", sync_index); |
428 return -1; |
426 return -EINVAL; |
429 } |
427 } |
430 |
428 |
431 down(&sc->master->master_sem); |
429 down(&sc->master->master_sem); |
432 |
430 |
433 if (!(pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, |
431 pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index); |
434 pdo_index))) { |
432 if (IS_ERR(pdo)) { |
435 up(&sc->master->master_sem); |
433 up(&sc->master->master_sem); |
436 return -1; |
434 return PTR_ERR(pdo); |
437 } |
435 } |
438 pdo->sync_index = sync_index; |
436 pdo->sync_index = sync_index; |
439 |
437 |
440 ec_slave_config_load_default_mapping(sc, pdo); |
438 ec_slave_config_load_default_mapping(sc, pdo); |
441 |
439 |
468 uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex, |
466 uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex, |
469 uint8_t entry_bit_length) |
467 uint8_t entry_bit_length) |
470 { |
468 { |
471 uint8_t sync_index; |
469 uint8_t sync_index; |
472 ec_pdo_t *pdo = NULL; |
470 ec_pdo_t *pdo = NULL; |
473 int retval = -1; |
471 ec_pdo_entry_t *entry; |
|
472 int retval = 0; |
474 |
473 |
475 if (sc->master->debug_level) |
474 if (sc->master->debug_level) |
476 EC_DBG("ecrt_slave_config_pdo_mapping_add(sc = 0x%x, " |
475 EC_DBG("ecrt_slave_config_pdo_mapping_add(sc = 0x%x, " |
477 "pdo_index = 0x%04X, entry_index = 0x%04X, " |
476 "pdo_index = 0x%04X, entry_index = 0x%04X, " |
478 "entry_subindex = 0x%02X, entry_bit_length = %u)\n", |
477 "entry_subindex = 0x%02X, entry_bit_length = %u)\n", |
484 &sc->sync_configs[sync_index].pdos, pdo_index))) |
483 &sc->sync_configs[sync_index].pdos, pdo_index))) |
485 break; |
484 break; |
486 |
485 |
487 if (pdo) { |
486 if (pdo) { |
488 down(&sc->master->master_sem); |
487 down(&sc->master->master_sem); |
489 retval = ec_pdo_add_entry(pdo, entry_index, entry_subindex, |
488 entry = ec_pdo_add_entry(pdo, entry_index, entry_subindex, |
490 entry_bit_length) ? 0 : -1; |
489 entry_bit_length); |
491 up(&sc->master->master_sem); |
490 up(&sc->master->master_sem); |
|
491 if (IS_ERR(entry)) |
|
492 retval = PTR_ERR(entry); |
492 } else { |
493 } else { |
493 EC_ERR("Pdo 0x%04X is not assigned in config %u:%u.\n", |
494 EC_ERR("Pdo 0x%04X is not assigned in config %u:%u.\n", |
494 pdo_index, sc->alias, sc->position); |
495 pdo_index, sc->alias, sc->position); |
|
496 retval = -ENOENT; |
495 } |
497 } |
496 |
498 |
497 return retval; |
499 return retval; |
498 } |
500 } |
499 |
501 |
547 if (sync_info->index == (uint8_t) EC_END) |
550 if (sync_info->index == (uint8_t) EC_END) |
548 break; |
551 break; |
549 |
552 |
550 if (sync_info->index >= EC_MAX_SYNC_MANAGERS) { |
553 if (sync_info->index >= EC_MAX_SYNC_MANAGERS) { |
551 EC_ERR("Invalid sync manager index %u!\n", sync_info->index); |
554 EC_ERR("Invalid sync manager index %u!\n", sync_info->index); |
552 return -1; |
555 return -ENOENT; |
553 } |
556 } |
554 |
557 |
555 if (ecrt_slave_config_sync_manager( |
558 ret = ecrt_slave_config_sync_manager( |
556 sc, sync_info->index, sync_info->dir)) |
559 sc, sync_info->index, sync_info->dir); |
557 return -1; |
560 if (ret) |
|
561 return ret; |
558 |
562 |
559 if (sync_info->n_pdos && sync_info->pdos) { |
563 if (sync_info->n_pdos && sync_info->pdos) { |
560 ecrt_slave_config_pdo_assign_clear(sc, sync_info->index); |
564 ecrt_slave_config_pdo_assign_clear(sc, sync_info->index); |
561 |
565 |
562 for (j = 0; j < sync_info->n_pdos; j++) { |
566 for (j = 0; j < sync_info->n_pdos; j++) { |
563 pdo_info = &sync_info->pdos[j]; |
567 pdo_info = &sync_info->pdos[j]; |
564 |
568 |
565 if (ecrt_slave_config_pdo_assign_add( |
569 ret = ecrt_slave_config_pdo_assign_add( |
566 sc, sync_info->index, pdo_info->index)) |
570 sc, sync_info->index, pdo_info->index); |
567 return -1; |
571 if (ret) |
|
572 return ret; |
568 |
573 |
569 if (pdo_info->n_entries && pdo_info->entries) { |
574 if (pdo_info->n_entries && pdo_info->entries) { |
570 ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index); |
575 ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index); |
571 |
576 |
572 for (k = 0; k < pdo_info->n_entries; k++) { |
577 for (k = 0; k < pdo_info->n_entries; k++) { |
573 entry_info = &pdo_info->entries[k]; |
578 entry_info = &pdo_info->entries[k]; |
574 |
579 |
575 if (ecrt_slave_config_pdo_mapping_add(sc, |
580 ret = ecrt_slave_config_pdo_mapping_add(sc, |
576 pdo_info->index, entry_info->index, |
581 pdo_info->index, entry_info->index, |
577 entry_info->subindex, |
582 entry_info->subindex, |
578 entry_info->bit_length)) |
583 entry_info->bit_length); |
579 return -1; |
584 if (ret) |
|
585 return ret; |
580 } |
586 } |
581 } |
587 } |
582 } |
588 } |
583 } |
589 } |
584 } |
590 } |
622 *bit_position = bit_pos; |
628 *bit_position = bit_pos; |
623 } else if (bit_pos) { |
629 } else if (bit_pos) { |
624 EC_ERR("Pdo entry 0x%04X:%02X does not byte-align " |
630 EC_ERR("Pdo entry 0x%04X:%02X does not byte-align " |
625 "in config %u:%u.\n", index, subindex, |
631 "in config %u:%u.\n", index, subindex, |
626 sc->alias, sc->position); |
632 sc->alias, sc->position); |
627 return -3; |
633 return -EFAULT; |
628 } |
634 } |
629 |
635 |
630 sync_offset = ec_slave_config_prepare_fmmu( |
636 sync_offset = ec_slave_config_prepare_fmmu( |
631 sc, domain, sync_index, sync_config->dir); |
637 sc, domain, sync_index, sync_config->dir); |
632 if (sync_offset < 0) |
638 if (sync_offset < 0) |
633 return -2; |
639 return sync_offset; |
634 |
640 |
635 return sync_offset + bit_offset / 8; |
641 return sync_offset + bit_offset / 8; |
636 } |
642 } |
637 } |
643 } |
638 } |
644 } |
639 } |
645 } |
640 |
646 |
641 EC_ERR("Pdo entry 0x%04X:%02X is not mapped in slave config %u:%u.\n", |
647 EC_ERR("Pdo entry 0x%04X:%02X is not mapped in slave config %u:%u.\n", |
642 index, subindex, sc->alias, sc->position); |
648 index, subindex, sc->alias, sc->position); |
643 return -1; |
649 return -ENOENT; |
644 } |
650 } |
645 |
651 |
646 |
652 |
647 /*****************************************************************************/ |
653 /*****************************************************************************/ |
648 |
654 |
649 int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index, |
655 int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index, |
650 uint8_t subindex, const uint8_t *data, size_t size) |
656 uint8_t subindex, const uint8_t *data, size_t size) |
651 { |
657 { |
652 ec_slave_t *slave = sc->slave; |
658 ec_slave_t *slave = sc->slave; |
653 ec_sdo_request_t *req; |
659 ec_sdo_request_t *req; |
|
660 int ret; |
654 |
661 |
655 if (sc->master->debug_level) |
662 if (sc->master->debug_level) |
656 EC_DBG("ecrt_slave_config_sdo(sc = 0x%x, index = 0x%04X, " |
663 EC_DBG("ecrt_slave_config_sdo(sc = 0x%x, index = 0x%04X, " |
657 "subindex = 0x%02X, data = 0x%x, size = %u)\n", (u32) sc, |
664 "subindex = 0x%02X, data = 0x%x, size = %u)\n", (u32) sc, |
658 index, subindex, (u32) data, size); |
665 index, subindex, (u32) data, size); |
659 |
666 |
660 if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) { |
667 if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) { |
661 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
668 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
662 return -1; |
669 return -EPROTONOSUPPORT; // protocol not supported |
663 } |
670 } |
664 |
671 |
665 if (!(req = (ec_sdo_request_t *) |
672 if (!(req = (ec_sdo_request_t *) |
666 kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) { |
673 kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) { |
667 EC_ERR("Failed to allocate memory for Sdo configuration!\n"); |
674 EC_ERR("Failed to allocate memory for Sdo configuration!\n"); |
668 return -1; |
675 return -ENOMEM; |
669 } |
676 } |
670 |
677 |
671 ec_sdo_request_init(req); |
678 ec_sdo_request_init(req); |
672 ec_sdo_request_address(req, index, subindex); |
679 ec_sdo_request_address(req, index, subindex); |
673 |
680 |
674 if (ec_sdo_request_copy_data(req, data, size)) { |
681 ret = ec_sdo_request_copy_data(req, data, size); |
|
682 if (ret < 0) { |
675 ec_sdo_request_clear(req); |
683 ec_sdo_request_clear(req); |
676 kfree(req); |
684 kfree(req); |
677 return -1; |
685 return ret; |
678 } |
686 } |
679 |
687 |
680 down(&sc->master->master_sem); |
688 down(&sc->master->master_sem); |
681 list_add_tail(&req->list, &sc->sdo_configs); |
689 list_add_tail(&req->list, &sc->sdo_configs); |
682 up(&sc->master->master_sem); |
690 up(&sc->master->master_sem); |
683 |
|
684 return 0; |
691 return 0; |
685 } |
692 } |
686 |
693 |
687 /*****************************************************************************/ |
694 /*****************************************************************************/ |
688 |
695 |