您的位置:首页 > 其它

DM9000A驱动调试(解决网卡无法接收数据问题)

2009-11-07 10:56 423 查看
DM9000A驱动调试

dm9000x.c和dm9000x.h文件中包含了网络芯片的收发函数,但是该驱动是基于DM9000的,需要做更改才能适合于DM9000A。
首先遇到的问题是DM9000A驱动无法获得MAC地址。
Uboot在配置文件中有MAC地址的定义:
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
奇怪的是这里怎么无法获得呢?查看源代码发现获得MAC地址部分的代码如下:
for (i = 0; i < 6; i++)
((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
原来Uboot要调用read_srom_word()函数从外面PHY中读取,反正芯片中已经集成了PHY,我们只需要设置PHY的MAC地址就可以了,代码更改如下:
unsigned char env_enetaddr[6];
char *tmp = getenv ("ethaddr");
// 将环境变量中保存的mac地址转换成数字
for (i=0; i<6; i++) {
env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
if (tmp)
tmp = (*end) ? end+1 : end;
}

// 保存mac地址
for (i = 0; i < 6; i++)
((u16 *) bd->bi_enetaddr)[i] = env_enetaddr[i];
这样DM9000A驱动就会使用我们配置的mac地址了。
接下来调试TFTP下载数据。
我在刚开始调试的时候发现使用TFTP总是不能正常下载数据,我以为是我设置的总线的访问时序上有问题,后来更改了读写访问延迟时间,已经放到了最大,但还是不能正常下载。打开网络调试开关,发现ARP获得了对方的MAC,但是到了开始传输数据的时候,主机发送下来的数据本机接受不到,然后主机发送第二次,本机才收到,然后返回确认,这样每发送一包数据就要有几秒钟的延迟,问题肯定出在网络接收处。
接下来我增加了调试tftp.c文件,发现接受到的数据和上次接受的数据的包号相同,当接受到同样的数据包的时候,网络的处理方法是丢弃,等待上位机机重新发送,难怪当时不返回,原来是给丢掉了!
这样就到了DM9000A的驱动部分代码。
DM9000A的接收数据函数:
eth_rx(void)
{
u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
u16 RxStatus, RxLen = 0;
u32 tmplen, i;
// DM9000A接收缓冲区中的数据格中格式是4字节的包头+真正的数据.
// 其中4字节包头分别位为: rxbyte, status, count_low, count_hight
// 说明如下:
// rxbyte: 0-没有接收到数据, 1-有新的数据包
// status: 状态
// count_low, count_hight: 接收到的数据长度
/* Check packet ready or not */
DM9000_ior(DM9000_MRCMDX); // 设置读取SRAM数据, 内部地址不递增
rxbyte = DM9000_inb(DM9000_DATA); // 读取查看是否有数据接收到
if (rxbyte == 0)
return 0;
// rxbyte值必须是0或者1, 其它值不正确, 这里检测其它值的情况
if (rxbyte > 1) {
DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
DM9000_DBG("rx status check: %d/n", rxbyte);
}
DM9000_DBG("receiving packet/n");
/* A packet ready now & Get status/length */
DM9000_outb(DM9000_MRCMD, DM9000_IO);
#ifdef CONFIG_DM9000_USE_16BIT
RxStatus = DM9000_inw(DM9000_DATA); // 获得接收的状态
RxLen = DM9000_inw(DM9000_DATA); // 获得数据包长度
#endif
… // 接下来进行数据解析的处理…

在初始化的时候,设置IMR寄存器的bit7为1,RXSRAM从0x0C00开始,当到达16K时,读取数据的地址重新返回到0x0C00位置。上面的代码在DM9000上工作的好好的,为什么到了DM9000A上就不能正常工作了呢?
仔细看DM9000A的datasheet发现存在另外两个寄存器,位置在0xF4和0xF5,上面解释说当IMR寄存器的bit7为1时,内存数据地址将被设置成0x0C00,也就是说读取这两个寄存器能导致数据读取的地址指针复位,于是就在读取状态位之前重新设置一下地址指针,代码如下:
u16 temp;
temp=DM9000_ior(DM9000_MRRH); // 读取这两个寄存器
temp=DM9000_ior(DM9000_MRRL);
加上以上三行代码后DM9000A工作正常了,看来就是这个原因。费了这么大的周折,原来是这里出的毛病!


有一个问题还是没有搞清楚:




DM9000的Datasheet上的RXRAM说明如下:

也就是说接收完成一包数据后,下一包数据将接着上一包数据的结束地址保存,那么在读取的过程中就不需要重新对RX RAM的地址指针进行重新复位,就像一个大的FIFO一样读取,但为什么对于DM9000A



文章出处:DIY部落(http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135101.html)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: