--- 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) {
--- 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");
--- 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 <linux/sysfs.h>
#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 */
--- 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"},
--- 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 <linux/list.h>
+#include <linux/kobject.h>
#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 *);