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

📄 oaknet.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	}	ei_status.dmaing |= 0x01;	outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD);	outb_p(sizeof(struct e8390_pkt_hdr), base + EN0_RCNTLO);	outb_p(0, base + EN0_RCNTHI);	outb_p(0, base + EN0_RSARLO);		/* On page boundary */	outb_p(ring_page, base + EN0_RSARHI);	outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);	if (ei_status.word16)		insw(base + OAKNET_DATA, hdr,		     sizeof(struct e8390_pkt_hdr) >> 1);	else		insb(base + OAKNET_DATA, hdr,		     sizeof(struct e8390_pkt_hdr));	/* Byte-swap the packet byte count */	hdr->count = le16_to_cpu(hdr->count);	outb_p(ENISR_RDC, base + EN0_ISR);	/* ACK Remote DMA interrupt */	ei_status.dmaing &= ~0x01;}/* * XXX - Document me. */static voidoaknet_block_input(struct net_device *dev, int count, struct sk_buff *skb,		   int ring_offset){	int base = OAKNET_BASE;	char *buf = skb->data;	/*	 * This should NOT happen. If it does, it is the LAST thing you'll	 * see.	 */	if (ei_status.dmaing) {		oaknet_dma_error(dev, "oaknet_block_input");		return;	}#ifdef OAKNET_DISINT	save_flags(flags);	cli();#endif	ei_status.dmaing |= 0x01;	ei_obp(E8390_NODMA + E8390_PAGE0 + E8390_START, base + E8390_CMD);	ei_obp(count & 0xff, base + EN0_RCNTLO);	ei_obp(count >> 8, base + EN0_RCNTHI);	ei_obp(ring_offset & 0xff, base + EN0_RSARLO);	ei_obp(ring_offset >> 8, base + EN0_RSARHI);	ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);	if (ei_status.word16) {		ei_isw(base + E8390_DATA, buf, count >> 1);		if (count & 0x01) {			buf[count - 1] = ei_ib(base + E8390_DATA);#ifdef OAKNET_HEADCHECK			bytes++;#endif		}	} else {		ei_isb(base + E8390_DATA, buf, count);	}#ifdef OAKNET_HEADCHECK	/*	 * This was for the ALPHA version only, but enough people have	 * been encountering problems so it is still here.  If you see	 * this message you either 1) have a slightly incompatible clone	 * or 2) have noise/speed problems with your bus.	 */	/* DMA termination address check... */	{		int addr, tries = 20;		do {			/* DON'T check for 'ei_ibp(EN0_ISR) & ENISR_RDC' here			   -- it's broken for Rx on some cards! */			int high = ei_ibp(base + EN0_RSARHI);			int low = ei_ibp(base + EN0_RSARLO);			addr = (high << 8) + low;			if (((ring_offset + bytes) & 0xff) == low)				break;		} while (--tries > 0);	 	if (tries <= 0)			printk("%s: RX transfer address mismatch,"			       "%#4.4x (expected) vs. %#4.4x (actual).\n",			       dev->name, ring_offset + bytes, addr);	}#endif	ei_obp(ENISR_RDC, base + EN0_ISR);	/* ACK Remote DMA interrupt */	ei_status.dmaing &= ~0x01;#ifdef OAKNET_DISINT	restore_flags(flags);#endif}/* * static void oaknet_block_output() * * Description: *   This routine... * * Input(s): *  *dev        - Pointer to the device structure for this driver. *   count      - Number of bytes to be transferred. *  *buf        -  *   start_page -  * * Output(s): *   N/A * * Returns: *   N/A * */static voidoaknet_block_output(struct net_device *dev, int count,		    const unsigned char *buf, int start_page){	int base = E8390_BASE;#if 0	int bug;#endif	unsigned long start;#ifdef OAKNET_DISINT	unsigned long flags;#endif#ifdef OAKNET_HEADCHECK	int retries = 0;#endif	/* Round the count up for word writes. */	if (ei_status.word16 && (count & 0x1))		count++;	/*	 * This should NOT happen. If it does, it is the LAST thing you'll	 * see.	 */	if (ei_status.dmaing) {		oaknet_dma_error(dev, "oaknet_block_output");		return;	}#ifdef OAKNET_DISINT	save_flags(flags);	cli();#endif	ei_status.dmaing |= 0x01;	/* Make sure we are in page 0. */	ei_obp(E8390_PAGE0 + E8390_START + E8390_NODMA, base + E8390_CMD);#ifdef OAKNET_HEADCHECKretry:#endif#if 0	/*	 * The 83902 documentation states that the processor needs to	 * do a "dummy read" before doing the remote write to work	 * around a chip bug they don't feel like fixing.	 */	bug = 0;	while (1) {		unsigned int rdhi;		unsigned int rdlo;		/* Now the normal output. */		ei_obp(ENISR_RDC, base + EN0_ISR);		ei_obp(count & 0xff, base + EN0_RCNTLO);		ei_obp(count >> 8,   base + EN0_RCNTHI);		ei_obp(0x00, base + EN0_RSARLO);		ei_obp(start_page, base + EN0_RSARHI);		if (bug++)			break;		/* Perform the dummy read */		rdhi = ei_ibp(base + EN0_CRDAHI);		rdlo = ei_ibp(base + EN0_CRDALO);		ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);		while (1) {			unsigned int nrdhi;			unsigned int nrdlo;			nrdhi = ei_ibp(base + EN0_CRDAHI);			nrdlo = ei_ibp(base + EN0_CRDALO);			if ((rdhi != nrdhi) || (rdlo != nrdlo))				break;		}	}#else#ifdef OAKNET_RWFIX	/*	 * Handle the read-before-write bug the same way as the	 * Crynwr packet driver -- the Nat'l Semi. method doesn't work.	 * Actually this doesn't always work either, but if you have	 * problems with your 83902 this is better than nothing!	 */	ei_obp(0x42, base + EN0_RCNTLO);	ei_obp(0x00, base + EN0_RCNTHI);	ei_obp(0x42, base + EN0_RSARLO);	ei_obp(0x00, base + EN0_RSARHI);	ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);	/* Make certain that the dummy read has occurred. */	udelay(6);#endif	ei_obp(ENISR_RDC, base + EN0_ISR);	/* Now the normal output. */	ei_obp(count & 0xff, base + EN0_RCNTLO);	ei_obp(count >> 8,   base + EN0_RCNTHI);	ei_obp(0x00, base + EN0_RSARLO);	ei_obp(start_page, base + EN0_RSARHI);#endif /* 0/1 */	ei_obp(E8390_RWRITE + E8390_START, base + E8390_CMD);	if (ei_status.word16) {		ei_osw(E8390_BASE + E8390_DATA, buf, count >> 1);	} else {		ei_osb(E8390_BASE + E8390_DATA, buf, count);	}#ifdef OAKNET_DISINT	restore_flags(flags);#endif	start = jiffies;#ifdef OAKNET_HEADCHECK	/*	 * This was for the ALPHA version only, but enough people have	 * been encountering problems so it is still here.	 */		{		/* DMA termination address check... */		int addr, tries = 20;		do {			int high = ei_ibp(base + EN0_RSARHI);			int low = ei_ibp(base + EN0_RSARLO);			addr = (high << 8) + low;			if ((start_page << 8) + count == addr)				break;		} while (--tries > 0);		if (tries <= 0) {			printk("%s: Tx packet transfer address mismatch,"			       "%#4.4x (expected) vs. %#4.4x (actual).\n",			       dev->name, (start_page << 8) + count, addr);			if (retries++ == 0)				goto retry;		}	}#endif	while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) {		if (jiffies - start > OAKNET_WAIT) {			printk("%s: timeout waiting for Tx RDC.\n", dev->name);			oaknet_reset_8390(dev);			NS8390_init(dev, TRUE);			break;		}	}		ei_obp(ENISR_RDC, base + EN0_ISR);	/* Ack intr. */	ei_status.dmaing &= ~0x01;}/* * static void oaknet_dma_error() * * Description: *   This routine prints out a last-ditch informative message to the console *   indicating that a DMA error occurred. If you see this, it's the last *   thing you'll see. * * Input(s): *  *dev  - Pointer to the device structure for this driver. *  *name - Informative text (e.g. function name) indicating where the *          DMA error occurred. * * Output(s): *   N/A * * Returns: *   N/A * */static voidoaknet_dma_error(struct net_device *dev, const char *name){	printk(KERN_EMERG "%s: DMAing conflict in %s."	       "[DMAstat:%d][irqlock:%d][intr:%ld]\n",	       dev->name, name, ei_status.dmaing, ei_status.irqlock,	       dev->interrupt);}/* * Oak Ethernet module load interface. */static int __init oaknet_init_module (void){	if (oaknet_devs != NULL)		return (-EBUSY);	return (oaknet_init());}/* * Oak Ethernet module unload interface. */static void __exit oaknet_cleanup_module (void){	if (oaknet_devs == NULL)		return;	if (oaknet_devs->priv != NULL) {		int ioaddr = oaknet_devs->base_addr;		void *priv = oaknet_devs->priv;		free_irq(oaknet_devs->irq, oaknet_devs);		release_region(ioaddr, OAKNET_IO_SIZE);		iounmap(ioaddr);		unregister_netdev(oaknet_dev);		kfree(priv);	}	/* Convert to loop once driver supports multiple devices. */	kfree(oaknet_devs);}module_init(oaknet_init_module);module_exit(oaknet_cleanup_module);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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