summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAaron Campbell <aaron@cvs.openbsd.org>2001-02-09 02:23:37 +0000
committerAaron Campbell <aaron@cvs.openbsd.org>2001-02-09 02:23:37 +0000
commita4f1d6caa16d538d3dcf3c973b49101a1cf19cb7 (patch)
tree1f136bf202f3a48ae4830b7bfac96ec5224de727 /sys
parent18eff6bb082eee1ed861a997ea92b93a3f473ab5 (diff)
Add support for parsing the media blocks from the SROM on the 21143 adapters.
These changes should make the driver work with the built-in Ethernet on the Alpha Miata machines. From FreeBSD. To make sure I didn't break anything (and as a general test), I tested the modified driver with the following dc(4) variants: Macronix PMAC 98715, Lite-On PNIC, Lite-On PNIC-II, ADMtek AL981, and ADMtek AN983.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/dc.c248
-rw-r--r--sys/dev/ic/dcreg.h156
-rw-r--r--sys/dev/pci/if_dc_pci.c63
3 files changed, 395 insertions, 72 deletions
diff --git a/sys/dev/ic/dc.c b/sys/dev/ic/dc.c
index ec3c867db1b..e68665dd46b 100644
--- a/sys/dev/ic/dc.c
+++ b/sys/dev/ic/dc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dc.c,v 1.20 2000/11/16 06:08:31 aaron Exp $ */
+/* $OpenBSD: dc.c,v 1.21 2001/02/09 02:23:34 aaron Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -76,27 +76,6 @@
* combination with the internal NWAY support to create a 10/100
* autosensing configuration.
*
- * Knowing which media is available on a given card is tough: you're
- * supposed to go slogging through the EEPROM looking for media
- * description structures. Unfortunately, some card vendors that use
- * the 21143 don't obey the DEC SROM spec correctly, which means that
- * what you find in the EEPROM may not agree with reality. Fortunately,
- * the 21143 provides us a way to get around this issue: lurking in
- * PCI configuration space is the Configuration Wake-Up Command Register.
- * This register is loaded with a value from the EEPROM when wake on LAN
- * mode is enabled; this value tells us quite clearly what kind of media
- * is attached to the NIC. The main purpose of this register is to tell
- * the NIC what media to scan when in wake on LAN mode, however by
- * forcibly enabling wake on LAN mode, we can use to learn what kind of
- * media a given NIC has available and adapt ourselves accordingly.
- *
- * Of course, if the media description blocks in the EEPROM are bogus.
- * what are the odds that the CWUC aren't bogus as well, right? Well,
- * the CWUC value is more likely to be correct since wake on LAN mode
- * won't work correctly without it, and wake on LAN is a big selling
- * point these days. It's also harder to screw up a single byte than
- * a whole media descriptor block.
- *
* Note that not all tulip workalikes are handled in this driver: we only
* deal with those which are relatively well behaved. The Winbond is
* handled separately due to its different register offsets and the
@@ -154,6 +133,9 @@
#include <dev/pci/pcidevs.h>
#define DC_USEIOSPACE
+#ifdef __alpha__
+#define SRM_MEDIA
+#endif
#include <dev/ic/dcreg.h>
@@ -209,6 +191,15 @@ void dc_reset __P((struct dc_softc *));
int dc_list_rx_init __P((struct dc_softc *));
int dc_list_tx_init __P((struct dc_softc *));
+void dc_parse_21143_srom __P((struct dc_softc *));
+void dc_decode_leaf_sia __P((struct dc_softc *,
+ struct dc_eblock_sia *));
+void dc_decode_leaf_mii __P((struct dc_softc *,
+ struct dc_eblock_mii *));
+void dc_decode_leaf_sym __P((struct dc_softc *,
+ struct dc_eblock_sym *));
+void dc_apply_fixup __P((struct dc_softc *, int));
+
#define DC_SETBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))
@@ -671,7 +662,7 @@ int dc_miibus_readreg(self, phy, reg)
if (DC_IS_ADMTEK(sc) && phy != DC_ADMTEK_PHYADDR)
return(0);
- if (sc->dc_pmode == DC_PMODE_SYM) {
+ if (sc->dc_pmode != DC_PMODE_MII) {
if (phy == (MII_NPHY - 1)) {
switch(reg) {
case MII_BMSR:
@@ -838,6 +829,7 @@ void dc_miibus_statchg(self)
if (DC_IS_ADMTEK(sc))
return;
+
mii = &sc->sc_mii;
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc) && IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
@@ -1182,7 +1174,7 @@ void dc_setfilt_xircom(sc)
/* Set our MAC address */
sp[0] = ((u_int16_t *)sc->arpcom.ac_enaddr)[0];
sp[1] = ((u_int16_t *)sc->arpcom.ac_enaddr)[1];
- sp[2] = ((u_int16_t *)sc->arpcom.ac_enaddr)[2];
+ sp[2] = ((u_int16_t *)sc->arpcom.ac_enaddr)[2];
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
@@ -1284,6 +1276,10 @@ void dc_setcfg(sc, media)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
+ if (DC_IS_INTEL(sc))
+ dc_apply_fixup(sc,
+ (media & IFM_GMASK) == IFM_FDX ?
+ IFM_100_TX|IFM_FDX : IFM_100_TX);
}
}
@@ -1318,6 +1314,21 @@ void dc_setcfg(sc, media)
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
+ if (DC_IS_INTEL(sc)) {
+ DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
+ DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
+ if ((media & IFM_GMASK) == IFM_FDX)
+ DC_SETBIT(sc, DC_10BTCTRL, 0x7F3D);
+ else
+ DC_SETBIT(sc, DC_10BTCTRL, 0x7F3F);
+ DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
+ DC_CLRBIT(sc, DC_10BTCTRL,
+ DC_TCTL_AUTONEGENBL);
+ dc_apply_fixup(sc,
+ (media & IFM_GMASK) == IFM_FDX ?
+ IFM_10_T|IFM_FDX : IFM_10_T);
+ DELAY(20000);
+ }
}
}
@@ -1387,8 +1398,160 @@ void dc_reset(sc)
* into a state where it will never come out of reset
* until we reset the whole chip again.
*/
- if (DC_IS_INTEL(sc))
+ if (DC_IS_INTEL(sc)) {
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
+ CSR_WRITE_4(sc, DC_10BTCTRL, 0);
+ CSR_WRITE_4(sc, DC_WATCHDOG, 0);
+ }
+
+ return;
+}
+
+void dc_apply_fixup(sc, media)
+ struct dc_softc *sc;
+ int media;
+{
+ struct dc_mediainfo *m;
+ u_int8_t *p;
+ int i;
+ u_int8_t reg;
+
+ m = sc->dc_mi;
+
+ while (m != NULL) {
+ if (m->dc_media == media)
+ break;
+ m = m->dc_next;
+ }
+
+ if (m == NULL)
+ return;
+
+ for (i = 0, p = m->dc_reset_ptr; i < m->dc_reset_len; i++, p += 2) {
+ reg = (p[0] | (p[1] << 8)) << 16;
+ CSR_WRITE_4(sc, DC_WATCHDOG, reg);
+ }
+
+ for (i = 0, p = m->dc_gp_ptr; i < m->dc_gp_len; i++, p += 2) {
+ reg = (p[0] | (p[1] << 8)) << 16;
+ CSR_WRITE_4(sc, DC_WATCHDOG, reg);
+ }
+
+ return;
+}
+
+void dc_decode_leaf_sia(sc, l)
+ struct dc_softc *sc;
+ struct dc_eblock_sia *l;
+{
+ struct dc_mediainfo *m;
+
+ m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT);
+ if (l->dc_sia_code == DC_SIA_CODE_10BT)
+ m->dc_media = IFM_10_T;
+
+ if (l->dc_sia_code == DC_SIA_CODE_10BT_FDX)
+ m->dc_media = IFM_10_T|IFM_FDX;
+
+ if (l->dc_sia_code == DC_SIA_CODE_10B2)
+ m->dc_media = IFM_10_2;
+
+ if (l->dc_sia_code == DC_SIA_CODE_10B5)
+ m->dc_media = IFM_10_5;
+
+ m->dc_gp_len = 2;
+ m->dc_gp_ptr = (u_int8_t *)&l->dc_sia_gpio_ctl;
+
+ m->dc_next = sc->dc_mi;
+ sc->dc_mi = m;
+
+ sc->dc_pmode = DC_PMODE_SIA;
+
+ return;
+}
+
+void dc_decode_leaf_sym(sc, l)
+ struct dc_softc *sc;
+ struct dc_eblock_sym *l;
+{
+ struct dc_mediainfo *m;
+
+ m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT);
+ if (l->dc_sym_code == DC_SYM_CODE_100BT)
+ m->dc_media = IFM_100_TX;
+
+ if (l->dc_sym_code == DC_SYM_CODE_100BT_FDX)
+ m->dc_media = IFM_100_TX|IFM_FDX;
+
+ m->dc_gp_len = 2;
+ m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl;
+
+ m->dc_next = sc->dc_mi;
+ sc->dc_mi = m;
+
+ sc->dc_pmode = DC_PMODE_SYM;
+
+ return;
+}
+
+void dc_decode_leaf_mii(sc, l)
+ struct dc_softc *sc;
+ struct dc_eblock_mii *l;
+{
+ u_int8_t *p;
+ struct dc_mediainfo *m;
+
+ m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT);
+ /* We abuse IFM_AUTO to represent MII. */
+ m->dc_media = IFM_AUTO;
+ m->dc_gp_len = l->dc_gpr_len;
+
+ p = (u_int8_t *)l;
+ p += sizeof(struct dc_eblock_mii);
+ m->dc_gp_ptr = p;
+ p += 2 * l->dc_gpr_len;
+ m->dc_reset_len = *p;
+ p++;
+ m->dc_reset_ptr = p;
+
+ m->dc_next = sc->dc_mi;
+ sc->dc_mi = m;
+
+ return;
+}
+
+void dc_parse_21143_srom(sc)
+ struct dc_softc *sc;
+{
+ struct dc_leaf_hdr *lhdr;
+ struct dc_eblock_hdr *hdr;
+ int i, loff;
+ char *ptr;
+
+ loff = sc->dc_srom[27];
+ lhdr = (struct dc_leaf_hdr *)&(sc->dc_srom[loff]);
+
+ ptr = (char *)lhdr;
+ ptr += sizeof(struct dc_leaf_hdr) - 1;
+ for (i = 0; i < lhdr->dc_mcnt; i++) {
+ hdr = (struct dc_eblock_hdr *)ptr;
+ switch(hdr->dc_type) {
+ case DC_EBLOCK_MII:
+ dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
+ break;
+ case DC_EBLOCK_SIA:
+ dc_decode_leaf_sia(sc, (struct dc_eblock_sia *)hdr);
+ break;
+ case DC_EBLOCK_SYM:
+ dc_decode_leaf_sym(sc, (struct dc_eblock_sym *)hdr);
+ break;
+ default:
+ /* Don't care. Yet. */
+ break;
+ }
+ ptr += (hdr->dc_len & 0x7F);
+ ptr++;
+ }
return;
}
@@ -1401,7 +1564,7 @@ void dc_attach_common(sc)
struct dc_softc *sc;
{
struct ifnet *ifp;
- int error = 0, mac_offset;
+ int error = 0, mac_offset, tmp;
if (!DC_IS_XIRCOM(sc))
dc_eeprom_width(sc);
@@ -1468,6 +1631,18 @@ void dc_attach_common(sc)
ifp->if_snd.ifq_maxlen = DC_TX_LIST_CNT - 1;
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+ /* Do MII setup. If this is a 21143, check for a PHY on the
+ * MII bus after applying any necessary fixups to twiddle the
+ * GPIO bits. If we don't end up finding a PHY, restore the
+ * old selection (SIA only or SIA/SYM) and attach the dcphy
+ * driver instead.
+ */
+ if (DC_IS_INTEL(sc)) {
+ dc_apply_fixup(sc, IFM_AUTO);
+ tmp = sc->dc_pmode;
+ sc->dc_pmode = DC_PMODE_MII;
+ }
+
sc->sc_mii.mii_ifp = ifp;
sc->sc_mii.mii_readreg = dc_miibus_readreg;
sc->sc_mii.mii_writereg = dc_miibus_writereg;
@@ -1488,7 +1663,9 @@ void dc_attach_common(sc)
if (DC_IS_INTEL(sc)) {
if (error) {
- sc->dc_pmode = DC_PMODE_SYM;
+ sc->dc_pmode = tmp;
+ if (sc->dc_pmode != DC_PMODE_SIA)
+ sc->dc_pmode = DC_PMODE_SYM;
sc->dc_flags |= DC_21143_NWAY;
mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff,
MII_PHY_ANY, MII_OFFSET_ANY, 0);
@@ -2331,6 +2508,10 @@ void dc_start(ifp)
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m_head);
#endif
+ if (sc->dc_flags & DC_TX_ONE) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
}
/* Transmit */
@@ -2507,6 +2688,15 @@ void dc_init(xsc)
timeout_add(&sc->dc_tick_tmo, hz);
}
+#ifdef SRM_MEDIA
+ if(sc->dc_srm_media) {
+ struct ifreq ifr;
+
+ ifr.ifr_media = sc->dc_srm_media;
+ ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
+ sc->dc_srm_media = 0;
+#endif
+
return;
}
@@ -2634,6 +2824,10 @@ int dc_ioctl(ifp, command, data)
case SIOCSIFMEDIA:
mii = &sc->sc_mii;
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+#ifdef SRM_MEDIA
+ if (sc->dc_srm_media)
+ sc->dc_srm_media = 0;
+#endif
break;
default:
error = EINVAL;
diff --git a/sys/dev/ic/dcreg.h b/sys/dev/ic/dcreg.h
index 8144a61afe4..d5e8e263201 100644
--- a/sys/dev/ic/dcreg.h
+++ b/sys/dev/ic/dcreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dcreg.h,v 1.9 2000/10/26 20:50:43 aaron Exp $ */
+/* $OpenBSD: dcreg.h,v 1.10 2001/02/09 02:23:35 aaron Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -101,6 +101,7 @@
/* MII/symbol mode port types */
#define DC_PMODE_MII 0x1
#define DC_PMODE_SYM 0x2
+#define DC_PMODE_SIA 0x3
/*
* Bus control bits.
@@ -354,21 +355,21 @@
/*
* SIA and General Purpose Port register (X3201)
*/
-#define DC_SIAGP_RXMATCH 0x40000000
-#define DC_SIAGP_INT1 0x20000000
-#define DC_SIAGP_INT0 0x10000000
-#define DC_SIAGP_WRITE_EN 0x08000000
-#define DC_SIAGP_RXMATCH_EN 0x04000000
-#define DC_SIAGP_INT1_EN 0x02000000
-#define DC_SIAGP_INT0_EN 0x01000000
-#define DC_SIAGP_LED3 0x00800000
-#define DC_SIAGP_LED2 0x00400000
-#define DC_SIAGP_LED1 0x00200000
-#define DC_SIAGP_LED0 0x00100000
-#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
-#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
-#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
-#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
+#define DC_SIAGP_RXMATCH 0x40000000
+#define DC_SIAGP_INT1 0x20000000
+#define DC_SIAGP_INT0 0x10000000
+#define DC_SIAGP_WRITE_EN 0x08000000
+#define DC_SIAGP_RXMATCH_EN 0x04000000
+#define DC_SIAGP_INT1_EN 0x02000000
+#define DC_SIAGP_INT0_EN 0x01000000
+#define DC_SIAGP_LED3 0x00800000
+#define DC_SIAGP_LED2 0x00400000
+#define DC_SIAGP_LED1 0x00200000
+#define DC_SIAGP_LED0 0x00100000
+#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
+#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
+#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
+#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
/*
* Size of a setup frame.
@@ -468,6 +469,15 @@ struct dc_chain_data {
int dc_rx_prod;
};
+struct dc_mediainfo {
+ int dc_media;
+ u_int8_t *dc_gp_ptr;
+ u_int8_t dc_gp_len;
+ u_int8_t *dc_reset_ptr;
+ u_int8_t dc_reset_len;
+ struct dc_mediainfo *dc_next;
+};
+
struct dc_type {
u_int16_t dc_vid;
u_int16_t dc_did;
@@ -520,8 +530,8 @@ struct dc_mii_frame {
/*
* ASIX specific registers.
*/
-#define DC_AX_FILTIDX 0x68 /* RX filter index */
-#define DC_AX_FILTDATA 0x70 /* RX filter data */
+#define DC_AX_FILTIDX 0x68 /* RX filter index */
+#define DC_AX_FILTDATA 0x70 /* RX filter data */
/*
* Special ASIX-specific bits in the ASIX NETCFG register (CSR6).
@@ -681,12 +691,17 @@ struct dc_softc {
int dc_if_media;
u_int32_t dc_flags;
u_int32_t dc_txthresh;
+ u_int8_t dc_srom[1024];
+ struct dc_mediainfo *dc_mi;
struct dc_list_data *dc_ldata;
caddr_t dc_ldata_ptr;
struct dc_chain_data dc_cdata;
u_int32_t dc_csid;
u_int dc_revision;
struct timeout dc_tick_tmo;
+#ifdef SRM_MEDIA
+ int dc_srm_media;
+#endif
};
#define DC_TX_POLL 0x00000001
@@ -704,6 +719,7 @@ struct dc_softc {
#define DC_128BIT_HASH 0x00001000
#define DC_64BIT_HASH 0x00002000
#define DC_TULIP_LEDS 0x00004000
+#define DC_TX_ONE 0x00008000
/*
* register space access macros
@@ -866,6 +882,110 @@ struct dc_softc {
#define DC_CWUC_SYM_ABILITY 0x00000080
#define DC_CWUC_LOCK 0x00000100
+/*
+ * SROM nonsense.
+ */
+
+#define DC_IB_CTLRCNT 0x13
+#define DC_IB_LEAF0_CNUM 0x1A
+#define DC_IB_LEAF0_OFFSET 0x1B
+
+struct dc_info_leaf {
+ u_int16_t dc_conntype;
+ u_int8_t dc_blkcnt;
+ u_int8_t dc_rsvd;
+ u_int16_t dc_infoblk;
+};
+
+#define DC_CTYPE_10BT 0x0000
+#define DC_CTYPE_10BT_NWAY 0x0100
+#define DC_CTYPE_10BT_FDX 0x0204
+#define DC_CTYPE_10B2 0x0001
+#define DC_CTYPE_10B5 0x0002
+#define DC_CTYPE_100BT 0x0003
+#define DC_CTYPE_100BT_FDX 0x0205
+#define DC_CTYPE_100T4 0x0006
+#define DC_CTYPE_100FX 0x0007
+#define DC_CTYPE_100FX_FDX 0x0208
+#define DC_CTYPE_MII_10BT 0x0009
+#define DC_CTYPE_MII_10BT_FDX 0x020A
+#define DC_CTYPE_MII_100BT 0x000D
+#define DC_CTYPE_MII_100BT_FDX 0x020E
+#define DC_CTYPE_MII_100T4 0x000F
+#define DC_CTYPE_MII_100FX 0x0010
+#define DC_CTYPE_MII_100FX_FDX 0x0211
+#define DC_CTYPE_DYN_PUP_AUTOSENSE 0x0800
+#define DC_CTYPE_PUP_AUTOSENSE 0x8800
+#define DC_CTYPE_NOMEDIA 0xFFFF
+
+#define DC_EBLOCK_SIA 0x0002
+#define DC_EBLOCK_MII 0x0003
+#define DC_EBLOCK_SYM 0x0004
+#define DC_EBLOCK_RESET 0x0005
+#define DC_EBLOCK_PHY_SHUTDOWN 0x0006
+
+struct dc_leaf_hdr {
+ u_int16_t dc_mtype;
+ u_int8_t dc_mcnt;
+ u_int8_t dc_rsvd;
+};
+
+struct dc_eblock_hdr {
+ u_int8_t dc_len;
+ u_int8_t dc_type;
+};
+
+struct dc_eblock_sia {
+ struct dc_eblock_hdr dc_sia_hdr;
+ u_int8_t dc_sia_code;
+ u_int8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
+ u_int8_t dc_sia_gpio_ctl[2];
+ u_int8_t dc_sia_gpio_dat[2];
+};
+
+#define DC_SIA_CODE_10BT 0x00
+#define DC_SIA_CODE_10B2 0x01
+#define DC_SIA_CODE_10B5 0x02
+#define DC_SIA_CODE_10BT_FDX 0x04
+#define DC_SIA_CODE_EXT 0x40
+
+/*
+ * Note that the first word in the gpr and reset
+ * sequences is always a control word.
+ */
+struct dc_eblock_mii {
+ struct dc_eblock_hdr dc_mii_hdr;
+ u_int8_t dc_mii_phynum;
+ u_int8_t dc_gpr_len;
+/* u_int16_t dc_gpr_dat[n]; */
+/* u_int8_t dc_reset_len; */
+/* u_int16_t dc_reset_dat[n]; */
+/* There are other fields after these, but we don't
+ * care about them since they can be determined by looking
+ * at the PHY.
+ */
+};
+
+struct dc_eblock_sym {
+ struct dc_eblock_hdr dc_sym_hdr;
+ u_int8_t dc_sym_code;
+ u_int8_t dc_sym_gpio_ctl[2];
+ u_int8_t dc_sym_gpio_dat[2];
+ u_int8_t dc_sym_cmd[2];
+};
+
+#define DC_SYM_CODE_100BT 0x03
+#define DC_SYM_CODE_100BT_FDX 0x05
+#define DC_SYM_CODE_100T4 0x06
+#define DC_SYM_CODE_100FX 0x07
+#define DC_SYM_CODE_100FX_FDX 0x08
+
+struct dc_eblock_reset {
+ struct dc_eblock_hdr dc_reset_hdr;
+ u_int8_t dc_reset_len;
+/* u_int16_t dc_reset_dat[n]; */
+};
+
#ifdef __alpha__
#undef vtophys
#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
diff --git a/sys/dev/pci/if_dc_pci.c b/sys/dev/pci/if_dc_pci.c
index 27cb61a77aa..ff2b0aa6b38 100644
--- a/sys/dev/pci/if_dc_pci.c
+++ b/sys/dev/pci/if_dc_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_dc_pci.c,v 1.11 2000/11/16 01:25:45 aaron Exp $ */
+/* $OpenBSD: if_dc_pci.c,v 1.12 2001/02/09 02:23:36 aaron Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -104,6 +104,10 @@ int dc_pci_probe __P((struct device *, void *, void *));
void dc_pci_attach __P((struct device *, struct device *, void *));
void dc_pci_acpi __P((struct device *, void *));
+extern void dc_read_eeprom __P((struct dc_softc *, caddr_t, int, int,
+ int));
+extern void dc_parse_21143_srom __P((struct dc_softc *));
+
/*
* Probe for a 21143 or clone chip. Check the PCI vendor and device
* IDs against our list and return a device name if we find a match.
@@ -263,6 +267,8 @@ void dc_pci_attach(parent, self, aux)
sc->dc_type = DC_TYPE_21143;
sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_REDUCED_MII_POLL;
+ /* Save EEPROM contents so we can parse them later. */
+ dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 512, 0);
}
break;
case PCI_VENDOR_DAVICOM:
@@ -424,32 +430,9 @@ void dc_pci_attach(parent, self, aux)
* The tricky ones are the Macronix/PNIC II and the
* Intel 21143.
*/
- if (DC_IS_INTEL(sc)) {
- u_int32_t media, cwuc;
- cwuc = pci_conf_read(pc, pa->pa_tag, DC_PCI_CWUC);
- cwuc |= DC_CWUC_FORCE_WUL;
- pci_conf_write(pc, pa->pa_tag, DC_PCI_CWUC, cwuc);
- DELAY(10000);
- media = pci_conf_read(pc, pa->pa_tag, DC_PCI_CWUC);
- cwuc &= ~DC_CWUC_FORCE_WUL;
- pci_conf_write(pc, pa->pa_tag, DC_PCI_CWUC, cwuc);
- DELAY(10000);
- if (media & DC_CWUC_MII_ABILITY)
- sc->dc_pmode = DC_PMODE_MII;
- if (media & DC_CWUC_SYM_ABILITY) {
- sc->dc_pmode = DC_PMODE_SYM;
- sc->dc_flags |= DC_21143_NWAY;
- }
- /*
- * If none of the bits are set, then this NIC
- * isn't meant to support 'wake up LAN' mode.
- * This is usually only the case on multiport
- * cards, and these cards almost always have
- * MII transceivers.
- */
- if (media == 0)
- sc->dc_pmode = DC_PMODE_MII;
- } else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
+ if (DC_IS_INTEL(sc))
+ dc_parse_21143_srom(sc);
+ else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
if (sc->dc_type == DC_TYPE_98713)
sc->dc_pmode = DC_PMODE_MII;
else
@@ -457,6 +440,32 @@ void dc_pci_attach(parent, self, aux)
} else if (!sc->dc_pmode)
sc->dc_pmode = DC_PMODE_MII;
+#ifdef SRM_MEDIA
+ sc->dc_srm_media = 0;
+
+ /* Remember the SRM console media setting */
+ if (DC_IS_INTEL(sc)) {
+ command = pci_read_config(dev, DC_PCI_CFDD, 4);
+ command &= ~(DC_CFDD_SNOOZE_MODE|DC_CFDD_SLEEP_MODE);
+ switch ((command >> 8) & 0xff) {
+ case 3:
+ sc->dc_srm_media = IFM_10_T;
+ break;
+ case 4:
+ sc->dc_srm_media = IFM_10_T | IFM_FDX;
+ break;
+ case 5:
+ sc->dc_srm_media = IFM_100_TX;
+ break;
+ case 6:
+ sc->dc_srm_media = IFM_100_TX | IFM_FDX;
+ break;
+ }
+ if (sc->dc_srm_media)
+ sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER;
+ }
+#endif
+
dc_attach_common(sc);
fail: