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

📄 ep93xx_irda.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
            /*      * Set start speed - 9600 (need to read clk first)      */    ep93xx_irda_sir_change_speed(self, (__u32)9600);       /*      * Turn on recieve interrupts for SIR (starting point)      */    uiRegVal = inl(UART2CR);    outl(uiRegVal|U2CR_RxIrq, UART2CR);    self->direction = DIR_RX;    /*     * Signal device is ready.      */    netif_start_queue(dev); 	    /*      * Give self a "hardware" name      */    sprintf(hwname, "EP93XX-S/M/FIR @ 0x%03x", IRDA_BASE);    /*      * Open new IrLAP layer instance, now that everything should be     * initialized properly      */    self->irlap = irlap_open(dev, &self->qos, hwname);		    MOD_INC_USE_COUNT;    EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);    return(0);}/* * Function ep93xx_irda_net_close (dev) * *    Stop the device. * */static int ep93xx_irda_net_close(struct net_device *dev){	    struct ep93xx_irda_cb *self;    int i;				    EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n",         __FUNCTION__);		    ASSERT(dev != NULL, return -1;);    self = (struct ep93xx_irda_cb *) dev->priv;    ASSERT(self != NULL, return 0;);    /*      * Stop device      */    netif_stop_queue(dev);	    /*     *  Stop and remove instance of IrLAP      */      if (self->irlap)    {	irlap_close(self->irlap);    }    self->irlap = NULL;		    /*      * Stop DMA channels & TX/RX.      */    SetDMA(self, DIR_BOTH, FALSE);    SetIR_Transmit(FALSE);    SetIR_Receive(FALSE);    /*      * Disable and release interrupts      */    SetInterrupts(self, FALSE);	           free_irq(self->iSIR_irq, dev);    free_irq(self->iMFIR_irq, dev);    /*     * release specialized EP93xx DMA channels      */    for(i = 0; i < DMA_COUNT; i++)    {        ep93xx_dma_free(self->iDMAh[i]);    }    MOD_DEC_USE_COUNT;    EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);	    return(0);}/* * Function ep93xx_irda_hard_xmit(skb, dev) * *    Prep a frame for Tx, and signal Tx (via ep93xx_irda_xmit). * */static int ep93xx_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev){    struct ep93xx_irda_cb *self;    unsigned long ulFlags;    int iLength;    __u32 speed;    int mtt;	    EP93XX_DEBUG(2, "%s(), ---------------- Start -----------------\n",         __FUNCTION__);    self = (struct ep93xx_irda_cb *) dev->priv;    SetDMA(self, self->direction, FALSE);    SetInterrupts(self, FALSE);    /*     * Getting ready to TX, so turn off RX.     */    //SetIR_Receive(FALSE);      /*      * Check if we need to change the speed      */   speed = irda_get_next_speed(skb);   if((speed != self->speed) && (speed != -1))    {	   EP93XX_DEBUG(1,"Speed change queued (%d)\n", speed);	   self->new_speed = speed;   }	      /*      * Check for empty frame      */    if((skb->len == 0) && (self->new_speed > 0))     {	EP93XX_DEBUG(1, "%s(), Empty frame for speed change.\n", __FUNCTION__);	ep93xx_irda_change_speed(self, speed); 	dev_kfree_skb(skb);	EP93XX_DEBUG(2,"%s(), ----------- SpeedOptOut ---------\n", 			__FUNCTION__);	return(0);    }      spin_lock_irqsave(&self->lock, ulFlags);   if((unsigned long)self->tx_fifo.tail % 0x10)   {	EP93XX_DEBUG(1, "Buffer not aligned?\n");   }      /*     * Register and copy this frame to DMA memory (do some alignment first).    */   self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;   if(self->speed <= 115200)   {        /*          * SIR: Copy skb to tx_fifo while wrapping, stuffing and making CRC.         */         netif_stop_queue(dev);	 self->tx_buff.data = self->tx_buff.head;	 iLength = async_wrap_skb(skb, self->tx_buff.data, 			 self->tx_buff.truesize);	 self->tx_buff.len = iLength;   }   else   {	EP93XX_DEBUG(1,"MFIR XMIT : %d bytes\n", skb->len);	memcpy(self->tx_fifo.queue[self->tx_fifo.free].start,			skb->data, skb->len);	iLength = skb->len;	self->tx_fifo.queue[self->tx_fifo.free].len = iLength;	self->tx_fifo.tail += iLength;	self->tx_fifo.len++;	self->tx_fifo.free++;   }     self->stats.tx_bytes += iLength;   /*     * Start transmit (if not currently)    */   if(((self->tx_fifo.len == 1) || (iLength > 0)))    {	self->direction = DIR_TX;        /*          * Check if we must wait the min turn time or not          */	mtt = irda_get_mtt(skb);	if(mtt) 	{		EP93XX_DEBUG(1, "%s(), ******* delay = %d ******* \n",                     __FUNCTION__, mtt);		mdelay(mtt);        }		/*	 * Enable TX	 */	SetIR_Transmit(TRUE);	   	/*     	 * Enable appropriate interrupts.    	 */   	SetInterrupts(self, TRUE);		    	/*     	 * Transmit frame, if MIR/FIR.    	 */	if(self->speed > 115200)	{	  	ep93xx_irda_dma_xmit(self);	}   }       /*     * Not busy transmitting if window is not full     */   if((self->tx_fifo.free < MAX_TX_WINDOW) && (self->speed > 115200))   {	netif_wake_queue(self->netdev);   }	   spin_unlock_irqrestore(&self->lock, ulFlags);   dev_kfree_skb(skb);   EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);	   return(0);}/* * Function ep93xx_irda_dma_xmit(self) *   *    Start DMA of TX buffer. *   */static void ep93xx_irda_dma_xmit(struct ep93xx_irda_cb *self){    int i;#ifndef PIO_TX    int iResult;#endif        unsigned long *ulDebug;    char *cDebug;		    EP93XX_DEBUG(1, "%s(), ---------------- Start -----------------\n",         __FUNCTION__);	    //MESSAGE("DMA_TX start\n");        /*      * Disable DMA      */    //SetDMA(self, DIR_BOTH, FALSE);    //self->direction = DIR_TX;    #ifdef PIO_TX       ulDebug = (unsigned long *)self->tx_fifo.queue[self->tx_fifo.ptr].start;    cDebug = (char *)self->tx_fifo.queue[self->tx_fifo.ptr].start + 	    self->tx_fifo.queue[self->tx_fifo.ptr].len;    // hit the tail register if necessary    switch(self->tx_fifo.queue[self->tx_fifo.ptr].len % 4)    {	    case 3: cDebug -= 3;		    outl(*((unsigned long *)cDebug), IrDataTail1);		    break;	    case 2: cDebug -= 2;		    outl(*((unsigned long *)cDebug), IrDataTail2);		    break;            case 1: cDebug -= 1;		    outl(*((unsigned long *)cDebug), IrDataTail3);		    break;            default: EP93XX_DEBUG(1, "No tail data.\n");		    break;    }    SetDMA(self, self->direction, TRUE);    for(i = 0; i < (self->tx_fifo.queue[self->tx_fifo.ptr].len / 4); i++)    {	/*	 * Wait for a SR to be flagged.	 */ 	while(!(inb(FISR) & MFISR_TXSR))	{		mdelay(1);	}			outl(ulDebug[i], IrData);    }    EP93XX_DEBUG(1,"XMIT wrote %d bytes\n", 	    ((i * 4) + self->tx_fifo.queue[self->tx_fifo.ptr].len % 4));#else            if(self->speed <= 115200)    {        iResult = ep93xx_dma_add_buffer(self->iDMAh[DMA_SIR_TX],             (unsigned int)self->tx_fifo.queue[self->tx_fifo.ptr].start, 0,                 self->tx_fifo.queue[self->tx_fifo.ptr].len, 0,                     self->iDMAh[DMA_SIR_TX]);    }    else    {	            iResult = ep93xx_dma_add_buffer(self->iDMAh[DMA_MFIR_TX],             (unsigned int)self->tx_fifo.queue[self->tx_fifo.ptr].start, 0,                 self->tx_fifo.queue[self->tx_fifo.ptr].len, 1,                     self->iDMAh[DMA_MFIR_TX]);    }	    if(iResult < 0)    {	EP93XX_DEBUG(1,"%s(), DMA add buffer failed (%d)\n", 			__FUNCTION__, iResult);    }        /*      * Enable DMA.      */    SetDMA(self, self->direction, TRUE);#endif       EP93XX_DEBUG(1, "%s(), ----------------- End ------------------\n",         __FUNCTION__);}/* * Function ep93xx_irda_dma_xmit_complete(self) * *    Clean up after TX. * */static int ep93xx_irda_dma_xmit_complete(struct ep93xx_irda_cb *self, int irqID){    int ret = TRUE;#ifndef PIO_TX        int iDMAh, iBufID, iTotalBytes;#endif    	    EP93XX_DEBUG(1, "%s(), ---------------- Start -----------------\n",         __FUNCTION__);    /*     * Disable DMA.     */    SetDMA(self, DIR_TX, FALSE);        /*     * Don't proceed until the transmitter goes idle.     */    do    {	mdelay(1); //new    }    while((inl(IrFlag) & IrFLAG_TXBUSY));#ifndef PIO_TX    /*     * Check for underrun. Due to SIP requirement and HW behavior, we'll     * need to check the DMA position to try and verify an underrun     * occured.     */    if(self->speed < 115200)    {        iDMAh = self->iDMAh[DMA_SIR_TX];    }    else    {        iDMAh = self->iDMAh[DMA_MFIR_TX];    }    ep93xx_dma_remove_buffer(iDMAh, &iBufID);        ep93xx_dma_get_position(iDMAh, &iBufID, &iTotalBytes, 0);        if((iTotalBytes < self->tx_fifo.queue[self->tx_fifo.ptr].len) && 		    (!(irqID & MFIIR_TXABORT)))    {	EP93XX_DEBUG(1,"TX Complete found a problem.\n");        self->stats.tx_errors++; 	self->stats.tx_fifo_errors++;		    }    else    {	self->stats.tx_packets++;    }#else    if(!(irqID & MFIIR_TXABORT))    {	    /*	     * "Assume" everything went well.	     */	    self->stats.tx_packets++;    }     else    {	    self->stats.tx_errors++;	    self->stats.tx_fifo_errors++;    }#endif        /*      * Check if we need to change the speed      */    if(self->new_speed)     {	EP93XX_DEBUG(1,"%s(), speed change queued - changing\n",			__FUNCTION__);        ep93xx_irda_change_speed(self, self->new_speed);	self->new_speed = 0;    }    /*      * Finished with this frame, so prepare for next      */    self->tx_fifo.ptr++;    self->tx_fifo.len--;    /*      * Any frames to be sent back-to-back?      */   if(self->tx_fifo.len)    {	ep93xx_irda_dma_xmit(self);			/*         * Not finished yet!          */	ret = FALSE;   }    else    {	        /*	 * Disable TX	 */	SetIR_Transmit(FALSE); //new	           /*          * Reset Tx FIFO info          */	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;	self->tx_fifo.tail = self->tx_buff.head;#ifndef PIO_TX        /*         * Flush the TX DMA (clears totalbytes for one thing).           */        ep93xx_dma_flush(iDMAh);#endif	    }    /*      * Make sure we have room for more frames      */    if(self->tx_fifo.free < MAX_TX_WINDOW)     {	/*          * Not busy transmitting anymore.  Tell the network layer,          * that we can accept more frames          */	netif_wake_queue(self->netdev);	    }		    /*     * Re-start the DMA     */    //SetDMA(self, self->direction, TRUE);    EP93XX_DEBUG(1, "%s(), ----------------- End ------------------\n",         __FUNCTION__);	    return(ret);}/* * Function ep93xx_irda_dma_receive (self) * *    Get ready to receive a frame. The device will initiate a DMA *    if it starts to receive a frame. * */static int ep93xx_irda_dma_receive(struct ep93xx_irda_cb *self) {    int iResult;    EP93XX_DEBUG(2, "%s(), ---------------- Start -----------------\n",         __FUNCTION__);    /*      * Reset the Tx FIFO info      */    self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;    self->tx_fifo.tail = self->tx_buff.head;		    /*      * Disable DMA until we're ready.     */    SetDMA(self, DIR_RX, FALSE);		    /*      * Reset Rx FIFO info      */    self->direction = DIR_RX;    self->rx_buff.data = self->rx_buff.head;		    /*      * Reset Rx FIFO      */    self->st_fifo.len = self->st_fifo.pending_bytes = 0;    self->st_fifo.tail = self->st_fifo.head = 0;        /*     * Add the buffer to the DMA queue.     */    iResult = ep93xx_dma_add_buffer(self->iDMAh[DMA_MFIR_RX], 		    (unsigned int)self->rx_buff.data, 0, 		    	self->rx_buff.truesize, 1, self->iDMAh[DMA_MFIR_RX]);    if(iResult < 0)    {	EP93XX_DEBUG(1,"DMARx failed to add buffer\n");    }    /*      * Enable RX & DMA     */    SetIR_Receive(TRUE);    SetDMA(self, DIR_RX, TRUE);    EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);    return(0);}

⌨️ 快捷键说明

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