linux下dm9000網絡卡驅動同樣是註冊成平台驅動(platform driver)的形式.平台驅動在此就不多做介紹了,具體請參考linux驅動分析之framebuffer驅動.重點介紹dm9000網絡卡的控制.
dm9000的引腳和mini2440的引腳連線:
dm9000 mini2440 功能描述
sd0 data0 資料訊號
sd15 data15 資料訊號
cmd addr2 識別為位址還是資料(為高電平時16位資料線上傳輸的是資料,為低電平時16位資料線上傳輸的是位址)
int eint7 中斷
ior# noe 讀命令使能
iow# nwe 寫命令使能
aen ngcs4 片選使能
可以看出dm9000與處理器連線了16根資料線,1根位址線,而這唯一的一根位址線用於判斷16根資料線上傳輸的是位址還是資料,所以這16條資料線為資料和位址復用.而片選訊號使用的ngcs4(bank4),則當處理器訪問0x20000000 – 0x27ffffff這個範圍的位址時會啟用片選使能訊號ngcs4.由於mini2440使用的是addr2這根位址線,故dm9000的位址io為0x20000000,資料io為0x2000 0004.向位址io寫資料的時候不會啟用addr2,所以向dm9000傳送的為位址,而向資料io寫資料的時候會啟用addr2,所以向dm9000傳送的為資料.
以上為dm9000的讀寫大致情況.下面著重從源**的角度分析linux下是如何驅動dm9000的.(driver/net/dm9000.c)
static int __init dm9000_init(void)
#if defined(config_arch_s3c2410)
unsigned int oldval_bwscon = *(volatile unsigned int *)s3c2410_bwscon;
unsigned int oldval_bankcon4 = *(volatile unsigned int *)s3c2410_bankcon4;
*((volatile unsigned int *)s3c2410_bwscon)=(oldval_bwscon&~(3<<16))|s3c2410_bwscon_dw4_16|s3c2410_bwscon_ws4 |
s3c2410_bwscon_st4;
*((volatile unsigned int *)s3c2410_bankcon4) = 0x1f7c;
*(volatile unsigned int *)s3c2410_bwscon = oldval_bwscon;
*(volatile unsigned int *)s3c2410_bankcon4 = oldval_bankcon4;
#endif //這一段是friendarm加上去的,下面會有所分析
printk(kern_info "%s ethernet driver, v%s/n", cardname, drv_version);
return platform_driver_register(&dm9000_driver);
static void __exit
dm9000_cleanup(void)
platform_driver_unregister(&dm9000_driver);
module_init(dm9000_init);
module_exit(dm9000_cleanup);
struct platform_driver dm9000_driver初始化如下:
static struct platform_driver dm9000_driver = {
.driver = {
.name = "dm9000",
.owner = this_module,
.pm = &dm9000_drv_pm_ops,
.probe = dm9000_probe,
.remove = __devexit_p(dm9000_drv_remove),
平台裝置驅動註冊成功時最終會呼叫到dm9000_driver的probe成員,在函式dm9000_probe中完成裝置資源的申請,註冊,dm9000網絡卡的相關檢測(如型別,id號等),網路裝置結構的初始化,註冊等工作.下面來重點分析這個函式.
static int __devinit dm9000_probe(struct platform_device *pdev)
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
struct board_info *db; /* point a board information structure */
struct net_device *ndev;
const unsigned char *mac_src;
int ret = 0;
int iosize;
int i;
u32 id_val;
/* init network device */
ndev = alloc_etherdev(sizeof(struct board_info));
if (!ndev) {
dev_err(&pdev->dev, "could not allocate device./n");
return -enomem;
set_netdev_dev(ndev, &pdev->dev);
dev_dbg(&pdev->dev, "dm9000_probe()/n");
/* setup board info structure */
db = netdev_priv(ndev);
db->dev = &pdev->dev;
db->ndev = ndev;
spin_lock_init(&db->lock);
mutex_init(&db->addr_lock);
init_delayed_work(&db->phy_poll, dm9000_poll_work);
此函式的引數struct platform_device *pdev是在平台驅動註冊的時候傳進來的,指向的結構具體為:
static struct resource mini2440_dm9k_resource = {
[0] = {
.start = mach_mini2440_dm9k_base,
.end = mach_mini2440_dm9k_base + 3,
.flags = ioresource_mem
[1] = {
.start = mach_mini2440_dm9k_base + 4,
.end = mach_mini2440_dm9k_base + 7,
.flags = ioresource_mem
[2] = {
.start = irq_eint7,
.end = irq_eint7,
.flags = ioresource_irq | ioresource_irq_highedge,
* * * the dm9000 has no eeprom, and it's mac address is set by
* * * the bootloader before starting the kernel.
static struct dm9000_plat_data mini2440_dm9k_pdata = {
.flags = (dm9000_platf_16bitonly | dm9000_platf_no_eeprom),
static struct platform_device mini2440_device_eth = {
.name = "dm9000",
.id = -1,
.num_resources = array_size(mini2440_dm9k_resource),
.resource = mini2440_dm9k_resource,
.dev = {
.platform_data = &mini2440_dm9k_pdata,
驅動 DM9000網絡卡驅動分析
preface 核心原始碼版本 linux 2.6.18 網絡卡驅動 linux核心網路分層結構 dm9000晶元 dm9000是一款高度整合低功耗快速乙太網處理器,該晶元整合了mac和phy。dm9000可以和cpu直接連線,支援8位 16位和32位資料匯流排寬度。該晶元支援10m和100m自適應...
DM9000網絡卡驅動移植
網絡卡驅動移植 步驟1 確定相異性 步驟2 修改 一般就是修改 iobase 和中斷 按照原理圖,其片選訊號可能是往固定段落記憶體寫資料,即是片選到這個裝置。這個也是統一編址的一種方式。根據原理圖,修改其中段引腳,把其irq修改為原理圖上面的iro.網絡卡中本來就有記憶體,當網絡卡接受到資料時候,就...
詳細透徹的分析DM9000網絡卡驅動程式(1)
自己感覺前段時間的學習,一直是東一榔頭,西一棒子,所以決定聽 趙磊 大哥的話 這個世界太浮躁,需要靜下心來做點兒學問。於是,哥們鼓起勇氣開始分析linux核心中的dm9000驅動程式 1.網路相關的程式在linux 中的層次機構 從哥們第一天進公司起,就讓哥們開始整理 我以為,整理 應該是從乙個較高...