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

📄 eepro.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static unsigned eeprom_reg = EEPROM_REG_PRO;#define EESK 0x01#define EECS 0x02#define EEDI 0x04#define EEDO 0x08/* do a full reset */#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr)/* do a nice reset */#define eepro_sel_reset(ioaddr) 	{ \					outb(SEL_RESET_CMD, ioaddr); \					SLOW_DOWN; \					SLOW_DOWN; \					}/* disable all interrupts */#define eepro_dis_int(ioaddr) outb(ALL_MASK, ioaddr + INT_MASK_REG)/* clear all interrupts */#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)/* enable tx/rx */#define eepro_en_int(ioaddr) outb(ALL_MASK & ~(RX_MASK | TX_MASK), \							ioaddr + INT_MASK_REG)/* enable exec event interrupt */#define eepro_en_intexec(ioaddr) outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG)/* enable rx */#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)/* disable rx */#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)/* switch bank */#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)/* enable interrupt line */#define eepro_en_intline(ioaddr) outb(inb(ioaddr + REG1) | INT_ENABLE,\				ioaddr + REG1)/* disable interrupt line */#define eepro_dis_intline(ioaddr) outb(inb(ioaddr + REG1) & 0x7f, \				ioaddr + REG1);/* set diagnose flag */#define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr)/* ack for rx/tx int */#define eepro_ack_rxtx(ioaddr) outb (RX_INT | TX_INT, ioaddr + STATUS_REG)/* ack for rx int */#define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG)/* ack for tx int */#define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG)/* a complete sel reset */#define eepro_complete_selreset(ioaddr) { 	eepro_dis_int(ioaddr);\						lp->stats.tx_errors++;\						eepro_sel_reset(ioaddr);\						lp->tx_end = \							(XMT_LOWER_LIMIT << 8);\						lp->tx_start = lp->tx_end;\						lp->tx_last = 0;\						dev->trans_start = jiffies;\						netif_wake_queue(dev);\						eepro_en_int(ioaddr);\						eepro_en_rx(ioaddr);\					}/* Check for a network adaptor of this type, and return '0' if one exists.   If dev->base_addr == 0, probe all likely locations.   If dev->base_addr == 1, always return failure.   If dev->base_addr == 2, allocate space for the device and return success   (detachable devices only).   */int __init eepro_probe(struct net_device *dev){	int i;	int base_addr = dev->base_addr;	SET_MODULE_OWNER(dev);#ifdef PnPWakeup	/* XXXX for multiple cards should this only be run once? */		/* Wakeup: */	#define WakeupPort 0x279	#define WakeupSeq    {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\	                      0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\	                      0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\	                      0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}	{		unsigned short int WS[32]=WakeupSeq;		if (check_region(WakeupPort, 2)==0) {			if (net_debug>5)				printk(KERN_DEBUG "Waking UP\n");			outb_p(0,WakeupPort);			outb_p(0,WakeupPort);			for (i=0; i<32; i++) {				outb_p(WS[i],WakeupPort);				if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);			}		} else printk(KERN_WARNING "Checkregion Failed!\n");	}#endif	if (base_addr > 0x1ff)		/* Check a single specified location. */		return eepro_probe1(dev, base_addr);	else if (base_addr != 0)	/* Don't probe at all. */		return -ENXIO;	for (i = 0; eepro_portlist[i]; i++) {		int ioaddr = eepro_portlist[i];		if (check_region(ioaddr, EEPRO_IO_EXTENT))			continue;		if (eepro_probe1(dev, ioaddr) == 0)			return 0;	}	return -ENODEV;}void printEEPROMInfo(short ioaddr, struct net_device *dev){	unsigned short Word;	int i,j;	for (i=0, j=ee_Checksum; i<ee_SIZE; i++)		j+=read_eeprom(ioaddr,i,dev);	printk("Checksum: %#x\n",j&0xffff);	Word=read_eeprom(ioaddr, 0, dev);	printk(KERN_DEBUG "Word0:\n");	printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));	printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );	printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg)); 	printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);	if (net_debug>4)  {		Word=read_eeprom(ioaddr, 1, dev);		printk(KERN_DEBUG "Word1:\n");		printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);		printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));		printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC));		printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));		printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));		printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber));		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));	}	Word=read_eeprom(ioaddr, 5, dev);	printk(KERN_DEBUG "Word5:\n");	printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));	printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));	printk(KERN_DEBUG " Has ");	if (GetBit(Word,ee_PortTPE)) printk("TPE ");	if (GetBit(Word,ee_PortBNC)) printk("BNC ");	if (GetBit(Word,ee_PortAUI)) printk("AUI ");	printk("port(s) \n");	Word=read_eeprom(ioaddr, 6, dev);	printk(KERN_DEBUG "Word6:\n");	printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);	printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);	Word=read_eeprom(ioaddr, 7, dev);	printk(KERN_DEBUG "Word7:\n");	printk(KERN_DEBUG " INT to IRQ:\n");	printk(KERN_DEBUG);	for (i=0, j=0; i<15; i++)		if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);	printk("\n");}/* This is the real probe routine.  Linux has a history of friendly device   probes on the ISA bus.  A good device probe avoids doing writes, and   verifies that the correct device exists and functions.  */static int eepro_probe1(struct net_device *dev, short ioaddr){	unsigned short station_addr[6], id, counter;	int i,j, irqMask;	int eepro = 0;	struct eepro_local *lp;	const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};	enum iftype { AUI=0, BNC=1, TPE=2 };	/* Now, we are going to check for the signature of the	   ID_REG (register 2 of bank 0) */	id=inb(ioaddr + ID_REG); 	if (((id) & ID_REG_MASK) == ID_REG_SIG) {		/* We seem to have the 82595 signature, let's		   play with its counter (last 2 bits of		   register 2 of bank 0) to be sure. */			counter = (id & R_ROBIN_BITS);			if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == 			(counter + 0x40)) {			/* Yes, the 82595 has been found */			printk(KERN_DEBUG " id: %#x ",id);			printk(" io: %#x ",ioaddr);			/* Initialize the device structure */			dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);			if (dev->priv == NULL)				return -ENOMEM;			memset(dev->priv, 0, sizeof(struct eepro_local));			lp = (struct eepro_local *)dev->priv;			/* Now, get the ethernet hardware address from			   the EEPROM */			station_addr[0] = read_eeprom(ioaddr, 2, dev);			/* FIXME - find another way to know that we've found			 * an Etherexpress 10			 */			if (station_addr[0] == 0x0000 ||			    station_addr[0] == 0xffff) {				eepro = 3;				lp->eepro = LAN595FX_10ISA;				eeprom_reg = EEPROM_REG_10;				rcv_start = RCV_START_10;				xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;				xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;				station_addr[0] = read_eeprom(ioaddr, 2, dev);			}						station_addr[1] = read_eeprom(ioaddr, 3, dev);			station_addr[2] = read_eeprom(ioaddr, 4, dev);			if (eepro) {				printk("%s: Intel EtherExpress 10 ISA\n at %#x,",					dev->name, ioaddr);			} else if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ) { 							/* int to IRQ Mask */				eepro = 2;				printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 					dev->name, ioaddr);			} else			if (station_addr[2] == 0x00aa)  {				eepro = 1;				printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", 					dev->name, ioaddr);			}			else {				eepro = 0;				printk("%s: Intel 82595-based lan card at %#x,", 					dev->name, ioaddr);			}			/* Fill in the 'dev' fields. */			dev->base_addr = ioaddr;						for (i=0; i < 6; i++) {				dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];				printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);			}				dev->mem_start = (RCV_LOWER_LIMIT << 8);						if ((dev->mem_end & 0x3f) < 3 ||	/* RX buffer must be more than 3K */				(dev->mem_end & 0x3f) > 29)	/* and less than 29K */				dev->mem_end = (RCV_UPPER_LIMIT << 8);			else {				dev->mem_end = (dev->mem_end * 1024) +							(RCV_LOWER_LIMIT << 8);				rcv_ram = dev->mem_end - (RCV_LOWER_LIMIT << 8);			}			/* From now on, dev->mem_end - dev->mem_start contains 			 * the actual size of rx buffer 			 */						if (net_debug > 3)				printk(", %dK RCV buffer", (int)(dev->mem_end -							 dev->mem_start)/1024);											/* ............... */			if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))				dev->if_port = BNC;			else dev->if_port = TPE;			/* ............... */			if ((dev->irq < 2) && (eepro!=0)) {				i = read_eeprom(ioaddr, 1, dev);				irqMask = read_eeprom(ioaddr, 7, dev);				i &= 0x07; /* Mask off INT number */								for (j=0; ((j<16) && (i>=0)); j++) {					if ((irqMask & (1<<j))!=0) {						if (i==0) {							dev->irq = j;							break; /* found bit corresponding to irq */						}						i--; /* count bits set in irqMask */					}				}				if (dev->irq < 2) {					printk(" Duh! illegal interrupt vector stored in EEPROM.\n");						return -ENODEV;				} else 								if (dev->irq==2)					dev->irq = 9;			}						if (dev->irq > 2) {				printk(", IRQ %d, %s.\n", dev->irq,						ifmap[dev->if_port]);			}			else printk(", %s.\n", ifmap[dev->if_port]);						if ((dev->mem_start & 0xf) > 0)	/* I don't know if this is */				net_debug = dev->mem_start & 7; /* still useful or not */			if (net_debug > 3) {				i = read_eeprom(ioaddr, 5, dev);				if (i & 0x2000) /* bit 13 of EEPROM word 5 */					printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",						dev->name);			}			if (net_debug) 				printk(version);			/* Grab the region so we can find another board if autoIRQ fails. */			request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);			((struct eepro_local *)dev->priv)->lock = SPIN_LOCK_UNLOCKED;			dev->open               = eepro_open;			dev->stop               = eepro_close;			dev->hard_start_xmit    = eepro_send_packet;			dev->get_stats          = eepro_get_stats;			dev->set_multicast_list = &set_multicast_list;			dev->tx_timeout		= eepro_tx_timeout;			dev->watchdog_timeo	= TX_TIMEOUT;			/* Fill in the fields of the device structure with			   ethernet generic values */			ether_setup(dev);			/* Check the station address for the manufacturer's code */			if (net_debug>3)				printEEPROMInfo(ioaddr, dev);			/* RESET the 82595 */			eepro_reset(ioaddr);			return 0;			}		else return -ENODEV;		}	else if (net_debug > 3)		printk ("EtherExpress Pro probed failed!\n");	return -ENODEV;}/* Open/initialize the board.  This is called (in the current kernel)   sometime after booting when the 'ifconfig' program is run.   This routine should set everything up anew at each open, even   registers that "should" only need to be set once at boot, so that   there is non-reboot way to recover if something goes wrong.   */static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};static int	eepro_grab_irq(struct net_device *dev){	int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 };	int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;		eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */	/* Enable the interrupt line. */	eepro_en_intline(ioaddr);		/* be CAREFUL, BANK 0 now */	eepro_sw2bank0(ioaddr);		/* clear all interrupts */	eepro_clear_int(ioaddr);	/* Let EXEC event to interrupt */	eepro_en_intexec(ioaddr);	do {		eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */		temp_reg = inb(ioaddr + INT_NO_REG);		outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG);		eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */		if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) {			/* Twinkle the interrupt, and check if it's seen */			autoirq_setup(0);			eepro_diag(ioaddr); /* RESET the 82595 */							if (*irqp == autoirq_report(2))  /* It's a good IRQ line */				break;			/* clear all interrupts */			eepro_clear_int(ioaddr);		}	} while (*++irqp);	eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */	/* Disable the physical interrupt line. */	eepro_dis_intline(ioaddr);	eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */	/* Mask all the interrupts. */	eepro_dis_int(ioaddr);	/* clear all interrupts */	eepro_clear_int(ioaddr);

⌨️ 快捷键说明

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