我们获得的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
http://lagignition.blog.163.com/blog/static/12873002320110443341961/
Linux DM9000网卡驱动程序完全分析
http://blog.csdn.net/ypoflyer/article/details/6209922
dm9000ae 在u-boot上的移植小结
http://weibing.blogbus.com/logs/12146712.html