diff options
author | wpaul <wpaul@FreeBSD.org> | 1999-09-20 20:26:14 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1999-09-20 20:26:14 +0000 |
commit | c248feb383a5c1f3b3c20ad1eb7f7082d51aa19e (patch) | |
tree | 79a4f8e9259cac15cc29b147fae61cc5bf23fc13 /sys/pci/if_xl.c | |
parent | b2a7a63df77ed3bffd9a435a7a072fcef0d0ac84 (diff) | |
download | FreeBSD-src-c248feb383a5c1f3b3c20ad1eb7f7082d51aa19e.zip FreeBSD-src-c248feb383a5c1f3b3c20ad1eb7f7082d51aa19e.tar.gz |
Close PR #13665. I managed to figure out the problem, no thanks to the
submitter, who *still* hasn't bothered to answer me back.
The thing which the submitter completely failed to mention is that
his 3c900B-TPO card has the transceiver selection in the EEPROM set
to "auto." You can tweak the setting using the 3C90XCFG.EXE utility
that 3Com provides with the card. I'm not sure if it's supposed to
default to auto or if the user fiddled with it. Currently, the xl
driver only does autoselection for 10/100 NICs (i.e. those with NWAY
autonegotiation capabilities). For the 10baseT, 10base5, 10base2,
10baseFL and 100baseFX cards, the driver sets the default media to
whatever the EEPROM transceiver selector says. The problem is that
the "auto" selection is mistakenly identified as "10/100 NWAY
autoselection mode" and this is not handled correctly: the default
media ends up being chosen as 100baseTX, which doesn't work because
we've only added 10baseT media types to the ifmedia word. This leads
to a panic in ifmedia_set() (something else which the submitter never
bothered to mention).
A workaround for this is to re-run the 3C90XCFG.EXE utility and change
the transceiver selection to something besides "auto." I have also
patched the driver to watch for the "auto" setting in the non-miibus
case and select a reasonable default based on the card type instead of
falling through to 100baseTX and exploding.
PR: misc/13665
Diffstat (limited to 'sys/pci/if_xl.c')
-rw-r--r-- | sys/pci/if_xl.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index 36ff5a2..9f667c7 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -239,6 +239,7 @@ static int xl_list_tx_init __P((struct xl_softc *)); static int xl_list_tx_init_90xB __P((struct xl_softc *)); static void xl_wait __P((struct xl_softc *)); static void xl_mediacheck __P((struct xl_softc *)); +static void xl_choose_xcvr __P((struct xl_softc *, int)); #ifdef notdef static void xl_testpacket __P((struct xl_softc *)); #endif @@ -1046,7 +1047,6 @@ static int xl_probe(dev) static void xl_mediacheck(sc) struct xl_softc *sc; { - u_int16_t devid; /* * If some of the media options bits are set, assume they are @@ -1079,6 +1079,16 @@ static void xl_mediacheck(sc) "should probably consult your vendor\n", sc->xl_unit); } + xl_choose_xcvr(sc, 1); + + return; +} + +static void xl_choose_xcvr(sc, verbose) + struct xl_softc *sc; + int verbose; +{ + u_int16_t devid; /* * Read the device ID from the EEPROM. @@ -1092,34 +1102,42 @@ static void xl_mediacheck(sc) case TC_DEVICEID_KRAKATOA_10BT: /* 3c900B-TPO */ sc->xl_media = XL_MEDIAOPT_BT; sc->xl_xcvr = XL_XCVR_10BT; - printf("xl%d: guessing 10BaseT transceiver\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing 10BaseT " + "transceiver\n", sc->xl_unit); break; case TC_DEVICEID_BOOMERANG_10BT_COMBO: /* 3c900-COMBO */ case TC_DEVICEID_KRAKATOA_10BT_COMBO: /* 3c900B-COMBO */ sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI; sc->xl_xcvr = XL_XCVR_10BT; - printf("xl%d: guessing COMBO (AUI/BNC/TP)\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing COMBO " + "(AUI/BNC/TP)\n", sc->xl_unit); break; case TC_DEVICEID_KRAKATOA_10BT_TPC: /* 3c900B-TPC */ sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC; sc->xl_xcvr = XL_XCVR_10BT; - printf("xl%d: guessing TPC (BNC/TP)\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing TPC (BNC/TP)\n", sc->xl_unit); break; case TC_DEVICEID_CYCLONE_10FL: /* 3c900B-FL */ sc->xl_media = XL_MEDIAOPT_10FL; sc->xl_xcvr = XL_XCVR_AUI; - printf("xl%d: guessing 10baseFL\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing 10baseFL\n", sc->xl_unit); break; case TC_DEVICEID_BOOMERANG_10_100BT: /* 3c905-TX */ sc->xl_media = XL_MEDIAOPT_MII; sc->xl_xcvr = XL_XCVR_MII; - printf("xl%d: guessing MII\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing MII\n", sc->xl_unit); break; case TC_DEVICEID_BOOMERANG_100BT4: /* 3c905-T4 */ case TC_DEVICEID_CYCLONE_10_100BT4: /* 3c905B-T4 */ sc->xl_media = XL_MEDIAOPT_BT4; sc->xl_xcvr = XL_XCVR_MII; - printf("xl%d: guessing 100BaseT4/MII\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing 100BaseT4/MII\n", sc->xl_unit); break; case TC_DEVICEID_HURRICANE_10_100BT: /* 3c905B-TX */ case TC_DEVICEID_HURRICANE_10_100BT_SERV:/*3c980-TX */ @@ -1128,12 +1146,15 @@ static void xl_mediacheck(sc) case TC_DEVICEID_TORNADO_10_100BT: /* 3c905C-TX */ sc->xl_media = XL_MEDIAOPT_BTX; sc->xl_xcvr = XL_XCVR_AUTO; - printf("xl%d: guessing 10/100 internal\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing 10/100 internal\n", sc->xl_unit); break; case TC_DEVICEID_CYCLONE_10_100_COMBO: /* 3c905B-COMBO */ sc->xl_media = XL_MEDIAOPT_BTX|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI; sc->xl_xcvr = XL_XCVR_AUTO; - printf("xl%d: guessing 10/100 plus BNC/AUI\n", sc->xl_unit); + if (verbose) + printf("xl%d: guessing 10/100 " + "plus BNC/AUI\n", sc->xl_unit); break; default: printf("xl%d: unknown device ID: %x -- " @@ -1368,6 +1389,14 @@ static int xl_attach(dev) } /* + * Sanity check. If the user has selected "auto" and this isn't + * a 10/100 card of some kind, we need to force the transceiver + * type to something sane. + */ + if (sc->xl_xcvr == XL_XCVR_AUTO) + xl_choose_xcvr(sc, bootverbose); + + /* * Do ifmedia setup. */ @@ -2539,13 +2568,6 @@ static void xl_init(xsc) if (mii != NULL) mii_mediachg(mii); - XL_SEL_WIN(7); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); - xl_wait(sc); - CSR_WRITE_4(sc, XL_UPLIST_PTR, vtophys(&sc->xl_ldata->xl_rx_list[0])); - CSR_WRITE_1(sc, XL_UP_POLL, 8); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); - xl_wait(sc); /* Select window 7 for normal operations. */ XL_SEL_WIN(7); |