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.
This commit is contained in:
mycroft 2000-03-07 00:39:17 +00:00
parent 064b1bd2e9
commit 5eee9ca94c
3 changed files with 124 additions and 148 deletions

View File

@ -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

View File

@ -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 *));

View File

@ -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);
}