📄 3c509.c
字号:
if (!eeprom_rdy()) return (0xffff); outw(EEPROM_CMD_RD | offset, IS_BASE + EP_W0_EEPROM_COMMAND); if (!eeprom_rdy()) return (0xffff); return (inw(IS_BASE + EP_W0_EEPROM_DATA));}static intsend_ID_sequence(int port){ int cx, al; for (al = 0xff, cx = 0; cx < 255; cx++) { outb(al, port); al <<= 1; if (al & 0x100) al ^= 0xcf; } return (1);}/* * We get eeprom data from the id_port given an offset into the eeprom. * Basically; after the ID_sequence is sent to all of the cards; they enter * the ID_CMD state where they will accept command requests. 0x80-0xbf loads * the eeprom data. We then read the port 16 times and with every read; the * cards check for contention (ie: if one card writes a 0 bit and another * writes a 1 bit then the host sees a 0. At the end of the cycle; each card * compares the data on the bus; if there is a difference then that card goes * into ID_WAIT state again). In the meantime; one bit of data is returned in * the AX register which is conveniently returned to us by inb(). Hence; we * read 16 times getting one bit of data with each read. */static intget_eeprom_data(int id_port, int offset){ int i, data = 0; outb(0x80 + offset, id_port); /* Do we really need this wait? Won't be noticeable anyway */ udelay(10000); for (i = 0; i < 16; i++) data = (data << 1) | (inw(id_port) & 1); return (data);}static void __t509_disable(void){ outb(0xc0, EP_ID_PORT);}static void t509_disable(struct dev *dev){ struct nic *nic = (struct nic *)dev; /* reset and disable merge */ t509_reset(nic); __t509_disable();}/**************************************************************************ETH_PROBE - Look for an adapter***************************************************************************/#ifdef INCLUDE_3C529static int t529_probe(struct dev *dev, unsigned short *probe_addrs __unused)#elsestatic int t509_probe(struct dev *dev, unsigned short *probe_addrs __unused)#endif{ struct nic *nic = (struct nic *)dev; /* common variables */ int i; int failcount;#ifdef INCLUDE_3C529 struct el3_mca_adapters_struct *mcafound = NULL; int mca_pos4 = 0, mca_pos5 = 0, mca_irq = 0;#endif __t509_disable(); /* in case board was active */ for (failcount = 0; failcount < 100; failcount++) { int data, j, io_base, id_port; unsigned short k; int ep_current_tag; short *p;#ifdef INCLUDE_3C529 int curboard;#endif id_port = EP_ID_PORT; ep_current_tag = EP_LAST_TAG + 1; /********************************************************* Search for 3Com 509 card ***********************************************************/#ifdef INCLUDE_3C529 /* * XXX: We should really check to make sure we have an MCA * bus controller before going ahead with this... * * For now, we avoid any hassle by making it a compile * time option. * */ /* printf("\nWarning: Assuming presence of MCA bus\n"); */ /* Make sure motherboard setup is off */ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG); /* Cycle through slots */ for(curboard=0; curboard<MCA_MAX_SLOT_NR; curboard++) { int boardid; int curcard; outb_p(0x8|(curboard&0xf), MCA_ADAPTER_SETUP_REG); boardid = inb_p(MCA_POS_REG(0)); boardid += inb_p(MCA_POS_REG(1)) << 8; curcard = 0; while (el3_mca_adapters[curcard].name) { if (el3_mca_adapters[curcard].id == boardid) { mcafound = &el3_mca_adapters[curcard]; mca_pos4 = inb_p(MCA_POS_REG(4)); mca_pos5 = inb_p(MCA_POS_REG(5)); goto donewithdetect; } else curcard++; } } donewithdetect: /* Kill all setup modes */ outb_p(0, MCA_ADAPTER_SETUP_REG); if (mcafound) { eth_nic_base = ((short)((mca_pos4&0xfc)|0x02)) << 8; mca_irq = mca_pos5 & 0x0f; ep_current_tag--; } else /*printf("MCA Card not found\n")*/;#endif /* Look for the EISA boards, leave them activated */ /* search for the first card, ignore all others */ for(j = 1; j < 16; j++) { io_base = (j * EP_EISA_START) | EP_EISA_W0; if (inw(io_base + EP_W0_MFG_ID) != MFG_ID) continue; /* we must have found 0x1f if the board is EISA configurated */ if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) continue; /* Reset and Enable the card */ outb(W0_P4_CMD_RESET_ADAPTER, io_base + EP_W0_CONFIG_CTRL); udelay(1000); /* Must wait 800 祍, be conservative */ outb(W0_P4_CMD_ENABLE_ADAPTER, io_base + EP_W0_CONFIG_CTRL); /* * Once activated, all the registers are mapped in the range * x000 - x00F, where x is the slot number. */ eth_nic_base = j * EP_EISA_START; break; } ep_current_tag--; /* Look for the ISA boards. Init and leave them actived */ /* search for the first card, ignore all others */ outb(0xc0, id_port); /* Global reset */ udelay(1000); /* wait 1 ms */ for (i = 0; i < EP_MAX_BOARDS; i++) { outb(0, id_port); outb(0, id_port); send_ID_sequence(id_port); data = get_eeprom_data(id_port, EEPROM_MFG_ID); if (data != MFG_ID) break; /* resolve contention using the Ethernet address */ for (j = 0; j < 3; j++) data = get_eeprom_data(id_port, j); eth_nic_base = (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200; outb(ep_current_tag, id_port); /* tags board */ outb(ACTIVATE_ADAPTER_TO_CONFIG, id_port); ep_current_tag--; break; } if (i >= EP_MAX_BOARDS) goto no3c509; /* * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be * 0x9[0-f]50 */ GO_WINDOW(0); k = get_e(EEPROM_PROD_ID);#ifdef INCLUDE_3C529 /* * On MCA, the PROD_ID matches the MCA card ID (POS0+POS1) */ if (mcafound) { if (mcafound->id != k) { printf("MCA: PROD_ID in EEPROM does not match MCA card ID! (%hX != %hX)\n", k, mcafound->id); goto no3c509; } } else { /* for ISA/EISA */ if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) goto no3c509; }#else if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) goto no3c509;#endif#ifdef INCLUDE_3C529 if (mcafound) { printf("%s board found on MCA at %#hx IRQ %d -", mcafound->name, eth_nic_base, mca_irq); } else {#endif if(eth_nic_base >= EP_EISA_START) printf("3C5x9 board on EISA at %#hx - ",eth_nic_base); else printf("3C5x9 board on ISA at %#hx - ",eth_nic_base);#ifdef INCLUDE_3C529 }#endif /* test for presence of connectors */ i = inw(IS_BASE + EP_W0_CONFIG_CTRL); j = (inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14) & 0x3; switch(j) { case 0: if (i & IS_UTP) { printf("10baseT\n"); connector = utp; } else { printf("10baseT not present\n"); goto no3c509; } break; case 1: if (i & IS_AUI) printf("10base5\n"); else { printf("10base5 not present\n"); goto no3c509; } break; case 3: if (i & IS_BNC) { printf("10base2\n"); connector = bnc; } else { printf("10base2 not present\n"); goto no3c509; } break; default: printf("unknown connector\n"); goto no3c509; } /* * Read the station address from the eeprom */ p = (unsigned short *) nic->node_addr; for (i = 0; i < ETH_ALEN / 2; i++) { GO_WINDOW(0); p[i] = htons(get_e(i)); GO_WINDOW(2); outw(ntohs(p[i]), BASE + EP_W2_ADDR_0 + (i * 2)); } printf("Ethernet address: %!\n", nic->node_addr); t509_reset(nic); dev->disable = t509_disable; nic->poll = t509_poll; nic->transmit = t509_transmit; /* Based on PnP ISA map */ dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); dev->devid.device_id = htons(0x80f7); return 1;no3c509: /* printf("(probe fail)"); */ } return 0;}#ifdef INCLUDE_3C509static struct isa_driver t509_driver __isa_driver = { .type = NIC_DRIVER, .name = "3C509", .probe = t509_probe, .ioaddrs = 0,};#endif#ifdef INCLUDE_3C529static struct isa_driver t529_driver __isa_driver = { .type = NIC_DRIVER, .name = "3C529", .probe = t529_probe, .ioaddrs = 0,};#endif/* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -