Skip to content
Snippets Groups Projects
Commit 6b12229e authored by Florian Pose's avatar Florian Pose
Browse files

Introduced per-master character devices for XML descriptions.

parent 0fd5c703
No related branches found
No related tags found
No related merge requests found
...@@ -43,7 +43,7 @@ ifneq ($(KERNELRELEASE),) ...@@ -43,7 +43,7 @@ ifneq ($(KERNELRELEASE),)
obj-m := ec_master.o obj-m := ec_master.o
ec_master-objs := module.o master.o device.o slave.o datagram.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") REV := $(shell svnversion $(src) 2>/dev/null || echo "unknown")
......
...@@ -98,7 +98,8 @@ static struct kobj_type ktype_ec_master = { ...@@ -98,7 +98,8 @@ static struct kobj_type ktype_ec_master = {
int ec_master_init(ec_master_t *master, /**< EtherCAT master */ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
unsigned int index, /**< master index */ 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; ec_eoe_t *eoe, *next_eoe;
...@@ -133,6 +134,12 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ ...@@ -133,6 +134,12 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
goto out_return; 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 // create EoE handlers
for (i = 0; i < eoeif_count; i++) { for (i = 0; i < eoeif_count; i++) {
if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { 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 */ ...@@ -168,6 +175,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
ec_eoe_clear(eoe); ec_eoe_clear(eoe);
kfree(eoe); kfree(eoe);
} }
ec_xmldev_clear(&master->xmldev);
out_clear_wq:
destroy_workqueue(master->workqueue); destroy_workqueue(master->workqueue);
out_return: out_return:
return -1; return -1;
...@@ -191,6 +200,7 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */) ...@@ -191,6 +200,7 @@ void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
ec_master_reset(master); ec_master_reset(master);
ec_fsm_clear(&master->fsm); ec_fsm_clear(&master->fsm);
destroy_workqueue(master->workqueue); destroy_workqueue(master->workqueue);
ec_xmldev_clear(&master->xmldev);
// clear EoE objects // clear EoE objects
list_for_each_entry_safe(eoe, next_eoe, &master->eoe_handlers, list) { list_for_each_entry_safe(eoe, next_eoe, &master->eoe_handlers, list) {
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "device.h" #include "device.h"
#include "domain.h" #include "domain.h"
#include "xmldev.h"
#include "fsm.h" #include "fsm.h"
/*****************************************************************************/ /*****************************************************************************/
...@@ -98,6 +99,8 @@ struct ec_master ...@@ -98,6 +99,8 @@ struct ec_master
ec_device_t *device; /**< EtherCAT device */ ec_device_t *device; /**< EtherCAT device */
ec_xmldev_t xmldev; /**< XML character device */
ec_fsm_t fsm; /**< master state machine */ ec_fsm_t fsm; /**< master state machine */
ec_master_mode_t mode; /**< master mode */ ec_master_mode_t mode; /**< master mode */
...@@ -136,7 +139,7 @@ struct ec_master ...@@ -136,7 +139,7 @@ struct ec_master
/*****************************************************************************/ /*****************************************************************************/
// master creation and deletion // 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_clear(struct kobject *);
void ec_master_reset(ec_master_t *); void ec_master_reset(ec_master_t *);
......
...@@ -56,6 +56,7 @@ void __exit ec_cleanup_module(void); ...@@ -56,6 +56,7 @@ void __exit ec_cleanup_module(void);
static int ec_master_count = 1; /**< parameter value, number of masters */ static int ec_master_count = 1; /**< parameter value, number of masters */
static int ec_eoeif_count = 0; /**< parameter value, number of EoE interf. */ static int ec_eoeif_count = 0; /**< parameter value, number of EoE interf. */
static struct list_head ec_masters; /**< list of masters */ static struct list_head ec_masters; /**< list of masters */
static dev_t device_number;
/*****************************************************************************/ /*****************************************************************************/
...@@ -89,7 +90,12 @@ int __init ec_init_module(void) ...@@ -89,7 +90,12 @@ int __init ec_init_module(void)
EC_INFO("Master driver, %s\n", EC_COMPILE_INFO); EC_INFO("Master driver, %s\n", EC_COMPILE_INFO);
if (ec_master_count < 1) { 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; goto out_return;
} }
...@@ -104,7 +110,7 @@ int __init ec_init_module(void) ...@@ -104,7 +110,7 @@ int __init ec_init_module(void)
goto out_free; 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; goto out_free;
if (kobject_add(&master->kobj)) { if (kobject_add(&master->kobj)) {
...@@ -148,6 +154,8 @@ void __exit ec_cleanup_module(void) ...@@ -148,6 +154,8 @@ void __exit ec_cleanup_module(void)
kobject_put(&master->kobj); // free master kobject_put(&master->kobj); // free master
} }
unregister_chrdev_region(device_number, ec_master_count);
EC_INFO("Master driver cleaned up.\n"); EC_INFO("Master driver cleaned up.\n");
} }
......
/******************************************************************************
*
* $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;
}
/*****************************************************************************/
/******************************************************************************
*
* $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
...@@ -49,6 +49,10 @@ ...@@ -49,6 +49,10 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
device="ecxml"
#------------------------------------------------------------------------------
ETHERCAT_CONFIG=/etc/sysconfig/ethercat ETHERCAT_CONFIG=/etc/sysconfig/ethercat
if [ ! -r $ETHERCAT_CONFIG ]; then if [ ! -r $ETHERCAT_CONFIG ]; then
...@@ -75,7 +79,7 @@ build_eoe_bridge() ...@@ -75,7 +79,7 @@ build_eoe_bridge()
# add bridge, if it does not already exist # add bridge, if it does not already exist
if ! /sbin/brctl show | grep -E -q "^$EOE_BRIDGE"; then 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 /bin/false
rc_status -v rc_status -v
rc_exit rc_exit
...@@ -155,7 +159,8 @@ case "$1" in ...@@ -155,7 +159,8 @@ case "$1" in
fi fi
if [ -z "$EOE_INTERFACES" ]; then 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 EOE_INTERFACES=$EOE_DEVICES
else else
EOE_INTERFACES=0 EOE_INTERFACES=0
...@@ -181,7 +186,16 @@ case "$1" in ...@@ -181,7 +186,16 @@ case "$1" in
rc_exit rc_exit
fi 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 if ! modprobe ec_8139too ec_device_index=$DEVICE_INDEX; then
rmmod ec_master rmmod ec_master
modprobe 8139too modprobe 8139too
...@@ -190,7 +204,7 @@ case "$1" in ...@@ -190,7 +204,7 @@ case "$1" in
rc_exit rc_exit
fi fi
# build EoE bridge # build EoE bridge
build_eoe_bridge build_eoe_bridge
rc_status -v rc_status -v
...@@ -199,7 +213,7 @@ case "$1" in ...@@ -199,7 +213,7 @@ case "$1" in
stop) stop)
echo -n "Shutting down EtherCAT master " echo -n "Shutting down EtherCAT master "
# unload modules # unload modules
for mod in ec_8139too ec_master; do for mod in ec_8139too ec_master; do
if lsmod | grep "^$mod " > /dev/null; then if lsmod | grep "^$mod " > /dev/null; then
if ! rmmod $mod; then if ! rmmod $mod; then
...@@ -210,9 +224,12 @@ case "$1" in ...@@ -210,9 +224,12 @@ case "$1" in
fi; fi;
done done
# remove device node
rm -f /dev/${device}0
sleep 1 sleep 1
# reload previous modules # reload previous modules
if ! modprobe 8139too; then if ! modprobe 8139too; then
echo "Warning: Failed to restore 8139too module." echo "Warning: Failed to restore 8139too module."
fi fi
...@@ -235,7 +252,7 @@ case "$1" in ...@@ -235,7 +252,7 @@ case "$1" in
lsmod | grep "^ec_8139too " > /dev/null lsmod | grep "^ec_8139too " > /dev/null
device_running=$? device_running=$?
# master module and device module loaded? # master module and device module loaded?
test $master_running -eq 0 -a $device_running -eq 0 test $master_running -eq 0 -a $device_running -eq 0
rc_status -v rc_status -v
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment