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

📄 lmc_main.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
    //    dev->start = 0;    LMC_XMITTER_BUSY(dev);    sc->stats.tx_tbusy1++ ;    /* stop interrupts */    /* Clear the interrupt mask */    LMC_CSR_WRITE (sc, csr_intr, 0x00000000);    /* Stop Tx and Rx on the chip */    csr6 = LMC_CSR_READ (sc, csr_command);    csr6 &= ~LMC_DEC_ST;		/* Turn off the Transmission bit */    csr6 &= ~LMC_DEC_SR;		/* Turn off the Receive bit */    LMC_CSR_WRITE (sc, csr_command, csr6);    dev->flags &= ~IFF_RUNNING;    sc->stats.rx_missed_errors +=        LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;    /* release the interrupt */    if(sc->got_irq == 1){        free_irq (dev->irq, dev);        sc->got_irq = 0;    }    /* free skbuffs in the Rx queue */    for (i = 0; i < LMC_RXDESCS; i++)    {        struct sk_buff *skb = sc->lmc_rxq[i];        sc->lmc_rxq[i] = 0;        sc->lmc_rxring[i].status = 0;        sc->lmc_rxring[i].length = 0;        sc->lmc_rxring[i].buffer1 = 0xDEADBEEF;        if (skb != NULL)        {            LMC_SKB_FREE(skb, 1);            LMC_DEV_KFREE_SKB (skb);        }        sc->lmc_rxq[i] = NULL;    }    for (i = 0; i < LMC_TXDESCS; i++)    {        if (sc->lmc_txq[i] != NULL)            LMC_DEV_KFREE_SKB (sc->lmc_txq[i]);        sc->lmc_txq[i] = NULL;    }    lmc_led_off (sc, LMC_MII16_LED_ALL);    LMC_XMITTER_FREE(dev);    sc->stats.tx_tbusy0++ ;    lmc_trace(dev, "lmc_ifdown out");    MOD_DEC_USE_COUNT;    return 0;}/* Interrupt handling routine.  This will take an incoming packet, or clean * up after a trasmit. */static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/{    struct net_device *dev = (struct net_device *) dev_instance;    lmc_softc_t *sc;    u32 csr;    int i;    s32 stat;    unsigned int badtx;    u32 firstcsr;    int max_work = LMC_RXDESCS;    lmc_trace(dev, "lmc_interrupt in");    sc = dev->priv;        spin_lock(&sc->lmc_lock);    /*     * Read the csr to find what interrupts we have (if any)     */    csr = LMC_CSR_READ (sc, csr_status);    /*     * Make sure this is our interrupt     */    if ( ! (csr & sc->lmc_intrmask)) {        goto lmc_int_fail_out;    }    firstcsr = csr;    /* always go through this loop at least once */    while (csr & sc->lmc_intrmask) {        /*         * Clear interrupt bits, we handle all case below         */        LMC_CSR_WRITE (sc, csr_status, csr);        /*         * One of         *  - Transmit process timed out CSR5<1>         *  - Transmit jabber timeout    CSR5<3>         *  - 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 {                    #if LINUX_VERSION_CODE >= 0x20200                    sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff;#endif                                        sc->stats.tx_packets++;                }                                //                LMC_DEV_KFREE_SKB (sc->lmc_txq[i]);                dev_kfree_skb_irq(sc->lmc_txq[i]);                sc->lmc_txq[i] = 0;                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;            LMC_XMITTER_FREE(dev);            sc->stats.tx_tbusy0++ ;#if LINUX_VERSION_CODE < 0x20363            mark_bh (NET_BH);	/* Tell Linux to give me more packets */#endif#ifdef DEBUG            sc->stats.dirtyTx = badtx;            sc->stats.lmc_next_tx = sc->lmc_next_tx;            sc->stats.lmc_txfull = sc->lmc_txfull;#if LINUX_VERSION_CODE < 0x20363            sc->stats.tbusy = dev->tbusy;#endif#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");}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;    LMC_SPIN_FLAGS;    lmc_trace(dev, "lmc_start_xmit in");    sc = dev->priv;    spin_lock_irqsave(&sc->lmc_lock, flags);    /*     * If the transmitter is busy     * this must be the 5 second polling     * from the kernel which called us.     * Poke the chip and try to get it running     *     */#if LINUX_VERSION_CODE < 0x20363    if(dev->tbusy != 0){        u32 csr6;        printk("%s: Xmitter busy|\n", dev->name);	sc->stats.tx_tbusy_calls++ ;        if (jiffies - dev->trans_start < TX_TIMEOUT) {            ret = 1;            goto lmc_start_xmit_bug_out;        }        /*         * Chip seems to have locked up         * Reset it         * This whips out all our decriptor         * table and starts from scartch         */        LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO,                      LMC_CSR_READ (sc, csr_status),                      sc->stats.tx_ProcTimeout);        lmc_running_reset (dev);        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));        /* restart the tx processes */        csr6 = LMC_CSR_READ (sc, csr_command);        LMC_CSR_WRITE (sc, csr_command, csr6 | 0x0002);        LMC_CSR_WRITE (sc, csr_command, csr6 | 0x2002);        /* immediate transmit */        LMC_CSR_WRITE (sc, csr_txpoll, 0);        sc->stats.tx_errors++;        sc->stats.tx_ProcTimeout++;	/* -baz */        dev->trans_start = jiffies;        ret = 1;        goto lmc_start_xmit_bug_out;    }#endif    /* 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;        LMC_XMITTER_FREE(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;        LMC_XMITTER_FREE(dev);    }    else if (sc->lmc_next_tx - sc->lmc_taint_tx < LMC_TXDESCS - 1)    {        /* Do not interrupt on completion of this packet */        flag = 0x60000000;        LMC_XMITTER_FREE(dev);    }    else    {        /* This generates an interrupt on completion of this packet */        flag = 0xe0000000;        sc->lmc_txfull = 1;        LMC_XMITTER_BUSY(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;        LMC_XMITTER_BUSY(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;#if LINUX_VERSION_CODE < 0x20363lmc_start_xmit_bug_out:#endif    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;        }

⌨️ 快捷键说明

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