aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2000-10-05 17:36:14 +0000
committerBill Paul <wpaul@FreeBSD.org>2000-10-05 17:36:14 +0000
commit5c1cfac46e47ae5f83346be09703ae711e47b4a4 (patch)
tree4b47a08c23d6c1d8c369e0700170c125e8bc4f89 /sys/dev
parentb75e82a0e60b039d0eca71e903a01a8bdc76813f (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dc/dcphy.c22
-rw-r--r--sys/dev/dc/if_dc.c278
-rw-r--r--sys/dev/dc/if_dcreg.h120
-rw-r--r--sys/dev/mii/dcphy.c22
4 files changed, 369 insertions, 73 deletions
diff --git a/sys/dev/dc/dcphy.c b/sys/dev/dc/dcphy.c
index 73e241e8f5cc..ad2599c69583 100644
--- a/sys/dev/dc/dcphy.c
+++ b/sys/dev/dc/dcphy.c
@@ -179,12 +179,17 @@ static int dcphy_attach(dev)
sc->mii_capabilities = BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX;
break;
default:
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
- sc->mii_inst), BMCR_LOOP|BMCR_S100);
+ if (dc_sc->dc_pmode == DC_PMODE_SIA) {
+ sc->mii_capabilities =
+ BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX;
+ } else {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
+ sc->mii_inst), BMCR_LOOP|BMCR_S100);
- sc->mii_capabilities =
- BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX|
- BMSR_10TFDX|BMSR_10THDX;
+ sc->mii_capabilities =
+ BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX|
+ BMSR_10TFDX|BMSR_10THDX;
+ }
break;
}
@@ -429,10 +434,11 @@ dcphy_status(sc)
}
skip:
- if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SCRAMBLER)
- mii->mii_media_active |= IFM_100_TX;
- else
+
+ if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SPEEDSEL)
mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_100_TX;
if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_FULLDUPLEX)
mii->mii_media_active |= IFM_FDX;
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 039f83574243..695b019fec29 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -73,27 +73,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
@@ -140,6 +119,9 @@
#include <pci/pcivar.h>
#define DC_USEIOSPACE
+#ifdef __alpha__
+#define SRM_MEDIA
+#endif
#include <pci/if_dcreg.h>
@@ -257,6 +239,15 @@ static void dc_reset __P((struct dc_softc *));
static int dc_list_rx_init __P((struct dc_softc *));
static int dc_list_tx_init __P((struct dc_softc *));
+static void dc_parse_21143_srom __P((struct dc_softc *));
+static void dc_decode_leaf_sia __P((struct dc_softc *,
+ struct dc_eblock_sia *));
+static void dc_decode_leaf_mii __P((struct dc_softc *,
+ struct dc_eblock_mii *));
+static void dc_decode_leaf_sym __P((struct dc_softc *,
+ struct dc_eblock_sym *));
+static void dc_apply_fixup __P((struct dc_softc *, int));
+
#ifdef DC_USEIOSPACE
#define DC_RES SYS_RES_IOPORT
#define DC_RID DC_PCI_CFBIO
@@ -691,7 +682,7 @@ static int dc_miibus_readreg(dev, 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:
@@ -860,6 +851,7 @@ static void dc_miibus_statchg(dev)
sc = device_get_softc(dev);
if (DC_IS_ADMTEK(sc))
return;
+
mii = device_get_softc(sc->dc_miibus);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc) &&
@@ -1248,6 +1240,10 @@ static 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);
}
}
@@ -1278,6 +1274,21 @@ static 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);
+ }
}
}
@@ -1346,8 +1357,11 @@ static 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;
}
@@ -1456,6 +1470,155 @@ static void dc_acpi(dev)
return;
}
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
/*
* Attach the interface. Allocate softc structures, do ifmedia
* setup and ethernet/BPF attach.
@@ -1463,7 +1626,7 @@ static void dc_acpi(dev)
static int dc_attach(dev)
device_t dev;
{
- int s;
+ int s, tmp = 0;
u_char eaddr[ETHER_ADDR_LEN];
u_int32_t command;
struct dc_softc *sc;
@@ -1548,12 +1711,14 @@ static int dc_attach(dev)
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 DC_DEVICEID_DM9100:
case DC_DEVICEID_DM9102:
sc->dc_type = DC_TYPE_DM9102;
sc->dc_flags |= DC_TX_COALESCE|DC_TX_USE_TX_INTR;
- sc->dc_flags |= DC_REDUCED_MII_POLL;
+ sc->dc_flags |= DC_REDUCED_MII_POLL|DC_TX_ONE;
sc->dc_pmode = DC_PMODE_MII;
break;
case DC_DEVICEID_AL981:
@@ -1650,32 +1815,9 @@ static int dc_attach(dev)
* The tricky ones are the Macronix/PNIC II and the
* Intel 21143.
*/
- if (DC_IS_INTEL(sc)) {
- u_int32_t media, cwuc;
- cwuc = pci_read_config(dev, DC_PCI_CWUC, 4);
- cwuc |= DC_CWUC_FORCE_WUL;
- pci_write_config(dev, DC_PCI_CWUC, cwuc, 4);
- DELAY(10000);
- media = pci_read_config(dev, DC_PCI_CWUC, 4);
- cwuc &= ~DC_CWUC_FORCE_WUL;
- pci_write_config(dev, DC_PCI_CWUC, cwuc, 4);
- 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
@@ -1749,13 +1891,25 @@ static int dc_attach(dev)
ifp->if_snd.ifq_maxlen = DC_TX_LIST_CNT - 1;
/*
- * Do MII setup.
+ * 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;
+ }
+
error = mii_phy_probe(dev, &sc->dc_miibus,
dc_ifmedia_upd, dc_ifmedia_sts);
if (error && DC_IS_INTEL(sc)) {
- 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_phy_probe(dev, &sc->dc_miibus,
dc_ifmedia_upd, dc_ifmedia_sts);
@@ -1786,7 +1940,7 @@ static int dc_attach(dev)
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
callout_handle_init(&sc->dc_stat_ch);
-#ifdef __alpha__
+#ifdef SRM_MEDIA
sc->dc_srm_media = 0;
/* Remember the SRM console media setting */
@@ -1825,6 +1979,7 @@ static int dc_detach(dev)
struct dc_softc *sc;
struct ifnet *ifp;
int s;
+ struct dc_mediainfo *m;
s = splimp();
@@ -1845,6 +2000,12 @@ static int dc_detach(dev)
if (sc->dc_pnic_rx_buf != NULL)
free(sc->dc_pnic_rx_buf, M_DEVBUF);
+ while(sc->dc_mi != NULL) {
+ m = sc->dc_mi->dc_next;
+ free(sc->dc_mi, M_DEVBUF);
+ sc->dc_mi = m;
+ }
+
splx(s);
return(0);
@@ -2609,6 +2770,11 @@ static void dc_start(ifp)
*/
if (ifp->if_bpf)
bpf_mtap(ifp, m_head);
+
+ if (sc->dc_flags & DC_TX_ONE) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
}
/* Transmit */
@@ -2775,7 +2941,7 @@ static void dc_init(xsc)
sc->dc_stat_ch = timeout(dc_tick, sc, hz);
}
-#ifdef __alpha__
+#ifdef SRM_MEDIA
if(sc->dc_srm_media) {
struct ifreq ifr;
@@ -2887,7 +3053,7 @@ static int dc_ioctl(ifp, command, data)
case SIOCSIFMEDIA:
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
-#ifdef __alpha__
+#ifdef SRM_MEDIA
if (sc->dc_srm_media)
sc->dc_srm_media = 0;
#endif
diff --git a/sys/dev/dc/if_dcreg.h b/sys/dev/dc/if_dcreg.h
index a0a2444de88b..9c6cfc41bf43 100644
--- a/sys/dev/dc/if_dcreg.h
+++ b/sys/dev/dc/if_dcreg.h
@@ -96,6 +96,7 @@
/* MII/symbol mode port types */
#define DC_PMODE_MII 0x1
#define DC_PMODE_SYM 0x2
+#define DC_PMODE_SIA 0x3
/*
* Bus control bits.
@@ -445,6 +446,16 @@ 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;
@@ -657,10 +668,12 @@ 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;
struct dc_chain_data dc_cdata;
struct callout_handle dc_stat_ch;
-#ifdef __alpha__
+#ifdef SRM_MEDIA
int dc_srm_media;
#endif
};
@@ -680,6 +693,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
@@ -930,6 +944,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/mii/dcphy.c b/sys/dev/mii/dcphy.c
index 73e241e8f5cc..ad2599c69583 100644
--- a/sys/dev/mii/dcphy.c
+++ b/sys/dev/mii/dcphy.c
@@ -179,12 +179,17 @@ static int dcphy_attach(dev)
sc->mii_capabilities = BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX;
break;
default:
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
- sc->mii_inst), BMCR_LOOP|BMCR_S100);
+ if (dc_sc->dc_pmode == DC_PMODE_SIA) {
+ sc->mii_capabilities =
+ BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX;
+ } else {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
+ sc->mii_inst), BMCR_LOOP|BMCR_S100);
- sc->mii_capabilities =
- BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX|
- BMSR_10TFDX|BMSR_10THDX;
+ sc->mii_capabilities =
+ BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX|
+ BMSR_10TFDX|BMSR_10THDX;
+ }
break;
}
@@ -429,10 +434,11 @@ dcphy_status(sc)
}
skip:
- if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SCRAMBLER)
- mii->mii_media_active |= IFM_100_TX;
- else
+
+ if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SPEEDSEL)
mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_100_TX;
if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_FULLDUPLEX)
mii->mii_media_active |= IFM_FDX;