From 2f846fc8203421908f9706aac9453120877748fa Mon Sep 17 00:00:00 2001 From: brad Date: Thu, 8 Jan 2015 00:49:18 +0000 Subject: [PATCH] Use the correct config registers for the RTL8139 family. Unlike the RTL8169 and RTL8168 family, the RTL8139 has different register map for config registers. From FreeBSD WoL bits reviewed and tested by stsp@ --- sys/dev/ic/re.c | 67 ++++++++++++++++++++++++++--------------- sys/dev/ic/rtl81x9.c | 11 +++++-- sys/dev/ic/rtl81x9reg.h | 16 +++++++++- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index be5f37f4d90..a47296c5f86 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.166 2015/01/04 07:14:41 brad Exp $ */ +/* $OpenBSD: re.c,v 1.167 2015/01/08 00:49:18 brad Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -799,6 +799,22 @@ re_attach(struct rl_softc *sc, const char *intrstr) break; } + if (sc->sc_hwrev == RL_HWREV_8139CPLUS) { + sc->rl_cfg0 = RL_8139_CFG0; + sc->rl_cfg1 = RL_8139_CFG1; + sc->rl_cfg2 = 0; + sc->rl_cfg3 = RL_8139_CFG3; + sc->rl_cfg4 = RL_8139_CFG4; + sc->rl_cfg5 = RL_8139_CFG5; + } else { + sc->rl_cfg0 = RL_CFG0; + sc->rl_cfg1 = RL_CFG1; + sc->rl_cfg2 = RL_CFG2; + sc->rl_cfg3 = RL_CFG3; + sc->rl_cfg4 = RL_CFG4; + sc->rl_cfg5 = RL_CFG5; + } + /* Reset the adapter. */ re_reset(sc); @@ -817,7 +833,7 @@ re_attach(struct rl_softc *sc, const char *intrstr) else { u_int8_t cfg2; - cfg2 = CSR_READ_1(sc, RL_CFG2); + cfg2 = CSR_READ_1(sc, sc->rl_cfg2); switch (cfg2 & RL_CFG2_PCI_MASK) { case RL_CFG2_PCI_33MHZ: sc->rl_bus_speed = 33; @@ -1968,7 +1984,8 @@ re_init(struct ifnet *ifp) mii_mediachg(&sc->sc_mii); - CSR_WRITE_1(sc, RL_CFG1, CSR_READ_1(sc, RL_CFG1) | RL_CFG1_DRVLOAD); + CSR_WRITE_1(sc, sc->rl_cfg1, CSR_READ_1(sc, sc->rl_cfg1) | + RL_CFG1_DRVLOAD); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -2303,28 +2320,15 @@ int re_wol(struct ifnet *ifp, int enable) { struct rl_softc *sc = ifp->if_softc; - int i; u_int8_t val; - struct re_wolcfg { - u_int8_t enable; - u_int8_t reg; - u_int8_t bit; - } re_wolcfg[] = { - /* Always disable all wake events expect magic packet. */ - { 0, RL_CFG5, RL_CFG5_WOL_UCAST }, - { 0, RL_CFG5, RL_CFG5_WOL_MCAST }, - { 0, RL_CFG5, RL_CFG5_WOL_BCAST }, - { 1, RL_CFG3, RL_CFG3_WOL_MAGIC }, - { 0, RL_CFG3, RL_CFG3_WOL_LINK } - }; if (enable) { - if ((CSR_READ_1(sc, RL_CFG1) & RL_CFG1_PME) == 0) { + if ((CSR_READ_1(sc, sc->rl_cfg1) & RL_CFG1_PME) == 0) { printf("%s: power management is disabled, " "cannot do WOL\n", sc->sc_dev.dv_xname); return (ENOTSUP); } - if ((CSR_READ_1(sc, RL_CFG2) & RL_CFG2_AUXPWR) == 0) + if ((CSR_READ_1(sc, sc->rl_cfg2) & RL_CFG2_AUXPWR) == 0) printf("%s: no auxiliary power, cannot do WOL from D3 " "(power-off) state\n", sc->sc_dev.dv_xname); } @@ -2334,13 +2338,26 @@ re_wol(struct ifnet *ifp, int enable) /* Temporarily enable write to configuration registers. */ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG); - for (i = 0; i < nitems(re_wolcfg); i++) { - val = CSR_READ_1(sc, re_wolcfg[i].reg); - if (enable && re_wolcfg[i].enable) - val |= re_wolcfg[i].bit; - else - val &= ~re_wolcfg[i].bit; - CSR_WRITE_1(sc, re_wolcfg[i].reg, val); + /* Always disable all wake events except magic packet. */ + if (enable) { + val = CSR_READ_1(sc, sc->rl_cfg5); + val &= ~(RL_CFG5_WOL_UCAST | RL_CFG5_WOL_MCAST | + RL_CFG5_WOL_BCAST); + CSR_WRITE_1(sc, sc->rl_cfg5, val); + + val = CSR_READ_1(sc, sc->rl_cfg3); + val |= RL_CFG3_WOL_MAGIC; + val &= ~RL_CFG3_WOL_LINK; + CSR_WRITE_1(sc, sc->rl_cfg3, val); + } else { + val = CSR_READ_1(sc, sc->rl_cfg5); + val &= ~(RL_CFG5_WOL_UCAST | RL_CFG5_WOL_MCAST | + RL_CFG5_WOL_BCAST); + CSR_WRITE_1(sc, sc->rl_cfg5, val); + + val = CSR_READ_1(sc, sc->rl_cfg3); + val &= ~(RL_CFG3_WOL_MAGIC | RL_CFG3_WOL_LINK); + CSR_WRITE_1(sc, sc->rl_cfg3, val); } CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); diff --git a/sys/dev/ic/rtl81x9.c b/sys/dev/ic/rtl81x9.c index 2f0bf2a93e2..16803467219 100644 --- a/sys/dev/ic/rtl81x9.c +++ b/sys/dev/ic/rtl81x9.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtl81x9.c,v 1.86 2014/12/22 02:28:51 tedu Exp $ */ +/* $OpenBSD: rtl81x9.c,v 1.87 2015/01/08 00:49:18 brad Exp $ */ /* * Copyright (c) 1997, 1998 @@ -974,7 +974,7 @@ rl_init(void *xsc) mii_mediachg(&sc->sc_mii); - CSR_WRITE_1(sc, RL_CFG1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX); + CSR_WRITE_1(sc, sc->rl_cfg1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -1118,6 +1118,13 @@ rl_attach(struct rl_softc *sc) caddr_t kva; int addr_len; + sc->rl_cfg0 = RL_8139_CFG0; + sc->rl_cfg1 = RL_8139_CFG1; + sc->rl_cfg2 = 0; + sc->rl_cfg3 = RL_8139_CFG3; + sc->rl_cfg4 = RL_8139_CFG4; + sc->rl_cfg5 = RL_8139_CFG5; + rl_reset(sc); /* diff --git a/sys/dev/ic/rtl81x9reg.h b/sys/dev/ic/rtl81x9reg.h index 0be8c6194a0..dba1ad606d6 100644 --- a/sys/dev/ic/rtl81x9reg.h +++ b/sys/dev/ic/rtl81x9reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rtl81x9reg.h,v 1.88 2014/11/24 02:03:37 brad Exp $ */ +/* $OpenBSD: rtl81x9reg.h,v 1.89 2015/01/08 00:49:18 brad Exp $ */ /* * Copyright (c) 1997, 1998 @@ -76,6 +76,14 @@ #define RL_TIMERCNT 0x0048 /* timer count register */ #define RL_MISSEDPKT 0x004C /* missed packet counter */ #define RL_EECMD 0x0050 /* EEPROM command register */ + +/* RTL8139/RTL8139C+ only */ +#define RL_8139_CFG0 0x0051 /* config register #0 */ +#define RL_8139_CFG1 0x0052 /* config register #1 */ +#define RL_8139_CFG3 0x0059 /* config register #3 */ +#define RL_8139_CFG4 0x005A /* config register #4 */ +#define RL_8139_CFG5 0x00D8 /* config register #5 */ + #define RL_CFG0 0x0051 /* config register #0 */ #define RL_CFG1 0x0052 /* config register #1 */ #define RL_CFG2 0x0053 /* config register #2 */ @@ -838,6 +846,12 @@ struct rl_softc { int rl_eewidth; int rl_bus_speed; int rl_txthresh; + bus_size_t rl_cfg0; + bus_size_t rl_cfg1; + bus_size_t rl_cfg2; + bus_size_t rl_cfg3; + bus_size_t rl_cfg4; + bus_size_t rl_cfg5; struct rl_chain_data rl_cdata; struct timeout sc_tick_tmo; -- 2.20.1