📄 ep93xx_irda.c
字号:
/* * Function ep93xx_irda_dma_receive_complete(self, size) * * Check for complete frame. Massage as needed and * put it on the stack if it's "good". * */static int ep93xx_irda_dma_receive_complete(struct ep93xx_irda_cb *self, unsigned int frameSize){ struct st_fifo *st_fifo; struct sk_buff *skb; int iDMAh, iBufID, iTotalBytes; EP93XX_DEBUG(2, "%s(), ---------------- Start -----------------\n", __FUNCTION__); /* * Stop DMA. */ SetDMA(self, self->direction, FALSE); st_fifo = &self->st_fifo; iDMAh = self->iDMAh[DMA_MFIR_RX]; if(ep93xx_dma_remove_buffer(iDMAh, &iBufID) == -EINVAL) { EP93XX_DEBUG(1, "DMARx failed to remove buffer?\n"); } if(ep93xx_dma_get_position(iDMAh, &iBufID, &iTotalBytes, 0) == -EINVAL) { /* * This can currently only happen if the handle is bad. */ ERROR("%s(), ********* DMA_GET_POS FAILED *********\n", __FUNCTION__); } /* * Flush the channel. */ ep93xx_dma_flush(iDMAh); if((frameSize > 2047) && (self->speed > 115200)) { /* * By IrDA protocol, this is invalid. */ EP93XX_DEBUG(1, "%s(), *******Rx frame size > 2047!****** \n", __FUNCTION__); self->stats.rx_errors++; self->rx_buff.data += frameSize; return(FALSE); } skb = dev_alloc_skb(frameSize+1); if(skb == NULL) { WARNING("%s(), memory squeeze, dropping frame.\n", __FUNCTION__); self->stats.rx_dropped++; return(FALSE); } /* * Make sure IP header gets aligned */ skb_reserve(skb, 1); /* * HW does not stuff CRC32 into RX buffer. */ skb_put(skb, frameSize); memcpy(skb->data, self->rx_buff.data, frameSize); /* * Move to next frame */ self->rx_buff.data += frameSize; self->stats.rx_bytes += frameSize; self->stats.rx_packets++; skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); netif_rx(skb); //mdelay(5); EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); return(TRUE);}/* * Function ep93xx_irda_net_ioctl(dev, rq, cmd) * * Process IOCTL commands for this device. * */static int ep93xx_irda_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ struct if_irda_req *irq = (struct if_irda_req *) rq; struct ep93xx_irda_cb *self; unsigned long ulFlags; int iRet = 0; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); self = dev->priv; ASSERT(self != NULL, return -1;); EP93XX_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); switch(cmd) { case SIOCSBANDWIDTH: { /* Set bandwidth */ EP93XX_DEBUG(1, "%s(), SIOCSBANDWIDTH\n", __FUNCTION__); /* Root only */ if (!capable(CAP_NET_ADMIN)) { return(-EPERM); } ep93xx_irda_change_speed(self, irq->ifr_baudrate); break; } case SIOCSMEDIABUSY: { /* Set media busy */ EP93XX_DEBUG(2, "%s(), SIOCSMEDIABUSY\n", __FUNCTION__); if (!capable(CAP_NET_ADMIN)) { return(-EPERM); } irda_device_set_media_busy(self->netdev, TRUE); break; } case SIOCGRECEIVING: { /* Check if we are receiving right now */ EP93XX_DEBUG(2, "%s(), SIOCGRECEIVING - %d\n", __FUNCTION__, self->speed); /* Is it really needed ? And what about spinlock ? */ save_flags(ulFlags); cli(); irq->ifr_receiving = ep93xx_irda_is_receiving(self); restore_flags(ulFlags); break; } default: { iRet = -EOPNOTSUPP; } } EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); return(iRet);}/* * Function ep93xx_irda_is_receiving(self) * * Return TRUE is we are currently receiving a frame * */static int ep93xx_irda_is_receiving(struct ep93xx_irda_cb *self){ unsigned long ulFlags; int iStatus = FALSE; EP93XX_DEBUG(2, "%s(), ---------------- Start -----------------\n", __FUNCTION__); ASSERT(self != NULL, return FALSE;); spin_lock_irqsave(&self->lock, ulFlags); if(self->speed > 115200) { EP93XX_DEBUG(1, "%s(), check MFIR.\n", __FUNCTION__); if((inl(IrFlag) & IrFLAG_RXINFRM) != 0) { /* * We are receiving something */ EP93XX_DEBUG(1, "%s(), We are receiving something\n", __FUNCTION__); iStatus = TRUE; } } else { iStatus = (self->rx_buff.state != OUTSIDE_FRAME); } spin_unlock_irqrestore(&self->lock, ulFlags); EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); return(iStatus);}/* * Function ep93xx_irda_net_get_stats(dev) * * Return stats structure. * */static struct net_device_stats *ep93xx_irda_net_get_stats(struct net_device *dev){ struct ep93xx_irda_cb *self = (struct ep93xx_irda_cb *) dev->priv; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); return(&self->stats);}#ifdef POWER_SAVING/* * Function ep93xx_irda_suspend(self) * * Called by the OS to indicate the system * is being suspended for PM. Shut our hardware * down. * */static void ep93xx_irda_suspend(struct ep93xx_irda_cb *self){ EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); MESSAGE("%s, Suspending\n", driver_name); if(self->suspended) { return; } ep93xx_irda_net_close(self->netdev); self->suspended = 1; EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); }/* * Function ep93xx_irda_wakeup(self) * * Called by the OS to indicate a resume from suspend is taking place. * Awaken the hardware. * */static void ep93xx_irda_wakeup(struct ep93xx_irda_cb *self){ EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); if(!self->suspended) { return; } ep93xx_irda_net_open(self->netdev); MESSAGE("%s, Waking up\n", driver_name); self->suspended = 0; EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);}/* * Function ep93xx_irda_pmproc(dev, rqst, data) * * Registered power management callback procedure. * */static int ep93xx_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data){ struct ep93xx_irda_cb *self = (struct ep93xx_irda_cb*) dev->data; EP93XX_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); if(self) { switch(rqst) { case PM_SUSPEND: { ep93xx_irda_suspend(self); break; } case PM_RESUME: { ep93xx_irda_wakeup(self); break; } } } EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); return(0);}#endif/* * Function SetInterrupts * * Sets interrupts on/off based on speed and boolean. * A boolean value of TRUE turns on interrupts for * the hardware that manages that IR speed. FALSE turns them off. * */static void SetInterrupts(struct ep93xx_irda_cb *self, unsigned char enable){ unsigned char ucRegVal = 0, ucRegMask = 0; unsigned long ulRegAddr, ulRegAddr2; EP93XX_DEBUG(2, "%s(), ----------- Start -----------\n", __FUNCTION__); EP93XX_DEBUG(2, "%s(), IRQs enable = %d, speed = %d\n", __FUNCTION__, enable, self->speed); if(self->speed <= 115200) { /* Action on IRQs in SIR mode */ ulRegAddr = UART2CR; ucRegVal = inl(ulRegAddr); if(self->direction & DIR_TX) { ucRegMask |= U2CR_TxIrq; } if(self->direction & DIR_RX) { ucRegMask |= U2CR_RxIrq; } if(enable) { ucRegVal &= (char)~(U2CR_RxIrq|U2CR_TxIrq); ucRegVal |= (char)(ucRegMask); } else { ucRegVal &= (char)~(ucRegMask); } } else { ucRegMask = 0; if(self->speed <= 1152000) { /* * Action on IRQs in MIR mode */ ulRegAddr = MIMR; ulRegAddr2 = MISR; } else { /* * Action on IRQs in FIR mode */ ulRegAddr = FIMR; ulRegAddr2 = FISR; } if(self->direction & DIR_TX) { ucRegMask |= (MFIMR_TXABORT|MFIMR_TXFC); } if(self->direction & DIR_RX) { ucRegMask |= (MFIMR_RXFL|MFIMR_RXFC); } /* * Bit mask is the same for MIR/FIR. */ if(enable) { ucRegVal |= (char)(ucRegMask); /* * Clear sticky bits before turning on IRQs */ outl(MFISR_TXFC|MFISR_TXFABORT|MFISR_RXIL|MFISR_RXFL, ulRegAddr2); inl(ulRegAddr2); inl(IrRIB); } else { /* * M/FIR IRQ registers only have IRQ related bits, safe * to blast them therefore. */ ucRegVal = 0; } } outl(ucRegVal, ulRegAddr); EP93XX_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__); }static void SetIR_Transmit(unsigned char ucEnable){ unsigned long ulRegVal; ulRegVal = inb(IrCtrl); if(ucEnable) { if(ulRegVal & IrCONTROL_TXON) { return; } else { outb(ulRegVal|IrCONTROL_TXON, IrCtrl); } } else { if(!(ulRegVal & IrCONTROL_TXON)) { return; } else { outb(ulRegVal&~(IrCONTROL_TXON), IrCtrl); } }}/* * Function SetIR_Receive() * * Enables OR Disables RX & RXRP in IrCtrl based on * supplied boolean. */static voidSetIR_Receive(unsigned char ucEnable){ unsigned long ulRegVal; ulRegVal = inb(IrCtrl); if(ucEnable) { if((ulRegVal & (IrCONTROL_RXON|IrCONTROL_RXRP)) == (IrCONTROL_RXON|IrCONTROL_RXRP)) { return; } else { outb(ulRegVal|IrCONTROL_RXON|IrCONTROL_RXRP, IrCtrl); } } else { if(!(ulRegVal & (IrCONTROL_RXON & IrCONTROL_RXRP))) { return; } else { outb(ulRegVal&~(IrCONTROL_RXON|IrCONTROL_RXRP), IrCtrl); } }}/* * Function SetDMA() * * Enables or disables DMA capability for current speed. * 'enable' parameter determines action. Direction * determines tx and/or rx DMA. * */static voidSetDMA(struct ep93xx_irda_cb *self, unsigned char direction, unsigned char enable){ int iRegVal, iDMARegVal; if(self->speed <= 115200) { /* * SIR section. No DMA for SIR at this time. */ if(direction == DIR_RX) { } else { } } else { /* * MFIR Section */ /* * Read in current value. */ iRegVal = iDMARegVal = inb(IrDMACR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -