diff --git a/devices/8139too.c b/devices/8139too.c index 55091701e96785f371ab03605d3fd8fa1f0874a5..6d53601b6c157171ba8d8fc7d3e4b7d0d8ab71c5 100644 --- a/devices/8139too.c +++ b/devices/8139too.c @@ -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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ diff --git a/devices/Makefile b/devices/Makefile index 38075b4e5d8a56c0501382cca25ea8b04a948bb2..ad72a82574724714c3e8d546e8f242d0c373e5af 100644 --- a/devices/Makefile +++ b/devices/Makefile @@ -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)" #------------------------------------------------------------------------------ diff --git a/devices/ecdev.h b/devices/ecdev.h index b5633f94a3b2be49faae332c1187f9953547bde6..6951400b7bb3feeeaf9f751146685f0d97d258d8 100644 --- a/devices/ecdev.h +++ b/devices/ecdev.h @@ -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); diff --git a/master/Makefile b/master/Makefile index f1516d203b57e7eb5905affe87f15c32ecffc0a2..682663b261a49914bb9386e4d04edc50f8a61917 100644 --- a/master/Makefile +++ b/master/Makefile @@ -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` diff --git a/master/device.c b/master/device.c index ff6fec8f3cb8a037cd0b01f377d5a128fd2d1e1e..a3f3bab693a4db20e4e1c3d3032fc293ba2e71e4 100644 --- a/master/device.c +++ b/master/device.c @@ -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); diff --git a/master/master.c b/master/master.c index 869c4a99df45c4598dd9b015b950c96ab90d537c..731d7a220210a92324702acadfcd6e1e09d4835f 100644 --- a/master/master.c +++ b/master/master.c @@ -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; } diff --git a/master/master.h b/master/master.h index ca5c4eb9e5fb58fbb9cda76c128480bdf6e9ffc1..f52dfc7b6f2191c7046925046ffcc80b2234914a 100644 --- a/master/master.h +++ b/master/master.h @@ -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 *); diff --git a/master/module.c b/master/module.c index ab1a3717a027979905fe3f4be4e52c036e18fc82..821639ac045e8508da525a5c06fed7521b93a988 100644 --- a/master/module.c +++ b/master/module.c @@ -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); diff --git a/rt/msr_rt.c b/rt/msr_rt.c index c2d901404fa8d8a724498e5b9a746d8c4efb51b3..5724bfc0525e60dbf5629b3b5ba776d8c6a7b885 100644 --- a/rt/msr_rt.c +++ b/rt/msr_rt.c @@ -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