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