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

📄 ne2.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
						/* Select page 0 */			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},			{0x49,	EN0_DCFG},  /* Set WORD-wide (0x49) access. */			{0x00,	EN0_RCNTLO},  /* Clear the count regs. */			{0x00,	EN0_RCNTHI},			{0x00,	EN0_IMR},  /* Mask completion irq. */			{0xFF,	EN0_ISR},			{E8390_RXOFF, EN0_RXCR},  /* 0x20  Set to monitor */			{E8390_TXOFF, EN0_TXCR},  /* 0x02  and loopback mode. */			{32,	EN0_RCNTLO},			{0x00,	EN0_RCNTHI},			{0x00,	EN0_RSARLO},  /* DMA starting at 0x0000. */			{0x00,	EN0_RSARHI},			{E8390_RREAD+E8390_START, E8390_CMD},		};		for (i = 0; i < ARRAY_SIZE(program_seq); i++)			outb_p(program_seq[i].value, base_addr +				program_seq[i].offset);	}	for(i = 0; i < 6 /*sizeof(SA_prom)*/; i+=1) {		SA_prom[i] = inb(base_addr + NE_DATAPORT);	}	/* I don't know whether the previous sequence includes the general           board reset procedure, so better don't omit it and just overwrite           the garbage read from a DE-320 with correct stuff. */	if (mca_read_stored_pos(slot, 0) == 0xea) {		unsigned int v;		for (i = 0; i < 3; i++) { 			v = dlink_get_eeprom(i, base_addr);			SA_prom[(i << 1)    ] = v & 0xff;			SA_prom[(i << 1) + 1] = (v >> 8) & 0xff;		}	}	start_page = NESM_START_PG;	stop_page = NESM_STOP_PG;	dev->irq=irq;	/* Snarf the interrupt now.  There's no point in waiting since we cannot	   share and the board will usually be enabled. */	retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);	if (retval) {		printk (" unable to get IRQ %d (irqval=%d).\n",				dev->irq, retval);		goto out;	}	dev->base_addr = base_addr;	for(i = 0; i < ETHER_ADDR_LEN; i++)		dev->dev_addr[i] = SA_prom[i];	printk(" %s\n", print_mac(mac, dev->dev_addr));	printk("%s: %s found at %#x, using IRQ %d.\n",			dev->name, name, base_addr, dev->irq);	mca_set_adapter_procfn(slot, (MCA_ProcFn) ne2_procinfo, dev);	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;#ifdef CONFIG_NET_POLL_CONTROLLER	dev->poll_controller = ei_poll;#endif	NS8390_init(dev, 0);	retval = register_netdev(dev);	if (retval)		goto out1;	return 0;out1:	mca_set_adapter_procfn( ei_status.priv, NULL, NULL);	free_irq(dev->irq, dev);out:	release_region(base_addr, NE_IO_EXTENT);	return retval;}static int ne_open(struct net_device *dev){	ei_open(dev);	return 0;}static int ne_close(struct net_device *dev){	if (ei_debug > 1)		printk("%s: Shutting down ethercard.\n", dev->name);	ei_close(dev);	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 net_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 (time_after(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 net_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].\n",				dev->name, ei_status.dmaing, ei_status.irqlock);		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 net_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].\n",				dev->name, ei_status.dmaing, ei_status.irqlock);		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 net_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]\n",				dev->name, ei_status.dmaing, ei_status.irqlock);		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 (time_after(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 */static struct net_device *dev_ne[MAX_NE_CARDS];static int io[MAX_NE_CARDS];static int irq[MAX_NE_CARDS];static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */MODULE_LICENSE("GPL");module_param_array(io, int, NULL, 0);module_param_array(irq, int, NULL, 0);module_param_array(bad, int, NULL, 0);MODULE_PARM_DESC(io, "(ignored)");MODULE_PARM_DESC(irq, "(ignored)");MODULE_PARM_DESC(bad, "(ignored)");/* Module code fixed by David Weinehall */int __init init_module(void){	struct net_device *dev;	int this_dev, found = 0;	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {		dev = alloc_ei_netdev();		if (!dev)			break;		dev->irq = irq[this_dev];		dev->mem_end = bad[this_dev];		dev->base_addr = io[this_dev];		if (do_ne2_probe(dev) == 0) {			dev_ne[found++] = dev;			continue;		}		free_netdev(dev);		break;	}	if (found)		return 0;	printk(KERN_WARNING "ne2.c: No NE/2 card found\n");	return -ENXIO;}static void cleanup_card(struct net_device *dev){	mca_mark_as_unused(ei_status.priv);	mca_set_adapter_procfn( ei_status.priv, NULL, NULL);	free_irq(dev->irq, dev);	release_region(dev->base_addr, NE_IO_EXTENT);}void __exit cleanup_module(void){	int this_dev;	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {		struct net_device *dev = dev_ne[this_dev];		if (dev) {			unregister_netdev(dev);			cleanup_card(dev);			free_netdev(dev);		}	}}#endif /* MODULE */

⌨️ 快捷键说明

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