Layed out device ID functionality in own files.
--- 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
--- 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 \
--- 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
--- /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 <linux/list.h>
+#include <linux/netdevice.h>
+
+#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;
+ }
+}
+
+/*****************************************************************************/
--- /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 <linux/if_ether.h>
+
+#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
--- 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 <asm/semaphore.h>
#include "device.h"
+#include "device_id.h"
#include "domain.h"
#include "fsm_master.h"
--- 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);