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上的移植小結