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

📄 w83977af_ir.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	/* Set speed mode */	switch_bank(iobase, SET0);	outb(ir_mode, iobase+HCR);	/* set FIFO size to 32 */	switch_bank(iobase, SET2);	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);			/* set FIFO threshold to TX17, RX16 */	switch_bank(iobase, SET0);	outb(0x00, iobase+UFR);        /* Reset */	outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */	outb(0xa7, iobase+UFR);	netif_wake_queue(self->netdev);			/* Enable some interrupts so we can receive frames */	switch_bank(iobase, SET0);	if (speed > PIO_MAX_SPEED) {		outb(ICR_EFSFI, iobase+ICR);		w83977af_dma_receive(self);	} else		outb(ICR_ERBRI, iobase+ICR);    		/* Restore SSR */	outb(set, iobase+SSR);}/* * Function w83977af_hard_xmit (skb, dev) * *    Sets up a DMA transfer to send the current frame. * */int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev){	struct w83977af_ir *self;	__s32 speed;	int iobase;	__u8 set;	int mtt;		self = (struct w83977af_ir *) dev->priv;	iobase = self->io.fir_base;	IRDA_DEBUG(4, "%s(%ld), skb->len=%d\n", __FUNCTION__ , jiffies, 		   (int) skb->len);		/* Lock transmit buffer */	netif_stop_queue(dev);		/* 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) {			w83977af_change_speed(self, speed); 			dev->trans_start = jiffies;			dev_kfree_skb(skb);			return 0;		} else			self->new_speed = speed;	}	/* Save current set */	set = inb(iobase+SSR);		/* Decide if we should use PIO or DMA transfer */	if (self->io.speed > PIO_MAX_SPEED) {		self->tx_buff.data = self->tx_buff.head;		memcpy(self->tx_buff.data, skb->data, skb->len);		self->tx_buff.len = skb->len;				mtt = irda_get_mtt(skb);#ifdef CONFIG_USE_INTERNAL_TIMER	        if (mtt > 50) {			/* Adjust for timer resolution */			mtt /= 1000+1;			/* Setup timer */			switch_bank(iobase, SET4);			outb(mtt & 0xff, iobase+TMRL);			outb((mtt >> 8) & 0x0f, iobase+TMRH);						/* Start timer */			outb(IR_MSL_EN_TMR, iobase+IR_MSL);			self->io.direction = IO_XMIT;						/* Enable timer interrupt */			switch_bank(iobase, SET0);			outb(ICR_ETMRI, iobase+ICR);		} else {#endif			IRDA_DEBUG(4, "%s(%ld), mtt=%d\n", __FUNCTION__ , jiffies, mtt);			if (mtt)				udelay(mtt);			/* Enable DMA interrupt */			switch_bank(iobase, SET0);	 		outb(ICR_EDMAI, iobase+ICR);	     		w83977af_dma_write(self, iobase);#ifdef CONFIG_USE_INTERNAL_TIMER		}#endif	} else {		self->tx_buff.data = self->tx_buff.head;		self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 						   self->tx_buff.truesize);				/* Add interrupt on tx low level (will fire immediately) */		switch_bank(iobase, SET0);		outb(ICR_ETXTHI, iobase+ICR);	}	dev->trans_start = jiffies;	dev_kfree_skb(skb);	/* Restore set register */	outb(set, iobase+SSR);	return 0;}/* * Function w83977af_dma_write (self, iobase) * *    Send frame using DMA * */static void w83977af_dma_write(struct w83977af_ir *self, int iobase){	__u8 set;#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS	unsigned long flags;	__u8 hcr;#endif        IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__ , self->tx_buff.len);	/* Save current set */	set = inb(iobase+SSR);	/* Disable DMA */	switch_bank(iobase, SET0);	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);	/* Choose transmit DMA channel  */ 	switch_bank(iobase, SET2);	outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS	spin_lock_irqsave(&self->lock, flags);	disable_dma(self->io.dma);	clear_dma_ff(self->io.dma);	set_dma_mode(self->io.dma, DMA_MODE_READ);	set_dma_addr(self->io.dma, self->tx_buff_dma);	set_dma_count(self->io.dma, self->tx_buff.len);#else	irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,		       DMA_MODE_WRITE);	#endif	self->io.direction = IO_XMIT;		/* Enable DMA */ 	switch_bank(iobase, SET0);#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS	hcr = inb(iobase+HCR);	outb(hcr | HCR_EN_DMA, iobase+HCR);	enable_dma(self->io.dma);	spin_unlock_irqrestore(&self->lock, flags);#else		outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);#endif	/* Restore set register */	outb(set, iobase+SSR);}/* * Function w83977af_pio_write (iobase, buf, len, fifo_size) * *     * */static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size){	int actual = 0;	__u8 set;		IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	/* Save current bank */	set = inb(iobase+SSR);	switch_bank(iobase, SET0);	if (!(inb_p(iobase+USR) & USR_TSRE)) {		IRDA_DEBUG(4,			   "%s(), warning, FIFO not empty yet!\n", __FUNCTION__  );		fifo_size -= 17;		IRDA_DEBUG(4, "%s(), %d bytes left in tx fifo\n", 			   __FUNCTION__ , fifo_size);	}	/* Fill FIFO with current frame */	while ((fifo_size-- > 0) && (actual < len)) {		/* Transmit next byte */		outb(buf[actual++], iobase+TBR);	}        	IRDA_DEBUG(4, "%s(), fifo_size %d ; %d sent of %d\n", 		   __FUNCTION__ , fifo_size, actual, len);	/* Restore bank */	outb(set, iobase+SSR);	return actual;}/* * Function w83977af_dma_xmit_complete (self) * *    The transfer of a frame in finished. So do the necessary things * *     */static void w83977af_dma_xmit_complete(struct w83977af_ir *self){	int iobase;	__u8 set;	IRDA_DEBUG(4, "%s(%ld)\n", __FUNCTION__ , jiffies);	IRDA_ASSERT(self != NULL, return;);	iobase = self->io.fir_base;	/* Save current set */	set = inb(iobase+SSR);	/* Disable DMA */	switch_bank(iobase, SET0);	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);		/* Check for underrrun! */	if (inb(iobase+AUDR) & AUDR_UNDR) {		IRDA_DEBUG(0, "%s(), Transmit underrun!\n", __FUNCTION__ );				self->stats.tx_errors++;		self->stats.tx_fifo_errors++;		/* Clear bit, by writing 1 to it */		outb(AUDR_UNDR, iobase+AUDR);	} else		self->stats.tx_packets++;		if (self->new_speed) {		w83977af_change_speed(self, self->new_speed);		self->new_speed = 0;	}	/* Unlock tx_buff and request another frame */	/* Tell the network layer, that we want more frames */	netif_wake_queue(self->netdev);		/* Restore set */	outb(set, iobase+SSR);}/* * Function w83977af_dma_receive (self) * *    Get ready for receiving a frame. The device will initiate a DMA *    if it starts to receive a frame. * */int w83977af_dma_receive(struct w83977af_ir *self) {	int iobase;	__u8 set;#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS	unsigned long flags;	__u8 hcr;#endif	IRDA_ASSERT(self != NULL, return -1;);	IRDA_DEBUG(4, "%s\n", __FUNCTION__ );	iobase= self->io.fir_base;	/* Save current set */	set = inb(iobase+SSR);	/* Disable DMA */	switch_bank(iobase, SET0);	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);	/* Choose DMA Rx, DMA Fairness, and Advanced mode */	switch_bank(iobase, SET2);	outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,	     iobase+ADCR1);	self->io.direction = IO_RECV;	self->rx_buff.data = self->rx_buff.head;#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS	spin_lock_irqsave(&self->lock, flags);	disable_dma(self->io.dma);	clear_dma_ff(self->io.dma);	set_dma_mode(self->io.dma, DMA_MODE_READ);	set_dma_addr(self->io.dma, self->rx_buff_dma);	set_dma_count(self->io.dma, self->rx_buff.truesize);#else	irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize,		       DMA_MODE_READ);#endif	/* 	 * Reset Rx FIFO. This will also flush the ST_FIFO, it's very 	 * important that we don't reset the Tx FIFO since it might not	 * be finished transmitting yet	 */	switch_bank(iobase, SET0);	outb(UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;		/* Enable DMA */	switch_bank(iobase, SET0);#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS	hcr = inb(iobase+HCR);	outb(hcr | HCR_EN_DMA, iobase+HCR);	enable_dma(self->io.dma);	spin_unlock_irqrestore(&self->lock, flags);#else		outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);#endif	/* Restore set */	outb(set, iobase+SSR);	return 0;}/* * Function w83977af_receive_complete (self) * *    Finished with receiving a frame * */int w83977af_dma_receive_complete(struct w83977af_ir *self){	struct sk_buff *skb;	struct st_fifo *st_fifo;	int len;	int iobase;	__u8 set;	__u8 status;	IRDA_DEBUG(4, "%s\n", __FUNCTION__ );	st_fifo = &self->st_fifo;	iobase = self->io.fir_base;	/* Save current set */	set = inb(iobase+SSR);		iobase = self->io.fir_base;	/* Read status FIFO */	switch_bank(iobase, SET5);	while ((status = inb(iobase+FS_FO)) & FS_FO_FSFDR) {		st_fifo->entries[st_fifo->tail].status = status;				st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;				st_fifo->tail++;		st_fifo->len++;	}		while (st_fifo->len) {		/* Get first entry */		status = st_fifo->entries[st_fifo->head].status;		len    = st_fifo->entries[st_fifo->head].len;		st_fifo->head++;		st_fifo->len--;		/* Check for errors */		if (status & FS_FO_ERR_MSK) {			if (status & FS_FO_LST_FR) {				/* Add number of lost frames to stats */				self->stats.rx_errors += len;				} else {				/* Skip frame */				self->stats.rx_errors++;								self->rx_buff.data += len;								if (status & FS_FO_MX_LEX)					self->stats.rx_length_errors++;								if (status & FS_FO_PHY_ERR) 					self->stats.rx_frame_errors++;								if (status & FS_FO_CRC_ERR) 					self->stats.rx_crc_errors++;			}			/* The errors below can be reported in both cases */			if (status & FS_FO_RX_OV)				self->stats.rx_fifo_errors++;						if (status & FS_FO_FSF_OV)				self->stats.rx_fifo_errors++;					} else {			/* Check if we have transferred all data to memory */			switch_bank(iobase, SET0);			if (inb(iobase+USR) & USR_RDR) {#ifdef CONFIG_USE_INTERNAL_TIMER				/* Put this entry back in fifo */				st_fifo->head--;				st_fifo->len++;				st_fifo->entries[st_fifo->head].status = status;				st_fifo->entries[st_fifo->head].len = len;								/* Restore set register */				outb(set, iobase+SSR);							return FALSE; 	/* I'll be back! */#else				udelay(80); /* Should be enough!? */#endif			}									skb = dev_alloc_skb(len+1);			if (skb == NULL)  {				printk(KERN_INFO				       "%s(), memory squeeze, dropping frame.\n", __FUNCTION__);				/* Restore set register */				outb(set, iobase+SSR);				return FALSE;			}						/*  Align to 20 bytes */			skb_reserve(skb, 1); 						/* Copy frame without CRC */			if (self->io.speed < 4000000) {				skb_put(skb, len-2);				memcpy(skb->data, self->rx_buff.data, len-2);			} else {				skb_put(skb, len-4);				memcpy(skb->data, self->rx_buff.data, len-4);			}

⌨️ 快捷键说明

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