📄 via-ircc.c
字号:
case 0x01: /* Differential serial interface */ break; case 0x02: /* same as */ case 0x03: /* Reserved */ break; case 0x04: /* Sharp RY5HD01 */ break; case 0x05: /* Reserved, but this is what the Thinkpad reports */ break; case 0x06: /* Single-ended serial interface */ break; case 0x07: /* Consumer-IR only */ break; case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ UseOneRX(iobase, ON); // use one RX pin RX1,RX2 InvertTX(iobase, OFF); InvertRX(iobase, OFF); EnRX2(iobase, ON); //sir to rx2 EnGPIOtoRX2(iobase, OFF); if (IsSIROn(iobase)) { //sir // Mode select Off SlowIRRXLowActive(iobase, ON); udelay(1000); SlowIRRXLowActive(iobase, OFF); } else { if (IsMIROn(iobase)) { //mir // Mode select On SlowIRRXLowActive(iobase, OFF); udelay(20); } else { // fir if (IsFIROn(iobase)) { //fir // Mode select On SlowIRRXLowActive(iobase, OFF); udelay(20); } } } break; case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ UseOneRX(iobase, ON); //use ONE RX....RX1 InvertTX(iobase, OFF); InvertRX(iobase, OFF); // invert RX pin EnRX2(iobase, ON); EnGPIOtoRX2(iobase, OFF); if (IsSIROn(iobase)) { //sir // Mode select On SlowIRRXLowActive(iobase, ON); udelay(20); // Mode select Off SlowIRRXLowActive(iobase, OFF); } if (IsMIROn(iobase)) { //mir // Mode select On SlowIRRXLowActive(iobase, OFF); udelay(20); // Mode select Off SlowIRRXLowActive(iobase, ON); } else { // fir if (IsFIROn(iobase)) { //fir // Mode select On SlowIRRXLowActive(iobase, OFF); // TX On WriteTX(iobase, ON); udelay(20); // Mode select OFF SlowIRRXLowActive(iobase, ON); udelay(20); // TX Off WriteTX(iobase, OFF); } } break; case 0x0d: UseOneRX(iobase, OFF); // use two RX pin RX1,RX2 InvertTX(iobase, OFF); InvertRX(iobase, OFF); SlowIRRXLowActive(iobase, OFF); if (IsSIROn(iobase)) { //sir EnGPIOtoRX2(iobase, OFF); WriteGIO(iobase, OFF); EnRX2(iobase, OFF); //sir to rx2 } else { // fir mir EnGPIOtoRX2(iobase, OFF); WriteGIO(iobase, OFF); EnRX2(iobase, OFF); //fir to rx } break; case 0x0ff: /* Vishay */ if (IsSIROn(iobase)) mode = 0; else if (IsMIROn(iobase)) mode = 1; else if (IsFIROn(iobase)) mode = 2; else if (IsVFIROn(iobase)) mode = 5; //VFIR-16 SI_SetMode(iobase, mode); } WriteReg(iobase, I_ST_CT_0, 0x80);}/* * Function via_ircc_change_speed (self, baud) * * Change the speed of the device * */static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed){ struct net_device *dev = self->netdev; u16 iobase; u8 value = 0, bTmp; iobase = self->io.fir_base; /* Update accounting for new speed */ self->io.speed = speed;#ifdef DBGMSG DBG(printk(KERN_INFO "change_speed =%x......\n", speed));#endif#ifdef DBG_IO if (self->io.speed > 0x2580) outb(0xaa, 0x90); else outb(0xbb, 0x90);#endif /* Controller mode sellection */ switch (speed) { case 9600: value = 11; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 19200: value = 5; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 38400: value = 2; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 57600: value = 1; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 115200: value = 0; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 576000: value = 0; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 1152000: value = 0; SetMIR(iobase, ON); break; case 4000000: value = 0; SetFIR(iobase, ON); SetPulseWidth(iobase, 0); SetSendPreambleCount(iobase, 14); CRC16(iobase, OFF); EnTXCRC(iobase, ON); break; case 16000000: value = 0; SetVFIR(iobase, ON); break; default: value = 0; break; } /* Set baudrate to 0x19[2..7] */ bTmp = (ReadReg(iobase, I_CF_H_1) & 0x03); bTmp = bTmp | (value << 2); WriteReg(iobase, I_CF_H_1, bTmp); via_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id);// EnTXFIFOHalfLevelInt(iobase,ON); /* Set FIFO size to 64 */ SetFIFO(iobase, 64); /* Enable some interrupts so we can receive frames */ //EnAllInt(iobase,ON); if (IsSIROn(iobase)) { SIRFilter(iobase, ON); SIRRecvAny(iobase, ON); } else { SIRFilter(iobase, OFF); SIRRecvAny(iobase, OFF); } if (speed > 115200) { /* Install FIR xmit handler */ dev->hard_start_xmit = via_ircc_hard_xmit_fir; via_ircc_dma_receive(self); } else { /* Install SIR xmit handler */ dev->hard_start_xmit = via_ircc_hard_xmit_sir; } netif_wake_queue(dev);}/* * Function via_ircc_hard_xmit (skb, dev) * * Transmit the frame! * */static int via_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev){ struct via_ircc_cb *self; unsigned long flags; u16 iobase; __u32 speed; self = (struct via_ircc_cb *) dev->priv; ASSERT(self != NULL, return 0;); iobase = self->io.fir_base; netif_stop_queue(dev); /* Check if we need to change the speed */ speed = irda_get_next_speed(skb); if ((speed != self->io.speed) && (speed != -1)) { /* Check for empty frame */ if (!skb->len) { via_ircc_change_speed(self, speed); dev->trans_start = jiffies; dev_kfree_skb(skb); return 0; } else self->new_speed = speed; } InitCard(iobase); CommonInit(iobase); SIRFilter(iobase, ON); SetSIR(iobase, ON); CRC16(iobase, ON); EnTXCRC(iobase, 0); WriteReg(iobase, I_ST_CT_0, 0x00); spin_lock_irqsave(&self->lock, flags); self->tx_buff.data = self->tx_buff.head; self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, self->tx_buff.truesize); self->stats.tx_bytes += self->tx_buff.len; SetBaudRate(iobase, speed); SetPulseWidth(iobase, 12); SetSendPreambleCount(iobase, 0); WriteReg(iobase, I_ST_CT_0, 0x80); EnableTX(iobase, ON); EnableRX(iobase, OFF); ResetChip(iobase, 0); ResetChip(iobase, 1); ResetChip(iobase, 2); ResetChip(iobase, 3); ResetChip(iobase, 4); EnAllInt(iobase, ON); EnTXDMA(iobase, ON); EnRXDMA(iobase, OFF); setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, DMA_TX_MODE); SetSendByte(iobase, self->tx_buff.len); RXStart(iobase, OFF); TXStart(iobase, ON); dev->trans_start = jiffies; spin_unlock_irqrestore(&self->lock, flags); dev_kfree_skb(skb); return 0;}static int via_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev){ struct via_ircc_cb *self; u16 iobase; __u32 speed; unsigned long flags; self = (struct via_ircc_cb *) dev->priv; iobase = self->io.fir_base; if (self->st_fifo.len) return 0; if (self->chip_id == 0x3076) iodelay(1500); else udelay(1500); netif_stop_queue(dev); speed = irda_get_next_speed(skb); if ((speed != self->io.speed) && (speed != -1)) { if (!skb->len) { via_ircc_change_speed(self, speed); dev->trans_start = jiffies; dev_kfree_skb(skb); return 0; } else self->new_speed = speed; } spin_lock_irqsave(&self->lock, flags); self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail; self->tx_fifo.queue[self->tx_fifo.free].len = skb->len; self->tx_fifo.tail += skb->len; self->stats.tx_bytes += skb->len; memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data, skb->len); self->tx_fifo.len++; self->tx_fifo.free++;//F01 if (self->tx_fifo.len == 1) { via_ircc_dma_xmit(self, iobase);//F01 }//F01 if (self->tx_fifo.free < (MAX_TX_WINDOW -1 )) netif_wake_queue(self->netdev); dev->trans_start = jiffies; dev_kfree_skb(skb); spin_unlock_irqrestore(&self->lock, flags); return 0;}static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase){// int i;// u8 *ch; EnTXDMA(iobase, OFF); self->io.direction = IO_XMIT; EnPhys(iobase, ON); EnableTX(iobase, ON); EnableRX(iobase, OFF); ResetChip(iobase, 0); ResetChip(iobase, 1); ResetChip(iobase, 2); ResetChip(iobase, 3); ResetChip(iobase, 4); EnAllInt(iobase, ON); EnTXDMA(iobase, ON); EnRXDMA(iobase, OFF); setup_dma(self->io.dma, self->tx_fifo.queue[self->tx_fifo.ptr].start, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE);#ifdef DBGMSG DBG(printk (KERN_INFO "dma_xmit:tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", self->tx_fifo.ptr, self->tx_fifo.queue[self->tx_fifo.ptr].len, self->tx_fifo.len));/* ch = self->tx_fifo.queue[self->tx_fifo.ptr].start; for(i=0 ; i < self->tx_fifo.queue[self->tx_fifo.ptr].len ; i++) { DBG(printk(KERN_INFO "%x..\n",ch[i])); }*/#endif SetSendByte(iobase, self->tx_fifo.queue[self->tx_fifo.ptr].len); RXStart(iobase, OFF); TXStart(iobase, ON); return 0;}/* * Function via_ircc_dma_xmit_complete (self) * * The transfer of a frame in finished. This function will only be called * by the interrupt handler * */static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self){ int iobase; int ret = TRUE; u8 Tx_status; IRDA_DEBUG(2, "%s()\n", __FUNCTION__); iobase = self->io.fir_base; /* Disable DMA */// DisableDmaChannel(self->io.dma); /* Check for underrrun! */ /* Clear bit, by writing 1 into it */ Tx_status = GetTXStatus(iobase); if (Tx_status & 0x08) { self->stats.tx_errors++; self->stats.tx_fifo_errors++; hwreset(self);// how to clear underrrun ? } else { self->stats.tx_packets++; ResetChip(iobase, 3); ResetChip(iobase, 4); } /* Check if we need to change the speed */ if (self->new_speed) { via_ircc_change_speed(self, self->new_speed); self->new_speed = 0; } /* Finished with this frame, so prepare for next */ if (IsFIROn(iobase)) { if (self->tx_fifo.len) { self->tx_fifo.len--; self->tx_fifo.ptr++; } }#ifdef DBGMSG DBG(printk (KERN_INFO "via_ircc_dma_xmit_complete:tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free));#endif/* F01_S // Any frames to be sent back-to-back? if (self->tx_fifo.len) { // Not finished yet! via_ircc_dma_xmit(self, iobase); ret = FALSE; } else { F01_E*/ // 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;//F01 } // Make sure we have room for more frames //F01 if (self->tx_fifo.free < (MAX_TX_WINDOW -1 )) { // Not busy transmitting anymore // Tell the network layer, that we can accept more frames netif_wake_queue(self->netdev);//F01 } return ret;}/* * Function via_ircc_dma_receive (self) * * Set configuration for receive a frame. * */static int via_ircc_dma_receive(struct via_ircc_cb *self){ int iobase; iobase = self->io.fir_base; self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; self->tx_fifo.tail = self->tx_buff.head; self->RxDataReady = 0; self->io.direction = IO_RECV; self->rx_buff.data = self->rx_buff.head; self->st_fifo.len = self->st_fifo.pending_bytes = 0; self->st_fifo.tail = self->st_fifo.head = 0; EnPhys(iobase, ON); EnableTX(iobase, OFF); EnableRX(iobase, ON); ResetChip(iobase, 0); ResetChip(iobase, 1); ResetChip(iobase, 2); ResetChip(iobase, 3); ResetChip(iobase, 4); EnAllInt(iobase, ON); EnTXDMA(iobase, OFF); EnRXDMA(iobase, ON); setup_dma(self->io.dma2, self->rx_buff.data, self->rx_buff.truesize, DMA_RX_MODE); TXStart(iobase, OFF); RXStart(iobase, ON); return 0;}/* * Function via_ircc_dma_receive_complete (self) * * Controller Finished with receiving frames, * and this routine is call by ISR * */static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, int iobase){ struct st_fifo *st_fifo; struct sk_buff *skb; int len, i; u8 status = 0; iobase = self->io.fir_base; st_fifo = &self->st_fifo; if (self->io.speed < 4000000) { //Speed below FIR len = GetRecvByte(iobase, self); skb = dev_alloc_skb(len + 1); if (skb == NULL) return FALSE; // Make sure IP header gets aligned skb_reserve(skb, 1); skb_put(skb, len - 2); if (self->chip_id == 0x3076) { for (i = 0; i < len - 2; i++) skb->data[i] = self->rx_buff.data[i * 2]; } else { if (self->chip_id == 0x3096) { for (i = 0; i < len - 2; i++) skb->data[i] = self->rx_buff.data[i]; } } // 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); return TRUE; } else { //FIR mode len = GetRecvByte(iobase, self); if (len == 0) return TRUE; //interrupt only, data maybe move by RxT if (((len - 4) < 2) || ((len - 4) > 2048)) {#ifdef DBGMSG DBG(printk (KERN_INFO "receive_comple:Trouble:len=%x,CurCount=%x,LastCount=%x..\n", len, RxCurCount(iobase, self), self->RxLastCount));#endif hwreset(self); return FALSE; }#ifdef DBGMSG DBG(printk
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -