📄 pxa_ir.c
字号:
* FIR format interrupt service routine. We only have to * handle RX events; transmit events go via the TX DMA irq handler. * * No matter what, we disable RX, process, and then restart RX. */static void pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = dev_id; struct pxa250_irda *si = dev->priv; int status; /* * Stop RX */ __ECHO_IN; pxa250_dma_stop(si->rxdma_ch); /* * Framing error - we throw away the packet completely. * Clearing RXE flushes the error conditions and data * from the fifo. */ status=ICSR0; if (status & (ICSR0_FRE | ICSR0_RAB)) { DBG_IRQ("Framing error or RAB\n"); si->stats.rx_errors++; if (ICSR0 & ICSR0_FRE) si->stats.rx_frame_errors++; /* Clear RX fifo * DMA will be cleared when we restart RX * Should we check RNE after that? */ ICCR0 &= ~ICCR0_RXE; /* * Clear selected status bits now, so we * don't miss them next time around. */ ICSR0 = status & (ICSR0_FRE | ICSR0_RAB); } /* * Deal with any receive errors. The any of the lowest * 8 bytes in the FIFO may contain an error. We must read * them one by one. The "error" could even be the end of * packet! */ if (ICSR0 & ICSR0_EIF) pxa250_irda_fir_error(dev); /* * No matter what happens, we must restart reception. */ ICCR0 = 0; pxa250_start_rx_dma(dev); pxa250_ficp_rx_start(); __ECHO_OUT;}/************************************************************************** * SIR * **************************************************************************//* * HP-SIR format interrupt service routines. */static void pxa250_sir_transmit(struct net_device *dev){ struct pxa250_irda *si = dev->priv; if (si->tx_buff.len) { /* Disable receiver and enable transmiter*/ DBG("tx routine\n"); STISR &= ~STISR_RCVEIR; STISR |= STISR_XMITIR; DBG("set STISR tx\n"); disable_irq(dev->irq); do { if (STLSR & LSR_TDRQ) { STTHR = *si->tx_buff.data++; si->tx_buff.len -= 1; tx_count++; } } while (si->tx_buff.len); if (si->tx_buff.len == 0) { si->stats.tx_packets++; si->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head; /* * We need to ensure that the transmitter has * finished. */ do { udelay(1); } while ( ! (STLSR & LSR_TEMT) ); /* * Ok, we've finished transmitting. Now enable * the receiver. Sometimes we get a receive IRQ * immediately after a transmit... */ if (si->newspeed) { pxa250_irda_set_speed(dev, si->newspeed); si->newspeed = 0; } /* I'm hungry! */ netif_wake_queue(dev); } enable_irq (dev->irq); STIER = (IER_RAVIE | IER_UUE | IER_RTIOE); STISR |= STISR_RCVEIR; STISR &= ~STISR_XMITIR; DBG("set STISR rx\n"); }}static void pxa250_irda_hpsir_irq(struct net_device *dev){ struct pxa250_irda *si = dev->priv; int istat; /* this mess is needed since when we read STLSR we destroy it */ /* * Deal with any receive errors first. The bytes in error may be * the only bytes in the receive FIFO, so we do this first. */ __ECHO_IN; istat = STLSR; DBG_IRQ("istat is %x\n", istat); while (1) { int stat, data; if (! (istat & LSR_FIFOE) ) break; /* jump out if no errors */ stat = istat; data = STRBR; DBG_IRQ("stat is %x, data is %x (error)\n", stat, data); if (stat & LSR_BI) { DBG_IRQ("break\n"); } if (stat & (LSR_FE | LSR_OE | LSR_PE)) { DBG_IRQ("error\n"); si->stats.rx_errors++; if (stat & LSR_FE) si->stats.rx_frame_errors++; if (stat & LSR_OE) si->stats.rx_fifo_errors++; } else { DBG_IRQ("rxing1\n"); rx_count++; async_unwrap_char(dev, &si->stats, &si->rx_buff, data); } istat = STLSR; DBG_IRQ("istat is %x\n", istat); } /* * We must clear certain bits. */ if (istat & (LSR_DR)) { /* * Fifo contains at least 1 character. */ do { int data; data = STRBR; DBG_IRQ("data is %x, rxing2\n", data); async_unwrap_char(dev, &si->stats, &si->rx_buff, data); /* was Ser2UTDR); Clo */ rx_count++; istat = STLSR; DBG_IRQ("istat is %x\n", istat); } while (istat & LSR_DR); dev->last_rx = jiffies; } __ECHO_OUT; }static void pxa250_sir_irda_shutdown(struct pxa250_irda *si){ STIER = 0; STFCR = 0; STISR = 0; CKEN &= ~CKEN5_STUART; #ifdef CONFIG_ARCH_H3900H3900_ASIC3_GPIO_B_DIR |= GPIO3_IR_ON_N;H3900_ASIC3_GPIO_B_OUT |= GPIO3_IR_ON_N;H3900_ASIC3_GPIO_B_DIR |= GPIO3_CIR_CTL_PWR_ON;H3900_ASIC3_GPIO_B_OUT &= ~GPIO3_CIR_CTL_PWR_ON;#endif}/************************************************************************************//*Low level init/uninstall function PM control and IrDA protocol stack registration *//* * Set the IrDA communications speed. * Interrupt have to be disabled here. */static int pxa250_irda_startup(struct net_device *dev){ __ECHO_IN; /* * Ensure that the ports for this device are setup correctly. */ DBG("GPIO sir\n"); set_GPIO_mode (GPIO46_STRXD_MD); set_GPIO_mode (GPIO47_STTXD_MD);// STMCR = MCR_OUT2 | (sir_loop?MCR_LOOP:0); STMCR = MCR_OUT2; STLCR = LCR_WLS1 | LCR_WLS0; SET_SIR_MODE; CKEN |= CKEN5_STUART; /* enable irq from stuart */ ICMR |= ( 1 << 20 ); /*reset FIFO*/ STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF; STIER = IER_UUE | IER_RAVIE | IER_RTIOE; __ECHO_OUT; return 0; }#ifdef CONFIG_PM/* * Suspend the IrDA interface. */static int pxa250_irda_shutdown(struct pxa250_irda *si){ pxa250_sir_irda_shutdown(si); return 0; }static int pxa250_irda_suspend(struct net_device *dev, int state){ struct pxa250_irda *si = dev->priv; if (si && si->open) { /* * Stop the transmit queue */ if (IS_FIR(si)) return -1; netif_stop_queue(dev); disable_irq(dev->irq); disable_irq(si->fir_irq); pxa250_sir_irda_shutdown(si); } return 0;}/* * Resume the IrDA interface. */static int pxa250_irda_resume(struct net_device *dev){ struct pxa250_irda *si = dev->priv; __ECHO_IN; if (si && si->open) { /* * If we missed a speed change, initialise at the new speed * directly. It is debatable whether this is actually * required, but in the interests of continuing from where * we left off it is desireable. The converse argument is * that we should re-negotiate at 9600 baud again. */ if (si->newspeed) { si->speed = si->newspeed; si->newspeed = 0; } pxa250_irda_startup(dev); enable_irq(dev->irq); /* * This automatically wakes up the queue */ netif_wake_queue(dev); pxa250_irda_set_speed(dev,si->speed = 9600); } __ECHO_OUT; return 0;}static int pxa250_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data){ int ret; if (!dev->data) return -EINVAL; switch (rqst) { case PM_SUSPEND: ret = pxa250_irda_suspend((struct net_device *)dev->data, (int)data); break; case PM_RESUME: ret = pxa250_irda_resume((struct net_device *)dev->data); break; default: ret = -EINVAL; break; } return ret;}#endifstatic void pxa250_irda_irq(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = dev_id; DBG("irq\n"); pxa250_irda_hpsir_irq(dev); }static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev){ struct pxa250_irda *si = dev->priv; int speed = irda_get_next_speed(skb); int mtt; __ECHO_IN; /* * Does this packet contain a request to change the interface * speed? If so, remember it until we complete the transmission * of this frame. */ if (speed != si->speed && speed != -1) si->newspeed = speed; /* * If this is an empty frame, we can bypass a lot. */ if (skb->len == 0) { if (si->newspeed) { si->newspeed = 0; pxa250_irda_set_speed(dev, speed); } dev_kfree_skb(skb); return 0; } DBG("stop queue\n"); netif_stop_queue(dev); if(!IS_FIR(si)) { DBG("sir tx\n"); si->tx_buff.data = si->tx_buff.head; si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize); pxa250_sir_transmit(dev); dev_kfree_skb(skb); dev->trans_start = jiffies; return 0; } else /* FIR */ { DBG("Enter FIR transmit\n"); /* * We must not be transmitting... */ if (si->txskb) BUG(); disable_irq(si->fir_irq); netif_stop_queue(dev); DBG("queue stoped\n"); si->txskb = skb; /* we could not just map so we'll need some triks */ /* skb->data may be not DMA capable -Sed- */ if (skb->len > TXBUFF_MAX_SIZE) { printk (KERN_ERR "skb data too large\n"); printk (KERN_ERR "len=%d",skb->len); BUG(); } DBG("gonna copy %d bytes to txbuf\n",skb->len); memcpy (si->txbuf_dma_virt, skb->data , skb->len); /* Actual sending ;must not be receiving !!! */ /* Write data and source address */ DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 ); /*Disable receiver and enable transifer */ ICCR0 &= ~ICCR0_RXE; if (ICSR1 & ICSR1_TBY) BUG(); ICCR0 |= ICCR0_TXE; DBG("FICP status %x\n",ICSR0); if (0){ int i; DBG("sending packet\n"); for (i=0;i<skb->len;i++) (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ; DBG(" done\n"); } /* * If we have a mean turn-around time, impose the specified * specified delay. We could shorten this by timing from * the point we received the packet. */ mtt = irda_get_mtt(skb); if(mtt) udelay(mtt); DCSR(si->txdma_ch)=0; DCSR(si->txdma_ch)=DCSR_NODESC; DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */ DTADR(si->txdma_ch) = __PREG(ICDR); DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len; DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -