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

📄 vlsi_ir.c

📁 移植到2410开发板上的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (baudrate == 4000000) {		mode = IFF_FIR;		config = IRCFG_FIR;		nphyctl = PHYCTL_FIR;	}	else if (baudrate == 1152000) {		mode = IFF_MIR;		config = IRCFG_MIR | IRCFG_CRC16;		nphyctl = PHYCTL_MIR(clksrc==3);	}	else {		mode = IFF_SIR;		config = IRCFG_SIR | IRCFG_SIRFILT | IRCFG_RXANY;		switch(baudrate) {			default:				printk(KERN_ERR "%s: undefined baudrate %d - fallback to 9600!\n",					__FUNCTION__, baudrate);				baudrate = 9600;				/* fallthru */			case 2400:			case 9600:			case 19200:			case 38400:			case 57600:			case 115200:				nphyctl = PHYCTL_SIR(baudrate,sirpulse,clksrc==3);				break;		}	}	config |= IRCFG_MSTR | IRCFG_ENRX;	outw(config, iobase+VLSI_PIO_IRCFG);	outw(nphyctl, iobase+VLSI_PIO_NPHYCTL);	wmb();	outw(IRENABLE_IREN, iobase+VLSI_PIO_IRENABLE);	/* chip fetches IRCFG on next rising edge of its 8MHz clock */	mb();	config = inw(iobase+VLSI_PIO_IRENABLE) & IRENABLE_MASK;	if (mode == IFF_FIR)		config ^= IRENABLE_FIR_ON;	else if (mode == IFF_MIR)		config ^= (IRENABLE_MIR_ON|IRENABLE_CRC16_ON);	else		config ^= IRENABLE_SIR_ON;	if (config != (IRENABLE_IREN|IRENABLE_ENRXST)) {		printk(KERN_ERR "%s: failed to set %s mode!\n", __FUNCTION__,			(mode==IFF_SIR)?"SIR":((mode==IFF_MIR)?"MIR":"FIR"));		ret = -1;	}	else {		if (inw(iobase+VLSI_PIO_PHYCTL) != nphyctl) {			printk(KERN_ERR "%s: failed to apply baudrate %d\n",				__FUNCTION__, baudrate);			ret = -1;		}		else {			idev->mode = mode;			idev->baud = baudrate;			idev->new_baud = 0;			ret = 0;		}	}	spin_unlock_irqrestore(&idev->lock, flags);	if (ret)		vlsi_reg_debug(iobase,__FUNCTION__);	return ret;}static int vlsi_init_chip(struct net_device *ndev){	vlsi_irda_dev_t *idev = ndev->priv;	unsigned	iobase;	u16 ptr;	iobase = ndev->base_addr;	outb(IRINTR_INT_MASK, iobase+VLSI_PIO_IRINTR); /* w/c pending IRQ, disable all INT */	outw(0, iobase+VLSI_PIO_IRENABLE);	/* disable IrPHY-interface */	/* disable everything, particularly IRCFG_MSTR - which resets the RING_PTR */	outw(0, iobase+VLSI_PIO_IRCFG);	wmb();	outw(IRENABLE_IREN, iobase+VLSI_PIO_IRENABLE);	mb();	outw(0, iobase+VLSI_PIO_IRENABLE);	outw(MAX_PACKET_LENGTH, iobase+VLSI_PIO_MAXPKT);  /* max possible value=0x0fff */	outw(BUS_TO_RINGBASE(idev->busaddr), iobase+VLSI_PIO_RINGBASE);	outw(TX_RX_TO_RINGSIZE(idev->tx_ring.size, idev->rx_ring.size),		iobase+VLSI_PIO_RINGSIZE);		ptr = inw(iobase+VLSI_PIO_RINGPTR);	idev->rx_ring.head = idev->rx_ring.tail = RINGPTR_GET_RX(ptr);	idev->tx_ring.head = idev->tx_ring.tail = RINGPTR_GET_TX(ptr);	outw(IRCFG_MSTR, iobase+VLSI_PIO_IRCFG);		/* ready for memory access */	wmb();	outw(IRENABLE_IREN, iobase+VLSI_PIO_IRENABLE);	mb();	idev->new_baud = 9600;		/* start with IrPHY using 9600(SIR) mode */	vlsi_set_baud(ndev);	outb(IRINTR_INT_MASK, iobase+VLSI_PIO_IRINTR);	/* just in case - w/c pending IRQ's */	wmb();	/* DO NOT BLINDLY ENABLE IRINTR_ACTEN!	 * basically every received pulse fires an ACTIVITY-INT	 * leading to >>1000 INT's per second instead of few 10	 */	outb(IRINTR_RPKTEN|IRINTR_TPKTEN, iobase+VLSI_PIO_IRINTR);	wmb();	return 0;}/**************************************************************/static void vlsi_refill_rx(struct vlsi_ring *r){	do {		if (rd_is_active(r, r->head))			BUG();		rd_activate(r, r->head);		ring_put(r);	} while (r->head != r->tail);}static int vlsi_rx_interrupt(struct net_device *ndev){	vlsi_irda_dev_t *idev = ndev->priv;	struct vlsi_ring *r;	int	len;	u8	status;	struct sk_buff	*skb;	int	crclen;	r = &idev->rx_ring;	while (!rd_is_active(r, r->tail)) {		status = rd_get_status(r, r->tail);		if (status & RX_STAT_ERROR) {			idev->stats.rx_errors++;			if (status & RX_STAT_OVER)  				idev->stats.rx_over_errors++;			if (status & RX_STAT_LENGTH)  				idev->stats.rx_length_errors++;			if (status & RX_STAT_PHYERR)  				idev->stats.rx_frame_errors++;			if (status & RX_STAT_CRCERR)  				idev->stats.rx_crc_errors++;		}		else {			len = rd_get_count(r, r->tail);			crclen = (idev->mode==IFF_FIR) ? sizeof(u32) : sizeof(u16);			if (len < crclen)				printk(KERN_ERR "%s: strange frame (len=%d)\n",					__FUNCTION__, len);			else				len -= crclen;		/* remove trailing CRC */			skb = dev_alloc_skb(len+1);			if (skb) {				skb->dev = ndev;				skb_reserve(skb,1);				memcpy(skb_put(skb,len), r->buf[r->tail].data, len);				idev->stats.rx_packets++;				idev->stats.rx_bytes += len;				skb->mac.raw = skb->data;				skb->protocol = htons(ETH_P_IRDA);				netif_rx(skb);							}			else {				idev->stats.rx_dropped++;				printk(KERN_ERR "%s: rx packet dropped\n", __FUNCTION__);			}		}		rd_set_count(r, r->tail, 0);		rd_set_status(r, r->tail, 0);		ring_get(r);		if (r->tail == r->head) {			printk(KERN_WARNING "%s: rx ring exhausted\n", __FUNCTION__);			break;		}	}	do_gettimeofday(&idev->last_rx); /* remember "now" for later mtt delay */	vlsi_refill_rx(r);	mb();	outw(0, ndev->base_addr+VLSI_PIO_PROMPT);	return 0;}static int vlsi_tx_interrupt(struct net_device *ndev){	vlsi_irda_dev_t *idev = ndev->priv;	struct vlsi_ring	*r;	unsigned	iobase;	int	ret;	u16	config;	u16	status;	r = &idev->tx_ring;	while (!rd_is_active(r, r->tail)) {		if (r->tail == r->head)			break;	/* tx ring empty - nothing to send anymore */		status = rd_get_status(r, r->tail);		if (status & TX_STAT_UNDRN) {			idev->stats.tx_errors++;			idev->stats.tx_fifo_errors++;		}		else {			idev->stats.tx_packets++;			idev->stats.tx_bytes += rd_get_count(r, r->tail); /* not correct for SIR */		}		rd_set_count(r, r->tail, 0);		rd_set_status(r, r->tail, 0);		if (r->buf[r->tail].skb) {			rd_set_addr_status(r, r->tail, 0, 0);			dev_kfree_skb(r->buf[r->tail].skb);			r->buf[r->tail].skb = NULL;			r->buf[r->tail].data = NULL;		}		ring_get(r);	}	ret = 0;	iobase = ndev->base_addr;	if (r->head == r->tail) {	/* tx ring empty: re-enable rx */		outw(0, iobase+VLSI_PIO_IRENABLE);		config = inw(iobase+VLSI_PIO_IRCFG);		mb();		outw((config & ~IRCFG_ENTX) | IRCFG_ENRX, iobase+VLSI_PIO_IRCFG);		wmb();		outw(IRENABLE_IREN, iobase+VLSI_PIO_IRENABLE);	}	else		ret = 1;			/* no speed-change-check */	mb();	outw(0, iobase+VLSI_PIO_PROMPT);	if (netif_queue_stopped(ndev)) {		netif_wake_queue(ndev);		printk(KERN_DEBUG "%s: queue awoken\n", __FUNCTION__);	}	return ret;}#if 0	/* disable ACTIVITY handling for now */static int vlsi_act_interrupt(struct net_device *ndev){	printk(KERN_DEBUG "%s\n", __FUNCTION__);	return 0;}#endifstatic void vlsi_interrupt(int irq, void *dev_instance, struct pt_regs *regs){	struct net_device *ndev = dev_instance;	vlsi_irda_dev_t *idev = ndev->priv;	unsigned	iobase;	u8		irintr;	int 		boguscount = 32;	int		no_speed_check = 0;	unsigned	got_act;	unsigned long	flags;	got_act = 0;	iobase = ndev->base_addr;	spin_lock_irqsave(&idev->lock,flags);	do {		irintr = inb(iobase+VLSI_PIO_IRINTR);		rmb();		outb(irintr, iobase+VLSI_PIO_IRINTR); /* acknowledge asap */		wmb();		if (!(irintr&=IRINTR_INT_MASK))		/* not our INT - probably shared */			break;//		vlsi_reg_debug(iobase,__FUNCTION__);		if (irintr&IRINTR_RPKTINT)			no_speed_check |= vlsi_rx_interrupt(ndev);		if (irintr&IRINTR_TPKTINT)			no_speed_check |= vlsi_tx_interrupt(ndev);#if 0	/* disable ACTIVITY handling for now */		if (got_act  &&  irintr==IRINTR_ACTIVITY) /* nothing new */			break;		if ((irintr&IRINTR_ACTIVITY) && !(irintr^IRINTR_ACTIVITY) ) {			no_speed_check |= vlsi_act_interrupt(ndev);			got_act = 1;		}#endif		if (irintr & ~(IRINTR_RPKTINT|IRINTR_TPKTINT|IRINTR_ACTIVITY))			printk(KERN_DEBUG "%s: IRINTR = %02x\n",				__FUNCTION__, (unsigned)irintr);				} while (--boguscount > 0);	spin_unlock_irqrestore(&idev->lock,flags);	if (boguscount <= 0)		printk(KERN_ERR "%s: too much work in interrupt!\n", __FUNCTION__);	else if (!no_speed_check) {		if (idev->new_baud)			vlsi_set_baud(ndev);	}}/**************************************************************//* writing all-zero to the VLSI PCI IO register area seems to prevent * some occasional situations where the hardware fails (symptoms are  * what appears as stalled tx/rx state machines, i.e. everything ok for * receive or transmit but hw makes no progress or is unable to access * the bus memory locations). * Best place to call this is immediately after/before the internal clock * gets started/stopped. */static inline void vlsi_clear_regs(unsigned iobase){	unsigned	i;	const unsigned	chip_io_extent = 32;	for (i = 0; i < chip_io_extent; i += sizeof(u16))		outw(0, iobase + i);}static int vlsi_open(struct net_device *ndev){	vlsi_irda_dev_t *idev = ndev->priv;	struct pci_dev *pdev = idev->pdev;	int	err;	char	hwname[32];	if (pci_request_regions(pdev,drivername)) {		printk(KERN_ERR "%s: io resource busy\n", __FUNCTION__);		return -EAGAIN;	}	/* under some rare occasions the chip apparently comes up	 * with IRQ's pending. So we get interrupts invoked much too early	 * which will immediately kill us again :-(	 * so we better w/c pending IRQ and disable them all	 */	outb(IRINTR_INT_MASK, ndev->base_addr+VLSI_PIO_IRINTR);	if (request_irq(ndev->irq, vlsi_interrupt, SA_SHIRQ,			drivername, ndev)) {		printk(KERN_ERR "%s: couldn't get IRQ: %d\n",			__FUNCTION__, ndev->irq);		pci_release_regions(pdev);		return -EAGAIN;	}	printk(KERN_INFO "%s: got resources for %s - irq=%d / io=%04lx\n",		__FUNCTION__, ndev->name, ndev->irq, ndev->base_addr );	if (vlsi_set_clock(pdev)) {		printk(KERN_ERR "%s: no valid clock source\n",			__FUNCTION__);		free_irq(ndev->irq,ndev);		pci_release_regions(pdev);		return -EIO;	}	vlsi_start_clock(pdev);	vlsi_clear_regs(ndev->base_addr);	err = vlsi_init_ring(idev);	if (err) {		vlsi_unset_clock(pdev);		free_irq(ndev->irq,ndev);		pci_release_regions(pdev);		return err;	}	vlsi_init_chip(ndev);	printk(KERN_INFO "%s: IrPHY setup: %d baud (%s), %s SIR-pulses\n",		__FUNCTION__, idev->baud, 		(idev->mode==IFF_SIR)?"SIR":((idev->mode==IFF_MIR)?"MIR":"FIR"),		(sirpulse)?"3/16 bittime":"short");	vlsi_arm_rx(&idev->rx_ring);	do_gettimeofday(&idev->last_rx);  /* first mtt may start from now on */	sprintf(hwname, "VLSI-FIR @ 0x%04x", (unsigned)ndev->base_addr);	idev->irlap = irlap_open(ndev,&idev->qos,hwname);	netif_start_queue(ndev);	outw(0, ndev->base_addr+VLSI_PIO_PROMPT);	/* kick hw state machine */	printk(KERN_INFO "%s: device %s operational using (%d,%d) tx,rx-ring\n",		__FUNCTION__, ndev->name, ringsize[0], ringsize[1]);	return 0;}static int vlsi_close(struct net_device *ndev){	vlsi_irda_dev_t *idev = ndev->priv;	struct pci_dev *pdev = idev->pdev;

⌨️ 快捷键说明

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