⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iphase.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* 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 over flow\n");)                }		free_desc(dev, desc);  		return 0;  	}    	/*  		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);           free_desc(dev, desc);            return 0;        }		  #if LINUX_VERSION_CODE >= 0x20312        if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) {#else        if (atm_charge(vcc, atm_pdu2truesize(len))) {	   /* lets allocate an skb for now */  	   skb = alloc_skb(len, GFP_ATOMIC);  	   if (!skb)  	   {                IF_ERR(printk("can't allocate memory for recv, drop pkt!\n");)                atomic_inc(&vcc->stats->rx_drop);              atm_return(vcc, atm_pdu2truesize(len));              free_desc(dev, desc); 	      return 0;  	   }          }        else {           IF_EVENT(printk("IA: Rx over the rx_quota %ld\n", vcc->rx_quota);)#endif           if (vcc->vci < 32)              printk("Drop control packets\n");           free_desc(dev, desc);           return 0;        }	skb_put(skb,len);          // pwang_test        ATM_SKB(skb)->vcc = vcc;        ATM_SKB(skb)->iovcnt = 0;        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 = virt_to_bus(skb->data);	  	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);   	return 0;  }    static void rx_intr(struct atm_dev *dev)  {    IADEV *iadev;    u_short status;    u_short state, i;      iadev = INPH_IA_DEV(dev);    status = readl(iadev->reass_reg+REASS_INTR_STATUS_REG) & 0xffff;    IF_EVENT(printk("rx_intr: status = 0x%x\n", status);)  if (status & RX_PKT_RCVD)    {  	/* do something */  	/* Basically recvd an interrupt for receving a packet.  	A descriptor would have been written to the packet complete   	queue. Get all the descriptors and set up dma to move the   	packets till the packet complete queue is empty..  	*/  	state = readl(iadev->reass_reg + STATE_REG) & 0xffff;          IF_EVENT(printk("Rx intr status: RX_PKT_RCVD %08x\n", status);) 	while(!(state & PCQ_EMPTY))  	{               rx_pkt(dev);  	     state = readl(iadev->reass_reg + STATE_REG) & 0xffff;  	}          iadev->rxing = 1;  }    if (status & RX_FREEQ_EMPT)    {        if (iadev->rxing) {        iadev->rx_tmp_cnt = iadev->rx_pkt_cnt;        iadev->rx_tmp_jif = jiffies;         iadev->rxing = 0;     }      else if (((jiffies - iadev->rx_tmp_jif) > 50) &&                ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {        for (i = 1; i <= iadev->num_rx_desc; i++)               free_desc(dev, i);printk("Test logic RUN!!!!\n");        writew( ~(RX_FREEQ_EMPT|RX_EXCP_RCVD),iadev->reass_reg+REASS_MASK_REG);        iadev->rxing = 1;     }     IF_EVENT(printk("Rx intr status: RX_FREEQ_EMPT %08x\n", status);)    }    if (status & RX_EXCP_RCVD)    {  	/* probably need to handle the exception queue also. */  	IF_EVENT(printk("Rx intr status: RX_EXCP_RCVD %08x\n", status);)  	rx_excp_rcvd(dev);    }    if (status & RX_RAW_RCVD)    {  	/* need to handle the raw incoming cells. This deepnds on   	whether we have programmed to receive the raw cells or not.  	Else ignore. */  	IF_EVENT(printk("Rx intr status:  RX_RAW_RCVD %08x\n", status);)    }  }      static void rx_dle_intr(struct atm_dev *dev)  {    IADEV *iadev;    struct atm_vcc *vcc;     struct sk_buff *skb;    int desc;    u_short state;     struct dle *dle, *cur_dle;    u_int dle_lp;    iadev = INPH_IA_DEV(dev);     /* free all the dles done, that is just update our own dle read pointer   	- do we really need to do this. Think not. */    /* DMA is done, just get all the recevie buffers from the rx dma queue  	and push them up to the higher layer protocol. Also free the desc  	associated with the buffer. */    dle = iadev->rx_dle_q.read;    dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);    cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));    while(dle != cur_dle)    {        /* free the DMAed skb */        skb = skb_dequeue(&iadev->rx_dma_q);        if (!skb)           goto INCR_DLE;      desc = ATM_DESC(skb);      free_desc(dev, desc);                       if (!skb->len)        {            printk("rx_dle_intr: skb len 0\n");  	  dev_kfree_skb_any(skb);        }        else        {            struct cpcs_trailer *trailer;          u_short length;          struct ia_vcc *ia_vcc;          /* no VCC related housekeeping done as yet. lets see */            vcc = ATM_SKB(skb)->vcc;	  if (!vcc) {	      printk("IA: null vcc\n");                atomic_inc(&vcc->stats->rx_err);              dev_kfree_skb_any(skb);              goto INCR_DLE;          }          ia_vcc = INPH_IA_VCC(vcc);          if (ia_vcc == NULL)          {             atomic_inc(&vcc->stats->rx_err);             dev_kfree_skb_any(skb);#if LINUX_VERSION_CODE >= 0x20312             atm_return(vcc, atm_guess_pdu2truesize(skb->len));#else             atm_return(vcc, atm_pdu2truesize(skb->len));#endif             goto INCR_DLE;           }          // get real pkt length  pwang_test          trailer = (struct cpcs_trailer*)((u_char *)skb->data +                                 skb->len - sizeof(struct cpcs_trailer));          length =  swap(trailer->length);          if ((length > iadev->rx_buf_sz) || (length >                               (skb->len - sizeof(struct cpcs_trailer))))          {             atomic_inc(&vcc->stats->rx_err);             dev_kfree_skb_any(skb);             IF_ERR(printk("rx_dle_intr: Bad  AAL5 trailer %d (skb len %d)",                                                             length, skb->len);)#if LINUX_VERSION_CODE >= 0x20312             atm_return(vcc, atm_guess_pdu2truesize(skb->len));#else             atm_return(vcc, atm_pdu2truesize(skb->len));#endif              goto INCR_DLE;          }          skb_trim(skb, length);          	  /* Display the packet */  	  IF_RXPKT(printk("\nDmad Recvd data: len = %d \n", skb->len);            xdump(skb->data, skb->len, "RX: ");          printk("\n");)	  IF_RX(printk("rx_dle_intr: skb push");)  	  vcc->push(vcc,skb);  	  atomic_inc(&vcc->stats->rx);          iadev->rx_pkt_cnt++;      }  INCR_DLE:      if (++dle == iadev->rx_dle_q.end)      	  dle = iadev->rx_dle_q.start;    }    iadev->rx_dle_q.read = dle;      /* if the interrupts are masked because there were no free desc available,  		unmask them now. */   if (!iadev->rxing) {     state = readl(iadev->reass_reg + STATE_REG) & 0xffff;     if (!(state & FREEQ_EMPTY)) {        state = readl(iadev->reass_reg + REASS_MASK_REG) & 0xffff;        writel(state & ~(RX_FREEQ_EMPT |/* RX_EXCP_RCVD |*/ RX_PKT_RCVD),                                      iadev->reass_reg+REASS_MASK_REG);        iadev->rxing++;      }  }}      static int open_rx(struct atm_vcc *vcc)  {  	IADEV *iadev;  	u_short *vc_table;  	u_short *reass_ptr;  	IF_EVENT(printk("iadev: open_rx %d.%d\n", vcc->vpi, vcc->vci);)	if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;    	iadev = INPH_IA_DEV(vcc->dev);          if (vcc->qos.rxtp.traffic_class == ATM_ABR) {             if (iadev->phy_type & FE_25MBIT_PHY) {               printk("IA:  ABR not support\n");               return -EINVAL;            }        }	/* Make only this VCI in the vc table valid and let all   		others be invalid entries */  	vc_table = (u_short *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);  	vc_table += vcc->vci;  	/* mask the last 6 bits and OR it with 3 for 1K VCs */          *vc_table = vcc->vci << 6;	/* Also keep a list of open rx vcs so that we can attach them with  		incoming PDUs later. */  	if ((vcc->qos.rxtp.traffic_class == ATM_ABR) ||                                 (vcc->qos.txtp.traffic_class == ATM_ABR))  	{                  srv_cls_param_t srv_p;                init_abr_vc(iadev, &srv_p);                ia_open_abr_vc(iadev, &srv_p, vcc, 0);	}        	else {  /* for UBR  later may need to add CBR logic */        	reass_ptr = (u_short *)                           (iadev->reass_ram+REASS_TABLE*iadev->memSize);           	reass_ptr += vcc->vci;             	*reass_ptr = NO_AAL5_PKT;       	}		if (iadev->rx_open[vcc->vci])  		printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n",  			vcc->dev->number, vcc->vci);  	iadev->rx_open[vcc->vci] = vcc;  	return 0;  }    static int rx_init(struct atm_dev *dev)  {  	IADEV *iadev;  	struct rx_buf_desc *buf_desc_ptr;  	unsigned long rx_pkt_start = 0;  	u32 *dle_addr;  	struct abr_vc_table  *abr_vc_table; 	u16 *vc_table;  	u16 *reass_table;          u16 *ptr16;	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); 	/* I need to initialize the DLEs somewhere. Lets see what I   		need to do for this, hmmm...  		- allocate memory for 256 DLEs. make sure that it starts  		on a 4k byte address boundary. Program the start address   		in Receive List address register.  ..... to do for TX also  	   To make sure that it is a 4k byte boundary - allocate 8k and find   		4k byte boundary within.  		( (addr + (4k-1)) & ~(4k-1) )  	*/     	/* allocate 8k bytes */  	dle_addr = (u32*)kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL);  	if (!dle_addr)  	{  		printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");  	}  	/* find 4k byte boundary within the 8k allocated */  	dle_addr = (u32*)( ((u32)dle_addr+(4096-1)) & ~(4096-1) );  	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*)((u32)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 */  	writel(virt_to_bus(dle_addr) & 0xfffff000, iadev->dma+IPHASE5575_RX_LIST_ADDR);  	IF_INIT(printk("Tx Dle list addr: 0x%08x value: 0x%0x\n",                       (u32)(iadev->dma+IPHASE5575_TX_LIST_ADDR),                       *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR));  	printk("Rx Dle list addr: 0x%08x value: 0x%0x\n",                       (u32)(iadev->dma+IPHASE5575_RX_LIST_ADDR),                       *(u32*)(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 =(struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR;	memset((caddr_t)buf_desc_ptr, 0, sizeof(struct rx_buf_desc));  	buf_desc_ptr++;  	rx_pkt_start = iadev->rx_pkt_ram;  	for(i=1; i<=iadev->num_rx_desc; i++)  	{  		memset((caddr_t)buf_desc_ptr, 0, sizeof(struct rx_buf_desc));  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -