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

📄 via-ircc.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		    (KERN_INFO		     "recv_comple:fifo.len=%x,len=%x,CurCount=%x..\n",		     st_fifo->len, len - 4, RxCurCount(iobase, self)));#endif		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--;		/*		 * if frame size or data ptr are wrong ,then get next		 * entry.		 */		if ((self->rx_buff.data == NULL) || (len < 6)) {			self->stats.rx_dropped++;			return TRUE;		}		skb = dev_alloc_skb(len + 1 - 4);		if (!skb) {			self->stats.rx_dropped++;			return TRUE;		}		skb_reserve(skb, 1);		skb_put(skb, len - 4);		memcpy(skb->data, self->rx_buff.data, len - 4);#ifdef	DBGMSG		DBG(printk		    (KERN_INFO "RxT:len=%x.rx_buff=%x\n", len - 4,		     self->rx_buff.data));/*		for(i=0 ; i < (len-4) ; i++) {		    DBG(printk(KERN_INFO "%x..\n",self->rx_buff.data[i]));		}*/#endif		// 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);#ifdef	DBGMSG	DBG(printk(KERN_INFO "upload_rxdata: len=%x\n", len));#endif	if ((len - 4) < 2) {		self->stats.rx_dropped++;		return FALSE;	}	skb = dev_alloc_skb(len + 1);	if (!skb) {		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--;			/*			 * if frame size or data ptr are wrong,			 * then get next entry.			 */			if ((self->rx_buff.data == NULL) || (len < 6)) {				self->stats.rx_dropped++;				continue;			}			skb = dev_alloc_skb(len + 1 - 4);			if (!skb) {				self->stats.rx_dropped++;				continue;			}			skb_reserve(skb, 1);			skb_put(skb, len - 4);			memcpy(skb->data, self->rx_buff.data, len - 4);#ifdef	DBGMSG			DBG(printk			    (KERN_INFO "RxT:len=%x.head=%x\n", len - 4,			     st_fifo->head));#endif			// 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;#ifdef	DBGMSG		DBG(printk		    (KERN_INFO		     "RxT:End of upload HostStatus=%x,RxStatus=%x\n",		     GetHostStatus(iobase), GetRXStatus(iobase)));#endif		/*		 * 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, regs) * *    An interrupt from the chip has arrived. Time to do some work * */static irqreturn_t via_ircc_interrupt(int irq, void *dev_id,				      struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_id;	struct via_ircc_cb *self;	int iobase;	u8 iHostIntType, iRxIntType, iTxIntType;	if (!dev) {		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);	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);		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);#ifdef	DBGMSG		if (!iRxIntType)			DBG(printk(KERN_INFO " RxIRQ =0\n"));#endif		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#ifdef	DBGMSG			DBG(printk			    (KERN_INFO			     " RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n",			     iRxIntType, iHostIntType, RxCurCount(iobase,								  self),			     self->RxLastCount));#endif			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_HANDLED;}void hwreset(struct via_ircc_cb *self){	int iobase;	iobase = self->io.fir_base;#ifdef	DBGMSG	DBG(printk(KERN_INFO "hwreset  ....\n"));#endif	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);	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;	ASSERT(self != NULL, return FALSE;);	iobase = self->io.fir_base;	if (CkRxRecv(iobase, self))		status = TRUE;#ifdef	DBGMSG	DBG(printk(KERN_INFO "is_receiving  status=%x....\n", status));#endif	return status;}/* * Function via_ircc_net_init (dev) * *    Initialize network device * */static int via_ircc_net_init(struct net_device *dev){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	/* Keep track of module usage */	SET_MODULE_OWNER(dev);	/* Setup to be a normal IrDA network device driver */	irda_device_setup(dev);	/* Insert overrides below this line! */	return 0;}/* * 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(4, "%s()\n", __FUNCTION__);	ASSERT(dev != NULL, return -1;);	self = (struct via_ircc_cb *) dev->priv;	self->stats.rx_packets = 0;	ASSERT(self != NULL, return 0;);	iobase = self->io.fir_base;	if (request_irq	    (self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) {		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)) {		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)) {			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);	/* Ready to play! */	netif_start_queue(dev);	/* 	 * Open new IrLAP layer instance, now that everything should be	 * initialized properly 	 */	sprintf(hwname, "VIA");	/*	 * for different kernel ,irlap_open have different parameter.	 */	self->irlap = irlap_open(dev, &self->qos, hwname);//      self->irlap = irlap_open(dev, &self->qos);	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(4, "%s()\n", __FUNCTION__);	ASSERT(dev != NULL, return -1;);	self = (struct via_ircc_cb *) dev->priv;	ASSERT(self != NULL, return 0;);#ifdef	DBG_IO	outb(0xff, 0x90);	outb(0xff, 0x94);#endif	/* 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;	ASSERT(dev != NULL, return -1;);	self = dev->priv;	ASSERT(self != NULL, return -1;);	IRDA_DEBUG(2, "%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 + -