62 ) |
62 ) |
63 { |
63 { |
64 EC_INFO("Initializing master %i.\n", index); |
64 EC_INFO("Initializing master %i.\n", index); |
65 |
65 |
66 master->index = index; |
66 master->index = index; |
67 master->slaves = NULL; |
|
68 master->device = NULL; |
67 master->device = NULL; |
69 master->reserved = 0; |
68 master->reserved = 0; |
70 |
69 |
|
70 INIT_LIST_HEAD(&master->slaves); |
71 INIT_LIST_HEAD(&master->command_queue); |
71 INIT_LIST_HEAD(&master->command_queue); |
72 INIT_LIST_HEAD(&master->domains); |
72 INIT_LIST_HEAD(&master->domains); |
73 INIT_LIST_HEAD(&master->eoe_slaves); |
73 INIT_LIST_HEAD(&master->eoe_slaves); |
74 |
74 |
75 // Init kobject and add it to the hierarchy |
75 // Init kobject and add it to the hierarchy |
128 |
128 |
129 void ec_master_reset(ec_master_t *master |
129 void ec_master_reset(ec_master_t *master |
130 /**< Zeiger auf den zurückzusetzenden Master */ |
130 /**< Zeiger auf den zurückzusetzenden Master */ |
131 ) |
131 ) |
132 { |
132 { |
133 unsigned int i; |
133 ec_slave_t *slave, *next_s; |
134 ec_command_t *command, *next_c; |
134 ec_command_t *command, *next_c; |
135 ec_domain_t *domain, *next_d; |
135 ec_domain_t *domain, *next_d; |
136 ec_eoe_t *eoe, *next_eoe; |
136 ec_eoe_t *eoe, *next_eoe; |
137 |
137 |
138 // Alle Slaves entfernen |
138 // Alle Slaves entfernen |
139 if (master->slaves) { |
139 list_for_each_entry_safe(slave, next_s, &master->slaves, list) { |
140 for (i = 0; i < master->slave_count; i++) |
140 list_del(&slave->list); |
141 ec_slave_clear(master->slaves + i); |
141 kobject_del(&slave->kobj); |
142 kfree(master->slaves); |
142 kobject_put(&slave->kobj); |
143 master->slaves = NULL; |
|
144 } |
143 } |
145 master->slave_count = 0; |
144 master->slave_count = 0; |
146 |
145 |
147 // Kommando-Warteschlange leeren |
146 // Kommando-Warteschlange leeren |
148 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
147 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
|
148 list_del_init(&command->queue); |
149 command->state = EC_CMD_ERROR; |
149 command->state = EC_CMD_ERROR; |
150 list_del_init(&command->queue); |
|
151 } |
150 } |
152 |
151 |
153 // Domain-Liste leeren |
152 // Domain-Liste leeren |
154 list_for_each_entry_safe(domain, next_d, &master->domains, list) { |
153 list_for_each_entry_safe(domain, next_d, &master->domains, list) { |
155 list_del(&domain->list); |
154 list_del(&domain->list); |
453 \return 0 bei Erfolg, sonst < 0 |
452 \return 0 bei Erfolg, sonst < 0 |
454 */ |
453 */ |
455 |
454 |
456 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */) |
455 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */) |
457 { |
456 { |
458 ec_slave_t *slave; |
457 ec_slave_t *slave, *next; |
459 ec_slave_ident_t *ident; |
458 ec_slave_ident_t *ident; |
460 unsigned int i; |
459 unsigned int i; |
461 ec_command_t *command; |
460 ec_command_t *command; |
462 ec_eoe_t *eoe; |
461 ec_eoe_t *eoe; |
463 |
462 uint16_t buscoupler_index, index_after_buscoupler; |
464 if (master->slaves || master->slave_count) { |
463 |
|
464 if (!list_empty(&master->slaves)) { |
465 EC_ERR("Slave scan already done!\n"); |
465 EC_ERR("Slave scan already done!\n"); |
466 return -1; |
466 return -1; |
467 } |
467 } |
468 |
468 |
469 command = &master->simple_command; |
469 command = &master->simple_command; |
474 master->slave_count = command->working_counter; |
474 master->slave_count = command->working_counter; |
475 EC_INFO("Found %i slaves on bus.\n", master->slave_count); |
475 EC_INFO("Found %i slaves on bus.\n", master->slave_count); |
476 |
476 |
477 if (!master->slave_count) return 0; |
477 if (!master->slave_count) return 0; |
478 |
478 |
479 if (!(master->slaves = (ec_slave_t *) |
|
480 kmalloc(master->slave_count * sizeof(ec_slave_t), GFP_KERNEL))) { |
|
481 EC_ERR("Failed to allocate slaves!\n"); |
|
482 return -1; |
|
483 } |
|
484 |
|
485 // Init slaves |
479 // Init slaves |
486 for (i = 0; i < master->slave_count; i++) { |
480 for (i = 0; i < master->slave_count; i++) { |
487 slave = master->slaves + i; |
481 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { |
488 ec_slave_init(slave, master); |
482 EC_ERR("Failed to allocate slave %i!\n", i); |
489 slave->ring_position = i; |
483 goto out_free; |
490 slave->station_address = i + 1; |
484 } |
491 } |
485 |
|
486 if (ec_slave_init(slave, master, i, i + 1)) goto out_free; |
|
487 |
|
488 if (kobject_add(&slave->kobj)) { |
|
489 EC_ERR("Failed to add kobject.\n"); |
|
490 kobject_put(&slave->kobj); // free |
|
491 goto out_free; |
|
492 } |
|
493 |
|
494 list_add_tail(&slave->list, &master->slaves); |
|
495 } |
|
496 |
|
497 buscoupler_index = 0xFFFF; |
|
498 index_after_buscoupler = 0; |
492 |
499 |
493 // For every slave on the bus |
500 // For every slave on the bus |
494 for (i = 0; i < master->slave_count; i++) { |
501 list_for_each_entry(slave, &master->slaves, list) { |
495 slave = master->slaves + i; |
|
496 |
502 |
497 // Write station address |
503 // Write station address |
498 if (ec_command_apwr(command, slave->ring_position, |
504 if (ec_command_apwr(command, slave->ring_position, 0x0010, |
499 0x0010, sizeof(uint16_t))) return -1; |
505 sizeof(uint16_t))) goto out_free; |
500 EC_WRITE_U16(command->data, slave->station_address); |
506 EC_WRITE_U16(command->data, slave->station_address); |
501 if (unlikely(ec_master_simple_io(master, command))) { |
507 if (unlikely(ec_master_simple_io(master, command))) { |
502 EC_ERR("Writing station address failed on slave %i!\n", i); |
508 EC_ERR("Writing station address failed on slave %i!\n", |
503 return -1; |
509 slave->ring_position); |
|
510 goto out_free; |
504 } |
511 } |
505 |
512 |
506 // Fetch all slave information |
513 // Fetch all slave information |
507 if (ec_slave_fetch(slave)) return -1; |
514 if (ec_slave_fetch(slave)) goto out_free; |
508 |
515 |
509 // Search for identification in "database" |
516 // Search for identification in "database" |
510 ident = slave_idents; |
517 ident = slave_idents; |
511 while (ident->type) { |
518 while (ident->type) { |
512 if (unlikely(ident->vendor_id == slave->sii_vendor_id |
519 if (unlikely(ident->vendor_id == slave->sii_vendor_id |
519 |
526 |
520 if (!slave->type) |
527 if (!slave->type) |
521 EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at" |
528 EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at" |
522 " position %i.\n", slave->sii_vendor_id, |
529 " position %i.\n", slave->sii_vendor_id, |
523 slave->sii_product_code, i); |
530 slave->sii_product_code, i); |
|
531 else { |
|
532 if (slave->type->special == EC_TYPE_BUS_COUPLER) { |
|
533 buscoupler_index++; |
|
534 index_after_buscoupler = 0; |
|
535 } |
|
536 } |
|
537 |
|
538 slave->buscoupler_index = buscoupler_index; |
|
539 slave->index_after_buscoupler = index_after_buscoupler; |
|
540 index_after_buscoupler++; |
524 |
541 |
525 // Does the slave support EoE? |
542 // Does the slave support EoE? |
526 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
543 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
527 if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { |
544 if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { |
528 EC_ERR("Failed to allocate EoE-Object.\n"); |
545 EC_ERR("Failed to allocate EoE-Object.\n"); |
529 return -1; |
546 goto out_free; |
530 } |
547 } |
531 |
548 |
532 ec_eoe_init(eoe, slave); |
549 ec_eoe_init(eoe, slave); |
533 list_add_tail(&eoe->list, &master->eoe_slaves); |
550 list_add_tail(&eoe->list, &master->eoe_slaves); |
534 } |
551 } |
535 } |
552 } |
536 |
553 |
537 return 0; |
554 return 0; |
|
555 |
|
556 out_free: |
|
557 list_for_each_entry_safe(slave, next, &master->slaves, list) { |
|
558 list_del(&slave->list); |
|
559 kobject_del(&slave->kobj); |
|
560 kobject_put(&slave->kobj); |
|
561 } |
|
562 return -1; |
538 } |
563 } |
539 |
564 |
540 /*****************************************************************************/ |
565 /*****************************************************************************/ |
541 |
566 |
542 /** |
567 /** |
598 const char *address /**< Address-String */ |
623 const char *address /**< Address-String */ |
599 ) |
624 ) |
600 { |
625 { |
601 unsigned long first, second; |
626 unsigned long first, second; |
602 char *remainder, *remainder2; |
627 char *remainder, *remainder2; |
603 unsigned int i, alias_requested, alias_slave_index, alias_found; |
628 unsigned int alias_requested, alias_found; |
604 int coupler_idx, slave_idx; |
629 ec_slave_t *alias_slave = NULL, *slave; |
605 ec_slave_t *slave; |
|
606 |
630 |
607 if (!address || address[0] == 0) return NULL; |
631 if (!address || address[0] == 0) return NULL; |
608 |
632 |
609 alias_requested = 0; |
633 alias_requested = 0; |
610 alias_slave_index = 0; |
|
611 if (address[0] == '#') { |
634 if (address[0] == '#') { |
612 alias_requested = 1; |
635 alias_requested = 1; |
613 address++; |
636 address++; |
614 } |
637 } |
615 |
638 |
659 EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address); |
681 EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address); |
660 return NULL; |
682 return NULL; |
661 } |
683 } |
662 |
684 |
663 if (alias_requested) { |
685 if (alias_requested) { |
664 for (i = alias_slave_index + 1; i < master->slave_count; i++) { |
686 list_for_each_entry(slave, &master->slaves, list) { |
665 slave = master->slaves + i; |
687 if (slave->buscoupler_index == alias_slave->buscoupler_index |
666 if (!slave->type || |
688 && alias_slave->index_after_buscoupler == 0 |
667 slave->type->special == EC_TYPE_BUS_COUPLER) break; |
689 && slave->index_after_buscoupler == second) |
668 if (i - alias_slave_index == second) return slave; |
690 return slave; |
669 } |
691 } |
670 EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave" |
692 EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave" |
671 " following!\n", address, |
693 " following!\n", address, alias_slave->ring_position, |
672 (master->slaves + alias_slave_index)->ring_position, |
|
673 second); |
694 second); |
674 return NULL; |
695 return NULL; |
675 } |
696 } |
676 else { |
697 else { |
677 coupler_idx = -1; |
698 list_for_each_entry(slave, &master->slaves, list) { |
678 slave_idx = 0; |
699 if (slave->buscoupler_index == first |
679 for (i = 0; i < master->slave_count; i++, slave_idx++) { |
700 && slave->index_after_buscoupler == second) return slave; |
680 slave = master->slaves + i; |
|
681 if (!slave->type) continue; |
|
682 if (slave->type->special == EC_TYPE_BUS_COUPLER) { |
|
683 coupler_idx++; |
|
684 slave_idx = 0; |
|
685 } |
|
686 if (coupler_idx == first && slave_idx == second) return slave; |
|
687 } |
701 } |
688 } |
702 } |
689 } |
703 } |
690 else |
704 else |
691 EC_ERR("Slave address \"%s\" - Invalid format!\n", address); |
705 EC_ERR("Slave address \"%s\" - Invalid format!\n", address); |
913 } |
927 } |
914 domain_offset += domain->data_size; |
928 domain_offset += domain->data_size; |
915 } |
929 } |
916 |
930 |
917 // Slaves aktivieren |
931 // Slaves aktivieren |
918 for (i = 0; i < master->slave_count; i++) { |
932 list_for_each_entry(slave, &master->slaves, list) { |
919 slave = master->slaves + i; |
|
920 |
933 |
921 // Change state to INIT |
934 // Change state to INIT |
922 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT))) |
935 if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT))) |
923 return -1; |
936 return -1; |
924 |
937 |
925 // Check if slave was registered... |
938 // Check if slave was registered... |
926 type = slave->type; |
939 type = slave->type; |
927 if (!type) EC_WARN("Slave %i has unknown type!\n", i); |
940 if (!type) |
|
941 EC_WARN("Slave %i has unknown type!\n", slave->ring_position); |
928 |
942 |
929 // Check and reset CRC fault counters |
943 // Check and reset CRC fault counters |
930 ec_slave_check_crc(slave); |
944 ec_slave_check_crc(slave); |
931 |
945 |
932 // Resetting FMMUs |
946 // Resetting FMMUs |
1101 */ |
1112 */ |
1102 |
1113 |
1103 int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */) |
1114 int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */) |
1104 { |
1115 { |
1105 ec_slave_t *slave; |
1116 ec_slave_t *slave; |
1106 unsigned int i; |
1117 |
1107 |
1118 list_for_each_entry(slave, &master->slaves, list) { |
1108 for (i = 0; i < master->slave_count; i++) { |
|
1109 slave = master->slaves + i; |
|
1110 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
1119 if (slave->sii_mailbox_protocols & EC_MBOX_COE) { |
1111 if (unlikely(ec_slave_fetch_sdo_list(slave))) { |
1120 if (unlikely(ec_slave_fetch_sdo_list(slave))) { |
1112 EC_ERR("Failed to fetch SDO list on slave %i!\n", |
1121 EC_ERR("Failed to fetch SDO list on slave %i!\n", |
1113 slave->ring_position); |
1122 slave->ring_position); |
1114 return -1; |
1123 return -1; |
1317 |
1326 |
1318 void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */ |
1327 void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */ |
1319 unsigned int verbosity /**< Geschwätzigkeit */ |
1328 unsigned int verbosity /**< Geschwätzigkeit */ |
1320 ) |
1329 ) |
1321 { |
1330 { |
1322 unsigned int i; |
1331 ec_slave_t *slave; |
1323 ec_eoe_t *eoe; |
1332 ec_eoe_t *eoe; |
1324 |
1333 |
1325 EC_INFO("*** Begin master information ***\n"); |
1334 EC_INFO("*** Begin master information ***\n"); |
1326 if (master->slave_count) { |
1335 if (master->slave_count) { |
1327 EC_INFO("Slave list:\n"); |
1336 EC_INFO("Slave list:\n"); |
1328 for (i = 0; i < master->slave_count; i++) |
1337 list_for_each_entry(slave, &master->slaves, list) |
1329 ec_slave_print(&master->slaves[i], verbosity); |
1338 ec_slave_print(slave, verbosity); |
1330 } |
1339 } |
1331 if (!list_empty(&master->eoe_slaves)) { |
1340 if (!list_empty(&master->eoe_slaves)) { |
1332 EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n"); |
1341 EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n"); |
1333 list_for_each_entry(eoe, &master->eoe_slaves, list) { |
1342 list_for_each_entry(eoe, &master->eoe_slaves, list) { |
1334 ec_eoe_print(eoe); |
1343 ec_eoe_print(eoe); |