📄 7990.c
字号:
int i, j; int status; DECLARE_LL; /* csr0 is 2f3 */ WRITERDP(LE_C0_TINT | LE_C0_INEA); /* csr0 is 73 */ j = lp->tx_old; for (i = j; i != lp->tx_new; i = j) { td = &ib->btx_ring [i]; /* If we hit a packet not owned by us, stop */ if (td->tmd1_bits & LE_T1_OWN) break; if (td->tmd1_bits & LE_T1_ERR) { status = td->misc; lp->stats.tx_errors++; if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++; if (status & LE_T3_LCOL) lp->stats.tx_window_errors++; if (status & LE_T3_CLOS) { lp->stats.tx_carrier_errors++; if (lp->auto_select) { lp->tpe = 1 - lp->tpe; printk("%s: Carrier Lost, trying %s\n", dev->name, lp->tpe?"TPE":"AUI"); /* Stop the lance */ WRITERAP(LE_CSR0); WRITERDP(LE_C0_STOP); lance_init_ring (dev); load_csrs (lp); init_restart_lance (lp); return 0; } } /* buffer errors and underflows turn off the transmitter */ /* Restart the adapter */ if (status & (LE_T3_BUF|LE_T3_UFL)) { lp->stats.tx_fifo_errors++; printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", dev->name); /* Stop the lance */ WRITERAP(LE_CSR0); WRITERDP(LE_C0_STOP); lance_init_ring (dev); load_csrs (lp); init_restart_lance (lp); return 0; } } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { /* * So we don't count the packet more than once. */ td->tmd1_bits &= ~(LE_T1_POK); /* One collision before packet was sent. */ if (td->tmd1_bits & LE_T1_EONE) lp->stats.collisions++; /* More than one collision, be optimistic. */ if (td->tmd1_bits & LE_T1_EMORE) lp->stats.collisions += 2; lp->stats.tx_packets++; } j = (j + 1) & lp->tx_ring_mod_mask; } lp->tx_old = j; WRITERDP(LE_C0_TINT | LE_C0_INEA); return 0;}static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *)dev_id; struct lance_private *lp = (struct lance_private *)dev->priv; int csr0; DECLARE_LL; spin_lock (&lp->devlock); WRITERAP(LE_CSR0); /* LANCE Controller Status */ csr0 = READRDP(); PRINT_RINGS(); if (!(csr0 & LE_C0_INTR)) { /* Check if any interrupt has */ spin_lock (&lp->devlock); return; /* been generated by the Lance. */ } /* Acknowledge all the interrupt sources ASAP */ WRITERDP(csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT)); if ((csr0 & LE_C0_ERR)) { /* Clear the error condition */ WRITERDP(LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA); } if (csr0 & LE_C0_RINT) lance_rx (dev); if (csr0 & LE_C0_TINT) lance_tx (dev); /* Log misc errors. */ if (csr0 & LE_C0_BABL) lp->stats.tx_errors++; /* Tx babble. */ if (csr0 & LE_C0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */ if (csr0 & LE_C0_MERR) { printk("%s: Bus master arbitration failure, status %4.4x.\n", dev->name, csr0); /* Restart the chip. */ WRITERDP(LE_C0_STRT); } if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) { lp->tx_full = 0; netif_wake_queue (dev); } WRITERAP(LE_CSR0); WRITERDP(LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA); spin_unlock (&lp->devlock);}int lance_open (struct net_device *dev){ struct lance_private *lp = (struct lance_private *)dev->priv; int res; DECLARE_LL; /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */ if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev)) return -EAGAIN; res = lance_reset(dev); lp->devlock = SPIN_LOCK_UNLOCKED; netif_start_queue (dev); return res;}int lance_close (struct net_device *dev){ struct lance_private *lp = (struct lance_private *) dev->priv; DECLARE_LL; netif_stop_queue (dev); /* Stop the LANCE */ WRITERAP(LE_CSR0); WRITERDP(LE_C0_STOP); free_irq(lp->irq, dev); return 0;}void lance_tx_timeout(struct net_device *dev){ printk("lance_tx_timeout\n"); lance_reset(dev); dev->trans_start = jiffies; netif_start_queue (dev);}int lance_start_xmit (struct sk_buff *skb, struct net_device *dev){ struct lance_private *lp = (struct lance_private *)dev->priv; volatile struct lance_init_block *ib = lp->init_block; int entry, skblen, len; static int outs; unsigned long flags; DECLARE_LL; if (!TX_BUFFS_AVAIL) return -1; netif_stop_queue (dev); skblen = skb->len;#ifdef DEBUG_DRIVER /* dump the packet */ { int i; for (i = 0; i < 64; i++) { if ((i % 16) == 0) printk ("\n"); printk ("%2.2x ", skb->data [i]); } }#endif len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; entry = lp->tx_new & lp->tx_ring_mod_mask; ib->btx_ring [entry].length = (-len) | 0xf000; ib->btx_ring [entry].misc = 0; memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen); /* Now, give the packet to the lance */ ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; outs++; /* Kick the lance: transmit now */ WRITERDP(LE_C0_INEA | LE_C0_TDMD); dev->trans_start = jiffies; dev_kfree_skb (skb); spin_lock_irqsave (&lp->devlock, flags); if (TX_BUFFS_AVAIL) netif_start_queue (dev); else lp->tx_full = 1; spin_unlock_irqrestore (&lp->devlock, flags); return 0;}struct net_device_stats *lance_get_stats (struct net_device *dev){ struct lance_private *lp = (struct lance_private *) dev->priv; return &lp->stats;}/* taken from the depca driver via a2065.c */static void lance_load_multicast (struct net_device *dev){ struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; struct dev_mc_list *dmi=dev->mc_list; char *addrs; int i, j, bit, byte; u32 crc, poly = CRC_POLYNOMIAL_LE; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI){ ib->filter [0] = 0xffffffff; ib->filter [1] = 0xffffffff; return; } /* clear the multicast filter */ ib->filter [0] = 0; ib->filter [1] = 0; /* Add addresses */ for (i = 0; i < dev->mc_count; i++){ addrs = dmi->dmi_addr; dmi = dmi->next; /* multicast address? */ if (!(*addrs & 1)) continue; crc = 0xffffffff; for (byte = 0; byte < 6; byte++) for (bit = *addrs++, j = 0; j < 8; j++, bit>>=1) { int test; test = ((bit ^ crc) & 0x01); crc >>= 1; if (test) { crc = crc ^ poly; } } crc = crc >> 26; mcast_table [crc >> 4] |= 1 << (crc & 0xf); } return;}void lance_set_multicast (struct net_device *dev){ struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; int stopped; DECLARE_LL; stopped = netif_queue_stopped(dev); if (!stopped) netif_stop_queue (dev); while (lp->tx_old != lp->tx_new) schedule(); WRITERAP(LE_CSR0); WRITERDP(LE_C0_STOP); lance_init_ring (dev); if (dev->flags & IFF_PROMISC) { ib->mode |= LE_MO_PROM; } else { ib->mode &= ~LE_MO_PROM; lance_load_multicast (dev); } load_csrs (lp); init_restart_lance (lp); if (!stopped) netif_start_queue (dev);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -