S3C6410开发全纪录(三)《UBOOT中添加DM9000AE网卡驱动》


我们获得的UBOOT的代码中实际是有DM9000的网口驱动的,位于:driver/dm9000x.c

在S3C6410的配置中,中并没有将之打开,而其他的芯片中有使用

特别需要注意的是dm9000的驱动与dm9000AE的驱动还是有区别的,如果直接使用代码中自带的dm9000驱动流程,会出现无法收到数据的情况

一、添加dm9000AE的驱动

[cpp] view plain copy
  1. 修改include/configs/smdk6410.h,参考 include/configs/scb9328.h 中的定义,添加如下宏定义  
[cpp] view plain copy
  1. #define CONFIG_DRIVER_DM9000                1  
  2. #define CONFIG_DM9000_BASE          0x18000000  
  3. #define DM9000_IO                   CONFIG_DM9000_BASE  
  4. #define DM9000_DATA                 (CONFIG_DM9000_BASE+4)  
  5. #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这个宏定义决定其内容的

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

[cpp] view plain copy
  1. #define CONFIG_ETHADDR          00:40:5c:26:0a:5b  
  2. #define CONFIG_NETMASK          255.255.255.0  
  3. #define CONFIG_IPADDR           192.168.30.233  
  4. #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这个文件,看到代码如下

[cpp] view plain copy
  1. eth_init(bd_t * bd) 函数中  
  2.   
  3. for (i = 0; i < 6; i++)  
  4.                 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);  
[cpp] view plain copy
  1. for (i = 0, oft = 0x10; i < 6; i++, oft++)  
  2.                 DM9000_iow(oft, bd->bi_enetaddr[i]);  

测试可以先做如下处理吧,回头我们再改成从其他地方读取,比如外部的EEPROM,NANDFLASH,等地方好了,毕竟不应该在这个单纯的网卡驱动中增加其他驱动的代码

[cpp] view plain copy
  1. u16 default_enetaddr[6] = { 0x00, 0x40, 0x5c, 0x26, 0x0a, 0x5b };   
  2. for (i = 0; i < 6; i++)  
  3.                 bd->bi_enetaddr[i] = default_enetaddr[i];  

如果要修改成从环境变量中读取MAC地址,则可以这样做

[cpp] view plain copy
  1. {  
  2.     char *s, *e;  
  3.     s = getenv ("ethaddr");  
  4.     for (i = 0; i < 6; ++i)   
  5.     {  
  6.         bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;  
  7.         if (s)  
  8.             s = (*e) ? e + 1 : e;  
  9.     }  
  10. }  

修改MAR寄存器(Multicast Address Register)的值,修正第一次收不到数据的错误

[cpp] view plain copy
  1. for (i = 0, oft = 0x16; i < 8; i++, oft++)  
  2.         // by tr modify  
  3.         DM9000_iow(oft,0x00);  
  4.         //DM9000_iow(oft, 0xff);  

修改void eth_halt(void) 函数将以下两行注释掉,修正一直无法收到数据的错误

[cpp] view plain copy
  1. 不要每次调用halt的时候都对PHY进行复位操作,否则会引起无法接受到数据的情况  
  2. //phy_write(0, 0x8000); /* PHY RESET */  
  3. //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


你可能感兴趣的:(c,工作,测试,interface)