# HG changeset patch # User Florian Pose # Date 1144746720 0 # Node ID 8c0bc99229a9b982043f308b354ac004fadfff2b # Parent 3e9155836bc74a933b5e2bf3ffcf76d57c695f6e Slaves stored in list, slaves in SysFS diff -r 3e9155836bc7 -r 8c0bc99229a9 master/domain.c --- a/master/domain.c Tue Apr 11 09:08:10 2006 +0000 +++ b/master/domain.c Tue Apr 11 09:12:00 2006 +0000 @@ -213,8 +213,7 @@ cmd_offset = base_address; cmd_data_size = 0; cmd_count = 0; - for (i = 0; i < domain->master->slave_count; i++) { - slave = &domain->master->slaves[i]; + list_for_each_entry(slave, &domain->master->slaves, list) { for (j = 0; j < slave->fmmu_count; j++) { fmmu = &slave->fmmus[j]; if (fmmu->domain == domain) { diff -r 3e9155836bc7 -r 8c0bc99229a9 master/master.c --- a/master/master.c Tue Apr 11 09:08:10 2006 +0000 +++ b/master/master.c Tue Apr 11 09:12:00 2006 +0000 @@ -64,10 +64,10 @@ EC_INFO("Initializing master %i.\n", index); master->index = index; - master->slaves = NULL; master->device = NULL; master->reserved = 0; + INIT_LIST_HEAD(&master->slaves); INIT_LIST_HEAD(&master->command_queue); INIT_LIST_HEAD(&master->domains); INIT_LIST_HEAD(&master->eoe_slaves); @@ -130,24 +130,23 @@ /**< Zeiger auf den zurückzusetzenden Master */ ) { - unsigned int i; + ec_slave_t *slave, *next_s; ec_command_t *command, *next_c; ec_domain_t *domain, *next_d; ec_eoe_t *eoe, *next_eoe; // Alle Slaves entfernen - if (master->slaves) { - for (i = 0; i < master->slave_count; i++) - ec_slave_clear(master->slaves + i); - kfree(master->slaves); - master->slaves = NULL; + list_for_each_entry_safe(slave, next_s, &master->slaves, list) { + list_del(&slave->list); + kobject_del(&slave->kobj); + kobject_put(&slave->kobj); } master->slave_count = 0; // Kommando-Warteschlange leeren list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { + list_del_init(&command->queue); command->state = EC_CMD_ERROR; - list_del_init(&command->queue); } // Domain-Liste leeren @@ -455,13 +454,14 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */) { - ec_slave_t *slave; + ec_slave_t *slave, *next; ec_slave_ident_t *ident; unsigned int i; ec_command_t *command; ec_eoe_t *eoe; - - if (master->slaves || master->slave_count) { + uint16_t buscoupler_index, index_after_buscoupler; + + if (!list_empty(&master->slaves)) { EC_ERR("Slave scan already done!\n"); return -1; } @@ -476,35 +476,42 @@ if (!master->slave_count) return 0; - if (!(master->slaves = (ec_slave_t *) - kmalloc(master->slave_count * sizeof(ec_slave_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate slaves!\n"); - return -1; - } - // Init slaves for (i = 0; i < master->slave_count; i++) { - slave = master->slaves + i; - ec_slave_init(slave, master); - slave->ring_position = i; - slave->station_address = i + 1; - } + if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate slave %i!\n", i); + goto out_free; + } + + if (ec_slave_init(slave, master, i, i + 1)) goto out_free; + + if (kobject_add(&slave->kobj)) { + EC_ERR("Failed to add kobject.\n"); + kobject_put(&slave->kobj); // free + goto out_free; + } + + list_add_tail(&slave->list, &master->slaves); + } + + buscoupler_index = 0xFFFF; + index_after_buscoupler = 0; // For every slave on the bus - for (i = 0; i < master->slave_count; i++) { - slave = master->slaves + i; + list_for_each_entry(slave, &master->slaves, list) { // Write station address - if (ec_command_apwr(command, slave->ring_position, - 0x0010, sizeof(uint16_t))) return -1; + if (ec_command_apwr(command, slave->ring_position, 0x0010, + sizeof(uint16_t))) goto out_free; EC_WRITE_U16(command->data, slave->station_address); if (unlikely(ec_master_simple_io(master, command))) { - EC_ERR("Writing station address failed on slave %i!\n", i); - return -1; + EC_ERR("Writing station address failed on slave %i!\n", + slave->ring_position); + goto out_free; } // Fetch all slave information - if (ec_slave_fetch(slave)) return -1; + if (ec_slave_fetch(slave)) goto out_free; // Search for identification in "database" ident = slave_idents; @@ -521,12 +528,22 @@ EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at" " position %i.\n", slave->sii_vendor_id, slave->sii_product_code, i); + else { + if (slave->type->special == EC_TYPE_BUS_COUPLER) { + buscoupler_index++; + index_after_buscoupler = 0; + } + } + + slave->buscoupler_index = buscoupler_index; + slave->index_after_buscoupler = index_after_buscoupler; + index_after_buscoupler++; // Does the slave support EoE? if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { EC_ERR("Failed to allocate EoE-Object.\n"); - return -1; + goto out_free; } ec_eoe_init(eoe, slave); @@ -535,6 +552,14 @@ } return 0; + + out_free: + list_for_each_entry_safe(slave, next, &master->slaves, list) { + list_del(&slave->list); + kobject_del(&slave->kobj); + kobject_put(&slave->kobj); + } + return -1; } /*****************************************************************************/ @@ -600,14 +625,12 @@ { unsigned long first, second; char *remainder, *remainder2; - unsigned int i, alias_requested, alias_slave_index, alias_found; - int coupler_idx, slave_idx; - ec_slave_t *slave; + unsigned int alias_requested, alias_found; + ec_slave_t *alias_slave = NULL, *slave; if (!address || address[0] == 0) return NULL; alias_requested = 0; - alias_slave_index = 0; if (address[0] == '#') { alias_requested = 1; address++; @@ -621,9 +644,8 @@ if (alias_requested) { alias_found = 0; - for (i = 0; i < master->slave_count; i++) { - if (master->slaves[i].sii_alias == first) { - alias_slave_index = i; + list_for_each_entry(alias_slave, &master->slaves, list) { + if (alias_slave->sii_alias == first) { alias_found = 1; break; } @@ -636,11 +658,11 @@ if (!remainder[0]) { // absolute position if (alias_requested) { - return master->slaves + alias_slave_index; + return alias_slave; } else { - if (first < master->slave_count) { - return master->slaves + first; + list_for_each_entry(slave, &master->slaves, list) { + if (slave->ring_position == first) return slave; } EC_ERR("Slave address \"%s\" - Absolute position invalid!\n", address); @@ -661,29 +683,21 @@ } if (alias_requested) { - for (i = alias_slave_index + 1; i < master->slave_count; i++) { - slave = master->slaves + i; - if (!slave->type || - slave->type->special == EC_TYPE_BUS_COUPLER) break; - if (i - alias_slave_index == second) return slave; + list_for_each_entry(slave, &master->slaves, list) { + if (slave->buscoupler_index == alias_slave->buscoupler_index + && alias_slave->index_after_buscoupler == 0 + && slave->index_after_buscoupler == second) + return slave; } EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave" - " following!\n", address, - (master->slaves + alias_slave_index)->ring_position, + " following!\n", address, alias_slave->ring_position, second); return NULL; } else { - coupler_idx = -1; - slave_idx = 0; - for (i = 0; i < master->slave_count; i++, slave_idx++) { - slave = master->slaves + i; - if (!slave->type) continue; - if (slave->type->special == EC_TYPE_BUS_COUPLER) { - coupler_idx++; - slave_idx = 0; - } - if (coupler_idx == first && slave_idx == second) return slave; + list_for_each_entry(slave, &master->slaves, list) { + if (slave->buscoupler_index == first + && slave->index_after_buscoupler == second) return slave; } } } @@ -887,7 +901,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */) { - unsigned int i, j; + unsigned int j; ec_slave_t *slave; ec_command_t *command; const ec_sync_t *sync; @@ -915,8 +929,7 @@ } // Slaves aktivieren - for (i = 0; i < master->slave_count; i++) { - slave = master->slaves + i; + list_for_each_entry(slave, &master->slaves, list) { // Change state to INIT if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT))) @@ -924,7 +937,8 @@ // Check if slave was registered... type = slave->type; - if (!type) EC_WARN("Slave %i has unknown type!\n", i); + if (!type) + EC_WARN("Slave %i has unknown type!\n", slave->ring_position); // Check and reset CRC fault counters ec_slave_check_crc(slave); @@ -1079,11 +1093,8 @@ void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT-Master */) { ec_slave_t *slave; - unsigned int i; - - for (i = 0; i < master->slave_count; i++) - { - slave = master->slaves + i; + + list_for_each_entry(slave, &master->slaves, list) { ec_slave_check_crc(slave); ec_slave_state_change(slave, EC_SLAVE_STATE_INIT); } @@ -1103,10 +1114,8 @@ int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */) { ec_slave_t *slave; - unsigned int i; - - for (i = 0; i < master->slave_count; i++) { - slave = master->slaves + i; + + list_for_each_entry(slave, &master->slaves, list) { if (slave->sii_mailbox_protocols & EC_MBOX_COE) { if (unlikely(ec_slave_fetch_sdo_list(slave))) { EC_ERR("Failed to fetch SDO list on slave %i!\n", @@ -1319,14 +1328,14 @@ unsigned int verbosity /**< Geschwätzigkeit */ ) { - unsigned int i; + ec_slave_t *slave; ec_eoe_t *eoe; EC_INFO("*** Begin master information ***\n"); if (master->slave_count) { EC_INFO("Slave list:\n"); - for (i = 0; i < master->slave_count; i++) - ec_slave_print(&master->slaves[i], verbosity); + list_for_each_entry(slave, &master->slaves, list) + ec_slave_print(slave, verbosity); } if (!list_empty(&master->eoe_slaves)) { EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n"); diff -r 3e9155836bc7 -r 8c0bc99229a9 master/master.h --- a/master/master.h Tue Apr 11 09:08:10 2006 +0000 +++ b/master/master.h Tue Apr 11 09:12:00 2006 +0000 @@ -15,7 +15,6 @@ #include #include "device.h" -#include "slave.h" #include "domain.h" /*****************************************************************************/ @@ -49,7 +48,7 @@ struct list_head list; /**< Noetig fuer Master-Liste */ struct kobject kobj; /**< Kernel-Object */ unsigned int index; /**< Master-Index */ - ec_slave_t *slaves; /**< Array von Slaves auf dem Bus */ + struct list_head slaves; /**< Liste der Slaves auf dem Bus */ unsigned int slave_count; /**< Anzahl Slaves auf dem Bus */ ec_device_t *device; /**< EtherCAT-Gerät */ struct list_head command_queue; /**< Kommando-Warteschlange */ diff -r 3e9155836bc7 -r 8c0bc99229a9 master/slave.c --- a/master/slave.c Tue Apr 11 09:08:10 2006 +0000 +++ b/master/slave.c Tue Apr 11 09:12:00 2006 +0000 @@ -24,6 +24,31 @@ int ec_slave_fetch_sync(ec_slave_t *, const uint8_t *, size_t); int ec_slave_fetch_pdo(ec_slave_t *, const uint8_t *, size_t, ec_pdo_type_t); int ec_slave_locate_string(ec_slave_t *, unsigned int, char **); +ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *); + +/*****************************************************************************/ + +static struct attribute attr_ring_position = { + .name = "ring_position", + .owner = THIS_MODULE, + .mode = S_IRUGO +}; + +static struct attribute *def_attrs[] = { + &attr_ring_position, + NULL, +}; + +static struct sysfs_ops sysfs_ops = { + .show = &ec_show_slave_attribute, + .store = NULL +}; + +static struct kobj_type ktype_ec_slave = { + .release = ec_slave_clear, + .sysfs_ops = &sysfs_ops, + .default_attrs = def_attrs +}; /*****************************************************************************/ @@ -35,20 +60,36 @@ EtherCAT-Slave-Konstruktor. */ -void ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */ - ec_master_t *master /**< EtherCAT-Master */ - ) +int ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */ + ec_master_t *master, /**< EtherCAT-Master */ + uint16_t ring_position, /**< Ringposition */ + uint16_t station_address /**< Programmierte Adresse */ + ) { unsigned int i; + slave->ring_position = ring_position; + slave->station_address = station_address; + + // Init kobject and add it to the hierarchy + memset(&slave->kobj, 0x00, sizeof(struct kobject)); + kobject_init(&slave->kobj); + slave->kobj.ktype = &ktype_ec_slave; + slave->kobj.parent = &master->kobj; + if (kobject_set_name(&slave->kobj, "slave%03i", slave->ring_position)) { + EC_ERR("Failed to set kobject name.\n"); + kobject_put(&slave->kobj); + return -1; + } + slave->master = master; + slave->buscoupler_index = 0; + slave->index_after_buscoupler = 0xFFFF; slave->base_type = 0; slave->base_revision = 0; slave->base_build = 0; slave->base_fmmu_count = 0; slave->base_sync_count = 0; - slave->ring_position = 0; - slave->station_address = 0; slave->sii_alias = 0; slave->sii_vendor_id = 0; slave->sii_product_code = 0; @@ -78,6 +119,8 @@ slave->dl_status_loop[i] = 0; slave->dl_status_comm[i] = 0; } + + return 0; } /*****************************************************************************/ @@ -86,8 +129,9 @@ EtherCAT-Slave-Destruktor. */ -void ec_slave_clear(ec_slave_t *slave /**< EtherCAT-Slave */) -{ +void ec_slave_clear(struct kobject *kobj /**< KObject des Slaves */) +{ + ec_slave_t *slave; ec_eeprom_string_t *string, *next_str; ec_eeprom_sync_t *sync, *next_sync; ec_eeprom_pdo_t *pdo, *next_pdo; @@ -95,6 +139,8 @@ ec_sdo_t *sdo, *next_sdo; ec_sdo_entry_t *en, *next_en; + slave = container_of(kobj, ec_slave_t, kobj); + // Alle Strings freigeben list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) { list_del(&string->list); @@ -1143,6 +1189,28 @@ /*****************************************************************************/ +/** + Formatiert Attribut-Daten für lesenden Zugriff im SysFS + + \return Anzahl Bytes im Speicher +*/ + +ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< KObject */ + struct attribute *attr, /**< Attribut */ + char *buffer /**< Speicher für die Daten */ + ) +{ + ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); + + if (attr == &attr_ring_position) { + return sprintf(buffer, "%i\n", slave->ring_position); + } + + return 0; +} + +/*****************************************************************************/ + const ec_code_msg_t al_status_messages[] = { {0x0001, "Unspecified error"}, {0x0011, "Invalud requested state change"}, diff -r 3e9155836bc7 -r 8c0bc99229a9 master/slave.h --- a/master/slave.h Tue Apr 11 09:08:10 2006 +0000 +++ b/master/slave.h Tue Apr 11 09:12:00 2006 +0000 @@ -12,6 +12,7 @@ #define _EC_SLAVE_H_ #include +#include #include "globals.h" #include "command.h" @@ -188,11 +189,15 @@ struct ec_slave { + struct list_head list; /**< Noetig fuer Slave-Liste im Master */ + struct kobject kobj; /**< Kernel-Object */ ec_master_t *master; /**< EtherCAT-Master, zu dem der Slave gehört. */ // Addresses uint16_t ring_position; /**< Position des Slaves im Bus */ uint16_t station_address; /**< Konfigurierte Slave-Adresse */ + uint16_t buscoupler_index; /**< Letzter Buskoppler */ + uint16_t index_after_buscoupler; /**< Index hinter letztem Buskoppler */ // Base data uint8_t base_type; /**< Slave-Typ */ @@ -242,8 +247,8 @@ /*****************************************************************************/ // Slave construction/destruction -void ec_slave_init(ec_slave_t *, ec_master_t *); -void ec_slave_clear(ec_slave_t *); +int ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t); +void ec_slave_clear(struct kobject *); // Slave control int ec_slave_fetch(ec_slave_t *);