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

📄 lmc_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
         *  - Transmit underflow         CSR5<5>         *  - Transmit Receiver buffer unavailable CSR5<7>         *  - Receive process stopped    CSR5<8>         *  - Receive watchdog timeout   CSR5<9>         *  - Early transmit interrupt   CSR5<10>         *         * Is this really right? Should we do a running reset for jabber?         * (being a WAN card and all)         */        if (csr & TULIP_STS_ABNRMLINTR){            lmc_running_reset (dev);            break;        }                if (csr & TULIP_STS_RXINTR){            lmc_trace(dev, "rx interrupt");            lmc_rx (dev);                    }        if (csr & (TULIP_STS_TXINTR | TULIP_STS_TXNOBUF | TULIP_STS_TXSTOPPED)) {	    int		n_compl = 0 ;            /* reset the transmit timeout detection flag -baz */            sc->stats.tx_NoCompleteCnt = 0;            badtx = sc->lmc_taint_tx;            i = badtx % LMC_TXDESCS;            while ((badtx < sc->lmc_next_tx)) {                stat = sc->lmc_txring[i].status;                LMC_EVENT_LOG (LMC_EVENT_XMTINT, stat,						 sc->lmc_txring[i].length);                /*                 * If bit 31 is 1 the tulip owns it break out of the loop                 */                if (stat & 0x80000000)                    break;		n_compl++ ;		/* i.e., have an empty slot in ring */                /*                 * If we have no skbuff or have cleared it                 * Already continue to the next buffer                 */                if (sc->lmc_txq[i] == NULL)                    continue;                /*                 * Check the total error summary to look for any errors                 */                if (stat & 0x8000) {                    sc->stats.tx_errors++;                    if (stat & 0x4104)                        sc->stats.tx_aborted_errors++;                    if (stat & 0x0C00)                        sc->stats.tx_carrier_errors++;                    if (stat & 0x0200)                        sc->stats.tx_window_errors++;                    if (stat & 0x0002)                        sc->stats.tx_fifo_errors++;                }                else {                                        sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff;                                        sc->stats.tx_packets++;                }                                //                dev_kfree_skb(sc->lmc_txq[i]);                dev_kfree_skb_irq(sc->lmc_txq[i]);                sc->lmc_txq[i] = NULL;                badtx++;                i = badtx % LMC_TXDESCS;            }            if (sc->lmc_next_tx - badtx > LMC_TXDESCS)            {                printk ("%s: out of sync pointer\n", dev->name);                badtx += LMC_TXDESCS;            }            LMC_EVENT_LOG(LMC_EVENT_TBUSY0, n_compl, 0);            sc->lmc_txfull = 0;            netif_wake_queue(dev);            sc->stats.tx_tbusy0++ ;#ifdef DEBUG            sc->stats.dirtyTx = badtx;            sc->stats.lmc_next_tx = sc->lmc_next_tx;            sc->stats.lmc_txfull = sc->lmc_txfull;#endif            sc->lmc_taint_tx = badtx;            /*             * Why was there a break here???             */        }			/* end handle transmit interrupt */        if (csr & TULIP_STS_SYSERROR) {            u32 error;            printk (KERN_WARNING "%s: system bus error csr: %#8.8x\n", dev->name, csr);            error = csr>>23 & 0x7;            switch(error){            case 0x000:                printk(KERN_WARNING "%s: Parity Fault (bad)\n", dev->name);                break;            case 0x001:                printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name);                break;            case 0x010:                printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name);                break;            default:                printk(KERN_WARNING "%s: This bus error code was supposed to be reserved!\n", dev->name);            }            lmc_dec_reset (sc);            lmc_reset (sc);            LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0);            LMC_EVENT_LOG(LMC_EVENT_RESET2,                          lmc_mii_readreg (sc, 0, 16),                          lmc_mii_readreg (sc, 0, 17));        }                if(max_work-- <= 0)            break;                /*         * Get current csr status to make sure         * we've cleared all interrupts         */        csr = LMC_CSR_READ (sc, csr_status);    }				/* end interrupt loop */    LMC_EVENT_LOG(LMC_EVENT_INT, firstcsr, csr);lmc_int_fail_out:    spin_unlock(&sc->lmc_lock);    lmc_trace(dev, "lmc_interrupt out");    return IRQ_RETVAL(handled);}static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/{    lmc_softc_t *sc;    u32 flag;    int entry;    int ret = 0;    unsigned long flags;    lmc_trace(dev, "lmc_start_xmit in");    sc = dev->priv;    spin_lock_irqsave(&sc->lmc_lock, flags);    /* normal path, tbusy known to be zero */    entry = sc->lmc_next_tx % LMC_TXDESCS;    sc->lmc_txq[entry] = skb;    sc->lmc_txring[entry].buffer1 = virt_to_bus (skb->data);    LMC_CONSOLE_LOG("xmit", skb->data, skb->len);#ifndef GCOM    /* If the queue is less than half full, don't interrupt */    if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS / 2)    {        /* Do not interrupt on completion of this packet */        flag = 0x60000000;        netif_wake_queue(dev);    }    else if (sc->lmc_next_tx - sc->lmc_taint_tx == LMC_TXDESCS / 2)    {        /* This generates an interrupt on completion of this packet */        flag = 0xe0000000;        netif_wake_queue(dev);    }    else if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS - 1)    {        /* Do not interrupt on completion of this packet */        flag = 0x60000000;        netif_wake_queue(dev);    }    else    {        /* This generates an interrupt on completion of this packet */        flag = 0xe0000000;        sc->lmc_txfull = 1;        netif_stop_queue(dev);    }#else    flag = LMC_TDES_INTERRUPT_ON_COMPLETION;    if (sc->lmc_next_tx - sc->lmc_taint_tx >= LMC_TXDESCS - 1)    {				/* ring full, go busy */        sc->lmc_txfull = 1;        netif_stop_queue(dev);        sc->stats.tx_tbusy1++ ;        LMC_EVENT_LOG(LMC_EVENT_TBUSY1, entry, 0);    }#endif    if (entry == LMC_TXDESCS - 1)	/* last descriptor in ring */	flag |= LMC_TDES_END_OF_RING;	/* flag as such for Tulip */    /* don't pad small packets either */    flag = sc->lmc_txring[entry].length = (skb->len) | flag |						sc->TxDescriptControlInit;    /* set the transmit timeout flag to be checked in     * the watchdog timer handler. -baz     */    sc->stats.tx_NoCompleteCnt++;    sc->lmc_next_tx++;    /* give ownership to the chip */    LMC_EVENT_LOG(LMC_EVENT_XMT, flag, entry);    sc->lmc_txring[entry].status = 0x80000000;    /* send now! */    LMC_CSR_WRITE (sc, csr_txpoll, 0);    dev->trans_start = jiffies;    spin_unlock_irqrestore(&sc->lmc_lock, flags);    lmc_trace(dev, "lmc_start_xmit_out");    return ret;}static int lmc_rx (struct net_device *dev) /*fold00*/{    lmc_softc_t *sc;    int i;    int rx_work_limit = LMC_RXDESCS;    unsigned int next_rx;    int rxIntLoopCnt;		/* debug -baz */    int localLengthErrCnt = 0;    long stat;    struct sk_buff *skb, *nsb;    u16 len;    lmc_trace(dev, "lmc_rx in");    sc = dev->priv;    lmc_led_on(sc, LMC_DS3_LED3);    rxIntLoopCnt = 0;		/* debug -baz */    i = sc->lmc_next_rx % LMC_RXDESCS;    next_rx = sc->lmc_next_rx;    while (((stat = sc->lmc_rxring[i].status) & LMC_RDES_OWN_BIT) != DESC_OWNED_BY_DC21X4)    {        rxIntLoopCnt++;		/* debug -baz */        len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER);        if ((stat & 0x0300) != 0x0300) {  /* Check first segment and last segment */            if ((stat & 0x0000ffff) != 0x7fff) {                /* Oversized frame */                sc->stats.rx_length_errors++;                goto skip_packet;            }        }        if(stat & 0x00000008){ /* Catch a dribbling bit error */            sc->stats.rx_errors++;            sc->stats.rx_frame_errors++;            goto skip_packet;        }        if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */            sc->stats.rx_errors++;            sc->stats.rx_crc_errors++;            goto skip_packet;        }        if (len > LMC_PKT_BUF_SZ){            sc->stats.rx_length_errors++;            localLengthErrCnt++;            goto skip_packet;        }        if (len < sc->lmc_crcSize + 2) {            sc->stats.rx_length_errors++;            sc->stats.rx_SmallPktCnt++;            localLengthErrCnt++;            goto skip_packet;        }        if(stat & 0x00004000){            printk(KERN_WARNING "%s: Receiver descriptor error, receiver out of sync?\n", dev->name);        }        len -= sc->lmc_crcSize;        skb = sc->lmc_rxq[i];        /*         * We ran out of memory at some point         * just allocate an skb buff and continue.         */                if(skb == 0x0){            nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);            if (nsb) {                sc->lmc_rxq[i] = nsb;                nsb->dev = dev;                sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);            }            sc->failed_recv_alloc = 1;            goto skip_packet;        }                dev->last_rx = jiffies;        sc->stats.rx_packets++;        sc->stats.rx_bytes += len;        LMC_CONSOLE_LOG("recv", skb->data, len);        /*         * I'm not sure of the sanity of this         * Packets could be arriving at a constant         * 44.210mbits/sec and we're going to copy         * them into a new buffer??         */                if(len > (LMC_MTU - (LMC_MTU>>2))){ /* len > LMC_MTU * 0.75 */            /*             * If it's a large packet don't copy it just hand it up             */        give_it_anyways:            sc->lmc_rxq[i] = NULL;            sc->lmc_rxring[i].buffer1 = 0x0;            skb_put (skb, len);            skb->protocol = lmc_proto_type(sc, skb);            skb->protocol = htons(ETH_P_WAN_PPP);            skb->mac.raw = skb->data;//            skb->nh.raw = skb->data;            skb->dev = dev;            lmc_proto_netif(sc, skb);            /*             * This skb will be destroyed by the upper layers, make a new one             */            nsb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2);            if (nsb) {                sc->lmc_rxq[i] = nsb;                nsb->dev = dev;                sc->lmc_rxring[i].buffer1 = virt_to_bus (nsb->tail);                /* Transferred to 21140 below */            }            else {                /*                 * We've run out of memory, stop trying to allocate                 * memory and exit the interrupt handler                 *                 * The chip may run out of receivers and stop                 * in which care we'll try to allocate the buffer                 * again.  (once a second)                 */                sc->stats.rx_BuffAllocErr++;                LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len);                sc->failed_recv_alloc = 1;                goto skip_out_of_mem;            }        }        else {            nsb = dev_alloc_skb(len);            if(!nsb) {                goto give_it_anyways;            }            memcpy(skb_put(nsb, len), skb->data, len);                        nsb->protocol = lmc_proto_type(sc, skb);            nsb->mac.raw = nsb->data;//            nsb->nh.raw = nsb->data;            nsb->dev = dev;            lmc_proto_netif(sc, nsb);        }    skip_packet:        LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len);        sc->lmc_rxring[i].status = DESC_OWNED_BY_DC21X4;        sc->lmc_next_rx++;        i = sc->lmc_next_rx % LMC_RXDESCS;        rx_work_limit--;        if (rx_work_limit < 0)            break;    }    /* detect condition for LMC1000 where DSU cable attaches and fills     * descriptors with bogus packets     *    if (localLengthErrCnt > LMC_RXDESCS - 3) {        sc->stats.rx_BadPktSurgeCnt++;        LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE,                      localLengthErrCnt,                      sc->stats.rx_BadPktSurgeCnt);    } */    /* save max count of receive descriptors serviced */    if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) {        sc->stats.rxIntLoopCnt = rxIntLoopCnt;	/* debug -baz */    }#ifdef DEBUG    if (rxIntLoopCnt == 0)    {        for (i = 0; i < LMC_RXDESCS; i++)        {            if ((sc->lmc_rxring[i].status & LMC_RDES_OWN_BIT)                != DESC_OWNED_BY_DC21X4)            {                rxIntLoopCnt++;            }        }        LMC_EVENT_LOG(LMC_EVENT_RCVEND, rxIntLoopCnt, 0);    }#endif    lmc_led_off(sc, LMC_DS3_LED3);skip_out_of_mem:    lmc_trace(dev, "lmc_rx out");

⌨️ 快捷键说明

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