# HG changeset patch # User Florian Pose # Date 1171964603 0 # Node ID 9a2121b500b1fd10327e7f3a97faefd0f3ac53d0 # Parent 609e58ece96a8307129950b2f02900e67afcce1b Layed out device ID functionality in own files. diff -r 609e58ece96a -r 9a2121b500b1 master/Kbuild --- a/master/Kbuild Tue Feb 20 09:37:57 2007 +0000 +++ b/master/Kbuild Tue Feb 20 09:43:23 2007 +0000 @@ -35,10 +35,9 @@ obj-m := ec_master.o -ec_master-objs := module.o master.o device.o slave.o datagram.o \ - domain.o mailbox.o canopen.o ethernet.o \ - fsm_sii.o fsm_change.o fsm_coe.o fsm_slave.o fsm_master.o \ - xmldev.o +ec_master-objs := module.o master.o device.o device_id.o slave.o datagram.o \ + domain.o mailbox.o canopen.o ethernet.o fsm_sii.o fsm_change.o fsm_coe.o \ + fsm_slave.o fsm_master.o xmldev.o ifeq ($(EC_DBG_IF),1) ec_master-objs += debug.o diff -r 609e58ece96a -r 9a2121b500b1 master/Makefile.am --- a/master/Makefile.am Tue Feb 20 09:37:57 2007 +0000 +++ b/master/Makefile.am Tue Feb 20 09:43:23 2007 +0000 @@ -37,6 +37,7 @@ datagram.c datagram.h \ debug.c debug.h \ device.c device.h \ + device_id.c device_id.h \ domain.c domain.h \ doxygen.c \ ethernet.c ethernet.h \ diff -r 609e58ece96a -r 9a2121b500b1 master/device.h --- a/master/device.h Tue Feb 20 09:37:57 2007 +0000 +++ b/master/device.h Tue Feb 20 09:43:23 2007 +0000 @@ -53,21 +53,6 @@ /*****************************************************************************/ -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; - -/*****************************************************************************/ - /** EtherCAT device. An EtherCAT device is a network interface card, that is owned by an diff -r 609e58ece96a -r 9a2121b500b1 master/device_id.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/device_id.c Tue Feb 20 09:43:23 2007 +0000 @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * $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; + } +} + +/*****************************************************************************/ diff -r 609e58ece96a -r 9a2121b500b1 master/device_id.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/device_id.h Tue Feb 20 09:43:23 2007 +0000 @@ -0,0 +1,73 @@ +/****************************************************************************** + * + * $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); + +/*****************************************************************************/ + +#endif diff -r 609e58ece96a -r 9a2121b500b1 master/master.h --- a/master/master.h Tue Feb 20 09:37:57 2007 +0000 +++ b/master/master.h Tue Feb 20 09:43:23 2007 +0000 @@ -48,6 +48,7 @@ #include #include "device.h" +#include "device_id.h" #include "domain.h" #include "fsm_master.h" diff -r 609e58ece96a -r 9a2121b500b1 master/module.c --- a/master/module.c Tue Feb 20 09:37:57 2007 +0000 +++ b/master/module.c Tue Feb 20 09:43:23 2007 +0000 @@ -57,8 +57,8 @@ static char *main; /**< main devices parameter */ static char *backup; /**< backup devices parameter */ -static LIST_HEAD(main_device_ids); /**< list of main device IDs */ -static LIST_HEAD(backup_device_ids); /**< list of main device IDs */ +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 dev_t device_number; /**< XML character device number */ ec_xmldev_t xmldev; /**< XML character device */ @@ -83,157 +83,6 @@ /*****************************************************************************/ -void clear_device_ids(struct list_head *device_ids) -{ - ec_device_id_t *dev_id, *next_dev_id; - - list_for_each_entry_safe(dev_id, next_dev_id, device_ids, list) { - list_del(&dev_id->list); - kfree(dev_id); - } -} - -/*****************************************************************************/ - -static int parse_device_id_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; -} - -/*****************************************************************************/ - -static int parse_device_ids(struct list_head *device_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 (parse_device_id_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, device_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: - clear_device_ids(device_ids); - return -1; -} - -/*****************************************************************************/ - -static int create_device_ids(void) -{ - ec_device_id_t *id; - unsigned int main_count = 0, backup_count = 0; - - if (parse_device_ids(&main_device_ids, main)) - return -1; - - if (parse_device_ids(&backup_device_ids, main)) - return -1; - - // count main device IDs and check for empty ones - list_for_each_entry(id, &main_device_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_device_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_device_ids); - backup_count++; - } - - return 0; -} - -/*****************************************************************************/ - -static int 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; - } -} - - -/*****************************************************************************/ - /** Module initialization. Initializes \a ec_master_count masters. @@ -253,14 +102,16 @@ goto out_return; } - if (create_device_ids()) - goto out_free_ids; + if (ec_device_id_process_params(main, backup, &main_ids, &backup_ids)) + goto out_cdev; - if (!list_empty(&main_device_ids)) { + // 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_device_ids.next, ec_device_id_t, list); + list_entry(main_ids.next, ec_device_id_t, list); backup_dev_id = - list_entry(backup_device_ids.next, ec_device_id_t, list); + list_entry(backup_ids.next, ec_device_id_t, list); while (1) { if (!(master = (ec_master_t *) @@ -278,7 +129,7 @@ master_index++; // last device IDs? - if (main_dev_id->list.next == &main_device_ids) + if (main_dev_id->list.next == &main_ids) break; // next device IDs @@ -296,12 +147,11 @@ out_free_masters: list_for_each_entry_safe(master, next, &masters, list) { list_del(&master->list); - kobject_del(&master->kobj); - kobject_put(&master->kobj); - } -out_free_ids: - clear_device_ids(&main_device_ids); - clear_device_ids(&backup_device_ids); + ec_master_destroy(master); + } + ec_device_id_clear_list(&main_ids); + ec_device_id_clear_list(&backup_ids); +out_cdev: unregister_chrdev_region(device_number, 1); out_return: return -1; @@ -318,16 +168,18 @@ { ec_master_t *master, *next; - EC_INFO("Cleaning up master driver...\n"); + 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); unregister_chrdev_region(device_number, 1); - EC_INFO("Master driver cleaned up.\n"); + EC_INFO("Master module cleaned up.\n"); } /*****************************************************************************/ @@ -474,7 +326,7 @@ goto out_return; } - if (device_id_check(master->main_device_id, net_dev, + if (ec_device_id_check(master->main_device_id, net_dev, driver_name, device_index)) { EC_INFO("Accepting device %s:%u (", driver_name, device_index);