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

📄 w83977af_ir.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			/* Move to next frame */			self->rx_buff.data += 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;		}	}	/* Restore set register */	outb(set, iobase+SSR);	return TRUE;}/* * Function pc87108_pio_receive (self) * *    Receive all data in receiver FIFO * */static void w83977af_pio_receive(struct w83977af_ir *self) {	__u8 byte = 0x00;	int iobase;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);		iobase = self->io.fir_base;		/*  Receive all characters in Rx FIFO */	do {		byte = inb(iobase+RBR);		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 				  byte);	} while (inb(iobase+USR) & USR_RDR); /* Data available */	}/* * Function w83977af_sir_interrupt (self, eir) * *    Handle SIR interrupt * */static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr){	int actual;	__u8 new_icr = 0;	__u8 set;	int iobase;	IRDA_DEBUG(4, "%s(), isr=%#x\n", __FUNCTION__ , isr);		iobase = self->io.fir_base;	/* Transmit FIFO low on data */	if (isr & ISR_TXTH_I) {		/* Write data left in transmit buffer */		actual = w83977af_pio_write(self->io.fir_base, 					    self->tx_buff.data, 					    self->tx_buff.len, 					    self->io.fifo_size);		self->tx_buff.data += actual;		self->tx_buff.len  -= actual;				self->io.direction = IO_XMIT;		/* Check if finished */		if (self->tx_buff.len > 0) {			new_icr |= ICR_ETXTHI;		} else {			set = inb(iobase+SSR);			switch_bank(iobase, SET0);			outb(AUDR_SFEND, iobase+AUDR);			outb(set, iobase+SSR); 			self->stats.tx_packets++;			/* Feed me more packets */			netif_wake_queue(self->netdev);			new_icr |= ICR_ETBREI;		}	}	/* Check if transmission has completed */	if (isr & ISR_TXEMP_I) {				/* Check if we need to change the speed? */		if (self->new_speed) {			IRDA_DEBUG(2,				   "%s(), Changing speed!\n", __FUNCTION__ );			w83977af_change_speed(self, self->new_speed);			self->new_speed = 0;		}		/* Turn around and get ready to receive some data */		self->io.direction = IO_RECV;		new_icr |= ICR_ERBRI;	}	/* Rx FIFO threshold or timeout */	if (isr & ISR_RXTH_I) {		w83977af_pio_receive(self);		/* Keep receiving */		new_icr |= ICR_ERBRI;	}	return new_icr;}/* * Function pc87108_fir_interrupt (self, eir) * *    Handle MIR/FIR interrupt * */static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr){	__u8 new_icr = 0;	__u8 set;	int iobase;	iobase = self->io.fir_base;	set = inb(iobase+SSR);		/* End of frame detected in FIFO */	if (isr & (ISR_FEND_I|ISR_FSF_I)) {		if (w83977af_dma_receive_complete(self)) {						/* Wait for next status FIFO interrupt */			new_icr |= ICR_EFSFI;		} else {			/* DMA not finished yet */			/* Set timer value, resolution 1 ms */			switch_bank(iobase, SET4);			outb(0x01, iobase+TMRL); /* 1 ms */			outb(0x00, iobase+TMRH);			/* Start timer */			outb(IR_MSL_EN_TMR, iobase+IR_MSL);			new_icr |= ICR_ETMRI;		}	}	/* Timer finished */	if (isr & ISR_TMR_I) {		/* Disable timer */		switch_bank(iobase, SET4);		outb(0, iobase+IR_MSL);		/* Clear timer event */		/* switch_bank(iobase, SET0); *//* 		outb(ASCR_CTE, iobase+ASCR); */		/* Check if this is a TX timer interrupt */		if (self->io.direction == IO_XMIT) {			w83977af_dma_write(self, iobase);			new_icr |= ICR_EDMAI;		} else {			/* Check if DMA has now finished */			w83977af_dma_receive_complete(self);			new_icr |= ICR_EFSFI;		}	}		/* Finished with DMA */	if (isr & ISR_DMA_I) {		w83977af_dma_xmit_complete(self);		/* Check if there are more frames to be transmitted */		/* if (irda_device_txqueue_empty(self)) { */				/* Prepare for receive 		 * 		 * ** Netwinder Tx DMA likes that we do this anyway **		 */		w83977af_dma_receive(self);		new_icr = ICR_EFSFI;	       /* } */	}		/* Restore set */	outb(set, iobase+SSR);	return new_icr;}/* * Function w83977af_interrupt (irq, dev_id, regs) * *    An interrupt from the chip has arrived. Time to do some work * */static irqreturn_t w83977af_interrupt(int irq, void *dev_id){	struct net_device *dev = dev_id;	struct w83977af_ir *self;	__u8 set, icr, isr;	int iobase;	self = dev->priv;	iobase = self->io.fir_base;	/* Save current bank */	set = inb(iobase+SSR);	switch_bank(iobase, SET0);		icr = inb(iobase+ICR); 	isr = inb(iobase+ISR) & icr; /* Mask out the interesting ones */ 	outb(0, iobase+ICR); /* Disable interrupts */		if (isr) {		/* Dispatch interrupt handler for the current speed */		if (self->io.speed > PIO_MAX_SPEED )			icr = w83977af_fir_interrupt(self, isr);		else			icr = w83977af_sir_interrupt(self, isr);	}	outb(icr, iobase+ICR);    /* Restore (new) interrupts */	outb(set, iobase+SSR);    /* Restore bank register */	return IRQ_RETVAL(isr);}/* * Function w83977af_is_receiving (self) * *    Return TRUE is we are currently receiving a frame * */static int w83977af_is_receiving(struct w83977af_ir *self){	int status = FALSE;	int iobase;	__u8 set;	IRDA_ASSERT(self != NULL, return FALSE;);	if (self->io.speed > 115200) {		iobase = self->io.fir_base;		/* Check if rx FIFO is not empty */		set = inb(iobase+SSR);		switch_bank(iobase, SET2);		if ((inb(iobase+RXFDTH) & 0x3f) != 0) {			/* We are receiving something */			status =  TRUE;		}		outb(set, iobase+SSR);	} else 		status = (self->rx_buff.state != OUTSIDE_FRAME);		return status;}/* * Function w83977af_net_open (dev) * *    Start the device * */static int w83977af_net_open(struct net_device *dev){	struct w83977af_ir *self;	int iobase;	char hwname[32];	__u8 set;		IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );		IRDA_ASSERT(dev != NULL, return -1;);	self = (struct w83977af_ir *) dev->priv;		IRDA_ASSERT(self != NULL, return 0;);		iobase = self->io.fir_base;	if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, 			(void *) dev)) {		return -EAGAIN;	}	/*	 * Always allocate the DMA channel after the IRQ,	 * and clean up on failure.	 */	if (request_dma(self->io.dma, dev->name)) {		free_irq(self->io.irq, self);		return -EAGAIN;	}			/* Save current set */	set = inb(iobase+SSR); 	/* Enable some interrupts so we can receive frames again */ 	switch_bank(iobase, SET0); 	if (self->io.speed > 115200) { 		outb(ICR_EFSFI, iobase+ICR); 		w83977af_dma_receive(self); 	} else 		outb(ICR_ERBRI, iobase+ICR);	/* Restore bank register */	outb(set, iobase+SSR);	/* Ready to play! */	netif_start_queue(dev);		/* Give self a hardware name */	sprintf(hwname, "w83977af @ 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);	return 0;}/* * Function w83977af_net_close (dev) * *    Stop the device * */static int w83977af_net_close(struct net_device *dev){	struct w83977af_ir *self;	int iobase;	__u8 set;	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(dev != NULL, return -1;);		self = (struct w83977af_ir *) dev->priv;		IRDA_ASSERT(self != NULL, return 0;);		iobase = self->io.fir_base;	/* 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);	/* Save current set */	set = inb(iobase+SSR);		/* Disable interrupts */	switch_bank(iobase, SET0);	outb(0, iobase+ICR); 	free_irq(self->io.irq, dev);	free_dma(self->io.dma);	/* Restore bank register */	outb(set, iobase+SSR);	return 0;}/* * Function w83977af_net_ioctl (dev, rq, cmd) * *    Process IOCTL commands for this device * */static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct if_irda_req *irq = (struct if_irda_req *) rq;	struct w83977af_ir *self;	unsigned long flags;	int ret = 0;	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);		spin_lock_irqsave(&self->lock, flags);	switch (cmd) {	case SIOCSBANDWIDTH: /* Set bandwidth */		if (!capable(CAP_NET_ADMIN)) {			ret = -EPERM;			goto out;		}		w83977af_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 = w83977af_is_receiving(self);		break;	default:		ret = -EOPNOTSUPP;	}out:	spin_unlock_irqrestore(&self->lock, flags);	return ret;}static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev){	struct w83977af_ir *self = (struct w83977af_ir *) dev->priv;		return &self->stats;}MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");MODULE_LICENSE("GPL");module_param(qos_mtt_bits, int, 0);MODULE_PARM_DESC(qos_mtt_bits, "Mimimum Turn Time");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");/* * Function init_module (void) * *     * */module_init(w83977af_init);/* * Function cleanup_module (void) * *     * */module_exit(w83977af_cleanup);

⌨️ 快捷键说明

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