分类: LINUX
2013-06-05 14:15:33
原文地址:一支使用了DMA的网卡驱动分析 作者:jinxinxin163
一支使用了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的原理说明
|