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

📄 ali-ircc.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Should be 0x00 in the M1535/M1535D */	if(version != 0x00)	{		IRDA_ERROR("%s, Wrong chip version %02x\n",			   ALI_IRCC_DRIVER_NAME, version);		return -1;	}		/* Set FIR FIFO Threshold Register */	switch_bank(iobase, BANK1);	outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR);		/* Set FIR DMA Threshold Register */	outb(RX_DMA_Threshold, iobase+FIR_DMA_TR);		/* CRC enable */	switch_bank(iobase, BANK2);	outb(inb(iobase+FIR_IRDA_CR) | IRDA_CR_CRC, iobase+FIR_IRDA_CR);		/* NDIS driver set TX Length here BANK2 Alias 3, Alias4*/		/* Switch to Bank 0 */	switch_bank(iobase, BANK0);		tmp = inb(iobase+FIR_LCR_B);	tmp &=~0x20; // disable SIP	tmp |= 0x80; // these two steps make RX mode	tmp &= 0xbf;		outb(tmp, iobase+FIR_LCR_B);			/* Disable Interrupt */	outb(0x00, iobase+FIR_IER);			/* Switch to SIR space */	FIR2SIR(iobase);		IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n",		     ALI_IRCC_DRIVER_NAME);		/* Enable receive interrupts */ 	// outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM	// Turn on the interrupts in ali_ircc_net_open		IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);			return 0;}/* * Function ali_ircc_read_dongle_id (int index, info) * * Try to read dongle indentification. This procedure needs to be executed * once after power-on/reset. It also needs to be used whenever you suspect * that the user may have plugged/unplugged the IrDA Dongle. */static int ali_ircc_read_dongle_id (int i, chipio_t *info){	int dongle_id, reg;	int cfg_base = info->cfg_base;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);			/* Enter Configuration */	outb(chips[i].entr1, cfg_base);	outb(chips[i].entr2, cfg_base);		/* Select Logical Device 5 Registers (UART2) */	outb(0x07, cfg_base);	outb(0x05, cfg_base+1);		/* Read Dongle ID */	outb(0xf0, cfg_base);	reg = inb(cfg_base+1);		dongle_id = ((reg>>6)&0x02) | ((reg>>5)&0x01);	IRDA_DEBUG(2, "%s(), probing dongle_id=%d, dongle_types=%s\n", __FUNCTION__, 		dongle_id, dongle_types[dongle_id]);		/* Exit configuration */	outb(0xbb, cfg_base);				IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);			return dongle_id;}/* * Function ali_ircc_interrupt (irq, dev_id, regs) * *    An interrupt from the chip has arrived. Time to do some work * */static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id){	struct net_device *dev = dev_id;	struct ali_ircc_cb *self;	int ret;			IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);			self = dev->priv;		spin_lock(&self->lock);		/* Dispatch interrupt handler for the current speed */	if (self->io.speed > 115200)		ret = ali_ircc_fir_interrupt(self);	else		ret = ali_ircc_sir_interrupt(self);			spin_unlock(&self->lock);		IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);	return ret;}/* * Function ali_ircc_fir_interrupt(irq, struct ali_ircc_cb *self) * *    Handle MIR/FIR interrupt * */static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self){	__u8 eir, OldMessageCount;	int iobase, tmp;		IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__);		iobase = self->io.fir_base;		switch_bank(iobase, BANK0);		self->InterruptID = inb(iobase+FIR_IIR);			self->BusStatus = inb(iobase+FIR_BSR);			OldMessageCount = (self->LineStatus + 1) & 0x07;	self->LineStatus = inb(iobase+FIR_LSR);		//self->ier = inb(iobase+FIR_IER); 		2000/12/1 04:32PM	eir = self->InterruptID & self->ier; /* Mask out the interesting ones */ 		IRDA_DEBUG(1, "%s(), self->InterruptID = %x\n", __FUNCTION__,self->InterruptID);	IRDA_DEBUG(1, "%s(), self->LineStatus = %x\n", __FUNCTION__,self->LineStatus);	IRDA_DEBUG(1, "%s(), self->ier = %x\n", __FUNCTION__,self->ier);	IRDA_DEBUG(1, "%s(), eir = %x\n", __FUNCTION__,eir);		/* Disable interrupts */	 SetCOMInterrupts(self, FALSE);		/* Tx or Rx Interrupt */		if (eir & IIR_EOM) 	{				if (self->io.direction == IO_XMIT) /* TX */		{			IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Tx) *******\n", __FUNCTION__);						if(ali_ircc_dma_xmit_complete(self))			{				if (irda_device_txqueue_empty(self->netdev)) 				{					/* Prepare for receive */					ali_ircc_dma_receive(self);										self->ier = IER_EOM;													}			}			else			{				self->ier = IER_EOM; 								}											}			else /* RX */		{			IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Rx) *******\n", __FUNCTION__);						if(OldMessageCount > ((self->LineStatus+1) & 0x07))			{				self->rcvFramesOverflow = TRUE;					IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ******** \n", __FUNCTION__);			}									if (ali_ircc_dma_receive_complete(self))			{				IRDA_DEBUG(1, "%s(), ******* receive complete ******** \n", __FUNCTION__);								self->ier = IER_EOM;							}			else			{				IRDA_DEBUG(1, "%s(), ******* Not receive complete ******** \n", __FUNCTION__);								self->ier = IER_EOM | IER_TIMER;											}					}			}	/* Timer Interrupt */	else if (eir & IIR_TIMER)	{			if(OldMessageCount > ((self->LineStatus+1) & 0x07))		{			self->rcvFramesOverflow = TRUE;				IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ******* \n", __FUNCTION__);		}		/* Disable Timer */		switch_bank(iobase, BANK1);		tmp = inb(iobase+FIR_CR);		outb( tmp& ~CR_TIMER_EN, iobase+FIR_CR);				/* Check if this is a Tx timer interrupt */		if (self->io.direction == IO_XMIT)		{			ali_ircc_dma_xmit(self);						/* Interrupt on EOM */			self->ier = IER_EOM;											}		else /* Rx */		{			if(ali_ircc_dma_receive_complete(self)) 			{				self->ier = IER_EOM;			}			else			{				self->ier = IER_EOM | IER_TIMER;			}			}			}		/* Restore Interrupt */		SetCOMInterrupts(self, TRUE);				IRDA_DEBUG(1, "%s(), ----------------- End ---------------\n", __FUNCTION__);	return IRQ_RETVAL(eir);}/* * Function ali_ircc_sir_interrupt (irq, self, eir) * *    Handle SIR interrupt * */static irqreturn_t ali_ircc_sir_interrupt(struct ali_ircc_cb *self){	int iobase;	int iir, lsr;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);		iobase = self->io.sir_base;	iir = inb(iobase+UART_IIR) & UART_IIR_ID;	if (iir) {			/* Clear interrupt */		lsr = inb(iobase+UART_LSR);		IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", __FUNCTION__, 			   iir, lsr, iobase);		switch (iir) 		{			case UART_IIR_RLSI:				IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);				break;			case UART_IIR_RDI:				/* Receive interrupt */				ali_ircc_sir_receive(self);				break;			case UART_IIR_THRI:				if (lsr & UART_LSR_THRE)				{					/* Transmitter ready for data */					ali_ircc_sir_write_wakeup(self);								}								break;			default:				IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);				break;		} 			}			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);		return IRQ_RETVAL(iir);}/* * Function ali_ircc_sir_receive (self) * *    Receive one frame from the infrared port * */static void ali_ircc_sir_receive(struct ali_ircc_cb *self) {	int boguscount = 0;	int iobase;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	iobase = self->io.sir_base;	/*  	 * Receive all characters in Rx FIFO, unwrap and unstuff them.          * async_unwrap_char will deliver all found frames  	 */	do {		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 				  inb(iobase+UART_RX));		/* Make sure we don't stay here too long */		if (boguscount++ > 32) {			IRDA_DEBUG(2,"%s(), breaking!\n", __FUNCTION__);			break;		}	} while (inb(iobase+UART_LSR) & UART_LSR_DR);			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}/* * Function ali_ircc_sir_write_wakeup (tty) * *    Called by the driver when there's room for more data.  If we have *    more packets to send, we send them here. * */static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self){	int actual = 0;	int iobase;		IRDA_ASSERT(self != NULL, return;);	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		iobase = self->io.sir_base;	/* Finished with frame?  */	if (self->tx_buff.len > 0)  	{		/* Write data left in transmit buffer */		actual = ali_ircc_sir_write(iobase, self->io.fifo_size, 				      self->tx_buff.data, self->tx_buff.len);		self->tx_buff.data += actual;		self->tx_buff.len  -= actual;	} 	else 	{		if (self->new_speed) 		{			/* We must wait until all data are gone */			while(!(inb(iobase+UART_LSR) & UART_LSR_TEMT))				IRDA_DEBUG(1, "%s(), UART_LSR_THRE\n", __FUNCTION__ );						IRDA_DEBUG(1, "%s(), Changing speed! self->new_speed = %d\n", __FUNCTION__ , self->new_speed);			ali_ircc_change_speed(self, self->new_speed);			self->new_speed = 0;									// benjamin 2000/11/10 06:32PM			if (self->io.speed > 115200)			{				IRDA_DEBUG(2, "%s(), ali_ircc_change_speed from UART_LSR_TEMT \n", __FUNCTION__ );													self->ier = IER_EOM;				// SetCOMInterrupts(self, TRUE);											return;										}		}		else		{			netif_wake_queue(self->netdev);			}					self->stats.tx_packets++;				/* Turn on receive interrupts */		outb(UART_IER_RDI, iobase+UART_IER);	}			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud){	struct net_device *dev = self->netdev;	int iobase;		IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		IRDA_DEBUG(2, "%s(), setting speed = %d \n", __FUNCTION__ , baud);		/* This function *must* be called with irq off and spin-lock.	 * - Jean II */	iobase = self->io.fir_base;		SetCOMInterrupts(self, FALSE); // 2000/11/24 11:43AM		/* Go to MIR, FIR Speed */	if (baud > 115200)	{									ali_ircc_fir_change_speed(self, baud);							/* Install FIR xmit handler*/		dev->hard_start_xmit = ali_ircc_fir_hard_xmit;								/* Enable Interuupt */		self->ier = IER_EOM; // benjamin 2000/11/20 07:24PM											/* Be ready for incomming frames */		ali_ircc_dma_receive(self);	// benajmin 2000/11/8 07:46PM not complete	}		/* Go to SIR Speed */	else	{		ali_ircc_sir_change_speed(self, baud);						/* Install SIR xmit handler*/		dev->hard_start_xmit = ali_ircc_sir_hard_xmit;	}				SetCOMInterrupts(self, TRUE);	// 2000/11/24 11:43AM			netif_wake_queue(self->netdev);			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud){			int iobase; 	struct ali_ircc_cb *self = (struct ali_ircc_cb *) priv;	struct net_device *dev;	IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );			IRDA_ASSERT(self != NULL, return;);	dev = self->netdev;	iobase = self->io.fir_base;		IRDA_DEBUG(1, "%s(), self->io.speed = %d, change to speed = %d\n", __FUNCTION__ ,self->io.speed,baud);		/* Come from SIR speed */	if(self->io.speed <=115200)	{		SIR2FIR(iobase);	}			/* Update accounting for new speed */	self->io.speed = baud;			// Set Dongle Speed mode	ali_ircc_change_dongle_speed(self, baud);			IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}/* * Function ali_sir_change_speed (self, speed) * *    Set speed of IrDA port to specified baudrate * */static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed){	struct ali_ircc_cb *self = (struct ali_ircc_cb *) priv;	unsigned long flags;	int iobase; 	int fcr;    /* FIFO control reg */	int lcr;    /* Line control reg */	int divisor;	IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		IRDA_DEBUG(1, "%s(), Setting speed to: %d\n", __FUNCTION__ , speed);	IRDA_ASSERT(self != NULL, return;);	iobase = self->io.sir_base;		/* Come from MIR or FIR speed */	if(self->io.speed >115200)	{			// Set Dongle Speed mode first		ali_ircc_change_dongle_speed(self, speed);					FIR2SIR(iobase);	}			// Clear Line and Auxiluary status registers 2000/11/24 11:47AM			inb(iobase+UART_LSR);	inb(iobase+UART_SCR);			/* Update accounting for new speed */	self->io.speed = speed;	spin_lock_irqsave(&self->lock, flags);	divisor = 115200/speed;		fcr = UART_FCR_ENABLE_FIFO;	/* 	 * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget	 * about this timeout since it will always be fast enough. 	 */	if (self->io.speed < 38400)		fcr |= UART_FCR_TRIGGER_1;	else 		fcr |= UART_FCR_TRIGGER_14;        	/* IrDA ports use 8N1 */	lcr = UART_LCR_WLEN8;		outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */	outb(divisor & 0xff,      iobase+UART_DLL); /* Set speed */	outb(divisor >> 8,	  iobase+UART_DLM);	outb(lcr,		  iobase+UART_LCR); /* Set 8N1	*/	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */	/* without this, the conection will be broken after come back from FIR speed,	   but with this, the SIR connection is harder to established */	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);		spin_unlock_irqrestore(&self->lock, flags);		IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed){		struct ali_ircc_cb *self = (struct ali_ircc_cb *) priv;	int iobase,dongle_id;	int tmp = 0;				IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );			iobase = self->io.fir_base; 	/* or iobase = self->io.sir_base; */	dongle_id = self->io.dongle_id;		/* We are already locked, no need to do it again */			IRDA_DEBUG(1, "%s(), Set Speed for %s , Speed = %d\n", __FUNCTION__ , dongle_types[dongle_id], speed);				switch_bank(iobase, BANK2);	tmp = inb(iobase+FIR_IRDA_CR);			/* IBM type dongle */	if(dongle_id == 0)	{						if(speed == 4000000)		{			//	      __ __				// SD/MODE __|     |__ __			//               __ __ 

⌨️ 快捷键说明

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