7990.c

来自「linux 内核源代码」· C语言 代码 · 共 674 行 · 第 1/2 页

C
674
字号
                                         len);                        skb->protocol = eth_type_trans (skb, dev);			netif_rx (skb);			dev->last_rx = jiffies;			dev->stats.rx_packets++;			dev->stats.rx_bytes += len;                }                /* Return the packet to the pool */                rd->mblength = 0;                rd->rmd1_bits = LE_R1_OWN;                lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;        }        return 0;}static int lance_tx (struct net_device *dev){        struct lance_private *lp = netdev_priv(dev);        volatile struct lance_init_block *ib = lp->init_block;        volatile struct lance_tx_desc *td;        int i, j;        int status;#ifdef CONFIG_HP300	blinken_leds(0x80, 0);#endif        /* csr0 is 2f3 */        WRITERDP(lp, 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;                        dev->stats.tx_errors++;                        if (status & LE_T3_RTY)  dev->stats.tx_aborted_errors++;                        if (status & LE_T3_LCOL) dev->stats.tx_window_errors++;                        if (status & LE_T3_CLOS) {                                dev->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(lp, LE_CSR0);                                        WRITERDP(lp, 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)) {                                dev->stats.tx_fifo_errors++;                                printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",                                        dev->name);                                /* Stop the lance */                                WRITERAP(lp, LE_CSR0);                                WRITERDP(lp, 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)                                dev->stats.collisions++;                        /* More than one collision, be optimistic. */                        if (td->tmd1_bits & LE_T1_EMORE)                                dev->stats.collisions += 2;                        dev->stats.tx_packets++;                }                j = (j + 1) & lp->tx_ring_mod_mask;        }        lp->tx_old = j;        WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);        return 0;}static irqreturn_tlance_interrupt (int irq, void *dev_id){        struct net_device *dev = (struct net_device *)dev_id;        struct lance_private *lp = netdev_priv(dev);        int csr0;	spin_lock (&lp->devlock);        WRITERAP(lp, LE_CSR0);              /* LANCE Controller Status */        csr0 = READRDP(lp);        PRINT_RINGS();        if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */		spin_unlock (&lp->devlock);                return IRQ_NONE;        /* been generated by the Lance. */	}        /* Acknowledge all the interrupt sources ASAP */        WRITERDP(lp, 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(lp, 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)                dev->stats.tx_errors++;       /* Tx babble. */        if (csr0 & LE_C0_MISS)                dev->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(lp, LE_C0_STRT);        }        if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {		lp->tx_full = 0;		netif_wake_queue (dev);        }        WRITERAP(lp, LE_CSR0);        WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);	spin_unlock (&lp->devlock);	return IRQ_HANDLED;}int lance_open (struct net_device *dev){        struct lance_private *lp = netdev_priv(dev);	int res;        /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */        if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))                return -EAGAIN;        res = lance_reset(dev);	spin_lock_init(&lp->devlock);	netif_start_queue (dev);	return res;}int lance_close (struct net_device *dev){        struct lance_private *lp = netdev_priv(dev);	netif_stop_queue (dev);        /* Stop the LANCE */        WRITERAP(lp, LE_CSR0);        WRITERDP(lp, 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_wake_queue (dev);}int lance_start_xmit (struct sk_buff *skb, struct net_device *dev){        struct lance_private *lp = netdev_priv(dev);        volatile struct lance_init_block *ib = lp->init_block;        int entry, skblen, len;        static int outs;	unsigned long flags;        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;	if (skb->len < ETH_ZLEN)		memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], 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(lp, 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;}/* taken from the depca driver via a2065.c */static void lance_load_multicast (struct net_device *dev){        struct lance_private *lp = netdev_priv(dev);        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;        u32 crc;        /* 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 = ether_crc_le(6, addrs);                crc = crc >> 26;                mcast_table [crc >> 4] |= 1 << (crc & 0xf);        }        return;}void lance_set_multicast (struct net_device *dev){        struct lance_private *lp = netdev_priv(dev);        volatile struct lance_init_block *ib = lp->init_block;	int stopped;	stopped = netif_queue_stopped(dev);	if (!stopped)		netif_stop_queue (dev);        while (lp->tx_old != lp->tx_new)                schedule();        WRITERAP(lp, LE_CSR0);        WRITERDP(lp, 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);}#ifdef CONFIG_NET_POLL_CONTROLLERvoid lance_poll(struct net_device *dev){	struct lance_private *lp = netdev_priv(dev);	spin_lock (&lp->devlock);	WRITERAP(lp, LE_CSR0);	WRITERDP(lp, LE_C0_STRT);	spin_unlock (&lp->devlock);	lance_interrupt(dev->irq, dev);}#endifMODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?