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