MERGE trunk -r428:447 -> branches/stable-1.0 (Complete EEPROM data, unloading buxfix, variable data, bridging)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FEATURES Mon Jun 26 15:04:06 2006 +0000
@@ -0,0 +1,66 @@
+-------------------------------------------------------------------------------
+
+This is the FEATURES file of the IgH EtherCAT Master.
+
+$Id$
+
+-------------------------------------------------------------------------------
+
+General Features:
+
+* Runs as kernel module for Linux 2.6.
+
+* Comes with EtherCAT-capable network driver for RTL8139 and compatible
+ network interface cards.
+ - Interrupt-less network driver operation.
+ - Easy implementation of additional network drivers through common device
+ interface of the master.
+ - Runs even with PCMCIA cards.
+
+* Supports multiple EtherCAT masters on one machine.
+
+* Supports any realtime extension through independent architecture.
+ - RTAI, IPIPE, ADEOS, etc.
+ - Runs well even without realtime extensions.
+
+* Common kernel interface, for realtime modules using EtherCAT functionality.
+ - Synchronous and asynchronous sending and receiving of frames.
+ - Avoidance of unnecessary copy operations for process data.
+
+* Separating slave groups through domains.
+ - Handling of multiple slave groups with different sampling rates.
+ - Automatic calculation of process data mapping, FMMU- and sync manager
+ configuration within the domains.
+
+* Master finite state machine (FSM). Thus:
+ - Bus monitoring during realtime operation.
+ - Automatic reconfiguration of slaves on bus power failure during realtime
+ operation.
+ - Controlling of slave states during realtime operation.
+
+* Free-Run mode, if master is idle.
+ - Automatic scanning of slaves upon topology changes.
+ - Bus visualisation and EoE processing without realtime process connected.
+
+* Implements the CANopen-over-EtherCAT (CoE) protocol.
+ - Configuration of CoE-capable slaves via SDO interface.
+ - SDO dictionary listing.
+
+* Implements the Ethernet-over-EtherCAT (EoE) protocol.
+ - Creates virtual network devices that are automatically coupled to
+ EoE-capable slaves.
+ - Thus natively supports either a switched or a routed EoE network
+ architecture.
+
+* User space interface via the System Filesystem (SysFS).
+ - User space tool for bus visualisation.
+ - Slave EĀ²PROM image reading and writing.
+
+* Seamless integration in your favourite Linux distibution.
+ - Master and network device configuration via sysconfig files.
+ - UnitedLinux compatible init script for master control.
+
+* Virtual read-only network interface for debugging purposes and for
+ "sniffing" the EtherCAT traffic (through Ethereal, or others).
+
+-------------------------------------------------------------------------------
--- a/Makefile Mon May 29 09:54:18 2006 +0000
+++ b/Makefile Mon Jun 26 15:04:06 2006 +0000
@@ -1,6 +1,8 @@
#------------------------------------------------------------------------------
#
-# EtherCAT Makefile
+# Makefile
+#
+# IgH EtherCAT master
#
# $Id$
#
@@ -53,9 +55,17 @@
KERNEL_DIR := /lib/modules/$(KERNEL)/build
CURRENT_DIR := $(shell pwd)
+INSTALL_MOD_DIR := ethercat
modules:
- $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR)
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
+
+install: modules_install
+ @script/install.sh $(KERNEL)
+
+modules_install:
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) \
+ INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) modules_install
clean: cleandoc
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
@@ -66,9 +76,6 @@
cleandoc:
@rm -rf doc
-install:
- @script/install.sh $(KERNEL)
-
#------------------------------------------------------------------------------
endif
--- a/README Mon May 29 09:54:18 2006 +0000
+++ b/README Mon Jun 26 15:04:06 2006 +0000
@@ -18,7 +18,7 @@
This is an Open-Source EtherCAT master implementation for Linux 2.6.
-For more information, see
+See the FEATURES file for a list of features. For more information, see
http://etherlab.org
--- a/TODO Mon May 29 09:54:18 2006 +0000
+++ b/TODO Mon Jun 26 15:04:06 2006 +0000
@@ -1,21 +1,39 @@
+-------------------------------------------------------------------------------
EtherCAT master TODO
-====================
$Id$
-- Mailbox-Handler
-- Dispatching of received mailbox data?
-- File access over EtherCAT (FoE)
+-------------------------------------------------------------------------------
-- Number of frames the NIC can handle
-- Remove slave type information from master / read XML files from user space
+Important things to do:
-- eepro100 driver
-- VLAN tagging
+* New SDO-Configuration interface
-- Calculate bus topology
+* Remove slave type information from master / New RT Interface
-- Documentation
+* Always use state machines / remove simple IO code
-- User space tool for configuration and visualisation
+* SysFS interface
+ - Add secondary slave address
+ - Add SDO dictionary
+
+* Implement all EtherCAT commands
+
+* Determine number of frames the NIC can handle
+
+* Implement eepro100 driver
+
+-------------------------------------------------------------------------------
+
+Not-so-important things to do:
+
+* User space tool for configuration
+
+* Calculate bus topology
+
+* File access over EtherCAT (FoE)
+
+* Allow VLAN tagging
+
+-------------------------------------------------------------------------------
--- a/devices/8139too.c Mon May 29 09:54:18 2006 +0000
+++ b/devices/8139too.c Mon Jun 26 15:04:06 2006 +0000
@@ -133,6 +133,7 @@
#define DRV_NAME "ec_8139too"
#define DRV_VERSION "0.9.27"
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -342,6 +343,7 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* prevent driver from being loaded automatically */
//MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -669,10 +671,8 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-MODULE_AUTHOR("Wilhelm Hagemeister <hm@igh-essen.com>,"
- " Florian Pose <fp@igh-essen.com>");
-MODULE_DESCRIPTION("RealTek RTL-8139 Fast Ethernet"
- " driver with EtherCAT functionality");
+MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
+MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(COMPILE_INFO);
@@ -1050,8 +1050,8 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (board_idx == ec_device_index) {
- rtl_ec_net_dev = dev;
- strcpy(dev->name, "ec0");
+ rtl_ec_net_dev = dev;
+ strcpy(dev->name, "ec0");
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1098,7 +1098,6 @@
(debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1));
spin_lock_init (&tp->lock);
spin_lock_init (&tp->rx_lock);
-
init_waitqueue_head (&tp->thr_wait);
init_completion (&tp->thr_exited);
tp->mii.dev = dev;
@@ -1111,11 +1110,10 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
- if (dev != rtl_ec_net_dev) {
- DPRINTK("About to register device named %s (%p)...\n",
- dev->name, dev);
- i = register_netdev (dev);
- if (i) goto err_out;
+ if (dev != rtl_ec_net_dev) {
+ DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
+ i = register_netdev (dev);
+ if (i) goto err_out;
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1207,10 +1205,10 @@
assert (dev != NULL);
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev != rtl_ec_net_dev) {
- unregister_netdev (dev);
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ unregister_netdev (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1417,16 +1415,12 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-#ifdef EC_DEBUG
- printk(KERN_DEBUG "%s: open\n", dev->name);
-#endif
-
- if (dev != rtl_ec_net_dev) {
- retval = request_irq(dev->irq, rtl8139_interrupt,
- SA_SHIRQ, dev->name, dev);
- if (retval)
- return retval;
- }
+ if (dev != rtl_ec_net_dev) {
+ retval = request_irq(dev->irq, rtl8139_interrupt,
+ SA_SHIRQ, dev->name, dev);
+ if (retval)
+ return retval;
+ }
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1434,24 +1428,24 @@
&tp->tx_bufs_dma);
tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
&tp->rx_ring_dma);
- if (tp->tx_bufs == NULL || tp->rx_ring == NULL)
- {
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev != rtl_ec_net_dev) {
- free_irq(dev->irq, dev);
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-
- if (tp->tx_bufs)
- pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
- tp->tx_bufs, tp->tx_bufs_dma);
- if (tp->rx_ring)
- pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
- tp->rx_ring, tp->rx_ring_dma);
-
- return -ENOMEM;
+ if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ free_irq(dev->irq, dev);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+ if (tp->tx_bufs)
+ pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
+ tp->tx_bufs, tp->tx_bufs_dma);
+ if (tp->rx_ring)
+ pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
+ tp->rx_ring, tp->rx_ring_dma);
+
+ return -ENOMEM;
+
}
tp->mii.full_duplex = tp->mii.force_media;
@@ -1460,40 +1454,45 @@
rtl8139_init_ring (dev);
rtl8139_hw_start (dev);
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev != rtl_ec_net_dev) {
- netif_start_queue (dev);
-
- if (netif_msg_ifup(tp)) {
- printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d"
- " GP Pins %2.2x %s-duplex.\n",
- dev->name, pci_resource_start (tp->pci_dev, 1),
- dev->irq, RTL_R8 (MediaStatus),
- tp->mii.full_duplex ? "full" : "half");
- }
-
- rtl8139_start_thread(dev);
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ netif_start_queue (dev);
+
+ if (netif_msg_ifup(tp))
+ printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d"
+ " GP Pins %2.2x %s-duplex.\n",
+ dev->name, pci_resource_start (tp->pci_dev, 1),
+ dev->irq, RTL_R8 (MediaStatus),
+ tp->mii.full_duplex ? "full" : "half");
+
+ rtl8139_start_thread(dev);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+ return 0;
+}
+
+
+static void rtl_check_media (struct net_device *dev, unsigned int init_media)
+{
+ struct rtl8139_private *tp = netdev_priv(dev);
+
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ if (tp->phys[0] >= 0) {
+ mii_check_media(&tp->mii, netif_msg_link(tp), init_media);
}
+ } else {
+ void __iomem *ioaddr = tp->mmio_addr;
+ uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS;
+ ecdev_link_state(rtl_ec_dev, state ? 1 : 0);
+ }
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
- return 0;
-}
-
-
-static void rtl_check_media (struct net_device *dev, unsigned int init_media)
-{
- struct rtl8139_private *tp = netdev_priv(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);
- }
- else if (tp->phys[0] >= 0) {
- mii_check_media(&tp->mii, netif_msg_link(tp), init_media);
- }
}
/* Start the hardware at open or resume. */
@@ -1560,9 +1559,9 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
- if (dev != rtl_ec_net_dev) {
- /* Enable all known interrupts by setting the interrupt mask. */
- RTL_W16 (IntrMask, rtl8139_intr_mask);
+ if (dev != rtl_ec_net_dev) {
+ /* Enable all known interrupts by setting the interrupt mask. */
+ RTL_W16 (IntrMask, rtl8139_intr_mask);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1818,7 +1817,6 @@
" (queue head)" : "");
tp->xstats.tx_timeouts++;
- printk(KERN_DEBUG "%s: tx_timeout\n", dev->name);
/* disable Tx ASAP, if not already */
tmp8 = RTL_R8 (ChipCmd);
@@ -1827,35 +1825,31 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev != rtl_ec_net_dev) {
- spin_lock(&tp->rx_lock);
-
- /* Disable interrupts by clearing the interrupt mask. */
- RTL_W16 (IntrMask, 0x0000);
-
- /* Stop a shared interrupt from scavenging while we are. */
- spin_lock_irqsave (&tp->lock, flags);
- rtl8139_tx_clear (tp);
- spin_unlock_irqrestore (&tp->lock, flags);
-
- /* ...and finally, reset everything */
-
- if (netif_running(dev)) {
- rtl8139_hw_start (dev);
- netif_wake_queue (dev);
- }
-
- spin_unlock(&tp->rx_lock);
+ if (dev != rtl_ec_net_dev) {
+ spin_lock(&tp->rx_lock);
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16 (IntrMask, 0x0000);
+
+ /* Stop a shared interrupt from scavenging while we are. */
+ spin_lock_irqsave (&tp->lock, flags);
+ rtl8139_tx_clear (tp);
+ spin_unlock_irqrestore (&tp->lock, flags);
+
+ /* ...and finally, reset everything */
+ if (netif_running(dev)) {
+ rtl8139_hw_start (dev);
+ netif_wake_queue (dev);
}
- else {
- rtl8139_tx_clear (tp);
- rtl8139_hw_start(dev);
- }
+ spin_unlock(&tp->rx_lock);
+ } else {
+ rtl8139_tx_clear (tp);
+ rtl8139_hw_start(dev);
+ }
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}
+
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
@@ -1866,27 +1860,27 @@
/* Calculate the next Tx descriptor entry. */
entry = tp->cur_tx % NUM_TX_DESC;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- /* Note: the chip doesn't have auto-pad! */
- if (likely(len < TX_BUF_SIZE))
- {
- if (len < ETH_ZLEN)
- memset(tp->tx_buf[entry], 0, ETH_ZLEN);
-
- skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
- if (dev != rtl_ec_net_dev) dev_kfree_skb(skb);
- }
- else
- {
- if (dev != rtl_ec_net_dev) dev_kfree_skb(skb);
- tp->stats.tx_dropped++;
- return 0;
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ /* Note: the chip doesn't have auto-pad! */
+ if (likely(len < TX_BUF_SIZE)) {
+ if (len < ETH_ZLEN)
+ memset(tp->tx_buf[entry], 0, ETH_ZLEN);
+ skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
+ if (dev != rtl_ec_net_dev) {
+ dev_kfree_skb(skb);
+ }
+ } else {
+ if (dev != rtl_ec_net_dev) {
+ dev_kfree_skb(skb);
+ }
+ tp->stats.tx_dropped++;
+ return 0;
}
if (dev != rtl_ec_net_dev) {
- spin_lock_irq(&tp->lock);
- }
+ spin_lock_irq(&tp->lock);
+ }
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1901,15 +1895,14 @@
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
- if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
- netif_stop_queue (dev);
-
- spin_unlock_irq(&tp->lock);
-
- if (netif_msg_tx_queued(tp))
- printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n",
- dev->name, len, entry);
- }
+ if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
+ netif_stop_queue (dev);
+ spin_unlock_irq(&tp->lock);
+
+ if (netif_msg_tx_queued(tp))
+ printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n",
+ dev->name, len, entry);
+ }
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1928,7 +1921,6 @@
dirty_tx = tp->dirty_tx;
tx_left = tp->cur_tx - dirty_tx;
-
while (tx_left > 0) {
int entry = dirty_tx % NUM_TX_DESC;
int txstatus;
@@ -1971,7 +1963,7 @@
tx_left--;
}
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
#ifndef RTL8139_NDEBUG
if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) {
@@ -1981,20 +1973,20 @@
}
#endif /* RTL8139_NDEBUG */
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/* only wake the queue if we did work, and the queue is stopped */
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
mb();
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
- netif_wake_queue (dev);
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ netif_wake_queue (dev);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}
}
@@ -2128,9 +2120,15 @@
RTL_R16 (RxBufAddr),
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
+
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
while ((dev == rtl_ec_net_dev || netif_running(dev))
&& received < budget
&& (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
u32 ring_offset = cur_rx % RX_BUF_LEN;
u32 rx_status;
unsigned int pkt_size;
@@ -2143,14 +2141,16 @@
rx_size = rx_status >> 16;
pkt_size = rx_size - 4;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- 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);
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ if (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);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
#if RTL8139_DEBUG > 2
{
@@ -2199,48 +2199,46 @@
goto out;
}
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev != rtl_ec_net_dev) {
- /* Malloc up new buffer, compatible with net-2e. */
- /* Omit the four octet CRC from the length. */
- skb = dev_alloc_skb(pkt_size + 2);
-
- if (likely(skb)) {
- skb->dev = dev;
- skb_reserve (skb, 2); /* 16 byte align the IP fields. */
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ /* Malloc up new buffer, compatible with net-2e. */
+ /* Omit the four octet CRC from the length. */
+
+ skb = dev_alloc_skb (pkt_size + 2);
+ if (likely(skb)) {
+ skb->dev = dev;
+ skb_reserve (skb, 2); /* 16 byte align the IP fields. */
#if RX_BUF_IDX == 3
- wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
+ wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
#else
- eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+ eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
#endif
- skb_put (skb, pkt_size);
-
- skb->protocol = eth_type_trans (skb, dev);
-
- dev->last_rx = jiffies;
- tp->stats.rx_bytes += pkt_size;
- tp->stats.rx_packets++;
-
- netif_receive_skb (skb);
- } else {
- if (net_ratelimit())
- printk (KERN_WARNING
- "%s: Memory squeeze, dropping packet.\n",
- dev->name);
- tp->stats.rx_dropped++;
- }
- }
- else
- {
- ecdev_receive(rtl_ec_dev,
- &rx_ring[ring_offset + 4], pkt_size);
- dev->last_rx = jiffies;
- tp->stats.rx_bytes += pkt_size;
- tp->stats.rx_packets++;
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ skb_put (skb, pkt_size);
+
+ skb->protocol = eth_type_trans (skb, dev);
+
+ dev->last_rx = jiffies;
+ tp->stats.rx_bytes += pkt_size;
+ tp->stats.rx_packets++;
+
+ netif_receive_skb (skb);
+ } else {
+ if (net_ratelimit())
+ printk (KERN_WARNING
+ "%s: Memory squeeze, dropping packet.\n",
+ dev->name);
+ tp->stats.rx_dropped++;
+ }
+ } else {
+ ecdev_receive(rtl_ec_dev,
+ &rx_ring[ring_offset + 4], pkt_size);
+ dev->last_rx = jiffies;
+ tp->stats.rx_bytes += pkt_size;
+ tp->stats.rx_packets++;
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
received++;
@@ -2337,11 +2335,10 @@
* Order is important since data can get interrupted
* again when we think we are done.
*/
-
- local_irq_disable();
- RTL_W16_F(IntrMask, rtl8139_intr_mask);
- __netif_rx_complete(dev);
- local_irq_enable();
+ local_irq_disable();
+ RTL_W16_F(IntrMask, rtl8139_intr_mask);
+ __netif_rx_complete(dev);
+ local_irq_enable();
}
spin_unlock(&tp->rx_lock);
@@ -2360,21 +2357,20 @@
int link_changed = 0; /* avoid bogus "uninit" warning */
int handled = 0;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev == rtl_ec_net_dev) {
- status = RTL_R16 (IntrStatus);
- }
- else {
- spin_lock(&tp->lock);
-
- status = RTL_R16 (IntrStatus);
-
- if (unlikely((status & rtl8139_intr_mask) == 0))
- goto out;
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ spin_lock (&tp->lock);
+ status = RTL_R16 (IntrStatus);
+
+ /* shared irq? */
+ if (unlikely((status & rtl8139_intr_mask) == 0))
+ goto out;
+ } else {
+ status = RTL_R16 (IntrStatus);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
handled = 1;
@@ -2382,17 +2378,17 @@
if (unlikely(status == 0xFFFF))
goto out;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
- /* close possible race's with dev_close */
- if (unlikely(!netif_running(dev))) {
- RTL_W16 (IntrMask, 0);
- goto out;
- }
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* close possible race's with dev_close */
+ if (unlikely(!netif_running(dev))) {
+ RTL_W16 (IntrMask, 0);
+ goto out;
+ }
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/* Acknowledge all of the current interrupt sources ASAP, but
an first get an additional status bit from CSCR. */
@@ -2400,31 +2396,28 @@
link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
ackstat = status & ~(RxAckBits | TxErr);
- if (ackstat) {
+ if (ackstat)
RTL_W16 (IntrStatus, ackstat);
- }
/* Receive packets are processed by poll routine.
If not running start it now. */
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (status & RxAckBits)
- {
- if (dev != rtl_ec_net_dev) {
- /* Mark for polling */
- if (netif_rx_schedule_prep(dev)) {
- RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
- __netif_rx_schedule (dev);
- }
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (status & RxAckBits){
+ if (dev != rtl_ec_net_dev) {
+ /* Mark for polling */
+ if (netif_rx_schedule_prep(dev)) {
+ RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
+ __netif_rx_schedule (dev);
}
- else {
- /* EtherCAT device: Just receive all frames */
- rtl8139_rx(dev, tp, 100); // FIXME
- }
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ } else {
+ /* EtherCAT device: Just receive all frames */
+ rtl8139_rx(dev, tp, 100); // FIXME
+ }
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/* Check uncommon events with one test. */
if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr)))
@@ -2437,13 +2430,14 @@
RTL_W16 (IntrStatus, TxErr);
}
out:
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
- spin_unlock (&tp->lock);
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ spin_unlock (&tp->lock);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
dev->name, RTL_R16 (IntrStatus));
@@ -2470,55 +2464,55 @@
int ret = 0;
unsigned long flags;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev != rtl_ec_net_dev) {
- netif_stop_queue(dev);
- if (tp->thr_pid >= 0) {
- tp->time_to_die = 1;
- wmb();
- ret = kill_proc (tp->thr_pid, SIGTERM, 1);
- if (ret) {
- printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
- return ret;
- }
- wait_for_completion (&tp->thr_exited);
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev != rtl_ec_net_dev) {
+ netif_stop_queue (dev);
+
+ if (tp->thr_pid >= 0) {
+ tp->time_to_die = 1;
+ wmb();
+ ret = kill_proc (tp->thr_pid, SIGTERM, 1);
+ if (ret) {
+ printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
+ return ret;
}
-
- if (netif_msg_ifdown(tp))
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
- dev->name, RTL_R16 (IntrStatus));
-
- spin_lock_irqsave (&tp->lock, flags);
-
- /* Stop the chip's Tx and Rx DMA processes. */
- RTL_W8 (ChipCmd, 0);
-
- /* Disable interrupts by clearing the interrupt mask. */
- RTL_W16 (IntrMask, 0);
-
- /* Update the error counts. */
- tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
- RTL_W32 (RxMissed, 0);
-
- spin_unlock_irqrestore (&tp->lock, flags);
-
- synchronize_irq (dev->irq); /* racy, but that's ok here */
- free_irq (dev->irq, dev);
+ wait_for_completion (&tp->thr_exited);
}
- else {
- /* Stop the chip's Tx and Rx DMA processes. */
- RTL_W8 (ChipCmd, 0);
-
- /* Disable interrupts by clearing the interrupt mask. */
- RTL_W16 (IntrMask, 0);
-
- /* Update the error counts. */
- tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
- RTL_W32 (RxMissed, 0);
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+
+ if (netif_msg_ifdown(tp))
+ printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
+ dev->name, RTL_R16 (IntrStatus));
+
+ spin_lock_irqsave (&tp->lock, flags);
+
+ /* Stop the chip's Tx and Rx DMA processes. */
+ RTL_W8 (ChipCmd, 0);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16 (IntrMask, 0);
+
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+
+ spin_unlock_irqrestore (&tp->lock, flags);
+
+ synchronize_irq (dev->irq); /* racy, but that's ok here */
+ free_irq (dev->irq, dev);
+ } else {
+ /* Stop the chip's Tx and Rx DMA processes. */
+ RTL_W8 (ChipCmd, 0);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16 (IntrMask, 0);
+
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
rtl8139_tx_clear (tp);
@@ -2733,12 +2727,12 @@
struct rtl8139_private *np = netdev_priv(dev);
int rc;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
- if (dev == rtl_ec_net_dev || !netif_running(dev))
- return -EINVAL;
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+ if (dev == rtl_ec_net_dev || !netif_running(dev))
+ return -EINVAL;
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
spin_lock_irq(&np->lock);
rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL);
@@ -2754,16 +2748,16 @@
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || netif_running(dev)) {
- spin_lock_irqsave (&tp->lock, flags);
- tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
- RTL_W32 (RxMissed, 0);
- spin_unlock_irqrestore (&tp->lock, flags);
- }
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ spin_lock_irqsave (&tp->lock, flags);
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+ spin_unlock_irqrestore (&tp->lock, flags);
+ }
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return &tp->stats;
}
@@ -2840,12 +2834,12 @@
pci_save_state (pdev);
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || !netif_running (dev))
- return 0;
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ return 0;
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
netif_device_detach (dev);
@@ -2873,12 +2867,12 @@
pci_restore_state (pdev);
- /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+ /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || !netif_running (dev))
- return 0;
-
- /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+ return 0;
+
+ /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
pci_set_power_state (pdev, PCI_D0);
rtl8139_init_ring (dev);
@@ -2928,9 +2922,8 @@
printk(KERN_ERR "Failed to start EtherCAT device!\n");
goto out_unregister;
}
- }
- else {
- printk(KERN_WARNING "NO EtherCAT device registered!\n");
+ } else {
+ printk(KERN_WARNING "No EtherCAT device registered!\n");
}
return 0;
--- a/devices/Makefile Mon May 29 09:54:18 2006 +0000
+++ b/devices/Makefile Mon Jun 26 15:04:06 2006 +0000
@@ -1,6 +1,6 @@
#------------------------------------------------------------------------------
#
-# kbuild Makefile
+# Makefile
#
# IgH EtherCAT master device modules
#
@@ -35,39 +35,45 @@
#
#------------------------------------------------------------------------------
-ifneq ($(KERNELRELEASE),)
-
#------------------------------------------------------------------------------
# kbuild section
+ifneq ($(KERNELRELEASE),)
+
obj-m := ec_8139too.o
ec_8139too-objs := 8139too.o
-REV := $(shell svnversion $(src) 2>/dev/null)
+REV := $(shell svnversion $(src) 2>/dev/null || echo "unknown")
EXTRA_CFLAGS = -DEC_REV=$(REV) -DEC_USER=$(USER)
#------------------------------------------------------------------------------
+# default section
else
-#------------------------------------------------------------------------------
-# default section
-
ifneq ($(wildcard ../ethercat.conf),)
include ../ethercat.conf
else
KERNEL := $(shell uname -r)
endif
-KERNELDIR := /lib/modules/$(KERNEL)/build
+KERNEL_DIR := /lib/modules/$(KERNEL)/build
+CURRENT_DIR := $(shell pwd)
+INSTALL_MOD_DIR := ethercat/devices
modules:
- $(MAKE) -C $(KERNELDIR) M=`pwd`
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
+
+install: modules_install
+
+modules_install:
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) \
+ INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) modules_install
clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
#------------------------------------------------------------------------------
--- a/ethercat.conf.tmpl Mon May 29 09:54:18 2006 +0000
+++ b/ethercat.conf.tmpl Mon Jun 26 15:04:06 2006 +0000
@@ -12,6 +12,6 @@
#
# The kernel to compile the EtherCAT sources against
#
-KERNEL := `uname -r`
+KERNEL := $(shell uname -r)
#------------------------------------------------------------------------------
--- a/examples/mini/Makefile Mon May 29 09:54:18 2006 +0000
+++ b/examples/mini/Makefile Mon Jun 26 15:04:06 2006 +0000
@@ -56,14 +56,16 @@
ifneq ($(wildcard kernel.conf),)
include kernel.conf
else
-KERNELDIR = /lib/modules/`uname -r`/build
+KERNEL_DIR := /lib/modules/$(shell uname -r)/build
endif
+CURRENT_DIR := $(shell pwd)
+
modules:
- $(MAKE) -C $(KERNELDIR) M=`pwd`
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR)
clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
#----------------------------------------------------------------
--- a/examples/mini/kernel.conf.tmpl Mon May 29 09:54:18 2006 +0000
+++ b/examples/mini/kernel.conf.tmpl Mon Jun 26 15:04:06 2006 +0000
@@ -9,4 +9,4 @@
#
#------------------------------------------------------------------------------
-KERNELDIR = /lib/modules/`uname -r`/build
+KERNELDIR := /lib/modules/$(shell uname -r)/build
--- a/examples/mini/mini.c Mon May 29 09:54:18 2006 +0000
+++ b/examples/mini/mini.c Mon Jun 26 15:04:06 2006 +0000
@@ -57,14 +57,15 @@
// data fields
//void *r_ssi_input, *r_ssi_status, *r_4102[3];
+void *r_kbus_in, *r_kbus_out;
// channels
uint32_t k_pos;
uint8_t k_stat;
ec_field_init_t domain1_fields[] = {
- {NULL, "3", "Beckhoff", "EL5001", "InputValue", 0},
- {NULL, "2", "Beckhoff", "EL4132", "OutputValue", 0},
+ //{&r_kbus_out, "0", "Beckhoff", "BK1120", "Outputs", 0},
+ //{&r_kbus_in, "0", "Beckhoff", "BK1120", "Inputs", 0},
{}
};
@@ -73,6 +74,7 @@
void run(unsigned long data)
{
static unsigned int counter = 0;
+ unsigned int i;
spin_lock(&master_lock);
@@ -105,8 +107,9 @@
}
else {
counter = FREQUENCY;
- //printk(KERN_INFO "k_pos = %i\n", k_pos);
- //printk(KERN_INFO "k_stat = 0x%02X\n", k_stat);
+ printk(KERN_INFO "input = ");
+ for (i = 0; i < 22; i++) printk("%02X ", *((uint8_t *) r_kbus_in + i));
+ printk("\n");
}
// restart timer
@@ -133,6 +136,8 @@
int __init init_mini_module(void)
{
+ ec_slave_t *slave;
+
printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n");
if ((master = ecrt_request_master(0)) == NULL) {
@@ -155,13 +160,23 @@
goto out_release_master;
}
+#if 1
+ printk(KERN_INFO "Setting variable data field sizes...\n");
+ if (!(slave = ecrt_master_get_slave(master, "0"))) {
+ printk(KERN_ERR "Failed to get slave!\n");
+ goto out_deactivate;
+ }
+ ecrt_slave_field_size(slave, "Outputs", 0, 0x16);
+ ecrt_slave_field_size(slave, "Inputs", 0, 0x16);
+#endif
+
printk(KERN_INFO "Activating master...\n");
if (ecrt_master_activate(master)) {
printk(KERN_ERR "Failed to activate master!\n");
goto out_release_master;
}
-#if 0
+#if 1
if (ecrt_master_fetch_sdo_lists(master)) {
printk(KERN_ERR "Failed to fetch SDO lists!\n");
goto out_deactivate;
@@ -191,14 +206,6 @@
}
#endif
-#if 0
- printk(KERN_INFO "Writing alias...\n");
- if (ecrt_slave_sdo_write_exp16(slave, 0xBEEF)) {
- printk(KERN_ERR "Failed to write alias!\n");
- goto out_deactivate;
- }
-#endif
-
#ifdef ASYNC
// send once and wait...
ecrt_master_prepare_async_io(master);
--- a/examples/msr/Makefile Mon May 29 09:54:18 2006 +0000
+++ b/examples/msr/Makefile Mon Jun 26 15:04:06 2006 +0000
@@ -75,13 +75,14 @@
KERNEL := $(shell uname -r)
endif
-KERNELDIR := /lib/modules/$(KERNEL)/build
+KERNEL_DIR := /lib/modules/$(KERNEL)/build
+CURRENT_DIR := $(shell pwd)
modules:
- $(MAKE) -C $(KERNELDIR) M=`pwd`
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR)
clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
install:
@./install.sh $(MODULE) $(KERNEL)
--- a/examples/msr/kernel.conf.tmpl Mon May 29 09:54:18 2006 +0000
+++ b/examples/msr/kernel.conf.tmpl Mon Jun 26 15:04:06 2006 +0000
@@ -10,6 +10,6 @@
#------------------------------------------------------------------------------
# Kernel sources for module compilation
-KERNEL := `uname -r`
+KERNEL := $(shell uname -r)
#------------------------------------------------------------------------------
--- a/examples/rtai/Makefile Mon May 29 09:54:18 2006 +0000
+++ b/examples/rtai/Makefile Mon Jun 26 15:04:06 2006 +0000
@@ -58,14 +58,16 @@
ifneq ($(wildcard kernel.conf),)
include kernel.conf
else
-KERNELDIR = /lib/modules/`uname -r`/build
+KERNEL_DIR := /lib/modules/$(shell uname -r)/build
endif
+CURRENT_DIR := $(shell pwd)
+
modules:
- $(MAKE) -C $(KERNELDIR) M=`pwd`
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR)
clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
#------------------------------------------------------------------------------
--- a/examples/rtai/kernel.conf.tmpl Mon May 29 09:54:18 2006 +0000
+++ b/examples/rtai/kernel.conf.tmpl Mon Jun 26 15:04:06 2006 +0000
@@ -9,4 +9,4 @@
#
#------------------------------------------------------------------------------
-KERNELDIR = /lib/modules/`uname -r`/build
+KERNELDIR := /lib/modules/$(shell uname -r)/build
--- a/include/ecrt.h Mon May 29 09:54:18 2006 +0000
+++ b/include/ecrt.h Mon Jun 26 15:04:06 2006 +0000
@@ -145,6 +145,8 @@
* Slave Methods
*****************************************************************************/
+/* there SDO functions are deprecated! */
+
int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint8_t *value);
int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, uint16_t sdo_index,
@@ -160,7 +162,10 @@
int ecrt_slave_sdo_read(ec_slave_t *slave, uint16_t sdo_index,
uint8_t sdo_subindex, uint8_t *data, size_t *size);
-int ecrt_slave_write_alias(ec_slave_t *slave, uint16_t alias);
+int ecrt_slave_write_alias(ec_slave_t *slave, uint16_t alias); // deprecated!
+
+int ecrt_slave_field_size(ec_slave_t *slave, const char *field_name,
+ unsigned int field_index, size_t size);
/******************************************************************************
* Bitwise read/write macros
--- a/master/Makefile Mon May 29 09:54:18 2006 +0000
+++ b/master/Makefile Mon Jun 26 15:04:06 2006 +0000
@@ -35,40 +35,46 @@
#
#------------------------------------------------------------------------------
-ifneq ($(KERNELRELEASE),)
-
#------------------------------------------------------------------------------
# kbuild section
+ifneq ($(KERNELRELEASE),)
+
obj-m := ec_master.o
ec_master-objs := module.o master.o device.o slave.o command.o types.o \
domain.o mailbox.o canopen.o ethernet.o debug.o fsm.o
-REV := $(shell svnversion $(src) 2>/dev/null)
+REV := $(shell svnversion $(src) 2>/dev/null || echo "unknown")
EXTRA_CFLAGS := -DSVNREV=$(REV) -DUSER=$(USER)
#------------------------------------------------------------------------------
+# default section
else
-#------------------------------------------------------------------------------
-# default section
-
ifneq ($(wildcard ../ethercat.conf),)
include ../ethercat.conf
else
KERNEL := $(shell uname -r)
endif
-KERNELDIR := /lib/modules/$(KERNEL)/build
+KERNEL_DIR := /lib/modules/$(KERNEL)/build
+CURRENT_DIR := $(shell pwd)
+INSTALL_MOD_DIR := ethercat/master
modules:
- $(MAKE) -C $(KERNELDIR) M=`pwd`
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
+
+install: modules_install
+
+modules_install:
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) \
+ INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) modules_install
clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+ $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
#------------------------------------------------------------------------------
--- a/master/canopen.c Mon May 29 09:54:18 2006 +0000
+++ b/master/canopen.c Mon Jun 26 15:04:06 2006 +0000
@@ -48,8 +48,9 @@
/*****************************************************************************/
void ec_canopen_abort_msg(uint32_t);
-int ec_slave_fetch_sdo_descriptions(ec_slave_t *);
-int ec_slave_fetch_sdo_entries(ec_slave_t *, ec_sdo_t *, uint8_t);
+int ec_slave_fetch_sdo_descriptions(ec_slave_t *, ec_command_t *);
+int ec_slave_fetch_sdo_entries(ec_slave_t *, ec_command_t *,
+ ec_sdo_t *, uint8_t);
/*****************************************************************************/
@@ -68,10 +69,14 @@
uint8_t *target /**< 4-byte memory */
)
{
+ ec_command_t command;
size_t rec_size;
uint8_t *data;
- if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 6))) return -1;
+ ec_command_init(&command);
+
+ if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 6)))
+ goto err;
EC_WRITE_U16(data, 0x2 << 12); // SDO request
EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer
@@ -79,14 +84,15 @@
EC_WRITE_U16(data + 3, sdo_index);
EC_WRITE_U8 (data + 5, sdo_subindex);
- if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
+ if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size)))
+ goto err;
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
sdo_index, sdo_subindex, slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
- return -1;
+ goto err;
}
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
@@ -97,11 +103,16 @@
EC_ERR("Invalid SDO upload response at slave %i!\n",
slave->ring_position);
ec_print_data(data, rec_size);
- return -1;
+ goto err;
}
memcpy(target, data + 6, 4);
- return 0;
+
+ ec_command_clear(&command);
+ return 0;
+ err:
+ ec_command_clear(&command);
+ return -1;
}
/*****************************************************************************/
@@ -120,13 +131,17 @@
{
uint8_t *data;
size_t rec_size;
+ ec_command_t command;
+
+ ec_command_init(&command);
if (size == 0 || size > 4) {
EC_ERR("Invalid data size!\n");
- return -1;
- }
-
- if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 0x0A))) return -1;
+ goto err;
+ }
+
+ if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 0x0A)))
+ goto err;
EC_WRITE_U16(data, 0x2 << 12); // SDO request
EC_WRITE_U8 (data + 2, (0x1 // size specified
@@ -138,7 +153,8 @@
memcpy(data + 6, sdo_data, size);
if (size < 4) memset(data + 6 + size, 0x00, 4 - size);
- if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
+ if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size)))
+ goto err;
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
@@ -160,7 +176,11 @@
return -1;
}
- return 0;
+ ec_command_clear(&command);
+ return 0;
+ err:
+ ec_command_clear(&command);
+ return -1;
}
/*****************************************************************************/
@@ -182,22 +202,27 @@
uint8_t *data;
size_t rec_size, data_size;
uint32_t complete_size;
-
- if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 6))) return -1;
+ ec_command_t command;
+
+ ec_command_init(&command);
+
+ if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 6)))
+ goto err;
EC_WRITE_U16(data, 0x2 << 12); // SDO request
EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
EC_WRITE_U16(data + 3, sdo_index);
EC_WRITE_U8 (data + 5, sdo_subindex);
- if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
+ if (!(data = ec_slave_mbox_simple_io(slave, &command, &rec_size)))
+ goto err;
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
sdo_index, sdo_subindex, slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
- return -1;
+ goto err;
}
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
@@ -208,30 +233,35 @@
EC_ERR("Invalid SDO upload response at slave %i!\n",
slave->ring_position);
ec_print_data(data, rec_size);
- return -1;
+ goto err;
}
if (rec_size < 10) {
EC_ERR("Received currupted SDO upload response!\n");
ec_print_data(data, rec_size);
- return -1;
+ goto err;
}
if ((complete_size = EC_READ_U32(data + 6)) > *size) {
EC_ERR("SDO data does not fit into buffer (%i / %i)!\n",
complete_size, *size);
- return -1;
+ goto err;
}
data_size = rec_size - 10;
if (data_size != complete_size) {
EC_ERR("SDO data incomplete - Fragmenting not implemented.\n");
- return -1;
+ goto err;
}
memcpy(target, data + 10, data_size);
- return 0;
+
+ ec_command_clear(&command);
+ return 0;
+ err:
+ ec_command_clear(&command);
+ return -1;
}
/*****************************************************************************/
@@ -248,8 +278,12 @@
unsigned int i, sdo_count;
ec_sdo_t *sdo;
uint16_t sdo_index;
-
- if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 8))) return -1;
+ ec_command_t command;
+
+ ec_command_init(&command);
+
+ if (!(data = ec_slave_mbox_prepare_send(slave, &command, 0x03, 8)))
+ goto err;
EC_WRITE_U16(data, 0x8 << 12); // SDO information
EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request
@@ -257,21 +291,22 @@
EC_WRITE_U16(data + 4, 0x0000);
EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs!
- if (unlikely(ec_master_simple_io(slave->master, &slave->mbox_command))) {
+ if (unlikely(ec_master_simple_io(slave->master, &command))) {
EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position);
- return -1;
+ goto err;
}
do {
- if (!(data = ec_slave_mbox_simple_receive(slave, 0x03, &rec_size)))
- return -1;
+ if (!(data = ec_slave_mbox_simple_receive(slave, &command,
+ 0x03, &rec_size)))
+ goto err;
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("SDO information error response at slave %i!\n",
slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
- return -1;
+ goto err;
}
if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
@@ -279,13 +314,13 @@
EC_ERR("Invalid SDO list response at slave %i!\n",
slave->ring_position);
ec_print_data(data, rec_size);
- return -1;
+ goto err;
}
if (rec_size < 8) {
EC_ERR("Invalid data size!\n");
ec_print_data(data, rec_size);
- return -1;
+ goto err;
}
sdo_count = (rec_size - 8) / 2;
@@ -295,7 +330,7 @@
if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate memory for SDO!\n");
- return -1;
+ goto err;
}
// Initialize SDO object
@@ -311,9 +346,13 @@
while (EC_READ_U8(data + 2) & 0x80);
// Fetch all SDO descriptions
- if (ec_slave_fetch_sdo_descriptions(slave)) return -1;
-
- return 0;
+ if (ec_slave_fetch_sdo_descriptions(slave, &command)) goto err;
+
+ ec_command_clear(&command);
+ return 0;
+ err:
+ ec_command_clear(&command);
+ return -1;
}
/*****************************************************************************/
@@ -323,21 +362,25 @@
\return 0 in case of success, else < 0
*/
-int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT slave */)
+int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave, /**< EtherCAT slave */
+ ec_command_t *command /**< command */
+ )
{
uint8_t *data;
size_t rec_size, name_size;
ec_sdo_t *sdo;
list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
- if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 8))) return -1;
+ if (!(data = ec_slave_mbox_prepare_send(slave, command, 0x03, 8)))
+ return -1;
EC_WRITE_U16(data, 0x8 << 12); // SDO information
EC_WRITE_U8 (data + 2, 0x03); // Get object description request
EC_WRITE_U8 (data + 3, 0x00);
EC_WRITE_U16(data + 4, 0x0000);
EC_WRITE_U16(data + 6, sdo->index); // SDO index
- if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
+ if (!(data = ec_slave_mbox_simple_io(slave, command, &rec_size)))
+ return -1;
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
@@ -364,8 +407,10 @@
return -1;
}
+#if 0
EC_DBG("object desc response:\n");
ec_print_data(data, rec_size);
+#endif
//sdo->unknown = EC_READ_U16(data + 8);
sdo->object_code = EC_READ_U8(data + 11);
@@ -387,7 +432,8 @@
}
// Fetch all entries (subindices)
- if (ec_slave_fetch_sdo_entries(slave, sdo, EC_READ_U8(data + 10)))
+ if (ec_slave_fetch_sdo_entries(slave, command, sdo,
+ EC_READ_U8(data + 10)))
return -1;
}
@@ -402,6 +448,7 @@
*/
int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */
+ ec_command_t *command, /**< command */
ec_sdo_t *sdo, /**< SDO */
uint8_t subindices /**< number of subindices */
)
@@ -412,7 +459,7 @@
ec_sdo_entry_t *entry;
for (i = 1; i <= subindices; i++) {
- if (!(data = ec_slave_mbox_prepare_send(slave, 0x03, 10)))
+ if (!(data = ec_slave_mbox_prepare_send(slave, command, 0x03, 10)))
return -1;
EC_WRITE_U16(data, 0x8 << 12); // SDO information
@@ -423,7 +470,8 @@
EC_WRITE_U8 (data + 8, i); // SDO subindex
EC_WRITE_U8 (data + 9, 0x00); // value info (no values)
- if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
+ if (!(data = ec_slave_mbox_simple_io(slave, command, &rec_size)))
+ return -1;
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
--- a/master/domain.c Mon May 29 09:54:18 2006 +0000
+++ b/master/domain.c Mon Jun 26 15:04:06 2006 +0000
@@ -225,7 +225,7 @@
*/
int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
- uint32_t base_address /**< Logische Basisadresse */
+ uint32_t base_address /**< logical base address */
)
{
ec_field_reg_t *field_reg;
@@ -234,12 +234,12 @@
unsigned int i, j, cmd_count;
uint32_t field_off, field_off_cmd;
uint32_t cmd_offset;
- size_t cmd_data_size;
+ size_t cmd_data_size, sync_size;
ec_command_t *command;
domain->base_address = base_address;
- // Größe der Prozessdaten berechnen und Kommandos allozieren
+ // calculate size of process data and allocate memory
domain->data_size = 0;
cmd_offset = base_address;
cmd_data_size = 0;
@@ -249,20 +249,21 @@
fmmu = &slave->fmmus[j];
if (fmmu->domain == domain) {
fmmu->logical_start_address = base_address + domain->data_size;
- domain->data_size += fmmu->sync->size;
- if (cmd_data_size + fmmu->sync->size > EC_MAX_DATA_SIZE) {
+ sync_size = ec_slave_calc_sync_size(slave, fmmu->sync);
+ domain->data_size += sync_size;
+ if (cmd_data_size + sync_size > EC_MAX_DATA_SIZE) {
if (ec_domain_add_command(domain, cmd_offset,
cmd_data_size)) return -1;
cmd_offset += cmd_data_size;
cmd_data_size = 0;
cmd_count++;
}
- cmd_data_size += fmmu->sync->size;
+ cmd_data_size += sync_size;
}
}
}
- // Letztes Kommando allozieren
+ // allocate last command
if (cmd_data_size) {
if (ec_domain_add_command(domain, cmd_offset, cmd_data_size))
return -1;
@@ -275,14 +276,14 @@
return 0;
}
- // Alle Prozessdatenzeiger setzen
+ // set all process data pointers
list_for_each_entry(field_reg, &domain->field_regs, list) {
for (i = 0; i < field_reg->slave->fmmu_count; i++) {
fmmu = &field_reg->slave->fmmus[i];
if (fmmu->domain == domain && fmmu->sync == field_reg->sync) {
field_off = fmmu->logical_start_address +
field_reg->field_offset;
- // Kommando suchen
+ // search command
list_for_each_entry(command, &domain->commands, list) {
field_off_cmd = field_off - command->address.logical;
if (field_off >= command->address.logical &&
--- a/master/ethernet.c Mon May 29 09:54:18 2006 +0000
+++ b/master/ethernet.c Mon Jun 26 15:04:06 2006 +0000
@@ -79,6 +79,7 @@
int result, i;
eoe->slave = NULL;
+ ec_command_init(&eoe->command);
eoe->state = ec_eoe_state_rx_start;
eoe->opened = 0;
eoe->rx_skb = NULL;
@@ -159,6 +160,8 @@
}
if (eoe->rx_skb) dev_kfree_skb(eoe->rx_skb);
+
+ ec_command_clear(&eoe->command);
}
/*****************************************************************************/
@@ -235,8 +238,8 @@
printk("\n");
#endif
- if (!(data = ec_slave_mbox_prepare_send(eoe->slave, 0x02,
- current_size + 4)))
+ if (!(data = ec_slave_mbox_prepare_send(eoe->slave, &eoe->command,
+ 0x02, current_size + 4)))
return -1;
EC_WRITE_U8 (data, 0x00); // eoe fragment req.
@@ -246,7 +249,7 @@
(eoe->tx_frame_number & 0x0F) << 12));
memcpy(data + 4, eoe->tx_frame->skb->data + eoe->tx_offset, current_size);
- ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
+ ec_master_queue_command(eoe->slave->master, &eoe->command);
eoe->tx_offset += current_size;
eoe->tx_fragment_number++;
@@ -310,8 +313,8 @@
if (!eoe->slave->online || !eoe->slave->master->device->link_state)
return;
- ec_slave_mbox_prepare_check(eoe->slave);
- ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
+ ec_slave_mbox_prepare_check(eoe->slave, &eoe->command);
+ ec_master_queue_command(eoe->slave->master, &eoe->command);
eoe->state = ec_eoe_state_rx_check;
}
@@ -325,19 +328,19 @@
void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
{
- if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
+ if (eoe->command.state != EC_CMD_RECEIVED) {
eoe->stats.rx_errors++;
eoe->state = ec_eoe_state_tx_start;
return;
}
- if (!ec_slave_mbox_check(eoe->slave)) {
+ if (!ec_slave_mbox_check(&eoe->command)) {
eoe->state = ec_eoe_state_tx_start;
return;
}
- ec_slave_mbox_prepare_fetch(eoe->slave);
- ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
+ ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->command);
+ ec_master_queue_command(eoe->slave->master, &eoe->command);
eoe->state = ec_eoe_state_rx_fetch;
}
@@ -356,13 +359,14 @@
uint8_t frame_number, fragment_offset, fragment_number;
off_t offset;
- if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
+ if (eoe->command.state != EC_CMD_RECEIVED) {
eoe->stats.rx_errors++;
eoe->state = ec_eoe_state_tx_start;
return;
}
- if (!(data = ec_slave_mbox_fetch(eoe->slave, 0x02, &rec_size))) {
+ if (!(data = ec_slave_mbox_fetch(eoe->slave, &eoe->command,
+ 0x02, &rec_size))) {
eoe->stats.rx_errors++;
eoe->state = ec_eoe_state_tx_start;
return;
@@ -554,13 +558,13 @@
void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE handler */)
{
- if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
+ if (eoe->command.state != EC_CMD_RECEIVED) {
eoe->stats.tx_errors++;
eoe->state = ec_eoe_state_rx_start;
return;
}
- if (eoe->slave->mbox_command.working_counter != 1) {
+ if (eoe->command.working_counter != 1) {
eoe->stats.tx_errors++;
eoe->state = ec_eoe_state_rx_start;
return;
--- a/master/ethernet.h Mon May 29 09:54:18 2006 +0000
+++ b/master/ethernet.h Mon Jun 26 15:04:06 2006 +0000
@@ -73,6 +73,7 @@
{
struct list_head list; /**< list item */
ec_slave_t *slave; /**< pointer to the corresponding slave */
+ ec_command_t command; /**< command */
void (*state)(ec_eoe_t *); /**< state function for the state machine */
struct net_device *dev; /**< net_device for virtual ethernet device */
struct net_device_stats stats; /**< device statistics */
--- a/master/fsm.c Mon May 29 09:54:18 2006 +0000
+++ b/master/fsm.c Mon Jun 26 15:04:06 2006 +0000
@@ -44,14 +44,6 @@
/*****************************************************************************/
-/**
- Size of memory to allocate while reading categories.
-*/
-
-#define EC_CAT_MEM 0x100
-
-/*****************************************************************************/
-
const ec_code_msg_t al_status_messages[];
/*****************************************************************************/
@@ -66,15 +58,15 @@
void ec_fsm_master_reconfigure(ec_fsm_t *);
void ec_fsm_master_address(ec_fsm_t *);
void ec_fsm_master_conf(ec_fsm_t *);
+void ec_fsm_master_eeprom(ec_fsm_t *);
void ec_fsm_slave_start_reading(ec_fsm_t *);
void ec_fsm_slave_read_status(ec_fsm_t *);
void ec_fsm_slave_read_base(ec_fsm_t *);
void ec_fsm_slave_read_dl(ec_fsm_t *);
-void ec_fsm_slave_prepare_sii(ec_fsm_t *);
-void ec_fsm_slave_read_sii(ec_fsm_t *);
-void ec_fsm_slave_category_header(ec_fsm_t *);
-void ec_fsm_slave_category_data(ec_fsm_t *);
+void ec_fsm_slave_eeprom_size(ec_fsm_t *);
+void ec_fsm_slave_fetch_eeprom(ec_fsm_t *);
+void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *);
void ec_fsm_slave_end(ec_fsm_t *);
void ec_fsm_slave_conf(ec_fsm_t *);
@@ -86,8 +78,11 @@
void ec_fsm_slave_op2(ec_fsm_t *);
void ec_fsm_sii_start_reading(ec_fsm_t *);
-void ec_fsm_sii_check(ec_fsm_t *);
-void ec_fsm_sii_fetch(ec_fsm_t *);
+void ec_fsm_sii_read_check(ec_fsm_t *);
+void ec_fsm_sii_read_fetch(ec_fsm_t *);
+void ec_fsm_sii_start_writing(ec_fsm_t *);
+void ec_fsm_sii_write_check(ec_fsm_t *);
+void ec_fsm_sii_write_check2(ec_fsm_t *);
void ec_fsm_sii_end(ec_fsm_t *);
void ec_fsm_sii_error(ec_fsm_t *);
@@ -115,7 +110,6 @@
fsm->master_slaves_responding = 0;
fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
fsm->master_validation = 0;
- fsm->slave_cat_data = NULL;
ec_command_init(&fsm->command);
if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) {
@@ -134,7 +128,6 @@
void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */)
{
- if (fsm->slave_cat_data) kfree(fsm->slave_cat_data);
ec_command_clear(&fsm->command);
}
@@ -149,11 +142,6 @@
fsm->master_state = ec_fsm_master_start;
fsm->master_slaves_responding = 0;
fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
-
- if (fsm->slave_cat_data) {
- kfree(fsm->slave_cat_data);
- fsm->slave_cat_data = NULL;
- }
}
/*****************************************************************************/
@@ -422,7 +410,25 @@
return;
}
- // nothing to configure. restart master state machine.
+ if (master->mode == EC_MASTER_MODE_FREERUN) {
+ // nothing to configure. check for pending EEPROM write operations.
+ list_for_each_entry(slave, &master->slaves, list) {
+ if (!slave->new_eeprom_data) continue;
+
+ // found pending EEPROM write operation. execute it!
+ EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position);
+ fsm->sii_offset = 0x0000;
+ memcpy(fsm->sii_value, slave->new_eeprom_data, 2);
+ fsm->sii_mode = 1;
+ fsm->sii_state = ec_fsm_sii_start_writing;
+ fsm->slave = slave;
+ fsm->master_state = ec_fsm_master_eeprom;
+ fsm->master_state(fsm); // execute immediately
+ return;
+ }
+ }
+
+ // nothing to do. restart master state machine.
fsm->master_state = ec_fsm_master_start;
fsm->master_state(fsm); // execute immediately
}
@@ -450,7 +456,7 @@
if (fsm->sii_state != ec_fsm_sii_end) return;
- if (fsm->sii_result != slave->sii_vendor_id) {
+ if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) {
EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position);
fsm->master_state = ec_fsm_master_start;
fsm->master_state(fsm); // execute immediately
@@ -488,10 +494,10 @@
if (fsm->sii_state != ec_fsm_sii_end) return;
- if (fsm->sii_result != slave->sii_product_code) {
+ if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) {
EC_ERR("Slave %i: invalid product code!\n", slave->ring_position);
EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code,
- fsm->sii_result);
+ EC_READ_U32(fsm->sii_value));
fsm->master_state = ec_fsm_master_start;
fsm->master_state(fsm); // execute immediately
return;
@@ -682,6 +688,49 @@
fsm->master_state(fsm); // execute immediately
}
+/*****************************************************************************/
+
+/**
+ Master state: EEPROM.
+*/
+
+void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */)
+{
+ ec_slave_t *slave = fsm->slave;
+
+ fsm->sii_state(fsm); // execute SII state machine
+
+ if (fsm->sii_state == ec_fsm_sii_error) {
+ EC_ERR("Failed to write EEPROM contents to slave %i.\n",
+ slave->ring_position);
+ kfree(slave->new_eeprom_data);
+ slave->new_eeprom_data = NULL;
+ fsm->master_state = ec_fsm_master_start;
+ fsm->master_state(fsm); // execute immediately
+ return;
+ }
+
+ if (fsm->sii_state != ec_fsm_sii_end) return;
+
+ fsm->sii_offset++;
+ if (fsm->sii_offset < slave->new_eeprom_size) {
+ memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2);
+ fsm->sii_state = ec_fsm_sii_start_writing;
+ fsm->sii_state(fsm); // execute immediately
+ return;
+ }
+
+ // finished writing EEPROM
+ EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position);
+ kfree(slave->new_eeprom_data);
+ slave->new_eeprom_data = NULL;
+
+ // restart master state machine.
+ fsm->master_state = ec_fsm_master_start;
+ fsm->master_state(fsm); // execute immediately
+ return;
+}
+
/******************************************************************************
* slave state machine
*****************************************************************************/
@@ -787,16 +836,17 @@
// read data link status
ec_command_nprd(command, slave->station_address, 0x0110, 2);
ec_master_queue_command(slave->master, command);
- fsm->slave_state = ec_fsm_slave_prepare_sii;
-}
-
-/*****************************************************************************/
-
-/**
- Slave state: PREPARE_SII.
-*/
-
-void ec_fsm_slave_prepare_sii(ec_fsm_t *fsm /**< finite state machine */)
+ fsm->slave_state = ec_fsm_slave_eeprom_size;
+}
+
+/*****************************************************************************/
+
+/**
+ Slave state: EEPROM_SIZE.
+ Read the actual size of the EEPROM to allocate the EEPROM image.
+*/
+
+void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
{
ec_command_t *command = &fsm->command;
ec_slave_t *slave = fsm->slave;
@@ -811,254 +861,183 @@
}
dl_status = EC_READ_U16(command->data);
-
for (i = 0; i < 4; i++) {
slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
}
- fsm->sii_offset = 0x0004;
+ // Start fetching EEPROM size
+
+ fsm->sii_offset = 0x0040; // first category header
fsm->sii_mode = 1;
fsm->sii_state = ec_fsm_sii_start_reading;
- fsm->slave_sii_num = 0;
- fsm->slave_state = ec_fsm_slave_read_sii;
+ fsm->slave_state = ec_fsm_slave_fetch_eeprom;
fsm->slave_state(fsm); // execute state immediately
}
/*****************************************************************************/
/**
- Slave state: READ_SII.
-*/
-
-void ec_fsm_slave_read_sii(ec_fsm_t *fsm /**< finite state machine */)
-{
- ec_slave_t *slave = fsm->slave;
+ Slave state: FETCH_EEPROM.
+*/
+
+void ec_fsm_slave_fetch_eeprom(ec_fsm_t *fsm /**< finite state machine */)
+{
+ ec_slave_t *slave = fsm->slave;
+ uint16_t cat_type, cat_size;
// execute SII state machine
fsm->sii_state(fsm);
if (fsm->sii_state == ec_fsm_sii_error) {
fsm->slave_state = ec_fsm_slave_end;
- EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n",
- fsm->sii_offset, slave->ring_position);
+ EC_ERR("Failed to read EEPROM size of slave %i.\n",
+ slave->ring_position);
return;
}
if (fsm->sii_state != ec_fsm_sii_end) return;
- switch (fsm->slave_sii_num) {
- case 0:
- slave->sii_alias = fsm->sii_result & 0xFFFF;
- fsm->sii_offset = 0x0008;
- break;
- case 1:
- slave->sii_vendor_id = fsm->sii_result;
- fsm->sii_offset = 0x000A;
- break;
- case 2:
- slave->sii_product_code = fsm->sii_result;
- fsm->sii_offset = 0x000C;
- break;
- case 3:
- slave->sii_revision_number = fsm->sii_result;
- fsm->sii_offset = 0x000E;
- break;
- case 4:
- slave->sii_serial_number = fsm->sii_result;
- fsm->sii_offset = 0x0018;
- break;
- case 5:
- slave->sii_rx_mailbox_offset = fsm->sii_result & 0xFFFF;
- slave->sii_rx_mailbox_size = fsm->sii_result >> 16;
- fsm->sii_offset = 0x001A;
- break;
- case 6:
- slave->sii_tx_mailbox_offset = fsm->sii_result & 0xFFFF;
- slave->sii_tx_mailbox_size = fsm->sii_result >> 16;
- fsm->sii_offset = 0x001C;
- break;
- case 7:
- slave->sii_mailbox_protocols = fsm->sii_result & 0xFFFF;
-
- fsm->slave_cat_offset = 0x0040;
-
- if (fsm->slave_cat_data) {
- EC_INFO("FSM freeing old category data on slave %i...\n",
- fsm->slave->ring_position);
- kfree(fsm->slave_cat_data);
- }
-
- if (!(fsm->slave_cat_data =
- (uint8_t *) kmalloc(EC_CAT_MEM, GFP_ATOMIC))) {
- EC_ERR("FSM Failed to allocate category data.\n");
- fsm->slave_state = ec_fsm_slave_end;
- return;
- }
-
- // start reading first category header
- fsm->sii_offset = fsm->slave_cat_offset;
- fsm->sii_state = ec_fsm_sii_start_reading;
-
- fsm->slave_state = ec_fsm_slave_category_header;
- fsm->slave_state(fsm); // execute state immediately
- return;
- }
-
- fsm->slave_sii_num++;
+ cat_type = EC_READ_U16(fsm->sii_value);
+ cat_size = EC_READ_U16(fsm->sii_value + 2);
+
+ if (cat_type != 0xFFFF) { // not the last category
+ fsm->sii_offset += cat_size + 2;
+ fsm->sii_state = ec_fsm_sii_start_reading;
+ fsm->sii_state(fsm); // execute state immediately
+ return;
+ }
+
+ slave->eeprom_size = (fsm->sii_offset + 1) * 2;
+
+ if (slave->eeprom_data) {
+ EC_INFO("Freeing old EEPROM data on slave %i...\n",
+ slave->ring_position);
+ kfree(slave->eeprom_data);
+ }
+
+ if (!(slave->eeprom_data =
+ (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
+ EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
+ slave->ring_position);
+ fsm->slave_state = ec_fsm_slave_end;
+ return;
+ }
+
+ // Start fetching EEPROM contents
+
+ fsm->sii_offset = 0x0000;
+ fsm->sii_mode = 1;
fsm->sii_state = ec_fsm_sii_start_reading;
+ fsm->slave_state = ec_fsm_slave_fetch_eeprom2;
fsm->slave_state(fsm); // execute state immediately
}
/*****************************************************************************/
/**
- Slave state: CATEGORY_HEADER.
- Start reading categories.
-*/
-
-void ec_fsm_slave_category_header(ec_fsm_t *fsm /**< finite state machine */)
-{
+ Slave state: FETCH_EEPROM2.
+*/
+
+void ec_fsm_slave_fetch_eeprom2(ec_fsm_t *fsm /**< finite state machine */)
+{
+ ec_slave_t *slave = fsm->slave;
+ uint16_t *cat_word, cat_type, cat_size;
+
// execute SII state machine
fsm->sii_state(fsm);
if (fsm->sii_state == ec_fsm_sii_error) {
- kfree(fsm->slave_cat_data);
- fsm->slave_cat_data = NULL;
fsm->slave_state = ec_fsm_slave_end;
- EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n",
- fsm->slave_cat_offset, fsm->slave->ring_position);
+ EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
+ slave->ring_position);
return;
}
if (fsm->sii_state != ec_fsm_sii_end) return;
- // last category?
- if ((fsm->sii_result & 0xFFFF) == 0xFFFF) {
- kfree(fsm->slave_cat_data);
- fsm->slave_cat_data = NULL;
- fsm->slave_state = ec_fsm_slave_end;
- return;
- }
-
- fsm->slave_cat_type = fsm->sii_result & 0x7FFF;
- fsm->slave_cat_words = (fsm->sii_result >> 16) & 0xFFFF;
-
- if (fsm->slave_cat_words > EC_CAT_MEM * 2) {
- EC_ERR("FSM category memory too small! %i words needed.\n",
- fsm->slave_cat_words);
- fsm->slave_state = ec_fsm_slave_end;
- return;
- }
-
- // start reading category data
- fsm->slave_cat_data_offset = 0;
- fsm->sii_offset = (fsm->slave_cat_offset + 2 +
- fsm->slave_cat_data_offset);
- fsm->sii_mode = 1;
- fsm->sii_state = ec_fsm_sii_start_reading;
- fsm->slave_state = ec_fsm_slave_category_data;
- fsm->slave_state(fsm); // execute state immediately
-}
-
-/*****************************************************************************/
-
-/**
- Slave state: CATEGORY_DATA.
- Reads category data.
-*/
-
-void ec_fsm_slave_category_data(ec_fsm_t *fsm /**< finite state machine */)
-{
- // execute SII state machine
- fsm->sii_state(fsm);
-
- if (fsm->sii_state == ec_fsm_sii_error) {
- kfree(fsm->slave_cat_data);
- fsm->slave_cat_data = NULL;
- fsm->slave_state = ec_fsm_slave_end;
- EC_ERR("FSM failed to read category 0x%02X data at 0x%04X"
- " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset,
- fsm->slave->ring_position);
- return;
- }
-
- if (fsm->sii_state != ec_fsm_sii_end) return;
-
- fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] =
- fsm->sii_result & 0xFF;
- fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] =
- (fsm->sii_result >> 8) & 0xFF;
-
- // read second word "on the fly"
- if (fsm->slave_cat_data_offset + 1 < fsm->slave_cat_words) {
- fsm->slave_cat_data_offset++;
- fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] =
- (fsm->sii_result >> 16) & 0xFF;
- fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] =
- (fsm->sii_result >> 24) & 0xFF;
- }
-
- fsm->slave_cat_data_offset++;
-
- if (fsm->slave_cat_data_offset < fsm->slave_cat_words) {
- fsm->sii_offset = (fsm->slave_cat_offset + 2 +
- fsm->slave_cat_data_offset);
- fsm->sii_mode = 1;
+ // 2 words fetched
+
+ if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit
+ memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4);
+ }
+ else { // copy the last word
+ memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2);
+ }
+
+ if (fsm->sii_offset + 2 < slave->eeprom_size / 2) {
+ // fetch the next 2 words
+ fsm->sii_offset += 2;
fsm->sii_state = ec_fsm_sii_start_reading;
- fsm->slave_state = ec_fsm_slave_category_data;
- fsm->slave_state(fsm); // execute state immediately
- return;
- }
-
- // category data complete
- switch (fsm->slave_cat_type)
- {
- case 0x000A:
- if (ec_slave_fetch_strings(fsm->slave, fsm->slave_cat_data))
- goto out_free;
- break;
- case 0x001E:
- if (ec_slave_fetch_general(fsm->slave, fsm->slave_cat_data))
- goto out_free;
- break;
- case 0x0028:
- break;
- case 0x0029:
- if (ec_slave_fetch_sync(fsm->slave, fsm->slave_cat_data,
- fsm->slave_cat_words))
- goto out_free;
- break;
- case 0x0032:
- if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data,
- fsm->slave_cat_words,
- EC_TX_PDO))
- goto out_free;
- break;
- case 0x0033:
- if (ec_slave_fetch_pdo(fsm->slave, fsm->slave_cat_data,
- fsm->slave_cat_words,
- EC_RX_PDO))
- goto out_free;
- break;
- default:
- EC_WARN("FSM: Unknown category type 0x%04X in slave %i.\n",
- fsm->slave_cat_type, fsm->slave->ring_position);
- }
-
- // start reading next category header
- fsm->slave_cat_offset += 2 + fsm->slave_cat_words;
- fsm->sii_offset = fsm->slave_cat_offset;
- fsm->sii_mode = 1;
- fsm->sii_state = ec_fsm_sii_start_reading;
- fsm->slave_state = ec_fsm_slave_category_header;
- fsm->slave_state(fsm); // execute state immediately
- return;
-
- out_free:
- kfree(fsm->slave_cat_data);
- fsm->slave_cat_data = NULL;
+ fsm->sii_state(fsm); // execute state immediately
+ return;
+ }
+
+ // Evaluate EEPROM contents
+
+ slave->sii_alias =
+ EC_READ_U16(slave->eeprom_data + 2 * 0x0004);
+ slave->sii_vendor_id =
+ EC_READ_U32(slave->eeprom_data + 2 * 0x0008);
+ slave->sii_product_code =
+ EC_READ_U32(slave->eeprom_data + 2 * 0x000A);
+ slave->sii_revision_number =
+ EC_READ_U32(slave->eeprom_data + 2 * 0x000C);
+ slave->sii_serial_number =
+ EC_READ_U32(slave->eeprom_data + 2 * 0x000E);
+ slave->sii_rx_mailbox_offset =
+ EC_READ_U16(slave->eeprom_data + 2 * 0x0018);
+ slave->sii_rx_mailbox_size =
+ EC_READ_U16(slave->eeprom_data + 2 * 0x0019);
+ slave->sii_tx_mailbox_offset =
+ EC_READ_U16(slave->eeprom_data + 2 * 0x001A);
+ slave->sii_tx_mailbox_size =
+ EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
+ slave->sii_mailbox_protocols =
+ EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
+
+ // evaluate category data
+ cat_word = (uint16_t *) slave->eeprom_data + 0x0040;
+ while (EC_READ_U16(cat_word) != 0xFFFF) {
+ cat_type = EC_READ_U16(cat_word) & 0x7FFF;
+ cat_size = EC_READ_U16(cat_word + 1);
+
+ switch (cat_type) {
+ case 0x000A:
+ if (ec_slave_fetch_strings(slave, (uint8_t *) (cat_word + 2)))
+ goto end;
+ break;
+ case 0x001E:
+ if (ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2)))
+ goto end;
+ break;
+ case 0x0028:
+ break;
+ case 0x0029:
+ if (ec_slave_fetch_sync(slave, (uint8_t *) (cat_word + 2),
+ cat_size))
+ goto end;
+ break;
+ case 0x0032:
+ if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
+ cat_size, EC_TX_PDO))
+ goto end;
+ break;
+ case 0x0033:
+ if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
+ cat_size, EC_RX_PDO))
+ goto end;
+ break;
+ default:
+ EC_WARN("Unknown category type 0x%04X in slave %i.\n",
+ cat_type, slave->ring_position);
+ }
+
+ cat_word += cat_size + 2;
+ }
+
+ end:
fsm->slave_state = ec_fsm_slave_end;
}
@@ -1149,7 +1128,7 @@
if (slave->type) {
for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
sync = slave->type->sync_managers[j];
- ec_sync_config(sync, command->data + EC_SYNC_SIZE * j);
+ ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j);
}
}
@@ -1268,7 +1247,8 @@
0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
for (j = 0; j < slave->fmmu_count; j++) {
- ec_fmmu_config(&slave->fmmus[j], command->data + EC_FMMU_SIZE * j);
+ ec_fmmu_config(&slave->fmmus[j], slave,
+ command->data + EC_FMMU_SIZE * j);
}
ec_master_queue_command(master, command);
@@ -1391,17 +1371,17 @@
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
EC_WRITE_U16(command->data + 2, fsm->sii_offset);
ec_master_queue_command(fsm->master, command);
- fsm->sii_state = ec_fsm_sii_check;
-}
-
-/*****************************************************************************/
-
-/**
- SII state: CHECK.
+ fsm->sii_state = ec_fsm_sii_read_check;
+}
+
+/*****************************************************************************/
+
+/**
+ SII state: READ_CHECK.
Checks, if the SII-read-command has been sent and issues a fetch command.
*/
-void ec_fsm_sii_check(ec_fsm_t *fsm /**< finite state machine */)
+void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */)
{
ec_command_t *command = &fsm->command;
@@ -1422,17 +1402,17 @@
}
ec_master_queue_command(fsm->master, command);
- fsm->sii_state = ec_fsm_sii_fetch;
-}
-
-/*****************************************************************************/
-
-/**
- SII state: FETCH.
+ fsm->sii_state = ec_fsm_sii_read_fetch;
+}
+
+/*****************************************************************************/
+
+/**
+ SII state: READ_FETCH.
Fetches the result of an SII-read command.
*/
-void ec_fsm_sii_fetch(ec_fsm_t *fsm /**< finite state machine */)
+void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */)
{
ec_command_t *command = &fsm->command;
@@ -1477,13 +1457,93 @@
#endif
// SII value received.
- fsm->sii_result = EC_READ_U32(command->data + 6);
+ memcpy(fsm->sii_value, command->data + 6, 4);
fsm->sii_state = ec_fsm_sii_end;
}
/*****************************************************************************/
/**
+ SII state: START_WRITING.
+ Starts reading the slave information interface.
+*/
+
+void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */)
+{
+ ec_command_t *command = &fsm->command;
+
+ // initiate write operation
+ ec_command_npwr(command, fsm->slave->station_address, 0x502, 8);
+ EC_WRITE_U8 (command->data, 0x01); // enable write access
+ EC_WRITE_U8 (command->data + 1, 0x02); // request write operation
+ EC_WRITE_U32(command->data + 2, fsm->sii_offset);
+ memcpy(command->data + 6, fsm->sii_value, 2);
+ ec_master_queue_command(fsm->master, command);
+ fsm->sii_state = ec_fsm_sii_write_check;
+}
+
+/*****************************************************************************/
+
+/**
+ SII state: WRITE_CHECK.
+*/
+
+void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */)
+{
+ ec_command_t *command = &fsm->command;
+
+ if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
+ EC_ERR("SII: Reception of write command failed.\n");
+ fsm->sii_state = ec_fsm_sii_error;
+ return;
+ }
+
+ fsm->sii_start = get_cycles();
+
+ // issue check/fetch command
+ ec_command_nprd(command, fsm->slave->station_address, 0x502, 2);
+ ec_master_queue_command(fsm->master, command);
+ fsm->sii_state = ec_fsm_sii_write_check2;
+}
+
+/*****************************************************************************/
+
+/**
+ SII state: WRITE_CHECK2.
+*/
+
+void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */)
+{
+ ec_command_t *command = &fsm->command;
+
+ if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
+ EC_ERR("SII: Reception of write check command failed.\n");
+ fsm->sii_state = ec_fsm_sii_error;
+ return;
+ }
+
+ if (EC_READ_U8(command->data + 1) & 0x82) {
+ // still busy... timeout?
+ if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
+ EC_ERR("SII: Write timeout.\n");
+ fsm->sii_state = ec_fsm_sii_error;
+ }
+
+ // issue check/fetch command again
+ ec_master_queue_command(fsm->master, command);
+ }
+ else if (EC_READ_U8(command->data + 1) & 0x40) {
+ EC_ERR("SII: Write operation failed!\n");
+ fsm->sii_state = ec_fsm_sii_error;
+ }
+ else { // success
+ fsm->sii_state = ec_fsm_sii_end;
+ }
+}
+
+/*****************************************************************************/
+
+/**
SII state: END.
End state of the slave SII state machine.
*/
--- a/master/fsm.h Mon May 29 09:54:18 2006 +0000
+++ b/master/fsm.h Mon Jun 26 15:04:06 2006 +0000
@@ -67,17 +67,11 @@
unsigned int master_validation; /**< non-zero, if validation to do */
void (*slave_state)(ec_fsm_t *); /**< slave state function */
- uint8_t slave_sii_num; /**< SII value iteration counter */
- uint8_t *slave_cat_data; /**< temporary memory for category data */
- uint16_t slave_cat_offset; /**< current category word offset in EEPROM */
- uint16_t slave_cat_data_offset; /**< current offset in category data */
- uint16_t slave_cat_type; /**< type of current category */
- uint16_t slave_cat_words; /**< number of words of current category */
void (*sii_state)(ec_fsm_t *); /**< SII state function */
uint16_t sii_offset; /**< input: offset in SII */
unsigned int sii_mode; /**< SII reading done by APRD (0) or NPRD (1) */
- uint32_t sii_result; /**< output: read SII value (32bit) */
+ uint8_t sii_value[4]; /**< raw SII value (32bit) */
cycles_t sii_start; /**< sii start */
void (*change_state)(ec_fsm_t *); /**< slave state change state function */
--- a/master/mailbox.c Mon May 29 09:54:18 2006 +0000
+++ b/master/mailbox.c Mon Jun 26 15:04:06 2006 +0000
@@ -52,12 +52,12 @@
\return pointer to mailbox command data
*/
-uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< slave */
+uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */
+ ec_command_t *command, /**< command */
uint8_t type, /**< mailbox protocol */
size_t size /**< size of the data */
)
{
- ec_command_t *command = &slave->mbox_command;
size_t total_size;
if (unlikely(!slave->sii_mailbox_protocols)) {
@@ -79,7 +79,7 @@
EC_WRITE_U16(command->data, size); // mailbox service data length
EC_WRITE_U16(command->data + 2, slave->station_address); // station address
- EC_WRITE_U8 (command->data + 4, 0x00); // hhannel & priority
+ EC_WRITE_U8 (command->data + 4, 0x00); // channel & priority
EC_WRITE_U8 (command->data + 5, type); // underlying protocol type
return command->data + 6;
@@ -92,10 +92,10 @@
\return 0 in case of success, else < 0
*/
-int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< slave */)
-{
- ec_command_t *command = &slave->mbox_command;
-
+int ec_slave_mbox_prepare_check(const ec_slave_t *slave, /**< slave */
+ ec_command_t *command /**< command */
+ )
+{
// FIXME: second sync manager?
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
return -1;
@@ -110,9 +110,9 @@
\return 0 in case of success, else < 0
*/
-int ec_slave_mbox_check(const ec_slave_t *slave /**< slave */)
-{
- return EC_READ_U8(slave->mbox_command.data + 5) & 8 ? 1 : 0;
+int ec_slave_mbox_check(const ec_command_t *command /**< command */)
+{
+ return EC_READ_U8(command->data + 5) & 8 ? 1 : 0;
}
/*****************************************************************************/
@@ -122,10 +122,10 @@
\return 0 in case of success, else < 0
*/
-int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< slave */)
-{
- ec_command_t *command = &slave->mbox_command;
-
+int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */
+ ec_command_t *command /**< command */
+ )
+{
if (ec_command_nprd(command, slave->station_address,
slave->sii_tx_mailbox_offset,
slave->sii_tx_mailbox_size)) return -1;
@@ -139,12 +139,12 @@
\return pointer to the received data
*/
-uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< slave */
+uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */
+ ec_command_t *command, /**< command */
uint8_t type, /**< expected mailbox protocol */
size_t *size /**< size of the received data */
)
{
- ec_command_t *command = &slave->mbox_command;
size_t data_size;
if ((EC_READ_U8(command->data + 5) & 0x0F) != type) {
@@ -171,14 +171,13 @@
\return pointer to the received data
*/
-uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< slave */
+uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *slave, /**< slave */
+ ec_command_t *command, /**< command */
size_t *size /**< size of the received data */
)
{
uint8_t type;
- ec_command_t *command;
-
- command = &slave->mbox_command;
+
type = EC_READ_U8(command->data + 5);
if (unlikely(ec_master_simple_io(slave->master, command))) {
@@ -187,7 +186,7 @@
return NULL;
}
- return ec_slave_mbox_simple_receive(slave, type, size);
+ return ec_slave_mbox_simple_receive(slave, command, type, size);
}
/*****************************************************************************/
@@ -197,21 +196,20 @@
\return pointer to the received data
*/
-uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< slave */
+uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */
+ ec_command_t *command, /**< command */
uint8_t type, /**< expected protocol */
size_t *size /**< received data size */
)
{
cycles_t start, end, timeout;
- ec_command_t *command;
-
- command = &slave->mbox_command;
+
start = get_cycles();
timeout = (cycles_t) 100 * cpu_khz; // 100ms
while (1)
{
- if (ec_slave_mbox_prepare_check(slave)) return NULL;
+ if (ec_slave_mbox_prepare_check(slave, command)) return NULL;
if (unlikely(ec_master_simple_io(slave->master, command))) {
EC_ERR("Mailbox checking failed on slave %i!\n",
slave->ring_position);
@@ -220,7 +218,7 @@
end = get_cycles();
- if (ec_slave_mbox_check(slave))
+ if (ec_slave_mbox_check(command))
break; // proceed with receiving data
if ((end - start) >= timeout) {
@@ -232,7 +230,7 @@
udelay(100);
}
- if (ec_slave_mbox_prepare_fetch(slave)) return NULL;
+ if (ec_slave_mbox_prepare_fetch(slave, command)) return NULL;
if (unlikely(ec_master_simple_io(slave->master, command))) {
EC_ERR("Mailbox receiving failed on slave %i!\n",
slave->ring_position);
@@ -243,7 +241,7 @@
EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
/ cpu_khz));
- return ec_slave_mbox_fetch(slave, type, size);
-}
-
-/*****************************************************************************/
+ return ec_slave_mbox_fetch(slave, command, type, size);
+}
+
+/*****************************************************************************/
--- a/master/mailbox.h Mon May 29 09:54:18 2006 +0000
+++ b/master/mailbox.h Mon Jun 26 15:04:06 2006 +0000
@@ -45,14 +45,17 @@
/*****************************************************************************/
-uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *, uint8_t, size_t);
-int ec_slave_mbox_prepare_check(ec_slave_t *);
-int ec_slave_mbox_check(const ec_slave_t *);
-int ec_slave_mbox_prepare_fetch(ec_slave_t *);
-uint8_t *ec_slave_mbox_fetch(ec_slave_t *, uint8_t, size_t *);
+uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *, ec_command_t *,
+ uint8_t, size_t);
+int ec_slave_mbox_prepare_check(const ec_slave_t *, ec_command_t *);
+int ec_slave_mbox_check(const ec_command_t *);
+int ec_slave_mbox_prepare_fetch(const ec_slave_t *, ec_command_t *);
+uint8_t *ec_slave_mbox_fetch(const ec_slave_t *, ec_command_t *,
+ uint8_t, size_t *);
-uint8_t *ec_slave_mbox_simple_io(ec_slave_t *, size_t *);
-uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *, uint8_t, size_t *);
+uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *, ec_command_t *, size_t *);
+uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *, ec_command_t *,
+ uint8_t, size_t *);
/*****************************************************************************/
--- a/master/master.c Mon May 29 09:54:18 2006 +0000
+++ b/master/master.c Mon Jun 26 15:04:06 2006 +0000
@@ -58,6 +58,8 @@
void ec_master_freerun(void *);
void ec_master_eoe_run(unsigned long);
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
+ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
+ const char *, size_t);
/*****************************************************************************/
@@ -65,16 +67,18 @@
EC_SYSFS_READ_ATTR(slave_count);
EC_SYSFS_READ_ATTR(mode);
+EC_SYSFS_READ_WRITE_ATTR(eeprom_write_enable);
static struct attribute *ec_def_attrs[] = {
&attr_slave_count,
&attr_mode,
+ &attr_eeprom_write_enable,
NULL,
};
static struct sysfs_ops ec_sysfs_ops = {
.show = &ec_show_master_attribute,
- .store = NULL
+ .store = ec_store_master_attribute
};
static struct kobj_type ktype_ec_master = {
@@ -244,6 +248,8 @@
master->release_cb = NULL;
master->cb_data = NULL;
+ master->eeprom_write_enable = 0;
+
ec_fsm_reset(&master->fsm);
}
@@ -492,7 +498,7 @@
{
unsigned int response_tries_left;
- response_tries_left = 10;
+ response_tries_left = 10000;
while (1)
{
@@ -698,13 +704,13 @@
ec_master_eoe_stop(master);
EC_INFO("Stopping Free-Run mode.\n");
+ master->mode = EC_MASTER_MODE_IDLE;
if (!cancel_delayed_work(&master->freerun_work)) {
flush_workqueue(master->workqueue);
}
ec_master_clear_slaves(master);
- master->mode = EC_MASTER_MODE_IDLE;
}
/*****************************************************************************/
@@ -730,7 +736,8 @@
// release master lock
spin_unlock_bh(&master->internal_lock);
- queue_delayed_work(master->workqueue, &master->freerun_work, 1);
+ if (master->mode == EC_MASTER_MODE_FREERUN)
+ queue_delayed_work(master->workqueue, &master->freerun_work, 1);
}
/*****************************************************************************/
@@ -741,11 +748,16 @@
*/
void ec_sync_config(const ec_sync_t *sync, /**< sync manager */
+ const ec_slave_t *slave, /**< EtherCAT slave */
uint8_t *data /**> configuration memory */
)
{
+ size_t sync_size;
+
+ sync_size = ec_slave_calc_sync_size(slave, sync);
+
EC_WRITE_U16(data, sync->physical_start_address);
- EC_WRITE_U16(data + 2, sync->size);
+ EC_WRITE_U16(data + 2, sync_size);
EC_WRITE_U8 (data + 4, sync->control_byte);
EC_WRITE_U8 (data + 5, 0x00); // status byte (read only)
EC_WRITE_U16(data + 6, 0x0001); // enable
@@ -777,11 +789,16 @@
*/
void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< FMMU */
+ const ec_slave_t *slave, /**< EtherCAT slave */
uint8_t *data /**> configuration memory */
)
{
+ size_t sync_size;
+
+ sync_size = ec_slave_calc_sync_size(slave, fmmu->sync);
+
EC_WRITE_U32(data, fmmu->logical_start_address);
- EC_WRITE_U16(data + 4, fmmu->sync->size);
+ EC_WRITE_U16(data + 4, sync_size); // size of fmmu
EC_WRITE_U8 (data + 6, 0x00); // logical start bit
EC_WRITE_U8 (data + 7, 0x07); // logical end bit
EC_WRITE_U16(data + 8, fmmu->sync->physical_start_address);
@@ -825,6 +842,44 @@
/*****************************************************************************/
/**
+ Formats attribute data for SysFS write access.
+ \return number of bytes processed, or negative error code
+*/
+
+ssize_t ec_store_master_attribute(struct kobject *kobj, /**< slave's kobject */
+ struct attribute *attr, /**< attribute */
+ const char *buffer, /**< memory with data */
+ size_t size /**< size of data to store */
+ )
+{
+ ec_master_t *master = container_of(kobj, ec_master_t, kobj);
+
+ if (attr == &attr_eeprom_write_enable) {
+ if (!strcmp(buffer, "1\n")) {
+ master->eeprom_write_enable = 1;
+ EC_INFO("Slave EEPROM writing enabled.\n");
+ return size;
+ }
+ else if (!strcmp(buffer, "0\n")) {
+ master->eeprom_write_enable = 0;
+ EC_INFO("Slave EEPROM writing disabled.\n");
+ return size;
+ }
+
+ EC_ERR("Invalid value for eeprom_write_enable!\n");
+
+ if (master->eeprom_write_enable) {
+ master->eeprom_write_enable = 0;
+ EC_INFO("Slave EEPROM writing disabled.\n");
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*****************************************************************************/
+
+/**
Starts Ethernet-over-EtherCAT processing for all EoE-capable slaves.
*/
@@ -1088,7 +1143,7 @@
if (ec_command_npwr(command, slave->station_address,
0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE))
return -1;
- ec_sync_config(sync, command->data);
+ ec_sync_config(sync, slave, command->data);
if (unlikely(ec_master_simple_io(master, command))) {
EC_ERR("Setting sync manager %i failed on slave %i!\n",
j, slave->ring_position);
@@ -1166,7 +1221,7 @@
if (ec_command_npwr(command, slave->station_address,
0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
return -1;
- ec_fmmu_config(fmmu, command->data);
+ ec_fmmu_config(fmmu, slave, command->data);
if (unlikely(ec_master_simple_io(master, command))) {
EC_ERR("Setting FMMU %i failed on slave %i!\n",
j, slave->ring_position);
--- a/master/master.h Mon May 29 09:54:18 2006 +0000
+++ b/master/master.h Mon Jun 26 15:04:06 2006 +0000
@@ -122,6 +122,8 @@
int (*request_cb)(void *); /**< lock request callback */
void (*release_cb)(void *); /**< lock release callback */
void *cb_data; /**< data parameter of locking callbacks */
+
+ uint8_t eeprom_write_enable; /**< allow write operations to EEPROMs */
};
/*****************************************************************************/
@@ -149,9 +151,9 @@
// misc.
void ec_master_clear_slaves(ec_master_t *);
-void ec_sync_config(const ec_sync_t *, uint8_t *);
+void ec_sync_config(const ec_sync_t *, const ec_slave_t *, uint8_t *);
void ec_eeprom_sync_config(const ec_eeprom_sync_t *, uint8_t *);
-void ec_fmmu_config(const ec_fmmu_t *, uint8_t *);
+void ec_fmmu_config(const ec_fmmu_t *, const ec_slave_t *, uint8_t *);
void ec_master_output_stats(ec_master_t *);
/*****************************************************************************/
--- a/master/slave.c Mon May 29 09:54:18 2006 +0000
+++ b/master/slave.c Mon Jun 26 15:04:06 2006 +0000
@@ -69,6 +69,7 @@
EC_SYSFS_READ_ATTR(sii_name);
EC_SYSFS_READ_ATTR(type);
EC_SYSFS_READ_WRITE_ATTR(state);
+EC_SYSFS_READ_WRITE_ATTR(eeprom);
static struct attribute *def_attrs[] = {
&attr_ring_position,
@@ -79,6 +80,7 @@
&attr_sii_name,
&attr_type,
&attr_state,
+ &attr_eeprom,
NULL,
};
@@ -145,6 +147,8 @@
slave->type = NULL;
slave->registered = 0;
slave->fmmu_count = 0;
+ slave->eeprom_data = NULL;
+ slave->eeprom_size = 0;
slave->eeprom_group = NULL;
slave->eeprom_image = NULL;
slave->eeprom_order = NULL;
@@ -153,13 +157,14 @@
slave->current_state = EC_SLAVE_STATE_UNKNOWN;
slave->state_error = 0;
slave->online = 1;
-
- ec_command_init(&slave->mbox_command);
+ slave->new_eeprom_data = NULL;
+ slave->new_eeprom_size = 0;
INIT_LIST_HEAD(&slave->eeprom_strings);
INIT_LIST_HEAD(&slave->eeprom_syncs);
INIT_LIST_HEAD(&slave->eeprom_pdos);
INIT_LIST_HEAD(&slave->sdo_dictionary);
+ INIT_LIST_HEAD(&slave->varsize_fields);
for (i = 0; i < 4; i++) {
slave->dl_link[i] = 0;
@@ -186,6 +191,7 @@
ec_eeprom_pdo_entry_t *entry, *next_ent;
ec_sdo_t *sdo, *next_sdo;
ec_sdo_entry_t *en, *next_en;
+ ec_varsize_t *var, *next_var;
slave = container_of(kobj, ec_slave_t, kobj);
@@ -234,7 +240,14 @@
kfree(sdo);
}
- ec_command_clear(&slave->mbox_command);
+ // free information about variable sized data fields
+ list_for_each_entry_safe(var, next_var, &slave->varsize_fields, list) {
+ list_del(&var->list);
+ kfree(var);
+ }
+
+ if (slave->eeprom_data) kfree(slave->eeprom_data);
+ if (slave->new_eeprom_data) kfree(slave->new_eeprom_data);
}
/*****************************************************************************/
@@ -1121,6 +1134,8 @@
EC_INFO(" EEPROM data:\n");
+ EC_INFO(" EEPROM content size: %i Bytes\n", slave->eeprom_size);
+
if (slave->sii_alias)
EC_INFO(" Configured station alias: 0x%04X (%i)\n",
slave->sii_alias, slave->sii_alias);
@@ -1239,6 +1254,83 @@
/*****************************************************************************/
/**
+ Schedules an EEPROM write operation.
+ \return 0 in case of success, else < 0
+*/
+
+ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
+ const uint8_t *data, /**< new EEPROM data */
+ size_t size /**< size of data in bytes */
+ )
+{
+ uint16_t word_size, cat_type, cat_size;
+ const uint16_t *data_words, *next_header;
+ uint16_t *new_data;
+
+ if (!slave->master->eeprom_write_enable) {
+ EC_ERR("Writing EEPROMs not allowed! Enable via"
+ " eeprom_write_enable SysFS entry.\n");
+ return -1;
+ }
+
+ if (slave->master->mode != EC_MASTER_MODE_FREERUN) {
+ EC_ERR("Writing EEPROMs only allowed in freerun mode!\n");
+ return -1;
+ }
+
+ if (slave->new_eeprom_data) {
+ EC_ERR("Slave %i already has a pending EEPROM write operation!\n",
+ slave->ring_position);
+ return -1;
+ }
+
+ // coarse check of the data
+
+ if (size % 2) {
+ EC_ERR("EEPROM size is odd! Dropping.\n");
+ return -1;
+ }
+
+ data_words = (const uint16_t *) data;
+ word_size = size / 2;
+
+ if (word_size < 0x0041) {
+ EC_ERR("EEPROM data too short! Dropping.\n");
+ return -1;
+ }
+
+ next_header = data_words + 0x0040;
+ cat_type = EC_READ_U16(next_header);
+ while (cat_type != 0xFFFF) {
+ cat_type = EC_READ_U16(next_header);
+ cat_size = EC_READ_U16(next_header + 1);
+ if ((next_header + cat_size + 2) - data_words >= word_size) {
+ EC_ERR("EEPROM data seems to be corrupted! Dropping.\n");
+ return -1;
+ }
+ next_header += cat_size + 2;
+ cat_type = EC_READ_U16(next_header);
+ }
+
+ // data ok!
+
+ if (!(new_data = (uint16_t *) kmalloc(word_size * 2, GFP_KERNEL))) {
+ EC_ERR("Unable to allocate memory for new EEPROM data!\n");
+ return -1;
+ }
+ memcpy(new_data, data, size);
+
+ slave->new_eeprom_size = word_size;
+ slave->new_eeprom_data = new_data;
+
+ EC_INFO("EEPROM writing scheduled for slave %i, %i words.\n",
+ slave->ring_position, word_size);
+ return 0;
+}
+
+/*****************************************************************************/
+
+/**
Formats attribute data for SysFS read access.
\return number of bytes to read
*/
@@ -1295,6 +1387,19 @@
return sprintf(buffer, "UNKNOWN\n");
}
}
+ else if (attr == &attr_eeprom) {
+ if (slave->eeprom_data) {
+ if (slave->eeprom_size > PAGE_SIZE) {
+ EC_ERR("EEPROM contents of slave %i exceed 1 page (%i/%i).\n",
+ slave->ring_position, slave->eeprom_size,
+ (int) PAGE_SIZE);
+ }
+ else {
+ memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
+ return slave->eeprom_size;
+ }
+ }
+ }
return 0;
}
@@ -1338,10 +1443,51 @@
EC_ERR("Failed to set slave state!\n");
}
+ else if (attr == &attr_eeprom) {
+ if (!ec_slave_write_eeprom(slave, buffer, size))
+ return size;
+ }
return -EINVAL;
}
+/*****************************************************************************/
+
+/**
+ \return size of sync manager contents
+*/
+
+size_t ec_slave_calc_sync_size(const ec_slave_t *slave, /**< EtherCAT slave */
+ const ec_sync_t *sync /**< sync manager */
+ )
+{
+ unsigned int i, found;
+ const ec_field_t *field;
+ const ec_varsize_t *var;
+ size_t size;
+
+ // if size is specified, return size
+ if (sync->size) return sync->size;
+
+ // sync manager has variable size (size == 0).
+
+ size = 0;
+ for (i = 0; (field = sync->fields[i]); i++) {
+ found = 0;
+ list_for_each_entry(var, &slave->varsize_fields, list) {
+ if (var->field != field) continue;
+ size += var->size;
+ found = 1;
+ }
+
+ if (!found) {
+ EC_WARN("Variable data field \"%s\" of slave %i has no size"
+ " information!\n", field->name, slave->ring_position);
+ }
+ }
+ return size;
+}
+
/******************************************************************************
* Realtime interface
*****************************************************************************/
@@ -1361,9 +1507,75 @@
/*****************************************************************************/
+/**
+ \return 0 in case of success, else < 0
+ \ingroup RealtimeInterface
+*/
+
+int ecrt_slave_field_size(ec_slave_t *slave, /**< EtherCAT slave */
+ const char *field_name, /**< data field name */
+ unsigned int field_index, /**< data field index */
+ size_t size /**< new data field size */
+ )
+{
+ unsigned int i, j, field_counter;
+ const ec_sync_t *sync;
+ const ec_field_t *field;
+ ec_varsize_t *var;
+
+ if (!slave->type) {
+ EC_ERR("Slave %i has no type information!\n", slave->ring_position);
+ return -1;
+ }
+
+ field_counter = 0;
+ for (i = 0; (sync = slave->type->sync_managers[i]); i++) {
+ for (j = 0; (field = sync->fields[j]); j++) {
+ if (!strcmp(field->name, field_name)) {
+ if (field_counter++ == field_index) {
+ // is the size of this field variable?
+ if (field->size) {
+ EC_ERR("Field \"%s\"[%i] of slave %i has no variable"
+ " size!\n", field->name, field_index,
+ slave->ring_position);
+ return -1;
+ }
+ // does a size specification already exist?
+ list_for_each_entry(var, &slave->varsize_fields, list) {
+ if (var->field == field) {
+ EC_WARN("Resizing field \"%s\"[%i] of slave %i.\n",
+ field->name, field_index,
+ slave->ring_position);
+ var->size = size;
+ return 0;
+ }
+ }
+ // create a new size specification...
+ if (!(var = kmalloc(sizeof(ec_varsize_t), GFP_KERNEL))) {
+ EC_ERR("Failed to allocate memory for varsize_t!\n");
+ return -1;
+ }
+ var->field = field;
+ var->size = size;
+ list_add_tail(&var->list, &slave->varsize_fields);
+ return 0;
+ }
+ }
+ }
+ }
+
+ EC_ERR("Slave %i (\"%s %s\") has no field \"%s\"[%i]!\n",
+ slave->ring_position, slave->type->vendor_name,
+ slave->type->product_name, field_name, field_index);
+ return -1;
+}
+
+/*****************************************************************************/
+
/**< \cond */
EXPORT_SYMBOL(ecrt_slave_write_alias);
+EXPORT_SYMBOL(ecrt_slave_field_size);
/**< \endcond */
--- a/master/slave.h Mon May 29 09:54:18 2006 +0000
+++ b/master/slave.h Mon Jun 26 15:04:06 2006 +0000
@@ -214,6 +214,20 @@
/*****************************************************************************/
/**
+ Variable-sized field information.
+*/
+
+typedef struct
+{
+ struct list_head list; /**< list item */
+ const ec_field_t *field; /**< data field */
+ size_t size; /**< field size */
+}
+ec_varsize_t;
+
+/*****************************************************************************/
+
+/**
EtherCAT slave.
*/
@@ -261,23 +275,28 @@
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU configurations */
uint8_t fmmu_count; /**< number of FMMUs used */
+ uint8_t *eeprom_data; /**< Complete EEPROM image */
+ uint16_t eeprom_size; /**< size of the EEPROM contents in byte */
struct list_head eeprom_strings; /**< EEPROM STRING categories */
struct list_head eeprom_syncs; /**< EEPROM SYNC MANAGER categories */
struct list_head eeprom_pdos; /**< EEPROM [RT]XPDO categories */
-
char *eeprom_group; /**< slave group acc. to EEPROM */
char *eeprom_image; /**< slave image name acc. to EEPROM */
char *eeprom_order; /**< slave order number acc. to EEPROM */
char *eeprom_name; /**< slave name acc. to EEPROM */
+ uint16_t *new_eeprom_data; /**< new EEPROM data to write */
+ size_t new_eeprom_size; /**< size of new EEPROM data in words */
+
struct list_head sdo_dictionary; /**< SDO directory list */
- ec_command_t mbox_command; /**< mailbox command */
-
ec_slave_state_t requested_state; /**< requested slave state */
ec_slave_state_t current_state; /**< current slave state */
unsigned int state_error; /**< a state error has happened */
unsigned int online; /**< non-zero, if the slave responds. */
+
+ struct list_head varsize_fields; /**< size information for variable-sized
+ data fields. */
};
/*****************************************************************************/
@@ -306,6 +325,7 @@
int ec_slave_locate_string(ec_slave_t *, unsigned int, char **);
// misc.
+size_t ec_slave_calc_sync_size(const ec_slave_t *, const ec_sync_t *);
void ec_slave_print(const ec_slave_t *, unsigned int);
int ec_slave_check_crc(ec_slave_t *);
--- a/master/types.c Mon May 29 09:54:18 2006 +0000
+++ b/master/types.c Mon Jun 26 15:04:06 2006 +0000
@@ -67,9 +67,39 @@
/*****************************************************************************/
+const ec_field_t bk1120_out = {"Outputs", 0}; // variable size
+const ec_field_t bk1120_in = {"Inputs", 0}; // variable size
+
+const ec_sync_t bk1120_sm0 = {0x1C00, 264, 0x26, {NULL}};
+const ec_sync_t bk1120_sm1 = {0x1E00, 264, 0x22, {NULL}};
+
+const ec_sync_t bk1120_sm2 = { // outputs
+ 0x1000, 0, 0x24, // variable size
+ {&bk1120_out, NULL}
+};
+
+const ec_sync_t bk1120_sm3 = { // inputs
+ 0x1600, 0, 0x00, // variable size
+ {&bk1120_in, NULL}
+};
+
const ec_slave_type_t Beckhoff_BK1120 = {
"Beckhoff", "BK1120", "KBUS Coupler", EC_TYPE_NORMAL,
- {NULL} // no sync managers
+ {&bk1120_sm0, &bk1120_sm1, &bk1120_sm2, &bk1120_sm3, NULL}
+};
+
+/*****************************************************************************/
+
+const ec_field_t el1004_in = {"InputValue", 1};
+
+const ec_sync_t el1004_sm0 = { // inputs
+ 0x1000, 1, 0x00,
+ {&el1004_in, NULL}
+};
+
+const ec_slave_type_t Beckhoff_EL1004 = {
+ "Beckhoff", "EL1004", "4x Digital Input, 3ms", EC_TYPE_NORMAL,
+ {&el1004_sm0, NULL}
};
/*****************************************************************************/
@@ -82,7 +112,7 @@
};
const ec_slave_type_t Beckhoff_EL1014 = {
- "Beckhoff", "EL1014", "4x Digital Input", EC_TYPE_NORMAL,
+ "Beckhoff", "EL1014", "4x Digital Input, 10us", EC_TYPE_NORMAL,
{&el1014_sm0, NULL}
};
@@ -186,8 +216,7 @@
{&el5101_st, &el5101_ip, &el5101_la, NULL}
};
-const ec_slave_type_t Beckhoff_EL5101 =
-{
+const ec_slave_type_t Beckhoff_EL5101 = {
"Beckhoff", "EL5101", "Incremental Encoder Interface", EC_TYPE_NORMAL,
{&mailbox_sm0, &mailbox_sm1, &el5101_sm2, &el5101_sm3, NULL}
};
@@ -230,10 +259,11 @@
*/
ec_slave_ident_t slave_idents[] = {
+ {0x00000002, 0x03EC3052, &Beckhoff_EL1004},
{0x00000002, 0x03F63052, &Beckhoff_EL1014},
{0x00000002, 0x044C2C52, &Beckhoff_EK1100},
{0x00000002, 0x04562C52, &Beckhoff_EK1110},
- //{0x00000002, 0x04602C22, &Beckhoff_BK1120},
+ {0x00000002, 0x04602C22, &Beckhoff_BK1120},
{0x00000002, 0x07D43052, &Beckhoff_EL2004},
{0x00000002, 0x07F03052, &Beckhoff_EL2032},
{0x00000002, 0x0C1E3052, &Beckhoff_EL3102},
--- a/script/ethercat.sh Mon May 29 09:54:18 2006 +0000
+++ b/script/ethercat.sh Mon Jun 26 15:04:06 2006 +0000
@@ -66,14 +66,14 @@
start)
echo -n "Starting EtherCAT master "
- if [ ! $DEVICE_INDEX ]; then
+ if [ -z "$DEVICE_INDEX" ]; then
echo "ERROR: DEVICE_INDEX not set!"
/bin/false
rc_status -v
rc_exit
fi
- if [ ! $EOE_DEVICES ]; then
+ if [ -z "$EOE_DEVICES" ]; then
EOE_DEVICES=0
fi
@@ -99,6 +99,50 @@
rc_exit
fi
+ # Build EoE bridge
+ if [ -n "$EOE_BRIDGE" ]; then
+
+ EOE_INTERFACES=`/sbin/ifconfig -a | grep -o -E "^eoe[0-9]+ "`
+
+ # 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
+ /bin/false
+ rc_status -v
+ rc_exit
+ fi
+ fi
+
+ # free all interfaces of their addresses and add them to the bridge
+ for interface in $EOE_INTERFACES $EOE_EXTRA_INTERFACES; do
+ if ! /sbin/ifconfig $interface 0.0.0.0 up; then
+ /bin/false
+ rc_status -v
+ rc_exit
+ fi
+ if ! /sbin/brctl show | grep -E -q "^$EOE_BRIDGE.*$interface"; then
+ if ! /sbin/brctl addif $EOE_BRIDGE $interface; then
+ /bin/false
+ rc_status -v
+ rc_exit
+ fi
+ fi
+ done
+ if [ -n "$EOE_IP_ADDRESS" -a -n "$EOE_IP_NETMASK" ]; then
+ if ! /sbin/ifconfig $EOE_BRIDGE $EOE_IP_ADDRESS \
+ netmask $EOE_IP_NETMASK; then
+ /bin/false
+ rc_status -v
+ rc_exit
+ fi
+ fi
+ if ! /sbin/ifconfig $EOE_BRIDGE up; then
+ /bin/false
+ rc_status -v
+ rc_exit
+ fi
+ fi
+
rc_status -v
;;
--- a/script/install.sh Mon May 29 09:54:18 2006 +0000
+++ b/script/install.sh Mon Jun 26 15:04:06 2006 +0000
@@ -49,24 +49,11 @@
exit 1
fi
-#------------------------------------------------------------------------------
-
-# Copy files
-
-INSTALLDIR=/lib/modules/$KERNEL/kernel/drivers/net
-MODULES=(master/ec_master.ko devices/ec_8139too.ko)
-
echo "EtherCAT installer - Kernel: $KERNEL"
-echo " Installing modules"
-
-for mod in ${MODULES[*]}; do
- echo " $mod"
- cp $mod $INSTALLDIR || exit 1
-done
#------------------------------------------------------------------------------
-# Update dependencies
+# Update module dependencies
echo " Building module dependencies"
depmod
--- a/script/sysconfig Mon May 29 09:54:18 2006 +0000
+++ b/script/sysconfig Mon Jun 26 15:04:06 2006 +0000
@@ -18,4 +18,34 @@
#
#EOE_DEVICES=0
+#
+# Bridge all EoE interfaces after master startup
+# This variable shall contain the name of the EoE bridge to set up.
+# If the variable is empty or undefined, no EoE bridge will be built.
+#
+#EOE_BRIDGE=eoebr0
+
+#
+# IP address of the EoE bridge
+# Set both EOE_IP_ADDRESS and EOE_IP_NETMASK to let the local host communicate
+# with devices on the EoE bridge.
+#
+#EOE_IP_ADDRESS=192.168.X.X
+
+#
+# IP netmask of the EoE bridge
+# See EOE_IP_ADDRESS.
+#
+#EOE_IP_NETMASK=255.255.255.0
+
+#
+# List of extra interfaces to include in the EoE bridge.
+# Set this to interconnect the EoE bridge with other local interfaces.
+# If EOE_BRIDGE is empty or undefined, setting this variable has no effect.
+# Important: The IP address of these interfaces will be cleared. Set
+# EOE_IP_ADDRESS and EOE_IP_NETMASK accordingly to enable IP traffic to
+# extra interfaces.
+#
+#EOE_EXTRA_INTERFACES=eth0
+
#------------------------------------------------------------------------------