# HG changeset patch # User Florian Pose # Date 1173377725 0 # Node ID aa23c48dca2da296287d9d1e6565ec3f0c154cd3 # Parent b0994b4e3b37ce67b78878d9d246f3dfdf65a91b Allow only MAC addresses as device identifiers; replaced master list by master array; hand ober MAC addresses with array module parameters. diff -r b0994b4e3b37 -r aa23c48dca2d NEWS --- a/NEWS Thu Mar 08 13:06:20 2007 +0000 +++ b/NEWS Thu Mar 08 18:15:25 2007 +0000 @@ -9,12 +9,11 @@ * Added testing version of Intel PRO/100 ethernet driver (e100). * Added testing version of NVIDIA nForce ethernet driver (forcedeth). * Removed "ec_eoeif_count" master module parameter. -* Introduced "Device IDs" to tell a master to wait for connection of certain - ethernet devices. -* Added "main" and "backup" parameters to master module to hand over - device ID lists. +* Added "main" and "backup" parameters to master module to hand over the + MAC addresses of the devices to wait for. This made the ec_device_index + parameter of the ethercat drivers obsolete. * Changed format of sysconfig file and accordingly adjusted functionality - of the init script to handle device ID lists. + of the init script to handle MAC address lists. * Realtime interface changes: - ecrt_master_run() became obsolete, because the master state machine is now run in process context. diff -r b0994b4e3b37 -r aa23c48dca2d TODO --- a/TODO Thu Mar 08 13:06:20 2007 +0000 +++ b/TODO Thu Mar 08 18:15:25 2007 +0000 @@ -8,7 +8,6 @@ * Release 1.3: - Remove addressing scheme "X:Y". - - Allow only MAC address as device ID. - Remove ugly ec_slave_is_coupler(). - Replace Vendor ID and product code arguments of ec_domain_register_pdo() by slave pointer. diff -r b0994b4e3b37 -r aa23c48dca2d devices/8139too-2.6.13-ethercat.c --- a/devices/8139too-2.6.13-ethercat.c Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/8139too-2.6.13-ethercat.c Thu Mar 08 18:15:25 2007 +0000 @@ -1069,8 +1069,7 @@ /* dev is fully set up and ready to use now */ // offer device to EtherCAT master module - if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, - ec_poll, THIS_MODULE)) { + if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) { printk(KERN_ERR PFX "Failed to offer device.\n"); goto err_out; } diff -r b0994b4e3b37 -r aa23c48dca2d devices/8139too-2.6.17-ethercat.c --- a/devices/8139too-2.6.17-ethercat.c Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/8139too-2.6.17-ethercat.c Thu Mar 08 18:15:25 2007 +0000 @@ -1073,8 +1073,7 @@ /* dev is fully set up and ready to use now */ // offer device to EtherCAT master module - if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, - ec_poll, THIS_MODULE)) { + if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) { printk(KERN_ERR PFX "Failed to offer device.\n"); goto err_out; } diff -r b0994b4e3b37 -r aa23c48dca2d devices/8139too-2.6.18-ethercat.c --- a/devices/8139too-2.6.18-ethercat.c Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/8139too-2.6.18-ethercat.c Thu Mar 08 18:15:25 2007 +0000 @@ -1074,8 +1074,7 @@ /* dev is fully set up and ready to use now */ // offer device to EtherCAT master module - if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, - ec_poll, THIS_MODULE)) { + if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) { printk(KERN_ERR PFX "Failed to offer device.\n"); goto err_out; } diff -r b0994b4e3b37 -r aa23c48dca2d devices/8139too-2.6.19-ethercat.c --- a/devices/8139too-2.6.19-ethercat.c Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/8139too-2.6.19-ethercat.c Thu Mar 08 18:15:25 2007 +0000 @@ -1073,8 +1073,7 @@ /* dev is fully set up and ready to use now */ // offer device to EtherCAT master module - if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, - ec_poll, THIS_MODULE)) { + if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) { printk(KERN_ERR PFX "Failed to offer device.\n"); goto err_out; } diff -r b0994b4e3b37 -r aa23c48dca2d devices/ecdev.h --- a/devices/ecdev.h Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/ecdev.h Thu Mar 08 18:15:25 2007 +0000 @@ -66,9 +66,8 @@ /*****************************************************************************/ // Offering/withdrawal functions -int ecdev_offer(struct net_device *net_dev, ec_device_t **, - const char *driver_name, unsigned int board_index, - ec_pollfunc_t poll, struct module *module); +int ecdev_offer(struct net_device *net_dev, ec_pollfunc_t poll, + struct module *module, ec_device_t **); void ecdev_withdraw(ec_device_t *device); /*****************************************************************************/ diff -r b0994b4e3b37 -r aa23c48dca2d devices/forcedeth-2.6.17-ethercat.c --- a/devices/forcedeth-2.6.17-ethercat.c Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/forcedeth-2.6.17-ethercat.c Thu Mar 08 18:15:25 2007 +0000 @@ -3336,8 +3336,7 @@ np->autoneg = 1; // offer device to EtherCAT master module - if (ecdev_offer(dev, &np->ecdev, "forcedeth", board_idx, ec_poll, - THIS_MODULE)) { + if (ecdev_offer(dev, ec_poll, THIS_MODULE, &np->ecdev)) { printk(KERN_ERR "forcedeth: Failed to offer device.\n"); goto out_freering; } diff -r b0994b4e3b37 -r aa23c48dca2d devices/forcedeth-2.6.19-ethercat.c --- a/devices/forcedeth-2.6.19-ethercat.c Thu Mar 08 13:06:20 2007 +0000 +++ b/devices/forcedeth-2.6.19-ethercat.c Thu Mar 08 18:15:25 2007 +0000 @@ -4628,8 +4628,7 @@ np->autoneg = 1; // offer device to EtherCAT master module - if (ecdev_offer(dev, &np->ecdev, "forcedeth", board_idx, ec_poll, - THIS_MODULE)) { + if (ecdev_offer(dev, ec_poll, THIS_MODULE, &np->ecdev)) { printk(KERN_ERR "forcedeth: Failed to offer device.\n"); goto out_error; } diff -r b0994b4e3b37 -r aa23c48dca2d master/Kbuild --- a/master/Kbuild Thu Mar 08 13:06:20 2007 +0000 +++ b/master/Kbuild Thu Mar 08 18:15:25 2007 +0000 @@ -35,9 +35,9 @@ obj-m := ec_master.o -ec_master-objs := module.o master.o device.o device_id.o pdo.o sync.o fmmu.o \ - slave.o datagram.o domain.o mailbox.o canopen.o ethernet.o fsm_sii.o \ - fsm_change.o fsm_coe.o fsm_mapping.o fsm_slave.o fsm_master.o xmldev.o +ec_master-objs := module.o master.o device.o pdo.o sync.o fmmu.o slave.o \ + datagram.o domain.o mailbox.o canopen.o ethernet.o fsm_sii.o fsm_change.o \ + fsm_coe.o fsm_mapping.o fsm_slave.o fsm_master.o xmldev.o ifeq ($(EC_DBG_IF),1) ec_master-objs += debug.o diff -r b0994b4e3b37 -r aa23c48dca2d master/Makefile.am --- a/master/Makefile.am Thu Mar 08 13:06:20 2007 +0000 +++ b/master/Makefile.am Thu Mar 08 18:15:25 2007 +0000 @@ -37,7 +37,6 @@ datagram.c datagram.h \ debug.c debug.h \ device.c device.h \ - device_id.c device_id.h \ pdo.c pdo.h \ sync.c sync.h \ fmmu.c fmmu.h \ diff -r b0994b4e3b37 -r aa23c48dca2d master/device_id.c --- a/master/device_id.c Thu Mar 08 13:06:20 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** - \file - EtherCAT device ID. -*/ - -/*****************************************************************************/ - -#include -#include - -#include "globals.h" -#include "device_id.h" - -/*****************************************************************************/ - -static int ec_device_id_parse_mac(ec_device_id_t *dev_id, - const char *src, const char **remainder) -{ - unsigned int i, value; - char *rem; - - for (i = 0; i < ETH_ALEN; i++) { - value = simple_strtoul(src, &rem, 16); - if (rem != src + 2 - || value > 0xFF - || (i < ETH_ALEN - 1 && *rem != ':')) { - return -1; - } - dev_id->octets[i] = value; - if (i < ETH_ALEN - 1) - src = rem + 1; - } - - dev_id->type = ec_device_id_mac; - *remainder = rem; - return 0; -} - -/*****************************************************************************/ - -void ec_device_id_clear_list(struct list_head *ids) -{ - ec_device_id_t *dev_id, *next_dev_id; - - list_for_each_entry_safe(dev_id, next_dev_id, ids, list) { - list_del(&dev_id->list); - kfree(dev_id); - } -} - -/*****************************************************************************/ - -static int ec_device_id_create_list(struct list_head *ids, const char *src) -{ - const char *rem; - ec_device_id_t *dev_id; - unsigned int index = 0; - - while (*src) { - // allocate new device ID - if (!(dev_id = kmalloc(sizeof(ec_device_id_t), GFP_KERNEL))) { - EC_ERR("Out of memory!\n"); - goto out_free; - } - - if (*src == ';') { // empty device ID - dev_id->type = ec_device_id_empty; - } - else if (*src == 'M') { - src++; - if (ec_device_id_parse_mac(dev_id, src, &rem)) { - EC_ERR("Device ID %u: Invalid MAC syntax!\n", index); - kfree(dev_id); - goto out_free; - } - src = rem; - } - else { - EC_ERR("Device ID %u: Unknown format \'%c\'!\n", index, *src); - kfree(dev_id); - goto out_free; - } - - list_add_tail(&dev_id->list, ids); - - if (*src) { - if (*src != ';') { - EC_ERR("Invalid delimiter '%c' after device ID %i!\n", - *src, index); - goto out_free; - } - src++; // skip delimiter - } - index++; - } - - return 0; - -out_free: - ec_device_id_clear_list(ids); - return -1; -} - -/*****************************************************************************/ - -int ec_device_id_process_params(const char *main, const char *backup, - struct list_head *main_ids, struct list_head *backup_ids) -{ - ec_device_id_t *id; - unsigned int main_count = 0, backup_count = 0; - - if (ec_device_id_create_list(main_ids, main)) - return -1; - - if (ec_device_id_create_list(backup_ids, backup)) - return -1; - - // count main device IDs and check for empty ones - list_for_each_entry(id, main_ids, list) { - if (id->type == ec_device_id_empty) { - EC_ERR("Main device IDs may not be empty!\n"); - return -1; - } - main_count++; - } - - // count backup device IDs - list_for_each_entry(id, backup_ids, list) { - backup_count++; - } - - // fill up backup device IDs - while (backup_count < main_count) { - if (!(id = kmalloc(sizeof(ec_device_id_t), GFP_KERNEL))) { - EC_ERR("Out of memory!\n"); - return -1; - } - - id->type = ec_device_id_empty; - list_add_tail(&id->list, backup_ids); - backup_count++; - } - - return 0; -} - -/*****************************************************************************/ - -int ec_device_id_check(const ec_device_id_t *dev_id, - const struct net_device *dev, const char *driver_name, - unsigned int device_index) -{ - unsigned int i; - - switch (dev_id->type) { - case ec_device_id_mac: - for (i = 0; i < ETH_ALEN; i++) - if (dev->dev_addr[i] != dev_id->octets[i]) - return 0; - return 1; - default: - return 0; - } -} - -/*****************************************************************************/ - -ssize_t ec_device_id_print(const ec_device_id_t *dev_id, char *buffer) -{ - off_t off = 0; - unsigned int i; - - switch (dev_id->type) { - case ec_device_id_empty: - off += sprintf(buffer + off, "none"); - break; - case ec_device_id_mac: - off += sprintf(buffer + off, "MAC "); - for (i = 0; i < ETH_ALEN; i++) { - off += sprintf(buffer + off, "%02X", dev_id->octets[i]); - if (i < ETH_ALEN - 1) off += sprintf(buffer + off, ":"); - } - break; - } - - return off; -} - -/*****************************************************************************/ diff -r b0994b4e3b37 -r aa23c48dca2d master/device_id.h --- a/master/device_id.h Thu Mar 08 13:06:20 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** - \file - EtherCAT device ID structure. -*/ - -/*****************************************************************************/ - -#ifndef _EC_DEVICE_ID_H_ -#define _EC_DEVICE_ID_H_ - -#include - -#include "globals.h" - -/*****************************************************************************/ - -typedef enum { - ec_device_id_empty, - ec_device_id_mac -} -ec_device_id_type_t; - -typedef struct { - struct list_head list; - ec_device_id_type_t type; - unsigned char octets[ETH_ALEN]; -} -ec_device_id_t; - -/*****************************************************************************/ - -int ec_device_id_process_params(const char *, const char *, - struct list_head *, struct list_head *); -void ec_device_id_clear_list(struct list_head *); -int ec_device_id_check(const ec_device_id_t *, const struct net_device *, - const char *, unsigned int); -ssize_t ec_device_id_print(const ec_device_id_t *, char *); - -/*****************************************************************************/ - -#endif diff -r b0994b4e3b37 -r aa23c48dca2d master/globals.h --- a/master/globals.h Thu Mar 08 13:06:20 2007 +0000 +++ b/master/globals.h Thu Mar 08 18:15:25 2007 +0000 @@ -157,6 +157,8 @@ void ec_print_data(const uint8_t *, size_t); void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t); size_t ec_state_string(uint8_t, char *); +ssize_t ec_mac_print(const uint8_t *, char *); +int ec_mac_is_zero(const uint8_t *); /*****************************************************************************/ diff -r b0994b4e3b37 -r aa23c48dca2d master/master.c --- a/master/master.c Thu Mar 08 13:06:20 2007 +0000 +++ b/master/master.c Thu Mar 08 18:15:25 2007 +0000 @@ -54,7 +54,6 @@ /*****************************************************************************/ -void ec_master_clear(struct kobject *); void ec_master_destroy_domains(ec_master_t *); void ec_master_sync_io(ec_master_t *); static int ec_master_idle_thread(ec_master_t *); @@ -85,7 +84,7 @@ }; static struct kobj_type ktype_ec_master = { - .release = ec_master_clear, + .release = NULL, .sysfs_ops = &ec_sysfs_ops, .default_attrs = ec_def_attrs }; @@ -102,9 +101,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ struct kobject *module_kobj, /**< kobject of the master module */ unsigned int index, /**< master index */ - const ec_device_id_t *main_id, /**< ID of main device */ - const ec_device_id_t *backup_id, /**< ID of main device */ - unsigned int eoeif_count /**< number of EoE interfaces */ + const uint8_t *main_mac, /**< MAC address of main device */ + const uint8_t *backup_mac /**< MAC address of backup device */ ) { ec_eoe_t *eoe, *next_eoe; @@ -113,8 +111,8 @@ atomic_set(&master->available, 1); master->index = index; - master->main_device_id = main_id; - master->backup_device_id = backup_id; + master->main_mac = main_mac; + master->backup_mac = backup_mac; init_MUTEX(&master->device_sem); master->mode = EC_MASTER_MODE_ORPHANED; @@ -175,19 +173,6 @@ if (ec_device_init(&master->backup_device, master)) goto out_clear_main; - // create EoE handlers - for (i = 0; i < eoeif_count; i++) { - if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate EoE-Object.\n"); - goto out_clear_eoe; - } - if (ec_eoe_init(eoe)) { - kfree(eoe); - goto out_clear_eoe; - } - list_add_tail(&eoe->list, &master->eoe_handlers); - } - // init state machine datagram ec_datagram_init(&master->fsm_datagram); if (ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE)) { @@ -234,34 +219,21 @@ /*****************************************************************************/ /** - Master destructor. - Clears the kobj-hierarchy bottom up and frees the master. -*/ - -void ec_master_destroy(ec_master_t *master /**< EtherCAT master */) -{ - ec_master_destroy_slaves(master); - ec_master_destroy_domains(master); - - // destroy self - kobject_del(&master->kobj); - kobject_put(&master->kobj); // free master -} - -/*****************************************************************************/ - -/** Clear and free master. This method is called by the kobject, once there are no more references to it. */ -void ec_master_clear(struct kobject *kobj /**< kobject of the master */) -{ - ec_master_t *master = container_of(kobj, ec_master_t, kobj); +void ec_master_clear( + ec_master_t *master /**< EtherCAT master */ + ) +{ ec_eoe_t *eoe, *next_eoe; ec_datagram_t *datagram, *next_datagram; + ec_master_destroy_slaves(master); + ec_master_destroy_domains(master); + // list of EEPROM requests is empty, // otherwise master could not be cleared. @@ -285,9 +257,11 @@ ec_device_clear(&master->backup_device); ec_device_clear(&master->main_device); - EC_INFO("Master %i freed.\n", master->index); - - kfree(master); + // destroy self + kobject_del(&master->kobj); + kobject_put(&master->kobj); + + EC_INFO("Master %u freed.\n", master->index); } /*****************************************************************************/ @@ -945,30 +919,34 @@ /*****************************************************************************/ -ssize_t ec_master_device_info(const ec_device_t *device, - const ec_device_id_t *dev_id, - char *buffer) +ssize_t ec_master_device_info( + const ec_device_t *device, + const uint8_t *mac, + char *buffer + ) { unsigned int frames_lost; off_t off = 0; - off += ec_device_id_print(dev_id, buffer + off); + if (ec_mac_is_zero(mac)) { + off += sprintf(buffer + off, "none.\n"); + } + else { + off += ec_mac_print(mac, buffer + off); - if (device->dev) { - off += sprintf(buffer + off, " (connected).\n"); - off += sprintf(buffer + off, " Frames sent: %u\n", - device->tx_count); - off += sprintf(buffer + off, " Frames received: %u\n", - device->rx_count); - frames_lost = device->tx_count - device->rx_count; - if (frames_lost) frames_lost--; - off += sprintf(buffer + off, " Frames lost: %u\n", frames_lost); - } - else if (dev_id->type != ec_device_id_empty) { - off += sprintf(buffer + off, " (WAITING).\n"); - } - else { - off += sprintf(buffer + off, ".\n"); + if (device->dev) { + off += sprintf(buffer + off, " (connected).\n"); + off += sprintf(buffer + off, " Frames sent: %u\n", + device->tx_count); + off += sprintf(buffer + off, " Frames received: %u\n", + device->rx_count); + frames_lost = device->tx_count - device->rx_count; + if (frames_lost) frames_lost--; + off += sprintf(buffer + off, " Frames lost: %u\n", frames_lost); + } + else { + off += sprintf(buffer + off, " (WAITING).\n"); + } } return off; @@ -1014,10 +992,10 @@ off += sprintf(buffer + off, " Main: "); off += ec_master_device_info(&master->main_device, - master->main_device_id, buffer + off); + master->main_mac, buffer + off); off += sprintf(buffer + off, " Backup: "); off += ec_master_device_info(&master->backup_device, - master->backup_device_id, buffer + off); + master->backup_mac, buffer + off); up(&master->device_sem); diff -r b0994b4e3b37 -r aa23c48dca2d master/master.h --- a/master/master.h Thu Mar 08 13:06:20 2007 +0000 +++ b/master/master.h Thu Mar 08 18:15:25 2007 +0000 @@ -49,7 +49,6 @@ #include #include "device.h" -#include "device_id.h" #include "domain.h" #include "fsm_master.h" @@ -94,16 +93,15 @@ struct ec_master { - struct list_head list; /**< list item for module's master list */ atomic_t available; /**< zero, if the master is reserved for RT */ unsigned int index; /**< master index */ struct kobject kobj; /**< kobject */ ec_device_t main_device; /**< EtherCAT device */ - const ec_device_id_t *main_device_id; /**< ID of main device */ + const uint8_t *main_mac; /**< MAC address of main device */ ec_device_t backup_device; /**< EtherCAT backup device */ - const ec_device_id_t *backup_device_id; /**< ID of backup device */ + const uint8_t *backup_mac; /**< MAC address of backup device */ struct semaphore device_sem; /**< device semaphore */ ec_fsm_master_t fsm; /**< master state machine */ @@ -164,8 +162,8 @@ // master creation/deletion int ec_master_init(ec_master_t *, struct kobject *, unsigned int, - const ec_device_id_t *, const ec_device_id_t *, unsigned int); -void ec_master_destroy(ec_master_t *); + const uint8_t *, const uint8_t *); +void ec_master_clear(ec_master_t *); // mode transitions int ec_master_enter_idle_mode(ec_master_t *); diff -r b0994b4e3b37 -r aa23c48dca2d master/module.c --- a/master/module.c Thu Mar 08 13:06:20 2007 +0000 +++ b/master/module.c Thu Mar 08 18:15:25 2007 +0000 @@ -49,19 +49,28 @@ /*****************************************************************************/ +#define MAX_MASTERS 5 /**< maximum number of masters */ + +/*****************************************************************************/ + int __init ec_init_module(void); void __exit ec_cleanup_module(void); -/*****************************************************************************/ - -struct kobject ec_kobj; /**< kobject for master module */ - -static char *main; /**< main devices parameter */ -static char *backup; /**< backup devices parameter */ - -static LIST_HEAD(main_ids); /**< list of main device IDs */ -static LIST_HEAD(backup_ids); /**< list of main device IDs */ -static LIST_HEAD(masters); /**< list of masters */ +static int ec_mac_parse(uint8_t *, const char *, int); + +/*****************************************************************************/ + +struct kobject kobj; /**< kobject for master module */ + +static char *main[MAX_MASTERS]; /**< main devices parameter */ +static char *backup[MAX_MASTERS]; /**< backup devices parameter */ + +static ec_master_t *masters; /**< master array */ +static unsigned int master_count; /**< number of masters */ +static unsigned int backup_count; /**< number of backup devices */ + +static uint8_t macs[MAX_MASTERS][2][ETH_ALEN]; /**< MAC addresses */ + static dev_t device_number; /**< XML character device number */ ec_xmldev_t xmldev; /**< XML character device */ @@ -76,104 +85,95 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); -module_param(main, charp, S_IRUGO); -MODULE_PARM_DESC(main, "main device IDs"); -module_param(backup, charp, S_IRUGO); -MODULE_PARM_DESC(backup, "backup device IDs"); +module_param_array(main, charp, &master_count, S_IRUGO); +MODULE_PARM_DESC(main, "MAC addresses of main devices"); +module_param_array(backup, charp, &backup_count, S_IRUGO); +MODULE_PARM_DESC(backup, "MAC addresses of backup devices"); /** \endcond */ /*****************************************************************************/ /** - Module initialization. - Initializes \a ec_master_count masters. - \return 0 on success, else < 0 -*/ + * Module initialization. + * Initializes \a ec_master_count masters. + * \return 0 on success, else < 0 + */ int __init ec_init_module(void) { - ec_master_t *master, *next; - ec_device_id_t *main_dev_id, *backup_dev_id; - unsigned int master_index = 0; + int i, ret = 0; EC_INFO("Master driver %s\n", EC_MASTER_VERSION); // init kobject and add it to the hierarchy - memset(&ec_kobj, 0x00, sizeof(struct kobject)); - kobject_init(&ec_kobj); // no ktype - - if (kobject_set_name(&ec_kobj, "ethercat")) { + memset(&kobj, 0x00, sizeof(struct kobject)); + kobject_init(&kobj); // no ktype + + if (kobject_set_name(&kobj, "ethercat")) { EC_ERR("Failed to set module kobject name.\n"); + ret = -ENOMEM; goto out_put; } - if (kobject_add(&ec_kobj)) { + if (kobject_add(&kobj)) { EC_ERR("Failed to add module kobject.\n"); + ret = -EEXIST; goto out_put; } if (alloc_chrdev_region(&device_number, 0, 1, "EtherCAT")) { EC_ERR("Failed to obtain device number!\n"); + ret = -EBUSY; goto out_del; } - if (ec_device_id_process_params(main, backup, &main_ids, &backup_ids)) - goto out_cdev; - - // create as many masters as main device IDs present - if (!list_empty(&main_ids)) { - // main_ids and backup_ids are of equal size at this point - main_dev_id = - list_entry(main_ids.next, ec_device_id_t, list); - backup_dev_id = - list_entry(backup_ids.next, ec_device_id_t, list); + // zero MAC addresses + memset(macs, 0x00, sizeof(uint8_t) * MAX_MASTERS * 2 * ETH_ALEN); + + // process MAC parameters + for (i = 0; i < master_count; i++) { + if (ec_mac_parse(macs[i][0], main[i], 0)) { + ret = -EINVAL; + goto out_cdev; + } - while (1) { - if (!(master = (ec_master_t *) - kmalloc(sizeof(ec_master_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate memory for EtherCAT master %i.\n", - master_index); - goto out_free_masters; - } - - if (ec_master_init(master, &ec_kobj, master_index, - main_dev_id, backup_dev_id, 0)) - goto out_free_masters; - - list_add_tail(&master->list, &masters); - master_index++; - - // last device IDs? - if (main_dev_id->list.next == &main_ids) - break; - - // next device IDs - main_dev_id = - list_entry(main_dev_id->list.next, ec_device_id_t, list); - backup_dev_id = - list_entry(backup_dev_id->list.next, ec_device_id_t, list); + if (i < backup_count && ec_mac_parse(macs[i][1], backup[i], 1)) { + ret = -EINVAL; + goto out_cdev; + } + } + + if (master_count) { + if (!(masters = kmalloc(sizeof(ec_master_t) * master_count, + GFP_KERNEL))) { + EC_ERR("Failed to allocate memory for EtherCAT masters.\n"); + ret = -ENOMEM; + goto out_cdev; + } + } + + for (i = 0; i < master_count; i++) { + if (ec_master_init(&masters[i], &kobj, i, macs[i][0], macs[i][1])) { + ret = -EIO; + goto out_free_masters; } } EC_INFO("%u master%s waiting for devices.\n", - master_index, (master_index == 1 ? "" : "s")); - return 0; + master_count, (master_count == 1 ? "" : "s")); + return ret; out_free_masters: - list_for_each_entry_safe(master, next, &masters, list) { - list_del(&master->list); - ec_master_destroy(master); - } - ec_device_id_clear_list(&main_ids); - ec_device_id_clear_list(&backup_ids); + for (i--; i >= 0; i--) ec_master_clear(&masters[i]); + kfree(masters); out_cdev: unregister_chrdev_region(device_number, 1); out_del: - kobject_del(&ec_kobj); + kobject_del(&kobj); out_put: - kobject_put(&ec_kobj); - return -1; + kobject_put(&kobj); + return ret; } /*****************************************************************************/ @@ -185,41 +185,96 @@ void __exit ec_cleanup_module(void) { - ec_master_t *master, *next; - - EC_INFO("Cleaning up master module...\n"); - - list_for_each_entry_safe(master, next, &masters, list) { - list_del(&master->list); - ec_master_destroy(master); - } - - ec_device_id_clear_list(&main_ids); - ec_device_id_clear_list(&backup_ids); + unsigned int i; + + for (i = 0; i < master_count; i++) { + ec_master_clear(&masters[i]); + } + if (master_count) + kfree(masters); + unregister_chrdev_region(device_number, 1); - kobject_del(&ec_kobj); - kobject_put(&ec_kobj); + kobject_del(&kobj); + kobject_put(&kobj); EC_INFO("Master module cleaned up.\n"); } -/*****************************************************************************/ - -/** - Gets a handle to a certain master. - \returns pointer to master -*/ - -ec_master_t *ec_find_master(unsigned int master_index /**< master index */) -{ - ec_master_t *master; - - list_for_each_entry(master, &masters, list) { - if (master->index == master_index) return master; - } - - EC_ERR("Master %i does not exist!\n", master_index); - return NULL; +/***************************************************************************** + * MAC address functions + ****************************************************************************/ + +int ec_mac_equal(const uint8_t *mac1, const uint8_t *mac2) +{ + unsigned int i; + + for (i = 0; i < ETH_ALEN; i++) + if (mac1[i] != mac2[i]) + return 0; + + return 1; +} + +/*****************************************************************************/ + +ssize_t ec_mac_print(const uint8_t *mac, char *buffer) +{ + off_t off = 0; + unsigned int i; + + for (i = 0; i < ETH_ALEN; i++) { + off += sprintf(buffer + off, "%02X", mac[i]); + if (i < ETH_ALEN - 1) off += sprintf(buffer + off, ":"); + } + + return off; +} + +/*****************************************************************************/ + +int ec_mac_is_zero(const uint8_t *mac) +{ + unsigned int i; + + for (i = 0; i < ETH_ALEN; i++) + if (mac[i]) + return 0; + + return 1; +} + +/*****************************************************************************/ + +static int ec_mac_parse(uint8_t *mac, const char *src, int allow_empty) +{ + unsigned int i, value; + const char *orig = src; + char *rem; + + if (!strlen(src)) { + if (allow_empty){ + return 0; + } + else { + EC_ERR("MAC address may not be empty.\n"); + return -EINVAL; + } + } + + for (i = 0; i < ETH_ALEN; i++) { + value = simple_strtoul(src, &rem, 16); + if (rem != src + 2 + || value > 0xFF + || (i < ETH_ALEN - 1 && *rem != ':')) { + EC_ERR("Invalid MAC address \"%s\".\n", orig); + return -EINVAL; + } + mac[i] = value; + if (i < ETH_ALEN - 1) + src = rem + 1; // skip colon + } + + return 0; } /*****************************************************************************/ @@ -331,20 +386,19 @@ */ int ecdev_offer(struct net_device *net_dev, /**< net_device to offer */ - ec_device_t **ecdev, /**< pointer to store a device on success */ - const char *driver_name, /**< name of the network driver */ - unsigned int device_index, /**< index of the supported device */ ec_pollfunc_t poll, /**< device poll function */ - struct module *module /**< pointer to the module */ + struct module *module, /**< pointer to the module */ + ec_device_t **ecdev /**< pointer to store a device on success */ ) { ec_master_t *master; - char str[50]; // FIXME - - list_for_each_entry(master, &masters, list) { - if (ec_device_id_check(master->main_device_id, net_dev, - driver_name, device_index)) { - ec_device_id_print(master->main_device_id, str); + char str[20]; + unsigned int i; + + for (i = 0; i < master_count; i++) { + master = &masters[i]; + if (ec_mac_equal(master->main_mac, net_dev->dev_addr)) { + ec_mac_print(master->main_mac, str); EC_INFO("Accepting device %s for master %u.\n", str, master->index); @@ -367,6 +421,10 @@ *ecdev = &master->main_device; // offer accepted return 0; // no error } + else if (master->debug_level) { + ec_mac_print(master->main_mac, str); + EC_DBG("Master %u declined device %s.\n", master->index, str); + } } *ecdev = NULL; // offer declined @@ -387,9 +445,9 @@ void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */) { ec_master_t *master = device->master; - char str[50]; // FIXME - - ec_device_id_print(master->main_device_id, str); + char str[20]; + + ec_mac_print(master->main_mac, str); EC_INFO("Master %u releasing main device %s.\n", master->index, str); @@ -468,7 +526,11 @@ EC_INFO("Requesting master %i...\n", master_index); - if (!(master = ec_find_master(master_index))) goto out_return; + if (master_index >= master_count) { + EC_ERR("Invalid master index %u.\n", master_index); + goto out_return; + } + master = &masters[master_index]; if (!atomic_dec_and_test(&master->available)) { atomic_inc(&master->available); diff -r b0994b4e3b37 -r aa23c48dca2d script/init.d/ethercat --- a/script/init.d/ethercat Thu Mar 08 13:06:20 2007 +0000 +++ b/script/init.d/ethercat Thu Mar 08 18:15:25 2007 +0000 @@ -68,16 +68,14 @@ #------------------------------------------------------------------------------ -function make_device_id() +function parse_mac_address() { if [ -z "${1}" ]; then - DEVICE_ID=";" + MAC="" elif echo ${1} | grep -qE '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'; then - DEVICE_ID="M${1};" - elif echo ${1} | grep -qE '^[^:]+:[0-9]+$'; then - DEVICE_ID="D${1};" + MAC=${1} else - echo Invalid device ID syntax in ${ETHERCAT_CONFIG} + echo Invalid MAC address \"${1}\" in ${ETHERCAT_CONFIG} /bin/false rc_status -v rc_exit @@ -103,10 +101,16 @@ BACKUP=$(eval echo "\${MASTER${MASTER_INDEX}_BACKUP}") if [ -z "${DEVICE}" ]; then break; fi - make_device_id ${DEVICE} - DEVICES=${DEVICES}${DEVICE_ID} - make_device_id ${BACKUP} - BACKUPS=${BACKUPS}${DEVICE_ID} + if [ ${MASTER_INDEX} -gt 0 ]; then + DEVICES=${DEVICES}, + BACKUPS=${BACKUPS}, + fi + + parse_mac_address ${DEVICE} + DEVICES=${DEVICES}${MAC} + + parse_mac_address ${BACKUP} + BACKUPS=${BACKUPS}${MAC} MASTER_INDEX=$(expr ${MASTER_INDEX} + 1) done diff -r b0994b4e3b37 -r aa23c48dca2d script/sysconfig/ethercat --- a/script/sysconfig/ethercat Thu Mar 08 13:06:20 2007 +0000 +++ b/script/sysconfig/ethercat Thu Mar 08 18:15:25 2007 +0000 @@ -9,20 +9,14 @@ # # Master device and backup-device settings. # -# The MASTERX_DEVICE variable specifies the ethernet device for master 'X', -# while the MASTERX_BACKUP variable specifies the backup ethernet device for +# The MASTER_DEVICE variable specifies the ethernet device for master 'X', +# while the MASTER_BACKUP variable specifies the backup ethernet device for # redundancy purposes. # -# There are three formats for specifying ethernet devices: -# 1) MAC address (example: "00:00:08:44:ab:66"). Specify the MAC address of -# the ethernet card to use. -# 2) PCI bus address (example: "01:1c.0"). Specify the PCU bis address of the -# ethernet card to use. -# 3) Driver and device index (example: "8139too:0"). Currently there are two -# drivers available: "8139too" and "e100". The device index is the index -# into driver-supported PCI cards. +# Specify the MAC address (hexadecimal with colons) of the Ethernet device to +# use. Example: 00:00:08:44:ab:66 # -# The MASTERX_DEVICE variables also determine, how many masters will be +# The MASTER_DEVICE variables also determine, how many masters will be # created: A non-empty variable MASTER0_DEVICE will create one master, adding # a non-empty variable MASTER1_DEVICE will create a second master, and so on. #