📄 3c509.c
字号:
if (i >= MAX_EEPROMBUSY) { /* printf("3c509: eeprom failed to come ready.\n"); */ printf("3c509: eeprom busy.\n"); /* memory in EPROM is tight */ return (0); } return (1);}/* * get_e: gets a 16 bits word from the EEPROM. we must have set the window * before */static intget_e(int offset){ 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(struct nic *nic){ outb(0xc0, EP_ID_PORT);}/**************************************************************************ETH_PROBE - Look for an adapter***************************************************************************/#ifdef INCLUDE_3C529struct nic *t529_probe(struct nic *nic, unsigned short *probe_addrs)#elsestruct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)#endif{ /* 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(nic); /* in case board was active */ /* note that nic is not used */ for (failcount = 0; failcount < 4000; 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); nic->reset = t509_reset; nic->poll = t509_poll; nic->transmit = t509_transmit; nic->disable = t509_disable; return nic;no3c509: printf("(probe fail)"); } return 0;}/* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -