Introduced device IDs; removed comment lines from 8139too; removed
ec_eoeif_count parameter.
This commit is contained in:
parent
cef0cc6409
commit
0f53f8fa3e
18
NEWS
18
NEWS
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
360
master/module.c
360
master/module.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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=
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue