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

📄 ne2.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	ei_status.name = name;	ei_status.tx_start_page = start_page;	ei_status.stop_page = stop_page;	ei_status.word16 = (2 == 2);	ei_status.rx_start_page = start_page + TX_PAGES;#ifdef PACKETBUF_MEMSIZE	/* Allow the packet buffer size to be overridden by know-it-alls. */	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;#endif	ei_status.reset_8390 = &ne_reset_8390;	ei_status.block_input = &ne_block_input;	ei_status.block_output = &ne_block_output;	ei_status.get_8390_hdr = &ne_get_8390_hdr;		ei_status.priv = slot;		dev->open = &ne_open;	dev->stop = &ne_close;	NS8390_init(dev, 0);	return 0;}static int ne_open(struct device *dev){	ei_open(dev);	MOD_INC_USE_COUNT;	return 0;}static int ne_close(struct device *dev){	if (ei_debug > 1)		printk("%s: Shutting down ethercard.\n", dev->name);	ei_close(dev);	MOD_DEC_USE_COUNT;	return 0;}/* Hard reset the card.  This used to pause for the same period that a   8390 reset command required, but that shouldn't be necessary. */static void ne_reset_8390(struct device *dev){	unsigned long reset_start_time = jiffies;	if (ei_debug > 1) 		printk("resetting the 8390 t=%ld...", jiffies);	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);	ei_status.txing = 0;	ei_status.dmaing = 0;	/* This check _should_not_ be necessary, omit eventually. */	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)		if (jiffies - reset_start_time > 2*HZ/100) {			printk("%s: ne_reset_8390() did not complete.\n", 					dev->name);			break;		}	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */}/* Grab the 8390 specific header. Similar to the block_input routine, but   we don't need to be concerned with ring wrap as the header will be at   the start of a page, so we optimize accordingly. */static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, 		int ring_page){	int nic_base = dev->base_addr;	/* This *shouldn't* happen. 	   If it does, it's the last thing you'll see */	if (ei_status.dmaing) {		printk("%s: DMAing conflict in ne_get_8390_hdr "				"[DMAstat:%d][irqlock:%d][intr:%ld].\n",				dev->name, ei_status.dmaing, ei_status.irqlock,				dev->interrupt);		return;	}	ei_status.dmaing |= 0x01;	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);	outb_p(0, nic_base + EN0_RCNTHI);	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */	outb_p(ring_page, nic_base + EN0_RSARHI);	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);	if (ei_status.word16)		insw(NE_BASE + NE_DATAPORT, hdr, 				sizeof(struct e8390_pkt_hdr)>>1);	else		insb(NE_BASE + NE_DATAPORT, hdr, 				sizeof(struct e8390_pkt_hdr));	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */	ei_status.dmaing &= ~0x01;}/* Block input and output, similar to the Crynwr packet driver.  If you   are porting to a new ethercard, look at the packet driver source for   hints. The NEx000 doesn't share the on-board packet memory -- you have   to put the packet out through the "remote DMA" dataport using outb. */static void ne_block_input(struct device *dev, int count, struct sk_buff *skb, 		int ring_offset){#ifdef NE_SANITY_CHECK	int xfer_count = count;#endif	int nic_base = dev->base_addr;	char *buf = skb->data;	/* This *shouldn't* happen. 	   If it does, it's the last thing you'll see */	if (ei_status.dmaing) {		printk("%s: DMAing conflict in ne_block_input "				"[DMAstat:%d][irqlock:%d][intr:%ld].\n",				dev->name, ei_status.dmaing, ei_status.irqlock,				dev->interrupt);		return;	}	ei_status.dmaing |= 0x01;	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);	outb_p(count & 0xff, nic_base + EN0_RCNTLO);	outb_p(count >> 8, nic_base + EN0_RCNTHI);	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);	if (ei_status.word16) {		insw(NE_BASE + NE_DATAPORT,buf,count>>1);		if (count & 0x01) {			buf[count-1] = inb(NE_BASE + NE_DATAPORT);#ifdef NE_SANITY_CHECK			xfer_count++;#endif		}	} else {		insb(NE_BASE + NE_DATAPORT, buf, count);	}#ifdef NE_SANITY_CHECK	/* 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. */	if (ei_debug > 1) {	/* DMA termination address check... */		int addr, tries = 20;		do {			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here			   -- it's broken for Rx on some cards! */			int high = inb_p(nic_base + EN0_RSARHI);			int low = inb_p(nic_base + EN0_RSARLO);			addr = (high << 8) + low;			if (((ring_offset + xfer_count) & 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 + xfer_count, addr);	}#endif	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */	ei_status.dmaing &= ~0x01;}static void ne_block_output(struct device *dev, int count,		const unsigned char *buf, const int start_page){	int nic_base = NE_BASE;	unsigned long dma_start;#ifdef NE_SANITY_CHECK	int retries = 0;#endif	/* Round the count up for word writes. Do we need to do this?	   What effect will an odd byte count have on the 8390?	   I should check someday. */	if (ei_status.word16 && (count & 0x01))		count++;	/* This *shouldn't* happen. 	   If it does, it's the last thing you'll see */	if (ei_status.dmaing) {		printk("%s: DMAing conflict in ne_block_output."				"[DMAstat:%d][irqlock:%d][intr:%ld]\n",				dev->name, ei_status.dmaing, ei_status.irqlock,				dev->interrupt);		return;	}	ei_status.dmaing |= 0x01;	/* We should already be in page 0, but to be safe... */	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);#ifdef NE_SANITY_CHECKretry:#endif#ifdef NE8390_RW_BUGFIX	/* Handle the read-before-write bug the same way as the	   Crynwr packet driver -- the NatSemi method doesn't work.	   Actually this doesn't always work either, but if you have	   problems with your NEx000 this is better than nothing! */	outb_p(0x42, nic_base + EN0_RCNTLO);	outb_p(0x00, nic_base + EN0_RCNTHI);	outb_p(0x42, nic_base + EN0_RSARLO);	outb_p(0x00, nic_base + EN0_RSARHI);	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);	/* Make certain that the dummy read has occurred. */	SLOW_DOWN_IO;	SLOW_DOWN_IO;	SLOW_DOWN_IO;#endif	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Now the normal output. */	outb_p(count & 0xff, nic_base + EN0_RCNTLO);	outb_p(count >> 8,   nic_base + EN0_RCNTHI);	outb_p(0x00, nic_base + EN0_RSARLO);	outb_p(start_page, nic_base + EN0_RSARHI);	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);	if (ei_status.word16) {		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);	} else {		outsb(NE_BASE + NE_DATAPORT, buf, count);	}	dma_start = jiffies;#ifdef NE_SANITY_CHECK	/* This was for the ALPHA version only, but enough people have	   been encountering problems so it is still here. */	if (ei_debug > 1) {		/* DMA termination address check... */		int addr, tries = 20;		do {			int high = inb_p(nic_base + EN0_RSARHI);			int low = inb_p(nic_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 ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */			printk("%s: timeout waiting for Tx RDC.\n", dev->name);			ne_reset_8390(dev);			NS8390_init(dev,1);			break;		}	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */	ei_status.dmaing &= ~0x01;	return;}#ifdef MODULE#define MAX_NE_CARDS	4	/* Max number of NE cards per module */#define NAMELEN		8	/* # of chars for storing dev->name */static char namelist[NAMELEN * MAX_NE_CARDS] = { 0, };static struct device dev_ne[MAX_NE_CARDS] = {	{		NULL,		/* assign a chunk of namelist[] below */		0, 0, 0, 0,		0, 0,		0, 0, 0, NULL, NULL	},};static int io[MAX_NE_CARDS] = { 0, };static int irq[MAX_NE_CARDS]  = { 0, };static int bad[MAX_NE_CARDS]  = { 0, };	/* 0xbad = bad sig or no reset ack */#ifdef MODULE_PARMMODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");#endif/* Module code fixed by David Weinehall */int init_module(void){	int this_dev, found = 0;	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {		struct device *dev = &dev_ne[this_dev];		dev->name = namelist+(NAMELEN*this_dev);		dev->irq = irq[this_dev];		dev->mem_end = bad[this_dev];		dev->base_addr = io[this_dev];		dev->init = ne2_probe;		if (register_netdev(dev) != 0) {			if (found != 0) return 0;   /* Got at least one. */			printk(KERN_WARNING "ne2.c: No NE/2 card found.\n");			return -ENXIO;		}		found++;	}	return 0;}void cleanup_module(void){	int this_dev;	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {		struct device *dev = &dev_ne[this_dev];		if (dev->priv != NULL) {			mca_mark_as_unused(ei_status.priv);			mca_set_adapter_procfn( ei_status.priv, NULL, NULL);			kfree(dev->priv);			free_irq(dev->irq, dev);			release_region(dev->base_addr, NE_IO_EXTENT);			unregister_netdev(dev);		}	}}#endif /* MODULE *//* * Local variables: *  compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne2.c" *  version-control: t *  kept-new-versions: 5 * End: */

⌨️ 快捷键说明

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