1. 程式人生 > >S3C6410開發全紀錄(三)《UBOOT中新增DM9000AE網絡卡驅動》

S3C6410開發全紀錄(三)《UBOOT中新增DM9000AE網絡卡驅動》

 我們獲得的UBOOT的程式碼中實際是有DM9000的網口驅動的,位於:driver/dm9000x.c

在S3C6410的配置中,中並沒有將之開啟,而其他的晶片中有使用

特別需要注意的是dm9000的驅動與dm9000AE的驅動還是有區別的,如果直接使用程式碼中自帶的dm9000驅動流程,會出現無法收到資料的情況

一、新增dm9000AE的驅動

修改include/configs/smdk6410.h,參考 include/configs/scb9328.h 中的定義,新增如下巨集定義
#define CONFIG_DRIVER_DM9000                1
#define CONFIG_DM9000_BASE          0x18000000
#define DM9000_IO                   CONFIG_DM9000_BASE
#define DM9000_DATA                 (CONFIG_DM9000_BASE+4)
#define CONFIG_DM9000_USE_16BIT

DM9000的基地址(CONFIG_DRIVER_DM9000的值)與硬體設計相關

檢視《OK6410底板原理圖.pdf》,看到,CS掛在CSN1上

檢視《s3c6410_rev12.pdf》,118頁,2.2 DEVICE SPECIFIC ADDRESS SPACE ,0x1800_0000  0x1FFF_FFFF  128MB  SROMC Bank 1 ,可以確定CONFIG_DM9000_BASE的值

檢視drivers/Makefile,可以看到dm9000x的驅動已經被編譯進去

 整個driver/dm9000x.c 的程式碼時靠CONFIG_DRIVER_DM9000這個巨集定義決定其內容的

配合著我們可以去修改如下可能用到的一些地址

#define CONFIG_ETHADDR          00:40:5c:26:0a:5b
#define CONFIG_NETMASK          255.255.255.0
#define CONFIG_IPADDR           192.168.30.233
#define CONFIG_SERVERIP         192.168.30.95

二、修改dm9000AE的驅動

檢視DM9000AE的手冊《DM9000AE.pdf》,可以看到,DM9000AE包括了,MAC,PHY,沒有帶EEPROM,可以通過引腳來控制外部的EEPROM

看到第11頁,5.2 EEPROM Interface,看到操作DM9000的EEPROM的PIN腳為19 20 21這3個

檢視《OK6410底板原理圖.pdf》,看到ethernet部分 19 20 21 這3個PIN腳是懸空的,額。。。,這意味著我們無法通過DM9000AE將MAC地址儲存在EEPROM中

檢視《DM9000AE.pdf》 6. Vendor Control and Status Register Set 這個章節,看到 PAR Physical Address Register 10H-15H 這部分是用來設定MAC地址的

也就是說我們必須將MAC地址寫入到這幾個暫存器中,下面我們來完成這個工作,開啟driver/dm9000x.c這個檔案,看到程式碼如下

eth_init(bd_t * bd) 函式中

for (i = 0; i < 6; i++)
                ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
for (i = 0, oft = 0x10; i < 6; i++, oft++)
                DM9000_iow(oft, bd->bi_enetaddr[i]);

測試可以先做如下處理吧,回頭我們再改成從其他地方讀取,比如外部的EEPROM,NANDFLASH,等地方好了,畢竟不應該在這個單純的網絡卡驅動中增加其他驅動的程式碼

u16 default_enetaddr[6] = { 0x00, 0x40, 0x5c, 0x26, 0x0a, 0x5b }; 
for (i = 0; i < 6; i++)
                bd->bi_enetaddr[i] = default_enetaddr[i];

如果要修改成從環境變數中讀取MAC地址,則可以這樣做

{
	char *s, *e;
	s = getenv ("ethaddr");
	for (i = 0; i < 6; ++i) 
	{
		bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
		if (s)
			s = (*e) ? e + 1 : e;
	}
}

修改MAR暫存器(Multicast Address Register)的值,修正第一次收不到資料的錯誤

        for (i = 0, oft = 0x16; i < 8; i++, oft++)
                // by tr modify
                DM9000_iow(oft,0x00);
                //DM9000_iow(oft, 0xff);

修改void eth_halt(void) 函式將以下兩行註釋掉,修正一直無法收到資料的錯誤

        不要每次呼叫halt的時候都對PHY進行復位操作,否則會引起無法接受到資料的情況
        //phy_write(0, 0x8000); /* PHY RESET */
        //DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */

查詢定位ping不通,資料無法接收的問題還是也讓人著實頭疼了一番,看到這個結果,可以發現,跟網上的其他描述都不大相同,也是幸虧有一些可以參考的程式碼,根據這些可以成功執行的程式碼,一步一步的定位,到底是那些地方出現了問題。

另外說明一下,DM9000這樣的晶片是MAC+PHY,現在有很多SOC都內建MAC,只用外掛PHY就可以了

一般來說,這種情況下,對PHY的配置,主要還是要根據硬體的設計,找到PHY的ADDR,在OK6410的配置中PHYADDR為1,跟程式碼一致,這裡就沒再做任何修改了

三、參考資料

《OK6410底板原理圖.pdf》
《s3c6410_rev12.pdf》
《DM9000AE.pdf》

移植OK6410'S dm9000ae驅動到u-boot

Linux DM9000網絡卡驅動程式完全分析

dm9000ae 在u-boot上的移植小結