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

📄 smsc-ircc2.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED;	if (irq < 255) {		if (irq != chip_irq)			IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",				     driver_name, chip_irq, irq);		self->io.irq = irq;	} else		self->io.irq = chip_irq;	if (dma < 255) {		if (dma != chip_dma)			IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",				     driver_name, chip_dma, dma);		self->io.dma = dma;	} else		self->io.dma = chip_dma;}/* * Function smsc_ircc_setup_qos(self) * *    Setup qos * */static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self){	/* Initialize QoS for this device */	irda_init_max_qos_capabilies(&self->qos);	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);	self->qos.min_turn_time.bits = SMSC_IRCC2_MIN_TURN_TIME;	self->qos.window_size.bits = SMSC_IRCC2_WINDOW_SIZE;	irda_qos_bits_to_value(&self->qos);}/* * Function smsc_ircc_init_chip(self) * *    Init chip * */static void smsc_ircc_init_chip(struct smsc_ircc_cb *self){	int iobase, ir_mode, ctrl, fast;	IRDA_ASSERT(self != NULL, return;);	iobase = self->io.fir_base;	ir_mode = IRCC_CFGA_IRDA_SIR_A;	ctrl = 0;	fast = 0;	register_bank(iobase, 0);	outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);	outb(0x00, iobase + IRCC_MASTER);	register_bank(iobase, 1);	outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode),	     iobase + IRCC_SCE_CFGA);#ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */	outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),	     iobase + IRCC_SCE_CFGB);#else	outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),	     iobase + IRCC_SCE_CFGB);#endif	(void) inb(iobase + IRCC_FIFO_THRESHOLD);	outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD);	register_bank(iobase, 4);	outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL);	register_bank(iobase, 0);	outb(fast, iobase + IRCC_LCR_A);	smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);	/* Power on device */	outb(0x00, iobase + IRCC_MASTER);}/* * Function smsc_ircc_net_ioctl (dev, rq, cmd) * *    Process IOCTL commands for this device * */static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct if_irda_req *irq = (struct if_irda_req *) rq;	struct smsc_ircc_cb *self;	unsigned long flags;	int ret = 0;	IRDA_ASSERT(dev != NULL, return -1;);	self = netdev_priv(dev);	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 */		if (!capable(CAP_NET_ADMIN))			ret = -EPERM;                else {			/* Make sure we are the only one touching			 * self->io.speed and the hardware - Jean II */			spin_lock_irqsave(&self->lock, flags);			smsc_ircc_change_speed(self, irq->ifr_baudrate);			spin_unlock_irqrestore(&self->lock, flags);		}		break;	case SIOCSMEDIABUSY: /* Set media busy */		if (!capable(CAP_NET_ADMIN)) {			ret = -EPERM;			break;		}		irda_device_set_media_busy(self->netdev, TRUE);		break;	case SIOCGRECEIVING: /* Check if we are receiving right now */		irq->ifr_receiving = smsc_ircc_is_receiving(self);		break;	#if 0	case SIOCSDTRRTS:		if (!capable(CAP_NET_ADMIN)) {			ret = -EPERM;			break;		}		smsc_ircc_sir_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);		break;	#endif	default:		ret = -EOPNOTSUPP;	}	return ret;}static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev){	struct smsc_ircc_cb *self = netdev_priv(dev);	return &self->stats;}#if SMSC_IRCC2_C_NET_TIMEOUT/* * Function smsc_ircc_timeout (struct net_device *dev) * *    The networking timeout management. * */static void smsc_ircc_timeout(struct net_device *dev){	struct smsc_ircc_cb *self = netdev_priv(dev);	unsigned long flags;	IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n",		     dev->name, self->io.speed);	spin_lock_irqsave(&self->lock, flags);	smsc_ircc_sir_start(self);	smsc_ircc_change_speed(self, self->io.speed);	dev->trans_start = jiffies;	netif_wake_queue(dev);	spin_unlock_irqrestore(&self->lock, flags);}#endif/* * Function smsc_ircc_hard_xmit_sir (struct sk_buff *skb, struct net_device *dev) * *    Transmits the current frame until FIFO is full, then *    waits until the next transmit interrupt, and continues until the *    frame is transmitted. */int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev){	struct smsc_ircc_cb *self;	unsigned long flags;	s32 speed;	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	IRDA_ASSERT(dev != NULL, return 0;);	self = netdev_priv(dev);	IRDA_ASSERT(self != NULL, return 0;);	netif_stop_queue(dev);	/* Make sure test of self->io.speed & speed change are atomic */	spin_lock_irqsave(&self->lock, flags);	/* 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) {			/*			 * We send frames one by one in SIR mode (no			 * pipelining), so at this point, if we were sending			 * a previous frame, we just received the interrupt			 * telling us it is finished (UART_IIR_THRI).			 * Therefore, waiting for the transmitter to really			 * finish draining the fifo won't take too long.			 * And the interrupt handler is not expected to run.			 * - Jean II */			smsc_ircc_sir_wait_hw_transmitter_finish(self);			smsc_ircc_change_speed(self, speed);			spin_unlock_irqrestore(&self->lock, flags);			dev_kfree_skb(skb);			return 0;		}		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, self->io.sir_base + UART_IER);	spin_unlock_irqrestore(&self->lock, flags);	dev_kfree_skb(skb);	return 0;}/* * Function smsc_ircc_set_fir_speed (self, baud) * *    Change the speed of the device * */static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed){	int fir_base, ir_mode, ctrl, fast;	IRDA_ASSERT(self != NULL, return;);	fir_base = self->io.fir_base;	self->io.speed = speed;	switch (speed) {	default:	case 576000:		ir_mode = IRCC_CFGA_IRDA_HDLC;		ctrl = IRCC_CRC;		fast = 0;		IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __FUNCTION__);		break;	case 1152000:		ir_mode = IRCC_CFGA_IRDA_HDLC;		ctrl = IRCC_1152 | IRCC_CRC;		fast = IRCC_LCR_A_FAST | IRCC_LCR_A_GP_DATA;		IRDA_DEBUG(0, "%s(), handling baud of 1152000\n",			   __FUNCTION__);		break;	case 4000000:		ir_mode = IRCC_CFGA_IRDA_4PPM;		ctrl = IRCC_CRC;		fast = IRCC_LCR_A_FAST;		IRDA_DEBUG(0, "%s(), handling baud of 4000000\n",			   __FUNCTION__);		break;	}	#if 0	Now in tranceiver!	/* This causes an interrupt */	register_bank(fir_base, 0);	outb((inb(fir_base + IRCC_LCR_A) &  0xbf) | fast, fir_base + IRCC_LCR_A);	#endif	register_bank(fir_base, 1);	outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base + IRCC_SCE_CFGA);	register_bank(fir_base, 4);	outb((inb(fir_base + IRCC_CONTROL) & 0x30) | ctrl, fir_base + IRCC_CONTROL);}/* * Function smsc_ircc_fir_start(self) * *    Change the speed of the device * */static void smsc_ircc_fir_start(struct smsc_ircc_cb *self){	struct net_device *dev;	int fir_base;	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	dev = self->netdev;	IRDA_ASSERT(dev != NULL, return;);	fir_base = self->io.fir_base;	/* Reset everything */	/* Install FIR transmit handler */	dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;	/* Clear FIFO */	outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A);	/* Enable interrupt */	/*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base + IRCC_IER);*/	register_bank(fir_base, 1);	/* Select the TX/RX interface */#ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */	outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),	     fir_base + IRCC_SCE_CFGB);#else	outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),	     fir_base + IRCC_SCE_CFGB);#endif	(void) inb(fir_base + IRCC_FIFO_THRESHOLD);	/* Enable SCE interrupts */	outb(0, fir_base + IRCC_MASTER);	register_bank(fir_base, 0);	outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, fir_base + IRCC_IER);	outb(IRCC_MASTER_INT_EN, fir_base + IRCC_MASTER);}/* * Function smsc_ircc_fir_stop(self, baud) * *    Change the speed of the device * */static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self){	int fir_base;	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	fir_base = self->io.fir_base;	register_bank(fir_base, 0);	/*outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);*/	outb(inb(fir_base + IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base + IRCC_LCR_B);}/* * Function smsc_ircc_change_speed(self, baud) * *    Change the speed of the device * * This function *must* be called with spinlock held, because it may * be called from the irq handler. - Jean II */static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed){	struct net_device *dev;	int last_speed_was_sir;	IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed);	IRDA_ASSERT(self != NULL, return;);	dev = self->netdev;	last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED;	#if 0	/* Temp Hack */	speed= 1152000;	self->io.speed = speed;	last_speed_was_sir = 0;	smsc_ircc_fir_start(self);	#endif	if (self->io.speed == 0)		smsc_ircc_sir_start(self);	#if 0	if (!last_speed_was_sir) speed = self->io.speed;	#endif	if (self->io.speed != speed)		smsc_ircc_set_transceiver_for_speed(self, speed);	self->io.speed = speed;	if (speed <= SMSC_IRCC2_MAX_SIR_SPEED) {		if (!last_speed_was_sir) {			smsc_ircc_fir_stop(self);			smsc_ircc_sir_start(self);		}		smsc_ircc_set_sir_speed(self, speed);	} else {		if (last_speed_was_sir) {			#if SMSC_IRCC2_C_SIR_STOP			smsc_ircc_sir_stop(self);			#endif			smsc_ircc_fir_start(self);		}		smsc_ircc_set_fir_speed(self, speed);		#if 0		self->tx_buff.len = 10;		self->tx_buff.data = self->tx_buff.head;		smsc_ircc_dma_xmit(self, 4000);		#endif		/* Be ready for incoming frames */		smsc_ircc_dma_receive(self);	}	netif_wake_queue(dev);}/* * Function smsc_ircc_set_sir_speed (self, speed) * *    Set speed of IrDA port to specified baudrate * */void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed){	int iobase;	int fcr;    /* FIFO control reg */	int lcr;    /* Line control reg */	int divisor;	IRDA_DEBUG(0, "%s(), Setting speed to: %d\n", __FUNCTION__, speed);	IRDA_ASSERT(self != NULL, return;);	iobase = self->io.sir_base;	/* Update accounting for new speed */	self->io.speed = speed;	/* Turn off interrupts */	outb(0, iobase + UART_IER);	divisor = SMSC_IRCC2_MAX_SIR_SPEED / 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.	 */	fcr |= self->io.speed < 38400 ?		UART_FCR_TRIGGER_1 : 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 */	/* Turn on interrups */	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);	IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed);}/* * Function smsc_ircc_hard_xmit_fir (skb, dev) * *    Transmit the frame! * */static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev){	struct smsc_ircc_cb *self;	unsigned long flags;	s32 speed;	int mtt;	IRDA_ASSERT(dev != NULL, return 0;);	self = netdev_priv(dev);	IRDA_ASSERT(self != NULL, return 0;);	netif_stop_queue(dev);	/* Make sure test of self->io.speed & speed change are atomic */	spin_lock_irqsave(&self->lock, flags);	/* Check if we need to change the speed after this frame */	speed = irda_get_next_speed(skb);	if (speed != self->io.speed && speed != -1) {		/* Check for empty frame */		if (!skb->len) {			/* 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 */			smsc_ircc_change_speed(self, speed);			spin_unlock_irqrestore(&self->lock, flags);			dev_kfree_skb(skb);			return 0;		}		self->new_speed = speed;	}	memcpy(self->tx_buff.head, skb->data, skb->len);	self->tx_buff.len = skb->len;	self->tx_buff.data = self->tx_buff.head;	mtt = irda_get_mtt(skb);	if (mtt) {		int bofs;		/*		 * Compute how many BOFs (STA or PA's) we need to waste the		 * min turn time given the speed of the link.		 */		bofs = mtt * (self->io.speed / 1000) / 8000;		if (bofs > 4095)			bofs = 4095;		smsc_ircc_dma_xmit(self, bofs);	} else {		/* Transmit frame */		smsc_ircc_dma_xmit(self, 0);	}	spin_unlock_irqrestore(&self->lock, flags);	dev_kfree_skb(skb);	return 0;}/* * Function smsc_ircc_dma_xmit (self, bofs) * *    Transmit data using DMA * */static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs){	int iobase = self->io.fir_base;	u8 ctrl;	IRDA_DEBUG(3, "%s\n", __FUNCTION__);#if 1	/* Disable Rx */	register_bank(iobase, 0);	outb(0x00, iobase + IRCC_LCR_B);#endif	register_bank(iobase, 1);	outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,	     iobase + IRCC_SCE_CFGB);	self->io.direction = IO_XMIT;	/* Set BOF additional count for generating the min turn time */	register_bank(iobase, 4);	outb(bofs & 0xff, iobase + IRCC_BOF_COUNT_LO);	ctrl = inb(iobase + IRCC_CONTROL) & 0xf0;	outb(ctrl | ((bofs >> 8) & 0x0f), iobase + IRCC_BOF_COUNT_HI);	/* Set max Tx frame size */	outb(self->tx_buff.len >> 8, iobase + IRCC_TX_SIZE_HI);	outb(self->tx_buff.len & 0xff, iobase + IRCC_TX_SIZE_LO);	/*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/	/* Enable burst mode chip Tx DMA */	register_bank(iobase, 1);	outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |	     IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB);

⌨️ 快捷键说明

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