Commit 32686b9d authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/net-drivers-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 532de20c fc252a2b
...@@ -1061,23 +1061,33 @@ M: tigran@veritas.com ...@@ -1061,23 +1061,33 @@ M: tigran@veritas.com
S: Maintained S: Maintained
INTEL PRO/100 ETHERNET SUPPORT INTEL PRO/100 ETHERNET SUPPORT
P: John Ronciak
M: john.ronciak@intel.com
P: Ganesh Venkatesan
M: ganesh.venkatesan@intel.com
P: Scott Feldman P: Scott Feldman
M: scott.feldman@intel.com M: scott.feldman@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported S: Supported
INTEL PRO/1000 GIGABIT ETHERNET SUPPORT INTEL PRO/1000 GIGABIT ETHERNET SUPPORT
P: Jeb Cramer P: Jeb Cramer
M: cramerj@intel.com M: cramerj@intel.com
P: Scott Feldman P: John Ronciak
M: scott.feldman@intel.com M: john.ronciak@intel.com
P: Ganesh Venkatesan
M: ganesh.venkatesan@intel.com
W: http://sourceforge.net/projects/e1000/ W: http://sourceforge.net/projects/e1000/
S: Supported S: Supported
INTEL PRO/10GbE SUPPORT INTEL PRO/10GbE SUPPORT
P: Ayyappan Veeraiyan
M: ayyappan.veeraiyan@intel.com
P: Ganesh Venkatesan P: Ganesh Venkatesan
M: Ganesh.Venkatesan@intel.com M: ganesh.venkatesan@intel.com
P: Scott Feldman P: John Ronciak
M: scott.feldman@intel.com M: john.ronciak@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported S: Supported
INTERMEZZO FILE SYSTEM INTERMEZZO FILE SYSTEM
......
...@@ -1084,7 +1084,7 @@ void NS8390_init(struct net_device *dev, int startp) ...@@ -1084,7 +1084,7 @@ void NS8390_init(struct net_device *dev, int startp)
for(i = 0; i < 6; i++) for(i = 0; i < 6; i++)
{ {
outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) if (ei_debug > 1 && inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
printk(KERN_ERR "Hw. address read/write mismap %d\n",i); printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
} }
......
...@@ -131,8 +131,19 @@ struct ei_device { ...@@ -131,8 +131,19 @@ struct ei_device {
#define inb_p(port) in_8(port) #define inb_p(port) in_8(port)
#define outb_p(val,port) out_8(port,val) #define outb_p(val,port) out_8(port,val)
#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \ #elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE)
defined(CONFIG_NET_CBUS) #define EI_SHIFT(x) (ei_local->reg_offset[x])
#undef inb
#undef inb_p
#undef outb
#undef outb_p
#define inb(_p) readb(_p)
#define outb(_v,_p) writeb(_v,_p)
#define inb_p(_p) inb(_p)
#define outb_p(_v,_p) outb(_v,_p)
#elif defined(CONFIG_NET_CBUS)
#define EI_SHIFT(x) (ei_local->reg_offset[x]) #define EI_SHIFT(x) (ei_local->reg_offset[x])
#else #else
#define EI_SHIFT(x) (x) #define EI_SHIFT(x) (x)
......
...@@ -1230,6 +1230,9 @@ config AMD8111_ETH ...@@ -1230,6 +1230,9 @@ config AMD8111_ETH
To compile this driver as a module, choose M here and read To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module <file:Documentation/networking/net-modules.txt>. The module
will be called amd8111e. will be called amd8111e.
config AMD8111E_NAPI
bool "Enable NAPI support"
depends on AMD8111_ETH
config ADAPTEC_STARFIRE config ADAPTEC_STARFIRE
tristate "Adaptec Starfire/DuraLAN support" tristate "Adaptec Starfire/DuraLAN support"
......
/* Advanced Micro Devices Inc. AMD8111E Linux Network Driver /* Advanced Micro Devices Inc. AMD8111E Linux Network Driver
* Copyright (C) 2003 Advanced Micro Devices * Copyright (C) 2004 Advanced Micro Devices
* *
* *
* Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ] * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
...@@ -55,6 +55,16 @@ Revision History: ...@@ -55,6 +55,16 @@ Revision History:
4. Dynamic IPG support is disabled by default. 4. Dynamic IPG support is disabled by default.
3.0.3 06/05/2003 3.0.3 06/05/2003
1. Bug fix: Fixed failure to close the interface if SMP is enabled. 1. Bug fix: Fixed failure to close the interface if SMP is enabled.
3.0.4 12/09/2003
1. Added set_mac_address routine for bonding driver support.
2. Tested the driver for bonding support
3. Bug fix: Fixed mismach in actual receive buffer lenth and lenth
indicated to the h/w.
4. Modified amd8111e_rx() routine to receive all the received packets
in the first interrupt.
5. Bug fix: Corrected rx_errors reported in get_stats() function.
3.0.5 03/22/2004
1. Added NAPI support
*/ */
...@@ -91,7 +101,7 @@ Revision History: ...@@ -91,7 +101,7 @@ Revision History:
#include "amd8111e.h" #include "amd8111e.h"
#define MODULE_NAME "amd8111e" #define MODULE_NAME "amd8111e"
#define MODULE_VERS "3.0.3" #define MODULE_VERS "3.0.5"
MODULE_AUTHOR("Advanced Micro Devices, Inc."); MODULE_AUTHOR("Advanced Micro Devices, Inc.");
MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3"); MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -276,8 +286,10 @@ static inline void amd8111e_set_rx_buff_len(struct net_device* dev) ...@@ -276,8 +286,10 @@ static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
unsigned int mtu = dev->mtu; unsigned int mtu = dev->mtu;
if (mtu > ETH_DATA_LEN){ if (mtu > ETH_DATA_LEN){
/* MTU + ethernet header + FCS + optional VLAN tag */ /* MTU + ethernet header + FCS
lp->rx_buff_len = mtu + ETH_HLEN + 8; + optional VLAN tag + skb reserve space 2 */
lp->rx_buff_len = mtu + ETH_HLEN + 10;
lp->options |= OPTION_JUMBO_ENABLE; lp->options |= OPTION_JUMBO_ENABLE;
} else{ } else{
lp->rx_buff_len = PKT_BUFF_SZ; lp->rx_buff_len = PKT_BUFF_SZ;
...@@ -337,7 +349,7 @@ static int amd8111e_init_ring(struct net_device *dev) ...@@ -337,7 +349,7 @@ static int amd8111e_init_ring(struct net_device *dev)
lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]); lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]);
lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len); lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2);
lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT); lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
} }
...@@ -513,6 +525,9 @@ static void amd8111e_init_hw_default( struct amd8111e_priv* lp) ...@@ -513,6 +525,9 @@ static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
void * mmio = lp->mmio; void * mmio = lp->mmio;
/* stop the chip */
writel(RUN, mmio + CMD0);
/* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */ /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
writew( 0x8101, mmio + AUTOPOLL0); writew( 0x8101, mmio + AUTOPOLL0);
...@@ -654,7 +669,11 @@ This is the receive indication function for packets with vlan tag. ...@@ -654,7 +669,11 @@ This is the receive indication function for packets with vlan tag.
*/ */
static int amd8111e_vlan_rx(struct amd8111e_priv *lp, struct sk_buff *skb, u16 vlan_tag) static int amd8111e_vlan_rx(struct amd8111e_priv *lp, struct sk_buff *skb, u16 vlan_tag)
{ {
#ifdef CONFIG_AMD8111E_NAPI
return vlan_hwaccel_receive_skb(skb, lp->vlgrp,vlan_tag);
#else
return vlan_hwaccel_rx(skb, lp->vlgrp, vlan_tag); return vlan_hwaccel_rx(skb, lp->vlgrp, vlan_tag);
#endif /* CONFIG_AMD8111E_NAPI */
} }
#endif #endif
...@@ -700,6 +719,142 @@ static int amd8111e_tx(struct net_device *dev) ...@@ -700,6 +719,142 @@ static int amd8111e_tx(struct net_device *dev)
return 0; return 0;
} }
#if CONFIG_AMD8111E_NAPI
/* This function handles the driver receive operation in polling mode */
static int amd8111e_rx_poll(struct net_device *dev, int * budget)
{
struct amd8111e_priv *lp = dev->priv;
int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
void * mmio = lp->mmio;
struct sk_buff *skb,*new_skb;
int min_pkt_len, status;
unsigned int intr0;
int num_rx_pkt = 0;
/*int max_rx_pkt = NUM_RX_BUFFERS;*/
short pkt_len;
#if AMD8111E_VLAN_TAG_USED
short vtag;
#endif
int rx_pkt_limit = dev->quota;
do{
/* process receive packets until we use the quota*/
/* If we own the next entry, it's a new packet. Send it up. */
while(!(lp->rx_ring[rx_index].rx_flags & OWN_BIT)){
/* check if err summary bit is set */
if(le16_to_cpu(lp->rx_ring[rx_index].rx_flags)
& ERR_BIT){
/*
* There is a tricky error noted by John Murphy,
* <murf@perftech.com> to Russ Nelson: Even with
* full-sized * buffers it's possible for a
* jabber packet to use two buffers, with only
* the last correctly noting the error.
*/
/* reseting flags */
lp->rx_ring[rx_index].rx_flags &=RESET_RX_FLAGS;
goto err_next_pkt;
}
/* check for STP and ENP */
status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
if(!((status & STP_BIT) && (status & ENP_BIT))){
/* reseting flags */
lp->rx_ring[rx_index].rx_flags &=RESET_RX_FLAGS;
goto err_next_pkt;
}
pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4;
#if AMD8111E_VLAN_TAG_USED
vtag = le16_to_cpu(lp->rx_ring[rx_index].rx_flags) & TT_MASK;
/*MAC will strip vlan tag*/
if(lp->vlgrp != NULL && vtag !=0)
min_pkt_len =MIN_PKT_LEN - 4;
else
#endif
min_pkt_len =MIN_PKT_LEN;
if (pkt_len < min_pkt_len) {
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->drv_rx_errors++;
goto err_next_pkt;
}
if(--rx_pkt_limit < 0)
goto rx_not_empty;
if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
/* if allocation fail,
ignore that pkt and go to next one */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->drv_rx_errors++;
goto err_next_pkt;
}
skb_reserve(new_skb, 2);
skb = lp->rx_skbuff[rx_index];
pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index],
lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
skb_put(skb, pkt_len);
skb->dev = dev;
lp->rx_skbuff[rx_index] = new_skb;
new_skb->dev = dev;
lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev,
new_skb->data, lp->rx_buff_len-2,PCI_DMA_FROMDEVICE);
skb->protocol = eth_type_trans(skb, dev);
#if AMD8111E_VLAN_TAG_USED
vtag = lp->rx_ring[rx_index].rx_flags & TT_MASK;
if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){
amd8111e_vlan_rx(lp, skb,
lp->rx_ring[rx_index].tag_ctrl_info);
} else
#endif
netif_receive_skb(skb);
/*COAL update rx coalescing parameters*/
lp->coal_conf.rx_packets++;
lp->coal_conf.rx_bytes += pkt_len;
num_rx_pkt++;
dev->last_rx = jiffies;
err_next_pkt:
lp->rx_ring[rx_index].buff_phy_addr
= cpu_to_le32(lp->rx_dma_addr[rx_index]);
lp->rx_ring[rx_index].buff_count =
cpu_to_le16(lp->rx_buff_len-2);
lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT);
rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
}
/* Check the interrupt status register for more packets in the
mean time. Process them since we have not used up our quota.*/
intr0 = readl(mmio + INT0);
/*Ack receive packets */
writel(intr0 & RINT0,mmio + INT0);
}while(intr0 & RINT0);
/* Receive descriptor is empty now */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
netif_rx_complete(dev);
/* enable receive interrupt */
writel(VAL0|RINTEN0, mmio + INTEN0);
writel(VAL2 | RDMD0, mmio + CMD0);
return 0;
rx_not_empty:
/* Do not call a netif_rx_complete */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
return 1;
}
#else
/* /*
This function will check the ownership of receive buffers and descriptors. It will indicate to kernel up to half the number of maximum receive buffers in the descriptor ring, in a single receive interrupt. It will also replenish the descriptors with new skbs. This function will check the ownership of receive buffers and descriptors. It will indicate to kernel up to half the number of maximum receive buffers in the descriptor ring, in a single receive interrupt. It will also replenish the descriptors with new skbs.
*/ */
...@@ -710,7 +865,7 @@ static int amd8111e_rx(struct net_device *dev) ...@@ -710,7 +865,7 @@ static int amd8111e_rx(struct net_device *dev)
int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK; int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
int min_pkt_len, status; int min_pkt_len, status;
int num_rx_pkt = 0; int num_rx_pkt = 0;
int max_rx_pkt = NUM_RX_BUFFERS/2; int max_rx_pkt = NUM_RX_BUFFERS;
short pkt_len; short pkt_len;
#if AMD8111E_VLAN_TAG_USED #if AMD8111E_VLAN_TAG_USED
short vtag; short vtag;
...@@ -752,14 +907,14 @@ static int amd8111e_rx(struct net_device *dev) ...@@ -752,14 +907,14 @@ static int amd8111e_rx(struct net_device *dev)
if (pkt_len < min_pkt_len) { if (pkt_len < min_pkt_len) {
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->stats.rx_errors++; lp->drv_rx_errors++;
goto err_next_pkt; goto err_next_pkt;
} }
if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){ if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
/* if allocation fail, /* if allocation fail,
ignore that pkt and go to next one */ ignore that pkt and go to next one */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->stats.rx_errors++; lp->drv_rx_errors++;
goto err_next_pkt; goto err_next_pkt;
} }
...@@ -803,7 +958,7 @@ static int amd8111e_rx(struct net_device *dev) ...@@ -803,7 +958,7 @@ static int amd8111e_rx(struct net_device *dev)
return 0; return 0;
} }
#endif /* CONFIG_AMD8111E_NAPI */
/* /*
This function will indicate the link status to the kernel. This function will indicate the link status to the kernel.
*/ */
...@@ -896,12 +1051,14 @@ static struct net_device_stats *amd8111e_get_stats(struct net_device * dev) ...@@ -896,12 +1051,14 @@ static struct net_device_stats *amd8111e_get_stats(struct net_device * dev)
new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets); new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets);
/* stats.rx_errors */ /* stats.rx_errors */
/* hw errors + errors driver reported */
new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+ new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+
amd8111e_read_mib(mmio, rcv_fragments)+ amd8111e_read_mib(mmio, rcv_fragments)+
amd8111e_read_mib(mmio, rcv_jabbers)+ amd8111e_read_mib(mmio, rcv_jabbers)+
amd8111e_read_mib(mmio, rcv_alignment_errors)+ amd8111e_read_mib(mmio, rcv_alignment_errors)+
amd8111e_read_mib(mmio, rcv_fcs_errors)+ amd8111e_read_mib(mmio, rcv_fcs_errors)+
amd8111e_read_mib(mmio, rcv_miss_pkts); amd8111e_read_mib(mmio, rcv_miss_pkts)+
lp->drv_rx_errors;
/* stats.tx_errors */ /* stats.tx_errors */
new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts); new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
...@@ -1119,20 +1276,36 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg ...@@ -1119,20 +1276,36 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
/* Process all the INT event until INTR bit is clear. */ /* Process all the INT event until INTR bit is clear. */
if (!(intr0 & INTR)) { if (!(intr0 & INTR)){
handled = 0; handled = 0;
goto err_no_interrupt; goto err_no_interrupt;
} }
/* Current driver processes 3 interrupts : RINT,TINT,LCINT */ /* Current driver processes 4 interrupts : RINT,TINT,LCINT,STINT */
writel(intr0, mmio + INT0); writel(intr0, mmio + INT0);
/* Check if Receive Interrupt has occurred. */ /* Check if Receive Interrupt has occurred. */
#if CONFIG_AMD8111E_NAPI
if(intr0 & RINT0){
if(netif_rx_schedule_prep(dev)){
/* Disable receive interupts */
writel(RINTEN0, mmio + INTEN0);
/* Schedule a polling routine */
__netif_rx_schedule(dev);
}
else {
printk("************Driver bug! \
interrupt while in poll\n");
/* Fix by disabling interrupts */
writel(RINT0, mmio + INT0);
}
}
#else
if(intr0 & RINT0){ if(intr0 & RINT0){
amd8111e_rx(dev); amd8111e_rx(dev);
writel(VAL2 | RDMD0, mmio + CMD0); writel(VAL2 | RDMD0, mmio + CMD0);
} }
#endif /* CONFIG_AMD8111E_NAPI */
/* Check if Transmit Interrupt has occurred. */ /* Check if Transmit Interrupt has occurred. */
if(intr0 & TINT0) if(intr0 & TINT0)
amd8111e_tx(dev); amd8111e_tx(dev);
...@@ -1164,6 +1337,7 @@ static void amd8111e_poll(struct net_device *dev) ...@@ -1164,6 +1337,7 @@ static void amd8111e_poll(struct net_device *dev)
} }
#endif #endif
/* /*
This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down. This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
*/ */
...@@ -1186,7 +1360,7 @@ static int amd8111e_close(struct net_device * dev) ...@@ -1186,7 +1360,7 @@ static int amd8111e_close(struct net_device * dev)
spin_unlock_irq(&lp->lock); spin_unlock_irq(&lp->lock);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
/* Update the statistics before closing */ /* Update the statistics before closing */
amd8111e_get_stats(dev); amd8111e_get_stats(dev);
lp->opened = 0; lp->opened = 0;
...@@ -1560,6 +1734,23 @@ static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd) ...@@ -1560,6 +1734,23 @@ static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
} }
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static int amd8111e_set_mac_address(struct net_device *dev, void *p)
{
struct amd8111e_priv *lp = dev->priv;
int i;
struct sockaddr *addr = p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_irq(&lp->lock);
/* Setting the MAC address to the device */
for(i = 0; i < ETH_ADDR_LEN; i++)
writeb( dev->dev_addr[i], lp->mmio + PADR + i );
spin_unlock_irq(&lp->lock);
return 0;
}
/* /*
This function changes the mtu of the device. It restarts the device to initialize the descriptor with new receive buffers. This function changes the mtu of the device. It restarts the device to initialize the descriptor with new receive buffers.
*/ */
...@@ -1890,11 +2081,16 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, ...@@ -1890,11 +2081,16 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
dev->stop = amd8111e_close; dev->stop = amd8111e_close;
dev->get_stats = amd8111e_get_stats; dev->get_stats = amd8111e_get_stats;
dev->set_multicast_list = amd8111e_set_multicast_list; dev->set_multicast_list = amd8111e_set_multicast_list;
dev->set_mac_address = amd8111e_set_mac_address;
dev->do_ioctl = amd8111e_ioctl; dev->do_ioctl = amd8111e_ioctl;
dev->change_mtu = amd8111e_change_mtu; dev->change_mtu = amd8111e_change_mtu;
dev->irq =pdev->irq; dev->irq =pdev->irq;
dev->tx_timeout = amd8111e_tx_timeout; dev->tx_timeout = amd8111e_tx_timeout;
dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
#ifdef CONFIG_AMD8111E_NAPI
dev->poll = amd8111e_rx_poll;
dev->weight = 32;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = amd8111e_poll; dev->poll_controller = amd8111e_poll;
#endif #endif
...@@ -1908,6 +2104,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, ...@@ -1908,6 +2104,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
/* Set receive buffer length and set jumbo option*/ /* Set receive buffer length and set jumbo option*/
amd8111e_set_rx_buff_len(dev); amd8111e_set_rx_buff_len(dev);
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
printk(KERN_ERR "amd8111e: Cannot register net device, " printk(KERN_ERR "amd8111e: Cannot register net device, "
...@@ -1954,7 +2151,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, ...@@ -1954,7 +2151,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
} }
static struct pci_driver amd8111e_driver = { static struct pci_driver amd8111e_driver = {
.name = MODULE_NAME, .name = MODULE_NAME,
.id_table = amd8111e_pci_tbl, .id_table = amd8111e_pci_tbl,
.probe = amd8111e_probe_one, .probe = amd8111e_probe_one,
.remove = __devexit_p(amd8111e_remove_one), .remove = __devexit_p(amd8111e_remove_one),
......
...@@ -606,7 +606,7 @@ typedef enum { ...@@ -606,7 +606,7 @@ typedef enum {
/* ipg parameters */ /* ipg parameters */
#define DEFAULT_IPG 0x60 #define DEFAULT_IPG 0x60
#define IFS1_DELTA 36 #define IFS1_DELTA 36
#define IPG_CONVERGE_JIFFIES (HZ / 2) #define IPG_CONVERGE_JIFFIES (HZ/2)
#define IPG_STABLE_TIME 5 #define IPG_STABLE_TIME 5
#define MIN_IPG 96 #define MIN_IPG 96
#define MAX_IPG 255 #define MAX_IPG 255
...@@ -790,6 +790,7 @@ struct amd8111e_priv{ ...@@ -790,6 +790,7 @@ struct amd8111e_priv{
#endif #endif
char opened; char opened;
struct net_device_stats stats; struct net_device_stats stats;
unsigned int drv_rx_errors;
struct dev_mc_list* mc_list; struct dev_mc_list* mc_list;
struct amd8111e_coalesce_conf coal_conf; struct amd8111e_coalesce_conf coal_conf;
......
...@@ -185,8 +185,6 @@ static void __exit com20020_exit(void) ...@@ -185,8 +185,6 @@ static void __exit com20020_exit(void)
#ifndef MODULE #ifndef MODULE
static int __init com20020isa_setup(char *s) static int __init com20020isa_setup(char *s)
{ {
struct net_device *dev;
struct arcnet_local *lp;
int ints[8]; int ints[8];
s = get_options(s, 8, ints); s = get_options(s, 8, ints);
......
...@@ -60,11 +60,28 @@ static unsigned int net_debug = NET_DEBUG; ...@@ -60,11 +60,28 @@ static unsigned int net_debug = NET_DEBUG;
struct etherh_priv { struct etherh_priv {
struct ei_device eidev; struct ei_device eidev;
void *ioc_fast;
void *memc;
unsigned int id; unsigned int id;
unsigned int ctrl_port; void *ctrl_port;
unsigned int ctrl; unsigned int ctrl;
}; };
struct etherh_data {
unsigned long ns8390_offset;
unsigned long dataport_offset;
unsigned long ctrlport_offset;
int ctrl_ioc;
const char name[16];
/*
* netdev flags and port
*/
unsigned short flags;
unsigned char if_port;
unsigned char tx_start_page;
unsigned char stop_page;
};
MODULE_AUTHOR("Russell King"); MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EtherH/EtherM driver"); MODULE_DESCRIPTION("EtherH/EtherM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -72,13 +89,13 @@ MODULE_LICENSE("GPL"); ...@@ -72,13 +89,13 @@ MODULE_LICENSE("GPL");
static char version[] __initdata = static char version[] __initdata =
"EtherH/EtherM Driver (c) 2002 Russell King v1.09\n"; "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n";
#define ETHERH500_DATAPORT 0x200 /* MEMC */ #define ETHERH500_DATAPORT 0x800 /* MEMC */
#define ETHERH500_NS8390 0x000 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */
#define ETHERH500_CTRLPORT 0x200 /* IOC */ #define ETHERH500_CTRLPORT 0x800 /* IOC */
#define ETHERH600_DATAPORT 16 /* MEMC */ #define ETHERH600_DATAPORT 0x040 /* MEMC */
#define ETHERH600_NS8390 0x200 /* MEMC */ #define ETHERH600_NS8390 0x800 /* MEMC */
#define ETHERH600_CTRLPORT 0x080 /* MEMC */ #define ETHERH600_CTRLPORT 0x200 /* MEMC */
#define ETHERH_CP_IE 1 #define ETHERH_CP_IE 1
#define ETHERH_CP_IF 2 #define ETHERH_CP_IF 2
...@@ -90,9 +107,9 @@ static char version[] __initdata = ...@@ -90,9 +107,9 @@ static char version[] __initdata =
/* /*
* These came from CK/TEW * These came from CK/TEW
*/ */
#define ETHERM_DATAPORT 0x080 /* MEMC */ #define ETHERM_DATAPORT 0x200 /* MEMC */
#define ETHERM_NS8390 0x200 /* MEMC */ #define ETHERM_NS8390 0x800 /* MEMC */
#define ETHERM_CTRLPORT 0x08f /* MEMC */ #define ETHERM_CTRLPORT 0x23c /* MEMC */
#define ETHERM_TX_START_PAGE 64 #define ETHERM_TX_START_PAGE 64
#define ETHERM_STOP_PAGE 127 #define ETHERM_STOP_PAGE 127
...@@ -102,18 +119,18 @@ static char version[] __initdata = ...@@ -102,18 +119,18 @@ static char version[] __initdata =
static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask) static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask)
{ {
eh->ctrl |= mask; eh->ctrl |= mask;
outb(eh->ctrl, eh->ctrl_port); writeb(eh->ctrl, eh->ctrl_port);
} }
static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask) static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask)
{ {
eh->ctrl &= ~mask; eh->ctrl &= ~mask;
outb(eh->ctrl, eh->ctrl_port); writeb(eh->ctrl, eh->ctrl_port);
} }
static inline unsigned int etherh_get_stat(struct etherh_priv *eh) static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
{ {
return inb(eh->ctrl_port); return readb(eh->ctrl_port);
} }
...@@ -158,10 +175,10 @@ etherh_setif(struct net_device *dev) ...@@ -158,10 +175,10 @@ etherh_setif(struct net_device *dev)
switch (dev->if_port) { switch (dev->if_port) {
case IF_PORT_10BASE2: case IF_PORT_10BASE2:
outb((inb(addr) & 0xf8) | 1, addr); writeb((readb(addr) & 0xf8) | 1, addr);
break; break;
case IF_PORT_10BASET: case IF_PORT_10BASET:
outb((inb(addr) & 0xf8), addr); writeb((readb(addr) & 0xf8), addr);
break; break;
} }
break; break;
...@@ -200,7 +217,7 @@ etherh_getifstat(struct net_device *dev) ...@@ -200,7 +217,7 @@ etherh_getifstat(struct net_device *dev)
stat = 1; stat = 1;
break; break;
case IF_PORT_10BASET: case IF_PORT_10BASET:
stat = inb(dev->base_addr+EN0_RCNTHI) & 4; stat = readb(dev->base_addr+EN0_RCNTHI) & 4;
break; break;
} }
break; break;
...@@ -258,7 +275,7 @@ etherh_reset(struct net_device *dev) ...@@ -258,7 +275,7 @@ etherh_reset(struct net_device *dev)
{ {
struct ei_device *ei_local = netdev_priv(dev); struct ei_device *ei_local = netdev_priv(dev);
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr); writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
/* /*
* See if we need to change the interface type. * See if we need to change the interface type.
...@@ -306,31 +323,31 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ...@@ -306,31 +323,31 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
count = (count + 1) & ~1; count = (count + 1) & ~1;
outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
outb (0x42, addr + EN0_RCNTLO); writeb (0x42, addr + EN0_RCNTLO);
outb (0x00, addr + EN0_RCNTHI); writeb (0x00, addr + EN0_RCNTHI);
outb (0x42, addr + EN0_RSARLO); writeb (0x42, addr + EN0_RSARLO);
outb (0x00, addr + EN0_RSARHI); writeb (0x00, addr + EN0_RSARHI);
outb (E8390_RREAD | E8390_START, addr + E8390_CMD); writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
udelay (1); udelay (1);
outb (ENISR_RDC, addr + EN0_ISR); writeb (ENISR_RDC, addr + EN0_ISR);
outb (count, addr + EN0_RCNTLO); writeb (count, addr + EN0_RCNTLO);
outb (count >> 8, addr + EN0_RCNTHI); writeb (count >> 8, addr + EN0_RCNTHI);
outb (0, addr + EN0_RSARLO); writeb (0, addr + EN0_RSARLO);
outb (start_page, addr + EN0_RSARHI); writeb (start_page, addr + EN0_RSARHI);
outb (E8390_RWRITE | E8390_START, addr + E8390_CMD); writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
if (ei_local->word16) if (ei_local->word16)
outsw (dma_addr, buf, count >> 1); writesw (dma_addr, buf, count >> 1);
else else
outsb (dma_addr, buf, count); writesb (dma_addr, buf, count);
dma_start = jiffies; dma_start = jiffies;
while ((inb (addr + EN0_ISR) & ENISR_RDC) == 0) while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
printk(KERN_ERR "%s: timeout waiting for TX RDC\n", printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
dev->name); dev->name);
...@@ -339,7 +356,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ...@@ -339,7 +356,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
break; break;
} }
outb (ENISR_RDC, addr + EN0_ISR); writeb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing = 0; ei_local->dmaing = 0;
} }
...@@ -366,21 +383,21 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ...@@ -366,21 +383,21 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
buf = skb->data; buf = skb->data;
outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
outb (count, addr + EN0_RCNTLO); writeb (count, addr + EN0_RCNTLO);
outb (count >> 8, addr + EN0_RCNTHI); writeb (count >> 8, addr + EN0_RCNTHI);
outb (ring_offset, addr + EN0_RSARLO); writeb (ring_offset, addr + EN0_RSARLO);
outb (ring_offset >> 8, addr + EN0_RSARHI); writeb (ring_offset >> 8, addr + EN0_RSARHI);
outb (E8390_RREAD | E8390_START, addr + E8390_CMD); writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
if (ei_local->word16) { if (ei_local->word16) {
insw (dma_addr, buf, count >> 1); readsw (dma_addr, buf, count >> 1);
if (count & 1) if (count & 1)
buf[count - 1] = inb (dma_addr); buf[count - 1] = readb (dma_addr);
} else } else
insb (dma_addr, buf, count); readsb (dma_addr, buf, count);
outb (ENISR_RDC, addr + EN0_ISR); writeb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing = 0; ei_local->dmaing = 0;
} }
...@@ -405,19 +422,19 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ...@@ -405,19 +422,19 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
outb (sizeof (*hdr), addr + EN0_RCNTLO); writeb (sizeof (*hdr), addr + EN0_RCNTLO);
outb (0, addr + EN0_RCNTHI); writeb (0, addr + EN0_RCNTHI);
outb (0, addr + EN0_RSARLO); writeb (0, addr + EN0_RSARLO);
outb (ring_page, addr + EN0_RSARHI); writeb (ring_page, addr + EN0_RSARHI);
outb (E8390_RREAD | E8390_START, addr + E8390_CMD); writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
if (ei_local->word16) if (ei_local->word16)
insw (dma_addr, hdr, sizeof (*hdr) >> 1); readsw (dma_addr, hdr, sizeof (*hdr) >> 1);
else else
insb (dma_addr, hdr, sizeof (*hdr)); readsb (dma_addr, hdr, sizeof (*hdr));
outb (ENISR_RDC, addr + EN0_ISR); writeb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing = 0; ei_local->dmaing = 0;
} }
...@@ -543,18 +560,22 @@ static u32 etherm_regoffsets[16]; ...@@ -543,18 +560,22 @@ static u32 etherm_regoffsets[16];
static int __init static int __init
etherh_probe(struct expansion_card *ec, const struct ecard_id *id) etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
{ {
const struct etherh_data *data = id->data;
struct ei_device *ei_local; struct ei_device *ei_local;
struct net_device *dev; struct net_device *dev;
struct etherh_priv *eh; struct etherh_priv *eh;
const char *dev_type; int i, ret;
int i, size, ret;
etherh_banner(); etherh_banner();
ret = ecard_request_resources(ec);
if (ret)
goto out;
dev = alloc_ei_netdev(); dev = alloc_ei_netdev();
if (!dev) { if (!dev) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto release;
} }
eh = netdev_priv(dev); eh = netdev_priv(dev);
...@@ -562,111 +583,64 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -562,111 +583,64 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
spin_lock_init(&eh->eidev.page_lock); spin_lock_init(&eh->eidev.page_lock);
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &ec->dev);
dev->open = etherh_open; dev->open = etherh_open;
dev->stop = etherh_close; dev->stop = etherh_close;
dev->set_config = etherh_set_config; dev->set_config = etherh_set_config;
dev->irq = ec->irq; dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); dev->if_port = data->if_port;
dev->flags |= data->flags;
/*
* IRQ and control port handling
*/
if (ec->irq != 11) {
ec->ops = &etherh_ops;
ec->irq_data = eh;
}
eh->ctrl = 0; eh->ctrl = 0;
eh->id = ec->cid.product; eh->id = ec->cid.product;
eh->memc = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), PAGE_SIZE);
switch (ec->cid.product) { if (!eh->memc) {
case PROD_ANT_ETHERM: ret = -ENOMEM;
etherm_addr(dev->dev_addr);
dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break;
case PROD_I3_ETHERLAN500:
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
+ ETHERH500_CTRLPORT;
break;
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
break;
default:
printk(KERN_ERR "%s: unknown card type %x\n",
dev->name, ec->cid.product);
ret = -ENODEV;
goto free; goto free;
} }
size = 16; eh->ctrl_port = eh->memc;
if (ec->cid.product == PROD_ANT_ETHERM) if (data->ctrl_ioc) {
size <<= 3; eh->ioc_fast = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), PAGE_SIZE);
if (!eh->ioc_fast) {
if (!request_region(dev->base_addr, size, dev->name)) { ret = -ENOMEM;
ret = -EBUSY; goto free;
goto free; }
eh->ctrl_port = eh->ioc_fast;
} }
dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
dev->mem_start = (unsigned long)eh->memc + data->dataport_offset;
eh->ctrl_port += data->ctrlport_offset;
/* /*
* If we're in the NIC slot, make sure the IRQ is enabled * IRQ and control port handling - only for non-NIC slot cards.
*/ */
if (dev->irq == 11) if (ec->slot_no != 8) {
ec->ops = &etherh_ops;
ec->irq_data = eh;
} else {
/*
* If we're in the NIC slot, make sure the IRQ is enabled
*/
etherh_set_ctrl(eh, ETHERH_CP_IE); etherh_set_ctrl(eh, ETHERH_CP_IE);
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
dev_type = "ANT EtherM";
dev->if_port = IF_PORT_UNKNOWN;
break;
case PROD_I3_ETHERLAN500:
dev_type = "i3 EtherH 500";
dev->if_port = IF_PORT_UNKNOWN;
break;
case PROD_I3_ETHERLAN600:
dev_type = "i3 EtherH 600";
dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA;
dev->if_port = IF_PORT_10BASET;
break;
case PROD_I3_ETHERLAN600A:
dev_type = "i3 EtherH 600A";
dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA;
dev->if_port = IF_PORT_10BASET;
break;
default:
dev_type = "unknown";
break;
} }
ei_local = netdev_priv(dev); ei_local = &eh->eidev;
if (ec->cid.product == PROD_ANT_ETHERM) { if (ec->cid.product == PROD_ANT_ETHERM) {
ei_local->tx_start_page = ETHERM_TX_START_PAGE; etherm_addr(dev->dev_addr);
ei_local->stop_page = ETHERM_STOP_PAGE; ei_local->reg_offset = etherm_regoffsets;
ei_local->reg_offset = etherm_regoffsets;
} else { } else {
ei_local->tx_start_page = ETHERH_TX_START_PAGE; etherh_addr(dev->dev_addr, ec);
ei_local->stop_page = ETHERH_STOP_PAGE; ei_local->reg_offset = etherh_regoffsets;
ei_local->reg_offset = etherh_regoffsets;
} }
ei_local->name = dev->name; ei_local->name = dev->name;
ei_local->word16 = 1; ei_local->word16 = 1;
ei_local->tx_start_page = data->tx_start_page;
ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES; ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
ei_local->stop_page = data->stop_page;
ei_local->reset_8390 = etherh_reset; ei_local->reset_8390 = etherh_reset;
ei_local->block_input = etherh_block_input; ei_local->block_input = etherh_block_input;
ei_local->block_output = etherh_block_output; ei_local->block_output = etherh_block_output;
...@@ -678,10 +652,10 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -678,10 +652,10 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
ret = register_netdev(dev); ret = register_netdev(dev);
if (ret) if (ret)
goto release; goto free;
printk(KERN_INFO "%s: %s in slot %d, ", printk(KERN_INFO "%s: %s in slot %d, ",
dev->name, dev_type, ec->slot_no); dev->name, data->name, ec->slot_no);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
...@@ -690,10 +664,14 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -690,10 +664,14 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0; return 0;
release:
release_region(dev->base_addr, 16);
free: free:
if (eh->ioc_fast)
iounmap(eh->ioc_fast);
if (eh->memc)
iounmap(eh->memc);
free_netdev(dev); free_netdev(dev);
release:
ecard_release_resources(ec);
out: out:
return ret; return ret;
} }
...@@ -701,25 +679,69 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -701,25 +679,69 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit etherh_remove(struct expansion_card *ec) static void __devexit etherh_remove(struct expansion_card *ec)
{ {
struct net_device *dev = ecard_get_drvdata(ec); struct net_device *dev = ecard_get_drvdata(ec);
int size = 16; struct etherh_priv *eh = netdev_priv(dev);
ecard_set_drvdata(ec, NULL); ecard_set_drvdata(ec, NULL);
unregister_netdev(dev); unregister_netdev(dev);
if (ec->cid.product == PROD_ANT_ETHERM) if (eh->ioc_fast)
size <<= 3; iounmap(eh->ioc_fast);
release_region(dev->base_addr, size); iounmap(eh->memc);
free_netdev(dev); free_netdev(dev);
ec->ops = NULL; ec->ops = NULL;
kfree(ec->irq_data); kfree(ec->irq_data);
ecard_release_resources(ec);
} }
static struct etherh_data etherm_data = {
.ns8390_offset = ETHERM_NS8390,
.dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT,
.ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT,
.name = "ANT EtherM",
.if_port = IF_PORT_UNKNOWN,
.tx_start_page = ETHERM_TX_START_PAGE,
.stop_page = ETHERM_STOP_PAGE,
};
static struct etherh_data etherlan500_data = {
.ns8390_offset = ETHERH500_NS8390,
.dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT,
.ctrlport_offset = ETHERH500_CTRLPORT,
.ctrl_ioc = 1,
.name = "i3 EtherH 500",
.if_port = IF_PORT_UNKNOWN,
.tx_start_page = ETHERH_TX_START_PAGE,
.stop_page = ETHERH_STOP_PAGE,
};
static struct etherh_data etherlan600_data = {
.ns8390_offset = ETHERH600_NS8390,
.dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
.ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
.name = "i3 EtherH 600",
.flags = IFF_PORTSEL | IFF_AUTOMEDIA,
.if_port = IF_PORT_10BASET,
.tx_start_page = ETHERH_TX_START_PAGE,
.stop_page = ETHERH_STOP_PAGE,
};
static struct etherh_data etherlan600a_data = {
.ns8390_offset = ETHERH600_NS8390,
.dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
.ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
.name = "i3 EtherH 600A",
.flags = IFF_PORTSEL | IFF_AUTOMEDIA,
.if_port = IF_PORT_10BASET,
.tx_start_page = ETHERH_TX_START_PAGE,
.stop_page = ETHERH_STOP_PAGE,
};
static const struct ecard_id etherh_ids[] = { static const struct ecard_id etherh_ids[] = {
{ MANU_ANT, PROD_ANT_ETHERM }, { MANU_ANT, PROD_ANT_ETHERM, &etherm_data },
{ MANU_I3, PROD_I3_ETHERLAN500 }, { MANU_I3, PROD_I3_ETHERLAN500, &etherlan500_data },
{ MANU_I3, PROD_I3_ETHERLAN600 }, { MANU_I3, PROD_I3_ETHERLAN600, &etherlan600_data },
{ MANU_I3, PROD_I3_ETHERLAN600A }, { MANU_I3, PROD_I3_ETHERLAN600A, &etherlan600a_data },
{ 0xffff, 0xffff } { 0xffff, 0xffff }
}; };
...@@ -737,8 +759,8 @@ static int __init etherh_init(void) ...@@ -737,8 +759,8 @@ static int __init etherh_init(void)
int i; int i;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
etherh_regoffsets[i] = i; etherh_regoffsets[i] = i << 2;
etherm_regoffsets[i] = i << 3; etherm_regoffsets[i] = i << 5;
} }
return ecard_register_driver(&etherh_driver); return ecard_register_driver(&etherh_driver);
......
...@@ -2910,7 +2910,7 @@ static void iph5526_timeout(struct net_device *dev) ...@@ -2910,7 +2910,7 @@ static void iph5526_timeout(struct net_device *dev)
{ {
struct fc_info *fi = dev->priv; struct fc_info *fi = dev->priv;
printk(KERN_WARNING "%s: timed out on send.\n", dev->name); printk(KERN_WARNING "%s: timed out on send.\n", dev->name);
fi->fc_stats.rx_dropped++; fi->fc_stats.tx_dropped++;
dev->trans_start = jiffies; dev->trans_start = jiffies;
netif_wake_queue(dev); netif_wake_queue(dev);
} }
...@@ -2953,7 +2953,7 @@ static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev) ...@@ -2953,7 +2953,7 @@ static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev)
fi->fc_stats.tx_packets++; fi->fc_stats.tx_packets++;
} }
else else
fi->fc_stats.rx_dropped++; fi->fc_stats.tx_dropped++;
dev->trans_start = jiffies; dev->trans_start = jiffies;
/* We free up the IP buffers in the OCI_interrupt handler. /* We free up the IP buffers in the OCI_interrupt handler.
* status == 0 implies that the frame was not transmitted. So the * status == 0 implies that the frame was not transmitted. So the
......
...@@ -387,7 +387,7 @@ enum register_offsets { ...@@ -387,7 +387,7 @@ enum register_offsets {
IntrStatus = 0x10, IntrStatus = 0x10,
IntrMask = 0x14, IntrMask = 0x14,
IntrEnable = 0x18, IntrEnable = 0x18,
IntrHoldoff = 0x16, /* DP83816 only */ IntrHoldoff = 0x1C, /* DP83816 only */
TxRingPtr = 0x20, TxRingPtr = 0x20,
TxConfig = 0x24, TxConfig = 0x24,
RxRingPtr = 0x30, RxRingPtr = 0x30,
......
...@@ -1022,10 +1022,11 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1022,10 +1022,11 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
* starting until the packet is loaded. Strike one for reliability, lose * starting until the packet is loaded. Strike one for reliability, lose
* one for latency - although on PCI this isnt a big loss. Older chips * one for latency - although on PCI this isnt a big loss. Older chips
* have FIFO's smaller than a packet, so you can't do this. * have FIFO's smaller than a packet, so you can't do this.
* Turn on BCR18:BurstRdEn and BCR18:BurstWrEn.
*/ */
if (fset) { if (fset) {
a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800)); a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0860));
a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00); a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00);
dxsuflo = 1; dxsuflo = 1;
ltint = 1; ltint = 1;
......
...@@ -28,10 +28,10 @@ ...@@ -28,10 +28,10 @@
Linux kernel version history: Linux kernel version history:
LK1.1.0: LK1.1.0:
- Jeff Garzik: softnet 'n stuff - Jeff Garzik: softnet 'n stuff
LK1.1.1: LK1.1.1:
- Justin Guyett: softnet and locking fixes - Justin Guyett: softnet and locking fixes
- Jeff Garzik: use PCI interface - Jeff Garzik: use PCI interface
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
LK1.1.6: LK1.1.6:
- Urban Widmark: merges from Beckers 1.08b version (VT6102 + mdio) - Urban Widmark: merges from Beckers 1.08b version (VT6102 + mdio)
set netif_running_on/off on startup, del_timer_sync set netif_running_on/off on startup, del_timer_sync
LK1.1.7: LK1.1.7:
- Manfred Spraul: added reset into tx_timeout - Manfred Spraul: added reset into tx_timeout
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
LK1.1.13 (jgarzik): LK1.1.13 (jgarzik):
- Add ethtool support - Add ethtool support
- Replace some MII-related magic numbers with constants - Replace some MII-related magic numbers with constants
LK1.1.14 (Ivan G.): LK1.1.14 (Ivan G.):
- fixes comments for Rhine-III - fixes comments for Rhine-III
- removes W_MAX_TIMEOUT (unused) - removes W_MAX_TIMEOUT (unused)
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
- sends chip_id as a parameter to wait_for_reset since np is not - sends chip_id as a parameter to wait_for_reset since np is not
initialized on first call initialized on first call
- changes mmio "else if (chip_id==VT6102)" to "else" so it will work - changes mmio "else if (chip_id==VT6102)" to "else" so it will work
for Rhine-III's (documentation says same bit is correct) for Rhine-III's (documentation says same bit is correct)
- transmit frame queue message is off by one - fixed - transmit frame queue message is off by one - fixed
- adds IntrNormalSummary to "Something Wicked" exclusion list - adds IntrNormalSummary to "Something Wicked" exclusion list
so normal interrupts will not trigger the message (src: Donald Becker) so normal interrupts will not trigger the message (src: Donald Becker)
...@@ -316,10 +316,10 @@ IIId. Synchronization ...@@ -316,10 +316,10 @@ IIId. Synchronization
The driver runs as two independent, single-threaded flows of control. One The driver runs as two independent, single-threaded flows of control. One
is the send-packet routine, which enforces single-threaded use by the is the send-packet routine, which enforces single-threaded use by the
dev->priv->lock spinlock. The other thread is the interrupt handler, which dev->priv->lock spinlock. The other thread is the interrupt handler, which
is single threaded by the hardware and interrupt handling software. is single threaded by the hardware and interrupt handling software.
The send packet thread has partial control over the Tx ring. It locks the The send packet thread has partial control over the Tx ring. It locks the
dev->priv->lock whenever it's queuing a Tx packet. If the next slot in the ring dev->priv->lock whenever it's queuing a Tx packet. If the next slot in the ring
is not available it stops the transmit queue by calling netif_stop_queue. is not available it stops the transmit queue by calling netif_stop_queue.
...@@ -639,7 +639,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev, ...@@ -639,7 +639,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
#ifdef USE_MEM #ifdef USE_MEM
long ioaddr0; long ioaddr0;
#endif #endif
/* when built into the kernel, we only print version if device is found */ /* when built into the kernel, we only print version if device is found */
#ifndef MODULE #ifndef MODULE
static int printed_version; static int printed_version;
...@@ -660,7 +660,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev, ...@@ -660,7 +660,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
printk(KERN_ERR "32-bit PCI DMA addresses not supported by the card!?\n"); printk(KERN_ERR "32-bit PCI DMA addresses not supported by the card!?\n");
goto err_out; goto err_out;
} }
/* sanity check */ /* sanity check */
if ((pci_resource_len (pdev, 0) < io_size) || if ((pci_resource_len (pdev, 0) < io_size) ||
(pci_resource_len (pdev, 1) < io_size)) { (pci_resource_len (pdev, 1) < io_size)) {
...@@ -681,7 +681,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev, ...@@ -681,7 +681,7 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
} }
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
if (pci_request_regions(pdev, shortname)) if (pci_request_regions(pdev, shortname))
goto err_out_free_netdev; goto err_out_free_netdev;
...@@ -847,6 +847,8 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev, ...@@ -847,6 +847,8 @@ static int __devinit via_rhine_init_one (struct pci_dev *pdev,
netif_carrier_on(dev); netif_carrier_on(dev);
else else
netif_carrier_off(dev); netif_carrier_off(dev);
break;
} }
} }
np->mii_cnt = phy_idx; np->mii_cnt = phy_idx;
...@@ -891,7 +893,7 @@ static int alloc_ring(struct net_device* dev) ...@@ -891,7 +893,7 @@ static int alloc_ring(struct net_device* dev)
void *ring; void *ring;
dma_addr_t ring_dma; dma_addr_t ring_dma;
ring = pci_alloc_consistent(np->pdev, ring = pci_alloc_consistent(np->pdev,
RX_RING_SIZE * sizeof(struct rx_desc) + RX_RING_SIZE * sizeof(struct rx_desc) +
TX_RING_SIZE * sizeof(struct tx_desc), TX_RING_SIZE * sizeof(struct tx_desc),
&ring_dma); &ring_dma);
...@@ -903,7 +905,7 @@ static int alloc_ring(struct net_device* dev) ...@@ -903,7 +905,7 @@ static int alloc_ring(struct net_device* dev)
np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE, np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,
&np->tx_bufs_dma); &np->tx_bufs_dma);
if (np->tx_bufs == NULL) { if (np->tx_bufs == NULL) {
pci_free_consistent(np->pdev, pci_free_consistent(np->pdev,
RX_RING_SIZE * sizeof(struct rx_desc) + RX_RING_SIZE * sizeof(struct rx_desc) +
TX_RING_SIZE * sizeof(struct tx_desc), TX_RING_SIZE * sizeof(struct tx_desc),
ring, ring_dma); ring, ring_dma);
...@@ -923,7 +925,7 @@ void free_ring(struct net_device* dev) ...@@ -923,7 +925,7 @@ void free_ring(struct net_device* dev)
{ {
struct netdev_private *np = dev->priv; struct netdev_private *np = dev->priv;
pci_free_consistent(np->pdev, pci_free_consistent(np->pdev,
RX_RING_SIZE * sizeof(struct rx_desc) + RX_RING_SIZE * sizeof(struct rx_desc) +
TX_RING_SIZE * sizeof(struct tx_desc), TX_RING_SIZE * sizeof(struct tx_desc),
np->rx_ring, np->rx_ring_dma); np->rx_ring, np->rx_ring_dma);
...@@ -948,7 +950,7 @@ static void alloc_rbufs(struct net_device *dev) ...@@ -948,7 +950,7 @@ static void alloc_rbufs(struct net_device *dev)
np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
np->rx_head_desc = &np->rx_ring[0]; np->rx_head_desc = &np->rx_ring[0];
next = np->rx_ring_dma; next = np->rx_ring_dma;
/* Init the ring entries */ /* Init the ring entries */
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
np->rx_ring[i].rx_status = 0; np->rx_ring[i].rx_status = 0;
...@@ -1151,7 +1153,7 @@ static int via_rhine_open(struct net_device *dev) ...@@ -1151,7 +1153,7 @@ static int via_rhine_open(struct net_device *dev)
if (debug > 1) if (debug > 1)
printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n", printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n",
dev->name, np->pdev->irq); dev->name, np->pdev->irq);
i = alloc_ring(dev); i = alloc_ring(dev);
if (i) if (i)
return i; return i;
...@@ -1266,7 +1268,7 @@ static void via_rhine_tx_timeout (struct net_device *dev) ...@@ -1266,7 +1268,7 @@ static void via_rhine_tx_timeout (struct net_device *dev)
/* Reinitialize the hardware. */ /* Reinitialize the hardware. */
wait_for_reset(dev, np->chip_id, dev->name); wait_for_reset(dev, np->chip_id, dev->name);
init_registers(dev); init_registers(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
enable_irq(np->pdev->irq); enable_irq(np->pdev->irq);
...@@ -1316,7 +1318,7 @@ static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -1316,7 +1318,7 @@ static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_ring[entry].addr = cpu_to_le32(np->tx_skbuff_dma[entry]); np->tx_ring[entry].addr = cpu_to_le32(np->tx_skbuff_dma[entry]);
} }
np->tx_ring[entry].desc_length = np->tx_ring[entry].desc_length =
cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
/* lock eth irq */ /* lock eth irq */
...@@ -1364,7 +1366,7 @@ static irqreturn_t via_rhine_interrupt(int irq, void *dev_instance, struct pt_re ...@@ -1364,7 +1366,7 @@ static irqreturn_t via_rhine_interrupt(int irq, void *dev_instance, struct pt_re
int handled = 0; int handled = 0;
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
while ((intr_status = get_intr_status(dev))) { while ((intr_status = get_intr_status(dev))) {
handled = 1; handled = 1;
...@@ -1584,7 +1586,7 @@ static void via_rhine_rx(struct net_device *dev) ...@@ -1584,7 +1586,7 @@ static void via_rhine_rx(struct net_device *dev)
break; /* Better luck next round. */ break; /* Better luck next round. */
skb->dev = dev; /* Mark as being used by this device. */ skb->dev = dev; /* Mark as being used by this device. */
np->rx_skbuff_dma[entry] = np->rx_skbuff_dma[entry] =
pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, pci_map_single(np->pdev, skb->tail, np->rx_buf_sz,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
np->rx_ring[entry].addr = cpu_to_le32(np->rx_skbuff_dma[entry]); np->rx_ring[entry].addr = cpu_to_le32(np->rx_skbuff_dma[entry]);
} }
...@@ -1892,7 +1894,7 @@ static int via_rhine_close(struct net_device *dev) ...@@ -1892,7 +1894,7 @@ static int via_rhine_close(struct net_device *dev)
static void __devexit via_rhine_remove_one (struct pci_dev *pdev) static void __devexit via_rhine_remove_one (struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
unregister_netdev(dev); unregister_netdev(dev);
pci_release_regions(pdev); pci_release_regions(pdev);
......
...@@ -42,13 +42,14 @@ struct divert_blk; ...@@ -42,13 +42,14 @@ struct divert_blk;
struct vlan_group; struct vlan_group;
struct ethtool_ops; struct ethtool_ops;
/* source back-compat hook */ /* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \ #define SET_ETHTOOL_OPS(netdev,ops) \
( (netdev)->ethtool_ops = (ops) ) ( (netdev)->ethtool_ops = (ops) )
#define HAVE_ALLOC_NETDEV /* feature macro: alloc_xxxdev #define HAVE_ALLOC_NETDEV /* feature macro: alloc_xxxdev
functions are available. */ functions are available. */
#define HAVE_FREE_NETDEV #define HAVE_FREE_NETDEV /* free_netdev() */
#define HAVE_NETDEV_PRIV /* netdev_priv() */
#define NET_XMIT_SUCCESS 0 #define NET_XMIT_SUCCESS 0
#define NET_XMIT_DROP 1 /* skb dropped */ #define NET_XMIT_DROP 1 /* skb dropped */
......
...@@ -163,21 +163,15 @@ void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) ...@@ -163,21 +163,15 @@ void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
spin_lock(&np->dev->xmit_lock); spin_lock(&np->dev->xmit_lock);
np->dev->xmit_lock_owner = smp_processor_id(); np->dev->xmit_lock_owner = smp_processor_id();
if (netif_queue_stopped(np->dev)) {
np->dev->xmit_lock_owner = -1;
spin_unlock(&np->dev->xmit_lock);
netpoll_poll(np);
goto repeat;
}
status = np->dev->hard_start_xmit(skb, np->dev); status = np->dev->hard_start_xmit(skb, np->dev);
np->dev->xmit_lock_owner = -1; np->dev->xmit_lock_owner = -1;
spin_unlock(&np->dev->xmit_lock); spin_unlock(&np->dev->xmit_lock);
/* transmit busy */ /* transmit busy */
if(status) if(status) {
netpoll_poll(np);
goto repeat; goto repeat;
}
} }
void netpoll_send_udp(struct netpoll *np, const char *msg, int len) void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
...@@ -231,9 +225,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) ...@@ -231,9 +225,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
static void arp_reply(struct sk_buff *skb) static void arp_reply(struct sk_buff *skb)
{ {
struct in_device *in_dev = (struct in_device *) skb->dev->ip_ptr;
struct arphdr *arp; struct arphdr *arp;
unsigned char *arp_ptr, *sha, *tha; unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
u32 sip, tip; u32 sip, tip;
struct sk_buff *send_skb; struct sk_buff *send_skb;
...@@ -253,7 +246,7 @@ static void arp_reply(struct sk_buff *skb) ...@@ -253,7 +246,7 @@ static void arp_reply(struct sk_buff *skb)
if (!np) return; if (!np) return;
/* No arp on this interface */ /* No arp on this interface */
if (!in_dev || skb->dev->flags & IFF_NOARP) if (skb->dev->flags & IFF_NOARP)
return; return;
if (!pskb_may_pull(skb, (sizeof(struct arphdr) + if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
...@@ -270,21 +263,15 @@ static void arp_reply(struct sk_buff *skb) ...@@ -270,21 +263,15 @@ static void arp_reply(struct sk_buff *skb)
arp->ar_op != htons(ARPOP_REQUEST)) arp->ar_op != htons(ARPOP_REQUEST))
return; return;
arp_ptr= (unsigned char *)(arp+1); arp_ptr = (unsigned char *)(arp+1) + skb->dev->addr_len;
sha = arp_ptr;
arp_ptr += skb->dev->addr_len;
memcpy(&sip, arp_ptr, 4); memcpy(&sip, arp_ptr, 4);
arp_ptr += 4; arp_ptr += 4 + skb->dev->addr_len;
tha = arp_ptr;
arp_ptr += skb->dev->addr_len;
memcpy(&tip, arp_ptr, 4); memcpy(&tip, arp_ptr, 4);
/* Should we ignore arp? */ /* Should we ignore arp? */
if (tip != in_dev->ifa_list->ifa_address || if (tip != htonl(np->local_ip) || LOOPBACK(tip) || MULTICAST(tip))
LOOPBACK(tip) || MULTICAST(tip))
return; return;
size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4); size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev), send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
LL_RESERVED_SPACE(np->dev)); LL_RESERVED_SPACE(np->dev));
...@@ -325,7 +312,7 @@ static void arp_reply(struct sk_buff *skb) ...@@ -325,7 +312,7 @@ static void arp_reply(struct sk_buff *skb)
arp_ptr += np->dev->addr_len; arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &tip, 4); memcpy(arp_ptr, &tip, 4);
arp_ptr += 4; arp_ptr += 4;
memcpy(arp_ptr, np->local_mac, np->dev->addr_len); memcpy(arp_ptr, np->remote_mac, np->dev->addr_len);
arp_ptr += np->dev->addr_len; arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &sip, 4); memcpy(arp_ptr, &sip, 4);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment