Layed out device ID functionality in own files.
authorFlorian Pose <fp@igh-essen.com>
Tue, 20 Feb 2007 09:43:23 +0000
changeset 575 9a2121b500b1
parent 574 609e58ece96a
child 576 158c5a3d0a2a
Layed out device ID functionality in own files.
master/Kbuild
master/Makefile.am
master/device.h
master/device_id.c
master/device_id.h
master/master.h
master/module.c
--- 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);