in iphase.c [1421:1643]
static int rx_init(struct atm_dev *dev)
{
IADEV *iadev;
struct rx_buf_desc __iomem *buf_desc_ptr;
unsigned long rx_pkt_start = 0;
void *dle_addr;
struct abr_vc_table *abr_vc_table;
u16 *vc_table;
u16 *reass_table;
int i,j, vcsize_sel;
u_short freeq_st_adr;
u_short *freeq_start;
iadev = INPH_IA_DEV(dev);
// spin_lock_init(&iadev->rx_lock);
/* Allocate 4k bytes - more aligned than needed (4k boundary) */
dle_addr = dma_alloc_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE,
&iadev->rx_dle_dma, GFP_KERNEL);
if (!dle_addr) {
printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
goto err_out;
}
iadev->rx_dle_q.start = (struct dle *)dle_addr;
iadev->rx_dle_q.read = iadev->rx_dle_q.start;
iadev->rx_dle_q.write = iadev->rx_dle_q.start;
iadev->rx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES);
/* the end of the dle q points to the entry after the last
DLE that can be used. */
/* write the upper 20 bits of the start address to rx list address register */
/* We know this is 32bit bus addressed so the following is safe */
writel(iadev->rx_dle_dma & 0xfffff000,
iadev->dma + IPHASE5575_RX_LIST_ADDR);
IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n",
iadev->dma+IPHASE5575_TX_LIST_ADDR,
readl(iadev->dma + IPHASE5575_TX_LIST_ADDR));
printk("Rx Dle list addr: 0x%p value: 0x%0x\n",
iadev->dma+IPHASE5575_RX_LIST_ADDR,
readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));)
writew(0xffff, iadev->reass_reg+REASS_MASK_REG);
writew(0, iadev->reass_reg+MODE_REG);
writew(RESET_REASS, iadev->reass_reg+REASS_COMMAND_REG);
/* Receive side control memory map
-------------------------------
Buffer descr 0x0000 (736 - 23K)
VP Table 0x5c00 (256 - 512)
Except q 0x5e00 (128 - 512)
Free buffer q 0x6000 (1K - 2K)
Packet comp q 0x6800 (1K - 2K)
Reass Table 0x7000 (1K - 2K)
VC Table 0x7800 (1K - 2K)
ABR VC Table 0x8000 (1K - 32K)
*/
/* Base address for Buffer Descriptor Table */
writew(RX_DESC_BASE >> 16, iadev->reass_reg+REASS_DESC_BASE);
/* Set the buffer size register */
writew(iadev->rx_buf_sz, iadev->reass_reg+BUF_SIZE);
/* Initialize each entry in the Buffer Descriptor Table */
iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize;
buf_desc_ptr = iadev->RX_DESC_BASE_ADDR;
memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
buf_desc_ptr++;
rx_pkt_start = iadev->rx_pkt_ram;
for(i=1; i<=iadev->num_rx_desc; i++)
{
memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16;
buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff;
buf_desc_ptr++;
rx_pkt_start += iadev->rx_buf_sz;
}
IF_INIT(printk("Rx Buffer desc ptr: 0x%p\n", buf_desc_ptr);)
i = FREE_BUF_DESC_Q*iadev->memSize;
writew(i >> 16, iadev->reass_reg+REASS_QUEUE_BASE);
writew(i, iadev->reass_reg+FREEQ_ST_ADR);
writew(i+iadev->num_rx_desc*sizeof(u_short),
iadev->reass_reg+FREEQ_ED_ADR);
writew(i, iadev->reass_reg+FREEQ_RD_PTR);
writew(i+iadev->num_rx_desc*sizeof(u_short),
iadev->reass_reg+FREEQ_WR_PTR);
/* Fill the FREEQ with all the free descriptors. */
freeq_st_adr = readw(iadev->reass_reg+FREEQ_ST_ADR);
freeq_start = (u_short *)(iadev->reass_ram+freeq_st_adr);
for(i=1; i<=iadev->num_rx_desc; i++)
{
*freeq_start = (u_short)i;
freeq_start++;
}
IF_INIT(printk("freeq_start: 0x%p\n", freeq_start);)
/* Packet Complete Queue */
i = (PKT_COMP_Q * iadev->memSize) & 0xffff;
writew(i, iadev->reass_reg+PCQ_ST_ADR);
writew(i+iadev->num_vc*sizeof(u_short), iadev->reass_reg+PCQ_ED_ADR);
writew(i, iadev->reass_reg+PCQ_RD_PTR);
writew(i, iadev->reass_reg+PCQ_WR_PTR);
/* Exception Queue */
i = (EXCEPTION_Q * iadev->memSize) & 0xffff;
writew(i, iadev->reass_reg+EXCP_Q_ST_ADR);
writew(i + NUM_RX_EXCP * sizeof(RX_ERROR_Q),
iadev->reass_reg+EXCP_Q_ED_ADR);
writew(i, iadev->reass_reg+EXCP_Q_RD_PTR);
writew(i, iadev->reass_reg+EXCP_Q_WR_PTR);
/* Load local copy of FREEQ and PCQ ptrs */
iadev->rfL.fdq_st = readw(iadev->reass_reg+FREEQ_ST_ADR) & 0xffff;
iadev->rfL.fdq_ed = readw(iadev->reass_reg+FREEQ_ED_ADR) & 0xffff ;
iadev->rfL.fdq_rd = readw(iadev->reass_reg+FREEQ_RD_PTR) & 0xffff;
iadev->rfL.fdq_wr = readw(iadev->reass_reg+FREEQ_WR_PTR) & 0xffff;
iadev->rfL.pcq_st = readw(iadev->reass_reg+PCQ_ST_ADR) & 0xffff;
iadev->rfL.pcq_ed = readw(iadev->reass_reg+PCQ_ED_ADR) & 0xffff;
iadev->rfL.pcq_rd = readw(iadev->reass_reg+PCQ_RD_PTR) & 0xffff;
iadev->rfL.pcq_wr = readw(iadev->reass_reg+PCQ_WR_PTR) & 0xffff;
IF_INIT(printk("INIT:pcq_st:0x%x pcq_ed:0x%x pcq_rd:0x%x pcq_wr:0x%x",
iadev->rfL.pcq_st, iadev->rfL.pcq_ed, iadev->rfL.pcq_rd,
iadev->rfL.pcq_wr);)
/* just for check - no VP TBL */
/* VP Table */
/* writew(0x0b80, iadev->reass_reg+VP_LKUP_BASE); */
/* initialize VP Table for invalid VPIs
- I guess we can write all 1s or 0x000f in the entire memory
space or something similar.
*/
/* This seems to work and looks right to me too !!! */
i = REASS_TABLE * iadev->memSize;
writew((i >> 3), iadev->reass_reg+REASS_TABLE_BASE);
/* initialize Reassembly table to I don't know what ???? */
reass_table = (u16 *)(iadev->reass_ram+i);
j = REASS_TABLE_SZ * iadev->memSize;
for(i=0; i < j; i++)
*reass_table++ = NO_AAL5_PKT;
i = 8*1024;
vcsize_sel = 0;
while (i != iadev->num_vc) {
i /= 2;
vcsize_sel++;
}
i = RX_VC_TABLE * iadev->memSize;
writew(((i>>3) & 0xfff8) | vcsize_sel, iadev->reass_reg+VC_LKUP_BASE);
vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);
j = RX_VC_TABLE_SZ * iadev->memSize;
for(i = 0; i < j; i++)
{
/* shift the reassembly pointer by 3 + lower 3 bits of
vc_lkup_base register (=3 for 1K VCs) and the last byte
is those low 3 bits.
Shall program this later.
*/
*vc_table = (i << 6) | 15; /* for invalid VCI */
vc_table++;
}
/* ABR VC table */
i = ABR_VC_TABLE * iadev->memSize;
writew(i >> 3, iadev->reass_reg+ABR_LKUP_BASE);
i = ABR_VC_TABLE * iadev->memSize;
abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i);
j = REASS_TABLE_SZ * iadev->memSize;
memset ((char*)abr_vc_table, 0, j * sizeof(*abr_vc_table));
for(i = 0; i < j; i++) {
abr_vc_table->rdf = 0x0003;
abr_vc_table->air = 0x5eb1;
abr_vc_table++;
}
/* Initialize other registers */
/* VP Filter Register set for VC Reassembly only */
writew(0xff00, iadev->reass_reg+VP_FILTER);
writew(0, iadev->reass_reg+XTRA_RM_OFFSET);
writew(0x1, iadev->reass_reg+PROTOCOL_ID);
/* Packet Timeout Count related Registers :
Set packet timeout to occur in about 3 seconds
Set Packet Aging Interval count register to overflow in about 4 us
*/
writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT );
i = (j >> 6) & 0xFF;
j += 2 * (j - 1);
i |= ((j << 2) & 0xFF00);
writew(i, iadev->reass_reg+TMOUT_RANGE);
/* initiate the desc_tble */
for(i=0; i<iadev->num_tx_desc;i++)
iadev->desc_tbl[i].timestamp = 0;
/* to clear the interrupt status register - read it */
readw(iadev->reass_reg+REASS_INTR_STATUS_REG);
/* Mask Register - clear it */
writew(~(RX_FREEQ_EMPT|RX_PKT_RCVD), iadev->reass_reg+REASS_MASK_REG);
skb_queue_head_init(&iadev->rx_dma_q);
iadev->rx_free_desc_qhead = NULL;
iadev->rx_open = kcalloc(iadev->num_vc, sizeof(void *), GFP_KERNEL);
if (!iadev->rx_open) {
printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n",
dev->number);
goto err_free_dle;
}
iadev->rxing = 1;
iadev->rx_pkt_cnt = 0;
/* Mode Register */
writew(R_ONLINE, iadev->reass_reg+MODE_REG);
return 0;
err_free_dle:
dma_free_coherent(&iadev->pci->dev, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
iadev->rx_dle_dma);
err_out:
return -ENOMEM;
}