|  | 
 
| 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);
 }
 | 
 |