Prepared Free-Run mode

This commit is contained in:
Florian Pose 2006-04-12 10:40:32 +00:00
parent be21ebac29
commit 7818664587
9 changed files with 246 additions and 118 deletions

View File

@ -199,15 +199,10 @@ static int debug = -1;
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
// Uncomment for debugging
//#define EC_DEBUG
// Device index for EtherCAT device selection
static int ec_device_index = -1;
static int ec_device_master_index = 0;
static ec_device_t *rtl_ec_dev;
int rtl_ec_dev_registered = 0;
struct net_device *rtl_ec_net_dev = NULL;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1025,13 +1020,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (board_idx == ec_device_index)
{
printk(KERN_INFO "Registering EtherCAT device...\n");
rtl_ec_dev = ecdev_register(ec_device_master_index, dev,
rtl8139_interrupt, THIS_MODULE);
if (rtl_ec_dev) strcpy(dev->name, "ec0");
if (board_idx == ec_device_index) {
rtl_ec_net_dev = dev;
strcpy(dev->name, "ec0");
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1092,7 +1083,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* EtherCAT-Karten nicht beim Stack anmelden. */
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
DPRINTK("About to register device named %s (%p)...\n", dev->name, dev);
i = register_netdev (dev);
@ -1190,7 +1181,7 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
unregister_netdev (dev);
}
@ -1403,7 +1394,7 @@ static int rtl8139_open (struct net_device *dev)
printk(KERN_DEBUG "%s: open\n", dev->name);
#endif
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
retval = request_irq(dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
if (retval)
@ -1420,7 +1411,7 @@ static int rtl8139_open (struct net_device *dev)
{
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
free_irq(dev->irq, dev);
}
@ -1445,7 +1436,7 @@ static int rtl8139_open (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
netif_start_queue (dev);
@ -1471,7 +1462,7 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
{
struct rtl8139_private *tp = netdev_priv(dev);
if (ecdev_is_ec(rtl_ec_dev, dev)) {
if (dev == rtl_ec_net_dev) {
void __iomem *ioaddr = tp->mmio_addr;
uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS;
ecdev_link_state(rtl_ec_dev, state ? 1 : 0);
@ -1545,7 +1536,7 @@ static void rtl8139_hw_start (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16 (IntrMask, rtl8139_intr_mask);
@ -1814,7 +1805,7 @@ static void rtl8139_tx_timeout (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
spin_lock(&tp->rx_lock);
@ -1864,16 +1855,16 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
memset(tp->tx_buf[entry], 0, ETH_ZLEN);
skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
if (!ecdev_is_ec(rtl_ec_dev, dev)) dev_kfree_skb(skb);
if (dev != rtl_ec_net_dev) dev_kfree_skb(skb);
}
else
{
if (!ecdev_is_ec(rtl_ec_dev, dev)) dev_kfree_skb(skb);
if (dev != rtl_ec_net_dev) dev_kfree_skb(skb);
tp->stats.tx_dropped++;
return 0;
}
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
spin_lock_irq(&tp->lock);
}
@ -1890,7 +1881,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
@ -1965,7 +1956,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
#ifndef RTL8139_NDEBUG
if (!ecdev_is_ec(rtl_ec_dev, dev) && tp->cur_tx - dirty_tx > NUM_TX_DESC) {
if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) {
printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n",
dev->name, dirty_tx, tp->cur_tx);
dirty_tx += NUM_TX_DESC;
@ -1981,7 +1972,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
netif_wake_queue (dev);
}
@ -2120,7 +2111,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
RTL_R16 (RxBufAddr),
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
while ((ecdev_is_ec(rtl_ec_dev, dev) || netif_running(dev))
while ((dev == rtl_ec_net_dev || netif_running(dev))
&& received < budget
&& (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
u32 ring_offset = cur_rx % RX_BUF_LEN;
@ -2137,7 +2128,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev) && netif_msg_rx_status(tp))
if (dev != rtl_ec_net_dev && netif_msg_rx_status(tp))
printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x,"
" cur %4.4x.\n", dev->name, rx_status,
rx_size, cur_rx);
@ -2193,7 +2184,7 @@ no_early_rx:
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
@ -2356,7 +2347,7 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (ecdev_is_ec(rtl_ec_dev, dev))
if (dev == rtl_ec_net_dev)
{
status = RTL_R16 (IntrStatus);
}
@ -2380,7 +2371,7 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
/* close possible race's with dev_close */
if (unlikely(!netif_running(dev))) {
@ -2408,7 +2399,7 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
if (status & RxAckBits)
{
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
/* Polling vormerken */
if (netif_rx_schedule_prep(dev)) {
@ -2438,7 +2429,7 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
out:
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
spin_unlock (&tp->lock);
}
@ -2472,7 +2463,7 @@ static int rtl8139_close (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (!ecdev_is_ec(rtl_ec_dev, dev))
if (dev != rtl_ec_net_dev)
{
netif_stop_queue(dev);
if (tp->thr_pid >= 0) {
@ -2737,7 +2728,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (ecdev_is_ec(rtl_ec_dev, dev) || !netif_running(dev))
if (dev == rtl_ec_net_dev || !netif_running(dev))
return -EINVAL;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2758,7 +2749,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (ecdev_is_ec(rtl_ec_dev, dev) || netif_running(dev))
if (dev == rtl_ec_net_dev || netif_running(dev))
{
spin_lock_irqsave (&tp->lock, flags);
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
@ -2845,7 +2836,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (ecdev_is_ec(rtl_ec_dev, dev) || !netif_running (dev))
if (dev == rtl_ec_net_dev || !netif_running (dev))
return 0;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2878,7 +2869,7 @@ static int rtl8139_resume (struct pci_dev *pdev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (ecdev_is_ec(rtl_ec_dev, dev) || !netif_running (dev))
if (dev == rtl_ec_net_dev || !netif_running (dev))
return 0;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2907,38 +2898,42 @@ static struct pci_driver rtl8139_pci_driver = {
static int __init rtl8139_init_module (void)
{
/* when we're a module, we always print a version message,
* even if no 8139 board is found.
*/
#ifdef MODULE
printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
#endif
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
printk(KERN_INFO "Initializing RTL8139-EtherCAT module. %s\n", COMPILE_INFO);
printk(KERN_INFO "EtherCAT device index is %i.\n", ec_device_index);
printk(KERN_INFO RTL8139_DRIVER_NAME " " COMPILE_INFO "\n");
printk(KERN_INFO "ec_device_index is %i\n", ec_device_index);
if (pci_module_init(&rtl8139_pci_driver) < 0)
{
printk(KERN_ERR "Could not init PCI module.\n");
goto out_ec_dev;
if (pci_module_init(&rtl8139_pci_driver) < 0) {
printk(KERN_ERR "Failed to init PCI module.\n");
goto out_return;
}
if (!rtl_ec_dev)
{
printk(KERN_WARNING "NO EtherCAT device registered!\n");
if (rtl_ec_net_dev) {
printk(KERN_INFO "Registering EtherCAT device...\n");
if (!(rtl_ec_dev = ecdev_register(ec_device_master_index,
rtl_ec_net_dev, rtl8139_interrupt,
THIS_MODULE))) {
printk(KERN_ERR "Failed to register EtherCAT device!\n");
goto out_pci;
}
printk(KERN_INFO "Starting EtherCAT device...\n");
if (ecdev_start(ec_device_master_index)) {
printk(KERN_ERR "Failed to start EtherCAT device!\n");
goto out_unregister;
}
}
else {
printk(KERN_WARNING "NO EtherCAT device registered!\n");
}
return 0;
out_ec_dev:
if (rtl_ec_dev) {
printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
}
out_unregister:
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
out_pci:
pci_unregister_driver(&rtl8139_pci_driver);
out_return:
return -1;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2951,14 +2946,16 @@ static void __exit rtl8139_cleanup_module (void)
printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
pci_unregister_driver(&rtl8139_pci_driver);
if (rtl_ec_dev) {
printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
if (rtl_ec_net_dev) {
printk(KERN_INFO "Stopping device...\n");
ecdev_stop(ec_device_master_index);
printk(KERN_INFO "Unregistering device...\n");
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
}
pci_unregister_driver(&rtl8139_pci_driver);
printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n");
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

View File

@ -17,9 +17,8 @@ obj-m := ec_8139too.o
ec_8139too-objs := 8139too.o
REV = `svnversion $(src)`
DATE = `date`
REV := $(shell svnversion $(src))
DATE := $(shell date)
EXTRA_CFLAGS = -DEC_REV="$(REV)" -DEC_USER="$(USER)" -DEC_DATE="$(DATE)"
#------------------------------------------------------------------------------

View File

@ -26,10 +26,12 @@ ec_device_t *ecdev_register(unsigned int master_index,
struct module *module);
void ecdev_unregister(unsigned int master_index, ec_device_t *device);
int ecdev_start(unsigned int master_index);
void ecdev_stop(unsigned int master_index);
/*****************************************************************************/
// Device methods
int ecdev_is_ec(const ec_device_t *device, const struct net_device *net_dev);
void ecdev_receive(ec_device_t *device, const void *data, size_t size);
void ecdev_link_state(ec_device_t *device, uint8_t newstate);

View File

@ -33,7 +33,7 @@ else
KERNEL := $(shell uname -r)
endif
KERNELDIR = /lib/modules/$(KERNEL)/build
KERNELDIR := /lib/modules/$(KERNEL)/build
modules:
$(MAKE) -C $(KERNELDIR) M=`pwd`

View File

@ -196,21 +196,6 @@ void ec_device_call_isr(ec_device_t *device /**< EtherCAT-Ger
*
*****************************************************************************/
/**
Prüft, ob das Net-Device \a dev zum registrierten EtherCAT-Gerät gehört.
\return 0 wenn nein, nicht-null wenn ja.
*/
inline int ecdev_is_ec(const ec_device_t *device, /**< EtherCAT-Gerät */
const struct net_device *dev /**< Net-Device */
)
{
return device && device->dev == dev;
}
/*****************************************************************************/
/**
Nimmt einen Empfangenen Rahmen entgegen.
@ -240,6 +225,11 @@ void ecdev_link_state(ec_device_t *device, /**< EtherCAT-Ger
uint8_t state /**< Verbindungszustand */
)
{
if (unlikely(!device)) {
EC_WARN("ecdev_link_state: no device!\n");
return;
}
if (likely(state != device->link_state)) {
device->link_state = state;
EC_INFO("Link state changed to %s.\n", (state ? "UP" : "DOWN"));
@ -248,7 +238,6 @@ void ecdev_link_state(ec_device_t *device, /**< EtherCAT-Ger
/*****************************************************************************/
EXPORT_SYMBOL(ecdev_is_ec);
EXPORT_SYMBOL(ecdev_receive);
EXPORT_SYMBOL(ecdev_link_state);

View File

@ -25,14 +25,17 @@
/*****************************************************************************/
void ec_master_freerun(unsigned long);
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
/*****************************************************************************/
EC_SYSFS_READ_ATTR(slave_count);
EC_SYSFS_READ_ATTR(mode);
static struct attribute *ec_def_attrs[] = {
&attr_slave_count,
&attr_mode,
NULL,
};
@ -78,6 +81,11 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT-Master */
return -1;
}
// Init freerun timer
init_timer(&master->freerun_timer);
master->freerun_timer.function = ec_master_freerun;
master->freerun_timer.data = (unsigned long) master;
ec_command_init(&master->simple_command);
ec_command_init(&master->watch_command);
@ -100,6 +108,8 @@ void ec_master_clear(struct kobject *kobj /**< KObject des Masters */)
EC_INFO("Clearing master %i...\n", master->index);
del_timer_sync(&master->freerun_timer);
ec_master_reset(master);
if (master->device) {
@ -131,6 +141,8 @@ void ec_master_reset(ec_master_t *master
ec_domain_t *domain, *next_d;
ec_eoe_t *eoe, *next_eoe;
ec_master_freerun_stop(master);
// Alle Slaves entfernen
list_for_each_entry_safe(slave, next_s, &master->slaves, list) {
list_del(&slave->list);
@ -172,6 +184,8 @@ void ec_master_reset(ec_master_t *master
master->stats.unmatched = 0;
master->stats.eoe_errors = 0;
master->stats.t_last = 0;
master->mode = EC_MASTER_MODE_IDLE;
}
/*****************************************************************************/
@ -605,6 +619,61 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Starts Free-Run mode.
*/
void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
{
if (master->mode == EC_MASTER_MODE_FREERUN) return;
if (master->mode == EC_MASTER_MODE_RUNNING) {
EC_ERR("ec_master_freerun_start: Master already running!\n");
return;
}
EC_INFO("Starting Free-Run mode.\n");
master->mode = EC_MASTER_MODE_FREERUN;
master->freerun_timer.expires = jiffies + 10;
add_timer(&master->freerun_timer);
}
/*****************************************************************************/
/**
Stops Free-Run mode.
*/
void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
{
if (master->mode != EC_MASTER_MODE_FREERUN) return;
EC_INFO("Stopping Free-Run mode.\n");
del_timer_sync(&master->freerun_timer);
master->mode = EC_MASTER_MODE_IDLE;
}
/*****************************************************************************/
/**
Free-Run mode function.
*/
void ec_master_freerun(unsigned long data)
{
ec_master_t *master = (ec_master_t *) data;
// nop
master->freerun_timer.expires += HZ;
add_timer(&master->freerun_timer);
}
/*****************************************************************************/
/**
Wandelt eine ASCII-kodierte Bus-Adresse in einen Slave-Zeiger.
@ -795,6 +864,16 @@ ssize_t ec_show_master_attribute(struct kobject *kobj, /**< KObject */
if (attr == &attr_slave_count) {
return sprintf(buffer, "%i\n", master->slave_count);
}
else if (attr == &attr_mode) {
switch (master->mode) {
case EC_MASTER_MODE_IDLE:
return sprintf(buffer, "IDLE\n");
case EC_MASTER_MODE_FREERUN:
return sprintf(buffer, "FREERUN\n");
case EC_MASTER_MODE_RUNNING:
return sprintf(buffer, "RUNNING\n");
}
}
return 0;
}

View File

@ -13,12 +13,27 @@
#include <linux/list.h>
#include <linux/sysfs.h>
#include <linux/timer.h>
#include "device.h"
#include "domain.h"
/*****************************************************************************/
/**
EtherCAT master mode.
*/
typedef enum
{
EC_MASTER_MODE_IDLE,
EC_MASTER_MODE_FREERUN,
EC_MASTER_MODE_RUNNING
}
ec_master_mode_t;
/*****************************************************************************/
/**
EtherCAT-Rahmen-Statistiken.
*/
@ -63,6 +78,8 @@ struct ec_master
unsigned int timeout; /**< Timeout für synchronen Datenaustausch */
struct list_head eoe_slaves; /**< Ethernet over EtherCAT Slaves */
unsigned int reserved; /**< Master durch Echtzeitprozess reserviert */
struct timer_list freerun_timer; /**< Timer fuer Free-Run-Modus. */
ec_master_mode_t mode; /**< Modus des Masters */
};
/*****************************************************************************/
@ -72,6 +89,10 @@ int ec_master_init(ec_master_t *, unsigned int);
void ec_master_clear(struct kobject *);
void ec_master_reset(ec_master_t *);
// Free-Run
void ec_master_freerun_start(ec_master_t *);
void ec_master_freerun_stop(ec_master_t *);
// IO
void ec_master_receive(ec_master_t *, const uint8_t *, size_t);
void ec_master_queue_command(ec_master_t *, ec_command_t *);

View File

@ -181,7 +181,7 @@ ec_device_t *ecdev_register(unsigned int master_index,
if (!net_dev) {
EC_WARN("Device is NULL!\n");
return NULL;
goto out_return;
}
if (!(master = ec_find_master(master_index))) return NULL;
@ -189,23 +189,30 @@ ec_device_t *ecdev_register(unsigned int master_index,
// critical section start
if (master->device) {
EC_ERR("Master %i already has a device!\n", master_index);
return NULL;
// critical section leave
goto out_return;
}
if (!(master->device =
(ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate device!\n");
return NULL;
// critical section leave
goto out_return;
}
// critical section end
if (ec_device_init(master->device, master, net_dev, isr, module)) {
kfree(master->device);
master->device = NULL;
return NULL;
EC_ERR("Failed to init device!\n");
goto out_free;
}
return master->device;
out_free:
kfree(master->device);
master->device = NULL;
out_return:
return NULL;
}
/*****************************************************************************/
@ -222,11 +229,6 @@ void ecdev_unregister(unsigned int master_index,
{
ec_master_t *master;
if (master_index >= ec_master_count) {
EC_WARN("Master %i does not exist!\n", master_index);
return;
}
if (!(master = ec_find_master(master_index))) return;
if (!master->device || master->device != device) {
@ -239,6 +241,47 @@ void ecdev_unregister(unsigned int master_index,
master->device = NULL;
}
/*****************************************************************************/
/**
Starts the master.
*/
int ecdev_start(unsigned int master_index
/**< Index des EtherCAT-Masters */
)
{
ec_master_t *master;
if (!(master = ec_find_master(master_index))) return -1;
if (ec_device_open(master->device)) {
EC_ERR("Failed to open device!\n");
return -1;
}
ec_master_freerun_start(master);
return 0;
}
/*****************************************************************************/
/**
Stops the master.
*/
void ecdev_stop(unsigned int master_index
/**< Index des EtherCAT-Masters */
)
{
ec_master_t *master;
if (!(master = ec_find_master(master_index))) return;
ec_master_freerun_stop(master);
if (ec_device_close(master->device))
EC_WARN("Failed to close device!\n");
}
/******************************************************************************
*
* Echtzeitschnittstelle
@ -261,50 +304,46 @@ ec_master_t *ecrt_request_master(unsigned int master_index
EC_INFO("Requesting master %i...\n", master_index);
if (!(master = ec_find_master(master_index))) goto req_return;
if (!(master = ec_find_master(master_index))) goto out_return;
// begin critical section
if (master->reserved) {
EC_ERR("Master %i is already in use!\n", master_index);
goto req_return;
goto out_return;
}
master->reserved = 1;
// end critical section
if (!master->device) {
EC_ERR("Master %i has no assigned device!\n", master_index);
goto req_release;
goto out_release;
}
if (!try_module_get(master->device->module)) {
EC_ERR("Failed to reserve device module!\n");
goto req_release;
goto out_release;
}
if (ec_device_open(master->device)) {
EC_ERR("Failed to open device!\n");
goto req_module_put;
}
ec_master_freerun_stop(master);
ec_master_reset(master);
master->mode = EC_MASTER_MODE_RUNNING;
if (!master->device->link_state) EC_WARN("Link is DOWN.\n");
if (ec_master_bus_scan(master)) {
EC_ERR("Bus scan failed!\n");
goto req_close;
goto out_module_put;
}
EC_INFO("Master %i is ready.\n", master_index);
return master;
req_close:
if (ec_device_close(master->device))
EC_WARN("Warning - Failed to close device!\n");
req_module_put:
out_module_put:
module_put(master->device->module);
ec_master_reset(master);
req_release:
out_release:
master->reserved = 0;
req_return:
out_return:
EC_ERR("Failed requesting master %i.\n", master_index);
return NULL;
}
@ -326,8 +365,8 @@ void ecrt_release_master(ec_master_t *master /**< EtherCAT-Master */)
ec_master_reset(master);
if (ec_device_close(master->device))
EC_WARN("Warning - Failed to close device!\n");
master->mode = EC_MASTER_MODE_IDLE;
ec_master_freerun_start(master);
module_put(master->device->module);
master->reserved = 0;
@ -389,6 +428,8 @@ module_exit(ec_cleanup_module);
EXPORT_SYMBOL(ecdev_register);
EXPORT_SYMBOL(ecdev_unregister);
EXPORT_SYMBOL(ecdev_start);
EXPORT_SYMBOL(ecdev_stop);
EXPORT_SYMBOL(ecrt_request_master);
EXPORT_SYMBOL(ecrt_release_master);

View File

@ -179,7 +179,7 @@ int __init init_rt_module(void)
}
ecrt_master_print(master, 2);
#else
ecrt_master_print(master, 1);
ecrt_master_print(master, 0);
#endif
#if 1