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

📄 ali-ircc.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	switch_bank(iobase, BANK0); 		IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		return ret;}/* * Function ali_ircc_dma_receive (self) * *    Get ready for receiving a frame. The device will initiate a DMA *    if it starts to receive a frame. * */static int ali_ircc_dma_receive(struct ali_ircc_cb *self) {	int iobase, tmp;		IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );			iobase = self->io.fir_base;		/* 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;			/* Disable DMA */	switch_bank(iobase, BANK1);	outb(inb(iobase+FIR_CR) & ~CR_DMA_EN, iobase+FIR_CR);		/* Reset Message Count */	switch_bank(iobase, BANK0);	outb(0x07, iobase+FIR_LSR);			self->rcvFramesOverflow = FALSE;			self->LineStatus = inb(iobase+FIR_LSR) ;		/* Reset Rx FIFO info */	self->io.direction = IO_RECV;	self->rx_buff.data = self->rx_buff.head;			/* Reset Rx FIFO */	// switch_bank(iobase, BANK0);	outb(LCR_A_FIFO_RESET, iobase+FIR_LCR_A); 		self->st_fifo.len = self->st_fifo.pending_bytes = 0;	self->st_fifo.tail = self->st_fifo.head = 0;			irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,		       DMA_RX_MODE);	 	/* Set Receive Mode,Brick Wall */	//switch_bank(iobase, BANK0);	tmp = inb(iobase+FIR_LCR_B);	outb((unsigned char)(tmp &0x3f) | LCR_B_RX_MODE | LCR_B_BW , iobase + FIR_LCR_B); // 2000/12/1 05:16PM	IRDA_DEBUG(1, "%s(), *** Change To RX mode: FIR_LCR_B = 0x%x *** \n", __FUNCTION__ , inb(iobase+FIR_LCR_B));				/* Set Rx Threshold */	switch_bank(iobase, BANK1);	outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR);	outb(RX_DMA_Threshold, iobase+FIR_DMA_TR);			/* Enable DMA and Burst Mode */	// switch_bank(iobase, BANK1);	outb(CR_DMA_EN | CR_DMA_BURST, iobase+FIR_CR);					switch_bank(iobase, BANK0); 	IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		return 0;}static int  ali_ircc_dma_receive_complete(struct ali_ircc_cb *self){	struct st_fifo *st_fifo;	struct sk_buff *skb;	__u8 status, MessageCount;	int len, i, iobase, val;		IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );		st_fifo = &self->st_fifo;			iobase = self->io.fir_base;				switch_bank(iobase, BANK0);	MessageCount = inb(iobase+ FIR_LSR)&0x07;		if (MessageCount > 0)			IRDA_DEBUG(0, "%s(), Messsage count = %d,\n", __FUNCTION__ , MessageCount);				for (i=0; i<=MessageCount; i++)	{		/* Bank 0 */		switch_bank(iobase, BANK0);		status = inb(iobase+FIR_LSR);				switch_bank(iobase, BANK2);		len = inb(iobase+FIR_RX_DSR_HI) & 0x0f;		len = len << 8; 		len |= inb(iobase+FIR_RX_DSR_LO);				IRDA_DEBUG(1, "%s(), RX Length = 0x%.2x,\n", __FUNCTION__ , len);			IRDA_DEBUG(1, "%s(), RX Status = 0x%.2x,\n", __FUNCTION__ , status);				if (st_fifo->tail >= MAX_RX_WINDOW) {			IRDA_DEBUG(0, "%s(), window is full!\n", __FUNCTION__ );			continue;		}					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++;	}				for (i=0; i<=MessageCount; i++)	{			/* Get first entry */		status = st_fifo->entries[st_fifo->head].status;		len    = st_fifo->entries[st_fifo->head].len;		st_fifo->pending_bytes -= len;		st_fifo->head++;		st_fifo->len--;							/* Check for errors */		if ((status & 0xd8) || self->rcvFramesOverflow || (len==0)) 				{			IRDA_DEBUG(0,"%s(), ************* RX Errors ************ \n", __FUNCTION__ );							/* Skip frame */			self->stats.rx_errors++;						self->rx_buff.data += len;						if (status & LSR_FIFO_UR) 			{				self->stats.rx_frame_errors++;				IRDA_DEBUG(0,"%s(), ************* FIFO Errors ************ \n", __FUNCTION__ );			}				if (status & LSR_FRAME_ERROR)			{				self->stats.rx_frame_errors++;				IRDA_DEBUG(0,"%s(), ************* FRAME Errors ************ \n", __FUNCTION__ );			}										if (status & LSR_CRC_ERROR) 			{				self->stats.rx_crc_errors++;				IRDA_DEBUG(0,"%s(), ************* CRC Errors ************ \n", __FUNCTION__ );			}						if(self->rcvFramesOverflow)			{				self->stats.rx_frame_errors++;				IRDA_DEBUG(0,"%s(), ************* Overran DMA buffer ************ \n", __FUNCTION__ );											}			if(len == 0)			{				self->stats.rx_frame_errors++;				IRDA_DEBUG(0,"%s(), ********** Receive Frame Size = 0 ********* \n", __FUNCTION__ );			}		}	 		else 		{						if (st_fifo->pending_bytes < 32) 			{				switch_bank(iobase, BANK0);				val = inb(iobase+FIR_BSR);					if ((val& BSR_FIFO_NOT_EMPTY)== 0x80) 				{					IRDA_DEBUG(0, "%s(), ************* BSR_FIFO_NOT_EMPTY ************ \n", __FUNCTION__ );										/* Put this entry back in fifo */					st_fifo->head--;					st_fifo->len++;					st_fifo->pending_bytes += len;					st_fifo->entries[st_fifo->head].status = status;					st_fifo->entries[st_fifo->head].len = len;											/*  		 			* DMA not finished yet, so try again 		 			* later, set timer value, resolution 		 			* 500 us 		 			*/					 					switch_bank(iobase, BANK1);					outb(TIMER_IIR_500, iobase+FIR_TIMER_IIR); // 2001/1/2 05:07PM										/* Enable Timer */					outb(inb(iobase+FIR_CR) | CR_TIMER_EN, iobase+FIR_CR);											return FALSE; /* I'll be back! */				}			}								/* 			 * Remember the time we received this frame, so we can			 * reduce the min turn time a bit since we will know			 * how much time we have used for protocol processing			 */			do_gettimeofday(&self->stamp);			skb = dev_alloc_skb(len+1);			if (skb == NULL)  			{				IRDA_WARNING("%s(), memory squeeze, "					     "dropping frame.\n",					     __FUNCTION__);				self->stats.rx_dropped++;				return FALSE;			}						/* Make sure IP header gets aligned */			skb_reserve(skb, 1); 						/* Copy frame without CRC, CRC is removed by hardware*/			skb_put(skb, len);			memcpy(skb->data, self->rx_buff.data, len);			/* 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);			self->netdev->last_rx = jiffies;		}	}		switch_bank(iobase, BANK0);				IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		return TRUE;}/* * Function ali_ircc_sir_hard_xmit (skb, dev) * *    Transmit the frame! * */static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev){	struct ali_ircc_cb *self;	unsigned long flags;	int iobase;	__u32 speed;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		IRDA_ASSERT(dev != NULL, return 0;);		self = (struct ali_ircc_cb *) dev->priv;	IRDA_ASSERT(self != NULL, return 0;);	iobase = self->io.sir_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;	}	/* Init tx buffer */	self->tx_buff.data = self->tx_buff.head;        /* Copy skb to tx_buff while wrapping, stuffing and making CRC */	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 					   self->tx_buff.truesize);		self->stats.tx_bytes += self->tx_buff.len;	/* Turn on transmit finished interrupt. Will fire immediately!  */	outb(UART_IER_THRI, iobase+UART_IER); 	dev->trans_start = jiffies;	spin_unlock_irqrestore(&self->lock, flags);	dev_kfree_skb(skb);		IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );			return 0;	}/* * Function ali_ircc_net_ioctl (dev, rq, cmd) * *    Process IOCTL commands for this device * */static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct if_irda_req *irq = (struct if_irda_req *) rq;	struct ali_ircc_cb *self;	unsigned long flags;	int ret = 0;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		IRDA_ASSERT(dev != NULL, return -1;);	self = dev->priv;	IRDA_ASSERT(self != NULL, return -1;);	IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__ , dev->name, cmd);		switch (cmd) {	case SIOCSBANDWIDTH: /* Set bandwidth */		IRDA_DEBUG(1, "%s(), SIOCSBANDWIDTH\n", __FUNCTION__ );		/*		 * This function will also be used by IrLAP to change the		 * speed, so we still must allow for speed change within		 * interrupt context.		 */		if (!in_interrupt() && !capable(CAP_NET_ADMIN))			return -EPERM;				spin_lock_irqsave(&self->lock, flags);		ali_ircc_change_speed(self, irq->ifr_baudrate);				spin_unlock_irqrestore(&self->lock, flags);		break;	case SIOCSMEDIABUSY: /* Set media busy */		IRDA_DEBUG(1, "%s(), SIOCSMEDIABUSY\n", __FUNCTION__ );		if (!capable(CAP_NET_ADMIN))			return -EPERM;		irda_device_set_media_busy(self->netdev, TRUE);		break;	case SIOCGRECEIVING: /* Check if we are receiving right now */		IRDA_DEBUG(2, "%s(), SIOCGRECEIVING\n", __FUNCTION__ );		/* This is protected */		irq->ifr_receiving = ali_ircc_is_receiving(self);		break;	default:		ret = -EOPNOTSUPP;	}		IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );			return ret;}/* * Function ali_ircc_is_receiving (self) * *    Return TRUE is we are currently receiving a frame * */static int ali_ircc_is_receiving(struct ali_ircc_cb *self){	unsigned long flags;	int status = FALSE;	int iobase;				IRDA_DEBUG(2, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );		IRDA_ASSERT(self != NULL, return FALSE;);	spin_lock_irqsave(&self->lock, flags);	if (self->io.speed > 115200) 	{		iobase = self->io.fir_base;				switch_bank(iobase, BANK1);		if((inb(iobase+FIR_FIFO_FR) & 0x3f) != 0) 				{			/* We are receiving something */			IRDA_DEBUG(1, "%s(), We are receiving something\n", __FUNCTION__ );			status = TRUE;		}		switch_bank(iobase, BANK0);			} 	else	{ 		status = (self->rx_buff.state != OUTSIDE_FRAME);	}		spin_unlock_irqrestore(&self->lock, flags);		IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );		return status;}static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev){	struct ali_ircc_cb *self = (struct ali_ircc_cb *) dev->priv;		IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );			return &self->stats;}static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state){	struct ali_ircc_cb *self = platform_get_drvdata(dev);		IRDA_MESSAGE("%s, Suspending\n", ALI_IRCC_DRIVER_NAME);	if (self->io.suspended)		return 0;	ali_ircc_net_close(self->netdev);	self->io.suspended = 1;		return 0;}static int ali_ircc_resume(struct platform_device *dev){	struct ali_ircc_cb *self = platform_get_drvdata(dev);		if (!self->io.suspended)		return 0;		ali_ircc_net_open(self->netdev);		IRDA_MESSAGE("%s, Waking up\n", ALI_IRCC_DRIVER_NAME);	self->io.suspended = 0;	return 0;}/* ALi Chip Function */static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable){		unsigned char newMask;		int iobase = self->io.fir_base; /* or sir_base */	IRDA_DEBUG(2, "%s(), -------- Start -------- ( Enable = %d )\n", __FUNCTION__ , enable);			/* Enable the interrupt which we wish to */	if (enable){		if (self->io.direction == IO_XMIT)		{			if (self->io.speed > 115200) /* FIR, MIR */			{				newMask = self->ier;			}			else /* SIR */			{				newMask = UART_IER_THRI | UART_IER_RDI;			}		}		else {			if (self->io.speed > 115200) /* FIR, MIR */			{				newMask = self->ier;			}			else /* SIR */			{				newMask = UART_IER_RDI;			}		}	}	else /* Disable all the interrupts */	{		newMask = 0x00;	}	//SIR and FIR has different registers	if (self->io.speed > 115200)	{			switch_bank(iobase, BANK0);		outb(newMask, iobase+FIR_IER);	}	else		outb(newMask, iobase+UART_IER);			IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}static void SIR2FIR(int iobase){	//unsigned char tmp;			IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		/* Already protected (change_speed() or setup()), no need to lock.	 * Jean II */		outb(0x28, iobase+UART_MCR);	outb(0x68, iobase+UART_MCR);	outb(0x88, iobase+UART_MCR);				outb(0x60, iobase+FIR_MCR); 	/*  Master Reset */	outb(0x20, iobase+FIR_MCR); 	/*  Master Interrupt Enable */		//tmp = inb(iobase+FIR_LCR_B);	/* SIP enable */	//tmp |= 0x20;	//outb(tmp, iobase+FIR_LCR_B);			IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	}static void FIR2SIR(int iobase){	unsigned char val;		IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );		/* Already protected (change_speed() or setup()), no need to lock.	 * Jean II */		outb(0x20, iobase+FIR_MCR); 	/* IRQ to low */	outb(0x00, iobase+UART_IER); 				outb(0xA0, iobase+FIR_MCR); 	/* Don't set master reset */	outb(0x00, iobase+UART_FCR);	outb(0x07, iobase+UART_FCR);				val = inb(iobase+UART_RX);	val = inb(iobase+UART_LSR);	val = inb(iobase+UART_MSR);		IRDA_DEBUG(1, "%s(), ----------------- End ------------------\n", __FUNCTION__ );}MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>");MODULE_DESCRIPTION("ALi FIR Controller Driver");MODULE_LICENSE("GPL");module_param_array(io, int, NULL, 0);MODULE_PARM_DESC(io, "Base I/O addresses");module_param_array(irq, int, NULL, 0);MODULE_PARM_DESC(irq, "IRQ lines");module_param_array(dma, int, NULL, 0);MODULE_PARM_DESC(dma, "DMA channels");module_init(ali_ircc_init);module_exit(ali_ircc_cleanup);

⌨️ 快捷键说明

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