新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > Davicom公司DM9000A和DM9010 ISA NIC 以太網驅動分析

        Davicom公司DM9000A和DM9010 ISA NIC 以太網驅動分析

        作者: 時間:2012-11-02 來源:網絡 收藏

        iow(db, DM9KS_BPTR, 0x3f); /* Less 3kb, 600us */

        iow(db, DM9KS_SMCR, 0); /* Special Mode */

        iow(db, DM9KS_NSR, 0x2c); /* clear TX status */

        iow(db, DM9KS_ISR, 0x0f); /* Clear interrupt status */

        /* Added by jackal at 03/29/2004 */

        #if defined(CHECKSUM)

        iow(db, DM9KS_TCCR, 0x07); /* TX UDP/TCP/IP checksum enable */

        iow(db, DM9KS_RCSR, 0x02); /*Receive checksum enable */

        #endif

        #if defined(ETRANS)

        iow(db, DM9KS_ETXCSR, 0x83);

        #endif

        /* Set address filter table */

        dm9000_hash_table(dev);

        /* Activate / */

        iow(db, DM9KS_RXCR, DM9KS_REG05 | 1); /* RX enable */

        iow(db, DM9KS_IMR, DM9KS_REGFF); // Enable TX/RX interrupt mask

        /* Init Driver variable */

        db->tx_pkt_cnt = 0;

        netif_carrier_on(dev);

        spin_lock_init(db->lock);

        }

        /*

        Hardware start transmission.

        Send a packet to media from the upper layer.

        */

        static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)

        {

        board_info_t *db = (board_info_t *)dev->priv;

        char * data_ptr;

        int i, tmplen;

        if(db->Speed == 10)

        {if (db->tx_pkt_cnt >= 1) return 1;}

        else

        {if (db->tx_pkt_cnt >= 2) return 1;}

        /* packet counting */

        db->tx_pkt_cnt++;

        db->stats.tx_packets++;

        db->stats.tx_bytes+=skb->len;

        if (db->Speed == 10)

        {if (db->tx_pkt_cnt >= 1) netif_stop_queue(dev);}

        else

        {if (db->tx_pkt_cnt >= 2) netif_stop_queue(dev);}

        /* Disable all interrupt */

        iow(db, DM9KS_IMR, DM9KS_DISINTR);

        /* Set TX length to reg. 0xfc 0xfd */

        iow(db, DM9KS_TXPLL, (skb->len 0xff));

        iow(db, DM9KS_TXPLH, (skb->len >> 8) 0xff);

        /* Move data to TX SRAM */

        data_ptr = (char *)skb->data;

        outb(DM9KS_MWCMD, db->io_addr); // Write data into SRAM trigger

        switch(db->io_mode)

        {

        case DM9KS_BYTE_MODE:

        for (i = 0; i skb->len; i++)

        outb((data_ptr[i] 0xff), db->io_data);

        break;

        case DM9KS_WORD_MODE:

        tmplen = (skb->len + 1) / 2;

        for (i = 0; i tmplen; i++)

        outw(((u16 *)data_ptr)[i], db->io_data);

        break;

        case DM9KS_DWORD_MODE:

        tmplen = (skb->len + 3) / 4;

        for (i = 0; i tmplen; i++)

        outl(((u32 *)data_ptr)[i], db->io_data);

        break;

        }

        #if !defined(ETRANS)

        /* Issue TX polling command */

        iow(db, DM9KS_TCR, 0x1); /* Cleared after TX complete*/

        #endif

        /* Saved the time stamp */

        dev->trans_start = jiffies;

        db->cont_rx_pkt_cnt =0;

        /* Free this SKB */

        dev_kfree_skb(skb);

        /* Re-enable interrupt */

        iow(db, DM9KS_IMR, DM9KS_REGFF);

        return 0;

        }

        /*

        Stop the interface.

        The interface is stopped when it is brought.

        */

        static int dmfe_stop(struct net_device *dev)

        {

        board_info_t *db = (board_info_t *)dev->priv;

        DMFE_DBUG(0, dmfe_stop, 0);

        /* deleted timer */

        del_timer(db->timer);

        netif_stop_queue(dev);

        /* free interrupt */

        free_irq(dev->irq, dev);

        /* RESET devie */

        phy_write(db, 0x00, 0x8000); /* PHY RESET */

        iow(db, DM9KS_GPR, 0x01); /* Power-Down PHY */

        iow(db, DM9KS_IMR, DM9KS_DISINTR); /* Disable all interrupt */

        iow(db, DM9KS_RXCR, 0x00); /* Disable RX */

        /* Dump Statistic counter */

        #if FALSE

        printk(nRX FIFO OVERFLOW %lxn, db->stats.rx_fifo_errors);

        printk(RX CRC %lxn, db->stats.rx_crc_errors);

        printk(RX LEN Err %lxn, db->stats.rx_length_errors);

        printk(RESET %xn, db->reset_counter);

        printk(RESET: TX Timeout %xn, db->reset_tx_timeout);

        printk(g_TX_nsr %xn, g_TX_nsr);

        #endif

        return 0;

        }

        static void dmfe_tx_done(unsigned long unused)

        {

        struct net_device *dev = dmfe_dev;

        board_info_t *db = (board_info_t *)dev->priv;

        int nsr;

        DMFE_DBUG(0, dmfe_tx_done(), 0);

        nsr = ior(db, DM9KS_NSR);

        if(nsr 0x04) db->tx_pkt_cnt--;

        if(nsr 0x08) db->tx_pkt_cnt--;

        if (db->tx_pkt_cnt 0)

        {

        printk([dmfe_tx_done] tx_pkt_cnt ERROR!!n);

        db->tx_pkt_cnt =0;

        }

        if (db->Speed == 10)

        {if(db->tx_pkt_cnt 1 ) netif_wake_queue(dev);}

        else

        {if(db->tx_pkt_cnt 2 ) netif_wake_queue(dev);}

        return;

        }

        /*

        DM9000 insterrupt handler

        pid控制相關文章:pid控制原理




        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 中阳县| 丁青县| 石楼县| 百色市| 汕头市| 巩留县| 清苑县| 台安县| 伊金霍洛旗| 开平市| 波密县| 竹溪县| 鲁甸县| 东安县| 平舆县| 郎溪县| 文安县| 瑞丽市| 乐清市| 绿春县| 都昌县| 南投县| 兖州市| 都安| 永新县| 凤冈县| 涞源县| 临江市| 衡阳市| 榆林市| 芷江| 怀来县| 怀柔区| 锦州市| 巴彦淖尔市| 横峰县| 石台县| 翁牛特旗| 伊金霍洛旗| 浦江县| 井陉县|