diff --git a/master/Makefile b/master/Makefile index af895dc885392b75c4e0cd28e0e13903da2678e0..ef5d2d2e11f4b2bdcfc5f356bbaee5129c831718 100644 --- a/master/Makefile +++ b/master/Makefile @@ -43,7 +43,7 @@ ifneq ($(KERNELRELEASE),) 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") diff --git a/master/master.c b/master/master.c index 0d817f5323e3f12da2f8ea176c8f110fcd7aab46..521dbc616f417e51dd154269f524fb665947fddb 100644 --- a/master/master.c +++ b/master/master.c @@ -98,7 +98,8 @@ static struct kobj_type ktype_ec_master = { 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 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ 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 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ 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 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */) 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) { diff --git a/master/master.h b/master/master.h index aae9481805cad45e71bf33f3c65955079b139156..1ba444d16505a549dba66ee9657c52c5d809ab3d 100644 --- a/master/master.h +++ b/master/master.h @@ -47,6 +47,7 @@ #include "device.h" #include "domain.h" +#include "xmldev.h" #include "fsm.h" /*****************************************************************************/ @@ -98,6 +99,8 @@ struct ec_master 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 @@ struct ec_master /*****************************************************************************/ // 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 *); diff --git a/master/module.c b/master/module.c index 270b07a79e7e6b91cdc4d2a499b7356d7c7390d4..67e6e779c0d379c8c17ebc41f35a5208702b101e 100644 --- a/master/module.c +++ b/master/module.c @@ -56,6 +56,7 @@ void __exit ec_cleanup_module(void); 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 @@ int __init ec_init_module(void) 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 @@ int __init ec_init_module(void) 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 @@ void __exit ec_cleanup_module(void) kobject_put(&master->kobj); // free master } + unregister_chrdev_region(device_number, ec_master_count); + EC_INFO("Master driver cleaned up.\n"); } diff --git a/master/xmldev.c b/master/xmldev.c new file mode 100644 index 0000000000000000000000000000000000000000..58bae23b1a208be93458fb70eb47f04c30865a4e --- /dev/null +++ b/master/xmldev.c @@ -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; +} + +/*****************************************************************************/ diff --git a/master/xmldev.h b/master/xmldev.h new file mode 100644 index 0000000000000000000000000000000000000000..9b8ea775a9ae8d0cf1b7425a9dc4d59dde485f3e --- /dev/null +++ b/master/xmldev.h @@ -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 diff --git a/script/ethercat.sh b/script/ethercat.sh index 79a365a5bae7d826e1e0d4be211edd941c63da1b..102ef8f8f2410166ad6273562e7c4c35b1b23e2b 100755 --- a/script/ethercat.sh +++ b/script/ethercat.sh @@ -49,6 +49,10 @@ #------------------------------------------------------------------------------ +device="ecxml" + +#------------------------------------------------------------------------------ + ETHERCAT_CONFIG=/etc/sysconfig/ethercat if [ ! -r $ETHERCAT_CONFIG ]; then @@ -75,7 +79,7 @@ build_eoe_bridge() # 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 @@ case "$1" in 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 @@ case "$1" in 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 @@ case "$1" in rc_exit fi - # build EoE bridge + # build EoE bridge build_eoe_bridge rc_status -v @@ -199,7 +213,7 @@ case "$1" in 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 @@ case "$1" in 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 @@ case "$1" in 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