From 5eee9ca94cc076f0d9b96109fd7a538c6a684bc2 Mon Sep 17 00:00:00 2001 From: mycroft Date: Tue, 7 Mar 2000 00:39:17 +0000 Subject: [PATCH] Determine the size of the SROM by probing the chip using the standard Microwire protocol. Eliminates the need for srom_quirks and some other trash. --- sys/dev/ic/tulip.c | 117 +++++++++++++++++++++++++----- sys/dev/ic/tulipvar.h | 6 +- sys/dev/pci/if_tlp_pci.c | 149 ++++++--------------------------------- 3 files changed, 124 insertions(+), 148 deletions(-) diff --git a/sys/dev/ic/tulip.c b/sys/dev/ic/tulip.c index f5fce7b08e16..5f41e1747aa9 100644 --- a/sys/dev/ic/tulip.c +++ b/sys/dev/ic/tulip.c @@ -1,4 +1,4 @@ -/* $NetBSD: tulip.c,v 1.46 2000/03/06 21:02:01 thorpej Exp $ */ +/* $NetBSD: tulip.c,v 1.47 2000/03/07 00:39:17 mycroft Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -152,6 +152,7 @@ void tlp_stop __P((struct tulip_softc *, int)); int tlp_add_rxbuf __P((struct tulip_softc *, int)); void tlp_idle __P((struct tulip_softc *, u_int32_t)); void tlp_srom_idle __P((struct tulip_softc *)); +int tlp_srom_size __P((struct tulip_softc *)); void tlp_filter_setup __P((struct tulip_softc *)); void tlp_winb_filter_setup __P((struct tulip_softc *)); @@ -598,6 +599,9 @@ tlp_detach(sc) shutdownhook_disestablish(sc->sc_sdhook); + if (sc->sc_srom) + free(sc->sc_srom, M_DEVBUF); + return (0); } @@ -1899,7 +1903,7 @@ tlp_stop(sc, drain) #define SROM_EMIT(sc, x) \ do { \ TULIP_WRITE((sc), CSR_MIIROM, (x)); \ - delay(1); \ + delay(2); \ } while (0) /* @@ -1925,8 +1929,8 @@ tlp_srom_idle(sc) SROM_EMIT(sc, miirom|MIIROM_SROMSK); - /* Strobe the clock 25 times. */ - for (i = 0; i < 25; i++) { + /* Strobe the clock 32 times. */ + for (i = 0; i < 32; i++) { SROM_EMIT(sc, miirom); SROM_EMIT(sc, miirom|MIIROM_SROMSK); } @@ -1940,21 +1944,16 @@ tlp_srom_idle(sc) } /* - * tlp_read_srom: + * tlp_srom_size: * - * Read the Tulip SROM. + * Determine the number of address bits in the SROM. */ -void -tlp_read_srom(sc, word, wordcnt, data) +int +tlp_srom_size(sc) struct tulip_softc *sc; - int word, wordcnt; - u_int8_t *data; { u_int32_t miirom; - u_int16_t datain; - int i, x; - - tlp_srom_idle(sc); + int x; /* Select the SROM. */ miirom = MIIROM_SR; @@ -1963,7 +1962,77 @@ tlp_read_srom(sc, word, wordcnt, data) miirom |= MIIROM_RD; SROM_EMIT(sc, miirom); - for (i = 0; i < wordcnt; i++) { + /* Send CHIP SELECT for one clock tick. */ + miirom |= MIIROM_SROMCS; + SROM_EMIT(sc, miirom); + + /* Shift in the READ opcode. */ + for (x = 3; x > 0; x--) { + if (TULIP_SROM_OPC_READ & (1 << (x - 1))) + miirom |= MIIROM_SROMDI; + else + miirom &= ~MIIROM_SROMDI; + SROM_EMIT(sc, miirom); + SROM_EMIT(sc, miirom|MIIROM_SROMSK); + SROM_EMIT(sc, miirom); + } + + /* Shift in address and look for dummy 0 bit. */ + for (x = 1; x <= 12; x++) { + miirom &= ~MIIROM_SROMDI; + SROM_EMIT(sc, miirom); + SROM_EMIT(sc, miirom|MIIROM_SROMSK); + if (!TULIP_ISSET(sc, CSR_MIIROM, MIIROM_SROMDO)) + break; + SROM_EMIT(sc, miirom); + } + + /* Clear CHIP SELECT. */ + miirom &= ~MIIROM_SROMCS; + SROM_EMIT(sc, miirom); + + /* Deselect the SROM. */ + SROM_EMIT(sc, 0); + + if (x > 12) { + printf("failed to find SROM size\n"); + return (0); + } else { + printf("SROM size is 2^%d*16 (%d) bits\n", x, 1 << (x + 4)); + return (x); + } +} + +/* + * tlp_read_srom: + * + * Read the Tulip SROM. + */ +int +tlp_read_srom(sc) + struct tulip_softc *sc; +{ + int size; + u_int32_t miirom; + u_int16_t datain; + int i, x; + + tlp_srom_idle(sc); + + sc->sc_srom_addrbits = tlp_srom_size(sc); + if (sc->sc_srom_addrbits == 0) + return (0); + size = TULIP_ROM_SIZE(sc->sc_srom_addrbits); + sc->sc_srom = malloc(size, M_DEVBUF, M_NOWAIT); + + /* Select the SROM. */ + miirom = MIIROM_SR; + SROM_EMIT(sc, miirom); + + miirom |= MIIROM_RD; + SROM_EMIT(sc, miirom); + + for (i = 0; i < size; i += 2) { /* Send CHIP SELECT for one clock tick. */ miirom |= MIIROM_SROMCS; SROM_EMIT(sc, miirom); @@ -1981,7 +2050,7 @@ tlp_read_srom(sc, word, wordcnt, data) /* Shift in address. */ for (x = sc->sc_srom_addrbits; x > 0; x--) { - if ((word + i) & (1 << (x - 1))) + if (i & (1 << x)) miirom |= MIIROM_SROMDI; else miirom &= ~MIIROM_SROMDI; @@ -1999,8 +2068,8 @@ tlp_read_srom(sc, word, wordcnt, data) datain |= (1 << (x - 1)); SROM_EMIT(sc, miirom); } - data[2 * i] = datain & 0xff; - data[(2 * i) + 1] = datain >> 8; + sc->sc_srom[i] = datain & 0xff; + sc->sc_srom[i + 1] = datain >> 8; /* Clear CHIP SELECT. */ miirom &= ~MIIROM_SROMCS; @@ -2012,6 +2081,18 @@ tlp_read_srom(sc, word, wordcnt, data) /* ...and idle it. */ tlp_srom_idle(sc); + +#if 0 + printf("SROM CONTENTS:"); + for (i = 0; i < size; i++) { + if ((i % 8) == 0) + printf("\n\t"); + printf("0x%02x ", sc->sc_srom[i]); + } + printf("\n"); +#endif + + return (1); } #undef SROM_EMIT diff --git a/sys/dev/ic/tulipvar.h b/sys/dev/ic/tulipvar.h index 2d3bbc5b3dfd..f28b11bad5e5 100644 --- a/sys/dev/ic/tulipvar.h +++ b/sys/dev/ic/tulipvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: tulipvar.h,v 1.28 2000/02/01 22:54:48 thorpej Exp $ */ +/* $NetBSD: tulipvar.h,v 1.29 2000/03/07 00:39:17 mycroft Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -276,7 +276,7 @@ struct tulip_softc { /* * Contents of the SROM. */ - u_int8_t sc_srom[TULIP_MAX_ROM_SIZE]; + u_int8_t *sc_srom; int sc_srom_addrbits; /* @@ -502,7 +502,7 @@ void tlp_attach __P((struct tulip_softc *, const u_int8_t *)); int tlp_activate __P((struct device *, enum devact)); int tlp_detach __P((struct tulip_softc *)); int tlp_intr __P((void *)); -void tlp_read_srom __P((struct tulip_softc *, int, int, u_int8_t *)); +int tlp_read_srom __P((struct tulip_softc *)); int tlp_srom_crcok __P((const u_int8_t *)); int tlp_isv_srom __P((const u_int8_t *)); int tlp_isv_srom_enaddr __P((struct tulip_softc *, u_int8_t *)); diff --git a/sys/dev/pci/if_tlp_pci.c b/sys/dev/pci/if_tlp_pci.c index 1e42459da31f..d4c0bc37b37e 100644 --- a/sys/dev/pci/if_tlp_pci.c +++ b/sys/dev/pci/if_tlp_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_tlp_pci.c,v 1.32 2000/01/26 16:51:11 thorpej Exp $ */ +/* $NetBSD: if_tlp_pci.c,v 1.33 2000/03/07 00:39:18 mycroft Exp $ */ /*- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. @@ -246,26 +246,6 @@ const struct tlp_pci_quirks tlp_pci_21142_quirks[] = { { NULL, { 0, 0, 0 } } }; -/* - * Even more disgusting... some 21143 implementations (namely Cobalt's) - * which should have a 8-address-bit SROM actually only have a - * 6-address-bit SROM (even though it's rev 4.1!). Broken! This - * quirk detects that. - */ -#define TPSQ_NOMATCH 0 -#define TPSQ_CONTINUE 1 -#define TPSQ_READ_AGAIN_AND_CONTINUE 2 - -typedef int (*tlp_pci_srom_quirk_t) __P((struct tulip_pci_softc *)); - -int tlp_pci_cobalt_21143_srom_quirks __P((struct tulip_pci_softc *)); -int tlp_pci_21143_srom_quirks __P((struct tulip_pci_softc *)); - -tlp_pci_srom_quirk_t tlp_pci_21143_srom_quirks_list[] = { - tlp_pci_cobalt_21143_srom_quirks, - tlp_pci_21143_srom_quirks, /* MUST BE AT THE END */ -}; - int tlp_pci_shared_intr __P((void *)); const struct tulip_pci_product *tlp_pci_lookup @@ -393,13 +373,6 @@ tlp_pci_attach(parent, self, aux) */ sc->sc_regshift = 3; - /* - * Some chips have a 128 byte SROM (6 address bits), and some - * have a 512 byte SROM (8 address bits). Default to 6; we'll - * adjust below. - */ - sc->sc_srom_addrbits = 6; - /* * Get revision info, and set some chip-specific variables. */ @@ -568,12 +541,12 @@ tlp_pci_attach(parent, self, aux) /* * Read the contents of the Ethernet Address ROM/SROM. */ - read_srom_again: - memset(sc->sc_srom, 0, sizeof(sc->sc_srom)); switch (sc->sc_chip) { case TULIP_CHIP_21040: + sc->sc_srom_addrbits = 6; + sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT); TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS); - for (i = 0; i < TULIP_ROM_SIZE(sc->sc_srom_addrbits); i++) { + for (i = 0; i < TULIP_ROM_SIZE(6); i++) { for (j = 0; j < 10000; j++) { val = TULIP_READ(sc, CSR_MIIROM); if ((val & MIIROM_DN) == 0) @@ -586,16 +559,17 @@ tlp_pci_attach(parent, self, aux) case TULIP_CHIP_82C168: case TULIP_CHIP_82C169: { - u_int16_t *rombuf = (u_int16_t *)sc->sc_srom; + sc->sc_srom_addrbits = 2; + sc->sc_srom = malloc(TULIP_ROM_SIZE(2), M_DEVBUF, M_NOWAIT); /* * The Lite-On PNIC stores the Ethernet address in * the first 3 words of the EEPROM. EEPROM access * is not like the other Tulip chips. */ - for (i = 0; i < 3; i++) { + for (i = 0; i < 6; i += 2) { TULIP_WRITE(sc, CSR_PNIC_SROMCTL, - PNIC_SROMCTL_READ | i); + PNIC_SROMCTL_READ | (i >> 1)); for (j = 0; j < 500; j++) { delay(2); val = TULIP_READ(sc, CSR_MIIROM); @@ -607,23 +581,17 @@ tlp_pci_attach(parent, self, aux) sc->sc_dev.dv_xname); return; } - rombuf[i] = bswap16(val & PNIC_MIIROM_DATA); + val &= PNIC_MIIROM_DATA; + sc->sc_srom[i] = val >> 8; + sc->sc_srom[i + 1] = val & 0xff; } break; } default: - tlp_read_srom(sc, 0, TULIP_ROM_SIZE(sc->sc_srom_addrbits) >> 1, - sc->sc_srom); -#if 0 - printf("SROM CONTENTS:"); - for (i = 0; i < TULIP_ROM_SIZE(sc->sc_srom_addrbits); i++) { - if ((i % 8) == 0) - printf("\n\t"); - printf("0x%02x ", sc->sc_srom[i]); - } - printf("\n"); -#endif + if (tlp_read_srom(sc) == 0) + goto cant_cope; + break; } /* @@ -643,11 +611,8 @@ tlp_pci_attach(parent, self, aux) /* * Parse the Ethernet Address ROM. */ - if (tlp_parse_old_srom(sc, enaddr) == 0) { - printf("%s: unable to decode Ethernet Address ROM\n", - sc->sc_dev.dv_xname); - return; - } + if (tlp_parse_old_srom(sc, enaddr) == 0) + goto cant_cope; /* * If we have a slaved ROM, adjust the Ethernet address. @@ -682,11 +647,8 @@ tlp_pci_attach(parent, self, aux) * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ - if (tlp_parse_old_srom(sc, enaddr) == 0) { - printf("%s: unable to decode Ethernet " - "Address ROM\n", sc->sc_dev.dv_xname); - return; - } + if (tlp_parse_old_srom(sc, enaddr) == 0) + goto cant_cope; } /* @@ -709,11 +671,8 @@ tlp_pci_attach(parent, self, aux) * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ - if (tlp_parse_old_srom(sc, enaddr) == 0) { - printf("%s: unable to decode Ethernet " - "Address ROM\n", sc->sc_dev.dv_xname); - return; - } + if (tlp_parse_old_srom(sc, enaddr) == 0) + goto cant_cope; } else { /* * We start out with the 2114x ISV media switch. @@ -739,37 +698,12 @@ tlp_pci_attach(parent, self, aux) case TULIP_CHIP_21143: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { - if (sc->sc_chip == TULIP_CHIP_21143) { - tlp_pci_srom_quirk_t q; - - /* - * Check for SROM quirkiness. - */ - for (i = 0; sc->sc_srom_addrbits != 8; i++) { - q = tlp_pci_21143_srom_quirks_list[i]; - switch ((*q)(psc)) { - case TPSQ_NOMATCH: - continue; - - case TPSQ_CONTINUE: - break; - - case TPSQ_READ_AGAIN_AND_CONTINUE: - goto read_srom_again; - } - break; /* for TPSQ_CONTINUE */ - } - } - /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ - if (tlp_parse_old_srom(sc, enaddr) == 0) { - printf("%s: unable to decode Ethernet " - "Address ROM\n", sc->sc_dev.dv_xname); - return; - } + if (tlp_parse_old_srom(sc, enaddr) == 0) + goto cant_cope; } else { /* * We start out with the 2114x ISV media switch. @@ -1158,42 +1092,3 @@ tlp_pci_cobalt_21142_quirks(psc, enaddr) */ sc->sc_mediasw = &tlp_sio_mii_mediasw; } - -int -tlp_pci_cobalt_21143_srom_quirks(psc) - struct tulip_pci_softc *psc; -{ - struct tulip_softc *sc = &psc->sc_tulip; - - /* - * Check for broken Cobalt interface; pass 4.1 Tulip with - * only 6-bit SROM and Ethernet address in first 6 bytes. - */ - if (sc->sc_srom[0] == 0x00 && - sc->sc_srom[1] == 0x10 && - sc->sc_srom[2] == 0xe0) - return (TPSQ_CONTINUE); - - return (TPSQ_NOMATCH); -} - -int -tlp_pci_21143_srom_quirks(psc) - struct tulip_pci_softc *psc; -{ - struct tulip_softc *sc = &psc->sc_tulip; - - /* - * Pass 4.1 21143s are supposed to have an 8-address-bit SROM. - * We need to read them again. - */ - if (sc->sc_rev >= 0x41) { - sc->sc_srom_addrbits = 8; - return (TPSQ_READ_AGAIN_AND_CONTINUE); - } - - /* - * ...otherwise, what we read is just fine. - */ - return (TPSQ_CONTINUE); -}