这一部分虽然移植起来简单,但是当我自己去分析的时候确实折腾了接近两天的时间,真的伤不起啊。虽然说网上对于uboot移植的DM9000A网卡的移植的资料很多,移植过程也很简单,总的来说主要就是设置一下头文件/include/configs/fl2440.h 中宏的定义和drivers/net/dm9000x.c中网卡的函数的修改,和在board/samsung/fl2440/fl2440.c中增加关于网卡的初始化。
打开/include/configs/fl2440.h:
注释掉下面语句:
#define CONFIG_DRIVER_CS8900 1/* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts *
增加下面语句:
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_NET_MULTI 1
#define CONFIG_DM9000_NO_SROM 1
#define CONFIG_DM9000_BASE 0x20000000 //网卡片选地址
#define DM9000_IO CONFIG_DM9000_BASE //网卡命令端口
#define DM9000_DATA (CONFIG_DM9000_BASE+4) //网卡数据端口
#define CONFIG_CMD_PING //增加ping命令
#define CONFIG_CMD_DHCP //这个是什么 目前还不知道 加不加好像是都没有影响
#define CONFIG_CMD_NET //这是一个红开关 我们没有用到 定不定义都无所谓
#define CONFIG_DM9000_USE_16BIT 1 //定义位宽
然后定义缺省的环境变量,先添加MAC地址,再修改开发板以及宿主机的IP地址:
#define CONFIG_ETHADDR 00:0c:29:4b:94:53//我选择的俄式和虚拟机上的一样的MAC地址
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 210.41.141.111 //开发板IP,自定义,注意要与主机IP在同一网段
#define CONFIG_SERVERIP 210.41.141.98//主机IP
#define CONFIG_GATEWAYIP 210.41.141.1//网关,在虚拟机上我都是静态设置好了的
修改board/samsung/fl2440/fl2440.c;添加网卡初始化代码:
#include <net.h>
#include <netdev.h>
#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
return dm9000_initialize(bis);
}
#endif
在drivers/net/dm9000x.c中修改:
i = 0;
while (!(phy_read(1) & 0x20)) {/* autonegation complete bit */
udelay(1000);
i++;
if (i == 500000) {
//将10000改为500000,这样就能解决第一次ping 不通的情况,网上说是把这段屏蔽掉,会有第一 次ping不通。
printf("could not establish link\n");
return 0;
}
}
接着在dm9000x.c中修改,屏蔽掉dm9000_halt函数中的内容,否则ping不通。
/*
Stop the interface.
The interface is stopped when it is brought.
*/
static void dm9000_halt(struct eth_device *netdev)
{
//DM9000_DBG("%sn", __func__);
///* RESET devie */
//phy_write(0, 0x8000); /* PHY RESET */
//DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
//DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
//DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
}
再修改dm9000x.c中phy_read() 函数,解决传输过程中出现“operating at unknow : 0 mode"字符串,如下:
phy_read(int reg)
{
u16 val;
/* Fill the phyxcer register into REG_0C */
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
DM9000_iow(DM9000_EPCR, 0xc);/* Issue phyxcer read command */
udelay(8000); /* Wait read complete */ //默认的的是8000的就不用修改 网上说要修改1000 没有必要 这几个值可以自己测试
DM9000_iow(DM9000_EPCR, 0x0);/* Clear phyxcer read command */
val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
/* The read data keeps on REG_0D & REG_0E */
DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
return val;
}
接下来打开net/tftp.c (注意net是在顶层目录下),修改TIMEOUT的值,原来是5000UL,否则会出现在超时重传的情况。
#define TIMEOUT 70000UL /* Millisecs to timeout for lost pkt */
(注意这里的值的是不固定的,70000UL就可以正常传输,这个值也不是越大越好,
到这里,DM9000A的网卡驱动就移值完成了。
简单介绍一个用到的宏定义CONFIG_DM9000_BASE
这里需要注意的是#define CONFIG_DM9000_BASE 0x20000000 //网卡片选地址。而不是0x20003000,这个是DM9000,而我们使用的是DM9000A。因为CMD接在ADDR2上所以#define DM9000_DATA (CONFIG_DM9000_BASE+4)。因为DM9000A的地址信号和数据信号复用,CMD引脚决定传输的是地址信号还是数据信号。数据手册上说CMD为0时是地址信号所以DM9000_IO CONFIG_DM9000_BASE,CMD为1时,是数据信号,所以#define DM9000_DATA (CONFIG_DM9000_BASE+4)。DM9000A内部有一个4K Dword SRAM,因为数据线和地址线是复用的,所以如果这部分用地址线进行寻址,范围是16KB,所以在 0x20000000~0x20000000+16KB范围内都可以的。所以0x20003000是碰巧在这里的。第一次ping不同,第二次开始就可以ping通了,这个是正常现象。
到此时就可以ping通虚拟机和pc机了。
在PC机上启动tftpd32.exe 选择好服务端,IP地址,端口。就可以传输了。
tftpboot 0x30008000 210.41.141.98:zImage
在这里我折腾了很久,就是因为这个路径选择错误了,错误的选择方法如下:
tftpboot 0x30008000 210.41.141.98:zImage //文章并没有提示我路径错误,只是不停的打印如下信息:
lzd> tftp 0x30000000 /home/lzd/nfs/image
TFTP from server 10.107.4.145; our IP address is 10.107.4.146
Filename '/home/lzd/nfs/image'.
Load address: 0x30000000
Loading: T T T T T T T T T T
Retry count exceeded; starting again
TFTP from server 10.107.4.145; our IP address is 10.107.4.146
Filename '/home/lzd/nfs/image'.
Load address: 0x30000000
Loading: T T T T T T T T T T
Retry count exceeded; starting again