static int rx_init()

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