1. 程式人生 > >S3C2440 DM9000C網絡卡移植(二十六)

S3C2440 DM9000C網絡卡移植(二十六)

上一節 我們學習了:

接下來本節,學習網絡卡晶片DM9000C,如何編寫移植DM9000C網絡卡驅動程式。

1、首先來看看DM9000C原理圖

如下圖所示:

(#表示低電平有效)

  • SD0~15:16位資料線,有CMD引腳決定訪問型別
  • CMD:命令線,當CMD為高電平,表示SD傳輸的是資料,當CMD為低電平,表示SD傳輸的是地址
  • INT:中斷引腳,接在2440的GPF7引腳上
  • IOR#:讀引腳,接在2440的nOE上
  • IOW#:寫引腳,接在2440的nWE上
  • CS#:片選引腳,放在2440的bank4的片選上面

1.1 其中2440手冊的bank4地址區間如下圖:

bank4的區間位於:0x2000 0000~0x2800 0000

,當我們訪問這個區間的地址,記憶體控制器便會使能網絡卡DM9000C的使能引腳(被選中了),所以我們的DM9000C的io基地址=0x2000 0000

其中DM9000C的CMD引腳接在bank4的LADDR2上面

比如當在地址0x2000 0000上讀寫資料時,表示讀寫的資料是DM9000C的地址

訪問的地址0x2000 0004上讀寫資料時,表示讀寫的資料是DM9000C的資料

1.2 DM9000C收發過程

當DM9000C收到外部資料後,會暫存到內部地址中,然後產生一個上升沿中斷,等待2440讀取資料

當DM9000C將2440的資料轉發出去後,也會產生一個上升沿中斷給2440

如下圖所示,DM9000C的中斷引腳位於PIN34腳

接在2440的GPF7引腳上,使用的中斷為EINT7

接下來便來修改廠家提供的DM9000C原始碼 dm9dev9000c.c

2、發現它的init_module()入口函式前有個條件編譯

所以要註釋掉“#ifdef MODULE”和“#endif

3、修改入口出口函式名,並修飾它們(修改函式名免與核心的其他函式重名)

4、修改驅動的硬體相異性(設定基地址,暫存器,中斷等)

4.1 先來找找程式碼在哪裡初始化DM9000C硬體的

進入dm9000c_init()

-》dmfe_probe()

struct net_device * __init dmfe_probe(void)
{
	struct net_device *dev;
	... ...
	dev= alloc_etherdev(sizeof(struct board_info));//分配一個net_device結構體
    ... ...
	err = dmfe_probe1(dev);//設定
	... ...
	err = register_netdev(dev);//向核心註冊net_device結構體
	... ...
}

雖然dmfe_probe1()函式是用來初始化DM9000C硬體和設定net_device結構體的成員用的

4.2 進入dmfe_probe1()函式

如下圖,這個iobase變數就是我們DM9000C的io基地址0x2000 0000

iobase的作用:

如上圖,讀一次DM9000C的VID低位元組之前,需要先將地址賦為0x2000 0000,也就是將DM9000C的CMD置0,然後向0x2000 0000寫入要讀的DM9KS_VID_L地址值

最後再將地址+4,也就是賦為0x2000 0100,將CMD置1,然後讀出0x2000 0100的值,也就是DM9000C的VID低位元組

DM9000C的讀寫方式都是這樣,先將CMD置0,寫入DM9000C的地址,然後再將CMD置1來讀寫資料

4.3 所以在init函式中便重新設定iobase變數,其中iobase是init型別

並在exit出口函式中,新增iounmap()

4.4 繼續進入dmfe_probe1()函式,往下看

如下圖所示,遮蔽紅色下劃線的程式碼,該程式碼用來核對版本,我們的DM9000C版本號不一樣,所以要遮蔽

4.5 在init函式中,修改中斷名,將irq修改為IRQ_EINIT7

4.6 修改中斷

當使用了register_netdev()註冊了網絡卡驅動net_device後,在核心中使用ifconfig就會進入net_device->open成員函式申請中斷,啟用佇列等

所以我們要修改open成員函式的申請中斷,將觸發中斷改為“IRQT_RISING”,上升沿觸發

5、接下來便開始設定2440的儲存控制暫存器(Memory Contrller)

設定2440的bank4的硬體位寬,時序,因為不同的硬體,涉及的資料收發都不同

5.1 設定BWSCON,匯流排寬度控制暫存器

我們只需要裝置BANK4的內容,所以只有下面3個(BANK0的位寬由OM[1:0]硬體設定)

設定ST4=0,不使用UB/LB(UB/LB:表示高位元組與低位元組是否分開傳輸)

設定WS4=0,其中WAIT引腳為PE4,而我們DM9000C沒有引腳接入PE4,所以禁止

設定DW4=0x01,從原理圖,我們可知DM9000C的資料線為16位(SD0~SD15)

5.2 設定BANKCON4控制暫存器

設定這些時序之前,首先來看DM9000C晶片手冊的時序圖和2440的時序圖

參考上圖,得出BANKCON4暫存器設定如下(HCLK=100MHZ,1個時鐘等於10ns)

  • 設定Tacs=0,表示發出片選訊號之前,多長時間內要發現地址訊號,CS和CMD可以同時結束(bank4地址(也就是CMD)穩定多久後,CS片選才啟動)
  • 設定Tcos=T1=0(發出CS片選訊號後,多久才能發出讀訊號nOE)
  • 設定Tacc=T2>=10ns=1,表示讀寫訊號的脈衝長度,2個時鐘(access cycle,讀寫使能後,多久才能訪問資料)
  • 設定Tcoh=T4>=3ns=1,表示當讀訊號nOE變為高電平後,片選訊號還要維持多長時間,1個時鐘,因為當DM9000C的寫訊號取消後,資料線上的資料還需要至少3ns才消失;當DM9000C的讀訊號取消後,資料線上的資料在6ns之內會笑死,取一個寬鬆值,維持10ns,所以設為01(nOE讀寫取消後,片選需要維持多長時間)
  • 設定Tcah=0,因為CS和CMD可以同時結束(CS片選變為高電平後,地址(也就是CMD)需要維持多長時間)

程式碼如下圖,在init入口函式中設定

(PS:若DM9000C無法驅動,可能是Tacc時間太短,導致讀取不到資料,可以將Tacc設大一點)

與硬體相關的部分已經改好了,接下來開始編譯

6、編譯測試

編譯之前,首先新增該驅動需要的核心標頭檔案:

#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch-s3c2410/regs-mem.h>

編譯無誤後,便開始測試DM9000C驅動程式:

1)把已經修改好的驅動程式dm9dev9000c.c放到核心的drivers/net目錄下,來替換原來核心的DM9000C

2)修改drivers/net/Makefile

obj-$(CONFIG_DM9000) += dm9000.o
改為(如下圖所示)
obj-$(CONFIG_DM9000) += dm9dev9000c.o

3)make uImage

如下圖,說明新的驅動已編譯進核心

4)使用新核心啟動

ifconfig eth0 192.168.1.17

ping 192.168.1.3

如下圖,可以ping通,說明移植成功