|
uclinux中对S3C4510的网络驱动程序如下所示:
请问其中的do{...}while(CFD_ptr != priv->rx_ptr)循环中,循环条件表示什么意思??
难道接收的最后一帧的指针与第一帧的指针是相同的吗?
请问驱动程序中的初始化、注册、接收、发送、打开、关闭等操作的相互逻辑关系是什没?
谢谢!
/*
* rx
*/
void s3c4510_rx(int irq, void *dev_id, struct pt_regs *regs)
{
// int i;
int len;
unsigned char *data;
struct sk_buff *skb;
struct FrameDesc *FD_ptr;
unsigned long CFD_ptr;
unsigned long RxStat;
unsigned long BDMAStat;
struct net_device *dev = (struct net_device *) dev_id;
struct s3c4510_priv *priv = (struct s3c4510_priv *) dev->priv;
TRACE("rx\n");
spin_lock(&priv->lock);
// 1. Get current frame descriptor and status
CFD_ptr = CSR_READ(BDMARXPTR);
BDMAStat = CSR_READ(BDMASTAT);
// 2. Clear BDMA status register bit by write 1
CSR_WRITE(BDMASTAT, BDMAStat | S_BRxRDF);
do {
// 3. Check Null List Interrupt
/*
if(CSR_READ(BDMASTAT) & BRxNL) {
CSR_WRITE(BDMASTAT, );
}
*/
// 4. Get Rx Frame Descriptor
FD_ptr = (struct FrameDesc *) priv->rx_ptr;
RxStat = (FD_ptr->StatusAndFrameLength >> 16) & 0xffff;
// 5. If Rx frame is good, then process received frame
if(RxStat & Good){
len = (FD_ptr->StatusAndFrameLength & 0xffff) - 4;
data = (unsigned char *) FD_ptr->FrameDataPtr + 2;
// 6. Get received frame to memory buffer
skb = dev_alloc_skb(len+2);
if(!skb) {
printk("S3C4510 eth: low on mem - packet dropped\n");
priv->stats.rx_dropped++;
return;
}
// memcpy(skb_put(skb, len), data, len);
/*
printk("len: %d\n", len);
for(i = 0; i < len; i++)
{
printk("%3x", data);
if((i+1)%16==0)
printk("\n");
}
printk("\n");
*/
skb->dev = dev;
skb_reserve(skb, 2);
skb_put(skb, len);
eth_copy_and_sum(skb, data, len, 0);
skb->protocol = eth_type_trans(skb, dev);
priv->stats.rx_packets++;
priv->stats.rx_bytes += len;
netif_rx(skb);
}
else {
// 7. If Rx frame has error, then process err frame
priv->stats.rx_errors++;
if(RxStat & LongErr)
priv->stats.rx_length_errors++;
if(RxStat & OvMax)
priv->stats.rx_over_errors++;
if(RxStat & CRCErr)
priv->stats.rx_crc_errors++;
if(RxStat & AlignErr)
priv->stats.rx_frame_errors++;
if(RxStat & Overflow)
priv->stats.rx_fifo_errors++;
}
// 8. Change ownership to BDMA for next use
FD_ptr -> FrameDataPtr |= BDMA_owner;
// Save Current Status and Frame Length field, and clear
FD_ptr -> StatusAndFrameLength = 0x0;
// 9. Get Next Frame Descriptor pointer to process
priv->rx_ptr = (unsigned long)(FD_ptr -> NextFrameDescriptor);
}while(CFD_ptr != priv->rx_ptr);
// 10. Check Notowner status
if(CSR_READ(BDMASTAT) & S_BRxNO) {
CSR_WRITE(BDMASTAT, S_BRxNO);
}
spin_unlock(&priv->lock);
} |
|