patch-2.4.0-test6 linux/drivers/net/ioc3-eth.c
Next file: linux/drivers/net/irda/Makefile
Previous file: linux/drivers/net/hydra.c
Back to the patch index
Back to the overall index
- Lines: 318
- Date:
Thu Jul 27 18:36:54 2000
- Orig file:
v2.4.0-test5/linux/drivers/net/ioc3-eth.c
- Orig date:
Fri Jun 23 21:55:09 2000
diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
@@ -105,8 +105,6 @@
static void ioc3_timeout(struct net_device *dev);
static inline unsigned int ioc3_hash(const unsigned char *addr);
static void ioc3_stop(struct net_device *dev);
-static void ioc3_clean_tx_ring(struct ioc3_private *ip);
-static void ioc3_clean_rx_ring(struct ioc3_private *ip);
static void ioc3_init(struct net_device *dev);
static const char ioc3_str[] = "IOC3 Ethernet";
@@ -446,7 +444,6 @@
ip->stats.rx_packets++; /* Statistics */
ip->stats.rx_bytes += len;
-
} else {
/* The frame is invalid and the skb never
reached the network layer so we can just
@@ -464,7 +461,6 @@
((unsigned long) rxb & TO_PHYS_MASK);
rxb->w0 = 0; /* Clear valid flag */
n_entry = (n_entry + 1) & 511; /* Update erpir */
- ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
/* Now go on to the next ring entry. */
rx_entry = (rx_entry + 1) & 511;
@@ -472,6 +468,7 @@
rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
w0 = rxb->w0;
}
+ ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
ip->rx_pi = n_entry;
ip->rx_ci = rx_entry;
}
@@ -527,17 +524,26 @@
ioc3_error(struct net_device *dev, struct ioc3_private *ip,
struct ioc3 *ioc3, u32 eisr)
{
- if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR)) {
- if (eisr & EISR_RXMEMERR) {
- printk(KERN_ERR "%s: RX PCI error.\n", dev->name);
- }
- if (eisr & EISR_TXMEMERR) {
- printk(KERN_ERR "%s: TX PCI error.\n", dev->name);
- }
+ if (eisr & EISR_RXOFLO) {
+ printk(KERN_ERR "%s: RX overflow.\n", dev->name);
+ }
+ if (eisr & EISR_RXBUFOFLO) {
+ printk(KERN_ERR "%s: RX buffer overflow.\n", dev->name);
+ }
+ if (eisr & EISR_RXMEMERR) {
+ printk(KERN_ERR "%s: RX PCI error.\n", dev->name);
+ }
+ if (eisr & EISR_RXPARERR) {
+ printk(KERN_ERR "%s: RX SSRAM parity error.\n", dev->name);
+ }
+ if (eisr & EISR_TXBUFUFLO) {
+ printk(KERN_ERR "%s: TX buffer underflow.\n", dev->name);
+ }
+ if (eisr & EISR_TXMEMERR) {
+ printk(KERN_ERR "%s: TX PCI error.\n", dev->name);
}
ioc3_stop(dev);
- ioc3_clean_tx_ring(dev->priv);
ioc3_init(dev);
dev->trans_start = jiffies;
@@ -551,8 +557,9 @@
struct net_device *dev = (struct net_device *)_dev;
struct ioc3_private *ip = dev->priv;
struct ioc3 *ioc3 = ip->regs;
- const u32 enabled = EISR_RXTIMERINT | EISR_TXEXPLICIT |
- EISR_RXMEMERR | EISR_TXMEMERR;
+ const u32 enabled = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO |
+ EISR_RXMEMERR | EISR_RXPARERR | EISR_TXBUFUFLO |
+ EISR_TXEXPLICIT | EISR_TXMEMERR;
u32 eisr;
eisr = ioc3->eisr & enabled;
@@ -560,12 +567,14 @@
ioc3->eisr = eisr;
ioc3->eisr; /* Flush */
+ if (eisr & (EISR_RXOFLO | EISR_RXBUFOFLO | EISR_RXMEMERR |
+ EISR_RXPARERR | EISR_TXBUFUFLO | EISR_TXMEMERR))
+ ioc3_error(dev, ip, ioc3, eisr);
if (eisr & EISR_RXTIMERINT)
ioc3_rx(dev, ip, ioc3);
if (eisr & EISR_TXEXPLICIT)
ioc3_tx(dev, ip, ioc3);
- if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR))
- ioc3_error(dev, ip, ioc3, eisr);
+
eisr = ioc3->eisr & enabled;
}
}
@@ -612,15 +621,73 @@
mii_write(ioc3, phy, 0, mii0 | 0x3100);
spin_unlock_irq(&ip->ioc3_lock);
- mdelay(1000); /* XXX Yikes XXX */
- spin_lock_irq(&ip->ioc3_lock);
-
- mii_status = mii_read(ioc3, phy, 1);
- spin_unlock_irq(&ip->ioc3_lock);
return 0;
}
+static inline void
+ioc3_clean_rx_ring(struct ioc3_private *ip)
+{
+ struct sk_buff *skb;
+ int i;
+
+ for (i = ip->rx_ci; i & 15; i++) {
+ ip->rx_skbs[ip->rx_pi] = ip->rx_skbs[ip->rx_ci];
+ ip->rxr[ip->rx_pi++] = ip->rxr[ip->rx_ci++];
+ }
+ ip->rx_pi &= 511;
+ ip->rx_ci &= 511;
+
+ for (i = ip->rx_ci; i != ip->rx_pi; i = (i+1) & 511) {
+ struct ioc3_erxbuf *rxb;
+ skb = ip->rx_skbs[i];
+ rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
+ rxb->w0 = 0;
+ }
+}
+
+static inline void
+ioc3_clean_tx_ring(struct ioc3_private *ip)
+{
+ struct sk_buff *skb;
+ int i;
+
+ for (i=0; i < 128; i++) {
+ skb = ip->tx_skbs[i];
+ if (skb) {
+ ip->tx_skbs[i] = NULL;
+ dev_kfree_skb_any(skb);
+ }
+ ip->txr[i].cmd = 0;
+ }
+ ip->tx_pi = 0;
+ ip->tx_ci = 0;
+}
+
+static void
+ioc3_free_rings(struct ioc3_private *ip)
+{
+ struct sk_buff *skb;
+ int rx_entry, n_entry;
+
+ ioc3_clean_tx_ring(ip);
+ ip->txr = NULL;
+ free_pages((unsigned long)ip->txr, 2);
+
+ n_entry = ip->rx_ci;
+ rx_entry = ip->rx_pi;
+
+ while (n_entry != rx_entry) {
+ skb = ip->rx_skbs[n_entry];
+ if (skb)
+ dev_kfree_skb_any(skb);
+
+ n_entry = (n_entry + 1) & 511;
+ }
+ free_page((unsigned long)ip->rxr);
+ ip->rxr = NULL;
+}
+
static void
ioc3_alloc_rings(struct net_device *dev, struct ioc3_private *ip,
struct ioc3 *ioc3)
@@ -676,8 +743,8 @@
ioc3_alloc_rings(dev, ip, ioc3);
- ioc3_clean_tx_ring(ip);
ioc3_clean_rx_ring(ip);
+ ioc3_clean_tx_ring(ip);
/* Now the rx ring base, consume & produce registers. */
ring = (0xa5UL << 56) | ((unsigned long)ip->rxr & TO_PHYS_MASK);
@@ -698,61 +765,6 @@
ioc3->etcir; /* Flush */
}
-static void
-ioc3_clean_tx_ring(struct ioc3_private *ip)
-{
- struct sk_buff *skb;
- int i;
-
- for (i=0; i < 128; i++) {
- skb = ip->tx_skbs[i];
- if (skb) {
- ip->tx_skbs[i] = NULL;
- dev_kfree_skb_any(skb);
- }
- ip->txr[i].cmd = 0;
- }
-}
-
-static void
-ioc3_clean_rx_ring(struct ioc3_private *ip)
-{
- struct sk_buff *skb;
- int i;
-
- for (i = 0; i < RX_BUFFS; i++) {
- struct ioc3_erxbuf *rxb;
- skb = ip->rx_skbs[i];
- rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
-
- rxb->w0 = 0;
- }
-}
-
-static void
-ioc3_free_rings(struct ioc3_private *ip)
-{
- struct sk_buff *skb;
- int rx_entry, n_entry;
-
- ioc3_clean_tx_ring(ip);
- free_pages((unsigned long)ip->txr, 2);
- ip->txr = NULL;
-
- n_entry = ip->rx_ci;
- rx_entry = ip->rx_pi;
-
- while (n_entry != rx_entry) {
- skb = ip->rx_skbs[n_entry];
- if (skb)
- dev_kfree_skb_any(skb);
-
- n_entry = (n_entry + 1) & 511;
- }
- free_page((unsigned long)ip->rxr);
- ip->rxr = NULL;
-}
-
static inline void
ioc3_ssram_disc(struct ioc3_private *ip)
{
@@ -797,17 +809,18 @@
ioc3->emar_h = (dev->dev_addr[5] << 8) | dev->dev_addr[4];
ioc3->emar_l = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
(dev->dev_addr[1] << 8) | dev->dev_addr[0];
- ioc3->ehar_h = ioc3->ehar_l = 0;
+ ioc3->ehar_h = ip->ehar_h;
+ ioc3->ehar_l = ip->ehar_l;
ioc3->ersr = 42; /* XXX should be random */
- //ioc3->erpir = ERPIR_ARM;
ioc3_init_rings(dev, ip, ioc3);
ip->emcr |= ((RX_OFFSET / 2) << EMCR_RXOFF_SHIFT) | EMCR_TXDMAEN |
- EMCR_TXEN | EMCR_RXDMAEN | EMCR_RXEN;
+ EMCR_TXEN | EMCR_RXDMAEN | EMCR_RXEN;
ioc3->emcr = ip->emcr;
- ioc3->eier = EISR_RXTIMERINT | EISR_TXEXPLICIT | /* Interrupts ... */
- EISR_RXMEMERR | EISR_TXMEMERR;
+ ioc3->eier = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO |
+ EISR_RXMEMERR | EISR_RXPARERR | EISR_TXBUFUFLO |
+ EISR_TXEXPLICIT | EISR_TXMEMERR;
ioc3->eier;
}
@@ -817,7 +830,6 @@
struct ioc3 *ioc3 = ip->regs;
ioc3->emcr = 0; /* Shutup */
- ip->emcr = 0;
ioc3->eier = 0; /* Disable interrupts */
ioc3->eier; /* Flush */
}
@@ -825,14 +837,18 @@
static int
ioc3_open(struct net_device *dev)
{
+ struct ioc3_private *ip;
+
if (request_irq(dev->irq, ioc3_interrupt, 0, ioc3_str, dev)) {
printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq);
return -EAGAIN;
}
- ((struct ioc3_private *)dev->priv)->ehar_h = 0;
- ((struct ioc3_private *)dev->priv)->ehar_l = 0;
+ ip = (struct ioc3_private *) dev->priv;
+
+ ip->ehar_h = 0;
+ ip->ehar_l = 0;
ioc3_init(dev);
netif_start_queue(dev);
@@ -1005,7 +1021,6 @@
printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
ioc3_stop(dev);
- ioc3_clean_tx_ring(dev->priv);
ioc3_init(dev);
dev->trans_start = jiffies;
@@ -1117,7 +1132,7 @@
if (!(*addr & 1))
continue;
- ehar |= (1 << ioc3_hash(addr));
+ ehar |= (1UL << ioc3_hash(addr));
}
ip->ehar_h = ehar >> 32;
ip->ehar_l = ehar & 0xffffffff;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)