📄 via-ircc.c
字号:
(KERN_INFO "recv_comple:fifo.len=%x,len=%x,CurCount=%x..\n", st_fifo->len, len - 4, RxCurCount(iobase, self)));#endif st_fifo->entries[st_fifo->tail].status = status; st_fifo->entries[st_fifo->tail].len = len; st_fifo->pending_bytes += len; st_fifo->tail++; st_fifo->len++; if (st_fifo->tail > MAX_RX_WINDOW) st_fifo->tail = 0; self->RxDataReady = 0; // It maybe have MAX_RX_WINDOW package receive by // receive_complete before Timer IRQ/* F01_S if (st_fifo->len < (MAX_RX_WINDOW+2 )) { RXStart(iobase,ON); SetTimer(iobase,4); } else { F01_E */ EnableRX(iobase, OFF); EnRXDMA(iobase, OFF); RXStart(iobase, OFF);//F01_S // Put this entry back in fifo if (st_fifo->head > MAX_RX_WINDOW) st_fifo->head = 0; status = st_fifo->entries[st_fifo->head].status; len = st_fifo->entries[st_fifo->head].len; st_fifo->head++; st_fifo->len--; /* * if frame size or data ptr are wrong ,then get next * entry. */ if ((self->rx_buff.data == NULL) || (len < 6)) { self->stats.rx_dropped++; return TRUE; } skb = dev_alloc_skb(len + 1 - 4); if (!skb) { self->stats.rx_dropped++; return TRUE; } skb_reserve(skb, 1); skb_put(skb, len - 4); memcpy(skb->data, self->rx_buff.data, len - 4);#ifdef DBGMSG DBG(printk (KERN_INFO "RxT:len=%x.rx_buff=%x\n", len - 4, self->rx_buff.data));/* for(i=0 ; i < (len-4) ; i++) { DBG(printk(KERN_INFO "%x..\n",self->rx_buff.data[i])); }*/#endif // Move to next frame self->rx_buff.data += len; self->stats.rx_bytes += len; self->stats.rx_packets++; skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); netif_rx(skb);//F01_E } //FIR return TRUE;}/* * if frame is received , but no INT ,then use this routine to upload frame. */static int upload_rxdata(struct via_ircc_cb *self, int iobase){ struct sk_buff *skb; int len; struct st_fifo *st_fifo; st_fifo = &self->st_fifo; len = GetRecvByte(iobase, self);#ifdef DBGMSG DBG(printk(KERN_INFO "upload_rxdata: len=%x\n", len));#endif if ((len - 4) < 2) { self->stats.rx_dropped++; return FALSE; } skb = dev_alloc_skb(len + 1); if (!skb) { self->stats.rx_dropped++; return FALSE; } skb_reserve(skb, 1); skb_put(skb, len - 4 + 1); memcpy(skb->data, self->rx_buff.data, len - 4 + 1); st_fifo->tail++; st_fifo->len++; if (st_fifo->tail > MAX_RX_WINDOW) st_fifo->tail = 0; // Move to next frame self->rx_buff.data += len; self->stats.rx_bytes += len; self->stats.rx_packets++; skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); netif_rx(skb); if (st_fifo->len < (MAX_RX_WINDOW + 2)) { RXStart(iobase, ON); } else { EnableRX(iobase, OFF); EnRXDMA(iobase, OFF); RXStart(iobase, OFF); } return TRUE;}/* * Implement back to back receive , use this routine to upload data. */static int RxTimerHandler(struct via_ircc_cb *self, int iobase){ struct st_fifo *st_fifo; struct sk_buff *skb; int len; u8 status; st_fifo = &self->st_fifo; if (CkRxRecv(iobase, self)) { // if still receiving ,then return ,don't upload frame self->RetryCount = 0; SetTimer(iobase, 20); self->RxDataReady++; return FALSE; } else self->RetryCount++; if ((self->RetryCount >= 1) || ((st_fifo->pending_bytes + 2048) > self->rx_buff.truesize) || (st_fifo->len >= (MAX_RX_WINDOW))) { while (st_fifo->len > 0) { //upload frame // Put this entry back in fifo if (st_fifo->head > MAX_RX_WINDOW) st_fifo->head = 0; status = st_fifo->entries[st_fifo->head].status; len = st_fifo->entries[st_fifo->head].len; st_fifo->head++; st_fifo->len--; /* * if frame size or data ptr are wrong, * then get next entry. */ if ((self->rx_buff.data == NULL) || (len < 6)) { self->stats.rx_dropped++; continue; } skb = dev_alloc_skb(len + 1 - 4); if (!skb) { self->stats.rx_dropped++; continue; } skb_reserve(skb, 1); skb_put(skb, len - 4); memcpy(skb->data, self->rx_buff.data, len - 4);#ifdef DBGMSG DBG(printk (KERN_INFO "RxT:len=%x.head=%x\n", len - 4, st_fifo->head));#endif // Move to next frame self->rx_buff.data += len; self->stats.rx_bytes += len; self->stats.rx_packets++; skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); netif_rx(skb); } //while self->RetryCount = 0;#ifdef DBGMSG DBG(printk (KERN_INFO "RxT:End of upload HostStatus=%x,RxStatus=%x\n", GetHostStatus(iobase), GetRXStatus(iobase)));#endif /* * if frame is receive complete at this routine ,then upload * frame. */ if ((GetRXStatus(iobase) & 0x10) && (RxCurCount(iobase, self) != self->RxLastCount)) { upload_rxdata(self, iobase); if (irda_device_txqueue_empty(self->netdev)) via_ircc_dma_receive(self); } } // timer detect complete else SetTimer(iobase, 4); return TRUE;}/* * Function via_ircc_interrupt (irq, dev_id, regs) * * An interrupt from the chip has arrived. Time to do some work * */static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *) dev_id; struct via_ircc_cb *self; int iobase; u8 iHostIntType, iRxIntType, iTxIntType; if (!dev) { WARNING("%s: irq %d for unknown device.\n", driver_name, irq); return IRQ_NONE; } self = (struct via_ircc_cb *) dev->priv; iobase = self->io.fir_base; spin_lock(&self->lock); iHostIntType = GetHostStatus(iobase); if ((iHostIntType & 0x40) != 0) { //Timer Event self->EventFlag.TimeOut++; ClearTimerInt(iobase, 1); if (self->io.direction == IO_XMIT) { via_ircc_dma_xmit(self, iobase); } if (self->io.direction == IO_RECV) { /* * frame ready hold too long, must reset. */ if (self->RxDataReady > 30) { hwreset(self); if (irda_device_txqueue_empty (self->netdev)) { via_ircc_dma_receive(self); } } else { // call this to upload frame. RxTimerHandler(self, iobase); } } //RECV } //Timer Event if ((iHostIntType & 0x20) != 0) { //Tx Event iTxIntType = GetTXStatus(iobase); if (iTxIntType & 0x4) { self->EventFlag.EOMessage++; // read and will auto clean if (via_ircc_dma_xmit_complete(self)) { if (irda_device_txqueue_empty (self->netdev)) { via_ircc_dma_receive(self); } } else { self->EventFlag.Unknown++; } } //EOP } //Tx Event //---------------------------------------- if ((iHostIntType & 0x10) != 0) { //Rx Event /* Check if DMA has finished */ iRxIntType = GetRXStatus(iobase);#ifdef DBGMSG if (!iRxIntType) DBG(printk(KERN_INFO " RxIRQ =0\n"));#endif if (iRxIntType & 0x10) { if (via_ircc_dma_receive_complete(self, iobase)) {//F01 if(!(IsFIROn(iobase))) via_ircc_dma_receive(self); via_ircc_dma_receive(self); } } // No ERR else { //ERR#ifdef DBGMSG DBG(printk (KERN_INFO " RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n", iRxIntType, iHostIntType, RxCurCount(iobase, self), self->RxLastCount));#endif if (iRxIntType & 0x20) { //FIFO OverRun ERR ResetChip(iobase, 0); ResetChip(iobase, 1); } else { //PHY,CRC ERR if (iRxIntType != 0x08) hwreset(self); //F01 } via_ircc_dma_receive(self); } //ERR } //Rx Event spin_unlock(&self->lock); return IRQ_HANDLED;}void hwreset(struct via_ircc_cb *self){ int iobase; iobase = self->io.fir_base;#ifdef DBGMSG DBG(printk(KERN_INFO "hwreset ....\n"));#endif ResetChip(iobase, 5); EnableDMA(iobase, OFF); EnableTX(iobase, OFF); EnableRX(iobase, OFF); EnRXDMA(iobase, OFF); EnTXDMA(iobase, OFF); RXStart(iobase, OFF); TXStart(iobase, OFF); InitCard(iobase); CommonInit(iobase); SIRFilter(iobase, ON); SetSIR(iobase, ON); CRC16(iobase, ON); EnTXCRC(iobase, 0); WriteReg(iobase, I_ST_CT_0, 0x00); SetBaudRate(iobase, 9600); SetPulseWidth(iobase, 12); SetSendPreambleCount(iobase, 0); WriteReg(iobase, I_ST_CT_0, 0x80); via_ircc_change_speed(self, self->io.speed); self->st_fifo.len = 0;}/* * Function via_ircc_is_receiving (self) * * Return TRUE is we are currently receiving a frame * */static int via_ircc_is_receiving(struct via_ircc_cb *self){ int status = FALSE; int iobase; ASSERT(self != NULL, return FALSE;); iobase = self->io.fir_base; if (CkRxRecv(iobase, self)) status = TRUE;#ifdef DBGMSG DBG(printk(KERN_INFO "is_receiving status=%x....\n", status));#endif return status;}/* * Function via_ircc_net_init (dev) * * Initialize network device * */static int via_ircc_net_init(struct net_device *dev){ IRDA_DEBUG(4, "%s()\n", __FUNCTION__); /* Keep track of module usage */ SET_MODULE_OWNER(dev); /* Setup to be a normal IrDA network device driver */ irda_device_setup(dev); /* Insert overrides below this line! */ return 0;}/* * Function via_ircc_net_open (dev) * * Start the device * */static int via_ircc_net_open(struct net_device *dev){ struct via_ircc_cb *self; int iobase; char hwname[32]; IRDA_DEBUG(4, "%s()\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); self = (struct via_ircc_cb *) dev->priv; self->stats.rx_packets = 0; ASSERT(self != NULL, return 0;); iobase = self->io.fir_base; if (request_irq (self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) { WARNING("%s, unable to allocate irq=%d\n", driver_name, self->io.irq); return -EAGAIN; } /* * Always allocate the DMA channel after the IRQ, and clean up on * failure. */ if (request_dma(self->io.dma, dev->name)) { WARNING("%s, unable to allocate dma=%d\n", driver_name, self->io.dma); free_irq(self->io.irq, self); return -EAGAIN; } if (self->io.dma2 != self->io.dma) { if (request_dma(self->io.dma2, dev->name)) { WARNING("%s, unable to allocate dma2=%d\n", driver_name, self->io.dma2); free_irq(self->io.irq, self); return -EAGAIN; } } /* turn on interrupts */ EnAllInt(iobase, ON); EnInternalLoop(iobase, OFF); EnExternalLoop(iobase, OFF); /* Ready to play! */ netif_start_queue(dev); /* * Open new IrLAP layer instance, now that everything should be * initialized properly */ sprintf(hwname, "VIA"); /* * for different kernel ,irlap_open have different parameter. */ self->irlap = irlap_open(dev, &self->qos, hwname);// self->irlap = irlap_open(dev, &self->qos); self->RxLastCount = 0; return 0;}/* * Function via_ircc_net_close (dev) * * Stop the device * */static int via_ircc_net_close(struct net_device *dev){ struct via_ircc_cb *self; int iobase; IRDA_DEBUG(4, "%s()\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); self = (struct via_ircc_cb *) dev->priv; ASSERT(self != NULL, return 0;);#ifdef DBG_IO outb(0xff, 0x90); outb(0xff, 0x94);#endif /* Stop device */ netif_stop_queue(dev); /* Stop and remove instance of IrLAP */ if (self->irlap) irlap_close(self->irlap); self->irlap = NULL; iobase = self->io.fir_base; EnTXDMA(iobase, OFF); EnRXDMA(iobase, OFF); DisableDmaChannel(self->io.dma); /* Disable interrupts */ EnAllInt(iobase, OFF); free_irq(self->io.irq, dev); free_dma(self->io.dma); return 0;}/* * Function via_ircc_net_ioctl (dev, rq, cmd) * * Process IOCTL commands for this device * */static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ struct if_irda_req *irq = (struct if_irda_req *) rq; struct via_ircc_cb *self; unsigned long flags; int ret = 0; ASSERT(dev != NULL, return -1;); self = dev->priv; ASSERT(self != NULL, return -1;); IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); /* Disable interrupts & save flags */ spin_lock_irqsave(&self->lock, flags); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; goto out; } via_ircc_change_speed(self, irq->ifr_baudrate); break; case SIOCSMEDIABUSY: /* Set media busy */ if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; goto out; } irda_device_set_media_busy(self->netdev, TRUE); break; case SIOCGRECEIVING: /* Check if we are receiving right now */ irq->ifr_receiving = via_ircc_is_receiving(self); break; default: ret = -EOPNOTSUPP; } out: spin_unlock_irqrestore(&self->lock, flags); return ret;}static struct net_device_stats *via_ircc_net_get_stats(struct net_device *dev){ struct via_ircc_cb *self = (struct via_ircc_cb *) dev->priv; return &self->stats;}MODULE_AUTHOR("VIA Technologies,inc");MODULE_DESCRIPTION("VIA IrDA Device Driver");MODULE_LICENSE("GPL");module_init(via_ircc_init);module_exit(via_ircc_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -