在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > ARM-Linux驅(qū)動--DM9000網(wǎng)卡驅(qū)動分析(三)

            ARM-Linux驅(qū)動--DM9000網(wǎng)卡驅(qū)動分析(三)

            作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
            ARM-Linux驅(qū)動--DM9000網(wǎng)卡驅(qū)動分析(二)硬件平臺:FL2440(s3c2440
            內(nèi)核版本:2.6.35
            主機平臺:Ubuntu11.04
            內(nèi)核版本:2.6.39
            交叉編譯器:arm-linuc-gcc4.3.2
            原創(chuàng)作品,轉(zhuǎn)載請標明出處http://blog.csdn.net/yming0221/article/details/6615027
            本文接上文
            ARM-Linux驅(qū)動--DM9000網(wǎng)卡驅(qū)動分析(一)
            ARM-Linux驅(qū)動--DM9000網(wǎng)卡驅(qū)動分析(二)
            下面開始看網(wǎng)卡設(shè)備的打開、關(guān)閉函數(shù)和操作函數(shù)
            view plainprint?
            static const struct net_device_ops dm9000_netdev_ops = {
            .ndo_open = dm9000_open,
            .ndo_stop = dm9000_stop,
            .ndo_start_xmit = dm9000_start_xmit,
            .ndo_tx_timeout = dm9000_timeout,
            .ndo_set_multicast_list = dm9000_hash_table,
            .ndo_do_ioctl = dm9000_ioctl,
            .ndo_change_mtu = eth_change_mtu,
            .ndo_validate_addr = eth_validate_addr,
            .ndo_set_mac_address = eth_mac_addr,
            #ifdef CONFIG_NET_POLL_CONTROLLER
            .ndo_poll_controller = dm9000_poll_controller,
            #endif
            };
            1、DM9000的打開函數(shù)
            由于在函數(shù)alloc_netdev_mq()中分配net_device和網(wǎng)卡的私有數(shù)據(jù)是一起分配的,詳見函數(shù)的實現(xiàn)
            view plainprint?
            struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
            void (*setup)(struct net_device *), unsigned int queue_count)
            {
            ...................
            alloc_size = sizeof(struct net_device);
            if (sizeof_priv) {
            alloc_size = ALIGN(alloc_size, NETDEV_ALIGN);
            alloc_size += sizeof_priv;
            }
            alloc_size += NETDEV_ALIGN - 1;
            p = kzalloc(alloc_size, GFP_KERNEL);
            if (!p) {
            printk(KERN_ERR "alloc_netdev: Unable to allocate device.n");
            return NULL;
            }
            tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
            if (!tx) {
            printk(KERN_ERR "alloc_netdev: Unable to allocate "
            "tx qdiscs.n");
            goto free_p;
            }
            #ifdef CONFIG_RPS
            rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL);
            if (!rx) {
            printk(KERN_ERR "alloc_netdev: Unable to allocate "
            "rx queues.n");
            goto free_tx;
            }
            ..............
            }
            所以使用函數(shù)netdev_priv()函數(shù)返回的是網(wǎng)卡的私有數(shù)據(jù)的地址,函數(shù)的實現(xiàn)如下:
            view plainprint?
            static inline void *netdev_priv(const struct net_device *dev)
            {
            return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN);
            }
            這樣兩者會同時生存和消失。
            dm9000_open()函數(shù)
            view plainprint?
            static int
            dm9000_open(struct net_device *dev)
            {
            board_info_t *db = netdev_priv(dev);
            unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
            if (netif_msg_ifup(db))
            dev_dbg(db->dev, "enabling %sn", dev->name);
            if (irqflags == IRQF_TRIGGER_NONE)
            dev_warn(db->dev, "WARNING: no IRQ resource flags set.n");
            irqflags |= IRQF_SHARED;
            if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
            return -EAGAIN;
            dm9000_reset(db);
            dm9000_init_dm9000(dev);
            db->dbug_cnt = 0;
            mii_check_media(&db->mii, netif_msg_link(db), 1);
            netif_start_queue(dev);
            dm9000_schedule_poll(db);
            return 0;
            }
            2、網(wǎng)卡關(guān)閉函數(shù)
            view plainprint?
            static int
            dm9000_stop(struct net_device *ndev)
            {
            board_info_t *db = netdev_priv(ndev);
            if (netif_msg_ifdown(db))
            dev_dbg(db->dev, "shutting down %sn", ndev->name);
            cancel_delayed_work_sync(&db->phy_poll);
            netif_stop_queue(ndev);
            netif_carrier_off(ndev);
            free_irq(ndev->irq, ndev);
            dm9000_shutdown(ndev);
            return 0;
            }
            下面是調(diào)用的dm9000_shutdown(ndev)函數(shù),該函數(shù)的功能是復位phy,配置寄存器GPR位0為1,關(guān)閉dm9000電源,配置寄存器IMR位7為1,disable中斷,配置寄存器RCR,disable接收
            函數(shù)如下:
            view plainprint?
            static void
            dm9000_shutdown(struct net_device *dev)
            {
            board_info_t *db = netdev_priv(dev);
            dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);
            iow(db, DM9000_GPR, 0x01);
            iow(db, DM9000_IMR, IMR_PAR);
            iow(db, DM9000_RCR, 0x00);
            }
            3、接下來了解一下數(shù)據(jù)的發(fā)送函數(shù)dm9000_start_xmit
            上圖可以看出DM9000的SRAM中地址0x0000到0x0BFF是TXBuffer,從0x0C00到0x3FFF是RXBuffer,包的有效數(shù)據(jù)必須提前放到TXBuffer緩沖區(qū),使用端口命令來選擇MWCMD寄存器。最后設(shè)置TXCR寄存器的bit[0]TXREQ來自動發(fā)送包。
            發(fā)送包的步驟如下:
            (1)檢查存儲器寬度,通過讀取ISR的bit[7:6]來確定位數(shù)
            (2)寫數(shù)據(jù)到TXSRAM
            (3)寫傳輸長度到TXPLL和TXPLH寄存器
            (4)設(shè)置TXCR的bit[0]TXREQ來發(fā)送包
            view plainprint?
            static int
            dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
            {
            unsigned long flags;
            board_info_t *db = netdev_priv(dev);
            dm9000_dbg(db, 3, "%s:n", __func__);
            if (db->tx_pkt_cnt > 1)
            return NETDEV_TX_BUSY;
            spin_lock_irqsave(&db->lock, flags);
            writeb(DM9000_MWCMD, db->io_addr);
            (db->outblk)(db->io_data, skb->data, skb->len);
            dev->stats.tx_bytes += skb->len;
            db->tx_pkt_cnt++;
            if (db->tx_pkt_cnt == 1) {
            dm9000_send_packet(dev, skb->ip_summed, skb->len);
            } else {
            db->queue_pkt_len = skb->len;
            db->queue_ip_summed = skb->ip_summed;
            netif_stop_queue(dev);
            }
            spin_unlock_irqrestore(&db->lock, flags);
            dev_kfree_skb(skb);
            return NETDEV_TX_OK;
            }
            上面函數(shù)調(diào)用下面的函數(shù) dm9000_send_packet來發(fā)送數(shù)據(jù)
            view plainprint?
            static void dm9000_send_packet(struct net_device *dev,
            int ip_summed,
            u16 pkt_len)
            {
            board_info_t *dm = to_dm9000_board(dev);
            if (dm->ip_summed != ip_summed) {
            if (ip_summed == CHECKSUM_NONE)
            iow(dm, DM9000_TCCR, 0);
            else
            iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);
            dm->ip_summed = ip_summed;
            }
            iow(dm, DM9000_TXPLL, pkt_len);
            iow(dm, DM9000_TXPLH, pkt_len >> 8);
            iow(dm, DM9000_TCR, TCR_TXREQ);
            }
            5、下面看一下當一個數(shù)據(jù)包發(fā)送完成后的中斷處理函數(shù)dm9000_tx_done
            view plainprint?
            static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
            {
            int tx_status = ior(db, DM9000_NSR);
            if (tx_status & (NSR_TX2END | NSR_TX1END)) {
            db->tx_pkt_cnt--;
            dev->stats.tx_packets++;
            if (netif_msg_tx_done(db))
            dev_dbg(db->dev, "tx done, NSR xn", tx_status);
            if (db->tx_pkt_cnt > 0)
            dm9000_send_packet(dev, db->queue_ip_summed,
            db->queue_pkt_len);
            netif_wake_queue(dev);
            }
            }


            評論


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

            關(guān)閉