⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 via-ircc.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************** Filename:      via-ircc.c Version:       1.0  Description:   Driver for the VIA VT8231/VT8233 IrDA chipsets Author:        VIA Technologies,inc Date  :	08/06/2003Copyright (c) 1998-2003 VIA Technologies, Inc.This program is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the Free SoftwareFoundation; either version 2, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUTANY WARRANTIES OR REPRESENTATIONS; without even the implied warranty ofMERCHANTABILITY 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 withthis 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 .       Aug/06/2003 : change driver format to pci driver .        ********************************************************************/#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   VIA_MODULE_NAME "via-ircc"#define CHIP_IO_EXTENT 8#define BROKEN_DONGLE_IDstatic 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 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, __u32 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, u16 iobase);static int upload_rxdata(struct via_ircc_cb *self, int iobase);static int via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id);static void via_remove_one (struct pci_dev *pdev);/* Should use udelay() instead, even if we are x86 only - Jean II */void iodelay(int udelay){	u8 data;	int i;	for (i = 0; i < udelay; i++) {		data = inb(0x80);	}}static struct pci_device_id via_pci_tbl[] = {	{ PCI_VENDOR_ID_VIA, DeviceID1, PCI_ANY_ID, PCI_ANY_ID,0,0,0 },	{ PCI_VENDOR_ID_VIA, DeviceID2, PCI_ANY_ID, PCI_ANY_ID,0,0,1 },	{ PCI_VENDOR_ID_VIA, DeviceID3, PCI_ANY_ID, PCI_ANY_ID,0,0,2 },	{ PCI_VENDOR_ID_VIA, DeviceID4, PCI_ANY_ID, PCI_ANY_ID,0,0,3 },	{ PCI_VENDOR_ID_VIA, DeviceID5, PCI_ANY_ID, PCI_ANY_ID,0,0,4 },	{ 0, }};MODULE_DEVICE_TABLE(pci,via_pci_tbl);static struct pci_driver via_driver = {	.name		= VIA_MODULE_NAME,	.id_table	= via_pci_tbl,	.probe		= via_init_one,	.remove		= __devexit_p(via_remove_one),};/* * Function via_ircc_init () * *    Initialize chip. Just find out chip type and resource. */static int __devinit via_ircc_init(void){	int rc;#ifdef	HEADMSG        DBG(printk(KERN_INFO "via_ircc_init ......\n"));#endif	rc = pci_register_driver (&via_driver);#ifdef	HEADMSG        DBG(printk(KERN_INFO "via_ircc_init :rc = %d......\n",rc));#endif	if (rc < 1) {#ifdef	HEADMSG        DBG(printk(KERN_INFO "via_ircc_init return -ENODEV......\n"));#endif		if (rc == 0)	pci_unregister_driver (&via_driver);		return -ENODEV;	}	return 0;}static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id){	int rc;        u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1;	u16 Chipset,FirDRQ1,FirDRQ0,FirIRQ,FirIOBase;	chipio_t info;	#ifdef	HEADMSG        DBG(printk(KERN_INFO "via_init_one : Device ID=(0X%X)\n",id->device));#endif	if(id->device != DeviceID1 && id->device != DeviceID2 &&	   id->device != DeviceID3 && id->device != DeviceID4 &&	   id->device != DeviceID5  ){#ifdef	HEADMSG		DBG(printk(KERN_INFO "via_init_one : Device ID(0X%X) not Supported\n",id->device));#endif	      return -ENODEV; //South not exist !!!!!	}	rc = pci_enable_device (pcidev);#ifdef	HEADMSG	DBG(printk(KERN_INFO "via_init_one : rc=%d\n",rc));#endif	if (rc)		return -ENODEV;         //South Bridge exist        if ( ReadLPCReg(0x20) != 0x3C )		Chipset=0x3096;	else		Chipset=0x3076;	if (Chipset==0x3076) {#ifdef	HEADMSG		DBG(printk(KERN_INFO "via_init_one : 3076 ......\n"));#endif		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)				rc=0;		} else			rc = -ENODEV; //IR not turn on	 	} else { //Not VT1211#ifdef	HEADMSG		DBG(printk(KERN_INFO "via_init_one : 3096 ......\n"));#endif		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)				rc=0;		} else			rc = -ENODEV; //IR not turn on !!!!!	}//Not VT1211#ifdef	HEADMSG	DBG(printk(KERN_INFO "via_init_one End : rc=%d\n",rc));#endif	return rc;}/* * Function via_ircc_clean () * *    Close all configured chips * */static void __devexit via_ircc_clean(void){	int i;#ifdef	HEADMSG	DBG(printk(KERN_INFO "via_ircc_clean\n"));#endif	for (i=0; i < 4; i++) {		if (dev_self[i])			via_ircc_close(dev_self[i]);	}}static void __devexit via_remove_one (struct pci_dev *pdev){#ifdef	HEADMSG        DBG(printk(KERN_INFO "via_remove_one :  ......\n"));#endif	via_ircc_clean();}static void __devexit via_ircc_cleanup(void){#ifdef	HEADMSG	DBG(printk(KERN_INFO "via_ircc_cleanup ......\n"));#endif	via_ircc_clean();	pci_unregister_driver (&via_driver); }/* * Function via_ircc_open (iobase, irq) * *    Open driver instance * */static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id){	struct net_device *dev;	struct via_ircc_cb *self;	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 */	if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {//              WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",self->io.fir_base);		err = -ENODEV;		goto err_out1;	}	/* 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) {		err = -ENOMEM;		goto err_out2;	}	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) {		err = -ENOMEM;		goto err_out3;	}	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))) {		err = -ENOMEM;		goto err_out4;	}	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)		goto err_out4;	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; err_out4:	kfree(self->tx_buff.head); err_out3:	kfree(self->rx_buff.head); err_out2:	release_region(self->io.fir_base, self->io.fir_ext); err_out1:	kfree(self);	dev_self[i] = NULL;	return err;}/* * Function via_ircc_close (self) * *    Close driver instance * */static int __devexit 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){	u8 mode = 0;	WriteReg(iobase, I_ST_CT_0, 0x0);	switch (dongle_id) {	//HP1100	case 0x00:		/* same as */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -