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

📄 3c505.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
		adapter->tx_pcb.length = 6 * dev->mc_count;		for (i = 0; i < dev->mc_count; i++) {			memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr, 6);			dmi = dmi->next;		}		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;		if (!send_pcb(dev, &adapter->tx_pcb))			printk("%s: couldn't send set_multicast command\n", dev->name);		else {			int timeout = jiffies + TIMEOUT;			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout);			if (jiffies >= timeout) {				TIMEOUT_MSG(__LINE__);			}		}		if (dev->mc_count)			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;		else		/* num_addrs == 0 */			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;	} else		adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC;	/*	 * configure adapter to receive messages (as specified above)	 * and wait for response	 */	if (elp_debug >= 3)		printk("%s: sending 82586 configure command\n", dev->name);	adapter->tx_pcb.command = CMD_CONFIGURE_82586;	adapter->tx_pcb.length = 2;	adapter->got[CMD_CONFIGURE_82586] = 0;	if (!send_pcb(dev, &adapter->tx_pcb))		printk("%s: couldn't send 82586 configure command\n", dev->name);	else {		int timeout = jiffies + TIMEOUT;		while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout);		if (jiffies >= timeout)			TIMEOUT_MSG(__LINE__);	}}/****************************************************** * * initialise Etherlink Plus board * ******************************************************/static void elp_init(struct device *dev){	elp_device *adapter = dev->priv;	/*	 * set ptrs to various functions	 */	dev->open = elp_open;	/* local */	dev->stop = elp_close;	/* local */	dev->get_stats = elp_get_stats;		/* local */	dev->hard_start_xmit = elp_start_xmit;	/* local */	dev->set_multicast_list = elp_set_mc_list;	/* local */	/* Setup the generic properties */	ether_setup(dev);	/*	 * setup ptr to adapter specific information	 */	memset(&(adapter->stats), 0, sizeof(struct enet_statistics));	/*	 * memory information	 */	dev->mem_start = dev->mem_end = dev->rmem_end = dev->rmem_start = 0;}/************************************************************ * * A couple of tests to see if there's 3C505 or not * Called only by elp_autodetect ************************************************************/static int elp_sense(struct device *dev){	int timeout;	int addr = dev->base_addr;	const char *name = dev->name;	long flags;	byte orig_HCR, orig_HSR;	if (check_region(addr, 0xf))		return -1;	orig_HCR = inb_control(addr);	orig_HSR = inb_status(addr);	if (elp_debug > 0)		printk(search_msg, name, addr);	if (((orig_HCR == 0xff) && (orig_HSR == 0xff)) ||	    ((orig_HCR & DIR) != (orig_HSR & DIR))) {		if (elp_debug > 0)			printk(notfound_msg, 1);		return -1;	/* It can't be 3c505 if HCR.DIR != HSR.DIR */	}	/* Enable interrupts - we need timers! */	save_flags(flags);	sti();	/* Wait for a while; the adapter may still be booting up */	if (elp_debug > 0)		printk(stilllooking_msg);	if (orig_HCR & DIR) {		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */		outb_control(orig_HCR & ~DIR, addr);		timeout = jiffies + 30;		while (jiffies < timeout);		restore_flags(flags);		if (inb_status(addr) & DIR) {			outb_control(orig_HCR, addr);			if (elp_debug > 0)				printk(notfound_msg, 2);			return -1;		}	} else {		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */		outb_control(orig_HCR | DIR, addr);		timeout = jiffies + 30;		while (jiffies < timeout);		restore_flags(flags);		if (!(inb_status(addr) & DIR)) {			outb_control(orig_HCR, addr);			if (elp_debug > 0)				printk(notfound_msg, 3);			return -1;		}	}	/*	 * It certainly looks like a 3c505. If it has DMA enabled, it needs	 * a hard reset. Also, do a hard reset if selected at the compile time.	 */	if (elp_debug > 0)		printk(found_msg);	return 0;}/************************************************************* * * Search through addr_list[] and try to find a 3C505 * Called only by eplus_probe *************************************************************/static int elp_autodetect(struct device *dev){	int idx = 0;	/* if base address set, then only check that address	   otherwise, run through the table */	if (dev->base_addr != 0) {	/* dev->base_addr == 0 ==> plain autodetect */		if (elp_sense(dev) == 0)			return dev->base_addr;	} else		while ((dev->base_addr = addr_list[idx++])) {			if (elp_sense(dev) == 0)				return dev->base_addr;		}	/* could not find an adapter */	if (elp_debug > 0)		printk(couldnot_msg, dev->name);	return 0;		/* Because of this, the layer above will return -ENODEV */}/****************************************************** * * probe for an Etherlink Plus board at the specified address * ******************************************************//* There are three situations we need to be able to detect here: *  a) the card is idle *  b) the card is still booting up *  c) the card is stuck in a strange state (some DOS drivers do this) * * In case (a), all is well.  In case (b), we wait 10 seconds to see if the * card finishes booting, and carry on if so.  In case (c), we do a hard reset, * loop round, and hope for the best. * * This is all very unpleasant, but hopefully avoids the problems with the old * probe code (which had a 15-second delay if the card was idle, and didn't * work at all if it was in a weird state). */int elplus_probe(struct device *dev){	elp_device *adapter;	int i, tries, tries1, timeout, okay;	/*	 *  setup adapter structure	 */	dev->base_addr = elp_autodetect(dev);	if (!(dev->base_addr))		return -ENODEV;	/*	 * setup ptr to adapter specific information	 */	adapter = (elp_device *) (dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL));	if (adapter == NULL) {		printk("%s: out of memory\n", dev->name);		return -ENODEV;        }	for (tries1 = 0; tries1 < 3; tries1++) {		outb_control((inb_control(dev->base_addr) | CMDE) & ~DIR, dev->base_addr);		/* First try to write just one byte, to see if the card is		 * responding at all normally.		 */		timeout = jiffies + 5;		okay = 0;		while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE));		if ((inb_status(dev->base_addr) & HCRE)) {			outb_command(0, dev->base_addr);	/* send a spurious byte */			timeout = jiffies + 5;			while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE));			if (inb_status(dev->base_addr) & HCRE)				okay = 1;		}		if (!okay) {			/* Nope, it's ignoring the command register.  This means that			 * either it's still booting up, or it's died.			 */			printk("%s: command register wouldn't drain, ", dev->name);			if ((inb_status(dev->base_addr) & 7) == 3) {				/* If the adapter status is 3, it *could* still be booting.				 * Give it the benefit of the doubt for 10 seconds.				 */				printk("assuming 3c505 still starting\n");				timeout = jiffies + 10 * HZ;				while (jiffies < timeout && (inb_status(dev->base_addr) & 7));				if (inb_status(dev->base_addr) & 7) {					printk("%s: 3c505 failed to start\n", dev->name);				} else {					okay = 1;  /* It started */				}			} else {				/* Otherwise, it must just be in a strange state.  We probably				 * need to kick it.				 */				printk("3c505 is sulking\n");			}		}		for (tries = 0; tries < 5 && okay; tries++) {			/*			 * Try to set the Ethernet address, to make sure that the board			 * is working.			 */			adapter->tx_pcb.command = CMD_STATION_ADDRESS;			adapter->tx_pcb.length = 0;			autoirq_setup(0);			if (!send_pcb(dev, &adapter->tx_pcb)) {				printk("%s: could not send first PCB\n", dev->name);				autoirq_report(0);				continue;			}			if (!receive_pcb(dev, &adapter->rx_pcb)) {				printk("%s: could not read first PCB\n", dev->name);				autoirq_report(0);				continue;			}			if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) ||			    (adapter->rx_pcb.length != 6)) {				printk("%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length);				autoirq_report(0);				continue;			}			goto okay;		}		/* It's broken.  Do a hard reset to re-initialise the board,		 * and try again.		 */		printk(KERN_INFO "%s: resetting adapter\n", dev->name);		outb_control(inb_control(dev->base_addr) | FLSH | ATTN, dev->base_addr);		outb_control(inb_control(dev->base_addr) & ~(FLSH | ATTN), dev->base_addr);	}	printk("%s: failed to initialise 3c505\n", dev->name);	return -ENODEV;      okay:	if (dev->irq) {		/* Is there a preset IRQ? */		int rpt = autoirq_report(0);		if (dev->irq != rpt) {			printk("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);			return -ENODEV;		}		/* if dev->irq == autoirq_report(0), all is well */	} else			/* No preset IRQ; just use what we can detect */		dev->irq = autoirq_report(0);	switch (dev->irq) {	/* Legal, sane? */	case 0:		printk("%s: No IRQ reported by autoirq_report().\n", dev->name);		printk("%s: Check the jumpers of your 3c505 board.\n", dev->name);		return -ENODEV;	case 1:	case 6:	case 8:	case 13:		printk("%s: Impossible IRQ %d reported by autoirq_report().\n",		       dev->name, dev->irq);		return -ENODEV;	}	/*	 *  Now we have the IRQ number so we can disable the interrupts from	 *  the board until the board is opened.	 */	outb_control(inb_control(dev->base_addr) & ~CMDE, dev->base_addr);	/*	 * copy ethernet address into structure	 */	for (i = 0; i < 6; i++)		dev->dev_addr[i] = adapter->rx_pcb.data.eth_addr[i];	/* set up the DMA channel */	dev->dma = ELP_DMA;	/*	 * print remainder of startup message	 */	printk("%s: 3c505 at %#lx, irq %d, dma %d, ",	       dev->name, dev->base_addr, dev->irq, dev->dma);	printk("addr %02x:%02x:%02x:%02x:%02x:%02x, ",	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);	/*	 * read more information from the adapter	 */	adapter->tx_pcb.command = CMD_ADAPTER_INFO;	adapter->tx_pcb.length = 0;	if (!send_pcb(dev, &adapter->tx_pcb) ||	    !receive_pcb(dev, &adapter->rx_pcb) ||	    (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) ||	    (adapter->rx_pcb.length != 10)) {		printk("%s: not responding to second PCB\n", dev->name);	}	printk("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz);	/*	 * reconfigure the adapter memory to better suit our purposes	 */	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;	adapter->tx_pcb.length = 12;	adapter->tx_pcb.data.memconf.cmd_q = 8;	adapter->tx_pcb.data.memconf.rcv_q = 8;	adapter->tx_pcb.data.memconf.mcast = 10;	adapter->tx_pcb.data.memconf.frame = 10;	adapter->tx_pcb.data.memconf.rcv_b = 10;	adapter->tx_pcb.data.memconf.progs = 0;	if (!send_pcb(dev, &adapter->tx_pcb) ||	    !receive_pcb(dev, &adapter->rx_pcb) ||	    (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) ||	    (adapter->rx_pcb.length != 2)) {		printk("%s: could not configure adapter memory\n", dev->name);	}	if (adapter->rx_pcb.data.configure) {		printk("%s: adapter configuration failed\n", dev->name);	}	/*	 * and reserve the address region	 */	request_region(dev->base_addr, ELP_IO_EXTENT, "3c505");	/*	 * initialise the device	 */	elp_init(dev);	return 0;}#ifdef MODULEstatic char devicename[9] = {0,};static struct device dev_3c505 ={	devicename,		/* device name is inserted by linux/drivers/net/net_init.c */	0, 0, 0, 0,	0, 0,	0, 0, 0, NULL, elplus_probe};int io = 0x300;int irq = 0;int init_module(void){	if (io == 0)		printk("3c505: You should not use auto-probing with insmod!\n");	dev_3c505.base_addr = io;	dev_3c505.irq = irq;	if (register_netdev(&dev_3c505) != 0) {		return -EIO;	}	return 0;}void cleanup_module(void){	unregister_netdev(&dev_3c505);	kfree(dev_3c505.priv);	dev_3c505.priv = NULL;	/* If we don't do this, we can't re-insmod it later. */	release_region(dev_3c505.base_addr, ELP_IO_EXTENT);}#endif				/* MODULE *//* * Local Variables: *  c-file-style: "linux" *  tab-width: 8 *  compile-command: "gcc -D__KERNEL__ -I/discs/bibble/src/linux-1.3.69/include  -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE  -c 3c505.c" * End: */

⌨️ 快捷键说明

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