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

📄 ali-ircc.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			// IRTX    __ __|     |__			//         T1 T2 T3 T4 T5						tmp &=  ~IRDA_CR_HDLC;		// HDLC=0			tmp |= IRDA_CR_CRC;	   	// CRC=1						switch_bank(iobase, BANK2);			outb(tmp, iobase+FIR_IRDA_CR);			      			// T1 -> SD/MODE:0 IRTX:0      			tmp &= ~0x09;      			tmp |= 0x02;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// T2 -> SD/MODE:1 IRTX:0      			tmp &= ~0x01;      			tmp |= 0x0a;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// T3 -> SD/MODE:1 IRTX:1      			tmp |= 0x0b;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// T4 -> SD/MODE:0 IRTX:1      			tmp &= ~0x08;      			tmp |= 0x03;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// T5 -> SD/MODE:0 IRTX:0      			tmp &= ~0x09;      			tmp |= 0x02;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// reset -> Normal TX output Signal      			outb(tmp & ~0x02, iobase+FIR_IRDA_CR);      					}		else /* speed <=1152000 */		{				//	      __				// SD/MODE __|  |__			//			// IRTX    ________			//         T1 T2 T3  						/* MIR 115200, 57600 */			if (speed==1152000)			{				tmp |= 0xA0;	   //HDLC=1, 1.152Mbps=1      			}      			else      			{				tmp &=~0x80;	   //HDLC 0.576Mbps				tmp |= 0x20;	   //HDLC=1,      			}			      			      			tmp |= IRDA_CR_CRC;	   	// CRC=1      			      			switch_bank(iobase, BANK2);      			outb(tmp, iobase+FIR_IRDA_CR);									/* MIR 115200, 57600 */										//switch_bank(iobase, BANK2);						// T1 -> SD/MODE:0 IRTX:0      			tmp &= ~0x09;      			tmp |= 0x02;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// T2 -> SD/MODE:1 IRTX:0      			tmp &= ~0x01;           			tmp |= 0x0a;            			outb(tmp, iobase+FIR_IRDA_CR);      			      			// T3 -> SD/MODE:0 IRTX:0      			tmp &= ~0x09;      			tmp |= 0x02;      			outb(tmp, iobase+FIR_IRDA_CR);      			udelay(2);      			      			// reset -> Normal TX output Signal      			outb(tmp & ~0x02, iobase+FIR_IRDA_CR);      								}			}	else if (dongle_id == 1) /* HP HDSL-3600 */	{		switch(speed)		{		case 4000000:			tmp &=  ~IRDA_CR_HDLC;	// HDLC=0			break;						case 1152000:			tmp |= 0xA0;	   	// HDLC=1, 1.152Mbps=1      			break;      			      		case 576000:      			tmp &=~0x80;	   	// HDLC 0.576Mbps			tmp |= 0x20;	   	// HDLC=1,			break;      		}								tmp |= IRDA_CR_CRC;	   	// CRC=1					switch_bank(iobase, BANK2);      		outb(tmp, iobase+FIR_IRDA_CR);			}	else /* HP HDSL-1100 */	{		if(speed <= 115200) /* SIR */		{						tmp &= ~IRDA_CR_FIR_SIN;	// HP sin select = 0						switch_bank(iobase, BANK2);      			outb(tmp, iobase+FIR_IRDA_CR);					}		else /* MIR FIR */		{							switch(speed)			{			case 4000000:				tmp &=  ~IRDA_CR_HDLC;	// HDLC=0				break;							case 1152000:				tmp |= 0xA0;	   	// HDLC=1, 1.152Mbps=1      				break;      			      			case 576000:      				tmp &=~0x80;	   	// HDLC 0.576Mbps				tmp |= 0x20;	   	// HDLC=1,				break;      			}									tmp |= IRDA_CR_CRC;	   	// CRC=1			tmp |= IRDA_CR_FIR_SIN;		// HP sin select = 1						switch_bank(iobase, BANK2);      			outb(tmp, iobase+FIR_IRDA_CR);					}	}				switch_bank(iobase, BANK0);		IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		}/* * Function ali_ircc_sir_write (driver) * *    Fill Tx FIFO with transmit data * */static int ali_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len){	int actual = 0;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );			/* Tx FIFO should be empty! */	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {		IRDA_DEBUG(0, "%s(), failed, fifo not empty!\n", __FUNCTION__ );		return 0;	}        	/* Fill FIFO with current frame */	while ((fifo_size-- > 0) && (actual < len)) {		/* Transmit next byte */		outb(buf[actual], iobase+UART_TX);		actual++;	}	        IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		return actual;}/* * Function ali_ircc_net_open (dev) * *    Start the device * */static int ali_ircc_net_open(struct net_device *dev){	struct ali_ircc_cb *self;	int iobase;	char hwname[32];			IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		IRDA_ASSERT(dev != NULL, return -1;);		self = (struct ali_ircc_cb *) dev->priv;		IRDA_ASSERT(self != NULL, return 0;);		iobase = self->io.fir_base;		/* Request IRQ and install Interrupt Handler */	if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev)) 	{		IRDA_WARNING("%s, unable to allocate irq=%d\n",			     ALI_IRCC_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)) {		IRDA_WARNING("%s, unable to allocate dma=%d\n",			     ALI_IRCC_DRIVER_NAME,			     self->io.dma);		free_irq(self->io.irq, self);		return -EAGAIN;	}		/* Turn on interrups */	outb(UART_IER_RDI , iobase+UART_IER);	/* Ready to play! */	netif_start_queue(dev); //benjamin by irport		/* Give self a hardware name */	sprintf(hwname, "ALI-FIR @ 0x%03x", self->io.fir_base);	/* 	 * Open new IrLAP layer instance, now that everything should be	 * initialized properly 	 */	self->irlap = irlap_open(dev, &self->qos, hwname);			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );			return 0;}/* * Function ali_ircc_net_close (dev) * *    Stop the device * */static int ali_ircc_net_close(struct net_device *dev){		struct ali_ircc_cb *self;	//int iobase;				IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );			IRDA_ASSERT(dev != NULL, return -1;);	self = (struct ali_ircc_cb *) dev->priv;	IRDA_ASSERT(self != NULL, return 0;);	/* Stop device */	netif_stop_queue(dev);		/* Stop and remove instance of IrLAP */	if (self->irlap)		irlap_close(self->irlap);	self->irlap = NULL;			disable_dma(self->io.dma);	/* Disable interrupts */	SetCOMInterrupts(self, FALSE);	       	free_irq(self->io.irq, dev);	free_dma(self->io.dma);	IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );			return 0;}/* * Function ali_ircc_fir_hard_xmit (skb, dev) * *    Transmit the frame * */static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev){	struct ali_ircc_cb *self;	unsigned long flags;	int iobase;	__u32 speed;	int mtt, diff;		IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );			self = (struct ali_ircc_cb *) dev->priv;	iobase = self->io.fir_base;	netif_stop_queue(dev);		/* Make sure tests *& speed change are atomic */	spin_lock_irqsave(&self->lock, flags);		/* Note : you should make sure that speed changes are not going	 * to corrupt any outgoing frame. Look at nsc-ircc for the gory	 * details - Jean II */	/* 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) {			ali_ircc_change_speed(self, speed); 			dev->trans_start = jiffies;			spin_unlock_irqrestore(&self->lock, flags);			dev_kfree_skb(skb);			return 0;		} else			self->new_speed = speed;	}	/* Register and copy this frame to DMA memory */	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++;	/* Start transmit only if there is currently no transmit going on */	if (self->tx_fifo.len == 1) 	{		/* Check if we must wait the min turn time or not */		mtt = irda_get_mtt(skb);						if (mtt) 		{			/* Check how much time we have used already */			do_gettimeofday(&self->now);						diff = self->now.tv_usec - self->stamp.tv_usec;			/* self->stamp is set from ali_ircc_dma_receive_complete() */										IRDA_DEBUG(1, "%s(), ******* diff = %d ******* \n", __FUNCTION__ , diff);							if (diff < 0) 				diff += 1000000;						/* Check if the mtt is larger than the time we have			 * already used by all the protocol processing			 */			if (mtt > diff)			{								mtt -= diff;												/* 				 * Use timer if delay larger than 1000 us, and				 * use udelay for smaller values which should				 * be acceptable				 */				if (mtt > 500) 				{					/* Adjust for timer resolution */					mtt = (mtt+250) / 500; 	/* 4 discard, 5 get advanced, Let's round off */										IRDA_DEBUG(1, "%s(), ************** mtt = %d ***********\n", __FUNCTION__ , mtt);											/* Setup timer */					if (mtt == 1) /* 500 us */					{						switch_bank(iobase, BANK1);						outb(TIMER_IIR_500, iobase+FIR_TIMER_IIR);					}						else if (mtt == 2) /* 1 ms */					{						switch_bank(iobase, BANK1);						outb(TIMER_IIR_1ms, iobase+FIR_TIMER_IIR);					}										else /* > 2ms -> 4ms */					{						switch_bank(iobase, BANK1);						outb(TIMER_IIR_2ms, iobase+FIR_TIMER_IIR);					}															/* Start timer */					outb(inb(iobase+FIR_CR) | CR_TIMER_EN, iobase+FIR_CR);					self->io.direction = IO_XMIT;										/* Enable timer interrupt */					self->ier = IER_TIMER;					SetCOMInterrupts(self, TRUE);															/* Timer will take care of the rest */					goto out; 				} 				else					udelay(mtt);			} // if (if (mtt > diff)		}// if (mtt) 						/* Enable EOM interrupt */		self->ier = IER_EOM;		SetCOMInterrupts(self, TRUE);				/* Transmit frame */		ali_ircc_dma_xmit(self);	} // if (self->tx_fifo.len == 1) 	 out: 		/* Not busy transmitting anymore if window is not full */	if (self->tx_fifo.free < MAX_TX_WINDOW)		netif_wake_queue(self->netdev);		/* Restore bank register */	switch_bank(iobase, BANK0);	dev->trans_start = jiffies;	spin_unlock_irqrestore(&self->lock, flags);	dev_kfree_skb(skb);	IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		return 0;	}static void ali_ircc_dma_xmit(struct ali_ircc_cb *self){	int iobase, tmp;	unsigned char FIFO_OPTI, Hi, Lo;			IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );			iobase = self->io.fir_base;		/* FIFO threshold , this method comes from NDIS5 code */		if(self->tx_fifo.queue[self->tx_fifo.ptr].len < TX_FIFO_Threshold)		FIFO_OPTI = self->tx_fifo.queue[self->tx_fifo.ptr].len-1;	else		FIFO_OPTI = TX_FIFO_Threshold;		/* Disable DMA */	switch_bank(iobase, BANK1);	outb(inb(iobase+FIR_CR) & ~CR_DMA_EN, iobase+FIR_CR);		self->io.direction = IO_XMIT;		irda_setup_dma(self->io.dma, 		       ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start -			self->tx_buff.head) + self->tx_buff_dma,		       self->tx_fifo.queue[self->tx_fifo.ptr].len, 		       DMA_TX_MODE);			/* Reset Tx FIFO */	switch_bank(iobase, BANK0);	outb(LCR_A_FIFO_RESET, iobase+FIR_LCR_A);		/* Set Tx FIFO threshold */	if (self->fifo_opti_buf!=FIFO_OPTI) 	{		switch_bank(iobase, BANK1);	    	outb(FIFO_OPTI, iobase+FIR_FIFO_TR) ;	    	self->fifo_opti_buf=FIFO_OPTI;	}		/* Set Tx DMA threshold */	switch_bank(iobase, BANK1);	outb(TX_DMA_Threshold, iobase+FIR_DMA_TR);		/* Set max Tx frame size */	Hi = (self->tx_fifo.queue[self->tx_fifo.ptr].len >> 8) & 0x0f;	Lo = self->tx_fifo.queue[self->tx_fifo.ptr].len & 0xff;	switch_bank(iobase, BANK2);	outb(Hi, iobase+FIR_TX_DSR_HI);	outb(Lo, iobase+FIR_TX_DSR_LO);		/* Disable SIP , Disable Brick Wall (we don't support in TX mode), Change to TX mode */	switch_bank(iobase, BANK0);		tmp = inb(iobase+FIR_LCR_B);	tmp &= ~0x20; // Disable SIP	outb(((unsigned char)(tmp & 0x3f) | LCR_B_TX_MODE) & ~LCR_B_BW, iobase+FIR_LCR_B);	IRDA_DEBUG(1, "%s(), ******* Change to TX mode: FIR_LCR_B = 0x%x ******* \n", __FUNCTION__ , inb(iobase+FIR_LCR_B));		outb(0, iobase+FIR_LSR);				/* Enable DMA and Burst Mode */	switch_bank(iobase, BANK1);	outb(inb(iobase+FIR_CR) | CR_DMA_EN | CR_DMA_BURST, iobase+FIR_CR);		switch_bank(iobase, BANK0); 		IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );}static int  ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self){	int iobase;	int ret = TRUE;		IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );			iobase = self->io.fir_base;		/* Disable DMA */	switch_bank(iobase, BANK1);	outb(inb(iobase+FIR_CR) & ~CR_DMA_EN, iobase+FIR_CR);		/* Check for underrun! */	switch_bank(iobase, BANK0);	if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT)		{		IRDA_ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __FUNCTION__);			self->stats.tx_errors++;		self->stats.tx_fifo_errors++;			}	else 	{		self->stats.tx_packets++;	}	/* Check if we need to change the speed */	if (self->new_speed) 	{		ali_ircc_change_speed(self, self->new_speed);		self->new_speed = 0;	}	/* Finished with this frame, so prepare for next */	self->tx_fifo.ptr++;	self->tx_fifo.len--;	/* Any frames to be sent back-to-back? */	if (self->tx_fifo.len) 	{		ali_ircc_dma_xmit(self);				/* Not finished yet! */		ret = FALSE;	} 	else 	{	/* 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;	}	/* Make sure we have room for more frames */	if (self->tx_fifo.free < MAX_TX_WINDOW) {		/* Not busy transmitting anymore */		/* Tell the network layer, that we can accept more frames */		netif_wake_queue(self->netdev);	}		

⌨️ 快捷键说明

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