111 slave->ring_position = ring_position; |
113 slave->ring_position = ring_position; |
112 slave->station_address = station_address; |
114 slave->station_address = station_address; |
113 |
115 |
114 slave->master = master; |
116 slave->master = master; |
115 |
117 |
|
118 slave->config = NULL; |
116 slave->requested_state = EC_SLAVE_STATE_PREOP; |
119 slave->requested_state = EC_SLAVE_STATE_PREOP; |
117 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
120 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
121 slave->online_state = EC_SLAVE_ONLINE; |
118 slave->self_configured = 0; |
122 slave->self_configured = 0; |
119 slave->error_flag = 0; |
123 slave->error_flag = 0; |
120 slave->online_state = EC_SLAVE_ONLINE; |
|
121 slave->fmmu_count = 0; |
|
122 slave->pdos_registered = 0; |
|
123 |
124 |
124 slave->base_type = 0; |
125 slave->base_type = 0; |
125 slave->base_revision = 0; |
126 slave->base_revision = 0; |
126 slave->base_build = 0; |
127 slave->base_build = 0; |
127 slave->base_fmmu_count = 0; |
128 slave->base_fmmu_count = 0; |
285 * SDO kobject clear method. |
280 * SDO kobject clear method. |
286 */ |
281 */ |
287 |
282 |
288 void ec_slave_sdos_clear(struct kobject *kobj /**< kobject for SDOs */) |
283 void ec_slave_sdos_clear(struct kobject *kobj /**< kobject for SDOs */) |
289 { |
284 { |
290 } |
|
291 |
|
292 /*****************************************************************************/ |
|
293 |
|
294 /** |
|
295 Reset slave from operation mode. |
|
296 */ |
|
297 |
|
298 void ec_slave_reset(ec_slave_t *slave /**< EtherCAT slave */) |
|
299 { |
|
300 ec_sdo_data_t *sdodata, *next_sdodata; |
|
301 unsigned int i; |
|
302 |
|
303 slave->fmmu_count = 0; |
|
304 slave->pdos_registered = 0; |
|
305 |
|
306 // free all SDO configurations |
|
307 list_for_each_entry_safe(sdodata, next_sdodata, &slave->sdo_confs, list) { |
|
308 list_del(&sdodata->list); |
|
309 kfree(sdodata->data); |
|
310 kfree(sdodata); |
|
311 } |
|
312 |
|
313 // remove estimated sync manager sizes |
|
314 for (i = 0; i < slave->sii_sync_count; i++) { |
|
315 slave->sii_syncs[i].est_length = 0; |
|
316 } |
|
317 } |
285 } |
318 |
286 |
319 /*****************************************************************************/ |
287 /*****************************************************************************/ |
320 |
288 |
321 /** |
289 /** |
349 ec_slave_online_state_t new_state /**< new online state */ |
317 ec_slave_online_state_t new_state /**< new online state */ |
350 ) |
318 ) |
351 { |
319 { |
352 if (new_state == EC_SLAVE_OFFLINE && |
320 if (new_state == EC_SLAVE_OFFLINE && |
353 slave->online_state == EC_SLAVE_ONLINE) { |
321 slave->online_state == EC_SLAVE_ONLINE) { |
354 if (slave->pdos_registered) |
|
355 slave->master->pdo_slaves_offline++; |
|
356 if (slave->master->debug_level) |
322 if (slave->master->debug_level) |
357 EC_DBG("Slave %u: offline.\n", slave->ring_position); |
323 EC_DBG("Slave %u: offline.\n", slave->ring_position); |
358 } |
324 } |
359 else if (new_state == EC_SLAVE_ONLINE && |
325 else if (new_state == EC_SLAVE_ONLINE && |
360 slave->online_state == EC_SLAVE_OFFLINE) { |
326 slave->online_state == EC_SLAVE_OFFLINE) { |
361 slave->error_flag = 0; // clear error flag |
327 slave->error_flag = 0; // clear error flag |
362 if (slave->pdos_registered) |
|
363 slave->master->pdo_slaves_offline--; |
|
364 if (slave->master->debug_level) { |
328 if (slave->master->debug_level) { |
365 char cur_state[EC_STATE_STRING_SIZE]; |
329 char cur_state[EC_STATE_STRING_SIZE]; |
366 ec_state_string(slave->current_state, cur_state); |
330 ec_state_string(slave->current_state, cur_state); |
367 EC_DBG("Slave %u: online (%s).\n", |
331 EC_DBG("Slave %u: online (%s).\n", |
368 slave->ring_position, cur_state); |
332 slave->ring_position, cur_state); |
562 if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) { |
531 if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) { |
563 EC_ERR("Failed to allocate PDO entry memory.\n"); |
532 EC_ERR("Failed to allocate PDO entry memory.\n"); |
564 return -1; |
533 return -1; |
565 } |
534 } |
566 |
535 |
|
536 ec_pdo_entry_init(entry); |
567 entry->index = EC_READ_U16(data); |
537 entry->index = EC_READ_U16(data); |
568 entry->subindex = EC_READ_U8(data + 2); |
538 entry->subindex = EC_READ_U8(data + 2); |
569 entry->name = ec_slave_sii_string(slave, EC_READ_U8(data + 3)); |
539 if (ec_pdo_entry_set_name(entry, |
|
540 ec_slave_sii_string(slave, EC_READ_U8(data + 3)))) { |
|
541 ec_pdo_entry_clear(entry); |
|
542 kfree(entry); |
|
543 return -1; |
|
544 } |
570 entry->bit_length = EC_READ_U8(data + 5); |
545 entry->bit_length = EC_READ_U8(data + 5); |
571 list_add_tail(&entry->list, &pdo->entries); |
546 list_add_tail(&entry->list, &pdo->entries); |
572 |
547 |
573 data_size -= 8; |
548 data_size -= 8; |
574 data += 8; |
549 data += 8; |
575 } |
550 } |
576 |
551 |
577 // if sync manager index is positive, the PDO is mapped by default |
552 // if sync manager index is positive, the PDO is mapped by default |
578 if (pdo->sync_index >= 0) { |
553 if (pdo->sync_index >= 0) { |
579 ec_sync_t *sync; |
554 ec_sync_t *sync; |
580 ec_pdo_t *mapped_pdo; |
|
581 |
555 |
582 if (pdo->sync_index >= slave->sii_sync_count) { |
556 if (pdo->sync_index >= slave->sii_sync_count) { |
583 EC_ERR("Invalid SM index %i for PDO 0x%04X in slave %u.", |
557 EC_ERR("Invalid SM index %i for PDO 0x%04X in slave %u.", |
584 pdo->sync_index, pdo->index, slave->ring_position); |
558 pdo->sync_index, pdo->index, slave->ring_position); |
585 return -1; |
559 return -1; |
586 } |
560 } |
587 sync = &slave->sii_syncs[pdo->sync_index]; |
561 sync = &slave->sii_syncs[pdo->sync_index]; |
588 |
562 |
589 if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) { |
563 if (ec_pdo_mapping_add_pdo(&sync->mapping, pdo)) |
590 EC_ERR("Failed to allocate PDO memory.\n"); |
|
591 return -1; |
564 return -1; |
592 } |
565 |
593 |
|
594 if (ec_pdo_copy(mapped_pdo, pdo)) { |
|
595 EC_ERR("Failed to copy PDO.\n"); |
|
596 kfree(mapped_pdo); |
|
597 return -1; |
|
598 } |
|
599 |
|
600 list_add_tail(&mapped_pdo->list, &sync->pdos); |
|
601 sync->mapping_source = EC_SYNC_MAPPING_SII; |
566 sync->mapping_source = EC_SYNC_MAPPING_SII; |
602 } |
567 } |
603 } |
568 } |
604 |
569 |
605 return 0; |
570 return 0; |
630 return slave->sii_strings[index]; |
595 return slave->sii_strings[index]; |
631 } |
596 } |
632 |
597 |
633 /*****************************************************************************/ |
598 /*****************************************************************************/ |
634 |
599 |
635 /** |
600 /** Outputs all information about a certain slave. |
636 * Prepares an FMMU configuration. |
|
637 * Configuration data for the FMMU is saved in the slave structure and is |
|
638 * written to the slave in ecrt_master_activate(). |
|
639 * The FMMU configuration is done in a way, that the complete data range |
|
640 * of the corresponding sync manager is covered. Seperate FMMUs are configured |
|
641 * for each domain. |
|
642 * If the FMMU configuration is already prepared, the function returns with |
|
643 * success. |
|
644 * \return 0 in case of success, else < 0 |
|
645 */ |
601 */ |
646 |
|
647 int ec_slave_prepare_fmmu( |
|
648 ec_slave_t *slave, /**< EtherCAT slave */ |
|
649 const ec_domain_t *domain, /**< domain */ |
|
650 const ec_sync_t *sync /**< sync manager */ |
|
651 ) |
|
652 { |
|
653 unsigned int i; |
|
654 ec_fmmu_t *fmmu; |
|
655 |
|
656 // FMMU configuration already prepared? |
|
657 for (i = 0; i < slave->fmmu_count; i++) { |
|
658 fmmu = &slave->fmmus[i]; |
|
659 if (fmmu->domain == domain && fmmu->sync == sync) |
|
660 return 0; |
|
661 } |
|
662 |
|
663 // reserve new FMMU... |
|
664 |
|
665 if (slave->fmmu_count >= slave->base_fmmu_count) { |
|
666 EC_ERR("Slave %u FMMU limit reached!\n", slave->ring_position); |
|
667 return -1; |
|
668 } |
|
669 |
|
670 fmmu = &slave->fmmus[slave->fmmu_count]; |
|
671 |
|
672 ec_fmmu_init(fmmu, slave, slave->fmmu_count++); |
|
673 fmmu->domain = domain; |
|
674 fmmu->sync = sync; |
|
675 fmmu->logical_start_address = 0; |
|
676 |
|
677 slave->pdos_registered = 1; |
|
678 |
|
679 ec_slave_request_state(slave, EC_SLAVE_STATE_OP); |
|
680 |
|
681 return 0; |
|
682 } |
|
683 |
|
684 /*****************************************************************************/ |
|
685 |
|
686 /** |
|
687 Outputs all information about a certain slave. |
|
688 */ |
|
689 |
|
690 ssize_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ |
602 ssize_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ |
691 char *buffer /**< Output buffer */ |
603 char *buffer /**< Output buffer */ |
692 ) |
604 ) |
693 { |
605 { |
694 ec_sync_t *sync; |
606 ec_sync_t *sync; |
695 ec_pdo_t *pdo; |
607 ec_pdo_t *pdo; |
696 ec_pdo_entry_t *pdo_entry; |
608 ec_pdo_entry_t *pdo_entry; |
697 int first, i; |
609 int first, i; |
698 ec_sdo_data_t *sdodata; |
|
699 char str[20]; |
|
700 char *large_buffer, *buf; |
610 char *large_buffer, *buf; |
701 unsigned int size; |
611 unsigned int size; |
702 |
612 |
703 if (!(large_buffer = (char *) kmalloc(PAGE_SIZE * 2, GFP_KERNEL))) { |
613 if (!(large_buffer = (char *) kmalloc(PAGE_SIZE * 2, GFP_KERNEL))) { |
704 return -ENOMEM; |
614 return -ENOMEM; |
711 buf += sprintf(buf, "State: "); |
621 buf += sprintf(buf, "State: "); |
712 buf += ec_state_string(slave->current_state, buf); |
622 buf += ec_state_string(slave->current_state, buf); |
713 buf += sprintf(buf, " ("); |
623 buf += sprintf(buf, " ("); |
714 buf += ec_state_string(slave->requested_state, buf); |
624 buf += ec_state_string(slave->requested_state, buf); |
715 buf += sprintf(buf, ")\n"); |
625 buf += sprintf(buf, ")\n"); |
716 buf += sprintf(buf, "Flags: %s, %s\n\n", |
626 buf += sprintf(buf, "Flags: %s\n\n", slave->error_flag ? "ERROR" : "ok"); |
717 slave->online_state == EC_SLAVE_ONLINE ? "online" : "OFFLINE", |
|
718 slave->error_flag ? "ERROR" : "ok"); |
|
719 |
627 |
720 buf += sprintf(buf, "Data link status:\n"); |
628 buf += sprintf(buf, "Data link status:\n"); |
721 for (i = 0; i < 4; i++) { |
629 for (i = 0; i < 4; i++) { |
722 buf += sprintf(buf, " Port %u: Phy %u (", |
630 buf += sprintf(buf, " Port %u: Phy %u (", |
723 i, slave->sii_physical_layer[i]); |
631 i, slave->sii_physical_layer[i]); |
819 for (i = 0; i < slave->sii_sync_count; i++) { |
727 for (i = 0; i < slave->sii_sync_count; i++) { |
820 sync = &slave->sii_syncs[i]; |
728 sync = &slave->sii_syncs[i]; |
821 buf += sprintf(buf, |
729 buf += sprintf(buf, |
822 " SM%u: addr 0x%04X, size %u, control 0x%02X, %s\n", |
730 " SM%u: addr 0x%04X, size %u, control 0x%02X, %s\n", |
823 sync->index, sync->physical_start_address, |
731 sync->index, sync->physical_start_address, |
824 ec_sync_size(sync), sync->control_register, |
732 sync->length, sync->control_register, |
825 sync->enable ? "enable" : "disable"); |
733 sync->enable ? "enable" : "disable"); |
826 |
734 |
827 if (list_empty(&sync->pdos)) { |
735 if (list_empty(&sync->mapping.pdos)) { |
828 buf += sprintf(buf, " No PDOs mapped.\n"); |
736 buf += sprintf(buf, " No PDOs mapped.\n"); |
829 } else if (sync->mapping_source != EC_SYNC_MAPPING_NONE) { |
737 } else if (sync->mapping_source != EC_SYNC_MAPPING_NONE) { |
830 buf += sprintf(buf, |
738 buf += sprintf(buf, |
831 " PDO mapping information from %s.\n", |
739 " PDO mapping information from %s.\n", |
832 sync->mapping_source == EC_SYNC_MAPPING_SII |
740 sync->mapping_source == EC_SYNC_MAPPING_SII |
833 ? "SII" : "CoE"); |
741 ? "SII" : "CoE"); |
834 } |
742 } |
835 |
743 |
836 list_for_each_entry(pdo, &sync->pdos, list) { |
744 list_for_each_entry(pdo, &sync->mapping.pdos, list) { |
837 buf += sprintf(buf, " %s 0x%04X \"%s\"\n", |
745 buf += sprintf(buf, " %s 0x%04X \"%s\"\n", |
838 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
746 pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo", |
839 pdo->index, pdo->name ? pdo->name : "???"); |
747 pdo->index, pdo->name ? pdo->name : "???"); |
840 |
748 |
841 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
749 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
842 buf += sprintf(buf, |
750 buf += sprintf(buf, |
843 " 0x%04X:%X \"%s\", %u bit\n", |
751 " 0x%04X:%X \"%s\", %u bit\n", |
854 if (!list_empty((struct list_head *) &slave->sii_pdos)) { |
762 if (!list_empty((struct list_head *) &slave->sii_pdos)) { |
855 buf += sprintf(buf, "Available PDOs from SII:\n"); |
763 buf += sprintf(buf, "Available PDOs from SII:\n"); |
856 |
764 |
857 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
765 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
858 buf += sprintf(buf, " %s 0x%04X \"%s\"", |
766 buf += sprintf(buf, " %s 0x%04X \"%s\"", |
859 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
767 pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo", |
860 pdo->index, pdo->name ? pdo->name : "???"); |
768 pdo->index, pdo->name ? pdo->name : "???"); |
861 if (pdo->sync_index >= 0) |
769 if (pdo->sync_index >= 0) |
862 buf += sprintf(buf, ", default mapping: SM%u.\n", |
770 buf += sprintf(buf, ", default mapping: SM%u.\n", |
863 pdo->sync_index); |
771 pdo->sync_index); |
864 else |
772 else |
868 buf += sprintf(buf, " 0x%04X:%X \"%s\", %u bit\n", |
776 buf += sprintf(buf, " 0x%04X:%X \"%s\", %u bit\n", |
869 pdo_entry->index, pdo_entry->subindex, |
777 pdo_entry->index, pdo_entry->subindex, |
870 pdo_entry->name ? pdo_entry->name : "???", |
778 pdo_entry->name ? pdo_entry->name : "???", |
871 pdo_entry->bit_length); |
779 pdo_entry->bit_length); |
872 } |
780 } |
873 } |
|
874 buf += sprintf(buf, "\n"); |
|
875 } |
|
876 |
|
877 // type-cast to avoid warnings on some compilers |
|
878 if (!list_empty((struct list_head *) &slave->sdo_confs)) { |
|
879 buf += sprintf(buf, "SDO configurations:\n"); |
|
880 |
|
881 list_for_each_entry(sdodata, &slave->sdo_confs, list) { |
|
882 switch (sdodata->size) { |
|
883 case 1: sprintf(str, "%u", EC_READ_U8(sdodata->data)); break; |
|
884 case 2: sprintf(str, "%u", EC_READ_U16(sdodata->data)); break; |
|
885 case 4: sprintf(str, "%u", EC_READ_U32(sdodata->data)); break; |
|
886 default: sprintf(str, "(invalid size)"); break; |
|
887 } |
|
888 buf += sprintf(buf, " 0x%04X:%-3i -> %s\n", |
|
889 sdodata->index, sdodata->subindex, str); |
|
890 } |
781 } |
891 buf += sprintf(buf, "\n"); |
782 buf += sprintf(buf, "\n"); |
892 } |
783 } |
893 |
784 |
894 size = buf - large_buffer; |
785 size = buf - large_buffer; |
1249 |
1140 |
1250 /** |
1141 /** |
1251 \return 0 in case of success, else < 0 |
1142 \return 0 in case of success, else < 0 |
1252 */ |
1143 */ |
1253 |
1144 |
1254 int ec_slave_conf_sdo(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1255 uint16_t sdo_index, /**< SDO index */ |
|
1256 uint8_t sdo_subindex, /**< SDO subindex */ |
|
1257 const uint8_t *data, /**< SDO data */ |
|
1258 size_t size /**< SDO size in bytes */ |
|
1259 ) |
|
1260 { |
|
1261 ec_sdo_data_t *sdodata; |
|
1262 |
|
1263 if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) { |
|
1264 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
|
1265 return -1; |
|
1266 } |
|
1267 |
|
1268 if (!(sdodata = (ec_sdo_data_t *) |
|
1269 kmalloc(sizeof(ec_sdo_data_t), GFP_KERNEL))) { |
|
1270 EC_ERR("Failed to allocate memory for SDO configuration object!\n"); |
|
1271 return -1; |
|
1272 } |
|
1273 |
|
1274 if (!(sdodata->data = (uint8_t *) kmalloc(size, GFP_KERNEL))) { |
|
1275 EC_ERR("Failed to allocate memory for SDO configuration data!\n"); |
|
1276 kfree(sdodata); |
|
1277 return -1; |
|
1278 } |
|
1279 |
|
1280 sdodata->index = sdo_index; |
|
1281 sdodata->subindex = sdo_subindex; |
|
1282 memcpy(sdodata->data, data, size); |
|
1283 sdodata->size = size; |
|
1284 |
|
1285 list_add_tail(&sdodata->list, &slave->sdo_confs); |
|
1286 return 0; |
|
1287 } |
|
1288 |
|
1289 /*****************************************************************************/ |
|
1290 |
|
1291 /** |
|
1292 \return 0 in case of success, else < 0 |
|
1293 */ |
|
1294 |
|
1295 int ec_slave_validate(const ec_slave_t *slave, /**< EtherCAT slave */ |
1145 int ec_slave_validate(const ec_slave_t *slave, /**< EtherCAT slave */ |
1296 uint32_t vendor_id, /**< vendor ID */ |
1146 uint32_t vendor_id, /**< vendor ID */ |
1297 uint32_t product_code /**< product code */ |
1147 uint32_t product_code /**< product code */ |
1298 ) |
1148 ) |
1299 { |
1149 { |
1355 } |
1205 } |
1356 |
1206 |
1357 return NULL; |
1207 return NULL; |
1358 } |
1208 } |
1359 |
1209 |
1360 /****************************************************************************** |
1210 /*****************************************************************************/ |
1361 * Realtime interface |
|
1362 *****************************************************************************/ |
|
1363 |
|
1364 /** |
|
1365 \return 0 in case of success, else < 0 |
|
1366 \ingroup RealtimeInterface |
|
1367 */ |
|
1368 |
|
1369 int ecrt_slave_conf_sdo8(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1370 uint16_t sdo_index, /**< SDO index */ |
|
1371 uint8_t sdo_subindex, /**< SDO subindex */ |
|
1372 uint8_t value /**< new SDO value */ |
|
1373 ) |
|
1374 { |
|
1375 uint8_t data[1]; |
|
1376 EC_WRITE_U8(data, value); |
|
1377 return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 1); |
|
1378 } |
|
1379 |
|
1380 /*****************************************************************************/ |
|
1381 |
|
1382 /** |
|
1383 \return 0 in case of success, else < 0 |
|
1384 \ingroup RealtimeInterface |
|
1385 */ |
|
1386 |
|
1387 int ecrt_slave_conf_sdo16(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1388 uint16_t sdo_index, /**< SDO index */ |
|
1389 uint8_t sdo_subindex, /**< SDO subindex */ |
|
1390 uint16_t value /**< new SDO value */ |
|
1391 ) |
|
1392 { |
|
1393 uint8_t data[2]; |
|
1394 EC_WRITE_U16(data, value); |
|
1395 return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 2); |
|
1396 } |
|
1397 |
|
1398 /*****************************************************************************/ |
|
1399 |
|
1400 /** |
|
1401 \return 0 in case of success, else < 0 |
|
1402 \ingroup RealtimeInterface |
|
1403 */ |
|
1404 |
|
1405 int ecrt_slave_conf_sdo32(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1406 uint16_t sdo_index, /**< SDO index */ |
|
1407 uint8_t sdo_subindex, /**< SDO subindex */ |
|
1408 uint32_t value /**< new SDO value */ |
|
1409 ) |
|
1410 { |
|
1411 uint8_t data[4]; |
|
1412 EC_WRITE_U32(data, value); |
|
1413 return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4); |
|
1414 } |
|
1415 |
|
1416 /*****************************************************************************/ |
|
1417 |
|
1418 /** |
|
1419 * Clear slave's PDO mapping. |
|
1420 */ |
|
1421 |
|
1422 void ecrt_slave_pdo_mapping_clear( |
|
1423 ec_slave_t *slave, /**< EtherCAT slave */ |
|
1424 ec_direction_t dir /**< output/input */ |
|
1425 ) |
|
1426 { |
|
1427 ec_sync_t *sync; |
|
1428 |
|
1429 if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) { |
|
1430 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
|
1431 return; |
|
1432 } |
|
1433 |
|
1434 if (!(sync = ec_slave_get_pdo_sync(slave, dir))) |
|
1435 return; |
|
1436 |
|
1437 ec_sync_clear_pdos(sync); |
|
1438 sync->alt_mapping = 1; |
|
1439 } |
|
1440 |
|
1441 /*****************************************************************************/ |
|
1442 |
|
1443 /** |
|
1444 * Add a PDO to the list of known mapped PDOs. |
|
1445 */ |
|
1446 |
|
1447 int ecrt_slave_pdo_mapping_add( |
|
1448 ec_slave_t *slave, /**< EtherCAT slave */ |
|
1449 ec_direction_t dir, /**< input/output */ |
|
1450 uint16_t pdo_index /**< Index of mapped PDO */) |
|
1451 { |
|
1452 ec_pdo_t *pdo; |
|
1453 ec_sync_t *sync; |
|
1454 unsigned int not_found = 1; |
|
1455 |
|
1456 if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) { |
|
1457 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
|
1458 return -1; |
|
1459 } |
|
1460 |
|
1461 // does the slave provide the PDO? FIXME |
|
1462 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
|
1463 if (pdo->index == pdo_index) { |
|
1464 not_found = 0; |
|
1465 break; |
|
1466 } |
|
1467 } |
|
1468 |
|
1469 if (not_found) { |
|
1470 EC_ERR("Slave %u does not provide PDO 0x%04X!\n", |
|
1471 slave->ring_position, pdo_index); |
|
1472 return -1; |
|
1473 } |
|
1474 |
|
1475 // check direction |
|
1476 if ((pdo->type == EC_TX_PDO && dir == EC_DIR_OUTPUT) || |
|
1477 (pdo->type == EC_RX_PDO && dir == EC_DIR_INPUT)) { |
|
1478 EC_ERR("Invalid direction for PDO 0x%04X.\n", pdo_index); |
|
1479 return -1; |
|
1480 } |
|
1481 |
|
1482 |
|
1483 if (!(sync = ec_slave_get_pdo_sync(slave, dir))) { |
|
1484 EC_ERR("Failed to obtain sync manager for PDO mapping of slave %u!\n", |
|
1485 slave->ring_position); |
|
1486 return -1; |
|
1487 } |
|
1488 |
|
1489 if (ec_sync_add_pdo(sync, pdo)) |
|
1490 return -1; |
|
1491 |
|
1492 sync->alt_mapping = 1; |
|
1493 return 0; |
|
1494 } |
|
1495 |
|
1496 /*****************************************************************************/ |
|
1497 |
|
1498 /** |
|
1499 * Convenience function for ecrt_slave_pdo_mapping_clear() and |
|
1500 * ecrt_slave_pdo_mapping_add(). |
|
1501 */ |
|
1502 |
|
1503 int ecrt_slave_pdo_mapping(ec_slave_t *slave, /**< EtherCAT slave */ |
|
1504 ec_direction_t dir, /**< input/output */ |
|
1505 unsigned int num_args, /**< Number of following arguments */ |
|
1506 ... /**< PDO indices to map */ |
|
1507 ) |
|
1508 { |
|
1509 va_list ap; |
|
1510 |
|
1511 ecrt_slave_pdo_mapping_clear(slave, dir); |
|
1512 |
|
1513 va_start(ap, num_args); |
|
1514 |
|
1515 for (; num_args; num_args--) { |
|
1516 if (ecrt_slave_pdo_mapping_add( |
|
1517 slave, dir, (uint16_t) va_arg(ap, int))) { |
|
1518 return -1; |
|
1519 } |
|
1520 } |
|
1521 |
|
1522 va_end(ap); |
|
1523 return 0; |
|
1524 } |
|
1525 |
|
1526 |
|
1527 /*****************************************************************************/ |
|
1528 |
|
1529 /** \cond */ |
|
1530 |
|
1531 EXPORT_SYMBOL(ecrt_slave_conf_sdo8); |
|
1532 EXPORT_SYMBOL(ecrt_slave_conf_sdo16); |
|
1533 EXPORT_SYMBOL(ecrt_slave_conf_sdo32); |
|
1534 EXPORT_SYMBOL(ecrt_slave_pdo_mapping_clear); |
|
1535 EXPORT_SYMBOL(ecrt_slave_pdo_mapping_add); |
|
1536 EXPORT_SYMBOL(ecrt_slave_pdo_mapping); |
|
1537 |
|
1538 /** \endcond */ |
|
1539 |
|
1540 /*****************************************************************************/ |
|