這周又沒看書。。。
由于最近要做些網絡方面的優化,就又學習了下網絡驅動模型。
e1000e網卡驅動分析—網卡驅動的體系結構在硬件上電初始化時,BIOS統一檢查所有的PCI設備,并為每個設備分配一個物理地址,該地址通過BIOS獲得并寫到設備的配置空間內,CPU不能直接訪問,驅動程序可以將這部分配置空間通過ioremap映射到普通內存供CPU問。
當操作系統初始化時,其為每個
PCI
設備分配了一個
pci_dev
結構,并將前面分配的物理地址寫到
pci_dev
的
resource
字段中。在驅動程序中,可以通過讀取這個字段得到設備的配置空間地址,由函數
pci_resource_start()
以及
pci_resource_len()
獲得配置空間的起始地址和大小,再通過
ioremap
映射到內存中,供
CPU
訪問,來控制該設備。
e1000e網卡驅動加載時,顯而易見的是調用module_init(e1000_init_module)宏,然后調用e1000_init_module()函數,該函數又會進一步的調用pci_register_driver()函數。
pci_register_driver()函數以一個pci_driver的結構作為入參,該結構定義了PCI設備相關的操作函數,如probe、shutdown、remove等,最主要的是定義了id_table。我們知道,網卡設備也是一個PCI設備,而系統所有PCI設備的id_table在系統啟動階段就已經分配,這里的主要目的是用pci_driver結構的id_table和所有PCI設備的id_table比較,找到匹配項,然后取出該PCI設備的pci_dev結構,最后調用probe方法。
/* PCI Device API Driver */
static struct pci_driver e1000_driver = {
? .name = e1000e_driver_name,
? .id_table = e1000_pci_tbl, // 驅動所能操縱的設備id列表
? .probe = e1000_probe,
? .remove = __devexit_p(e1000_remove),
#ifdef CONFIG_PM
? .driver.pm = &e1000_pm_ops,
#endif
? .shutdown = e1000_shutdown,
? .err_handler = &e1000_err_handler
};
static struct pci_driver e1000_driver = {
? .name = e1000e_driver_name,
? .id_table = e1000_pci_tbl, // 驅動所能操縱的設備id列表
? .probe = e1000_probe,
? .remove = __devexit_p(e1000_remove),
#ifdef CONFIG_PM
? .driver.pm = &e1000_pm_ops,
#endif
? .shutdown = e1000_shutdown,
? .err_handler = &e1000_err_handler
};
在介紹具體的代碼前,先介紹下驅動相關的三個數據結構:pci_dev、net_device以及e1000_adapter。這三個數據結構實現了硬件到軟件驅動的過渡,要讀懂網卡驅動,必須弄清楚這三個結構的關系。
pci_dev結構是在啟動階段保留下來的,體現了PCI設備所有應有的規范。net_device結構,是驅動層的網卡操作結構。這兩個結構都表示網卡設備,只是體現的角度不一樣,net_device是對特定適配器的抽象,其為上層協議提供了統一的結構,網卡驅動則基于特定的適配器實現了這一抽象。網卡驅動實際操作的是特定的適配器,是由硬件相關的adapter即該驅動中的e1000_adapter所表示的結構體,adapter體現了大部分與硬件相關的特性,網卡驅動除了直接對pci_dev結構操作外,其他隊網卡設備的操作基本都是對adapter結構的操作。adapter結構體現了net_device與pci_dev的關聯,也實現了網絡設備的適配器無關性。
上圖中,描述了這三個數據結果的關系。pci_dev結構體現了網卡的配置空間和I/O內存區域,net_device結構則向內核同了操作網卡的抽象接口。e1000_adapter結構除了體現相應的硬件無關性外,還管理了發送與接受數據包的相應緩沖區,網卡的物理地址空間映射后的虛擬地址也在改結構中保存。e1000_adapter結構中的e1000_hw結構主要保存網卡的硬件參數,其值就是通過讀取pci_dev的結構獲取出來的。
舉個例子來說,用戶態的收發包驅動netmap,在實現是就繼承了網卡驅動中的e1000_adapter和net_device結構,來操作硬件、收發隊列以及向上提供接口。