# HG changeset patch # User Florian Pose # Date 1171646019 0 # Node ID cdee4ea90ce9b73541e4f385761b9ebc20a97ce8 # Parent aef7ea866a41be609c760fb6547f73bb830d2442 Introduced device IDs; removed comment lines from 8139too; removed ec_eoeif_count parameter. diff -r aef7ea866a41 -r cdee4ea90ce9 NEWS --- a/NEWS Fri Feb 16 13:30:46 2007 +0000 +++ b/NEWS Fri Feb 16 17:13:39 2007 +0000 @@ -4,6 +4,24 @@ ------------------------------------------------------------------------------- +Changes in version 1.3.0: + +* Added Intel e100 ethernet driver. +* Removed "ec_eoeif_count" master module parameter. +* Introduced "device IDs" to tell a master to wait for certain ethernet + devices. +* Added "main" and "backup" parameters to master module. To hand over + device ID lists. +* Changed format of sysconfig file and accordingly adjusted functionality + of the init script to handle device IDs. +* Device interface changes: + - Replaced ecdev_register() and ecdev_unregister() with ecdev_offer() and + ecdev_withdraw(), respectively. The device modules now offer all their + devices to the master, which decides, which ones to register. +* Removed EtherCAT line comments from 8139too drivers. + +------------------------------------------------------------------------------- + Changes in version 1.2.0: * Serveral fixes of bugs and stability issues. Master should now run fine diff -r aef7ea866a41 -r cdee4ea90ce9 devices/8139too-2.6.13-ethercat.c --- a/devices/8139too-2.6.13-ethercat.c Fri Feb 16 13:30:46 2007 +0000 +++ b/devices/8139too-2.6.13-ethercat.c Fri Feb 16 17:13:39 2007 +0000 @@ -153,8 +153,6 @@ #include #include -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #include "../globals.h" #include "ecdev.h" @@ -162,8 +160,6 @@ " EtherCAT-capable Fast Ethernet driver " \ DRV_VERSION ", master " EC_MASTER_VERSION -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - #define PFX DRV_NAME ": " /* Default Message level */ @@ -215,15 +211,6 @@ /* bitmapped message enable number */ static int debug = -1; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -static int ec_device_index = -1; -static int ec_device_master_index = 0; -static ec_device_t *rtl_ec_dev; -struct net_device *rtl_ec_net_dev = NULL; - -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* * Receive ring size * Warning: 64K ring has hardware issues and may lock up. @@ -338,13 +325,9 @@ {0,} }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - /* prevent driver from being loaded automatically */ //MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static struct { const char str[ETH_GSTRING_LEN]; } ethtool_stats_keys[] = { @@ -664,17 +647,15 @@ struct mii_if_info mii; unsigned int regs_len; unsigned long fifo_copy_timeout; + + ec_device_t *ecdev; }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - MODULE_AUTHOR("Florian Pose "); MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - module_param(multicast_filter_limit, int, 0); module_param_array(media, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); @@ -684,19 +665,8 @@ MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -module_param(ec_device_index, int, -1); -module_param(ec_device_master_index, int, 0); -MODULE_PARM_DESC(ec_device_index, - "Index of the device reserved for EtherCAT."); -MODULE_PARM_DESC(ec_device_master_index, - "Index of the EtherCAT master to register the device."); - void ec_poll(struct net_device *); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); @@ -1046,15 +1016,6 @@ assert (dev != NULL); tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (board_idx == ec_device_index) { - rtl_ec_net_dev = dev; - strcpy(dev->name, "ec0"); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - ioaddr = tp->mmio_addr; assert (ioaddr != NULL); @@ -1106,17 +1067,20 @@ tp->mii.reg_num_mask = 0x1f; /* dev is fully set up and ready to use now */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + + // offer device to EtherCAT master module + if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, + ec_poll, THIS_MODULE)) { + printk(KERN_ERR PFX "Failed to offer device.\n"); + goto err_out; + } + + if (!tp->ecdev) { DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); i = register_netdev (dev); if (i) goto err_out; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_drvdata (pdev, dev); printk (KERN_INFO "%s: %s at 0x%lx, " @@ -1189,6 +1153,11 @@ if (rtl_chip_info[tp->chipset].flags & HasHltClk) RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ + if (tp->ecdev && ecdev_open(tp->ecdev)) { + ecdev_withdraw(tp->ecdev); + goto err_out; + } + return 0; err_out: @@ -1201,17 +1170,18 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); assert (dev != NULL); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_close(tp->ecdev); + ecdev_withdraw(tp->ecdev); + } + else { unregister_netdev (dev); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - __rtl8139_cleanup_dev (dev); pci_disable_device (pdev); } @@ -1412,30 +1382,19 @@ int retval; void __iomem *ioaddr = tp->mmio_addr; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { retval = request_irq(dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); if (retval) return retval; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, &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->ecdev) free_irq(dev->irq, dev); if (tp->tx_bufs) pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, tp->tx_bufs, tp->tx_bufs_dma); @@ -1453,9 +1412,7 @@ rtl8139_init_ring (dev); rtl8139_hw_start (dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { netif_start_queue (dev); if (netif_msg_ifup(tp)) @@ -1468,8 +1425,6 @@ rtl8139_start_thread(dev); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return 0; } @@ -1478,19 +1433,16 @@ { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + void __iomem *ioaddr = tp->mmio_addr; + uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; + ecdev_link_state(tp->ecdev, state ? 1 : 0); + } + else { 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } /* Start the hardware at open or resume. */ @@ -1555,14 +1507,9 @@ if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16 (IntrMask, rtl8139_intr_mask); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } @@ -1821,30 +1768,27 @@ if (tmp8 & CmdTxEnb) RTL_W8 (ChipCmd, CmdRxEnb); - /* 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); - } else { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (tp->ecdev) { + rtl8139_tx_clear (tp); + rtl8139_hw_start (dev); + } + else { + 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); + } } @@ -1858,30 +1802,19 @@ /* 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); - } + if (!tp->ecdev) dev_kfree_skb(skb); } else { - if (dev != rtl_ec_net_dev) { - dev_kfree_skb(skb); - } + if (!tp->ecdev) dev_kfree_skb(skb); tp->stats.tx_dropped++; return 0; } - if (dev != rtl_ec_net_dev) { - spin_lock_irq(&tp->lock); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - + if (!tp->ecdev) spin_lock_irq(&tp->lock); RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); @@ -1890,9 +1823,7 @@ tp->cur_tx++; wmb(); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) netif_stop_queue (dev); spin_unlock_irq(&tp->lock); @@ -1902,8 +1833,6 @@ dev->name, len, entry); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return 0; } @@ -1961,10 +1890,8 @@ tx_left--; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #ifndef RTL8139_NDEBUG - if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { + if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", dev->name, dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; @@ -1975,13 +1902,8 @@ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; mb(); - - if (dev != rtl_ec_net_dev) { - netif_wake_queue (dev); - } - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) netif_wake_queue (dev); + } } @@ -2114,15 +2036,9 @@ RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - while ((dev == rtl_ec_net_dev || netif_running(dev)) + while ((tp->ecdev || 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; @@ -2135,17 +2051,12 @@ rx_size = rx_status >> 16; pkt_size = rx_size - 4; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { 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 { int i; @@ -2193,9 +2104,14 @@ goto out; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_receive(tp->ecdev, + &rx_ring[ring_offset + 4], pkt_size); + dev->last_rx = jiffies; + tp->stats.rx_bytes += pkt_size; + tp->stats.rx_packets++; + } + else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ @@ -2220,20 +2136,11 @@ } else { if (net_ratelimit()) printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); + "%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++; cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; @@ -2339,19 +2246,15 @@ return !done; } -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - void ec_poll(struct net_device *dev) { rtl8139_interrupt(0, dev, NULL); } -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, + struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; struct rtl8139_private *tp = netdev_priv(dev); @@ -2360,20 +2263,17 @@ int link_changed = 0; /* avoid bogus "uninit" warning */ int handled = 0; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + status = RTL_R16 (IntrStatus); + } + else { 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; @@ -2381,9 +2281,7 @@ if (unlikely(status == 0xFFFF)) goto out; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { /* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) { RTL_W16 (IntrMask, 0); @@ -2391,8 +2289,6 @@ } } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Acknowledge all of the current interrupt sources ASAP, but an first get an additional status bit from CSCR. */ if (unlikely(status & RxUnderrun)) @@ -2404,24 +2300,20 @@ /* Receive packets are processed by poll routine. If not running start it now. */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - if (status & RxAckBits){ - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* EtherCAT device: Just receive all frames */ + rtl8139_rx(dev, tp, 100); // FIXME + } + else { /* 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Check uncommon events with one test. */ if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) rtl8139_weird_interrupt (dev, tp, ioaddr, @@ -2433,14 +2325,7 @@ RTL_W16 (IntrStatus, TxErr); } out: - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { - spin_unlock (&tp->lock); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) spin_unlock (&tp->lock); DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); @@ -2467,9 +2352,17 @@ int ret = 0; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* 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); + } else { netif_stop_queue (dev); if (tp->thr_pid >= 0) { @@ -2503,19 +2396,7 @@ 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); @@ -2730,13 +2611,9 @@ struct rtl8139_private *np = netdev_priv(dev); int rc; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running(dev)) + if (np->ecdev || !netif_running(dev)) return -EINVAL; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - spin_lock_irq(&np->lock); rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); spin_unlock_irq(&np->lock); @@ -2751,17 +2628,13 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || netif_running(dev)) { + if (tp->ecdev || 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return &tp->stats; } @@ -2837,13 +2710,9 @@ pci_save_state (pdev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - netif_device_detach (dev); spin_lock_irqsave (&tp->lock, flags); @@ -2867,16 +2736,11 @@ static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); pci_restore_state (pdev); - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_power_state (pdev, PCI_D0); rtl8139_init_ring (dev); rtl8139_hw_start (dev); @@ -2901,69 +2765,20 @@ static int __init rtl8139_init_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO RTL8139_DRIVER_NAME "\n"); - printk(KERN_INFO "ec_device_index is %i\n", ec_device_index); - - if (pci_module_init(&rtl8139_pci_driver) < 0) { - printk(KERN_ERR "Failed to init PCI module.\n"); - goto out_return; - } - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Registering EtherCAT device...\n"); - if (!(rtl_ec_dev = ecdev_register(ec_device_master_index, - rtl_ec_net_dev, ec_poll, THIS_MODULE))) { - printk(KERN_ERR "Failed to register EtherCAT device!\n"); - goto out_pci; - } - - printk(KERN_INFO "Opening EtherCAT device...\n"); - if (ecdev_open(rtl_ec_dev)) { - printk(KERN_ERR "Failed to open EtherCAT device!\n"); - goto out_unregister; - } - - printk(KERN_INFO "EtherCAT device ready.\n"); - } else { - printk(KERN_WARNING "No EtherCAT device registered!\n"); - } - - return 0; - - out_unregister: - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - out_pci: - pci_unregister_driver(&rtl8139_pci_driver); - out_return: - return -1; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + /* when we're a module, we always print a version message, + * even if no 8139 board is found. + */ +#ifdef MODULE + printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); +#endif + + return pci_module_init (&rtl8139_pci_driver); } static void __exit rtl8139_cleanup_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n"); - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Closing EtherCAT device...\n"); - ecdev_close(rtl_ec_dev); - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - } - - pci_unregister_driver(&rtl8139_pci_driver); - - printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n"); - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + pci_unregister_driver (&rtl8139_pci_driver); } diff -r aef7ea866a41 -r cdee4ea90ce9 devices/8139too-2.6.17-ethercat.c --- a/devices/8139too-2.6.17-ethercat.c Fri Feb 16 13:30:46 2007 +0000 +++ b/devices/8139too-2.6.17-ethercat.c Fri Feb 16 17:13:39 2007 +0000 @@ -153,8 +153,6 @@ #include #include -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #include "../globals.h" #include "ecdev.h" @@ -162,8 +160,6 @@ " EtherCAT-capable Fast Ethernet driver " \ DRV_VERSION ", master " EC_MASTER_VERSION -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - #define PFX DRV_NAME ": " /* Default Message level */ @@ -215,15 +211,6 @@ /* bitmapped message enable number */ static int debug = -1; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -static int ec_device_index = -1; -static int ec_device_master_index = 0; -static ec_device_t *rtl_ec_dev; -struct net_device *rtl_ec_net_dev = NULL; - -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* * Receive ring size * Warning: 64K ring has hardware issues and may lock up. @@ -338,13 +325,9 @@ {0,} }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - /* prevent driver from being loaded automatically */ //MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static struct { const char str[ETH_GSTRING_LEN]; } ethtool_stats_keys[] = { @@ -666,17 +649,15 @@ struct mii_if_info mii; unsigned int regs_len; unsigned long fifo_copy_timeout; + + ec_device_t *ecdev; }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - MODULE_AUTHOR("Florian Pose "); MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - module_param(multicast_filter_limit, int, 0); module_param_array(media, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); @@ -686,19 +667,8 @@ MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -module_param(ec_device_index, int, -1); -module_param(ec_device_master_index, int, 0); -MODULE_PARM_DESC(ec_device_index, - "Index of the device reserved for EtherCAT."); -MODULE_PARM_DESC(ec_device_master_index, - "Index of the EtherCAT master to register the device."); - void ec_poll(struct net_device *); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); @@ -1050,15 +1020,6 @@ assert (dev != NULL); tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (board_idx == ec_device_index) { - rtl_ec_net_dev = dev; - strcpy(dev->name, "ec0"); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - ioaddr = tp->mmio_addr; assert (ioaddr != NULL); @@ -1110,17 +1071,20 @@ tp->mii.reg_num_mask = 0x1f; /* dev is fully set up and ready to use now */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + + // offer device to EtherCAT master module + if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, + ec_poll, THIS_MODULE)) { + printk(KERN_ERR PFX "Failed to offer device.\n"); + goto err_out; + } + + if (!tp->ecdev) { DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); i = register_netdev (dev); if (i) goto err_out; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_drvdata (pdev, dev); printk (KERN_INFO "%s: %s at 0x%lx, " @@ -1193,6 +1157,11 @@ if (rtl_chip_info[tp->chipset].flags & HasHltClk) RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ + if (tp->ecdev && ecdev_open(tp->ecdev)) { + ecdev_withdraw(tp->ecdev); + goto err_out; + } + return 0; err_out: @@ -1205,17 +1174,18 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); assert (dev != NULL); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_close(tp->ecdev); + ecdev_withdraw(tp->ecdev); + } + else { unregister_netdev (dev); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - __rtl8139_cleanup_dev (dev); pci_disable_device (pdev); } @@ -1416,30 +1386,19 @@ int retval; void __iomem *ioaddr = tp->mmio_addr; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { retval = request_irq(dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); if (retval) return retval; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, &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->ecdev) free_irq(dev->irq, dev); if (tp->tx_bufs) pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, tp->tx_bufs, tp->tx_bufs_dma); @@ -1457,9 +1416,7 @@ rtl8139_init_ring (dev); rtl8139_hw_start (dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { netif_start_queue (dev); if (netif_msg_ifup(tp)) @@ -1472,8 +1429,6 @@ rtl8139_start_thread(tp); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return 0; } @@ -1482,19 +1437,16 @@ { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + void __iomem *ioaddr = tp->mmio_addr; + uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; + ecdev_link_state(tp->ecdev, state ? 1 : 0); + } + else { 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } /* Start the hardware at open or resume. */ @@ -1559,14 +1511,9 @@ if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16 (IntrMask, rtl8139_intr_mask); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } @@ -1814,9 +1761,11 @@ if (tmp8 & CmdTxEnb) RTL_W8 (ChipCmd, CmdRxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + rtl8139_tx_clear (tp); + rtl8139_hw_start (dev); + } + else { spin_lock_bh(&tp->rx_lock); /* Disable interrupts by clearing the interrupt mask. */ RTL_W16 (IntrMask, 0x0000); @@ -1832,27 +1781,19 @@ netif_wake_queue (dev); } spin_unlock_bh(&tp->rx_lock); - } else { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } static void rtl8139_tx_timeout (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev && !tp->have_thread) { + if (!tp->ecdev && !tp->have_thread) { INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); schedule_delayed_work(&tp->thread, next_tick); } else tp->watchdog_fired = 1; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) @@ -1865,30 +1806,19 @@ /* 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); - } + if (!tp->ecdev) dev_kfree_skb(skb); } else { - if (dev != rtl_ec_net_dev) { - dev_kfree_skb(skb); - } + if (!tp->ecdev) dev_kfree_skb(skb); tp->stats.tx_dropped++; return 0; } - if (dev != rtl_ec_net_dev) { - spin_lock_irq(&tp->lock); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - + if (!tp->ecdev) spin_lock_irq(&tp->lock); RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); @@ -1897,9 +1827,7 @@ tp->cur_tx++; wmb(); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) netif_stop_queue (dev); spin_unlock_irq(&tp->lock); @@ -1909,8 +1837,6 @@ dev->name, len, entry); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return 0; } @@ -1968,10 +1894,8 @@ tx_left--; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #ifndef RTL8139_NDEBUG - if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { + if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", dev->name, dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; @@ -1982,13 +1906,8 @@ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; mb(); - - if (dev != rtl_ec_net_dev) { - netif_wake_queue (dev); - } - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) netif_wake_queue (dev); + } } @@ -2121,15 +2040,9 @@ RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - while ((dev == rtl_ec_net_dev || netif_running(dev)) + while ((tp->ecdev || 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; @@ -2142,17 +2055,12 @@ rx_size = rx_status >> 16; pkt_size = rx_size - 4; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { 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 { int i; @@ -2200,9 +2108,14 @@ goto out; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_receive(tp->ecdev, + &rx_ring[ring_offset + 4], pkt_size); + dev->last_rx = jiffies; + tp->stats.rx_bytes += pkt_size; + tp->stats.rx_packets++; + } + else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ @@ -2227,20 +2140,11 @@ } else { if (net_ratelimit()) printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); + "%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++; cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; @@ -2346,19 +2250,15 @@ return !done; } -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - void ec_poll(struct net_device *dev) { rtl8139_interrupt(0, dev, NULL); } -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, + struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; struct rtl8139_private *tp = netdev_priv(dev); @@ -2367,20 +2267,17 @@ int link_changed = 0; /* avoid bogus "uninit" warning */ int handled = 0; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + status = RTL_R16 (IntrStatus); + } + else { 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; @@ -2388,9 +2285,7 @@ if (unlikely(status == 0xFFFF)) goto out; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { /* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) { RTL_W16 (IntrMask, 0); @@ -2398,8 +2293,6 @@ } } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Acknowledge all of the current interrupt sources ASAP, but an first get an additional status bit from CSCR. */ if (unlikely(status & RxUnderrun)) @@ -2411,24 +2304,20 @@ /* Receive packets are processed by poll routine. If not running start it now. */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - if (status & RxAckBits){ - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* EtherCAT device: Just receive all frames */ + rtl8139_rx(dev, tp, 100); // FIXME + } + else { /* 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Check uncommon events with one test. */ if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) rtl8139_weird_interrupt (dev, tp, ioaddr, @@ -2440,14 +2329,7 @@ RTL_W16 (IntrStatus, TxErr); } out: - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { - spin_unlock (&tp->lock); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) spin_unlock (&tp->lock); DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); @@ -2473,9 +2355,17 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* 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); + } else { netif_stop_queue (dev); rtl8139_stop_thread(tp); @@ -2500,19 +2390,7 @@ 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); @@ -2728,13 +2606,9 @@ struct rtl8139_private *np = netdev_priv(dev); int rc; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running(dev)) + if (np->ecdev || !netif_running(dev)) return -EINVAL; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - spin_lock_irq(&np->lock); rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); spin_unlock_irq(&np->lock); @@ -2749,17 +2623,13 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || netif_running(dev)) { + if (tp->ecdev || 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return &tp->stats; } @@ -2835,13 +2705,9 @@ pci_save_state (pdev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - netif_device_detach (dev); spin_lock_irqsave (&tp->lock, flags); @@ -2865,16 +2731,11 @@ static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); pci_restore_state (pdev); - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_power_state (pdev, PCI_D0); rtl8139_init_ring (dev); rtl8139_hw_start (dev); @@ -2899,69 +2760,20 @@ static int __init rtl8139_init_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO RTL8139_DRIVER_NAME "\n"); - printk(KERN_INFO "ec_device_index is %i\n", ec_device_index); - - if (pci_module_init(&rtl8139_pci_driver) < 0) { - printk(KERN_ERR "Failed to init PCI module.\n"); - goto out_return; - } - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Registering EtherCAT device...\n"); - if (!(rtl_ec_dev = ecdev_register(ec_device_master_index, - rtl_ec_net_dev, ec_poll, THIS_MODULE))) { - printk(KERN_ERR "Failed to register EtherCAT device!\n"); - goto out_pci; - } - - printk(KERN_INFO "Opening EtherCAT device...\n"); - if (ecdev_open(rtl_ec_dev)) { - printk(KERN_ERR "Failed to open EtherCAT device!\n"); - goto out_unregister; - } - - printk(KERN_INFO "EtherCAT device ready.\n"); - } else { - printk(KERN_WARNING "No EtherCAT device registered!\n"); - } - - return 0; - - out_unregister: - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - out_pci: - pci_unregister_driver(&rtl8139_pci_driver); - out_return: - return -1; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + /* when we're a module, we always print a version message, + * even if no 8139 board is found. + */ +#ifdef MODULE + printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); +#endif + + return pci_module_init (&rtl8139_pci_driver); } static void __exit rtl8139_cleanup_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n"); - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Closing EtherCAT device...\n"); - ecdev_close(rtl_ec_dev); - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - } - - pci_unregister_driver(&rtl8139_pci_driver); - - printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n"); - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + pci_unregister_driver (&rtl8139_pci_driver); } diff -r aef7ea866a41 -r cdee4ea90ce9 devices/8139too-2.6.18-ethercat.c --- a/devices/8139too-2.6.18-ethercat.c Fri Feb 16 13:30:46 2007 +0000 +++ b/devices/8139too-2.6.18-ethercat.c Fri Feb 16 17:13:39 2007 +0000 @@ -152,8 +152,6 @@ #include #include -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #include "../globals.h" #include "ecdev.h" @@ -161,8 +159,6 @@ " EtherCAT-capable Fast Ethernet driver " \ DRV_VERSION ", master " EC_MASTER_VERSION -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - #define PFX DRV_NAME ": " /* Default Message level */ @@ -214,15 +210,6 @@ /* bitmapped message enable number */ static int debug = -1; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -static int ec_device_index = -1; -static int ec_device_master_index = 0; -static ec_device_t *rtl_ec_dev; -struct net_device *rtl_ec_net_dev = NULL; - -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* * Receive ring size * Warning: 64K ring has hardware issues and may lock up. @@ -337,13 +324,9 @@ {0,} }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - /* prevent driver from being loaded automatically */ //MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static struct { const char str[ETH_GSTRING_LEN]; } ethtool_stats_keys[] = { @@ -665,17 +648,15 @@ struct mii_if_info mii; unsigned int regs_len; unsigned long fifo_copy_timeout; + + ec_device_t *ecdev; }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - MODULE_AUTHOR("Florian Pose "); MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - module_param(multicast_filter_limit, int, 0); module_param_array(media, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); @@ -685,19 +666,8 @@ MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -module_param(ec_device_index, int, -1); -module_param(ec_device_master_index, int, 0); -MODULE_PARM_DESC(ec_device_index, - "Index of the device reserved for EtherCAT."); -MODULE_PARM_DESC(ec_device_master_index, - "Index of the EtherCAT master to register the device."); - void ec_poll(struct net_device *); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); @@ -1051,15 +1021,6 @@ assert (dev != NULL); tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (board_idx == ec_device_index) { - rtl_ec_net_dev = dev; - strcpy(dev->name, "ec0"); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - ioaddr = tp->mmio_addr; assert (ioaddr != NULL); @@ -1111,17 +1072,20 @@ tp->mii.reg_num_mask = 0x1f; /* dev is fully set up and ready to use now */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + + // offer device to EtherCAT master module + if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, + ec_poll, THIS_MODULE)) { + printk(KERN_ERR PFX "Failed to offer device.\n"); + goto err_out; + } + + if (!tp->ecdev) { DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); i = register_netdev (dev); if (i) goto err_out; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_drvdata (pdev, dev); printk (KERN_INFO "%s: %s at 0x%lx, " @@ -1194,6 +1158,11 @@ if (rtl_chip_info[tp->chipset].flags & HasHltClk) RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ + if (tp->ecdev && ecdev_open(tp->ecdev)) { + ecdev_withdraw(tp->ecdev); + goto err_out; + } + return 0; err_out: @@ -1206,17 +1175,18 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); assert (dev != NULL); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_close(tp->ecdev); + ecdev_withdraw(tp->ecdev); + } + else { unregister_netdev (dev); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - __rtl8139_cleanup_dev (dev); pci_disable_device (pdev); } @@ -1417,29 +1387,19 @@ int retval; void __iomem *ioaddr = tp->mmio_addr; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { retval = request_irq(dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); if (retval) return retval; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, &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->ecdev) free_irq(dev->irq, dev); if (tp->tx_bufs) pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, @@ -1458,9 +1418,7 @@ rtl8139_init_ring (dev); rtl8139_hw_start (dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { netif_start_queue (dev); if (netif_msg_ifup(tp)) @@ -1472,8 +1430,6 @@ rtl8139_start_thread(tp); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return 0; } @@ -1482,19 +1438,16 @@ { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + void __iomem *ioaddr = tp->mmio_addr; + uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; + ecdev_link_state(tp->ecdev, state ? 1 : 0); + } + else { 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } /* Start the hardware at open or resume. */ @@ -1559,14 +1512,9 @@ if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16 (IntrMask, rtl8139_intr_mask); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } @@ -1814,9 +1762,11 @@ if (tmp8 & CmdTxEnb) RTL_W8 (ChipCmd, CmdRxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + rtl8139_tx_clear (tp); + rtl8139_hw_start (dev); + } + else { spin_lock_bh(&tp->rx_lock); /* Disable interrupts by clearing the interrupt mask. */ RTL_W16 (IntrMask, 0x0000); @@ -1832,27 +1782,19 @@ netif_wake_queue (dev); } spin_unlock_bh(&tp->rx_lock); - } else { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } static void rtl8139_tx_timeout (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev && !tp->have_thread) { + if (!tp->ecdev && !tp->have_thread) { INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); schedule_delayed_work(&tp->thread, next_tick); } else tp->watchdog_fired = 1; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) @@ -1866,27 +1808,28 @@ /* 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); - } + if (!tp->ecdev) dev_kfree_skb(skb); } else { - if (dev != rtl_ec_net_dev) { - dev_kfree_skb(skb); - } + if (!tp->ecdev) dev_kfree_skb(skb); tp->stats.tx_dropped++; return 0; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), + tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); + + dev->trans_start = jiffies; + + tp->cur_tx++; + wmb(); + } + else { spin_lock_irqsave(&tp->lock, flags); RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), @@ -1905,17 +1848,6 @@ printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", dev->name, len, entry); } - else { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ return 0; } @@ -1974,10 +1906,8 @@ tx_left--; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #ifndef RTL8139_NDEBUG - if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { + if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", dev->name, dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; @@ -1988,13 +1918,8 @@ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; mb(); - - if (dev != rtl_ec_net_dev) { - netif_wake_queue (dev); - } - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) netif_wake_queue (dev); + } } @@ -2127,14 +2052,9 @@ RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - while ((dev == rtl_ec_net_dev || netif_running(dev)) + while ((tp->ecdev || 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; @@ -2147,17 +2067,12 @@ rx_size = rx_status >> 16; pkt_size = rx_size - 4; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { 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 { int i; @@ -2205,9 +2120,14 @@ goto out; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_receive(tp->ecdev, + &rx_ring[ring_offset + 4], pkt_size); + dev->last_rx = jiffies; + tp->stats.rx_bytes += pkt_size; + tp->stats.rx_packets++; + } + else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ @@ -2232,20 +2152,11 @@ } else { if (net_ratelimit()) printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); + "%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++; cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; @@ -2351,19 +2262,15 @@ return !done; } -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - void ec_poll(struct net_device *dev) { rtl8139_interrupt(0, dev, NULL); } -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, + struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; struct rtl8139_private *tp = netdev_priv(dev); @@ -2372,20 +2279,17 @@ int link_changed = 0; /* avoid bogus "uninit" warning */ int handled = 0; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + status = RTL_R16 (IntrStatus); + } + else { 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; @@ -2393,9 +2297,7 @@ if (unlikely(status == 0xFFFF)) goto out; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { /* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) { RTL_W16 (IntrMask, 0); @@ -2403,8 +2305,6 @@ } } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Acknowledge all of the current interrupt sources ASAP, but an first get an additional status bit from CSCR. */ if (unlikely(status & RxUnderrun)) @@ -2416,24 +2316,20 @@ /* Receive packets are processed by poll routine. If not running start it now. */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - if (status & RxAckBits){ - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* EtherCAT device: Just receive all frames */ + rtl8139_rx(dev, tp, 100); // FIXME + } + else { /* 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Check uncommon events with one test. */ if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) rtl8139_weird_interrupt (dev, tp, ioaddr, @@ -2445,14 +2341,7 @@ RTL_W16 (IntrStatus, TxErr); } out: - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { - spin_unlock (&tp->lock); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) spin_unlock (&tp->lock); DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); @@ -2478,9 +2367,17 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* 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); + } else { netif_stop_queue (dev); rtl8139_stop_thread(tp); @@ -2505,19 +2402,7 @@ 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,13 +2618,9 @@ struct rtl8139_private *np = netdev_priv(dev); int rc; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running(dev)) + if (np->ecdev || !netif_running(dev)) return -EINVAL; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - spin_lock_irq(&np->lock); rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); spin_unlock_irq(&np->lock); @@ -2754,17 +2635,13 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || netif_running(dev)) { + if (tp->ecdev || 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return &tp->stats; } @@ -2840,13 +2717,9 @@ pci_save_state (pdev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - netif_device_detach (dev); spin_lock_irqsave (&tp->lock, flags); @@ -2870,16 +2743,11 @@ static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); pci_restore_state (pdev); - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_power_state (pdev, PCI_D0); rtl8139_init_ring (dev); rtl8139_hw_start (dev); @@ -2904,69 +2772,20 @@ static int __init rtl8139_init_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO RTL8139_DRIVER_NAME "\n"); - printk(KERN_INFO "ec_device_index is %i\n", ec_device_index); - - if (pci_module_init(&rtl8139_pci_driver) < 0) { - printk(KERN_ERR "Failed to init PCI module.\n"); - goto out_return; - } - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Registering EtherCAT device...\n"); - if (!(rtl_ec_dev = ecdev_register(ec_device_master_index, - rtl_ec_net_dev, ec_poll, THIS_MODULE))) { - printk(KERN_ERR "Failed to register EtherCAT device!\n"); - goto out_pci; - } - - printk(KERN_INFO "Opening EtherCAT device...\n"); - if (ecdev_open(rtl_ec_dev)) { - printk(KERN_ERR "Failed to open EtherCAT device!\n"); - goto out_unregister; - } - - printk(KERN_INFO "EtherCAT device ready.\n"); - } else { - printk(KERN_WARNING "No EtherCAT device registered!\n"); - } - - return 0; - - out_unregister: - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - out_pci: - pci_unregister_driver(&rtl8139_pci_driver); - out_return: - return -1; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + /* when we're a module, we always print a version message, + * even if no 8139 board is found. + */ +#ifdef MODULE + printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); +#endif + + return pci_module_init (&rtl8139_pci_driver); } static void __exit rtl8139_cleanup_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n"); - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Closing EtherCAT device...\n"); - ecdev_close(rtl_ec_dev); - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - } - - pci_unregister_driver(&rtl8139_pci_driver); - - printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n"); - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + pci_unregister_driver (&rtl8139_pci_driver); } diff -r aef7ea866a41 -r cdee4ea90ce9 devices/8139too-2.6.19-ethercat.c --- a/devices/8139too-2.6.19-ethercat.c Fri Feb 16 13:30:46 2007 +0000 +++ b/devices/8139too-2.6.19-ethercat.c Fri Feb 16 17:13:39 2007 +0000 @@ -152,8 +152,6 @@ #include #include -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #include "../globals.h" #include "ecdev.h" @@ -161,8 +159,6 @@ " EtherCAT-capable Fast Ethernet driver " \ DRV_VERSION ", master " EC_MASTER_VERSION -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - #define PFX DRV_NAME ": " /* Default Message level */ @@ -214,15 +210,6 @@ /* bitmapped message enable number */ static int debug = -1; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -static int ec_device_index = -1; -static int ec_device_master_index = 0; -static ec_device_t *rtl_ec_dev; -struct net_device *rtl_ec_net_dev = NULL; - -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* * Receive ring size * Warning: 64K ring has hardware issues and may lock up. @@ -337,13 +324,9 @@ {0,} }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - /* prevent driver from being loaded automatically */ //MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static struct { const char str[ETH_GSTRING_LEN]; } ethtool_stats_keys[] = { @@ -665,17 +648,15 @@ struct mii_if_info mii; unsigned int regs_len; unsigned long fifo_copy_timeout; + + ec_device_t *ecdev; }; -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - MODULE_AUTHOR("Florian Pose "); MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - module_param(multicast_filter_limit, int, 0); module_param_array(media, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); @@ -685,19 +666,8 @@ MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)"); -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -module_param(ec_device_index, int, -1); -module_param(ec_device_master_index, int, 0); -MODULE_PARM_DESC(ec_device_index, - "Index of the device reserved for EtherCAT."); -MODULE_PARM_DESC(ec_device_master_index, - "Index of the EtherCAT master to register the device."); - void ec_poll(struct net_device *); -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - static int read_eeprom (void __iomem *ioaddr, int location, int addr_len); static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); @@ -1050,15 +1020,6 @@ assert (dev != NULL); tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (board_idx == ec_device_index) { - rtl_ec_net_dev = dev; - strcpy(dev->name, "ec0"); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - ioaddr = tp->mmio_addr; assert (ioaddr != NULL); @@ -1110,17 +1071,20 @@ tp->mii.reg_num_mask = 0x1f; /* dev is fully set up and ready to use now */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + + // offer device to EtherCAT master module + if (ecdev_offer(dev, &tp->ecdev, "8139too", board_idx, + ec_poll, THIS_MODULE)) { + printk(KERN_ERR PFX "Failed to offer device.\n"); + goto err_out; + } + + if (!tp->ecdev) { DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); i = register_netdev (dev); if (i) goto err_out; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_drvdata (pdev, dev); printk (KERN_INFO "%s: %s at 0x%lx, " @@ -1193,6 +1157,11 @@ if (rtl_chip_info[tp->chipset].flags & HasHltClk) RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ + if (tp->ecdev && ecdev_open(tp->ecdev)) { + ecdev_withdraw(tp->ecdev); + goto err_out; + } + return 0; err_out: @@ -1205,17 +1174,18 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); assert (dev != NULL); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_close(tp->ecdev); + ecdev_withdraw(tp->ecdev); + } + else { unregister_netdev (dev); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - __rtl8139_cleanup_dev (dev); pci_disable_device (pdev); } @@ -1416,29 +1386,19 @@ int retval; void __iomem *ioaddr = tp->mmio_addr; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { retval = request_irq(dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); if (retval) return retval; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, &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->ecdev) free_irq(dev->irq, dev); if (tp->tx_bufs) pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN, @@ -1457,9 +1417,7 @@ rtl8139_init_ring (dev); rtl8139_hw_start (dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { netif_start_queue (dev); if (netif_msg_ifup(tp)) @@ -1471,8 +1429,6 @@ rtl8139_start_thread(tp); } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return 0; } @@ -1481,19 +1437,16 @@ { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + void __iomem *ioaddr = tp->mmio_addr; + uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS; + ecdev_link_state(tp->ecdev, state ? 1 : 0); + } + else { 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } /* Start the hardware at open or resume. */ @@ -1558,14 +1511,9 @@ if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb))) RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16 (IntrMask, rtl8139_intr_mask); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } @@ -1813,9 +1761,11 @@ if (tmp8 & CmdTxEnb) RTL_W8 (ChipCmd, CmdRxEnb); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + rtl8139_tx_clear (tp); + rtl8139_hw_start (dev); + } + else { spin_lock_bh(&tp->rx_lock); /* Disable interrupts by clearing the interrupt mask. */ RTL_W16 (IntrMask, 0x0000); @@ -1831,27 +1781,19 @@ netif_wake_queue (dev); } spin_unlock_bh(&tp->rx_lock); - } else { - rtl8139_tx_clear (tp); - rtl8139_hw_start (dev); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + } } static void rtl8139_tx_timeout (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev && !tp->have_thread) { + if (!tp->ecdev && !tp->have_thread) { INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); schedule_delayed_work(&tp->thread, next_tick); } else tp->watchdog_fired = 1; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ } static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) @@ -1865,27 +1807,28 @@ /* 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); - } + if (!tp->ecdev) dev_kfree_skb(skb); } else { - if (dev != rtl_ec_net_dev) { - dev_kfree_skb(skb); - } + if (!tp->ecdev) dev_kfree_skb(skb); tp->stats.tx_dropped++; return 0; } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), + tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); + + dev->trans_start = jiffies; + + tp->cur_tx++; + wmb(); + } + else { spin_lock_irqsave(&tp->lock, flags); RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), @@ -1904,17 +1847,6 @@ printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n", dev->name, len, entry); } - else { - RTL_W32_F (TxStatus0 + (entry * sizeof (u32)), - tp->tx_flag | max(len, (unsigned int)ETH_ZLEN)); - - dev->trans_start = jiffies; - - tp->cur_tx++; - wmb(); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ return 0; } @@ -1973,10 +1905,8 @@ tx_left--; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #ifndef RTL8139_NDEBUG - if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { + if (!tp->ecdev && tp->cur_tx - dirty_tx > NUM_TX_DESC) { printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", dev->name, dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; @@ -1987,13 +1917,8 @@ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; mb(); - - if (dev != rtl_ec_net_dev) { - netif_wake_queue (dev); - } - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) netif_wake_queue (dev); + } } @@ -2126,14 +2051,9 @@ RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - while ((dev == rtl_ec_net_dev || netif_running(dev)) + while ((tp->ecdev || 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; @@ -2146,17 +2066,12 @@ rx_size = rx_status >> 16; pkt_size = rx_size - 4; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { 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 { int i; @@ -2204,9 +2119,14 @@ goto out; } - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + ecdev_receive(tp->ecdev, + &rx_ring[ring_offset + 4], pkt_size); + dev->last_rx = jiffies; + tp->stats.rx_bytes += pkt_size; + tp->stats.rx_packets++; + } + else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ @@ -2231,20 +2151,11 @@ } else { if (net_ratelimit()) printk(KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); + "%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++; cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; @@ -2350,15 +2261,11 @@ return !done; } -/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - void ec_poll(struct net_device *dev) { rtl8139_interrupt(0, dev); } -/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) @@ -2370,20 +2277,17 @@ int link_changed = 0; /* avoid bogus "uninit" warning */ int handled = 0; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + status = RTL_R16 (IntrStatus); + } + else { 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; @@ -2391,9 +2295,7 @@ if (unlikely(status == 0xFFFF)) goto out; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (!tp->ecdev) { /* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) { RTL_W16 (IntrMask, 0); @@ -2401,8 +2303,6 @@ } } - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Acknowledge all of the current interrupt sources ASAP, but an first get an additional status bit from CSCR. */ if (unlikely(status & RxUnderrun)) @@ -2414,24 +2314,20 @@ /* Receive packets are processed by poll routine. If not running start it now. */ - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - if (status & RxAckBits){ - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* EtherCAT device: Just receive all frames */ + rtl8139_rx(dev, tp, 100); // FIXME + } + else { /* 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - /* Check uncommon events with one test. */ if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr))) rtl8139_weird_interrupt (dev, tp, ioaddr, @@ -2443,14 +2339,7 @@ RTL_W16 (IntrStatus, TxErr); } out: - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { - spin_unlock (&tp->lock); - } - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + if (!tp->ecdev) spin_unlock (&tp->lock); DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, RTL_R16 (IntrStatus)); @@ -2476,9 +2365,17 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev != rtl_ec_net_dev) { + if (tp->ecdev) { + /* 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); + } else { netif_stop_queue (dev); rtl8139_stop_thread(tp); @@ -2503,19 +2400,7 @@ 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); @@ -2731,13 +2616,9 @@ struct rtl8139_private *np = netdev_priv(dev); int rc; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running(dev)) + if (np->ecdev || !netif_running(dev)) return -EINVAL; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - spin_lock_irq(&np->lock); rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL); spin_unlock_irq(&np->lock); @@ -2752,17 +2633,13 @@ void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || netif_running(dev)) { + if (tp->ecdev || 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - return &tp->stats; } @@ -2835,13 +2712,9 @@ pci_save_state (pdev); - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - netif_device_detach (dev); spin_lock_irqsave (&tp->lock, flags); @@ -2865,16 +2738,11 @@ static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); + struct rtl8139_private *tp = netdev_priv(dev); pci_restore_state (pdev); - - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - if (dev == rtl_ec_net_dev || !netif_running (dev)) + if (tp->ecdev || !netif_running (dev)) return 0; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ - pci_set_power_state (pdev, PCI_D0); rtl8139_init_ring (dev); rtl8139_hw_start (dev); @@ -2899,69 +2767,20 @@ static int __init rtl8139_init_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO RTL8139_DRIVER_NAME "\n"); - printk(KERN_INFO "ec_device_index is %i\n", ec_device_index); - - if (pci_register_driver(&rtl8139_pci_driver) < 0) { - printk(KERN_ERR "Failed to init PCI module.\n"); - goto out_return; - } - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Registering EtherCAT device...\n"); - if (!(rtl_ec_dev = ecdev_register(ec_device_master_index, - rtl_ec_net_dev, ec_poll, THIS_MODULE))) { - printk(KERN_ERR "Failed to register EtherCAT device!\n"); - goto out_pci; - } - - printk(KERN_INFO "Opening EtherCAT device...\n"); - if (ecdev_open(rtl_ec_dev)) { - printk(KERN_ERR "Failed to open EtherCAT device!\n"); - goto out_unregister; - } - - printk(KERN_INFO "EtherCAT device ready.\n"); - } else { - printk(KERN_WARNING "No EtherCAT device registered!\n"); - } - - return 0; - - out_unregister: - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - out_pci: - pci_unregister_driver(&rtl8139_pci_driver); - out_return: - return -1; - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + /* when we're a module, we always print a version message, + * even if no 8139 board is found. + */ +#ifdef MODULE + printk (KERN_INFO RTL8139_DRIVER_NAME "\n"); +#endif + + return pci_register_driver(&rtl8139_pci_driver); } static void __exit rtl8139_cleanup_module (void) { - /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n"); - - if (rtl_ec_net_dev) { - printk(KERN_INFO "Closing EtherCAT device...\n"); - ecdev_close(rtl_ec_dev); - printk(KERN_INFO "Unregistering EtherCAT device...\n"); - ecdev_unregister(ec_device_master_index, rtl_ec_dev); - rtl_ec_dev = NULL; - } - - pci_unregister_driver(&rtl8139_pci_driver); - - printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n"); - - /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ + pci_unregister_driver (&rtl8139_pci_driver); } diff -r aef7ea866a41 -r cdee4ea90ce9 devices/ecdev.h --- a/devices/ecdev.h Fri Feb 16 13:30:46 2007 +0000 +++ b/devices/ecdev.h Fri Feb 16 17:13:39 2007 +0000 @@ -64,12 +64,12 @@ typedef void (*ec_pollfunc_t)(struct net_device *); /*****************************************************************************/ -// Registration functions +// Offering/withdrawal functions -ec_device_t *ecdev_register(unsigned int master_index, - struct net_device *net_dev, ec_pollfunc_t poll, - struct module *module); -void ecdev_unregister(unsigned int master_index, ec_device_t *device); +int ecdev_offer(struct net_device *net_dev, ec_device_t **, + const char *driver_name, unsigned int board_index, + ec_pollfunc_t poll, struct module *module); +void ecdev_withdraw(ec_device_t *device); /*****************************************************************************/ // Device methods diff -r aef7ea866a41 -r cdee4ea90ce9 master/device.h --- a/master/device.h Fri Feb 16 13:30:46 2007 +0000 +++ b/master/device.h Fri Feb 16 17:13:39 2007 +0000 @@ -53,6 +53,21 @@ /*****************************************************************************/ +typedef enum { + ec_device_id_empty, + ec_device_id_mac +} +ec_device_id_type_t; + +typedef struct { + struct list_head list; + ec_device_id_type_t type; + unsigned char octets[ETH_ALEN]; +} +ec_device_id_t; + +/*****************************************************************************/ + /** EtherCAT device. An EtherCAT device is a network interface card, that is owned by an diff -r aef7ea866a41 -r cdee4ea90ce9 master/master.c --- a/master/master.c Fri Feb 16 13:30:46 2007 +0000 +++ b/master/master.c Fri Feb 16 17:13:39 2007 +0000 @@ -102,18 +102,20 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ unsigned int index, /**< master index */ + const ec_device_id_t *main_id, /**< ID of main device */ + const ec_device_id_t *backup_id, /**< ID of main device */ unsigned int eoeif_count /**< number of EoE interfaces */ ) { ec_eoe_t *eoe, *next_eoe; unsigned int i; - EC_INFO("Initializing master %i.\n", index); - atomic_set(&master->available, 1); master->index = index; master->device = NULL; + master->main_device_id = main_id; + master->backup_device_id = backup_id; init_MUTEX(&master->device_sem); master->mode = EC_MASTER_MODE_ORPHANED; diff -r aef7ea866a41 -r cdee4ea90ce9 master/master.h --- a/master/master.h Fri Feb 16 13:30:46 2007 +0000 +++ b/master/master.h Fri Feb 16 17:13:39 2007 +0000 @@ -99,6 +99,8 @@ struct kobject kobj; /**< kobject */ ec_device_t *device; /**< EtherCAT device */ + const ec_device_id_t *main_device_id; /**< ID of main device */ + const ec_device_id_t *backup_device_id; /**< ID of backup device */ struct semaphore device_sem; /**< device semaphore */ ec_fsm_master_t fsm; /**< master state machine */ @@ -147,7 +149,8 @@ /*****************************************************************************/ // master creation/deletion -int ec_master_init(ec_master_t *, unsigned int, unsigned int); +int ec_master_init(ec_master_t *, unsigned int, + const ec_device_id_t *, const ec_device_id_t *, unsigned int); void ec_master_destroy(ec_master_t *); // mode transitions diff -r aef7ea866a41 -r cdee4ea90ce9 master/module.c --- a/master/module.c Fri Feb 16 13:30:46 2007 +0000 +++ b/master/module.c Fri Feb 16 17:13:39 2007 +0000 @@ -54,8 +54,12 @@ /*****************************************************************************/ -static int ec_master_count = 1; /**< parameter value, number of masters */ -static struct list_head ec_masters; /**< list of masters */ +static char *main; /**< main devices parameter */ +static char *backup; /**< backup devices parameter */ + +static LIST_HEAD(main_device_ids); /**< list of main device IDs */ +static LIST_HEAD(backup_device_ids); /**< list of main device IDs */ +static LIST_HEAD(masters); /**< list of masters */ static dev_t device_number; /**< XML character device number */ ec_xmldev_t xmldev; /**< XML character device */ @@ -65,18 +69,171 @@ /** \cond */ -module_param(ec_master_count, int, S_IRUGO); - MODULE_AUTHOR("Florian Pose "); MODULE_DESCRIPTION("EtherCAT master driver module"); MODULE_LICENSE("GPL"); MODULE_VERSION(EC_MASTER_VERSION); -MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize"); + +module_param(main, charp, S_IRUGO); +MODULE_PARM_DESC(main, "main device IDs"); +module_param(backup, charp, S_IRUGO); +MODULE_PARM_DESC(backup, "backup device IDs"); /** \endcond */ /*****************************************************************************/ +void clear_device_ids(struct list_head *device_ids) +{ + ec_device_id_t *dev_id, *next_dev_id; + + list_for_each_entry_safe(dev_id, next_dev_id, device_ids, list) { + list_del(&dev_id->list); + kfree(dev_id); + } +} + +/*****************************************************************************/ + +static int parse_device_id_mac(ec_device_id_t *dev_id, + const char *src, const char **remainder) +{ + unsigned int i, value; + char *rem; + + for (i = 0; i < ETH_ALEN; i++) { + value = simple_strtoul(src, &rem, 16); + if (rem != src + 2 + || value > 0xFF + || (i < ETH_ALEN - 1 && *rem != ':')) { + return -1; + } + dev_id->octets[i] = value; + if (i < ETH_ALEN - 1) + src = rem + 1; + } + + dev_id->type = ec_device_id_mac; + *remainder = rem; + return 0; +} + +/*****************************************************************************/ + +static int parse_device_ids(struct list_head *device_ids, const char *src) +{ + const char *rem; + ec_device_id_t *dev_id; + unsigned int index = 0; + + while (*src) { + // allocate new device ID + if (!(dev_id = kmalloc(sizeof(ec_device_id_t), GFP_KERNEL))) { + EC_ERR("Out of memory!\n"); + goto out_free; + } + + if (*src == ';') { // empty device ID + dev_id->type = ec_device_id_empty; + } + else if (*src == 'M') { + src++; + if (parse_device_id_mac(dev_id, src, &rem)) { + EC_ERR("Device ID %u: Invalid MAC syntax!\n", index); + kfree(dev_id); + goto out_free; + } + src = rem; + } + else { + EC_ERR("Device ID %u: Unknown format \'%c\'!\n", index, *src); + kfree(dev_id); + goto out_free; + } + + list_add_tail(&dev_id->list, device_ids); + if (*src) { + if (*src != ';') { + EC_ERR("Invalid delimiter '%c' after device ID %i!\n", + *src, index); + goto out_free; + } + src++; // skip delimiter + } + index++; + } + + return 0; + +out_free: + clear_device_ids(device_ids); + return -1; +} + +/*****************************************************************************/ + +static int create_device_ids(void) +{ + ec_device_id_t *id; + unsigned int main_count = 0, backup_count = 0; + + if (parse_device_ids(&main_device_ids, main)) + return -1; + + if (parse_device_ids(&backup_device_ids, main)) + return -1; + + // count main device IDs and check for empty ones + list_for_each_entry(id, &main_device_ids, list) { + if (id->type == ec_device_id_empty) { + EC_ERR("Main device IDs may not be empty!\n"); + return -1; + } + main_count++; + } + + // count backup device IDs + list_for_each_entry(id, &backup_device_ids, list) { + backup_count++; + } + + // fill up backup device IDs + while (backup_count < main_count) { + if (!(id = kmalloc(sizeof(ec_device_id_t), GFP_KERNEL))) { + EC_ERR("Out of memory!\n"); + return -1; + } + + id->type = ec_device_id_empty; + list_add_tail(&id->list, &backup_device_ids); + backup_count++; + } + + return 0; +} + +/*****************************************************************************/ + +static int device_id_check(const ec_device_id_t *dev_id, + const struct net_device *dev, const char *driver_name, + unsigned int device_index) +{ + unsigned int i; + + switch (dev_id->type) { + case ec_device_id_mac: + for (i = 0; i < ETH_ALEN; i++) + if (dev->dev_addr[i] != dev_id->octets[i]) + return 0; + return 1; + default: + return 0; + } +} + + +/*****************************************************************************/ + /** Module initialization. Initializes \a ec_master_count masters. @@ -85,48 +242,68 @@ int __init ec_init_module(void) { - unsigned int i; ec_master_t *master, *next; + ec_device_id_t *main_dev_id, *backup_dev_id; + unsigned int master_index = 0; EC_INFO("Master driver %s\n", EC_MASTER_VERSION); - if (ec_master_count < 1) { - EC_ERR("Invalid ec_master_count: %i\n", ec_master_count); + if (alloc_chrdev_region(&device_number, 0, 1, "EtherCAT")) { + EC_ERR("Failed to obtain device number!\n"); goto out_return; } - if (alloc_chrdev_region(&device_number, 0, ec_master_count, "EtherCAT")) { - EC_ERR("Failed to allocate device number!\n"); - goto out_return; - } - - EC_INFO("Initializing %i EtherCAT master(s)...\n", ec_master_count); - - INIT_LIST_HEAD(&ec_masters); - - for (i = 0; i < ec_master_count; i++) { - if (!(master = - (ec_master_t *) kmalloc(sizeof(ec_master_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate memory for EtherCAT master %i.\n", i); - goto out_free; - } - - if (ec_master_init(master, i, 0)) - goto out_free; - - list_add_tail(&master->list, &ec_masters); - } - - EC_INFO("Master driver initialized.\n"); + if (create_device_ids()) + goto out_free_ids; + + if (!list_empty(&main_device_ids)) { + main_dev_id = + list_entry(main_device_ids.next, ec_device_id_t, list); + backup_dev_id = + list_entry(backup_device_ids.next, ec_device_id_t, list); + + while (1) { + if (!(master = (ec_master_t *) + kmalloc(sizeof(ec_master_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate memory for EtherCAT master %i.\n", + master_index); + goto out_free_masters; + } + + if (ec_master_init(master, master_index, + main_dev_id, backup_dev_id, 0)) + goto out_free_masters; + + list_add_tail(&master->list, &masters); + master_index++; + + // last device IDs? + if (main_dev_id->list.next == &main_device_ids) + break; + + // next device IDs + main_dev_id = + list_entry(main_dev_id->list.next, ec_device_id_t, list); + backup_dev_id = + list_entry(backup_dev_id->list.next, ec_device_id_t, list); + } + } + + EC_INFO("%u master%s waiting for devices.\n", + master_index, (master_index == 1 ? "" : "s")); return 0; - out_free: - list_for_each_entry_safe(master, next, &ec_masters, list) { +out_free_masters: + list_for_each_entry_safe(master, next, &masters, list) { list_del(&master->list); kobject_del(&master->kobj); kobject_put(&master->kobj); } - out_return: +out_free_ids: + clear_device_ids(&main_device_ids); + clear_device_ids(&backup_device_ids); + unregister_chrdev_region(device_number, 1); +out_return: return -1; } @@ -143,12 +320,12 @@ EC_INFO("Cleaning up master driver...\n"); - list_for_each_entry_safe(master, next, &ec_masters, list) { + list_for_each_entry_safe(master, next, &masters, list) { list_del(&master->list); ec_master_destroy(master); } - unregister_chrdev_region(device_number, ec_master_count); + unregister_chrdev_region(device_number, 1); EC_INFO("Master driver cleaned up.\n"); } @@ -164,7 +341,7 @@ { ec_master_t *master; - list_for_each_entry(master, &ec_masters, list) { + list_for_each_entry(master, &masters, list) { if (master->index == master_index) return master; } @@ -270,48 +447,71 @@ *****************************************************************************/ /** - Connects an EtherCAT device to a certain master. - The master will use the device for sending and receiving frames. It is - required that no other instance (for example the kernel IP stack) uses - the device. + Offers an EtherCAT device to a certain master. + The master decides, if it wants to use the device for EtherCAT operation, + or not. It is important, that the offered net_device is not used by + the kernel IP stack. If the master, accepted the offer, the address of + the newly created EtherCAT device is written to the ecdev pointer, else + the pointer is written to zero. \return 0 on success, else < 0 \ingroup DeviceInterface */ -ec_device_t *ecdev_register(unsigned int master_index, /**< master index */ - struct net_device *net_dev, /**< net_device of - the device */ - ec_pollfunc_t poll, /**< device poll function */ - struct module *module /**< pointer to the module */ - ) +int ecdev_offer(struct net_device *net_dev, /**< net_device to offer */ + ec_device_t **ecdev, /**< pointer to store a device on success */ + const char *driver_name, /**< name of the network driver */ + unsigned int device_index, /**< index of the supported device */ + ec_pollfunc_t poll, /**< device poll function */ + struct module *module /**< pointer to the module */ + ) { ec_master_t *master; - - if (!(master = ec_find_master(master_index))) return NULL; - - if (down_interruptible(&master->device_sem)) { - EC_ERR("Interrupted while waiting for device!\n"); - goto out_return; - } - - if (master->device) { - EC_ERR("Master %i already has a device!\n", master_index); - goto out_up; - } - - if (!(master->device = - (ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate device!\n"); - goto out_up; - } - - if (ec_device_init(master->device, master, net_dev, poll, module)) { - EC_ERR("Failed to init device!\n"); - goto out_free; - } - - up(&master->device_sem); - return master->device; + unsigned int i; + + list_for_each_entry(master, &masters, list) { + if (down_interruptible(&master->device_sem)) { + EC_ERR("Interrupted while waiting for device semaphore!\n"); + goto out_return; + } + + if (device_id_check(master->main_device_id, net_dev, + driver_name, device_index)) { + + EC_INFO("Accepting device %s:%u (", driver_name, device_index); + for (i = 0; i < ETH_ALEN; i++) { + printk("%02X", net_dev->dev_addr[i]); + if (i < ETH_ALEN - 1) printk(":"); + } + printk(") for master %u.\n", master->index); + + if (master->device) { + EC_ERR("Master already has a device.\n"); + goto out_up; + } + + if (!(master->device = (ec_device_t *) + kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate device!\n"); + goto out_up; + } + + if (ec_device_init(master->device, master, + net_dev, poll, module)) { + EC_ERR("Failed to init device!\n"); + goto out_free; + } + + up(&master->device_sem); + sprintf(net_dev->name, "ec%u", master->index); + *ecdev = master->device; // offer accepted + return 0; // no error + } + + up(&master->device_sem); + } + + *ecdev = NULL; // offer declined + return 0; // no error out_free: kfree(master->device); @@ -319,13 +519,13 @@ out_up: up(&master->device_sem); out_return: - return NULL; -} - -/*****************************************************************************/ - -/** - Disconnect an EtherCAT device from the master. + return 1; +} + +/*****************************************************************************/ + +/** + Withdraws an EtherCAT device from the master. The device is disconnected from the master and all device ressources are freed. \attention Before calling this function, the ecdev_stop() function has @@ -333,26 +533,24 @@ \ingroup DeviceInterface */ -void ecdev_unregister(unsigned int master_index, /**< master index */ - ec_device_t *device /**< EtherCAT device */ - ) -{ - ec_master_t *master; - - if (!(master = ec_find_master(master_index))) return; +void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */) +{ + ec_master_t *master = device->master; + unsigned int i; down(&master->device_sem); - - if (!master->device || master->device != device) { - up(&master->device_sem); - EC_WARN("Unable to unregister device!\n"); - return; - } - + + EC_INFO("Master %u releasing device ", master->index); + for (i = 0; i < ETH_ALEN; i++) { + printk("%02X", device->dev->dev_addr[i]); + if (i < ETH_ALEN - 1) printk(":"); + } + printk(".\n"); + ec_device_clear(master->device); kfree(master->device); master->device = NULL; - + up(&master->device_sem); } @@ -505,8 +703,8 @@ module_init(ec_init_module); module_exit(ec_cleanup_module); -EXPORT_SYMBOL(ecdev_register); -EXPORT_SYMBOL(ecdev_unregister); +EXPORT_SYMBOL(ecdev_offer); +EXPORT_SYMBOL(ecdev_withdraw); EXPORT_SYMBOL(ecdev_open); EXPORT_SYMBOL(ecdev_close); EXPORT_SYMBOL(ecrt_request_master); diff -r aef7ea866a41 -r cdee4ea90ce9 script/init.d/ethercat --- a/script/init.d/ethercat Fri Feb 16 13:30:46 2007 +0000 +++ b/script/init.d/ethercat Fri Feb 16 17:13:39 2007 +0000 @@ -49,100 +49,39 @@ #------------------------------------------------------------------------------ -device="ecxml" - -IFCONFIG=ifconfig -BRCTL=brctl -ROUTE=route +XMLDEVICE='ecxml' #------------------------------------------------------------------------------ ETHERCAT_CONFIG=/etc/sysconfig/ethercat -if [ ! -r $ETHERCAT_CONFIG ]; then - echo "$ETHERCAT_CONFIG not existing"; - if [ "$1" = "stop" ]; then +if [ ! -r ${ETHERCAT_CONFIG} ]; then + echo "${ETHERCAT_CONFIG} not existing"; + if [ "${1}" = "stop" ]; then exit 0 else exit 6 fi fi -. $ETHERCAT_CONFIG - -#------------------------------------------------------------------------------ - -# -# Function for setting up the EoE bridge -# -build_eoe_bridge() +. ${ETHERCAT_CONFIG} + +#------------------------------------------------------------------------------ + +function make_device_id() { - if [ -z "$EOE_BRIDGE" ]; then return; fi - - EOEIF=`$IFCONFIG -a | grep -o -E "^eoe[0-9]+ "` - - # add bridge, if it does not already exist - if ! $BRCTL show | grep -E -q "^$EOE_BRIDGE"; then - if ! $BRCTL addbr $EOE_BRIDGE; then - /bin/false - rc_status -v - rc_exit - fi - fi - - # check if specified interfaces are bridged - for interf in $EOEIF $EOE_EXTRA_INTERFACES; do - # interface is already part of the bridge (FIXME->show $EOE_BRIDGE) - if $BRCTL show | grep -E -q $interf - then continue - fi - # clear IP address and open interface - if ! $IFCONFIG $interf 0.0.0.0 up; then - /bin/false - rc_status -v - rc_exit - fi - # add interface to the bridge - if ! $BRCTL addif $EOE_BRIDGE $interf; then - /bin/false - rc_status -v - rc_exit - fi - done - - # configure IP on bridge - if [ -n "$EOE_IP_ADDRESS" -a -n "$EOE_IP_NETMASK" ]; then - if ! $IFCONFIG $EOE_BRIDGE $EOE_IP_ADDRESS \ - netmask $EOE_IP_NETMASK; then - /bin/false - rc_status -v - rc_exit - fi - fi - - # open bridge - if ! $IFCONFIG $EOE_BRIDGE up; then - /bin/false - rc_status -v - rc_exit - fi - - # install new default gateway - if [ -n "$EOE_GATEWAY" ]; then - while $ROUTE -n | grep -E -q "^0.0.0.0"; do - if ! $ROUTE del default; then - echo "Failed to remove route!" 1>&2 - /bin/false - rc_status -v - rc_exit - fi - done - if ! $ROUTE add default gw $EOE_GATEWAY; then - /bin/false - rc_status -v - rc_exit - fi - fi + if [ -z "${1}" ]; then + DEVICE_ID=";" + elif echo ${1} | grep -qE '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'; then + DEVICE_ID="M${1};" + elif echo ${1} | grep -qE '^[^:]+:[0-9]+$'; then + DEVICE_ID="D${1};" + else + echo Invalid device ID syntax in ${ETHERCAT_CONFIG} + /bin/false + rc_status -v + rc_exit + fi } #------------------------------------------------------------------------------ @@ -150,127 +89,119 @@ . /etc/rc.status rc_reset -case "$1" in - - start) - echo -n "Starting EtherCAT master " - - if [ -z "$DEVICE_INDEX" ]; then - echo "ERROR: DEVICE_INDEX not set!" - /bin/false - rc_status -v - rc_exit - fi - - if [ -z "$EOE_INTERFACES" ]; then - # support legacy sysconfig files - if [ -n "$EOE_DEVICES" ]; then - EOE_INTERFACES=$EOE_DEVICES - else - EOE_INTERFACES=0 - fi - fi - - # unload conflicting modules at first - for mod in 8139too; do - if lsmod | grep "^$mod " > /dev/null; then - if ! rmmod $mod; then - /bin/false - rc_status -v - rc_exit - fi - fi - done - - # load master module - if ! modprobe ec_master ec_eoeif_count=$EOE_INTERFACES; then - modprobe 8139too - /bin/false - rc_status -v - rc_exit - fi - - # remove stale device node - rm -f /dev/${device}0 - - # get dynamic major number - major=$(awk "\$2==\"EtherCAT\" {print \$1}" /proc/devices) - - # create character device - mknod /dev/${device}0 c $major 0 - - # load device module - if ! modprobe ec_8139too ec_device_index=$DEVICE_INDEX; then - rmmod ec_master - modprobe 8139too - /bin/false - rc_status -v - rc_exit - fi - - # build EoE bridge - build_eoe_bridge - - rc_status -v - ;; - - stop) - echo -n "Shutting down EtherCAT master " - - # unload modules - for mod in ec_8139too ec_master; do - if lsmod | grep "^$mod " > /dev/null; then - if ! rmmod $mod; then - /bin/false - rc_status -v - rc_exit - fi; - fi; - done - - # remove device node - rm -f /dev/${device}0 - - sleep 1 - - # reload previous modules - if ! modprobe 8139too; then - echo "Warning: Failed to restore 8139too module." - fi - - rc_status -v - ;; - - restart) - $0 stop || exit 1 - sleep 1 - $0 start - rc_status - ;; - - status) - echo -n "Checking for EtherCAT " - - lsmod | grep "^ec_master " > /dev/null - master_running=$? - lsmod | grep "^ec_8139too " > /dev/null - device_running=$? - - # master module and device module loaded? - test $master_running -eq 0 -a $device_running -eq 0 - - rc_status -v - ;; - - bridge) - echo -n "Building EoE bridge " - build_eoe_bridge - rc_status -v - ;; - - *) - echo "USAGE: $0 {start|stop|restart|status|bridge}" - ;; +case "${1}" in + +start) + echo -n "Starting EtherCAT master " + + # construct DEVICES and BACKUPS from configuration variables + DEVICES="" + BACKUPS="" + MASTER_INDEX=0 + while true; do + DEVICE=$(eval echo "\${MASTER${MASTER_INDEX}_DEVICE}") + BACKUP=$(eval echo "\${MASTER${MASTER_INDEX}_BACKUP}") + if [ -z "${DEVICE}" ]; then break; fi + + make_device_id ${DEVICE} + DEVICES=${DEVICES}${DEVICE_ID} + make_device_id ${BACKUP} + BACKUPS=${BACKUPS}${DEVICE_ID} + + MASTER_INDEX=$(expr ${MASTER_INDEX} + 1) + done + + # unload conflicting modules at first + for MODULE in 8139too; do + if lsmod | grep "^${MODULE} " > /dev/null; then + if ! rmmod ${MODULE}; then + /bin/false + rc_status -v + rc_exit + fi + fi + done + + # load master module + if ! modprobe ec_master main=${DEVICES} backup=${BACKUPS}; then + modprobe 8139too + /bin/false + rc_status -v + rc_exit + fi + + # remove stale device node + rm -f /dev/${XMLDEVICE}0 + + # get dynamic major number + MAJOR=$(awk "\$2==\"EtherCAT\" {print \$1}" /proc/devices) + + # create character device + mknod /dev/${XMLDEVICE}0 c ${MAJOR} 0 + + # load device module + if ! modprobe ec_8139too; then + rmmod ec_master + modprobe 8139too + /bin/false + rc_status -v + rc_exit + fi + + rc_status -v + ;; + +stop) + echo -n "Shutting down EtherCAT master " + + # unload modules + for mod in ec_8139too ec_master; do + if lsmod | grep "^$mod " > /dev/null; then + if ! rmmod $mod; then + /bin/false + rc_status -v + rc_exit + fi; + fi; + done + + # remove device node + rm -f /dev/${XMLDEVICE}0 + + sleep 1 + + # reload previous modules + if ! modprobe 8139too; then + echo "Warning: Failed to restore 8139too module." + fi + + rc_status -v + ;; + +restart) + $0 stop || exit 1 + sleep 1 + $0 start + rc_status + ;; + +status) + echo -n "Checking for EtherCAT " + + lsmod | grep "^ec_master " > /dev/null + master_running=$? + lsmod | grep "^ec_8139too " > /dev/null + device_running=$? + + # master module and device module loaded? + test $master_running -eq 0 -a $device_running -eq 0 + + rc_status -v + ;; + +*) + echo "USAGE: $0 {start|stop|restart|status}" + ;; esac diff -r aef7ea866a41 -r cdee4ea90ce9 script/sysconfig/ethercat --- a/script/sysconfig/ethercat Fri Feb 16 13:30:46 2007 +0000 +++ b/script/sysconfig/ethercat Fri Feb 16 17:13:39 2007 +0000 @@ -1,58 +1,32 @@ #------------------------------------------------------------------------------ # -# EtherCAT sysconfig file +# EtherCAT master sysconfig file # # $Id$ # #------------------------------------------------------------------------------ # -# PCI index of the (RTL8139-)EtherCAT device -# Setting this is mandatory for the EtherCAT init script! +# Master device and backup-device settings. # -#DEVICE_INDEX=99 - +# The MASTERX_DEVICE variable specifies the ethernet device for master 'X', +# while the MASTERX_BACKUP variable specifies the backup ethernet device for +# redundancy purposes. # -# Number of Ethernet-over-EtherCAT interfaces every master shall create -# on startup. Default is 0. +# There are three formats for specifying ethernet devices: +# 1) MAC address (example: "00:00:08:44:55:66"). Specify the MAC address of +# the ethernet card to use. +# 2) PCI bus address (example: "01:1c.0"). Specify the PCU bis address of the +# ethernet card to use. +# 3) Driver and device index (example: "8139too:0"). Currently there are two +# drivers available: "8139too" and "e100". The device index is the index +# into driver-supported PCI cards. # -#EOE_INTERFACES=0 - +# The MASTERX_DEVICE variables also determine, how many masters will be +# created: A non-empty variable MASTER0_DEVICE will create one master, adding +# a non-empty variable MASTER1_DEVICE will create a second master, and so on. # -# 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 - -# -# Renew default gateway after bridge installation. -# Set this to the new default gateway, if the default route shall -# be renewed after the bridge has been installed. -# -#EOE_GATEWAY=192.168.X.X - -# -# 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 +MASTER0_DEVICE= +MASTER0_BACKUP= #------------------------------------------------------------------------------