Chinaunix首页 | 论坛 | 博客
  • 博客访问: 80510
  • 博文数量: 24
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 135
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-03 10:38
文章分类

全部博文(24)

文章存档

2015年(1)

2014年(23)

我的朋友

分类: LINUX

2014-04-03 10:53:52

原文地址:dm9000网络数据包分析 作者:zzbok

    接收的数据存储在RX SRAM中,地址是0C00h~3FFFh。存储在RX_SRAM中的每个包都有4个字节的信息头。可以使用MRCMDXMRCMD寄存器来得到这些信息。第一个字节用来检查数据包是否接收到了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);  /*读取寄存器MRCMDXrxbyte定义是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~0x0BFFTX Buffer, 地址0x0C00~0x3FFFRX 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;

/++++++++++++++++++++++++++++++++++++++++++++++++++++++++/

阅读(1856) | 评论(0) | 转发(0) |
0

上一篇:dm9000网卡驱动分析4

下一篇:DM9000网卡简介

给主人留下些什么吧!~~