Introduced device IDs; removed comment lines from 8139too; removed

ec_eoeif_count parameter.
This commit is contained in:
Florian Pose 2007-02-16 17:13:39 +00:00
parent cef0cc6409
commit 0f53f8fa3e
12 changed files with 840 additions and 1434 deletions

18
NEWS
View File

@ -4,6 +4,24 @@ $Id$
-------------------------------------------------------------------------------
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

View File

@ -153,8 +153,6 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
/* 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 @@ static int multicast_filter_limit = 32;
/* 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 @@ static struct pci_device_id rtl8139_pci_tbl[] = {
{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 rtl8139_private {
struct mii_if_info mii;
unsigned int regs_len;
unsigned long fifo_copy_timeout;
ec_device_t *ecdev;
};
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
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 (multicast_filter_limit, "8139too maximum number of filtered mu
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->mii.reg_num_mask = 0x1f;
/* dev is fully set up and ready to use now */
// 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;
}
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ err_out:
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
rtl8139_start_thread(dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return 0;
}
@ -1478,19 +1433,16 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
{
struct rtl8139_private *tp = netdev_priv(dev);
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
if (tp->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 @@ static void rtl8139_hw_start (struct net_device *dev)
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 @@ static void rtl8139_tx_timeout (struct net_device *dev)
if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, CmdRxEnb);
/* 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);
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);
/* 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/* ...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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
/* 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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
dev->name, len, entry);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return 0;
}
@ -1961,10 +1890,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
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 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
mb();
if (dev != rtl_ec_net_dev) {
netif_wake_queue (dev);
}
if (!tp->ecdev) netif_wake_queue (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}
@ -2114,15 +2036,9 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ no_early_rx:
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 @@ no_early_rx:
} 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 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
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,30 +2263,25 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
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;
/* h/w no longer present (hotplug?) or major error, bail */
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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
}
}
/* 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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* 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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
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 @@ static int rtl8139_close (struct net_device *dev)
int ret = 0;
unsigned long flags;
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (tp->ecdev) {
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
if (dev != rtl_ec_net_dev) {
/* 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,20 +2396,8 @@ static int rtl8139_close (struct net_device *dev)
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);
pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
@ -2730,13 +2611,9 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
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 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
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 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
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_suspend (struct pci_dev *pdev, pm_message_t state)
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 struct pci_driver rtl8139_pci_driver = {
static int __init rtl8139_init_module (void)
{
/* 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
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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
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);
}

View File

@ -153,8 +153,6 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
/* 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 @@ static int multicast_filter_limit = 32;
/* 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 @@ static struct pci_device_id rtl8139_pci_tbl[] = {
{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 rtl8139_private {
struct mii_if_info mii;
unsigned int regs_len;
unsigned long fifo_copy_timeout;
ec_device_t *ecdev;
};
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
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 (multicast_filter_limit, "8139too maximum number of filtered mu
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->mii.reg_num_mask = 0x1f;
/* dev is fully set up and ready to use now */
// 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;
}
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ err_out:
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
rtl8139_start_thread(tp);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return 0;
}
@ -1482,19 +1437,16 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
{
struct rtl8139_private *tp = netdev_priv(dev);
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
if (tp->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 @@ static void rtl8139_hw_start (struct net_device *dev)
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 @@ static void rtl8139_tx_timeout_task (void *_data)
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 @@ static void rtl8139_tx_timeout_task (void *_data)
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
/* 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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
dev->name, len, entry);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return 0;
}
@ -1968,10 +1894,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
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 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
mb();
if (dev != rtl_ec_net_dev) {
netif_wake_queue (dev);
}
if (!tp->ecdev) netif_wake_queue (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}
@ -2121,15 +2040,9 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ no_early_rx:
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 @@ no_early_rx:
} 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 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
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,30 +2267,25 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
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;
/* h/w no longer present (hotplug?) or major error, bail */
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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
}
}
/* 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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* 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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
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 @@ static int rtl8139_close (struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (tp->ecdev) {
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
if (dev != rtl_ec_net_dev) {
/* 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,20 +2390,8 @@ static int rtl8139_close (struct net_device *dev)
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);
pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
@ -2728,13 +2606,9 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
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 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
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 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
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_suspend (struct pci_dev *pdev, pm_message_t state)
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 struct pci_driver rtl8139_pci_driver = {
static int __init rtl8139_init_module (void)
{
/* 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
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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
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);
}

View File

@ -152,8 +152,6 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
/* 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 @@ static int multicast_filter_limit = 32;
/* 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 @@ static struct pci_device_id rtl8139_pci_tbl[] = {
{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 rtl8139_private {
struct mii_if_info mii;
unsigned int regs_len;
unsigned long fifo_copy_timeout;
ec_device_t *ecdev;
};
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
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 (multicast_filter_limit, "8139too maximum number of filtered mu
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->mii.reg_num_mask = 0x1f;
/* dev is fully set up and ready to use now */
// 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;
}
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ err_out:
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
rtl8139_start_thread(tp);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return 0;
}
@ -1482,19 +1438,16 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
{
struct rtl8139_private *tp = netdev_priv(dev);
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
if (tp->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 @@ static void rtl8139_hw_start (struct net_device *dev)
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 @@ static void rtl8139_tx_timeout_task (void *_data)
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 @@ static void rtl8139_tx_timeout_task (void *_data)
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
/* 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 (tp->ecdev) {
RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
if (dev != rtl_ec_net_dev) {
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
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 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
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 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
mb();
if (dev != rtl_ec_net_dev) {
netif_wake_queue (dev);
}
if (!tp->ecdev) netif_wake_queue (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}
@ -2127,14 +2052,9 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ no_early_rx:
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 @@ no_early_rx:
} 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 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
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,30 +2279,25 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
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;
/* h/w no longer present (hotplug?) or major error, bail */
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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
}
}
/* 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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* 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 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
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 @@ static int rtl8139_close (struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (tp->ecdev) {
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
if (dev != rtl_ec_net_dev) {
/* 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,20 +2402,8 @@ static int rtl8139_close (struct net_device *dev)
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);
pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
@ -2733,13 +2618,9 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
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 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
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 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
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_suspend (struct pci_dev *pdev, pm_message_t state)
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 struct pci_driver rtl8139_pci_driver = {
static int __init rtl8139_init_module (void)
{
/* 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
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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
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);
}

View File

@ -152,8 +152,6 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
/* 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 @@ static int multicast_filter_limit = 32;
/* 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 @@ static struct pci_device_id rtl8139_pci_tbl[] = {
{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 rtl8139_private {
struct mii_if_info mii;
unsigned int regs_len;
unsigned long fifo_copy_timeout;
ec_device_t *ecdev;
};
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
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 (multicast_filter_limit, "8139too maximum number of filtered mu
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
tp->mii.reg_num_mask = 0x1f;
/* dev is fully set up and ready to use now */
// 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;
}
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
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 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
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 @@ err_out:
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
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 @@ static int rtl8139_open (struct net_device *dev)
rtl8139_start_thread(tp);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
return 0;
}
@ -1481,19 +1437,16 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
{
struct rtl8139_private *tp = netdev_priv(dev);
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev) {
if (tp->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 @@ static void rtl8139_hw_start (struct net_device *dev)
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 @@ static void rtl8139_tx_timeout_task (void *_data)
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 @@ static void rtl8139_tx_timeout_task (void *_data)
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
/* 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 (tp->ecdev) {
RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));
if (dev != rtl_ec_net_dev) {
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 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
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 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
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 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
mb();
if (dev != rtl_ec_net_dev) {
netif_wake_queue (dev);
}
if (!tp->ecdev) netif_wake_queue (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}
@ -2126,14 +2051,9 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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 @@ no_early_rx:
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 @@ no_early_rx:
} 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 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
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,30 +2277,25 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
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;
/* h/w no longer present (hotplug?) or major error, bail */
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 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
}
}
/* 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 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
/* 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 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
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 @@ static int rtl8139_close (struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (tp->ecdev) {
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
if (dev != rtl_ec_net_dev) {
/* 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,20 +2400,8 @@ static int rtl8139_close (struct net_device *dev)
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);
pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
@ -2731,13 +2616,9 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
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 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
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 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
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_suspend (struct pci_dev *pdev, pm_message_t state)
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 struct pci_driver rtl8139_pci_driver = {
static int __init rtl8139_init_module (void)
{
/* 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
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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
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);
}

View File

@ -64,12 +64,12 @@ typedef struct ec_device ec_device_t; /**< \see ec_device */
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

View File

@ -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

View File

@ -102,18 +102,20 @@ static struct kobj_type ktype_ec_master = {
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;

View File

@ -99,6 +99,8 @@ struct ec_master
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 @@ struct ec_master
/*****************************************************************************/
// 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

View File

@ -54,8 +54,12 @@ void __exit ec_cleanup_module(void);
/*****************************************************************************/
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,16 +69,169 @@ char *ec_master_version_str = EC_MASTER_VERSION;
/** \cond */
module_param(ec_master_count, int, S_IRUGO);
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
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;
}
}
/*****************************************************************************/
/**
@ -85,48 +242,68 @@ MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize");
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;
}
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;
}
EC_INFO("Initializing %i EtherCAT master(s)...\n", ec_master_count);
if (ec_master_init(master, master_index,
main_dev_id, backup_dev_id, 0))
goto out_free_masters;
INIT_LIST_HEAD(&ec_masters);
list_add_tail(&master->list, &masters);
master_index++;
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;
// 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);
}
if (ec_master_init(master, i, 0))
goto out_free;
list_add_tail(&master->list, &ec_masters);
}
EC_INFO("Master driver initialized.\n");
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 @@ void __exit ec_cleanup_module(void)
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 *ec_find_master(unsigned int master_index /**< master index */)
{
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 @@ size_t ec_state_string(uint8_t states, /**< slave states */
*****************************************************************************/
/**
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;
unsigned int i;
if (!(master = ec_find_master(master_index))) return NULL;
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 (down_interruptible(&master->device_sem)) {
EC_ERR("Interrupted while waiting for device!\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);
}
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;
*ecdev = NULL; // offer declined
return 0; // no error
out_free:
kfree(master->device);
@ -319,13 +519,13 @@ ec_device_t *ecdev_register(unsigned int master_index, /**< master index */
out_up:
up(&master->device_sem);
out_return:
return NULL;
return 1;
}
/*****************************************************************************/
/**
Disconnect an EtherCAT device from the master.
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 @@ ec_device_t *ecdev_register(unsigned int master_index, /**< master index */
\ingroup DeviceInterface
*/
void ecdev_unregister(unsigned int master_index, /**< master index */
ec_device_t *device /**< EtherCAT device */
)
void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
{
ec_master_t *master;
if (!(master = ec_find_master(master_index))) return;
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 @@ void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
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);

View File

@ -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
. ${ETHERCAT_CONFIG}
#------------------------------------------------------------------------------
#
# Function for setting up the EoE bridge
#
build_eoe_bridge()
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 @@ build_eoe_bridge()
. /etc/rc.status
rc_reset
case "$1" in
case "${1}" in
start)
echo -n "Starting EtherCAT master "
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
# 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
if [ -z "$EOE_INTERFACES" ]; then
# support legacy sysconfig files
if [ -n "$EOE_DEVICES" ]; then
EOE_INTERFACES=$EOE_DEVICES
else
EOE_INTERFACES=0
fi
fi
make_device_id ${DEVICE}
DEVICES=${DEVICES}${DEVICE_ID}
make_device_id ${BACKUP}
BACKUPS=${BACKUPS}${DEVICE_ID}
# 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
MASTER_INDEX=$(expr ${MASTER_INDEX} + 1)
done
# load master module
if ! modprobe ec_master ec_eoeif_count=$EOE_INTERFACES; then
modprobe 8139too
/bin/false
rc_status -v
rc_exit
fi
# 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
# remove stale device node
rm -f /dev/${device}0
# load master module
if ! modprobe ec_master main=${DEVICES} backup=${BACKUPS}; then
modprobe 8139too
/bin/false
rc_status -v
rc_exit
fi
# get dynamic major number
major=$(awk "\$2==\"EtherCAT\" {print \$1}" /proc/devices)
# remove stale device node
rm -f /dev/${XMLDEVICE}0
# create character device
mknod /dev/${device}0 c $major 0
# get dynamic major number
MAJOR=$(awk "\$2==\"EtherCAT\" {print \$1}" /proc/devices)
# 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
# create character device
mknod /dev/${XMLDEVICE}0 c ${MAJOR} 0
# build EoE bridge
build_eoe_bridge
# load device module
if ! modprobe ec_8139too; then
rmmod ec_master
modprobe 8139too
/bin/false
rc_status -v
rc_exit
fi
rc_status -v
;;
rc_status -v
;;
stop)
echo -n "Shutting down EtherCAT master "
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
# 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
# remove device node
rm -f /dev/${XMLDEVICE}0
sleep 1
sleep 1
# reload previous modules
if ! modprobe 8139too; then
echo "Warning: Failed to restore 8139too module."
fi
# reload previous modules
if ! modprobe 8139too; then
echo "Warning: Failed to restore 8139too module."
fi
rc_status -v
;;
rc_status -v
;;
restart)
$0 stop || exit 1
sleep 1
$0 start
rc_status
;;
restart)
$0 stop || exit 1
sleep 1
$0 start
rc_status
;;
status)
echo -n "Checking for EtherCAT "
status)
echo -n "Checking for EtherCAT "
lsmod | grep "^ec_master " > /dev/null
master_running=$?
lsmod | grep "^ec_8139too " > /dev/null
device_running=$?
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
# master module and device module loaded?
test $master_running -eq 0 -a $device_running -eq 0
rc_status -v
;;
rc_status -v
;;
bridge)
echo -n "Building EoE bridge "
build_eoe_bridge
rc_status -v
;;
*)
echo "USAGE: $0 {start|stop|restart|status|bridge}"
;;
*)
echo "USAGE: $0 {start|stop|restart|status}"
;;
esac

View File

@ -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=
#------------------------------------------------------------------------------