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

📄 ep93xx_irda.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
        	}	if(iIrq & U2IICR_TXIRQ)        {            EP93XX_DEBUG(2, "%s(), Transmit IRQ\n", __FUNCTION__);            /*             * Tx'd a char, check Tx FIFO status.             */            iVal = inl(UART2FR);            if(iVal & U2FR_TXFE)            {#if U2_DMA_MODE                /*                 * TxFIFO is empty, check DMA position vs frame length.                 */                ep93xx_irda_dma_xmit_complete(self, iIrq);#else                /*                 * Check if more data to send.                 */                ep93xx_irda_sir_write_wakeup(self);#endif            }        }	if(iIrq & U2IICR_RXIRQ)        {	    EP93XX_DEBUG(2, "%s(), Receive IRQ\n", __FUNCTION__);            ep93xx_irda_sir_receive(self);        }        if(iIrq & U2IICR_MDMIRQ)        {            EP93XX_DEBUG(1, "%s(), Modem IRQ\n", __FUNCTION__);            /*             * Modem status, ignore but notify developer if in debug mode.             */        }    }    else    {        EP93XX_DEBUG(1, "%s(), An interrupt was signaled but not found.\n",             __FUNCTION__);    }     EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);}/* * Function ep93xx_irda_sir_receive (self) * *    Pull data from the RX FIFO and parse for *    frames. * */static void ep93xx_irda_sir_receive(struct ep93xx_irda_cb *self) {	int iLoopCt = 0, iRxPkts = 0;	char cData;		EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", 			__FUNCTION__);	ASSERT(self != NULL, return;);	iRxPkts = self->stats.rx_packets;	/*  	 * Receive all characters in Rx FIFO, unwrap and unstuff them.          * async_unwrap_char will deliver all found frames  	 */	do {		cData = inb(UART2DR);		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 				  cData);		EP93XX_DEBUG(2,"Byte = 0x%x\n", cData); 		/* 		 * Avoid taking too much time in here.		 */		if (iLoopCt++ > 32)         	{			EP93XX_DEBUG(1, "%s(), breaking!\n", __FUNCTION__);			break;		}					} while (!(inl(UART2FR) & U2FR_RXFE));			if(iRxPkts < self->stats.rx_packets)	{		EP93XX_DEBUG(2, "Received %d packets so far...\n", 				self->stats.rx_packets);		//mdelay(5);	}		EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", 			__FUNCTION__);	}/* * Function ep93xx_irda_sir_write_wakeup (tty) * *    Called by the driver when there's room for more data.  If we have *    more packets to send, we send them here. * */static void ep93xx_irda_sir_write_wakeup(struct ep93xx_irda_cb *self){	int iBytes = 0;	char cUART = 0;	ASSERT(self != NULL, return;);	EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", 			__FUNCTION__);       SetInterrupts(self, FALSE);	       /*         * Finished with frame?          */	if (self->tx_buff.len > 0)  	{		/*         	 * Write data left in transmit buffer         	 */		iBytes = ep93xx_irda_sir_write(self->fifo_size, 				      self->tx_buff.data, self->tx_buff.len);		self->tx_buff.data += iBytes;		self->tx_buff.len  -= iBytes;	} 	else //if(!(inl(UART2FR) & U2FR_BUSY))	{				if ((self->new_speed > 0)) 		{			/*              		 * Wait until the TX FIFO is empty.             		 */			do			{			    cUART=inl(UART2FR);  			    EP93XX_DEBUG(2, "Waiting on TX to complete...\n");			} while (cUART & U2FR_BUSY);						EP93XX_DEBUG(1, 				"%s(), Changing speed! self->new_speed = %d\n",         	        		__FUNCTION__, self->new_speed);						ep93xx_irda_change_speed(self, self->new_speed);		}		else		{			/*			 * Notify the stack we're ready for more data.			 */			netif_wake_queue(self->netdev);		}				self->stats.tx_packets++;		self->direction = DIR_RX;	}	SetInterrupts(self,TRUE);			EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", 			__FUNCTION__);	}/* * Function ep93xx_irda_sir_write () * *    Fill Tx FIFO with transmit data * */static int ep93xx_irda_sir_write(int iFifo_size, __u8 *pBuf, int iLen){	int iByteCt = 0;		EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", 			__FUNCTION__);       	/*     	 * Fill TX FIFO with current frame.    	 */	while ((iFifo_size-- > 0) && (iByteCt < iLen))     	{		/*        	 * Transmit byte         	 */		outl(pBuf[iByteCt], UART2DR);		EP93XX_DEBUG(2,"Tx Byte = 0x%x\n", pBuf[iByteCt]);		iByteCt++;	}	        EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", 			__FUNCTION__);		return(iByteCt);}/* * Function ep93xx_irda_change_speed * *    Exposed interface function.  Check speed *    and call worker function. * */static void ep93xx_irda_change_speed(struct ep93xx_irda_cb *self, __u32 baud){	unsigned long ulFlags;		EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n",         __FUNCTION__);	    if(self->speed == baud)    {        /*         * Desired speed is configured speed.         */        return;    }    EP93XX_DEBUG(1, "%s(), setting speed = %d \n", __FUNCTION__, baud);	    /*     * Turn off all interrupts.     */    save_flags(ulFlags);    cli();		    if(baud > 115200)    {    	/*          * Change to MIR/FIR speed          */  	 ep93xx_irda_mfir_change_speed(self, baud); 	/* 	 * Ready DMA for receive... 	 */ 	ep93xx_irda_dma_receive(self);    }	    else    {        /*          * Change to SIR speed          */	ep93xx_irda_sir_change_speed(self, baud);		/*	 * Ready for receive...	 */	self->direction = DIR_RX;	SetInterrupts(self, TRUE);    }    EP93XX_DEBUG(1, 	    "IrCtrl = 0x%x, IrEnable = 0x%x, FIMR = 0x%x, DMA = 0x%x\n", 		    inb(IrCtrl), inb(IrEnable), inb(FIMR), inb(IrDMACR));    /*     * Enable IRQs.     */    restore_flags(ulFlags);    /*     * Debug stuff - print packets tx/rx here.     */    EP93XX_DEBUG(2,"Packets:  RX = %d; TX = %d\n", self->stats.rx_packets, 		    self->stats.tx_packets);        /*     * Notify the upper layers the driver is read to receive packets     * and to schedule the driver for service.     */    netif_wake_queue(self->netdev);	     	    EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);}/* * Function ep93xx_irda_mfir_change_speed * *    Adjusts speed for MFIR (possibly needs to handle  *    transition from SIR). * */static void ep93xx_irda_mfir_change_speed(struct ep93xx_irda_cb *self, __u32 speed){    EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n",         __FUNCTION__);		    ASSERT(self != NULL, return;);    EP93XX_DEBUG(2, "%s(), self->speed = %d, change to speed = %d\n",         __FUNCTION__, self->speed, speed);	    /*      * Call regardless, no point duplicating code.     */    SIR2MFIR(self, speed);		    /*      * Update accounting for new speed      */    self->speed = speed;    self->new_speed = 0;				    EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);}/* * Function ep93xx_irda_sir_change_speed (self, speed) * *    Adjusts speed for SIR (possibly needs to handle *    transition from MFIR). * */static void ep93xx_irda_sir_change_speed(struct ep93xx_irda_cb *priv, __u32 speed){    struct ep93xx_irda_cb *self = (struct ep93xx_irda_cb *) priv;    unsigned int uiRegVal, uiCR_H, uiCR;    EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n",         __FUNCTION__);    ASSERT(self != NULL, return;);    EP93XX_DEBUG(2, "%s(), self->speed = %d, change to speed = %d\n",         __FUNCTION__, self->speed, speed);    /*     * May be transitioning from MFIR to SIR.     */    if(self->speed > 115200)    {        MFIR2SIR(self, speed);    }    /*      * Determine the clock and divisor      */    uiRegVal = inl(SYSCON_PWRCNT);    if(uiRegVal & SYSCON_PWRCNT_UARTBAUD)    {        /*          * UART CLK is 14.7456          */	uiRegVal = 14.7456 * 1000000;    }    else    {        /*          * UART CLK is 7.3728          */	uiRegVal = 7.3728 * 1000000;    }	    uiRegVal /= (16*speed);    uiRegVal -= 1;            /*      * IrDA ports use 8N1      */    uiCR_H = U2CRH_WLen | U2CRH_FEn;	    /*     * Clear all related registers before we update.  Save     * CR first.     */    uiCR = inl(UART2CR);        outb(0, UART2CR);    outb(0, UART2CR_M);    outb(0, UART2CR_L);    outb(0, UART2CR_H);        /*     * Three write options for these registers:     *     *  - UART2CR_L, UART2CR_M, UARTCR_H     *  - UART2CR_M, UART2CR_L, UARTCR_H     *  - UART2CR_L || UART2CR_M, UART2CR_H     */    outb(((uiRegVal & 0xf00) >> 8), UART2CR_M);    outb((uiRegVal & 0xff), UART2CR_L);    outb(uiCR_H, UART2CR_H);    outb(uiCR, UART2CR);				    /*      * Update accounting for new speed      */    self->speed = speed;    self->new_speed = 0;    /*     * The following is recommended by other implementations to maintain      * connection from MIR/FIR speed transition:     *      * 	                set DSR|CTS.     */    //uiRegVal = inl(UART2FR) & ~(U2FR_DSR | U2FR_CTS);    //outl(uiRegVal, UART2FR);	    EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);	}/* * Function ep93xx_irda_net_init (dev) * *    Initialize network device. * */static int ep93xx_irda_net_init(struct net_device *dev){	EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n",         __FUNCTION__);		/*      * Setup to be a normal IrDA network device driver      */	irda_device_setup(dev);	EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n",         __FUNCTION__);		return(0);}/* * Function ep93xx_irda_net_open (dev) * *    Start the device. * */static int ep93xx_irda_net_open(struct net_device *dev){    struct ep93xx_irda_cb *self;    char hwname[64];    unsigned int uiRegVal;		    EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n",         __FUNCTION__);	    ASSERT(dev != NULL, return -1;);	    self = (struct ep93xx_irda_cb *) dev->priv;	    ASSERT(self != NULL, return 0;);	    /*      * Request IRQs and install Interrupt Handler for them      */    if(request_irq(self->iSIR_irq, ep93xx_irda_interrupt, 0, dev->name, dev))     {	WARNING("%s, unable to allocate irq=%d\n", driver_name, 			self->iSIR_irq);	return(-EAGAIN);    }    if(request_irq(self->iMFIR_irq, ep93xx_irda_interrupt, 0, dev->name, dev))     {	WARNING("%s, unable to allocate irq=%d\n", driver_name, 			self->iMFIR_irq);	return(-EAGAIN);    }	    /*     * Allocate the DMA channels through the ep9xx special DMA API. Clean up on      * failure.  As there is no way to report failure in change_speed requests,     * get everything we need for all cases now.     */    if(ep93xx_dma_request(&(self->iDMAh[DMA_SIR_TX]), driver_name,         		self->ePorts[DMA_SIR_TX]))    {	ERROR("%s, unable to allocate SIR dma tx channel.\n", driver_name);	free_irq(self->iSIR_irq, self);        free_irq(self->iMFIR_irq, self);	return(-EAGAIN);    }    if(ep93xx_dma_config(self->iDMAh[DMA_SIR_TX], IGNORE_CHANNEL_ERROR, 0,			    0, 0))    {	ERROR("%s, unable to config SIR dma tx channel.\n", driver_name);	ep93xx_dma_free(self->iDMAh[DMA_SIR_TX]);	free_irq(self->iSIR_irq, self);	free_irq(self->iMFIR_irq, self);	return(-EAGAIN);    }    if(ep93xx_dma_request(&(self->iDMAh[DMA_MFIR_TX]), driver_name, 			    self->ePorts[DMA_MFIR_TX]))    {	ERROR("%s, unable to allocate MFIR dma tx channel.\n", driver_name);        ep93xx_dma_free(self->iDMAh[DMA_SIR_TX]);	free_irq(self->iSIR_irq, self);        free_irq(self->iMFIR_irq, self);	return(-EAGAIN);    }    if(ep93xx_dma_config(self->iDMAh[DMA_MFIR_TX], IGNORE_CHANNEL_ERROR,			    0, 0, 0))    {	ERROR("%s, unable to configure MFIR dma tx channel.\n", driver_name);	ep93xx_dma_free(self->iDMAh[DMA_SIR_TX]);	ep93xx_dma_free(self->iDMAh[DMA_MFIR_TX]);	free_irq(self->iSIR_irq, self);	free_irq(self->iMFIR_irq, self);	return(-EAGAIN);    }    if(ep93xx_dma_request(&(self->iDMAh[DMA_MFIR_RX]), driver_name, 			    self->ePorts[DMA_MFIR_RX]))    {	ERROR("%s, unable to allocate MFIR dma rx channel.\n", driver_name);        ep93xx_dma_free(self->iDMAh[DMA_SIR_TX]);        ep93xx_dma_free(self->iDMAh[DMA_MFIR_TX]);	free_irq(self->iSIR_irq, self);        free_irq(self->iMFIR_irq, self);	return(-EAGAIN);    }    if(ep93xx_dma_config(self->iDMAh[DMA_MFIR_RX], IGNORE_CHANNEL_ERROR,			    0, 0, 0))    {	ERROR("%s, unable to configure MFIR dma rx channel.\n", driver_name);	ep93xx_dma_free(self->iDMAh[DMA_SIR_TX]);	ep93xx_dma_free(self->iDMAh[DMA_MFIR_TX]);	ep93xx_dma_free(self->iDMAh[DMA_MFIR_RX]);	free_irq(self->iSIR_irq, self);	free_irq(self->iMFIR_irq, self);	return(-EAGAIN);    }

⌨️ 快捷键说明

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