新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Davicom公司DM9000A和DM9010 ISA NIC 以太網(wǎng)驅(qū)動(dòng)分析

        Davicom公司DM9000A和DM9010 ISA NIC 以太網(wǎng)驅(qū)動(dòng)分析

        作者: 時(shí)間:2012-11-02 來源:網(wǎng)絡(luò) 收藏

        #define check_rx_ready(a) ((a) == 0x01)

        #else

        inline u8 check_rx_ready(u8 rxbyte)

        {

        if (!(rxbyte 0x01))

        return 0;

        return ((rxbyte >> 4) | 0x01);

        }

        #endif

        /*

        Received a packet and pass to upper layer

        */

        static void dmfe_packet_receive(struct net_device *dev)

        {

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

        struct sk_buff *skb;

        u8 rxbyte, val;

        u16 i, GoodPacket, tmplen = 0, MDRAH, MDRAL;

        u32 tmpdata;

        rx_t rx;

        u16 * ptr = (u16*)rx;

        u8* rdptr;

        DMFE_DBUG(0, dmfe_packet_receive(), 0);

        do {

        /*store the value of Memory Data Read address register*/

        MDRAH=ior(db, DM9KS_MDRAH);

        MDRAL=ior(db, DM9KS_MDRAL);

        ior(db, DM9KS_MRCMDX); /* Dummy read */

        rxbyte = inb(db->io_data); /* Got most updated data */

        /* packet ready to receive check */

        if(!(val = check_rx_ready(rxbyte))) break;

        /* A packet ready now Get status/length */

        GoodPacket = TRUE;

        outb(DM9KS_MRCMD, db->io_addr);

        /* Read packet status length */

        switch (db->io_mode)

        {

        case DM9KS_BYTE_MODE:

        *ptr = inb(db->io_data) +

        (inb(db->io_data) 8);

        *(ptr+1) = inb(db->io_data) +

        (inb(db->io_data) 8);

        break;

        case DM9KS_WORD_MODE:

        *ptr = inw(db->io_data);

        *(ptr+1) = inw(db->io_data);

        break;

        case DM9KS_DWORD_MODE:

        tmpdata = inl(db->io_data);

        *ptr = tmpdata;

        *(ptr+1) = tmpdata >> 16;

        break;

        default:

        break;

        }

        /* Packet status check */

        if (rx.desc.status 0xbf)

        {

        GoodPacket = FALSE;

        if (rx.desc.status 0x01)

        {

        db->stats.rx_fifo_errors++;

        printk(n);

        }

        if (rx.desc.status 0x02)

        {

        db->stats.rx_crc_errors++;

        printk(n);

        }

        if (rx.desc.status 0x80)

        {

        db->stats.rx_length_errors++;

        printk(n);

        }

        if (rx.desc.status 0x08)

        printk(n);

        }

        if (!GoodPacket)

        {

        // drop this packet!!!

        switch (db->io_mode)

        {

        case DM9KS_BYTE_MODE:

        for (i=0; i

        inb(db->io_data);

        break;

        case DM9KS_WORD_MODE:

        tmplen = (rx.desc.length + 1) / 2;

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

        inw(db->io_data);

        break;

        case DM9KS_DWORD_MODE:

        tmplen = (rx.desc.length + 3) / 4;

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

        inl(db->io_data);

        break;

        }

        continue;/*next the packet*/

        }

        skb = dev_alloc_skb(rx.desc.length+4);

        if (skb == NULL )

        {

        printk(KERN_INFO %s: Memory squeeze.n, dev->name);

        /*re-load the value into Memory data read address register*/

        iow(db,DM9KS_MDRAH,MDRAH);

        iow(db,DM9KS_MDRAL,MDRAL);

        return;

        }

        else

        {

        /* Move data from DM9000 */

        skb->dev = dev;

        skb_reserve(skb, 2);

        rdptr = (u8*)skb_put(skb, rx.desc.length - 4);

        /* Read received packet from RX SARM */

        switch (db->io_mode)

        {

        case DM9KS_BYTE_MODE:

        for (i=0; i

        rdptr[i]=inb(db->io_data);

        break;

        case DM9KS_WORD_MODE:

        tmplen = (rx.desc.length + 1) / 2;

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

        ((u16 *)rdptr)[i] = inw(db->io_data);

        break;

        case DM9KS_DWORD_MODE:

        tmplen = (rx.desc.length + 3) / 4;

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

        ((u32 *)rdptr)[i] = inl(db->io_data);

        break;

        }

        /* Pass to upper layer */

        skb->protocol = eth_type_trans(skb,dev);

        #if defined(CHECKSUM)

        if (val == 0x01)

        skb->ip_summed = CHECKSUM_UNNECESSARY;

        #endif

        netif_rx(skb);

        dev->last_rx=jiffies;

        db->stats.rx_packets++;

        db->stats.rx_bytes += rx.desc.length;

        db->cont_rx_pkt_cnt++;

        if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)

        {

        dmfe_tx_done(0);

        break;

        }

        }

        }while((rxbyte 0x01) == DM9KS_PKT_RDY);

        DMFE_DBUG(0, [END]dmfe_packet_receive(), 0);

        }

        /*

        Read a word data from SROM

        */

        static u16 read_srom_word(board_info_t *db, int offset)

        {

        iow(db, DM9KS_EPAR, offset);

        iow(db, DM9KS_EPCR, 0x4);

        udelay(200);

        iow(db, DM9KS_EPCR, 0x0);

        pid控制相關(guān)文章:pid控制原理




        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 海城市| 楚雄市| 萨迦县| 青冈县| 营口市| 乌拉特后旗| 朝阳县| 垣曲县| 麻城市| 东至县| 蒙城县| 普洱| 渭南市| 察隅县| 桑植县| 新昌县| 拜泉县| 南华县| 大丰市| 姚安县| 余干县| 鸡泽县| 开江县| 双辽市| 鄢陵县| 定安县| 东丽区| 光泽县| 南江县| 若尔盖县| 彰化市| 闵行区| 桂林市| 迭部县| 平谷区| 乐东| 塔城市| 北辰区| 隆子县| 宾川县| 象山县|