分类: LINUX
2014-04-03 10:53:52
原文地址:dm9000网络数据包分析 作者:zzbok
接收的数据存储在RX SRAM中,地址是0C00h~3FFFh。存储在RX_SRAM中的每个包都有4个字节的信息头。可以使用MRCMDX和MRCMD寄存器来得到这些信息。第一个字节用来检查数据包是否接收到了RX_SRAM中,如果这个字节是"01",意味着一个包已经接收。如果是"00",则还没有数据包被接收到RX_SRAM中。第二个字节保存接收到的数据包的信息,格式和RSR寄存器一样。根据这个格式,接收到的包能被校验是正确的还是错误的包。第三和第四字节保存了接收的数据包的长度。这四个字节以外的其他字节就是接收包的数据。看下图可以更好的理解这种格式。
根据包的结构可以知道接收一个包应该按照下面的步骤来进行:
第一步:判断包是否已经接收过来了。需要用到MRCMDX寄存器。MRCMDX寄存器是存储数据读命令寄存器(地址不增加)。这个寄存器只是用来读接收包标志位"01"。下面这段代码是一个例子,用来判断RX ready:
ior(db, DM9000_MRCMDX); /* 读取寄存器MRCMDX,因为地址不增加,且无返回值,所以称为虚拟读。但这行代码并非什么都没有做,因为执行这行代码之后,MRCMDX寄存器地址保存在了db->io_addr中,下面要读取CRCMDX寄存器的值,只需要读取db->io_data即可。可参见下面的 rxbyte = readb(db->io_data); */
/* Get most updated data */
rxbyte = readb(db->io_data); /*读取寄存器MRCMDX,rxbyte定义是u8 rxbyte,一个字节,所以这次读取首字节,即接收包标志位*/
/* Status check: this byte must be 0 or 1 */
if (rxbyte > DM9000_PKT_RDY) /*DM9000_PKT_RDY 定义为0x01,而rxbyte为读取的第一个字节,其值只能是0x00(表示还没接收)或0x01(表示已经接收) */
第二步:检查包的状态和长度。需要用到MRCMD寄存器(存储数据读命令,读指针自动增加)。下面这段例子代码用来读RX状态和长度。
第三步:读包的数据。也需要MRCMD寄存器。例子代码如下:
注释一:我们讲到在DM9000内部SRAM中,地址0x0000~0x0BFF是TX Buffer, 地址0x0C00~0x3FFF是RX Buffer。显而易见,接收到的数据会存储在RX Buffer中,其格式如下:
要修改的代码如下:
static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)函数:
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++/
/* Link status change */
if (int_status & DM9KS_LINK_INTR)
{
netif_stop_queue(dev);
for(i=0; i<10; i++) /*wait link OK, waiting time =0.5s */
{
phy_read(db,0x1);
if(phy_read(db,0x1) & 0x4) /*Link OK*/
{
/* wait for detected Speed */
udelay(100);
/* set media speed */
if(phy_read(db,0)&0x2000) db->Speed =100;
else db->Speed =10;
break;
}
udelay(10);
}
netif_wake_queue(dev);
}
static void dmfe_packet_receive(struct net_device *dev)函数:
/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
/* Status check: this byte must be 0 or 1 */
if (rxbyte > 0x01) {
printk("status check fail: rxbyte=0x%x\n",rxbyte);//++by zjp
dmfe_reset(dev); /*reset net*/
return;
}
if (!(rxbyte & DM9KS_PKT_RDY))
return;
/++++++++++++++++++++++++++++++++++++++++++++++++++++++++/