* [PATCH 2.5 IrDA] VIA driver
@ 2003-07-09 23:53 Jean Tourrilhes
2003-07-10 21:25 ` Jeff Garzik
0 siblings, 1 reply; 2+ messages in thread
From: Jean Tourrilhes @ 2003-07-09 23:53 UTC (permalink / raw)
To: Jeff Garzik, Linux kernel mailing list
ir254_via_ircc-1.diff :
~~~~~~~~~~~~~~~~~~~~~
<Patch from Joseph Chan/VIA>
o [FEATURE] driver for IrDA integrated in VIA chipsets
diff -u -p -r --new-file linux/drivers/net/irda.d1/Kconfig linux/drivers/net/irda/Kconfig
--- linux/drivers/net/irda.d1/Kconfig Wed Jul 9 12:02:24 2003
+++ linux/drivers/net/irda/Kconfig Wed Jul 9 15:56:08 2003
@@ -348,5 +348,23 @@ config SA1100_FIR
tristate "SA1100 Internal IR"
depends on ARCH_SA1100 && IRDA
+config VIA_FIR
+ tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
+ depends on IRDA && ISA
+ help
+ Say Y here if you want to build support for the VIA VT8231
+ and VIA VT1211 IrDA controllers, found on the motherboards using
+ those those VIA chipsets. To use this controller, you will need
+ to plug a specific 5 pins FIR IrDA dongle in the specific
+ motherboard connector. The driver provides support for SIR, MIR
+ and FIR (4Mbps) speeds.
+
+ You will need to specify the 'dongle_id' module parameter to
+ indicate the FIR dongle attached to the controller.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ via-ircc.
+
endmenu
diff -u -p -r --new-file linux/drivers/net/irda.d1/Makefile linux/drivers/net/irda/Makefile
--- linux/drivers/net/irda.d1/Makefile Wed Jul 9 10:56:26 2003
+++ linux/drivers/net/irda/Makefile Wed Jul 9 15:55:05 2003
@@ -19,6 +19,7 @@ obj-$(CONFIG_SMC_IRCC_OLD) += smc-ircc.o
obj-$(CONFIG_SMC_IRCC_FIR) += smsc-ircc2.o
obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
+obj-$(CONFIG_VIA_FIR) += via-ircc.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_DONGLE_OLD) += esi.o
obj-$(CONFIG_TEKRAM_DONGLE_OLD) += tekram.o
diff -u -p -r --new-file linux/drivers/net/irda.d1/via-ircc.c linux/drivers/net/irda/via-ircc.c
--- linux/drivers/net/irda.d1/via-ircc.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/via-ircc.c Wed Jul 9 15:55:05 2003
@@ -0,0 +1,1483 @@
+/********************************************************************
+ Filename: via-ircc.c
+ Version: 0.3
+ Description: Driver for the VIA VT8231/VT8233 IrDA chipsets
+ Author: VIA Technologies,inc
+ Date : Oct/28/2002
+
+Copyright (c) 1998-2003 VIA Technologies, Inc.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTIES OR REPRESENTATIONS; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+F01 Oct/02/02: Modify code for V0.11(move out back to back transfer)
+F02 Oct/28/02: Add SB device ID for 3147 and 3177.
+ Comment :
+ jul/09/2002 : only implement two kind of dongle currently.
+ Oct/02/2002 : work on VT8231 and VT8233 .
+ ********************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/rtnetlink.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <linux/pm.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irda_device.h>
+
+#include "via-ircc.h"
+
+//#define DBG_IO 1
+//#define DBGMSG 1
+//#define DBGMSG_96 1
+//#define DBGMSG_76 1
+//static int debug=0;
+
+
+#define DBG(x) {if (debug) x;}
+
+#define CHIP_IO_EXTENT 8
+#define BROKEN_DONGLE_ID
+
+static char *driver_name = "via-ircc";
+
+/* Module parameters */
+static int qos_mtt_bits = 0x07; /* 1 ms or more */
+static int dongle_id=9; //defalut IBM type
+
+/* Resource is allocate by BIOS user only need to supply dongle_id*/
+MODULE_PARM(dongle_id, "i");
+
+/* Max 4 instances for now */
+static struct via_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
+
+/* Some prototypes */
+static int via_ircc_open(int i, chipio_t *info,unsigned int id);
+static int __exit via_ircc_close(struct via_ircc_cb *self);
+static int via_ircc_setup(chipio_t *info,unsigned int id);
+static int via_ircc_dma_receive(struct via_ircc_cb *self);
+static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, int iobase);
+static int via_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
+static int via_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
+static void via_ircc_change_speed(struct via_ircc_cb *self, DWORD baud);
+static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int via_ircc_is_receiving(struct via_ircc_cb *self);
+static int via_ircc_read_dongle_id (int iobase);
+
+static int via_ircc_net_init(struct net_device *dev);
+static int via_ircc_net_open(struct net_device *dev);
+static int via_ircc_net_close(struct net_device *dev);
+static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *via_ircc_net_get_stats(struct net_device *dev);
+static void via_ircc_change_dongle_speed(int iobase, int speed, int dongle_id);
+static int RxTimerHandler(struct via_ircc_cb *self, int iobase);
+void hwreset(struct via_ircc_cb *self);
+static int via_ircc_dma_xmit(struct via_ircc_cb *self,WORD iobase);
+static int upload_rxdata(struct via_ircc_cb *self, int iobase);
+void iodelay(int udelay)
+{
+ BYTE data;
+ int i;
+
+ for(i=0;i < udelay ; i++){
+ data=inb(0x80);
+ }
+}
+
+/*
+ * Function via_ircc_init ()
+ *
+ * Initialize chip. Just find out chip type and resource.
+ */
+int __init via_ircc_init(void)
+{
+ chipio_t info;
+ int ret = -ENODEV;
+ unsigned int Chipset;
+ BYTE temp,oldPCI_40,oldPCI_44,bTmp,bTmp1;
+ WORD FirDRQ0,FirIRQ,FirIOBase;
+ WORD FirDRQ1;
+ struct pci_dev *pcidev=NULL;
+
+ /* Probe for South Bridge */
+
+ if(!(pcidev = pci_find_device(VenderID,DeviceID1,pcidev) )) {
+ if(!(pcidev = pci_find_device(VenderID,DeviceID2,pcidev) )) {
+ if(!(pcidev = pci_find_device(VenderID,DeviceID3,pcidev) )) {
+//F02_S
+ if(!(pcidev = pci_find_device(VenderID,DeviceID4,pcidev) )) {
+ if(!(pcidev = pci_find_device(VenderID,DeviceID5,pcidev) )) {
+//F02_E
+ return -ENOMEM;
+ }
+ }
+ }
+ }
+ }
+ if (pcidev) { //South Bridge exist
+ if ( ReadLPCReg(0x20) != 0x3C ) Chipset=0x3096;
+ else Chipset=0x3076;
+ if (Chipset==0x3076) {
+ WriteLPCReg(7,0x0c );
+ temp=ReadLPCReg(0x30);//check if BIOS Enable Fir
+ if((temp&0x01)==1) { // BIOS close or no FIR
+ WriteLPCReg(0x1d, 0x82 );
+ WriteLPCReg(0x23,0x18);
+ temp=ReadLPCReg(0xF0);
+ if((temp&0x01)==0) {
+ temp=(ReadLPCReg(0x74)&0x03); //DMA
+ FirDRQ0=temp + 4;
+ temp=(ReadLPCReg(0x74)&0x0C) >> 2;
+ FirDRQ1=temp + 4;
+ }
+ else {
+ temp=(ReadLPCReg(0x74)&0x0C) >> 2; //DMA
+ FirDRQ0=temp + 4;
+ FirDRQ1=FirDRQ0;
+ }
+ FirIRQ=(ReadLPCReg(0x70)&0x0f); //IRQ
+ FirIOBase=ReadLPCReg(0x60 ) << 8; //IO Space :high byte
+ FirIOBase=FirIOBase| ReadLPCReg(0x61) ; //low byte
+ FirIOBase=FirIOBase ;
+ info.fir_base=FirIOBase;
+ info.irq=FirIRQ;
+ info.dma=FirDRQ1;
+ info.dma2=FirDRQ0;
+ pci_read_config_byte(pcidev,0x40,&bTmp);
+ pci_write_config_byte(pcidev,0x40,((bTmp | 0x08) & 0xfe));
+ pci_read_config_byte(pcidev,0x42,&bTmp);
+ pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0));
+ pci_write_config_byte(pcidev,0x5a,0xc0);
+ WriteLPCReg(0x28, 0x70 );
+ if (via_ircc_open(0, &info,0x3076) == 0)
+ ret=0;
+ }
+ else {
+ }
+ }
+ else { //Not VT1211
+ pci_read_config_byte(pcidev,0x67,&bTmp);//check if BIOS Enable Fir
+ if((bTmp&0x01)==1) { // BIOS enable FIR
+ //Enable Double DMA clock
+ pci_read_config_byte(pcidev,0x42,&oldPCI_40);
+ pci_write_config_byte(pcidev,0x42,oldPCI_40 | 0x80);
+ pci_read_config_byte(pcidev,0x40,&oldPCI_40);
+ pci_write_config_byte(pcidev,0x40,oldPCI_40 & 0xf7);
+ pci_read_config_byte(pcidev,0x44,&oldPCI_44);
+ pci_write_config_byte(pcidev,0x44,0x4e);
+ //---------- read configuration from Function0 of south bridge
+ if((bTmp&0x02)==0) {
+ pci_read_config_byte(pcidev,0x44,&bTmp1); //DMA
+ FirDRQ0 = (bTmp1 & 0x30) >> 4;
+ pci_read_config_byte(pcidev,0x44,&bTmp1);
+ FirDRQ1 = (bTmp1 & 0xc0) >> 6;
+
+ }
+ else {
+ pci_read_config_byte(pcidev,0x44,&bTmp1); //DMA
+ FirDRQ0 = (bTmp1 & 0x30) >> 4 ;
+ FirDRQ1=0;
+
+ }
+ pci_read_config_byte(pcidev,0x47,&bTmp1); //IRQ
+ FirIRQ = bTmp1 & 0x0f;
+
+ pci_read_config_byte(pcidev,0x69,&bTmp);
+ FirIOBase = bTmp << 8;//hight byte
+ pci_read_config_byte(pcidev,0x68,&bTmp);
+ FirIOBase = (FirIOBase | bTmp ) & 0xfff0;
+
+ //-------------------------
+ info.fir_base=FirIOBase;
+ info.irq=FirIRQ;
+ info.dma=FirDRQ1;
+ info.dma2=FirDRQ0;
+ if (via_ircc_open(0, &info,0x3096) == 0) ret=0;
+ }
+ else { // IR not turn on !!!!!!!!!!
+ }
+ }//Not VT1211
+ }//SB exist
+
+ return ret;
+}
+
+/*
+ * Function via_ircc_cleanup ()
+ *
+ * Close all configured chips
+ *
+ */
+static void __exit via_ircc_cleanup(void)
+{
+ int i;
+
+
+ for (i=0; i < 4; i++) {
+ if (dev_self[i])
+ via_ircc_close(dev_self[i]);
+ }
+}
+
+/*
+ * Function via_ircc_open (iobase, irq)
+ *
+ * Open driver instance
+ *
+ */
+static __init int via_ircc_open(int i, chipio_t *info,unsigned int id)
+{
+ struct net_device *dev;
+ struct via_ircc_cb *self;
+ int ret;
+ int err;
+
+ if ((via_ircc_setup(info,id)) == -1) return -1;
+
+ /* Allocate new instance of the driver */
+ self = kmalloc(sizeof(struct via_ircc_cb), GFP_KERNEL);
+ if (self == NULL) {
+ return -ENOMEM;
+ }
+ memset(self, 0, sizeof(struct via_ircc_cb));
+ spin_lock_init(&self->lock);
+
+ /* Need to store self somewhere */
+ dev_self[i] = self;
+ self->index = i;
+ /* Initialize Resource */
+ self->io.cfg_base = info->cfg_base;
+ self->io.fir_base = info->fir_base;
+ self->io.irq = info->irq;
+ self->io.fir_ext = CHIP_IO_EXTENT;
+ self->io.dma = info->dma;
+ self->io.dma2 = info->dma2;
+ self->io.fifo_size = 32;
+ self->chip_id = id;
+ self->st_fifo.len =0;
+ self->RxDataReady = 0;
+
+ /* Reserve the ioports that we need */
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
+ if (ret < 0) {
+// WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",self->io.fir_base);
+ dev_self[i] = NULL;
+ kfree(self);
+ return -ENODEV;
+ }
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies(&self->qos);
+ /* The only value we must override it the baudrate */
+// self->qos.baud_rate.bits = IR_9600;// May use this for testing
+
+ self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8);
+
+ self->qos.min_turn_time.bits = qos_mtt_bits;
+ irda_qos_bits_to_value(&self->qos);
+
+ self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
+ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+ self->rx_buff.truesize = 14384 + 2048;
+ self->tx_buff.truesize = 14384 + 2048;
+
+ /* Allocate memory if needed */
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,GFP_KERNEL|GFP_DMA);
+ if (self->rx_buff.head == NULL) {
+ kfree(self);
+ return -ENOMEM;
+ }
+ memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, GFP_KERNEL|GFP_DMA);
+ if (self->tx_buff.head == NULL) {
+ kfree(self->rx_buff.head);
+ kfree(self);
+ return -ENOMEM;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->tx_buff.data = self->tx_buff.head;
+ self->rx_buff.data = self->rx_buff.head;
+
+ /* Reset Tx queue info */
+ self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+ self->tx_fifo.tail = self->tx_buff.head;
+
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ kfree(self->tx_buff.head);
+ kfree(self->rx_buff.head);
+ kfree(self);
+ return -ENOMEM;
+ }
+
+ dev->priv = (void *) self;
+ self->netdev = dev;
+
+ /* Override the network functions we need to use */
+ dev->init = via_ircc_net_init;
+ dev->hard_start_xmit = via_ircc_hard_xmit_sir;
+ dev->open = via_ircc_net_open;
+ dev->stop = via_ircc_net_close;
+ dev->do_ioctl = via_ircc_net_ioctl;
+ dev->get_stats = via_ircc_net_get_stats;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ return -1;
+ }
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ /* Check if user has supplied the dongle id or not */
+ if (!dongle_id) dongle_id = via_ircc_read_dongle_id(self->io.fir_base);
+ self->io.dongle_id = dongle_id;
+ via_ircc_change_dongle_speed(self->io.fir_base, 9600, self->io.dongle_id);
+
+ return 0;
+}
+
+/*
+ * Function via_ircc_close (self)
+ *
+ * Close driver instance
+ *
+ */
+static int __exit via_ircc_close(struct via_ircc_cb *self)
+{
+ int iobase;
+
+ IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
+
+ ASSERT(self != NULL, return -1;);
+
+ iobase = self->io.fir_base;
+
+ ResetChip(iobase,5); //hardware reset.
+ /* Remove netdevice */
+ if (self->netdev) {
+ rtnl_lock();
+ unregister_netdevice(self->netdev);
+ rtnl_unlock();
+ }
+
+ /* Release the PORT that this driver is using */
+ IRDA_DEBUG(4, "%s(), Releasing Region %03x\n",
+ __FUNCTION__, self->io.fir_base);
+ release_region(self->io.fir_base, self->io.fir_ext);
+ if (self->tx_buff.head) kfree(self->tx_buff.head);
+ if (self->rx_buff.head) kfree(self->rx_buff.head);
+ dev_self[self->index] = NULL;
+ kfree(self);
+
+ return 0;
+}
+
+/*
+ * Function via_ircc_setup (info)
+ *
+ * Returns non-negative on success.
+ *
+ */
+static int via_ircc_setup(chipio_t *info,unsigned int chip_id)
+{
+ int iobase = info->fir_base;
+
+ SetMaxRxPacketSize(iobase,0x0fff); //set to max:4095
+ // FIFO Init
+ EnRXFIFOReadyInt(iobase,OFF);
+ EnRXFIFOHalfLevelInt(iobase,OFF);
+ EnTXFIFOHalfLevelInt(iobase,OFF);
+ EnTXFIFOUnderrunEOMInt(iobase,ON);
+ EnTXFIFOReadyInt(iobase,OFF);
+ InvertTX(iobase,OFF);
+ InvertRX(iobase,OFF);
+ if(ReadLPCReg(0x20) == 0x3c) WriteLPCReg(0xF0,0);// for VT1211
+ if ( IsSIROn(iobase) ) {
+ SIRFilter(iobase,ON);
+ SIRRecvAny(iobase,ON);
+ }
+ else {
+ SIRFilter(iobase,OFF);
+ SIRRecvAny(iobase,OFF);
+ }
+ //Int Init
+ EnRXSpecInt(iobase,ON);
+ //DMA Init Later....
+ WriteReg(iobase,I_ST_CT_0,0x80);
+ EnableDMA(iobase,ON);
+
+ return 0;
+}
+
+/*
+ * Function via_ircc_read_dongle_id (void)
+ *
+ */
+static int via_ircc_read_dongle_id (int iobase)
+{
+ int dongle_id=9;
+
+ 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)
+{
+ BYTE mode=0;
+
+ WriteReg(iobase,I_ST_CT_0,0x0);
+ switch (dongle_id) { //HP1100
+ case 0x00: /* same as */
+ 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, DWORD speed)
+{
+ struct net_device *dev = self->netdev;
+ WORD iobase;
+ BYTE 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;
+ WORD iobase;
+ DWORD 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;
+ WORD iobase;
+ DWORD speed,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,WORD iobase)
+{
+// int i;
+// BYTE *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;
+ BYTE 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;
+ BYTE 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(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--;
+
+ skb = dev_alloc_skb(len+1-4);
+ /*
+ * if frame size,data ptr,or skb ptr are wrong ,the get next * entry.
+ */
+ if ((skb == NULL) || (skb->data == NULL) || (self->rx_buff.data ==NULL) || (len < 6)) {
+ 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
+ skb = dev_alloc_skb(len+1);
+ if ((skb == NULL) || ((len-4) < 2)) {
+ 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;
+ BYTE 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--;
+
+ skb = dev_alloc_skb(len+1-4);
+ /*
+ * if frame size,data ptr,or skb ptr are wrong ,the get next * entry.
+ */
+ if ((skb == NULL) || (skb->data == NULL) || (self->rx_buff.data ==NULL) || (len < 6)) {
+ 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;
+ BYTE 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);
diff -u -p -r --new-file linux/drivers/net/irda.d1/via-ircc.h linux/drivers/net/irda/via-ircc.h
--- linux/drivers/net/irda.d1/via-ircc.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/via-ircc.h Wed Jul 9 15:55:05 2003
@@ -0,0 +1,1027 @@
+/*********************************************************************
+ *
+ * Filename: via-ircc.h
+ * Version: 0.1
+ * Description: Driver for the VIA VT8231 IrDA chipsets
+ * Author: VIA Technologies, inc
+ * Date : jul/09/2002
+
+Copyright (c) 1998-2003 VIA Technologies, Inc.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTIES OR REPRESENTATIONS; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ * Comment:
+ * jul/08/2002 : Rx buffer length should use Rx ring ptr.
+ * F01 Oct/28/2002 : Add SB id for 3147 and 3177.
+ ********************************************************************/
+#ifndef via_IRCC_H
+#define via_IRCC_H
+#include <linux/time.h>
+#include <linux/spinlock.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+
+#define MAX_TX_WINDOW 7
+#define MAX_RX_WINDOW 7
+
+struct st_fifo_entry {
+ int status;
+ int len;
+};
+
+struct st_fifo {
+ struct st_fifo_entry entries[MAX_RX_WINDOW+2];
+ int pending_bytes;
+ int head;
+ int tail;
+ int len;
+};
+
+struct frame_cb {
+ void *start; /* Start of frame in DMA mem */
+ int len; /* Lenght of frame in DMA mem */
+};
+
+struct tx_fifo {
+ struct frame_cb queue[MAX_TX_WINDOW+2]; /* Info about frames in queue */
+ int ptr; /* Currently being sent */
+ int len; /* Lenght of queue */
+ int free; /* Next free slot */
+ void *tail; /* Next free start in DMA mem */
+};
+
+
+struct eventflag // for keeping track of Interrupt Events
+ {
+ //--------tx part
+ unsigned char TxFIFOUnderRun;
+ unsigned char EOMessage;
+ unsigned char TxFIFOReady;
+ unsigned char EarlyEOM;
+ //--------rx part
+ unsigned char PHYErr;
+ unsigned char CRCErr;
+ unsigned char RxFIFOOverRun;
+ unsigned char EOPacket;
+ unsigned char RxAvail;
+ unsigned char TooLargePacket;
+ unsigned char SIRBad;
+ //--------unknown
+ unsigned char Unknown;
+ //----------
+ unsigned char TimeOut;
+ unsigned char RxDMATC;
+ unsigned char TxDMATC;
+ };
+
+/* Private data for each instance */
+struct via_ircc_cb {
+ struct st_fifo st_fifo; /* Info about received frames */
+ struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
+
+ struct net_device *netdev; /* Yes! we are some kind of netdevice */
+ struct net_device_stats stats;
+
+ struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct qos_info qos; /* QoS capabilities for this device */
+
+ chipio_t io; /* IrDA controller information */
+ iobuff_t tx_buff; /* Transmit buffer */
+ iobuff_t rx_buff; /* Receive buffer */
+
+ __u8 ier; /* Interrupt enable register */
+
+ struct timeval stamp;
+ struct timeval now;
+
+ spinlock_t lock; /* For serializing operations */
+
+ __u32 flags; /* Interface flags */
+ __u32 new_speed;
+ int index; /* Instance index */
+
+ struct eventflag EventFlag;
+ struct pm_dev *dev;
+ unsigned int chip_id; /* to remember chip id */
+ unsigned int RetryCount;
+ unsigned int RxDataReady;
+ unsigned int RxLastCount;
+};
+
+
+//---------I=Infrared, H=Host, M=Misc, T=Tx, R=Rx, ST=Status,
+// CF=Config, CT=Control, L=Low, H=High, C=Count
+#define I_CF_L_0 0x10
+#define I_CF_H_0 0x11
+#define I_SIR_BOF 0x12
+#define I_SIR_EOF 0x13
+#define I_ST_CT_0 0x15
+#define I_ST_L_1 0x16
+#define I_ST_H_1 0x17
+#define I_CF_L_1 0x18
+#define I_CF_H_1 0x19
+#define I_CF_L_2 0x1a
+#define I_CF_H_2 0x1b
+#define I_CF_3 0x1e
+#define H_CT 0x20
+#define H_ST 0x21
+#define M_CT 0x22
+#define TX_CT_1 0x23
+#define TX_CT_2 0x24
+#define TX_ST 0x25
+#define RX_CT 0x26
+#define RX_ST 0x27
+#define RESET 0x28
+#define P_ADDR 0x29
+#define RX_C_L 0x2a
+#define RX_C_H 0x2b
+#define RX_P_L 0x2c
+#define RX_P_H 0x2d
+#define TX_C_L 0x2e
+#define TX_C_H 0x2f
+#define TIMER 0x32
+#define I_CF_4 0x33
+#define I_T_C_L 0x34
+#define I_T_C_H 0x35
+#define VERSION 0x3f
+//-------------------------------
+#define StartAddr 0x10 // the first register address
+#define EndAddr 0x3f // the last register address
+#define GetBit(val,bit) val = (unsigned char) ((val>>bit) & 0x1)
+ // Returns the bit
+#define SetBit(val,bit) val= (unsigned char ) (val | (0x1 << bit))
+ // Sets bit to 1
+#define ResetBit(val,bit) val= (unsigned char ) (val & ~(0x1 << bit))
+ // Sets bit to 0
+#define PCI_CONFIG_ADDRESS 0xcf8
+#define PCI_CONFIG_DATA 0xcfc
+
+#define VenderID 0x1106
+#define DeviceID1 0x8231
+#define DeviceID2 0x3109
+#define DeviceID3 0x3074
+//F01_S
+#define DeviceID4 0x3147
+#define DeviceID5 0x3177
+//F01_E
+
+#define OFF 0
+#define ON 1
+#define DMA_TX_MODE 0x08
+#define DMA_RX_MODE 0x04
+
+#define DMA1 0
+#define DMA2 0xc0
+#define MASK1 DMA1+0x0a
+#define MASK2 DMA2+0x14
+
+#define Clk_bit 0x40
+#define Tx_bit 0x01
+#define Rd_Valid 0x08
+#define RxBit 0x08
+
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef unsigned long ULONG;
+typedef unsigned int UINT;
+
+BYTE ReadPCIByte(BYTE ,BYTE ,BYTE ,BYTE );
+DWORD ReadPCI(BYTE ,BYTE ,BYTE ,BYTE );
+void WritePCI(BYTE ,BYTE ,BYTE ,BYTE ,DWORD );
+void WritePCIByte(BYTE ,BYTE ,BYTE ,BYTE ,BYTE );
+int mySearchPCI(BYTE * ,WORD,WORD);
+
+
+void DisableDmaChannel(unsigned int channel)
+{
+ switch (channel) {// 8 Bit DMA channels DMAC1
+ case 0:
+ outb(4,MASK1); //mask channel 0
+ break;
+ case 1:
+ outb(5,MASK1); //Mask channel 1
+ break;
+ case 2:
+ outb(6,MASK1); //Mask channel 2
+ break;
+ case 3:
+ outb(7,MASK1); //Mask channel 3
+ break;
+ case 5:
+ outb(5,MASK2); //Mask channel 5
+ break;
+ case 6:
+ outb(6,MASK2); //Mask channel 6
+ break;
+ case 7:
+ outb(7,MASK2); //Mask channel 7
+ break;
+ default:
+ break;
+ }; //Switch
+}
+
+unsigned char ReadLPCReg(int iRegNum)
+{
+ unsigned char iVal;
+
+ outb(0x87,0x2e );
+ outb(0x87,0x2e );
+ outb(iRegNum ,0x2e);
+ iVal=inb(0x2f);
+ outb(0xaa,0x2e);
+
+ return iVal ;
+}
+
+void WriteLPCReg(int iRegNum,unsigned char iVal)
+{
+
+ outb(0x87,0x2e );
+ outb(0x87,0x2e );
+ outb(iRegNum ,0x2e);
+ outb(iVal,0x2f );
+ outb(0xAA,0x2e );
+}
+
+BYTE ReadReg(unsigned int BaseAddr,int iRegNum)
+{
+ return((BYTE)inb(BaseAddr + iRegNum ));
+}
+
+void WriteReg(unsigned int BaseAddr,int iRegNum, UCHAR iVal)
+{
+ outb(iVal,BaseAddr + iRegNum );
+}
+
+int WriteRegBit(unsigned int BaseAddr,unsigned char RegNum,unsigned char BitPos,unsigned char value)
+{
+ BYTE Rtemp,Wtemp;
+
+ if(BitPos>7) {
+ return -1;
+ }
+ if((RegNum<StartAddr)||(RegNum>EndAddr)) return -1;
+ Rtemp=ReadReg(BaseAddr,RegNum);
+ if(value==0) Wtemp=ResetBit(Rtemp,BitPos);
+ else {
+ if(value==1) Wtemp=SetBit(Rtemp,BitPos);
+ else return -1;
+ }
+ WriteReg(BaseAddr,RegNum,Wtemp);
+ return 0;
+}
+
+BYTE CheckRegBit(unsigned int BaseAddr,unsigned char RegNum,unsigned char BitPos)
+{
+ BYTE temp;
+
+ if(BitPos>7) return 0xff;
+ if((RegNum<StartAddr)||(RegNum>EndAddr)) {
+// printf("what is the register %x!\n",RegNum);
+ }
+ temp=ReadReg(BaseAddr,RegNum);
+ return GetBit(temp,BitPos);
+}
+
+BYTE ReadPCIByte(BYTE bus,BYTE device,BYTE fun,BYTE reg)
+{
+ DWORD dTmp;
+ BYTE bData,bTmp;
+
+ bTmp = reg & ~0x03;
+ dTmp = ReadPCI(bus,device,fun,bTmp);
+ bTmp = reg & 0x03;
+ bData = (BYTE) (dTmp >> bTmp);
+ return bData;
+}
+
+DWORD ReadPCI(BYTE bus,BYTE device,BYTE fun,BYTE reg)
+{
+ DWORD CONFIG_ADDR,temp,data;
+
+ if((bus==0xff)||(device==0xff)||(fun==0xff)) return 0xffffffff;
+ CONFIG_ADDR=0x80000000;
+ temp=(DWORD)reg<<2;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+ temp=(DWORD)fun<<8;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+ temp=(DWORD)device<<11;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+ temp=(DWORD)bus<<16;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+
+ outl(PCI_CONFIG_ADDRESS,CONFIG_ADDR);
+ data=inl(PCI_CONFIG_DATA);
+ return data;
+}
+
+
+void WritePCIByte(BYTE bus,BYTE device,BYTE fun,BYTE reg,BYTE CONFIG_DATA)
+{
+ DWORD dTmp,dTmp1=0;
+ BYTE bTmp;
+
+ bTmp = reg & ~0x03;
+ dTmp = ReadPCI(bus,device,fun,bTmp);
+ switch(reg &0x03) {
+ case 0:
+ dTmp1 = (dTmp & ~0xff) | CONFIG_DATA;
+ break;
+ case 1:
+ dTmp = (dTmp & ~0x00ff00);
+ dTmp1 = CONFIG_DATA ;
+ dTmp1 = dTmp1 << 8;
+ dTmp1 = dTmp1 | dTmp;
+ break;
+ case 2:
+ dTmp = (dTmp & ~0xff0000);
+ dTmp1 = CONFIG_DATA ;
+ dTmp1 = dTmp1 << 16;
+ dTmp1 = dTmp1 | dTmp;
+ break;
+ case 3:
+ dTmp = (dTmp & ~0xff000000);
+ dTmp1 = CONFIG_DATA ;
+ dTmp1 = dTmp1 << 24;
+ dTmp1 = dTmp1 | dTmp;
+ break;
+ }
+ WritePCI(bus,device,fun,bTmp,dTmp1);
+}
+
+//------------------
+void WritePCI(BYTE bus,BYTE device,BYTE fun,BYTE reg,DWORD CONFIG_DATA)
+{
+ DWORD CONFIG_ADDR,temp;
+
+ if((bus==0xff)||(device==0xff)||(fun==0xff)) return;
+ CONFIG_ADDR=0x80000000;
+ temp=(DWORD)reg<<2;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+ temp=(DWORD)fun<<8;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+ temp=(DWORD)device<<11;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+ temp=(DWORD)bus<<16;
+ CONFIG_ADDR=CONFIG_ADDR|temp;
+
+ outl(PCI_CONFIG_ADDRESS,CONFIG_ADDR);
+ outl(PCI_CONFIG_DATA,CONFIG_DATA);
+
+}
+
+ // find device with DeviceID and VenderID // if match return three byte buffer (bus,device,function) // no found, address={99,99,99}
+int mySearchPCI(BYTE *SBridpos,WORD VID,WORD DID)
+{
+ BYTE i,j,k;
+ WORD FindDeviceID,FindVenderID;
+
+ for(k=0;k<8;k++) { //scan function
+ i=0;
+ j=0x11;
+ k=0;
+ if(ReadPCI(i,j,k,0)<0xffffffff) { // not empty
+ FindDeviceID=(WORD)(ReadPCI(i,j,k,0)>>16);
+ FindVenderID=(WORD)(ReadPCI(i,j,k,0)&0x0000ffff);
+ if((VID==FindVenderID)&&(DID==FindDeviceID)) {
+ SBridpos[0]=i; // bus
+ SBridpos[1]=j; //device
+ SBridpos[2]=k; //func
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void SetMaxRxPacketSize(WORD iobase ,WORD size)
+{
+ WORD low,high;
+ if((size &0xe000) ==0) {
+ low = size & 0x00ff;
+ high = (size & 0x1f00) >> 8 ;
+ WriteReg(iobase ,I_CF_L_2,low);
+ WriteReg(iobase ,I_CF_H_2,high);
+
+ }
+
+}
+
+//for both Rx and Tx
+
+void SetFIFO(WORD iobase,WORD value)
+{
+ switch (value) {
+ case 128 :
+ WriteRegBit(iobase,0x11,0,0);
+ WriteRegBit(iobase,0x11,7,1);
+ break;
+ case 64 :
+ WriteRegBit(iobase,0x11,0,0);
+ WriteRegBit(iobase,0x11,7,0);
+ break;
+ case 32 :
+ WriteRegBit(iobase,0x11,0,1);
+ WriteRegBit(iobase,0x11,7,0);
+ break;
+ default :
+ WriteRegBit(iobase,0x11,0,0);
+ WriteRegBit(iobase,0x11,7,0);
+ }
+
+}
+
+#define CRC16(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,7,val) //0 for 32 CRC
+/*
+#define SetVFIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,5,val)
+#define SetFIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,6,val)
+#define SetMIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,5,val)
+#define SetSIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,4,val)
+*/
+#define SIRFilter(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,3,val)
+#define Filter(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,2,val)
+#define InvertTX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,1,val)
+#define InvertRX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,0,val)
+//****************************I_CF_H_0
+#define EnableTX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,4,val)
+#define EnableRX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,3,val)
+#define EnableDMA(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,2,val)
+#define SIRRecvAny(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,1,val)
+#define DiableTrans(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,0,val)
+//***************************I_SIR_BOF,I_SIR_EOF
+#define SetSIRBOF(BaseAddr,val) WriteReg(BaseAddr,I_SIR_BOF,val)
+#define SetSIREOF(BaseAddr,val) WriteReg(BaseAddr,I_SIR_EOF,val)
+#define GetSIRBOF(BaseAddr) ReadReg(BaseAddr,I_SIR_BOF)
+#define GetSIREOF(BaseAddr) ReadReg(BaseAddr,I_SIR_EOF)
+//*******************I_ST_CT_0
+#define EnPhys(BaseAddr,val) WriteRegBit(BaseAddr,I_ST_CT_0,7,val)
+#define IsModeError(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,6) //RO
+#define IsVFIROn(BaseAddr) CheckRegBit(BaseAddr,0x14,0) //RO for VT1211 only
+#define IsFIROn(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,5) //RO
+#define IsMIROn(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,4) //RO
+#define IsSIROn(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,3) //RO
+#define IsEnableTX(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,2) //RO
+#define IsEnableRX(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,1) //RO
+#define Is16CRC(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,0) //RO
+//***************************I_CF_3
+#define DisableAdjacentPulseWidth(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,5,val) //1 disable
+#define DisablePulseWidthAdjust(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,4,val) //1 disable
+#define UseOneRX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,1,val) //0 use two RX
+#define SlowIRRXLowActive(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,0,val) //0 show RX high=1 in SIR
+//***************************H_CT
+#define EnAllInt(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,7,val)
+#define TXStart(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,6,val)
+#define RXStart(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,5,val)
+#define ClearRXInt(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,4,val) // 1 clear
+//*****************H_ST
+#define IsRXInt(BaseAddr) CheckRegBit(BaseAddr,H_ST,4)
+#define GetIntIndentify(BaseAddr) ((ReadReg(BaseAddr,H_ST)&0xf1) >>1)
+#define IsHostBusy(BaseAddr) CheckRegBit(BaseAddr,H_ST,0)
+#define GetHostStatus(BaseAddr) ReadReg(BaseAddr,H_ST) //RO
+//**************************M_CT
+#define EnTXDMA(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,7,val)
+#define EnRXDMA(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,6,val)
+#define SwapDMA(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,5,val)
+#define EnInternalLoop(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,4,val)
+#define EnExternalLoop(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,3,val)
+//**************************TX_CT_1
+#define EnTXFIFOHalfLevelInt(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_1,4,val) //half empty int (1 half)
+#define EnTXFIFOUnderrunEOMInt(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_1,5,val)
+#define EnTXFIFOReadyInt(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_1,6,val) //int when reach it threshold (setting by bit 4)
+//**************************TX_CT_2
+#define ForceUnderrun(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,7,val) // force an underrun int
+#define EnTXCRC(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,6,val) //1 for FIR,MIR...0 (not SIR)
+#define ForceBADCRC(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,5,val) //force an bad CRC
+#define SendSIP(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,4,val) //send indication pulse for prevent SIR disturb
+#define ClearEnTX(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,3,val) // opposite to EnTX
+//*****************TX_ST
+#define GetTXStatus(BaseAddr) ReadReg(BaseAddr,TX_ST) //RO
+//**************************RX_CT
+#define EnRXSpecInt(BaseAddr,val) WriteRegBit(BaseAddr,RX_CT,0,val)
+#define EnRXFIFOReadyInt(BaseAddr,val) WriteRegBit(BaseAddr,RX_CT,1,val) //enable int when reach it threshold (setting by bit 7)
+#define EnRXFIFOHalfLevelInt(BaseAddr,val) WriteRegBit(BaseAddr,RX_CT,7,val) //enable int when (1) half full...or (0) just not full
+//*****************RX_ST
+#define GetRXStatus(BaseAddr) ReadReg(BaseAddr,RX_ST) //RO
+//***********************P_ADDR
+#define SetPacketAddr(BaseAddr,addr) WriteReg(BaseAddr,P_ADDR,addr)
+//***********************I_CF_4
+#define EnGPIOtoRX2(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_4,7,val)
+#define EnTimerInt(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_4,1,val)
+#define ClearTimerInt(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_4,0,val)
+//***********************I_T_C_L
+#define WriteGIO(BaseAddr,val) WriteRegBit(BaseAddr,I_T_C_L,7,val)
+#define ReadGIO(BaseAddr) CheckRegBit(BaseAddr,I_T_C_L,7)
+#define ReadRX(BaseAddr) CheckRegBit(BaseAddr,I_T_C_L,3) //RO
+#define WriteTX(BaseAddr,val) WriteRegBit(BaseAddr,I_T_C_L,0,val)
+//***********************I_T_C_H
+#define EnRX2(BaseAddr,val) WriteRegBit(BaseAddr,I_T_C_H,7,val)
+#define ReadRX2(BaseAddr) CheckRegBit(BaseAddr,I_T_C_H,7)
+//**********************Version
+#define GetFIRVersion(BaseAddr) ReadReg(BaseAddr,VERSION)
+
+
+void SetTimer(WORD iobase ,BYTE count)
+{
+ EnTimerInt(iobase,OFF);
+ WriteReg(iobase,TIMER,count);
+ EnTimerInt(iobase,ON);
+}
+
+
+void SetSendByte(WORD iobase,DWORD count)
+{
+ DWORD low,high;
+
+ if((count & 0xf000) == 0) {
+ low = count & 0x00ff ;
+ high = (count & 0x0f00) >> 8 ;
+ WriteReg(iobase,TX_C_L,low) ;
+ WriteReg(iobase,TX_C_H,high);
+ }
+}
+
+void ResetChip(WORD iobase ,BYTE type)
+{
+ BYTE value;
+
+ value = (type+2) << 4 ;
+ WriteReg(iobase,RESET,type);
+}
+
+void SetAddrMode(WORD iobase,BYTE mode)
+{
+ BYTE bTmp = 0;
+ if(mode < 3) {
+ bTmp = (ReadReg(iobase,RX_CT) & 0xcf) | (mode << 4) ;
+ WriteReg(iobase,RX_CT,bTmp);
+ }
+}
+
+int CkRxRecv(WORD iobase,struct via_ircc_cb *self)
+{
+ BYTE low,high;
+ WORD wTmp = 0,wTmp1 = 0 ,wTmp_new = 0;
+
+ low=ReadReg(iobase,RX_C_L);
+ high=ReadReg(iobase,RX_C_H);
+ wTmp1 = high ;
+ wTmp = (wTmp1 << 8 ) | low ;
+ udelay(10);
+ low=ReadReg(iobase,RX_C_L);
+ high=ReadReg(iobase,RX_C_H);
+ wTmp1 = high ;
+ wTmp_new = (wTmp1 << 8 ) | low ;
+ if(wTmp_new != wTmp) return 1;
+ else return 0;
+
+}
+
+WORD RxCurCount(WORD iobase,struct via_ircc_cb *self)
+{
+ BYTE low,high;
+ WORD wTmp = 0,wTmp1 = 0 ;
+
+ low=ReadReg(iobase,RX_P_L);
+ high=ReadReg(iobase,RX_P_H);
+ wTmp1 = high ;
+ wTmp = (wTmp1 << 8 ) | low ;
+ return wTmp;
+}
+
+/* This Routine can only use in recevie_complete
+ * for it will update last count.
+ */
+
+WORD GetRecvByte(WORD iobase,struct via_ircc_cb *self)
+{
+ BYTE low,high;
+ WORD wTmp,wTmp1,ret;
+
+ low=ReadReg(iobase,RX_P_L);
+ high=ReadReg(iobase,RX_P_H);
+ wTmp1 = high ;
+ wTmp = (wTmp1 << 8 ) | low ;
+
+
+ if (wTmp >= self->RxLastCount) ret = wTmp - self->RxLastCount;
+ else ret = (0x8000 - self->RxLastCount) + wTmp ;
+ self->RxLastCount= wTmp;
+
+/* RX_P is more actually the RX_C
+ low=ReadReg(iobase,RX_C_L);
+ high=ReadReg(iobase,RX_C_H);
+
+ if(!(high&0xe000)) {
+ temp=(high<<8)+low;
+ return temp;
+ }
+ else return 0;
+*/
+ return ret;
+}
+
+
+WORD GetRecvLen(WORD iobase)
+{
+ BYTE low,high;
+ WORD temp;
+
+ low=ReadReg(iobase,RX_P_L);
+ high=ReadReg(iobase,RX_P_H);
+
+ if(!(high&0xe000)) {
+ temp=(high<<8)+low;
+ return temp;
+ }
+ else return 0;
+}
+
+void Sdelay(WORD scale)
+{
+ BYTE bTmp;
+ int i,j;
+
+ for(j=0; j< scale; j++){
+ for(i=0;i<0x20 ; i++ ){
+ bTmp = inb(0xeb);
+ outb(bTmp,0xeb);
+ }
+ }
+}
+
+void Tdelay(WORD scale)
+{
+ BYTE bTmp;
+ int i,j;
+
+ for(j=0; j< scale; j++){
+ for(i=0;i<0x50 ; i++ ){
+ bTmp = inb(0xeb);
+ outb(bTmp,0xeb);
+ }
+ }
+}
+
+
+void ActClk(WORD iobase,BYTE value)
+{
+ BYTE bTmp;
+ bTmp = ReadReg(iobase,0x34);
+ if (value) WriteReg(iobase,0x34,bTmp | Clk_bit);
+ else WriteReg(iobase,0x34,bTmp & ~Clk_bit);
+}
+
+void ActTx(WORD iobase,BYTE value)
+{
+ BYTE bTmp;
+
+ bTmp = ReadReg(iobase,0x34);
+ if (value) WriteReg(iobase,0x34,bTmp | Tx_bit);
+ else WriteReg(iobase,0x34,bTmp & ~Tx_bit);
+}
+
+void ClkTx(WORD iobase,BYTE Clk,BYTE Tx)
+{
+ BYTE bTmp;
+
+ bTmp = ReadReg(iobase,0x34);
+ if (Clk == 0) bTmp &= ~Clk_bit;
+ else {
+ if (Clk == 1) bTmp |= Clk_bit;
+ }
+ WriteReg(iobase,0x34,bTmp);
+ Sdelay(1);
+ if (Tx == 0) bTmp &= ~Tx_bit;
+ else {
+ if (Tx == 1) bTmp |= Tx_bit;
+ }
+ WriteReg(iobase,0x34,bTmp);
+}
+
+void Wr_Byte(WORD iobase,BYTE data)
+{
+ BYTE bData=data;
+// BYTE btmp;
+ int i;
+
+ ClkTx(iobase,0,1) ;
+
+ Tdelay(2);
+ ActClk(iobase,1);
+ Tdelay(1);
+
+ for(i=0 ; i < 8 ; i++){ //LDN
+
+ if((bData >> i) & 0x01) {
+ ClkTx(iobase,0,1) ; //bit data = 1;
+ }
+ else {
+ ClkTx(iobase,0,0) ; //bit data = 1;
+ }
+ Tdelay(2);
+ Sdelay(1);
+ ActClk(iobase,1);//clk hi
+ Tdelay(1);
+ }
+}
+
+BYTE Rd_Indx(WORD iobase,BYTE addr,BYTE index)
+{
+ BYTE data=0,bTmp,data_bit;
+ int i;
+
+ bTmp = addr | (index << 1) | 0;
+ ClkTx(iobase,0,0) ;
+ Tdelay(2);
+ ActClk(iobase,1);
+ udelay(1);
+ Wr_Byte(iobase,bTmp) ;
+ Sdelay(1);
+ ClkTx(iobase,0,0) ;
+ Tdelay(2);
+ for (i=0;i < 10 ; i++){
+ ActClk(iobase,1);
+ Tdelay(1);
+ ActClk(iobase,0);
+ Tdelay(1);
+ ClkTx(iobase,0,1) ;
+ Tdelay(1);
+ bTmp = ReadReg(iobase,0x34);
+ if(!(bTmp & Rd_Valid)) break;
+ }
+ if(!(bTmp & Rd_Valid)) {
+ for(i = 0; i < 8 ; i++){
+ ActClk(iobase,1);
+ Tdelay(1);
+ ActClk(iobase,0);
+ bTmp = ReadReg(iobase,0x34);
+ data_bit = 1 << i;
+ if(bTmp & RxBit) data |= data_bit;
+ else data &= ~data_bit;
+ Tdelay(2);
+ }
+ }
+ else {
+ for (i=0;i < 2 ; i++){
+ ActClk(iobase,1);
+ Tdelay(1);
+ ActClk(iobase,0);
+ Tdelay(2);
+ }
+ bTmp = ReadReg(iobase,0x34);
+ }
+ for (i=0;i < 1 ; i++){
+ ActClk(iobase,1);
+ Tdelay(1);
+ ActClk(iobase,0);
+ Tdelay(2);
+ }
+ ClkTx(iobase,0,0) ;
+ Tdelay(1);
+ for (i=0;i < 3 ; i++){
+ ActClk(iobase,1);
+ Tdelay(1);
+ ActClk(iobase,0);
+ Tdelay(2);
+ }
+ return data;
+}
+
+void Wr_Indx(WORD iobase,BYTE addr,BYTE index,BYTE data)
+{
+ int i;
+ BYTE bTmp;
+
+ ClkTx(iobase,0,0) ;
+ udelay(2);
+ ActClk(iobase,1);
+ udelay(1);
+ bTmp = addr | (index << 1) | 1;
+ Wr_Byte(iobase,bTmp) ;
+ Wr_Byte(iobase,data) ;
+ for(i = 0 ; i < 2 ; i++) {
+ ClkTx(iobase,0,0) ;
+ Tdelay(2);
+ ActClk(iobase,1);
+ Tdelay(1);
+ }
+ ActClk(iobase,0);
+}
+
+void ResetDongle(WORD iobase)
+{
+ int i;
+ ClkTx(iobase,0,0);
+ Tdelay(1);
+ for(i=0 ; i < 30 ; i++){
+ ActClk(iobase,1);
+ Tdelay(1);
+ ActClk(iobase,0);
+ Tdelay(1);
+ }
+ ActClk(iobase,0);
+}
+
+void SetSITmode(WORD iobase)
+{
+
+ BYTE bTmp;
+
+ bTmp = ReadLPCReg(0x28) ;
+ WriteLPCReg(0x28,bTmp | 0x10 );//select ITMOFF
+ bTmp = ReadReg(iobase,0x35);
+ WriteReg(iobase,0x35, bTmp | 0x40);// Driver ITMOFF
+ WriteReg(iobase,0x28, bTmp | 0x80);// enable All interrupt
+}
+
+void SI_SetMode(WORD iobase,int mode)
+{
+ //DWORD dTmp;
+ BYTE bTmp;
+
+ WriteLPCReg(0x28,0x70); // S/W Reset
+ SetSITmode(iobase);
+ ResetDongle(iobase);
+ udelay(10);
+ Wr_Indx(iobase,0x40,0x0,0x17) ; //RX ,APEN enable,Normal power
+ Wr_Indx(iobase,0x40,0x1,mode) ; //Set Mode
+ Wr_Indx(iobase,0x40,0x2,0xff) ; //Set power to FIR VFIR > 1m
+ bTmp = Rd_Indx(iobase,0x40,1);
+}
+
+void InitCard(WORD iobase)
+{
+ ResetChip(iobase,5);
+ WriteReg(iobase,I_ST_CT_0,0x00); // open CHIP on
+ SetSIRBOF(iobase,0xc0); // hardware default value
+ SetSIREOF(iobase,0xc1);
+}
+
+void CommonShutDown(WORD iobase,BYTE TxDMA)
+{
+ DisableDmaChannel(TxDMA);
+}
+
+void CommonInit(WORD iobase)
+{
+// EnTXCRC(iobase,0);
+ SwapDMA(iobase,OFF);
+ SetMaxRxPacketSize(iobase,0x0fff); //set to max:4095
+ EnRXFIFOReadyInt(iobase,OFF);
+ EnRXFIFOHalfLevelInt(iobase,OFF);
+ EnTXFIFOHalfLevelInt(iobase,OFF);
+ EnTXFIFOUnderrunEOMInt(iobase,ON);
+// EnTXFIFOReadyInt(iobase,ON);
+ InvertTX(iobase,OFF);
+ InvertRX(iobase,OFF);
+// WriteLPCReg(0xF0,0); //(if VT1211 then do this)
+ if ( IsSIROn(iobase) ) {
+ SIRFilter(iobase,ON);
+ SIRRecvAny(iobase,ON);
+ }
+ else {
+ SIRFilter(iobase,OFF);
+ SIRRecvAny(iobase,OFF);
+ }
+ EnRXSpecInt(iobase,ON);
+ WriteReg(iobase,I_ST_CT_0,0x80);
+ EnableDMA(iobase,ON);
+}
+
+void SetBaudRate(WORD iobase,DWORD rate)
+{
+ BYTE value=11,temp;
+
+ if(IsSIROn(iobase)) {
+ switch(rate) {
+ case (DWORD)(2400L):
+ value=47;
+ break;
+ case (DWORD)(9600L):
+ value=11;
+ break;
+ case (DWORD)(19200L):
+ value=5;
+ break;
+ case (DWORD)(38400L):
+ value=2;
+ break;
+ case (DWORD)(57600L):
+ value=1;
+ break;
+ case (DWORD)(115200L):
+ value=0;
+ break;
+ default:
+ break;
+ };
+ }
+ else if(IsMIROn(iobase)) {
+ value=0; // will automatically be fixed in 1.152M
+ }
+ else if(IsFIROn(iobase)) {
+ value=0; // will automatically be fixed in 4M
+ }
+ temp=(ReadReg(iobase,I_CF_H_1)&0x03);
+ temp=temp|(value<<2);
+ WriteReg(iobase,I_CF_H_1,temp);
+}
+
+void SetPulseWidth(WORD iobase,BYTE width)
+{
+ BYTE temp,temp1,temp2;
+
+ temp =(ReadReg(iobase,I_CF_L_1) & 0x1f);
+ temp1=(ReadReg(iobase,I_CF_H_1) & 0xfc);
+ temp2=(width & 0x07) << 5;
+ temp = temp | temp2;
+ temp2=(width & 0x18) >> 3;
+ temp1 = temp1 | temp2 ;
+ WriteReg(iobase,I_CF_L_1,temp);
+ WriteReg(iobase,I_CF_H_1,temp1);
+}
+
+void SetSendPreambleCount(WORD iobase,BYTE count)
+{
+ BYTE temp;
+
+ temp = ReadReg(iobase,I_CF_L_1) & 0xe0;
+ temp = temp | count ;
+ WriteReg(iobase,I_CF_L_1,temp);
+
+}
+
+void SetVFIR(WORD BaseAddr,BYTE val)
+{
+ BYTE tmp;
+
+ tmp = ReadReg(BaseAddr,I_CF_L_0);
+ WriteReg(BaseAddr,I_CF_L_0, tmp & 0x8f);
+ WriteRegBit(BaseAddr,I_CF_H_0,5,val);
+}
+
+void SetFIR(WORD BaseAddr,BYTE val)
+{
+ BYTE tmp;
+
+ WriteRegBit(BaseAddr,I_CF_H_0,5,0);
+ tmp = ReadReg(BaseAddr,I_CF_L_0);
+ WriteReg(BaseAddr,I_CF_L_0, tmp & 0x8f);
+ WriteRegBit(BaseAddr,I_CF_L_0,6,val);
+}
+
+void SetMIR(WORD BaseAddr,BYTE val)
+{
+ BYTE tmp;
+
+ WriteRegBit(BaseAddr,I_CF_H_0,5,0);
+ tmp = ReadReg(BaseAddr,I_CF_L_0);
+ WriteReg(BaseAddr,I_CF_L_0, tmp & 0x8f);
+ WriteRegBit(BaseAddr,I_CF_L_0,5,val);
+}
+
+void SetSIR(WORD BaseAddr,BYTE val)
+{
+ BYTE tmp;
+
+ WriteRegBit(BaseAddr,I_CF_H_0,5,0);
+ tmp = ReadReg(BaseAddr,I_CF_L_0);
+ WriteReg(BaseAddr,I_CF_L_0, tmp & 0x8f);
+ WriteRegBit(BaseAddr,I_CF_L_0,4,val);
+}
+
+void ClrHBusy(WORD iobase)
+{
+
+ EnableDMA(iobase,OFF);
+ EnableDMA(iobase,ON);
+ RXStart(iobase,OFF);
+ RXStart(iobase,ON);
+ RXStart(iobase,OFF);
+ EnableDMA(iobase,OFF);
+ EnableDMA(iobase,ON);
+}
+
+void SetFifo64(WORD iobase)
+{
+
+ WriteRegBit(iobase,I_CF_H_0,0,0);
+ WriteRegBit(iobase,I_CF_H_0,7,0);
+}
+
+
+#endif /* via_IRCC_H */
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 2.5 IrDA] VIA driver
2003-07-09 23:53 [PATCH 2.5 IrDA] VIA driver Jean Tourrilhes
@ 2003-07-10 21:25 ` Jeff Garzik
0 siblings, 0 replies; 2+ messages in thread
From: Jeff Garzik @ 2003-07-10 21:25 UTC (permalink / raw)
To: jt; +Cc: Linux kernel mailing list
Ug. Did you even read this driver before forwarding??
The coding style is half linux kernel, half drunken fool. And the PCI
probing is one huge mess.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2003-07-10 21:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-07-09 23:53 [PATCH 2.5 IrDA] VIA driver Jean Tourrilhes
2003-07-10 21:25 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox