📄 donauboe.c
字号:
self->txs %= TX_SLOTS; toshoboe_dumptx (self); /* Turn on TX and RX and loopback */ toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); i = 0; n = fir ? 1 : 4; while (toshoboe_numvalidrcvs (self) != n) { if (i > 4800) return toshoboe_probefail (self, "filter test"); udelay ((9600*(TT_LEN+16))/self->speed); i++; } n = fir ? 203 : 102; while ((toshoboe_numrcvs(self) != self->int_rx) || (self->int_tx != n)) { if (i > 4800) return toshoboe_probefail (self, "interrupt test"); udelay ((9600*(TT_LEN+16))/self->speed); i++; } toshoboe_dumprx (self,i); } /* test 2: SIR in char at a time */ toshoboe_stopchip (self); self->int_rx = self->int_tx = 0; spin_lock_irqsave(&self->spinlock, flags); toshoboe_startchip (self); spin_unlock_irqrestore(&self->spinlock, flags); self->async = 1; self->speed = 115200; toshoboe_setbaud (self); self->ring->tx[self->txs].control = OBOE_CTL_TX_RTCENTX | OBOE_CTL_TX_HW_OWNS; self->ring->tx[self->txs].len = 4; ((unsigned char *) self->tx_bufs[self->txs])[0] = 'f'; ((unsigned char *) self->tx_bufs[self->txs])[1] = 'i'; ((unsigned char *) self->tx_bufs[self->txs])[2] = 's'; ((unsigned char *) self->tx_bufs[self->txs])[3] = 'h'; toshoboe_dumptx (self); toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); i = 0; while (toshoboe_numvalidrcvs (self) != 4) { if (i > 100) return toshoboe_probefail (self, "Async test"); udelay (100); i++; } while ((toshoboe_numrcvs (self) != self->int_rx) || (self->int_tx != 1)) { if (i > 100) return toshoboe_probefail (self, "Async interrupt test"); udelay (100); i++; } toshoboe_dumprx (self,i); self->async = 0; self->speed = 9600; toshoboe_setbaud (self); toshoboe_stopchip (self); free_irq (self->io.irq, (void *) self); printk (KERN_WARNING DRIVER_NAME ": Self test passed ok\n"); return 1;}#endif/******************************************************************//* Netdev style code *//* Transmit something */static inttoshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev){ struct toshoboe_cb *self; __s32 speed; int mtt, len, ctl; unsigned long flags; struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb; self = (struct toshoboe_cb *) dev->priv; IRDA_ASSERT (self != NULL, return 0; ); IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __FUNCTION__ ,skb->len,self->txpending,INB (OBOE_ENABLEH)); if (!cb->magic) { IRDA_DEBUG (2, "%s.Not IrLAP:%x\n", __FUNCTION__, cb->magic);#ifdef DUMP_PACKETS _dumpbufs(skb->data,skb->len,'>');#endif } /* change speed pending, wait for its execution */ if (self->new_speed) return -EBUSY; /* device stopped (apm) wait for restart */ if (self->stopped) return -EBUSY; toshoboe_checkstuck (self); dev->trans_start = jiffies; /* Check if we need to change the speed */ /* But not now. Wait after transmission if mtt not required */ speed=irda_get_next_speed(skb); if ((speed != self->io.speed) && (speed != -1)) { spin_lock_irqsave(&self->spinlock, flags); if (self->txpending || skb->len) { self->new_speed = speed; IRDA_DEBUG (1, "%s: Queued TxDone scheduled speed change %d\n" , __FUNCTION__, speed); /* if no data, that's all! */ if (!skb->len) { spin_unlock_irqrestore(&self->spinlock, flags); dev_kfree_skb (skb); return 0; } /* True packet, go on, but */ /* do not accept anything before change speed execution */ netif_stop_queue(dev); /* ready to process TxDone interrupt */ spin_unlock_irqrestore(&self->spinlock, flags); } else { /* idle and no data, change speed now */ self->speed = speed; toshoboe_setbaud (self); spin_unlock_irqrestore(&self->spinlock, flags); dev_kfree_skb (skb); return 0; } } if ((mtt = irda_get_mtt(skb))) { /* This is fair since the queue should be empty anyway */ spin_lock_irqsave(&self->spinlock, flags); if (self->txpending) { spin_unlock_irqrestore(&self->spinlock, flags); return -EBUSY; } /* If in SIR mode we need to generate a string of XBOFs */ /* In MIR and FIR we need to generate a string of data */ /* which we will add a wrong checksum to */ mtt = toshoboe_makemttpacket (self, self->tx_bufs[self->txs], mtt); IRDA_DEBUG (1, "%s.mtt:%x(%x)%d\n", __FUNCTION__ ,skb->len,mtt,self->txpending); if (mtt) { self->ring->tx[self->txs].len = mtt & 0xfff; ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX; if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON) { ctl |= OBOE_CTL_TX_BAD_CRC | OBOE_CTL_TX_SIP ; }#ifdef USE_MIR else if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_MIRON) { ctl |= OBOE_CTL_TX_BAD_CRC; }#endif self->ring->tx[self->txs].control = ctl; OUTB (0x0, OBOE_ENABLEH); /* It is only a timer. Do not send mtt packet outside! */ toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); self->txpending++; self->txs++; self->txs %= TX_SLOTS; } else { printk(KERN_ERR DRIVER_NAME ": problem with mtt packet - ignored\n"); } spin_unlock_irqrestore(&self->spinlock, flags); }#ifdef DUMP_PACKETSdumpbufs(skb->data,skb->len,'>');#endif spin_lock_irqsave(&self->spinlock, flags); if (self->ring->tx[self->txs].control & OBOE_CTL_TX_HW_OWNS) { IRDA_DEBUG (0, "%s.ful:%x(%x)%x\n", __FUNCTION__ ,skb->len, self->ring->tx[self->txs].control, self->txpending); toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); spin_unlock_irqrestore(&self->spinlock, flags); return -EBUSY; } if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON) { len = async_wrap_skb (skb, self->tx_bufs[self->txs], TX_BUF_SZ); } else { len = skb->len; memcpy (self->tx_bufs[self->txs], skb->data, len); } self->ring->tx[self->txs].len = len & 0x0fff; /*Sometimes the HW doesn't see us assert RTCENTX in the interrupt code */ /*later this plays safe, we garuntee the last packet to be transmitted */ /*has RTCENTX set */ ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX; if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON) { ctl |= OBOE_CTL_TX_SIP ; } self->ring->tx[self->txs].control = ctl; /* If transmitter is idle start in one-shot mode */ if (!self->txpending) toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); self->txpending++; self->txs++; self->txs %= TX_SLOTS; spin_unlock_irqrestore(&self->spinlock, flags); dev_kfree_skb (skb); return 0;}/*interrupt handler */static irqreturn_ttoshoboe_interrupt (int irq, void *dev_id){ struct toshoboe_cb *self = dev_id; __u8 irqstat; struct sk_buff *skb = NULL; irqstat = INB (OBOE_ISR);/* was it us */ if (!(irqstat & OBOE_INT_MASK)) return IRQ_NONE;/* Ack all the interrupts */ OUTB (irqstat, OBOE_ISR); toshoboe_isntstuck (self);/* Txdone */ if (irqstat & OBOE_INT_TXDONE) { int txp, txpc; int i; txp = self->txpending; self->txpending = 0; for (i = 0; i < TX_SLOTS; ++i) { if (self->ring->tx[i].control & OBOE_CTL_TX_HW_OWNS) self->txpending++; } IRDA_DEBUG (1, "%s.txd(%x)%x/%x\n", __FUNCTION__ ,irqstat,txp,self->txpending); txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK; /* Got anything queued ? start it together */ if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS) { txpc = txp;#ifdef OPTIMIZE_TX while (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS) { txp = txpc; txpc++; txpc %= TX_SLOTS; self->stats.tx_packets++; if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS) self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX; } self->stats.tx_packets--;#else self->stats.tx_packets++;#endif toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); } if ((!self->txpending) && (self->new_speed)) { self->speed = self->new_speed; IRDA_DEBUG (1, "%s: Executed TxDone scheduled speed change %d\n", __FUNCTION__, self->speed); toshoboe_setbaud (self); } /* Tell network layer that we want more frames */ if (!self->new_speed) netif_wake_queue(self->netdev); } if (irqstat & OBOE_INT_RXDONE) { while (!(self->ring->rx[self->rxs].control & OBOE_CTL_RX_HW_OWNS)) { int len = self->ring->rx[self->rxs].len; skb = NULL; IRDA_DEBUG (3, "%s.rcv:%x(%x)\n", __FUNCTION__ ,len,self->ring->rx[self->rxs].control);#ifdef DUMP_PACKETSdumpbufs(self->rx_bufs[self->rxs],len,'<');#endif if (self->ring->rx[self->rxs].control == 0) { __u8 enable = INB (OBOE_ENABLEH); /* In SIR mode we need to check the CRC as this */ /* hasn't been done by the hardware */ if (enable & OBOE_ENABLEH_SIRON) { if (!toshoboe_checkfcs (self->rx_bufs[self->rxs], len)) len = 0; /*Trim off the CRC */ if (len > 1) len -= 2; else len = 0; IRDA_DEBUG (1, "%s.SIR:%x(%x)\n", __FUNCTION__, len,enable); }#ifdef USE_MIR else if (enable & OBOE_ENABLEH_MIRON) { if (len > 1) len -= 2; else len = 0; IRDA_DEBUG (2, "%s.MIR:%x(%x)\n", __FUNCTION__, len,enable); }#endif else if (enable & OBOE_ENABLEH_FIRON) { if (len > 3) len -= 4; /*FIXME: check this */ else len = 0; IRDA_DEBUG (1, "%s.FIR:%x(%x)\n", __FUNCTION__, len,enable); } else IRDA_DEBUG (0, "%s.?IR:%x(%x)\n", __FUNCTION__, len,enable); if (len) { skb = dev_alloc_skb (len + 1); if (skb) { skb_reserve (skb, 1); skb_put (skb, len); memcpy (skb->data, self->rx_bufs[self->rxs], len); self->stats.rx_packets++; skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons (ETH_P_IRDA); } else { printk (KERN_INFO "%s(), memory squeeze, dropping frame.\n", __FUNCTION__); } } } else { /* TODO: =========================================== */ /* if OBOE_CTL_RX_LENGTH, our buffers are too small */ /* (MIR or FIR) data is lost. */ /* (SIR) data is splitted in several slots. */ /* we have to join all the received buffers received */ /*in a large buffer before checking CRC. */ IRDA_DEBUG (0, "%s.err:%x(%x)\n", __FUNCTION__ ,len,self->ring->rx[self->rxs].control); } self->ring->rx[self->rxs].len = 0x0; self->ring->rx[self->rxs].control = OBOE_CTL_RX_HW_OWNS; self->rxs++; self->rxs %= RX_SLOTS; if (skb) netif_rx (skb); } } if (irqstat & OBOE_INT_TXUNDER) { printk (KERN_WARNING DRIVER_NAME ": tx fifo underflow\n"); } if (irqstat & OBOE_INT_RXOVER) { printk (KERN_WARNING DRIVER_NAME ": rx fifo overflow\n"); }/* This must be useful for something... */ if (irqstat & OBOE_INT_SIP) { self->int_sip++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -