📄 eepro.c
字号:
#define BNC_BIT 0x20#define REG13 0x0d#define FDX 0x00#define A_N_ENABLE 0x02 #define I_ADD_REG0 0x04#define I_ADD_REG1 0x05#define I_ADD_REG2 0x06#define I_ADD_REG3 0x07#define I_ADD_REG4 0x08#define I_ADD_REG5 0x09#define EEPROM_REG 0x0a#define EESK 0x01#define EECS 0x02#define EEDI 0x04#define EEDO 0x08/* 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). */#ifdef HAVE_DEVLIST/* Support for an alternate probe manager, which will eliminate the boilerplate below. */struct netdev_entry netcard_drv ={"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};#elsecompat_init_func(int eepro_probe(struct device *dev)){ int i; int base_addr = dev ? dev->base_addr : 0;#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;}#endifvoid printEEPROMInfo(short ioaddr){ unsigned short Word; int i,j; for (i=0, j=ee_Checksum; i<ee_SIZE; i++) j+=read_eeprom(ioaddr,i); printk("Checksum: %#x\n",j&0xffff); Word=read_eeprom(ioaddr, 0); 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); 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); 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); 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); 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. */int eepro_probe1(struct device *dev, short ioaddr){ unsigned short station_addr[6], id, counter; int i,j, irqMask; int eepro; 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); printk(KERN_DEBUG " id: %#x ",id); printk(" io: %#x ",ioaddr); 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 */ /* Now, get the ethernet hardware address from the EEPROM */ station_addr[0] = read_eeprom(ioaddr, 2); station_addr[1] = read_eeprom(ioaddr, 3); station_addr[2] = read_eeprom(ioaddr, 4); /* Check the station address for the manufacturer's code */ if (net_debug>3) printEEPROMInfo(ioaddr); if (read_eeprom(ioaddr,7)== 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]); } 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_RAM; /* or it will be set to 24K */ else dev->mem_end = 1024*dev->mem_end; /* Maybe I should shift << 10 */ /* From now on, dev->mem_end contains the actual size of rx buffer */ if (net_debug > 3) printk(", %dK RCV buffer", (int)(dev->mem_end)/1024); /* ............... */ if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE)) dev->if_port = BNC; else dev->if_port = TPE; /* ............... */ if ((dev->irq < 2) && (eepro!=0)) { i = read_eeprom(ioaddr, 1); irqMask = read_eeprom(ioaddr, 7); 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; 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); 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); /* 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));#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155 spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));#endif 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; /* Fill in the fields of the device structure with ethernet generic values */ ether_setup(dev); outb(RESET_CMD, ioaddr); /* RESET the 82595 */ 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 device *dev){ int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 }; int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr; outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ /* Enable the interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg | INT_ENABLE, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); /* Let EXEC event to interrupt */ outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); do { outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ temp_reg = inb(ioaddr + INT_NO_REG); outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); outb(BANK0_SELECT, 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); outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */ if (*irqp == autoirq_report(2)) /* It's a good IRQ line */ break; /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); } } while (*++irqp); outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg & 0x7f, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Mask all the interrupts. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); return dev->irq;}static int eepro_open(struct device *dev){ unsigned short temp_reg, old8, old9; int irqMask; int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end; struct eepro_local *lp = (struct eepro_local *)dev->priv; if (net_debug > 3) printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name); if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */ { lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); } else if ((dev->dev_addr[0] == SA_ADDR0 && dev->dev_addr[1] == SA_ADDR1 && dev->dev_addr[2] == SA_ADDR2)) { lp->eepro = 1; if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n"); } /* Yes, an Intel EtherExpress Pro/10 */ else lp->eepro = 0; /* No, it is a generic 82585 lan card */ /* Get the interrupt vector for the 82595 */ if (dev->irq < 2 && eepro_grab_irq(dev) == 0) { printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) { printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } #ifdef irq2dev_map if (((irq2dev_map[dev->irq] != 0) || (irq2dev_map[dev->irq] = dev) == 0) && (irq2dev_map[dev->irq]!=dev)) { /* printk("%s: IRQ map wrong\n", dev->name); */ return -EAGAIN; }#endif /* Initialize the 82595. */ outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ temp_reg = inb(ioaddr + EEPROM_REG); lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */ if (net_debug > 3) printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping); if (temp_reg & 0x10) /* Check the TurnOff Enable bit */ outb(temp_reg & 0xef, ioaddr + EEPROM_REG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -