📄 eepro.c
字号:
#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 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) { \ dev->stats.tx_errors++;\ eepro_sel_reset(ioaddr);\ lp->tx_end = \ lp->xmt_lower_limit;\ lp->tx_start = lp->tx_end;\ lp->tx_last = 0;\ dev->trans_start = jiffies;\ netif_wake_queue(dev);\ 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). */static int __init do_eepro_probe(struct net_device *dev){ int i; int base_addr = dev->base_addr; int irq = dev->irq;#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 (request_region(WakeupPort, 2, "eepro wakeup")) { 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]); } release_region(WakeupPort, 2); } else printk(KERN_WARNING "PnP wakeup region busy!\n"); }#endif if (base_addr > 0x1ff) /* Check a single specified location. */ return eepro_probe1(dev, 0); else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; for (i = 0; eepro_portlist[i]; i++) { dev->base_addr = eepro_portlist[i]; dev->irq = irq; if (eepro_probe1(dev, 1) == 0) return 0; } return -ENODEV;}#ifndef MODULEstruct net_device * __init eepro_probe(int unit){ struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local)); int err; if (!dev) return ERR_PTR(-ENODEV); sprintf(dev->name, "eth%d", unit); netdev_boot_setup_check(dev); err = do_eepro_probe(dev); if (err) goto out; return dev;out: free_netdev(dev); return ERR_PTR(err);}#endifstatic void __init printEEPROMInfo(struct net_device *dev){ struct eepro_local *lp = (struct eepro_local *)dev->priv; int ioaddr = dev->base_addr; unsigned short Word; int i,j; j = ee_Checksum; for (i = 0; i < 8; i++) j += lp->word[i]; for ( ; i < ee_SIZE; i++) j += read_eeprom(ioaddr, i, dev); printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff); Word = lp->word[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 = lp->word[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 = lp->word[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(KERN_DEBUG "TPE "); if (GetBit(Word,ee_PortBNC)) printk(KERN_DEBUG "BNC "); if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI "); printk(KERN_DEBUG "port(s) \n"); Word = lp->word[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 = lp->word[7]; printk(KERN_DEBUG "Word7:\n"); printk(KERN_DEBUG " INT to IRQ:\n"); for (i=0, j=0; i<15; i++) if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i); printk(KERN_DEBUG "\n");}/* function to recalculate the limits of buffer based on rcv_ram */static void eepro_recalc (struct net_device *dev){ struct eepro_local * lp; lp = netdev_priv(dev); lp->xmt_ram = RAM_SIZE - lp->rcv_ram; if (lp->eepro == LAN595FX_10ISA) { lp->xmt_lower_limit = XMT_START_10; lp->xmt_upper_limit = (lp->xmt_ram - 2); lp->rcv_lower_limit = lp->xmt_ram; lp->rcv_upper_limit = (RAM_SIZE - 2); } else { lp->rcv_lower_limit = RCV_START_PRO; lp->rcv_upper_limit = (lp->rcv_ram - 2); lp->xmt_lower_limit = lp->rcv_ram; lp->xmt_upper_limit = (RAM_SIZE - 2); }}/* prints boot-time info */static void __init eepro_print_info (struct net_device *dev){ struct eepro_local * lp = netdev_priv(dev); int i; const char * ifmap[] = {"AUI", "10Base2", "10BaseT"}; DECLARE_MAC_BUF(mac); i = inb(dev->base_addr + ID_REG); printk(KERN_DEBUG " id: %#x ",i); printk(" io: %#x ", (unsigned)dev->base_addr); switch (lp->eepro) { case LAN595FX_10ISA: printk("%s: Intel EtherExpress 10 ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595FX: printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595TX: printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595: printk("%s: Intel 82595-based lan card at %#x,", dev->name, (unsigned)dev->base_addr); break; } printk(" %s", print_mac(mac, dev->dev_addr)); if (net_debug > 3) printk(KERN_DEBUG ", %dK RCV buffer", (int)(lp->rcv_ram)/1024); if (dev->irq > 2) printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); else printk(", %s.\n", ifmap[dev->if_port]); if (net_debug > 3) { i = lp->word[5]; if (i & 0x2000) /* bit 13 of EEPROM word 5 */ printk(KERN_DEBUG "%s: Concurrent Processing is " "enabled but not used!\n", dev->name); } /* Check the station address for the manufacturer's code */ if (net_debug>3) printEEPROMInfo(dev);}static const struct ethtool_ops eepro_ethtool_ops;/* 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 __init eepro_probe1(struct net_device *dev, int autoprobe){ unsigned short station_addr[3], id, counter; int i; struct eepro_local *lp; int ioaddr = dev->base_addr; int err; /* Grab the region so we can find another board if autoIRQ fails. */ if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { if (!autoprobe) printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n", ioaddr); return -EBUSY; } /* 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) goto exit; /* 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 ((inb(ioaddr + ID_REG) & R_ROBIN_BITS) != (counter + 0x40)) goto exit; lp = netdev_priv(dev); memset(lp, 0, sizeof(struct eepro_local)); lp->xmt_bar = XMT_BAR_PRO; lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO; lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO; lp->eeprom_reg = EEPROM_REG_PRO; spin_lock_init(&lp->lock); /* 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) { lp->eepro = LAN595FX_10ISA; lp->eeprom_reg = EEPROM_REG_10; lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10; lp->xmt_bar = XMT_BAR_10; station_addr[0] = read_eeprom(ioaddr, 2, dev); } /* get all words at once. will be used here and for ethtool */ for (i = 0; i < 8; i++) { lp->word[i] = read_eeprom(ioaddr, i, dev); } station_addr[1] = lp->word[3]; station_addr[2] = lp->word[4]; if (!lp->eepro) { if (lp->word[7] == ee_FX_INT2IRQ) lp->eepro = 2; else if (station_addr[2] == SA_ADDR1) lp->eepro = 1; } /* Fill in the 'dev' fields. */ for (i=0; i < 6; i++) dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; /* RX buffer must be more than 3K and less than 29K */ if (dev->mem_end < 3072 || dev->mem_end > 29696) lp->rcv_ram = RCV_DEFAULT_RAM; /* calculate {xmt,rcv}_{lower,upper}_limit */ eepro_recalc(dev); if (GetBit(lp->word[5], ee_BNC_TPE)) dev->if_port = BNC; else dev->if_port = TPE; if (dev->irq < 2 && lp->eepro != 0) { /* Mask off INT number */ int count = lp->word[1] & 7; unsigned irqMask = lp->word[7]; while (count--) irqMask &= irqMask - 1; count = ffs(irqMask); if (count) dev->irq = count - 1; if (dev->irq < 2) { printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n"); goto exit; } else if (dev->irq == 2) { dev->irq = 9; } } dev->open = eepro_open; dev->stop = eepro_close; dev->hard_start_xmit = eepro_send_packet; dev->set_multicast_list = &set_multicast_list; dev->tx_timeout = eepro_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->ethtool_ops = &eepro_ethtool_ops; /* print boot time info */ eepro_print_info(dev); /* reset 82595 */ eepro_reset(ioaddr); err = register_netdev(dev); if (err) goto err; return 0;exit: err = -ENODEV;err: release_region(dev->base_addr, EEPRO_IO_EXTENT); return err;}/* 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -