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

📄 3c505.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 && time_before(jiffies, timeout));		if (time_after_eq(jiffies, timeout))			TIMEOUT_MSG(__LINE__);	}}/****************************************************** * * initialise Etherlink Plus board * ******************************************************/static inline 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 net_device_stats));	/*	 * 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 ************************************************************/__initfunc(static int elp_sense(struct device *dev)){	int timeout;	int addr = dev->base_addr;	const char *name = dev->name;	long flags;	byte orig_HSR;	if (check_region(addr, 0xf))		return -1;	orig_HSR = inb_status(addr);	if (elp_debug > 0)		printk(search_msg, name, addr);	if (orig_HSR == 0xff) {		if (elp_debug > 0)			printk(notfound_msg, 1);		return -1;	}	/* 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_HSR & DIR) {		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */		outb(0, dev->base_addr + PORT_CONTROL);		timeout = jiffies + 30*HZ/100;		while (time_before(jiffies, timeout));		restore_flags(flags);		if (inb_status(addr) & DIR) {			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(DIR, dev->base_addr + PORT_CONTROL);		timeout = jiffies + 30*HZ/100;		while (time_before(jiffies, timeout));		restore_flags(flags);		if (!(inb_status(addr) & DIR)) {			if (elp_debug > 0)				printk(notfound_msg, 3);			return -1;		}	}	/*	 * It certainly looks like a 3c505.	 */	if (elp_debug > 0)		printk(found_msg);	return 0;}/************************************************************* * * Search through addr_list[] and try to find a 3C505 * Called only by eplus_probe *************************************************************/__initfunc(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). */__initfunc(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;        }	adapter->send_pcb_semaphore = 0;	for (tries1 = 0; tries1 < 3; tries1++) {		outb_control((adapter->hcr_val | CMDE) & ~DIR, dev);		/* First try to write just one byte, to see if the card is		 * responding at all normally.		 */		timeout = jiffies + 5*HZ/100;		okay = 0;		while (time_before(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*HZ/100;			while (time_before(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 (time_before(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(adapter->hcr_val | FLSH | ATTN, dev);		outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);	}	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);		}		/* 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: IRQ probe failed: check 3c505 jumpers.\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(adapter->hcr_val & ~CMDE, dev);	/*	 * copy Ethernet address into structure	 */	for (i = 0; i < 6; i++)		dev->dev_addr[i] = adapter->rx_pcb.data.eth_addr[i];	/* find a DMA channel */	if (!dev->dma) {		if (dev->mem_start) {			dev->dma = dev->mem_start & 7;		}		else {			printk(KERN_WARNING "%s: warning, DMA channel not specified, using default\n", dev->name);			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("not responding to second PCB\n");	}	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 MODULE#define NAMELEN 9static char devicename[ELP_MAX_CARDS][NAMELEN] = {{0,}};static struct device dev_3c505[ELP_MAX_CARDS] ={	{ NULL,		/* device name is inserted by net_init.c */	0, 0, 0, 0,	0, 0,	0, 0, 0, NULL, elplus_probe},};static int io[ELP_MAX_CARDS] = { 0, };static int irq[ELP_MAX_CARDS] = { 0, };static int dma[ELP_MAX_CARDS] = { 0, };MODULE_PARM(io, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i");MODULE_PARM(irq, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i");MODULE_PARM(dma, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i");int init_module(void){	int this_dev, found = 0;	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {		struct device *dev = &dev_3c505[this_dev];		dev->name = devicename[this_dev];		dev->irq = irq[this_dev];		dev->base_addr = io[this_dev];		if (dma[this_dev]) {			dev->dma = dma[this_dev];		} else {			dev->dma = ELP_DMA;			printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n");		}		if (io[this_dev] == 0) {			if (this_dev) break;			printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n");		}		if (register_netdev(dev) != 0) {			printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]);			if (found != 0) return 0;			return -ENXIO;		}		found++;	}	return 0;}void cleanup_module(void){	int this_dev;	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {		struct device *dev = &dev_3c505[this_dev];		if (dev->priv != NULL) {			unregister_netdev(dev);			kfree(dev->priv);			dev->priv = NULL;			release_region(dev->base_addr, ELP_IO_EXTENT);		}	}}#endif				/* MODULE */

⌨️ 快捷键说明

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