static int rx_pkt()

in iphase.c [1097:1210]


static int rx_pkt(struct atm_dev *dev)  
{  
	IADEV *iadev;  
	struct atm_vcc *vcc;  
	unsigned short status;  
	struct rx_buf_desc __iomem *buf_desc_ptr;  
	int desc;   
	struct dle* wr_ptr;  
	int len;  
	struct sk_buff *skb;  
	u_int buf_addr, dma_addr;  

	iadev = INPH_IA_DEV(dev);  
	if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff)) 
	{  
   	    printk(KERN_ERR DEV_LABEL "(itf %d) Receive queue empty\n", dev->number);  
	    return -EINVAL;  
	}  
	/* mask 1st 3 bits to get the actual descno. */  
	desc = readw(iadev->reass_ram+iadev->rfL.pcq_rd) & 0x1fff;  
        IF_RX(printk("reass_ram = %p iadev->rfL.pcq_rd = 0x%x desc = %d\n", 
                                    iadev->reass_ram, iadev->rfL.pcq_rd, desc);
              printk(" pcq_wr_ptr = 0x%x\n",
                               readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff);)
	/* update the read pointer  - maybe we shud do this in the end*/  
	if ( iadev->rfL.pcq_rd== iadev->rfL.pcq_ed) 
		iadev->rfL.pcq_rd = iadev->rfL.pcq_st;  
	else  
		iadev->rfL.pcq_rd += 2;
	writew(iadev->rfL.pcq_rd, iadev->reass_reg+PCQ_RD_PTR);  
  
	/* get the buffer desc entry.  
		update stuff. - doesn't seem to be any update necessary  
	*/  
	buf_desc_ptr = iadev->RX_DESC_BASE_ADDR;
	/* make the ptr point to the corresponding buffer desc entry */  
	buf_desc_ptr += desc;	  
        if (!desc || (desc > iadev->num_rx_desc) || 
                      ((buf_desc_ptr->vc_index & 0xffff) >= iadev->num_vc)) {
            free_desc(dev, desc);
            IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
            return -1;
        }
	vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];  
	if (!vcc)  
	{      
                free_desc(dev, desc); 
		printk("IA: null vcc, drop PDU\n");  
		return -1;  
	}  
	  
  
	/* might want to check the status bits for errors */  
	status = (u_short) (buf_desc_ptr->desc_mode);  
	if (status & (RX_CER | RX_PTE | RX_OFL))  
	{  
                atomic_inc(&vcc->stats->rx_err);
		IF_ERR(printk("IA: bad packet, dropping it");)  
                if (status & RX_CER) { 
                    IF_ERR(printk(" cause: packet CRC error\n");)
                }
                else if (status & RX_PTE) {
                    IF_ERR(printk(" cause: packet time out\n");)
                }
                else {
                    IF_ERR(printk(" cause: buffer overflow\n");)
                }
		goto out_free_desc;
	}  
  
	/*  
		build DLE.	  
	*/  
  
	buf_addr = (buf_desc_ptr->buf_start_hi << 16) | buf_desc_ptr->buf_start_lo;  
	dma_addr = (buf_desc_ptr->dma_start_hi << 16) | buf_desc_ptr->dma_start_lo;  
	len = dma_addr - buf_addr;  
        if (len > iadev->rx_buf_sz) {
           printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz);
           atomic_inc(&vcc->stats->rx_err);
	   goto out_free_desc;
        }
		  
        if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) {
           if (vcc->vci < 32)
              printk("Drop control packets\n");
	   goto out_free_desc;
        }
	skb_put(skb,len);  
        // pwang_test
        ATM_SKB(skb)->vcc = vcc;
        ATM_DESC(skb) = desc;        
	skb_queue_tail(&iadev->rx_dma_q, skb);  

	/* Build the DLE structure */  
	wr_ptr = iadev->rx_dle_q.write;  
	wr_ptr->sys_pkt_addr = dma_map_single(&iadev->pci->dev, skb->data,
					      len, DMA_FROM_DEVICE);
	wr_ptr->local_pkt_addr = buf_addr;  
	wr_ptr->bytes = len;	/* We don't know this do we ?? */  
	wr_ptr->mode = DMA_INT_ENABLE;  
  
	/* shud take care of wrap around here too. */  
        if(++wr_ptr == iadev->rx_dle_q.end)
             wr_ptr = iadev->rx_dle_q.start;
	iadev->rx_dle_q.write = wr_ptr;  
	udelay(1);  
	/* Increment transaction counter */  
	writel(1, iadev->dma+IPHASE5575_RX_COUNTER);   
out:	return 0;  
out_free_desc:
        free_desc(dev, desc);
        goto out;
}