Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519614
  • 博文数量: 398
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-21 16:02
个人简介

嵌入式屌丝

文章分类

全部博文(398)

文章存档

2013年(398)

我的朋友

分类: LINUX

2013-08-21 17:05:59

一支使用了DMA的网卡驱动分析:

1.初始化
x540_priv->start_rx_ptr =(unsigned long)&x540_priv->rx_desc[0];
x540_priv->start_rx_ptr指向环状缓存描述符数组

2.接收中断会调用netdev_rx函数
static void netdev_rx(struct net_device *dev)
{
    struct x540_priv * priv = netdev_priv(dev);
    RXBD *rxbd;
    unsigned long length;
    unsigned long status;
    int flag = 0;

    rxbd = (RXBD *)priv->rx_ptr ;
    printk(KERN_INFO "##### netif_rx, rx_ptr1=%x\n", priv->rx_ptr);

    do {
        printk(KERN_INFO "rx_ptr=%x\n", priv->rx_ptr);
#if 0
        if(!priv->is_rx_all
            && (x540_ReadReg(CRXDSA, priv->which) == (unsigned long)rxbd)) {
            break;
        }
        priv->is_rx_all = 0;
#endif

        if(priv->is_rx_all>0) {
            flag=1;
            --priv->is_rx_all;
            printk(KERN_INFO "error 0\n");
        } else if(flag==1) {
            flag=0;
            printk(KERN_INFO "error 1\n");
            break;
        } else if(((x540_ReadReg(CRXDSA, priv->which)
            == (unsigned long)rxbd)
            || (rxbd->SL & RXfOwnership_NAT))) {
            //NIC把接收到的数据放入报文缓存后,会清除相应环状缓存描述符的SL变量的RXfOwnership_NAT标记
            //所以,此处若rxbd->SL & RXfOwnership_NAT非零,表示rxbd控制的报文缓存是空的
            printk(KERN_INFO "error 2, SL=%x\n", (rxbd->SL & RXfOwnership_NAT));
            break;
        }

        /*    if(!(rxbd->SL & RXfOwnership_CPU))
            {
                if(priv->is_rx_all)
                    rxbd->SL |=RXfOwnership_DMA;

                priv->rx_ptr=( RXBD *)rxbd->next;
                rxbd=priv->rx_ptr;
                continue;
            }
        */

        length = rxbd->SL & 0xFFFF;
        status = (rxbd->SL & 0xFFFF0000) & ((unsigned long)~0 >>2);

        if(status & RXDS_RXGD) {
            unsigned char  * data;
            struct sk_buff * skb;
            //When NATA Hit , Transmit it derictly
#ifdef WINBOND_NATA
            if(status & (RXDS_NATFSH | RXDS_Hit)) {
                TRACE("NATA Hit");
                printk(KERN_INFO "error 4\n");
                //if(prossess_nata(dev, (unsigned char *) rxbd->buffer))
                continue;
            }
#endif     //end WINBOND_NATA
#if 0
            if(which==1)
                printk("****Good****\n");
#endif
            data = (unsigned char *) rxbd->buffer;

            skb = dev_alloc_skb(length+2);  //Get Skb Buffer;
            if(!skb) {
                TRACE_ERROR("W90N740: I Have Not Got Memory In Fun %s\n", __FUNCTION__);
                priv->stats.rx_dropped++;
                printk(KERN_INFO "error 5\n");
                return;
            }

            skb->dev = dev;
            skb_reserve(skb, 2);   //For IP Align 4-byte
            skb_put(skb, length);
//Wei.gang modify
            //eth_copy_and_sum(skb, data, length, 0);  //copy
            skb_copy_to_linear_data(skb, data, length);  //copy
//Wei.gang modify end
            skb->protocol = eth_type_trans(skb, dev);
            priv->stats.rx_packets++;
            priv->stats.rx_bytes += length;
            netif_rx(skb);    // Enqueue for Up Layer

        } else {

            if(priv->is_rx_all==RX_DESC_SIZE)
                TRACE_ERROR("Rx error:%x, rxbd:%x, priv->is_rx_all:%d\n", (int)status, (int)rxbd, (int)priv->is_rx_all);
            priv->stats.rx_errors++;
            if(status & RXDS_RP ) {
                TRACE_ERROR("W90N740 MAC: Receive Runt Packet Drop it!\n");
                priv->stats.rx_length_errors++;
            }
            if(status & RXDS_CRCE ) {
                TRACE_ERROR("W90N740 MAC Receive CRC  Packet Drop It! \n");
                priv->stats.rx_crc_errors ++;
            }
            if(status & RXDS_ALIE ) {
                TRACE_ERROR("W90N740 MAC Receive Aligment Packet Dropt It!\n");
                priv->stats.rx_frame_errors++;
            }

            if(status &  RXDS_PTLE) {
                TRACE_ERROR("W90N740 MAC Receive Too Long  Packet Dropt It!\n");
                priv->stats.rx_over_errors++;
            }
        }

        //rxbd->SL= RX_OWNERSHIP_DMA; //clear status and set dma flag
        rxbd->SL =RXfOwnership_DMA;//表示此描述符控制的报文缓存为空,NIC可以往里边存放数据
        rxbd->reserved = 0;
        priv->rx_ptr = (unsigned long)rxbd->next;
        rxbd = (RXBD *)priv->rx_ptr;
        dev->last_rx = jiffies;
    } while(1);
    printk(KERN_INFO "#### end\n");
    priv->is_rx_all = 0;
}

执行结果:
priv->start_rx_ptr=de0490
##### netif_rx, rx_ptr1=de0490
rx_ptr=de0490
rx_ptr=de04a0
error 2, SL=80000000
//接收了一个报文
#### end
##### netif_rx, rx_ptr1=de04a0
rx_ptr=de04a0
rx_ptr=de04b0
rx_ptr=de04c0
error 2, SL=80000000
//接收了两个报文
#### end
##### netif_rx, rx_ptr1=de04c0
rx_ptr=de04c0
rx_ptr=de04d0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de04d0
rx_ptr=de04d0
rx_ptr=de04e0
rx_ptr=de04f0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de04f0
rx_ptr=de04f0
rx_ptr=de0500
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0500
rx_ptr=de0500
rx_ptr=de0510
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0510
rx_ptr=de0510
rx_ptr=de0520
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0520
rx_ptr=de0520
rx_ptr=de0530
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0530
rx_ptr=de0530
rx_ptr=de0540
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0540
rx_ptr=de0540
rx_ptr=de0550
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0550
rx_ptr=de0550
rx_ptr=de0560
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0560
rx_ptr=de0560
rx_ptr=de0570
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0570
rx_ptr=de0570
rx_ptr=de0580
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0580
rx_ptr=de0580
rx_ptr=de0590
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0590
rx_ptr=de0590
rx_ptr=de05a0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de05a0
rx_ptr=de05a0
rx_ptr=de05b0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de05b0
rx_ptr=de05b0
rx_ptr=de05c0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de05c0
rx_ptr=de05c0
rx_ptr=de05d0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de05d0
rx_ptr=de05d0
rx_ptr=de05e0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de05e0
rx_ptr=de05e0
rx_ptr=de05f0
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de05f0
rx_ptr=de05f0
rx_ptr=de0600
error 2, SL=80000000
#### end
##### netif_rx, rx_ptr1=de0600
rx_ptr=de0600
rx_ptr=de0610
error 2, SL=80000000
#### end

附件为此驱动使用的DMA的原理说明

文件: NIC-DMA.pdf
大小: 104KB
下载: 下载

阅读(428) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~