Introduced per-master character devices for XML descriptions.
authorFlorian Pose <fp@igh-essen.com>
Tue, 19 Sep 2006 13:28:40 +0000
changeset 361 29af81543ce1
parent 360 a7a8ed41b50a
child 362 ae38aeb6fde9
Introduced per-master character devices for XML descriptions.
master/Makefile
master/master.c
master/master.h
master/module.c
master/xmldev.c
master/xmldev.h
script/ethercat.sh
--- a/master/Makefile	Tue Sep 19 13:09:39 2006 +0000
+++ b/master/Makefile	Tue Sep 19 13:28:40 2006 +0000
@@ -43,7 +43,7 @@
 obj-m := ec_master.o
 
 ec_master-objs := module.o master.o device.o slave.o datagram.o \
-		domain.o mailbox.o ethernet.o debug.o fsm.o
+		domain.o mailbox.o ethernet.o debug.o fsm.o xmldev.o
 
 REV := $(shell svnversion $(src) 2>/dev/null || echo "unknown")
 
--- a/master/master.c	Tue Sep 19 13:09:39 2006 +0000
+++ b/master/master.c	Tue Sep 19 13:28:40 2006 +0000
@@ -98,7 +98,8 @@
 
 int ec_master_init(ec_master_t *master, /**< EtherCAT master */
                    unsigned int index, /**< master index */
-                   unsigned int eoeif_count /**< number of EoE interfaces */
+                   unsigned int eoeif_count, /**< number of EoE interfaces */
+                   dev_t dev_num /**< number for XML cdev's */
                    )
 {
     ec_eoe_t *eoe, *next_eoe;
@@ -133,6 +134,12 @@
         goto out_return;
     }
 
+    // init XML character device
+    if (ec_xmldev_init(&master->xmldev, master, dev_num)) {
+        EC_ERR("Failed to init XML character device.\n");
+        goto out_clear_wq;
+    }
+
     // create EoE handlers
     for (i = 0; i < eoeif_count; i++) {
         if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
@@ -168,6 +175,8 @@
         ec_eoe_clear(eoe);
         kfree(eoe);
     }
+    ec_xmldev_clear(&master->xmldev);
+ out_clear_wq:
     destroy_workqueue(master->workqueue);
  out_return:
     return -1;
@@ -191,6 +200,7 @@
     ec_master_reset(master);
     ec_fsm_clear(&master->fsm);
     destroy_workqueue(master->workqueue);
+    ec_xmldev_clear(&master->xmldev);
 
     // clear EoE objects
     list_for_each_entry_safe(eoe, next_eoe, &master->eoe_handlers, list) {
--- a/master/master.h	Tue Sep 19 13:09:39 2006 +0000
+++ b/master/master.h	Tue Sep 19 13:28:40 2006 +0000
@@ -47,6 +47,7 @@
 
 #include "device.h"
 #include "domain.h"
+#include "xmldev.h"
 #include "fsm.h"
 
 /*****************************************************************************/
@@ -98,6 +99,8 @@
 
     ec_device_t *device; /**< EtherCAT device */
 
+    ec_xmldev_t xmldev; /**< XML character device */
+
     ec_fsm_t fsm; /**< master state machine */
     ec_master_mode_t mode; /**< master mode */
 
@@ -136,7 +139,7 @@
 /*****************************************************************************/
 
 // master creation and deletion
-int ec_master_init(ec_master_t *, unsigned int, unsigned int);
+int ec_master_init(ec_master_t *, unsigned int, unsigned int, dev_t);
 void ec_master_clear(struct kobject *);
 void ec_master_reset(ec_master_t *);
 
--- a/master/module.c	Tue Sep 19 13:09:39 2006 +0000
+++ b/master/module.c	Tue Sep 19 13:28:40 2006 +0000
@@ -56,6 +56,7 @@
 static int ec_master_count = 1; /**< parameter value, number of masters */
 static int ec_eoeif_count = 0; /**< parameter value, number of EoE interf. */
 static struct list_head ec_masters; /**< list of masters */
+static dev_t device_number;
 
 /*****************************************************************************/
 
@@ -89,7 +90,12 @@
     EC_INFO("Master driver, %s\n", EC_COMPILE_INFO);
 
     if (ec_master_count < 1) {
-        EC_ERR("Error - Invalid ec_master_count: %i\n", ec_master_count);
+        EC_ERR("Invalid ec_master_count: %i\n", ec_master_count);
+        goto out_return;
+    }
+
+    if (alloc_chrdev_region(&device_number, 0, ec_master_count, "EtherCAT")) {
+        EC_ERR("Failed to allocate device number!\n");
         goto out_return;
     }
 
@@ -104,7 +110,7 @@
             goto out_free;
         }
 
-        if (ec_master_init(master, i, ec_eoeif_count))
+        if (ec_master_init(master, i, ec_eoeif_count, device_number))
             goto out_free;
 
         if (kobject_add(&master->kobj)) {
@@ -148,6 +154,8 @@
         kobject_put(&master->kobj); // free master
     }
 
+    unregister_chrdev_region(device_number, ec_master_count);
+
     EC_INFO("Master driver cleaned up.\n");
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/xmldev.c	Tue Sep 19 13:28:40 2006 +0000
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ *  $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 XML device.
+*/
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+
+#include "master.h"
+#include "xmldev.h"
+
+/*****************************************************************************/
+
+static char *test_str = "hello world!\n";
+
+int ecxmldev_open(struct inode *, struct file *);
+int ecxmldev_release(struct inode *, struct file *);
+ssize_t ecxmldev_read(struct file *, char __user *, size_t, loff_t *);
+ssize_t ecxmldev_write(struct file *, const char __user *, size_t, loff_t *);
+
+/*****************************************************************************/
+
+static struct file_operations fops = {
+    .owner   = THIS_MODULE,
+    .open    = ecxmldev_open,
+    .release = ecxmldev_release,
+    .read    = ecxmldev_read,
+    .write   = ecxmldev_write
+};
+
+/*****************************************************************************/
+
+/**
+   XML device constructor.
+   \return 0 in case of success, else < 0
+*/
+
+int ec_xmldev_init(ec_xmldev_t *xmldev, /**< EtherCAT XML device */
+                   ec_master_t *master, /**< EtherCAT master */
+                   dev_t dev_num /**< device number */
+                   )
+{
+    cdev_init(&xmldev->cdev, &fops);
+    xmldev->cdev.owner = THIS_MODULE;
+    if (cdev_add(&xmldev->cdev,
+		 MKDEV(MAJOR(dev_num), master->index), 1)) {
+	EC_ERR("Failed to add character device!\n");
+	return -1;
+    }
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   XML device destructor.
+*/
+
+void ec_xmldev_clear(ec_xmldev_t *xmldev /**< EtherCAT XML device */)
+{
+    cdev_del(&xmldev->cdev);
+}
+
+/*****************************************************************************/
+
+int ecxmldev_open(struct inode *inode, struct file *filp)
+{
+    ec_xmldev_t *xmldev;
+
+    xmldev = container_of(inode->i_cdev, ec_xmldev_t, cdev);
+    filp->private_data = xmldev;
+
+    EC_DBG("File opened.\n");
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+int ecxmldev_release(struct inode *inode, struct file *filp)
+{
+    EC_DBG("File closed.\n");
+    return 0;
+}
+
+/*****************************************************************************/
+
+ssize_t ecxmldev_read(struct file *filp, char __user *buf,
+		      size_t count, loff_t *f_pos)
+{
+    size_t len = strlen(test_str);
+
+    if (*f_pos >= len) return 0;
+    if (*f_pos + count > len) count = len - *f_pos;
+
+    if (copy_to_user(buf, test_str + *f_pos, count)) return -EFAULT;
+
+    *f_pos += count;
+
+    return count;
+}
+
+/*****************************************************************************/
+
+ssize_t ecxmldev_write(struct file *filp,
+		       const char __user *buf,
+		       size_t count,
+		       loff_t *f_pos)
+{
+    return -EFAULT;
+}
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/xmldev.h	Tue Sep 19 13:28:40 2006 +0000
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ *  $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 XML device.
+*/
+
+/*****************************************************************************/
+
+#ifndef _EC_XMLDEV_H_
+#define _EC_XMLDEV_H_
+
+#include <linux/fs.h>
+#include <linux/cdev.h>
+
+#include "globals.h"
+#include "../include/ecrt.h"
+
+/*****************************************************************************/
+
+/**
+   EtherCAT XML character device.
+*/
+
+typedef struct
+{
+    ec_master_t *master; /**< master owning the device */
+    struct cdev cdev; /**< character device */
+}
+ec_xmldev_t;
+
+/*****************************************************************************/
+
+int ec_xmldev_init(ec_xmldev_t *, ec_master_t *, dev_t);
+void ec_xmldev_clear(ec_xmldev_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/script/ethercat.sh	Tue Sep 19 13:09:39 2006 +0000
+++ b/script/ethercat.sh	Tue Sep 19 13:28:40 2006 +0000
@@ -49,6 +49,10 @@
 
 #------------------------------------------------------------------------------
 
+device="ecxml"
+
+#------------------------------------------------------------------------------
+
 ETHERCAT_CONFIG=/etc/sysconfig/ethercat
 
 if [ ! -r $ETHERCAT_CONFIG ]; then
@@ -75,7 +79,7 @@
 
     # add bridge, if it does not already exist
     if ! /sbin/brctl show | grep -E -q "^$EOE_BRIDGE"; then
-	if ! /sbin/brctl addbr $EOE_BRIDGE; then
+        if ! /sbin/brctl addbr $EOE_BRIDGE; then
 	    /bin/false
 	    rc_status -v
 	    rc_exit
@@ -155,7 +159,8 @@
 	fi
 
 	if [ -z "$EOE_INTERFACES" ]; then
-	    if [ -n "$EOE_DEVICES" ]; then # support legacy sysconfig files
+            # support legacy sysconfig files
+	    if [ -n "$EOE_DEVICES" ]; then
 		EOE_INTERFACES=$EOE_DEVICES
 	    else
 		EOE_INTERFACES=0
@@ -181,7 +186,16 @@
 	    rc_exit
 	fi
 
-        # load device module
+	# remove stale device node
+	rm -f /dev/${device}0
+
+	# get dynamic major number
+	major=$(awk "\$2==\"EtherCAT\" {print \$1}" /proc/devices)
+
+	# create character device
+	mknod /dev/${device}0 c $major 0
+
+	# load device module
 	if ! modprobe ec_8139too ec_device_index=$DEVICE_INDEX; then
 	    rmmod ec_master
 	    modprobe 8139too
@@ -190,7 +204,7 @@
 	    rc_exit
 	fi
 
-        # build EoE bridge
+	# build EoE bridge
 	build_eoe_bridge
 
 	rc_status -v
@@ -199,7 +213,7 @@
     stop)
 	echo -n "Shutting down EtherCAT master "
 
-        # unload modules
+	# unload modules
 	for mod in ec_8139too ec_master; do
 	    if lsmod | grep "^$mod " > /dev/null; then
 		if ! rmmod $mod; then
@@ -210,9 +224,12 @@
 	    fi;
 	done
 
+	# remove device node
+	rm -f /dev/${device}0
+
 	sleep 1
 
-        # reload previous modules
+	# reload previous modules
 	if ! modprobe 8139too; then
 	    echo "Warning: Failed to restore 8139too module."
 	fi
@@ -235,7 +252,7 @@
 	lsmod | grep "^ec_8139too " > /dev/null
 	device_running=$?
 
-        # master module and device module loaded?
+	# master module and device module loaded?
 	test $master_running -eq 0 -a $device_running -eq 0
 
 	rc_status -v