📄 via-ircc.c
字号:
/* * Function via_ircc_read_dongle_id (void) * */static int via_ircc_read_dongle_id(int iobase){ int dongle_id = 9; /* Default to IBM */ IRDA_ERROR("via-ircc: dongle probing not supported, please specify dongle_id module parameter.\n"); return dongle_id;}/* * Function via_ircc_change_dongle_speed (iobase, speed, dongle_id) * Change speed of the attach dongle * only implement two type of dongle currently. */static void via_ircc_change_dongle_speed(int iobase, int speed, int dongle_id){ u8 mode = 0; /* speed is unused, as we use IsSIROn()/IsMIROn() */ speed = speed; IRDA_DEBUG(1, "%s(): change_dongle_speed to %d for 0x%x, %d\n", __FUNCTION__, speed, iobase, dongle_id); switch (dongle_id) { /* Note: The dongle_id's listed here are derived from * nsc-ircc.c */ 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 0x11: /* Temic TFDS4500 */ IRDA_DEBUG(2, "%s: Temic TFDS4500: One RX pin, TX normal, RX inverted.\n", __FUNCTION__); UseOneRX(iobase, ON); //use ONE RX....RX1 InvertTX(iobase, OFF); InvertRX(iobase, ON); // invert RX pin EnRX2(iobase, ON); //sir to rx2 EnGPIOtoRX2(iobase, OFF); if( IsSIROn(iobase) ){ //sir // Mode select On SlowIRRXLowActive(iobase, ON); udelay(20); // Mode select Off SlowIRRXLowActive(iobase, OFF); } else{ IRDA_DEBUG(0, "%s: Warning: TFDS4500 not running in SIR mode !\n", __FUNCTION__); } 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); break; default: IRDA_ERROR("%s: Error: dongle_id %d unsupported !\n", __FUNCTION__, dongle_id); }}/* * 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; IRDA_DEBUG(1, "%s: change_speed to %d bps.\n", __FUNCTION__, speed); WriteReg(iobase, I_ST_CT_0, 0x0); /* Controller mode sellection */ switch (speed) { case 2400: case 9600: case 19200: case 38400: case 57600: case 115200: value = (115200/speed)-1; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 576000: /* FIXME: this can't be right, as it's the same as 115200, * and 576000 is MIR, not SIR. */ value = 0; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 1152000: value = 0; SetMIR(iobase, ON); /* FIXME: CRC ??? */ 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); /* FIXME: CRC ??? */ break; default: value = 0; break; } /* Set baudrate to 0x19[2..7] */ bTmp = (ReadReg(iobase, I_CF_H_1) & 0x03); bTmp |= value << 2; WriteReg(iobase, I_CF_H_1, bTmp); /* Some dongles may need to be informed about speed changes. */ via_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id); /* Set FIFO size to 64 */ SetFIFO(iobase, 64); /* Enable IR */ WriteReg(iobase, I_ST_CT_0, 0x80); // EnTXFIFOHalfLevelInt(iobase,ON); /* 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; IRDA_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; /* Send this frame with old speed */ SetBaudRate(iobase, self->io.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); irda_setup_dma(self->io.dma, self->tx_buff_dma, 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){ 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); irda_setup_dma(self->io.dma, ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - self->tx_buff.head) + self->tx_buff_dma, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); IRDA_DEBUG(1, "%s: tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", __FUNCTION__, self->tx_fifo.ptr, self->tx_fifo.queue[self->tx_fifo.ptr].len, self->tx_fifo.len); 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(3, "%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++; } } IRDA_DEBUG(1, "%s: tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", __FUNCTION__, self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free);/* 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; IRDA_DEBUG(3, "%s()\n", __FUNCTION__); 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); irda_setup_dma(self->io.dma2, self->rx_buff_dma, 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]; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -