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

📄 via-ircc.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Function via_ircc_read_dongle_id (void) * */static int via_ircc_read_dongle_id(int iobase){	int dongle_id = 9;	/* Default to IBM */	IRDA_ERROR("via-ircc: dongle probing not supported, please specify dongle_id module parameter.\n");	return dongle_id;}/* * Function via_ircc_change_dongle_speed (iobase, speed, dongle_id) *    Change speed of the attach dongle *    only implement two type of dongle currently. */static void via_ircc_change_dongle_speed(int iobase, int speed,					 int dongle_id){	u8 mode = 0;	/* speed is unused, as we use IsSIROn()/IsMIROn() */	speed = speed;	IRDA_DEBUG(1, "%s(): change_dongle_speed to %d for 0x%x, %d\n",		   __FUNCTION__, speed, iobase, dongle_id);	switch (dongle_id) {		/* Note: The dongle_id's listed here are derived from		 * nsc-ircc.c */ 	case 0x08:		/* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */		UseOneRX(iobase, ON);	// use one RX pin   RX1,RX2		InvertTX(iobase, OFF);		InvertRX(iobase, OFF);		EnRX2(iobase, ON);	//sir to rx2		EnGPIOtoRX2(iobase, OFF);		if (IsSIROn(iobase)) {	//sir			// Mode select Off			SlowIRRXLowActive(iobase, ON);			udelay(1000);			SlowIRRXLowActive(iobase, OFF);		} else {			if (IsMIROn(iobase)) {	//mir				// Mode select On				SlowIRRXLowActive(iobase, OFF);				udelay(20);			} else {	// fir				if (IsFIROn(iobase)) {	//fir					// Mode select On					SlowIRRXLowActive(iobase, OFF);					udelay(20);				}			}		}		break;	case 0x09:		/* IBM31T1100 or Temic TFDS6000/TFDS6500 */		UseOneRX(iobase, ON);	//use ONE RX....RX1		InvertTX(iobase, OFF);		InvertRX(iobase, OFF);	// invert RX pin		EnRX2(iobase, ON);		EnGPIOtoRX2(iobase, OFF);		if (IsSIROn(iobase)) {	//sir			// Mode select On			SlowIRRXLowActive(iobase, ON);			udelay(20);			// Mode select Off			SlowIRRXLowActive(iobase, OFF);		}		if (IsMIROn(iobase)) {	//mir			// Mode select On			SlowIRRXLowActive(iobase, OFF);			udelay(20);			// Mode select Off			SlowIRRXLowActive(iobase, ON);		} else {	// fir			if (IsFIROn(iobase)) {	//fir				// Mode select On				SlowIRRXLowActive(iobase, OFF);				// TX On				WriteTX(iobase, ON);				udelay(20);				// Mode select OFF				SlowIRRXLowActive(iobase, ON);				udelay(20);				// TX Off				WriteTX(iobase, OFF);			}		}		break;	case 0x0d:		UseOneRX(iobase, OFF);	// use two RX pin   RX1,RX2		InvertTX(iobase, OFF);		InvertRX(iobase, OFF);		SlowIRRXLowActive(iobase, OFF);		if (IsSIROn(iobase)) {	//sir			EnGPIOtoRX2(iobase, OFF);			WriteGIO(iobase, OFF);			EnRX2(iobase, OFF);	//sir to rx2		} else {	// fir mir			EnGPIOtoRX2(iobase, OFF);			WriteGIO(iobase, OFF);			EnRX2(iobase, OFF);	//fir to rx		}		break;	case 0x11:		/* Temic TFDS4500 */		IRDA_DEBUG(2, "%s: Temic TFDS4500: One RX pin, TX normal, RX inverted.\n", __FUNCTION__);		UseOneRX(iobase, ON);	//use ONE RX....RX1		InvertTX(iobase, OFF);		InvertRX(iobase, ON);	// invert RX pin			EnRX2(iobase, ON);	//sir to rx2		EnGPIOtoRX2(iobase, OFF);		if( IsSIROn(iobase) ){	//sir			// Mode select On			SlowIRRXLowActive(iobase, ON);			udelay(20);			// Mode select Off			SlowIRRXLowActive(iobase, OFF);		} else{			IRDA_DEBUG(0, "%s: Warning: TFDS4500 not running in SIR mode !\n", __FUNCTION__);		}		break;	case 0x0ff:		/* Vishay */		if (IsSIROn(iobase))			mode = 0;		else if (IsMIROn(iobase))			mode = 1;		else if (IsFIROn(iobase))			mode = 2;		else if (IsVFIROn(iobase))			mode = 5;	//VFIR-16		SI_SetMode(iobase, mode);		break;	default:		IRDA_ERROR("%s: Error: dongle_id %d unsupported !\n",			   __FUNCTION__, dongle_id);	}}/* * Function via_ircc_change_speed (self, baud) * *    Change the speed of the device * */static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed){	struct net_device *dev = self->netdev;	u16 iobase;	u8 value = 0, bTmp;	iobase = self->io.fir_base;	/* Update accounting for new speed */	self->io.speed = speed;	IRDA_DEBUG(1, "%s: change_speed to %d bps.\n", __FUNCTION__, speed);	WriteReg(iobase, I_ST_CT_0, 0x0);	/* Controller mode sellection */	switch (speed) {	case 2400:	case 9600:	case 19200:	case 38400:	case 57600:	case 115200:		value = (115200/speed)-1;		SetSIR(iobase, ON);		CRC16(iobase, ON);		break;	case 576000:		/* FIXME: this can't be right, as it's the same as 115200,		 * and 576000 is MIR, not SIR. */		value = 0;		SetSIR(iobase, ON);		CRC16(iobase, ON);		break;	case 1152000:		value = 0;		SetMIR(iobase, ON);		/* FIXME: CRC ??? */		break;	case 4000000:		value = 0;		SetFIR(iobase, ON);		SetPulseWidth(iobase, 0);		SetSendPreambleCount(iobase, 14);		CRC16(iobase, OFF);		EnTXCRC(iobase, ON);		break;	case 16000000:		value = 0;		SetVFIR(iobase, ON);		/* FIXME: CRC ??? */		break;	default:		value = 0;		break;	}	/* Set baudrate to 0x19[2..7] */	bTmp = (ReadReg(iobase, I_CF_H_1) & 0x03);	bTmp |= value << 2;	WriteReg(iobase, I_CF_H_1, bTmp);	/* Some dongles may need to be informed about speed changes. */	via_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id);	/* Set FIFO size to 64 */	SetFIFO(iobase, 64);	/* Enable IR */	WriteReg(iobase, I_ST_CT_0, 0x80);	// EnTXFIFOHalfLevelInt(iobase,ON);	/* Enable some interrupts so we can receive frames */	//EnAllInt(iobase,ON);	if (IsSIROn(iobase)) {		SIRFilter(iobase, ON);		SIRRecvAny(iobase, ON);	} else {		SIRFilter(iobase, OFF);		SIRRecvAny(iobase, OFF);	}	if (speed > 115200) {		/* Install FIR xmit handler */		dev->hard_start_xmit = via_ircc_hard_xmit_fir;		via_ircc_dma_receive(self);	} else {		/* Install SIR xmit handler */		dev->hard_start_xmit = via_ircc_hard_xmit_sir;	}	netif_wake_queue(dev);}/* * Function via_ircc_hard_xmit (skb, dev) * *    Transmit the frame! * */static int via_ircc_hard_xmit_sir(struct sk_buff *skb,				  struct net_device *dev){	struct via_ircc_cb *self;	unsigned long flags;	u16 iobase;	__u32 speed;	self = (struct via_ircc_cb *) dev->priv;	IRDA_ASSERT(self != NULL, return 0;);	iobase = self->io.fir_base;	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) {			via_ircc_change_speed(self, speed);			dev->trans_start = jiffies;			dev_kfree_skb(skb);			return 0;		} else			self->new_speed = speed;	}	InitCard(iobase);	CommonInit(iobase);	SIRFilter(iobase, ON);	SetSIR(iobase, ON);	CRC16(iobase, ON);	EnTXCRC(iobase, 0);	WriteReg(iobase, I_ST_CT_0, 0x00);	spin_lock_irqsave(&self->lock, flags);	self->tx_buff.data = self->tx_buff.head;	self->tx_buff.len =	    async_wrap_skb(skb, self->tx_buff.data,			   self->tx_buff.truesize);	self->stats.tx_bytes += self->tx_buff.len;	/* Send this frame with old speed */	SetBaudRate(iobase, self->io.speed);	SetPulseWidth(iobase, 12);	SetSendPreambleCount(iobase, 0);	WriteReg(iobase, I_ST_CT_0, 0x80);	EnableTX(iobase, ON);	EnableRX(iobase, OFF);	ResetChip(iobase, 0);	ResetChip(iobase, 1);	ResetChip(iobase, 2);	ResetChip(iobase, 3);	ResetChip(iobase, 4);	EnAllInt(iobase, ON);	EnTXDMA(iobase, ON);	EnRXDMA(iobase, OFF);	irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len,		       DMA_TX_MODE);	SetSendByte(iobase, self->tx_buff.len);	RXStart(iobase, OFF);	TXStart(iobase, ON);	dev->trans_start = jiffies;	spin_unlock_irqrestore(&self->lock, flags);	dev_kfree_skb(skb);	return 0;}static int via_ircc_hard_xmit_fir(struct sk_buff *skb,				  struct net_device *dev){	struct via_ircc_cb *self;	u16 iobase;	__u32 speed;	unsigned long flags;	self = (struct via_ircc_cb *) dev->priv;	iobase = self->io.fir_base;	if (self->st_fifo.len)		return 0;	if (self->chip_id == 0x3076)		iodelay(1500);	else		udelay(1500);	netif_stop_queue(dev);	speed = irda_get_next_speed(skb);	if ((speed != self->io.speed) && (speed != -1)) {		if (!skb->len) {			via_ircc_change_speed(self, speed);			dev->trans_start = jiffies;			dev_kfree_skb(skb);			return 0;		} else			self->new_speed = speed;	}	spin_lock_irqsave(&self->lock, flags);	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++;//F01   if (self->tx_fifo.len == 1) {	via_ircc_dma_xmit(self, iobase);//F01   }//F01   if (self->tx_fifo.free < (MAX_TX_WINDOW -1 )) netif_wake_queue(self->netdev);	dev->trans_start = jiffies;	dev_kfree_skb(skb);	spin_unlock_irqrestore(&self->lock, flags);	return 0;}static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase){	EnTXDMA(iobase, OFF);	self->io.direction = IO_XMIT;	EnPhys(iobase, ON);	EnableTX(iobase, ON);	EnableRX(iobase, OFF);	ResetChip(iobase, 0);	ResetChip(iobase, 1);	ResetChip(iobase, 2);	ResetChip(iobase, 3);	ResetChip(iobase, 4);	EnAllInt(iobase, ON);	EnTXDMA(iobase, ON);	EnRXDMA(iobase, OFF);	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);	IRDA_DEBUG(1, "%s: tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n",		   __FUNCTION__, self->tx_fifo.ptr,		   self->tx_fifo.queue[self->tx_fifo.ptr].len,		   self->tx_fifo.len);	SetSendByte(iobase, self->tx_fifo.queue[self->tx_fifo.ptr].len);	RXStart(iobase, OFF);	TXStart(iobase, ON);	return 0;}/* * Function via_ircc_dma_xmit_complete (self) * *    The transfer of a frame in finished. This function will only be called  *    by the interrupt handler * */static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self){	int iobase;	int ret = TRUE;	u8 Tx_status;	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	iobase = self->io.fir_base;	/* Disable DMA *///      DisableDmaChannel(self->io.dma);	/* Check for underrrun! */	/* Clear bit, by writing 1 into it */	Tx_status = GetTXStatus(iobase);	if (Tx_status & 0x08) {		self->stats.tx_errors++;		self->stats.tx_fifo_errors++;		hwreset(self);// how to clear underrrun ?	} else {		self->stats.tx_packets++;		ResetChip(iobase, 3);		ResetChip(iobase, 4);	}	/* Check if we need to change the speed */	if (self->new_speed) {		via_ircc_change_speed(self, self->new_speed);		self->new_speed = 0;	}	/* Finished with this frame, so prepare for next */	if (IsFIROn(iobase)) {		if (self->tx_fifo.len) {			self->tx_fifo.len--;			self->tx_fifo.ptr++;		}	}	IRDA_DEBUG(1,		   "%s: tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n",		   __FUNCTION__,		   self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free);/* F01_S	// Any frames to be sent back-to-back? 	if (self->tx_fifo.len) {		// Not finished yet! 	  	via_ircc_dma_xmit(self, iobase);		ret = FALSE;	} else { F01_E*/	// 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;//F01   }	// Make sure we have room for more frames //F01   if (self->tx_fifo.free < (MAX_TX_WINDOW -1 )) {	// Not busy transmitting anymore 	// Tell the network layer, that we can accept more frames 	netif_wake_queue(self->netdev);//F01   }	return ret;}/* * Function via_ircc_dma_receive (self) * *    Set configuration for receive a frame. * */static int via_ircc_dma_receive(struct via_ircc_cb *self){	int iobase;	iobase = self->io.fir_base;	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;	self->tx_fifo.tail = self->tx_buff.head;	self->RxDataReady = 0;	self->io.direction = IO_RECV;	self->rx_buff.data = self->rx_buff.head;	self->st_fifo.len = self->st_fifo.pending_bytes = 0;	self->st_fifo.tail = self->st_fifo.head = 0;	EnPhys(iobase, ON);	EnableTX(iobase, OFF);	EnableRX(iobase, ON);	ResetChip(iobase, 0);	ResetChip(iobase, 1);	ResetChip(iobase, 2);	ResetChip(iobase, 3);	ResetChip(iobase, 4);	EnAllInt(iobase, ON);	EnTXDMA(iobase, OFF);	EnRXDMA(iobase, ON);	irda_setup_dma(self->io.dma2, self->rx_buff_dma,		  self->rx_buff.truesize, DMA_RX_MODE);	TXStart(iobase, OFF);	RXStart(iobase, ON);	return 0;}/* * Function via_ircc_dma_receive_complete (self) * *    Controller Finished with receiving frames, *    and this routine is call by ISR *     */static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,					 int iobase){	struct st_fifo *st_fifo;	struct sk_buff *skb;	int len, i;	u8 status = 0;	iobase = self->io.fir_base;	st_fifo = &self->st_fifo;	if (self->io.speed < 4000000) {	//Speed below FIR		len = GetRecvByte(iobase, self);		skb = dev_alloc_skb(len + 1);		if (skb == NULL)			return FALSE;		// Make sure IP header gets aligned 		skb_reserve(skb, 1);		skb_put(skb, len - 2);		if (self->chip_id == 0x3076) {			for (i = 0; i < len - 2; i++)				skb->data[i] = self->rx_buff.data[i * 2];		} else {			if (self->chip_id == 0x3096) {				for (i = 0; i < len - 2; i++)					skb->data[i] =					    self->rx_buff.data[i];			}		}

⌨️ 快捷键说明

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