⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 7990.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -