欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Linux設備驅動(dòng)簡(jiǎn)析--dm9000網(wǎng)卡驅動(dòng) - Network - Neil Chiao's Blog

Linux設備驅動(dòng)簡(jiǎn)析--dm9000網(wǎng)卡驅動(dòng)


/*

*By Neil Chiao (neilchiao at gmail.com)

*轉載請注明出處:neilengineer.cublog.cn

*本文部分內容來(lái)自網(wǎng)絡(luò )

*歡迎到“新星灣(www.xinxingwan.com)”指導

*/

 

1、Linux網(wǎng)絡(luò )設備驅動(dòng)的體系結構

Linux網(wǎng)絡(luò )驅動(dòng)程序的體系結構可劃分為4個(gè)層次。Linux內核源代碼中提供了網(wǎng)絡(luò )設備接口及以上層次的代碼,因此移植特定網(wǎng)絡(luò )硬件的驅動(dòng)程序的主要工作就是完成設備驅動(dòng)功能層的相應代碼,根據底層具體的硬件特性,定義網(wǎng)絡(luò )設備接口struct net_device類(lèi)型的結構體變量,并實(shí)現其中相應的操作函數及中斷處理程序。

Linux中所有的網(wǎng)絡(luò )設備都抽象為一個(gè)統一的接口,即網(wǎng)絡(luò )設備接口,通過(guò)struct net_device類(lèi)型的結構體變量表示網(wǎng)絡(luò )設備在內核中的運行情況,這里既包括回環(huán)(loopback)設備,也包括硬件網(wǎng)絡(luò )設備接口。內核通過(guò)以dev_base<drives/net/space.c>為頭指針的設備鏈表來(lái)管理所有的網(wǎng)絡(luò )設備。

 

net_device數據結構

struct net_device結構體是整個(gè)網(wǎng)絡(luò )驅動(dòng)結構的核心,其中定義了很多供網(wǎng)絡(luò )協(xié)議接口層調用設備的標準方法,該結構在<include/linux/netdevice.h>文件中定義,下面只列出其中主要的成員。

 

1)全局信息及底層硬件信息

name:      網(wǎng)絡(luò )設備名稱(chēng);

base_addr,irq:         網(wǎng)絡(luò )設備的I/O基地址,中斷號,ifconfig命令可顯示和修改;

hard_header_len:    硬件頭的長(cháng)度,以太網(wǎng)中值為14;

mtu:               最大傳輸單元,以太網(wǎng)中值為1500B;

dev_addr[MAX_ADDR_LEN]:      MAC地址,ether_setup會(huì )對其進(jìn)行正確的設置;

 

2)主要的操作方法

int (*init)(struct net_device *dev);       設備初始化和向系統注冊的函數,僅調用一次;

int (*open)(struct net_device *dev);     設備打開(kāi)接口函數,當用ifconfig激活網(wǎng)絡(luò )設備時(shí)被調用,注冊所用的系統資源(I/O端口,IRQ,DMA等)同時(shí)激活硬件并增加使用計數;

int (*stop)(struct net_device *dev);      執行open方法的反操作;

*hard_start_xmit; 初始化數據包傳輸的函數;

 

網(wǎng)絡(luò )驅動(dòng)程序實(shí)現原理

Linux網(wǎng)絡(luò )系統各個(gè)層次之間的數據傳送都是通過(guò)套接字緩沖區sk_buff完成的,sk_buff數據結構是各層協(xié)議數據處理的對象。sk_buff<linux/skbuff.h>是驅動(dòng)程序與網(wǎng)絡(luò )之間交換數據的媒介,驅動(dòng)程序向網(wǎng)絡(luò )發(fā)送數據時(shí),必須從其中獲取數據源和數據長(cháng)度;驅動(dòng)程序從網(wǎng)絡(luò )上接收到數據后也要將數據保存到sk_buff中才能交給上層協(xié)議處理。

網(wǎng)絡(luò )驅動(dòng)程序主要的幾個(gè)操作如下:

1) 初始化(init)

驅動(dòng)程序必須有一個(gè)初始化方法。在把驅動(dòng)程序載入系統的時(shí)候會(huì )調用這個(gè)初始化程序,它做以下幾方面的工作。

檢測設備。配置和初始化硬件。配置或協(xié)商好硬件占用的資源以后,就可以向系統申請這些資源。有些資源是可以和別的設備共享的,如中斷。有些是不能共享的,如IO、DMA。接下來(lái)你要初始化device結構中的變量。最后,你可以讓硬件正式開(kāi)始工作。

 

2) 打開(kāi)(open)

open這個(gè)方法在網(wǎng)絡(luò )設備驅動(dòng)里是網(wǎng)絡(luò )設備被激活的時(shí)候被調用(即設備狀態(tài)由down-->up)。所以實(shí)際上很多在initialize中的工作可以放到這里來(lái)做。比如資源的申請,硬件的激活。如果dev->open返回非0(error),則硬件的狀態(tài)還是down。 open方法另一個(gè)作用是如果驅動(dòng)程序做為一個(gè)模塊被裝入,則要防止模塊卸載時(shí)設備處于打開(kāi)狀態(tài)。在open方法里要調用MOD_INC_USE_COUNT宏。

 

3)關(guān)閉(stop)

stop方法做和open相反的工作??梢葬尫拍承┵Y源以減少系統負擔。stop是在設備狀態(tài)由up轉為down時(shí)被調用的。另外如果是做為模塊裝入的驅動(dòng)程序,close里應該調用MOD_DEC_USE_COUNT,減少設備被引用的次數,以使驅動(dòng)程序可以被卸載。

 

4) 發(fā)送(hard_start_xmit)

所有的網(wǎng)絡(luò )設備驅動(dòng)都必須有這個(gè)發(fā)送方法。在系統調用驅動(dòng)程序的xmit時(shí),發(fā)送的數據放在一個(gè)sk_buff結構中。一般的驅動(dòng)把數據傳給硬件發(fā)出去。也有一些特殊的設備比如loopback把數據組成一個(gè)接收數據再回送給系統,或者dummy設備直接丟棄數據。如果發(fā)送成功,hard_start_xmit方法里釋放sk_buff,返回0(發(fā)送成功)。如果設備暫時(shí)無(wú)法處理,比如硬件忙,則返回1。這時(shí)如果dev->tbusy置為非0,則系統認為硬件忙,要等到dev->tbusy0以后才會(huì )再次發(fā)送。tbusy的置0任務(wù)一般由中斷完成。硬件在發(fā)送結束后產(chǎn)生中斷,這時(shí)可以把tbusy0,然后用mark_bh()調用通知系統可以再次發(fā)送。在發(fā)送不成功的情況下,也可以不置dev->tbusy為非0,這樣系統會(huì )不斷嘗試重發(fā)。如果hard_start_xmit發(fā)送不成功,則不要釋放sk_buff。傳送下來(lái)的sk_buff中的數據已經(jīng)包含硬件需要的幀頭。所以在發(fā)送方法里不需要再填充硬件幀頭,數據可以直接提交給硬件發(fā)送。sk_buff是被鎖住的(locked),確保其他程序不會(huì )存取它。

 

5) 接收(reception)

有數據收到時(shí),驅動(dòng)程序通知系統。一般設備收到數據后都會(huì )產(chǎn)生一個(gè)中斷,在中斷處理程序中驅動(dòng)程序申請一塊sk_buff(skb),從硬件讀出數據放置到申請好的緩沖區里。接下來(lái)填充sk_buff中的一些信息。skb->dev= dev,判斷收到幀的協(xié)議類(lèi)型,填入skb->protocol(多協(xié)議的支持)。把指針skb->mac.raw指向硬件數據然后丟棄硬件幀頭(skb_pull)。還要設置skb->pkt_type,標明第二層(鏈路層)數據類(lèi)型??梢允且韵骂?lèi)型:

PACKET_BROADCAST : 鏈路層廣播;

PACKET_MULTICAST : 鏈路層組播;

PACKET_SELF : 發(fā)給自己的幀;

PACKET_OTHERHOST : 發(fā)給別人的幀(監聽(tīng)模式時(shí)會(huì )有這種幀)。

最后調用netif_rx()把數據傳送給協(xié)議層。netif_rx()里數據放入處理隊列然后返回,真正的處理是在中斷返回以后,這樣可以減少中斷時(shí)間。調用netif_rx()以后,驅動(dòng)程序就不能再存取數據緩沖區skb。

 

2、dm9000網(wǎng)卡驅動(dòng)簡(jiǎn)析

Dm9000是嵌入式平臺上常用的MAC+PHY芯片。針對各種SoC,2.6內核引進(jìn)了platform設備模型來(lái)封裝相關(guān)驅動(dòng),Dm9000驅動(dòng)就用platform改寫(xiě)了。

       在分析dm9000驅動(dòng)前,先看一下platform,其大致調用過(guò)程如下:

start_kernelàrest_initàkernel_initàdo_basic_setupà driver_inità platform_bus_init

int __init platform_bus_init(void)

{

。。。。。。

       error = device_register(&platform_bus);

。。。。。。

       error = bus_register(&platform_bus_type);

。。。。。。

}

      

dm9000驅動(dòng)模塊初始化函數dm9000_init使用了platform_driver_register來(lái)注冊:

static int __init dm9000_init(void)

{

       printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION);

       return platform_driver_register(&dm9000_driver);

}

其中,&dm9000_driver如下定義:

static struct platform_driver dm9000_driver = {

       .driver     = {

              .name    = "dm9000",

              .owner    = THIS_MODULE,

       },

       .probe   = dm9000_probe,

       .remove  = __devexit_p(dm9000_drv_remove),

       .suspend = dm9000_drv_suspend,

       .resume  = dm9000_drv_resume,

};

       使用platform_driver_register(&dm9000_driver) 注冊dm9000_driver,會(huì )調用其中的.probe也就是這里的dm9000_probe函數。其調用過(guò)程如下:

platform_driver_register(&dm9000_driver)à

driver_register(&drv->driver)à

bus_add_driver(drv)à

driver_attach(drv) à

bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)à

__driver_attachà

driver_probe_device(drv, dev)à

really_probe(dev, drv) à

if (dev->bus->probe)  dev->bus->probe(dev)

    else if (drv->probe) drv->probe(dev)       //調用dm9000_probe()

 

dm9000_probe函數分析

       dm9000_probe函數實(shí)現如下:

static int __devinit dm9000_probe(struct platform_device *pdev)

{

......

       ndev = alloc_etherdev(sizeof(struct board_info));

//分配空間,并初始化部分東西

......

db = ndev->priv;

       memset(db, 0, sizeof(*db));

       db->dev = &pdev->dev;

       db->ndev = ndev;

       INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);

       db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

       db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);

       db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

       iosize = res_size(db->addr_res);

       db->addr_req = request_mem_region(db->addr_res->start, iosize,pdev->name);

       db->io_addr = ioremap(db->addr_res->start, iosize);

       iosize = res_size(db->data_res);

       db->data_req = request_mem_region(db->data_res->start, iosize, pdev->name);

       db->io_data = ioremap(db->data_res->start, iosize);

//上述代碼初始化bd結構體,bddm9000.c中定義的board結構,其中db = ndev->priv;

db初始化為net device中的priv成員。

......

//初始化net_device結構體中的一些重要函數指針及變量

       ether_setup(ndev);

 

ndev->open           = &dm9000_open;

       ndev->hard_start_xmit    = &dm9000_start_xmit;

       ndev->tx_timeout         = &dm9000_timeout;

       ndev->watchdog_timeo = msecs_to_jiffies(watchdog);

       ndev->stop            = &dm9000_stop;

       ndev->set_multicast_list = &dm9000_hash_table;

       ndev->ethtool_ops  = &dm9000_ethtool_ops;

       ndev->do_ioctl              = &dm9000_ioctl;

......

//初始化MII接口使用的最重要2個(gè)函數

       db->mii.mdio_read    = dm9000_phy_read;

       db->mii.mdio_write   = dm9000_phy_write;

......

//E2PROM中讀取MAC地址,并驗證是否為合法MAC地址

       for (i = 0; i < 6; i += 2)

              dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);

       if (!is_valid_ether_addr(ndev->dev_addr))

              dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "

                      "set using ifconfig\n", ndev->name);

......

//最終注冊

       ret = register_netdev(ndev);

}

      

       DM9000的驅動(dòng)初始化基本是由probe函數進(jìn)行。

實(shí)際發(fā)送數據在dm9000_start_xmit函數中實(shí)現,而接收數據在中斷處理函數dm9000_interrupt實(shí)現。具體實(shí)現,請大家自己看代碼去:) 。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
DM9000 驅動(dòng)移植及源碼簡(jiǎn)析
以太網(wǎng)驅動(dòng)程序
linux 網(wǎng)絡(luò )設備驅動(dòng)-steven
網(wǎng)卡驅動(dòng)注冊到PCI總線(xiàn)這一過(guò)程的分析
Linux驅動(dòng)的platform機制
Linux設備模型 - 鍵盤(pán)棒棒的日志 - 網(wǎng)易博客
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久