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

📄 via-ircc.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		// 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);		return TRUE;	}	else {			//FIR mode		len = GetRecvByte(iobase, self);		if (len == 0)			return TRUE;	//interrupt only, data maybe move by RxT  		if (((len - 4) < 2) || ((len - 4) > 2048)) {			IRDA_DEBUG(1, "%s(): Trouble:len=%x,CurCount=%x,LastCount=%x..\n",				   __FUNCTION__, len, RxCurCount(iobase, self),				   self->RxLastCount);			hwreset(self);			return FALSE;		}		IRDA_DEBUG(2, "%s(): fifo.len=%x,len=%x,CurCount=%x..\n",			   __FUNCTION__,			   st_fifo->len, len - 4, RxCurCount(iobase, self));		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++;		if (st_fifo->tail > MAX_RX_WINDOW)			st_fifo->tail = 0;		self->RxDataReady = 0;		// It maybe have MAX_RX_WINDOW package receive by		// receive_complete before Timer IRQ/* F01_S          if (st_fifo->len < (MAX_RX_WINDOW+2 )) { 		  RXStart(iobase,ON);	  	  SetTimer(iobase,4);	  }	  else	  { F01_E */		EnableRX(iobase, OFF);		EnRXDMA(iobase, OFF);		RXStart(iobase, OFF);//F01_S		// Put this entry back in fifo 		if (st_fifo->head > MAX_RX_WINDOW)			st_fifo->head = 0;		status = st_fifo->entries[st_fifo->head].status;		len = st_fifo->entries[st_fifo->head].len;		st_fifo->head++;		st_fifo->len--;		skb = dev_alloc_skb(len + 1 - 4);		/*		 * if frame size,data ptr,or skb ptr are wrong ,the get next		 * entry.		 */		if ((skb == NULL) || (skb->data == NULL)		    || (self->rx_buff.data == NULL) || (len < 6)) {			self->stats.rx_dropped++;			return TRUE;		}		skb_reserve(skb, 1);		skb_put(skb, len - 4);		memcpy(skb->data, self->rx_buff.data, len - 4);		IRDA_DEBUG(2, "%s(): len=%x.rx_buff=%p\n", __FUNCTION__,			   len - 4, self->rx_buff.data);		// 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);//F01_E	}			//FIR	return TRUE;}/* * if frame is received , but no INT ,then use this routine to upload frame. */static int upload_rxdata(struct via_ircc_cb *self, int iobase){	struct sk_buff *skb;	int len;	struct st_fifo *st_fifo;	st_fifo = &self->st_fifo;	len = GetRecvByte(iobase, self);	IRDA_DEBUG(2, "%s(): len=%x\n", __FUNCTION__, len);	if ((len - 4) < 2) {		self->stats.rx_dropped++;		return FALSE;	}	skb = dev_alloc_skb(len + 1);	if (skb == NULL) {		self->stats.rx_dropped++;		return FALSE;	}	skb_reserve(skb, 1);	skb_put(skb, len - 4 + 1);	memcpy(skb->data, self->rx_buff.data, len - 4 + 1);	st_fifo->tail++;	st_fifo->len++;	if (st_fifo->tail > MAX_RX_WINDOW)		st_fifo->tail = 0;	// 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);	if (st_fifo->len < (MAX_RX_WINDOW + 2)) {		RXStart(iobase, ON);	} else {		EnableRX(iobase, OFF);		EnRXDMA(iobase, OFF);		RXStart(iobase, OFF);	}	return TRUE;}/* * Implement back to back receive , use this routine to upload data. */static int RxTimerHandler(struct via_ircc_cb *self, int iobase){	struct st_fifo *st_fifo;	struct sk_buff *skb;	int len;	u8 status;	st_fifo = &self->st_fifo;	if (CkRxRecv(iobase, self)) {		// if still receiving ,then return ,don't upload frame 		self->RetryCount = 0;		SetTimer(iobase, 20);		self->RxDataReady++;		return FALSE;	} else		self->RetryCount++;	if ((self->RetryCount >= 1) ||	    ((st_fifo->pending_bytes + 2048) > self->rx_buff.truesize)	    || (st_fifo->len >= (MAX_RX_WINDOW))) {		while (st_fifo->len > 0) {	//upload frame			// Put this entry back in fifo 			if (st_fifo->head > MAX_RX_WINDOW)				st_fifo->head = 0;			status = st_fifo->entries[st_fifo->head].status;			len = st_fifo->entries[st_fifo->head].len;			st_fifo->head++;			st_fifo->len--;			skb = dev_alloc_skb(len + 1 - 4);			/*			 * if frame size, data ptr, or skb ptr are wrong,			 * then get next entry.			 */			if ((skb == NULL) || (skb->data == NULL)			    || (self->rx_buff.data == NULL) || (len < 6)) {				self->stats.rx_dropped++;				continue;			}			skb_reserve(skb, 1);			skb_put(skb, len - 4);			memcpy(skb->data, self->rx_buff.data, len - 4);			IRDA_DEBUG(2, "%s(): len=%x.head=%x\n", __FUNCTION__,				   len - 4, st_fifo->head);			// 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);		}		//while		self->RetryCount = 0;		IRDA_DEBUG(2,			   "%s(): End of upload HostStatus=%x,RxStatus=%x\n",			   __FUNCTION__,			   GetHostStatus(iobase), GetRXStatus(iobase));		/*		 * if frame is receive complete at this routine ,then upload		 * frame.		 */		if ((GetRXStatus(iobase) & 0x10)		    && (RxCurCount(iobase, self) != self->RxLastCount)) {			upload_rxdata(self, iobase);			if (irda_device_txqueue_empty(self->netdev))				via_ircc_dma_receive(self);		}	}			// timer detect complete	else		SetTimer(iobase, 4);	return TRUE;}/* * Function via_ircc_interrupt (irq, dev_id) * *    An interrupt from the chip has arrived. Time to do some work * */static irqreturn_t via_ircc_interrupt(int irq, void *dev_id){	struct net_device *dev = (struct net_device *) dev_id;	struct via_ircc_cb *self;	int iobase;	u8 iHostIntType, iRxIntType, iTxIntType;	if (!dev) {		IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name,			     irq);		return IRQ_NONE;	}	self = (struct via_ircc_cb *) dev->priv;	iobase = self->io.fir_base;	spin_lock(&self->lock);	iHostIntType = GetHostStatus(iobase);	IRDA_DEBUG(4, "%s(): iHostIntType %02x:  %s %s %s  %02x\n",		   __FUNCTION__, iHostIntType,		   (iHostIntType & 0x40) ? "Timer" : "",		   (iHostIntType & 0x20) ? "Tx" : "",		   (iHostIntType & 0x10) ? "Rx" : "",		   (iHostIntType & 0x0e) >> 1);	if ((iHostIntType & 0x40) != 0) {	//Timer Event		self->EventFlag.TimeOut++;		ClearTimerInt(iobase, 1);		if (self->io.direction == IO_XMIT) {			via_ircc_dma_xmit(self, iobase);		}		if (self->io.direction == IO_RECV) {			/*			 * frame ready hold too long, must reset.			 */			if (self->RxDataReady > 30) {				hwreset(self);				if (irda_device_txqueue_empty(self->netdev)) {					via_ircc_dma_receive(self);				}			} else {	// call this to upload frame.				RxTimerHandler(self, iobase);			}		}		//RECV	}			//Timer Event	if ((iHostIntType & 0x20) != 0) {	//Tx Event		iTxIntType = GetTXStatus(iobase);		IRDA_DEBUG(4, "%s(): iTxIntType %02x:  %s %s %s %s\n",			   __FUNCTION__, iTxIntType,			   (iTxIntType & 0x08) ? "FIFO underr." : "",			   (iTxIntType & 0x04) ? "EOM" : "",			   (iTxIntType & 0x02) ? "FIFO ready" : "",			   (iTxIntType & 0x01) ? "Early EOM" : "");		if (iTxIntType & 0x4) {			self->EventFlag.EOMessage++;	// read and will auto clean			if (via_ircc_dma_xmit_complete(self)) {				if (irda_device_txqueue_empty				    (self->netdev)) {					via_ircc_dma_receive(self);				}			} else {				self->EventFlag.Unknown++;			}		}		//EOP	}			//Tx Event	//----------------------------------------	if ((iHostIntType & 0x10) != 0) {	//Rx Event		/* Check if DMA has finished */		iRxIntType = GetRXStatus(iobase);		IRDA_DEBUG(4, "%s(): iRxIntType %02x:  %s %s %s %s %s %s %s\n",			   __FUNCTION__, iRxIntType,			   (iRxIntType & 0x80) ? "PHY err."	: "",			   (iRxIntType & 0x40) ? "CRC err"	: "",			   (iRxIntType & 0x20) ? "FIFO overr."	: "",			   (iRxIntType & 0x10) ? "EOF"		: "",			   (iRxIntType & 0x08) ? "RxData"	: "",			   (iRxIntType & 0x02) ? "RxMaxLen"	: "",			   (iRxIntType & 0x01) ? "SIR bad"	: "");		if (!iRxIntType)			IRDA_DEBUG(3, "%s(): RxIRQ =0\n", __FUNCTION__);		if (iRxIntType & 0x10) {			if (via_ircc_dma_receive_complete(self, iobase)) {//F01       if(!(IsFIROn(iobase)))  via_ircc_dma_receive(self);				via_ircc_dma_receive(self);			}		}		// No ERR     		else {		//ERR			IRDA_DEBUG(4, "%s(): RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n",				   __FUNCTION__, iRxIntType, iHostIntType,				   RxCurCount(iobase, self),				   self->RxLastCount);			if (iRxIntType & 0x20) {	//FIFO OverRun ERR				ResetChip(iobase, 0);				ResetChip(iobase, 1);			} else {	//PHY,CRC ERR				if (iRxIntType != 0x08)					hwreset(self);	//F01			}			via_ircc_dma_receive(self);		}		//ERR	}			//Rx Event	spin_unlock(&self->lock);	return IRQ_RETVAL(iHostIntType);}static void hwreset(struct via_ircc_cb *self){	int iobase;	iobase = self->io.fir_base;	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	ResetChip(iobase, 5);	EnableDMA(iobase, OFF);	EnableTX(iobase, OFF);	EnableRX(iobase, OFF);	EnRXDMA(iobase, OFF);	EnTXDMA(iobase, OFF);	RXStart(iobase, OFF);	TXStart(iobase, OFF);	InitCard(iobase);	CommonInit(iobase);	SIRFilter(iobase, ON);	SetSIR(iobase, ON);	CRC16(iobase, ON);	EnTXCRC(iobase, 0);	WriteReg(iobase, I_ST_CT_0, 0x00);	SetBaudRate(iobase, 9600);	SetPulseWidth(iobase, 12);	SetSendPreambleCount(iobase, 0);	WriteReg(iobase, I_ST_CT_0, 0x80);	/* Restore speed. */	via_ircc_change_speed(self, self->io.speed);	self->st_fifo.len = 0;}/* * Function via_ircc_is_receiving (self) * *    Return TRUE is we are currently receiving a frame * */static int via_ircc_is_receiving(struct via_ircc_cb *self){	int status = FALSE;	int iobase;	IRDA_ASSERT(self != NULL, return FALSE;);	iobase = self->io.fir_base;	if (CkRxRecv(iobase, self))		status = TRUE;	IRDA_DEBUG(2, "%s(): status=%x....\n", __FUNCTION__, status);	return status;}/* * Function via_ircc_net_open (dev) * *    Start the device * */static int via_ircc_net_open(struct net_device *dev){	struct via_ircc_cb *self;	int iobase;	char hwname[32];	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	IRDA_ASSERT(dev != NULL, return -1;);	self = (struct via_ircc_cb *) dev->priv;	self->stats.rx_packets = 0;	IRDA_ASSERT(self != NULL, return 0;);	iobase = self->io.fir_base;	if (request_irq(self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) {		IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name,			     self->io.irq);		return -EAGAIN;	}	/*	 * Always allocate the DMA channel after the IRQ, and clean up on 	 * failure.	 */	if (request_dma(self->io.dma, dev->name)) {		IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name,			     self->io.dma);		free_irq(self->io.irq, self);		return -EAGAIN;	}	if (self->io.dma2 != self->io.dma) {		if (request_dma(self->io.dma2, dev->name)) {			IRDA_WARNING("%s, unable to allocate dma2=%d\n",				     driver_name, self->io.dma2);			free_irq(self->io.irq, self);			return -EAGAIN;		}	}	/* turn on interrupts */	EnAllInt(iobase, ON);	EnInternalLoop(iobase, OFF);	EnExternalLoop(iobase, OFF);	/* */	via_ircc_dma_receive(self);	/* Ready to play! */	netif_start_queue(dev);	/* 	 * Open new IrLAP layer instance, now that everything should be	 * initialized properly 	 */	sprintf(hwname, "VIA @ 0x%x", iobase);	self->irlap = irlap_open(dev, &self->qos, hwname);	self->RxLastCount = 0;	return 0;}/* * Function via_ircc_net_close (dev) * *    Stop the device * */static int via_ircc_net_close(struct net_device *dev){	struct via_ircc_cb *self;	int iobase;	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	IRDA_ASSERT(dev != NULL, return -1;);	self = (struct via_ircc_cb *) dev->priv;	IRDA_ASSERT(self != NULL, return 0;);	/* Stop device */	netif_stop_queue(dev);	/* Stop and remove instance of IrLAP */	if (self->irlap)		irlap_close(self->irlap);	self->irlap = NULL;	iobase = self->io.fir_base;	EnTXDMA(iobase, OFF);	EnRXDMA(iobase, OFF);	DisableDmaChannel(self->io.dma);	/* Disable interrupts */	EnAllInt(iobase, OFF);	free_irq(self->io.irq, dev);	free_dma(self->io.dma);	return 0;}/* * Function via_ircc_net_ioctl (dev, rq, cmd) * *    Process IOCTL commands for this device * */static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,			      int cmd){	struct if_irda_req *irq = (struct if_irda_req *) rq;	struct via_ircc_cb *self;	unsigned long flags;	int ret = 0;	IRDA_ASSERT(dev != NULL, return -1;);	self = dev->priv;	IRDA_ASSERT(self != NULL, return -1;);	IRDA_DEBUG(1, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name,		   cmd);	/* Disable interrupts & save flags */	spin_lock_irqsave(&self->lock, flags);	switch (cmd) {	case SIOCSBANDWIDTH:	/* Set bandwidth */		if (!capable(CAP_NET_ADMIN)) {			ret = -EPERM;			goto out;		}		via_ircc_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 = via_ircc_is_receiving(self);		break;	default:		ret = -EOPNOTSUPP;	}      out:	spin_unlock_irqrestore(&self->lock, flags);	return ret;}static struct net_device_stats *via_ircc_net_get_stats(struct net_device						       *dev){	struct via_ircc_cb *self = (struct via_ircc_cb *) dev->priv;	return &self->stats;}MODULE_AUTHOR("VIA Technologies,inc");MODULE_DESCRIPTION("VIA IrDA Device Driver");MODULE_LICENSE("GPL");module_init(via_ircc_init);module_exit(via_ircc_cleanup);

⌨️ 快捷键说明

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