📄 ep93xx_irda.c
字号:
} 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 + -