summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1999-04-10 18:44:53 +0000
committerwpaul <wpaul@FreeBSD.org>1999-04-10 18:44:53 +0000
commit4c3f741f0c1e261a383ad0ce26ae922f8e4d9d84 (patch)
treefe8fd8d722eb4d46840ffc610954939dea6464bb /sys/pci
parentb790d856f9d0e1847332703dbd5527af921734c7 (diff)
downloadFreeBSD-src-4c3f741f0c1e261a383ad0ce26ae922f8e4d9d84.zip
FreeBSD-src-4c3f741f0c1e261a383ad0ce26ae922f8e4d9d84.tar.gz
Finally add support for the older 82c168 PNIC chip with the built-in
transceiver. Thanks to Brian Walenze for donating a NIC with this chip on it (LinkSys didn't really sell that many of them and they're not in production anymore). The driver now distinguishes between the 82c168 and 82c169 when probing. If no MII transceiver is detected, it switches over to using the internal one.
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_pn.c294
-rw-r--r--sys/pci/if_pnreg.h58
2 files changed, 314 insertions, 38 deletions
diff --git a/sys/pci/if_pn.c b/sys/pci/if_pn.c
index ee81b37..24a3c5b 100644
--- a/sys/pci/if_pn.c
+++ b/sys/pci/if_pn.c
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_pn.c,v 1.42 1999/03/30 19:29:25 wpaul Exp $
+ * $Id: if_pn.c,v 1.45 1999/04/10 18:22:22 wpaul Exp $
*/
/*
@@ -97,7 +97,7 @@
#ifndef lint
static const char rcsid[] =
- "$Id: if_pn.c,v 1.42 1999/03/30 19:29:25 wpaul Exp $";
+ "$Id: if_pn.c,v 1.45 1999/04/10 18:22:22 wpaul Exp $";
#endif
/*
@@ -105,7 +105,9 @@ static const char rcsid[] =
*/
static struct pn_type pn_devs[] = {
{ PN_VENDORID, PN_DEVICEID_PNIC,
- "82c168/82c169 PNIC 10/100BaseTX" },
+ "82c168 PNIC 10/100BaseTX" },
+ { PN_VENDORID, PN_DEVICEID_PNIC,
+ "82c169 PNIC 10/100BaseTX" },
{ PN_VENDORID, PN_DEVICEID_PNIC_II,
"82c115 PNIC II 10/100BaseTX" },
{ 0, 0, NULL }
@@ -164,7 +166,9 @@ static void pn_autoneg_xmit __P((struct pn_softc *));
static void pn_autoneg_mii __P((struct pn_softc *, int, int));
static void pn_setmode_mii __P((struct pn_softc *, int));
static void pn_getmode_mii __P((struct pn_softc *));
-static void pn_setcfg __P((struct pn_softc *, u_int16_t));
+static void pn_autoneg __P((struct pn_softc *, int, int));
+static void pn_setmode __P((struct pn_softc *, int));
+static void pn_setcfg __P((struct pn_softc *, u_int32_t));
static u_int32_t pn_calchash __P((u_int8_t *));
static void pn_setfilt __P((struct pn_softc *));
static void pn_reset __P((struct pn_softc *));
@@ -441,7 +445,7 @@ static void pn_autoneg_mii(sc, flag, verbose)
media &= ~PHY_BMCR_AUTONEGENBL;
/* Set ASIC's duplex mode to match the PHY. */
- pn_setcfg(sc, media);
+ pn_setcfg(sc, ifm->ifm_media);
pn_phy_writereg(sc, PHY_BMCR, media);
} else {
if (verbose)
@@ -539,9 +543,166 @@ static void pn_getmode_mii(sc)
return;
}
-/*
- * Set speed and duplex mode.
- */
+static void pn_autoneg(sc, flag, verbose)
+ struct pn_softc *sc;
+ int flag;
+ int verbose;
+{
+ u_int32_t nway = 0, ability;
+ struct ifnet *ifp;
+ struct ifmedia *ifm;
+
+ ifm = &sc->ifmedia;
+ ifp = &sc->arpcom.ac_if;
+
+ ifm->ifm_media = IFM_ETHER | IFM_AUTO;
+
+ switch (flag) {
+ case PN_FLAG_FORCEDELAY:
+ /*
+ * XXX Never use this option anywhere but in the probe
+ * routine: making the kernel stop dead in its tracks
+ * for three whole seconds after we've gone multi-user
+ * is really bad manners.
+ */
+ CSR_WRITE_4(sc, PN_GEN,
+ PN_GEN_MUSTBEONE|PN_GEN_100TX_LOOP);
+ PN_CLRBIT(sc, PN_NWAY, PN_NWAY_AUTONEGRSTR);
+ PN_SETBIT(sc, PN_NWAY, PN_NWAY_AUTOENB);
+ DELAY(5000000);
+ break;
+ case PN_FLAG_SCHEDDELAY:
+ /*
+ * Wait for the transmitter to go idle before starting
+ * an autoneg session, otherwise pn_start() may clobber
+ * our timeout, and we don't want to allow transmission
+ * during an autoneg session since that can screw it up.
+ */
+ if (sc->pn_cdata.pn_tx_head != NULL) {
+ sc->pn_want_auto = 1;
+ return;
+ }
+ CSR_WRITE_4(sc, PN_GEN,
+ PN_GEN_MUSTBEONE|PN_GEN_100TX_LOOP);
+ PN_CLRBIT(sc, PN_NWAY, PN_NWAY_AUTONEGRSTR);
+ PN_SETBIT(sc, PN_NWAY, PN_NWAY_AUTOENB);
+ ifp->if_timer = 5;
+ sc->pn_autoneg = 1;
+ sc->pn_want_auto = 0;
+ return;
+ break;
+ case PN_FLAG_DELAYTIMEO:
+ ifp->if_timer = 0;
+ sc->pn_autoneg = 0;
+ break;
+ default:
+ printf("pn%d: invalid autoneg flag: %d\n", sc->pn_unit, flag);
+ return;
+ }
+
+ if (CSR_READ_4(sc, PN_NWAY) & PN_NWAY_LPAR) {
+ if (verbose)
+ printf("pn%d: autoneg complete, ", sc->pn_unit);
+ } else {
+ if (verbose)
+ printf("pn%d: autoneg not complete, ", sc->pn_unit);
+ }
+
+ /* Link is good. Report modes and set duplex mode. */
+ if (CSR_READ_4(sc, PN_ISR) & PN_ISR_LINKPASS) {
+ if (verbose)
+ printf("link status good ");
+
+ ability = CSR_READ_4(sc, PN_NWAY);
+ if (ability & PN_NWAY_LPAR100T4) {
+ ifm->ifm_media = IFM_ETHER|IFM_100_T4;
+ nway = PN_NWAY_MODE_100T4;
+ printf("(100baseT4)\n");
+ } else if (ability & PN_NWAY_LPAR100FULL) {
+ ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX;
+ nway = PN_NWAY_MODE_100FD;
+ printf("(full-duplex, 100Mbps)\n");
+ } else if (ability & PN_NWAY_LPAR100HALF) {
+ ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX;
+ nway = PN_NWAY_MODE_100HD;
+ printf("(half-duplex, 100Mbps)\n");
+ } else if (ability & PN_NWAY_LPAR10FULL) {
+ ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX;
+ nway = PN_NWAY_MODE_10FD;
+ printf("(full-duplex, 10Mbps)\n");
+ } else if (ability & PN_NWAY_LPAR10HALF) {
+ ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
+ nway = PN_NWAY_MODE_10HD;
+ printf("(half-duplex, 10Mbps)\n");
+ }
+
+ /* Set ASIC's duplex mode to match the PHY. */
+ pn_setcfg(sc, ifm->ifm_media);
+ CSR_WRITE_4(sc, PN_NWAY, nway);
+ } else {
+ if (verbose)
+ printf("no carrier\n");
+ }
+
+ pn_init(sc);
+
+ if (sc->pn_tx_pend) {
+ sc->pn_autoneg = 0;
+ sc->pn_tx_pend = 0;
+ pn_start(ifp);
+ }
+
+ return;
+}
+
+static void pn_setmode(sc, media)
+ struct pn_softc *sc;
+ int media;
+{
+ u_int32_t nway = 0;
+ struct ifnet *ifp;
+
+ ifp = &sc->arpcom.ac_if;
+
+ /*
+ * If an autoneg session is in progress, stop it.
+ */
+ if (sc->pn_autoneg) {
+ printf("pn%d: canceling autoneg session\n", sc->pn_unit);
+ ifp->if_timer = sc->pn_autoneg = sc->pn_want_auto = 0;
+ PN_CLRBIT(sc, PN_NWAY, PN_NWAY_AUTONEGRSTR);
+ }
+
+ printf("pn%d: selecting NWAY, ", sc->pn_unit);
+
+ if (IFM_SUBTYPE(media) == IFM_100_T4) {
+ printf("100Mbps/T4, half-duplex\n");
+ nway = PN_NWAY_MODE_100T4;
+ }
+
+ if (IFM_SUBTYPE(media) == IFM_100_TX) {
+ printf("100Mbps, ");
+ nway = PN_NWAY_MODE_100HD;
+ }
+
+ if (IFM_SUBTYPE(media) == IFM_10_T) {
+ printf("10Mbps, ");
+ nway = PN_NWAY_MODE_10HD;
+ }
+
+ if ((media & IFM_GMASK) == IFM_FDX) {
+ printf("full duplex\n");
+ nway |= PN_NWAY_DUPLEX;
+ } else {
+ printf("half duplex\n");
+ }
+
+ pn_setcfg(sc, media);
+ CSR_WRITE_4(sc, PN_NWAY, nway);
+
+ return;
+}
+
static void pn_setmode_mii(sc, media)
struct pn_softc *sc;
int media;
@@ -593,7 +754,7 @@ static void pn_setmode_mii(sc, media)
bmcr &= ~PHY_BMCR_DUPLEX;
}
- pn_setcfg(sc, bmcr);
+ pn_setcfg(sc, media);
pn_phy_writereg(sc, PHY_BMCR, bmcr);
return;
@@ -688,9 +849,9 @@ void pn_setfilt(sc)
* 'full-duplex' and '100Mbps' bits in the netconfig register, we
* first have to put the transmit and/or receive logic in the idle state.
*/
-static void pn_setcfg(sc, bmcr)
+static void pn_setcfg(sc, media)
struct pn_softc *sc;
- u_int16_t bmcr;
+ u_int32_t media;
{
int i, restart = 0;
@@ -711,12 +872,17 @@ static void pn_setcfg(sc, bmcr)
}
- if (bmcr & PHY_BMCR_SPEEDSEL)
+ if (IFM_SUBTYPE(media) == IFM_100_TX) {
PN_CLRBIT(sc, PN_NETCFG, PN_NETCFG_SPEEDSEL);
- else
+ CSR_WRITE_4(sc, PN_GEN, PN_GEN_MUSTBEONE|
+ PN_GEN_SPEEDSEL|PN_GEN_100TX_LOOP);
+ } else {
PN_SETBIT(sc, PN_NETCFG, PN_NETCFG_SPEEDSEL);
+ CSR_WRITE_4(sc, PN_GEN,
+ PN_GEN_MUSTBEONE|PN_GEN_100TX_LOOP);
+ }
- if (bmcr & PHY_BMCR_DUPLEX)
+ if ((media & IFM_GMASK) == IFM_FDX)
PN_SETBIT(sc, PN_NETCFG, PN_NETCFG_FULLDUPLEX);
else
PN_CLRBIT(sc, PN_NETCFG, PN_NETCFG_FULLDUPLEX);
@@ -757,12 +923,28 @@ pn_probe(config_id, device_id)
pcidi_t device_id;
{
struct pn_type *t;
+ u_int32_t rev;
t = pn_devs;
while(t->pn_name != NULL) {
if ((device_id & 0xFFFF) == t->pn_vid &&
((device_id >> 16) & 0xFFFF) == t->pn_did) {
+ if (t->pn_did == PN_DEVICEID_PNIC) {
+ rev = pci_conf_read(config_id,
+ PN_PCI_REVISION) & 0xFF;
+ switch(rev & PN_REVMASK) {
+ case PN_REVID_82C168:
+ return(t->pn_name);
+ break;
+ case PN_REVID_82C169:
+ t++;
+ return(t->pn_name);
+ default:
+ printf("unknown PNIC rev: %x\n", rev);
+ break;
+ }
+ }
return(t->pn_name);
}
t++;
@@ -886,6 +1068,9 @@ pn_attach(config_id, unit)
goto fail;
}
+ /* Save the cache line size. */
+ sc->pn_cachesize = pci_conf_read(config_id, PN_PCI_CACHELEN) & 0xFF;
+
/* Reset the adapter. */
pn_reset(sc);
@@ -951,6 +1136,8 @@ pn_attach(config_id, unit)
ifp->if_baudrate = 10000000;
ifp->if_snd.ifq_maxlen = PN_TX_LIST_CNT - 1;
+ ifmedia_init(&sc->ifmedia, 0, pn_ifmedia_upd, pn_ifmedia_sts);
+
if (bootverbose)
printf("pn%d: probing for a PHY\n", sc->pn_unit);
for (i = PN_PHYADDR_MIN; i < PN_PHYADDR_MAX + 1; i++) {
@@ -988,21 +1175,25 @@ pn_attach(config_id, unit)
if (bootverbose)
printf("pn%d: PHY type: %s\n",
sc->pn_unit, sc->pn_pinfo->pn_name);
+
+ pn_getmode_mii(sc);
+ pn_autoneg_mii(sc, PN_FLAG_FORCEDELAY, 1);
} else {
- printf("pn%d: MII without any phy!\n", sc->pn_unit);
- goto fail;
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
+ ifmedia_add(&sc->ifmedia,
+ IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL);
+ ifmedia_add(&sc->ifmedia,
+ IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_T4, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
+ pn_autoneg(sc, PN_FLAG_FORCEDELAY, 1);
}
- /*
- * Do ifmedia setup.
- */
- ifmedia_init(&sc->ifmedia, 0, pn_ifmedia_upd, pn_ifmedia_sts);
-
- pn_getmode_mii(sc);
- pn_autoneg_mii(sc, PN_FLAG_FORCEDELAY, 1);
media = sc->ifmedia.ifm_media;
pn_stop(sc);
-
ifmedia_set(&sc->ifmedia, media);
/*
@@ -1477,8 +1668,13 @@ static void pn_txeoc(sc)
if (sc->pn_cdata.pn_tx_head == NULL) {
ifp->if_flags &= ~IFF_OACTIVE;
sc->pn_cdata.pn_tx_tail = NULL;
- if (sc->pn_want_auto)
- pn_autoneg_mii(sc, PN_FLAG_SCHEDDELAY, 1);
+ if (sc->pn_want_auto) {
+ if (sc->pn_pinfo == NULL)
+ pn_autoneg(sc, PN_FLAG_SCHEDDELAY, 1);
+ else
+ pn_autoneg_mii(sc, PN_FLAG_SCHEDDELAY, 1);
+ }
+
}
return;
@@ -1746,7 +1942,22 @@ static void pn_init(xsc)
/*
* Set cache alignment and burst length.
*/
- CSR_WRITE_4(sc, PN_BUSCTL, PN_BUSCTL_CONFIG);
+ switch(sc->pn_cachesize) {
+ case 32:
+ PN_SETBIT(sc, PN_BUSCTL, PN_CACHEALIGN_32LONG);
+ break;
+ case 16:
+ PN_SETBIT(sc, PN_BUSCTL, PN_CACHEALIGN_16LONG);
+ break;
+ case 8:
+ PN_SETBIT(sc, PN_BUSCTL, PN_CACHEALIGN_8LONG);
+ break;
+ case 0:
+ default:
+ PN_SETBIT(sc, PN_BUSCTL, PN_CACHEALIGN_NONE);
+ break;
+ }
+ CSR_WRITE_4(sc, PN_BUSCTL, PN_BURSTLEN_USECA);
PN_CLRBIT(sc, PN_NETCFG, PN_NETCFG_TX_IMMEDIATE);
PN_CLRBIT(sc, PN_NETCFG, PN_NETCFG_NO_RXCRC);
@@ -1757,13 +1968,16 @@ static void pn_init(xsc)
PN_CLRBIT(sc, PN_NETCFG, PN_NETCFG_TX_THRESH);
PN_SETBIT(sc, PN_NETCFG, PN_TXTHRESH_72BYTES);
- pn_setcfg(sc, pn_phy_readreg(sc, PHY_BMCR));
-
- if (sc->pn_pinfo != NULL) {
+ if (sc->pn_pinfo == NULL) {
+ PN_CLRBIT(sc, PN_NETCFG, PN_NETCFG_MIIENB);
+ PN_SETBIT(sc, PN_NETCFG, PN_NETCFG_TX_BACKOFF);
+ } else {
PN_SETBIT(sc, PN_NETCFG, PN_NETCFG_MIIENB);
PN_SETBIT(sc, PN_ENDEC, PN_ENDEC_JABBERDIS);
}
+ pn_setcfg(sc, sc->ifmedia.ifm_media);
+
/* Init circular RX list. */
if (pn_list_rx_init(sc) == ENOBUFS) {
printf("pn%d: initialization failed: no "
@@ -1825,10 +2039,17 @@ static int pn_ifmedia_upd(ifp)
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
return(EINVAL);
- if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
- pn_autoneg_mii(sc, PN_FLAG_SCHEDDELAY, 1);
- else
- pn_setmode_mii(sc, ifm->ifm_media);
+ if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
+ if (sc->pn_pinfo == NULL)
+ pn_autoneg(sc, PN_FLAG_SCHEDDELAY, 1);
+ else
+ pn_autoneg_mii(sc, PN_FLAG_SCHEDDELAY, 1);
+ } else {
+ if (sc->pn_pinfo == NULL)
+ pn_setmode(sc, ifm->ifm_media);
+ else
+ pn_setmode_mii(sc, ifm->ifm_media);
+ }
return(0);
}
@@ -1934,7 +2155,10 @@ static void pn_watchdog(ifp)
sc = ifp->if_softc;
if (sc->pn_autoneg) {
- pn_autoneg_mii(sc, PN_FLAG_DELAYTIMEO, 1);
+ if (sc->pn_pinfo == NULL)
+ pn_autoneg(sc, PN_FLAG_DELAYTIMEO, 1);
+ else
+ pn_autoneg_mii(sc, PN_FLAG_DELAYTIMEO, 1);
return;
}
diff --git a/sys/pci/if_pnreg.h b/sys/pci/if_pnreg.h
index f97e044..1e901b9 100644
--- a/sys/pci/if_pnreg.h
+++ b/sys/pci/if_pnreg.h
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_pnreg.h,v 1.21 1999/03/27 20:08:53 wpaul Exp $
+ * $Id: if_pnreg.h,v 1.23 1999/04/10 18:22:22 wpaul Exp $
*/
/*
@@ -53,7 +53,6 @@
#define PN_MII 0xA0 /* MII access register */
#define PN_NWAY 0xB8 /* Internal NWAY register */
-
/*
* Bus control bits.
*/
@@ -71,6 +70,7 @@
#define PN_SKIPLEN_4LONG 0x00000020
#define PN_SKIPLEN_5LONG 0x00000040
+#define PN_CACHEALIGN_NONE 0x00000000
#define PN_CACHEALIGN_8LONG 0x00004000
#define PN_CACHEALIGN_16LONG 0x00008000
#define PN_CACHEALIGN_32LONG 0x0000C000
@@ -109,6 +109,7 @@
#define PN_ISR_RX_IDLE 0x00000100 /* rx stopped */
#define PN_ISR_RX_WATCHDOG 0x00000200 /* rx watchdog timeo */
#define PN_ISR_TX_EARLY 0x00000400 /* rx watchdog timeo */
+#define PN_ISR_LINKFAIL 0x00001000
#define PN_ISR_BUS_ERR 0x00002000
#define PN_ISR_ABNORMAL 0x00008000
#define PN_ISR_NORMAL 0x00010000
@@ -253,7 +254,7 @@
#define PN_NWAY_TP 0x00000040 /* 1 == tp, 0 == AUI */
#define PN_NWAY_AUIVOLT 0x00000080 /* 1 == full, 0 == half */
#define PN_NWAY_DUPLEX 0x00000100 /* 1 == full, 0 == half */
-#define PN_NWAY_LINKTEST 0x00000200 /* 1 == on, 0 == off */
+#define PN_NWAY_LINKTEST 0x00000200 /* 0 == on, 1 == off */
#define PN_NWAY_AUTODETECT 0x00000400 /* 1 == off, 0 == on */
#define PN_NWAY_SPEEDSEL 0x00000800 /* 0 == 10, 1 == 100 */
#define PN_NWAY_NWAY_ENB 0x00001000 /* 0 == off, 1 == on */
@@ -271,6 +272,46 @@
#define PN_NWAY_LPAR100T4 0x80000000
/*
+ * Nway register bits that must be set to turn on to initiate
+ * an autoneg session with all modes advertized and AUI disabled.
+ */
+#define PN_NWAY_AUTOENB \
+ (PN_NWAY_AUILOWCUR|PN_NWAY_TPEXTEND|PN_NWAY_POLARITY|PN_NWAY_TP \
+ |PN_NWAY_NWAY_ENB|PN_NWAY_CAP10HALF|PN_NWAY_CAP10FULL| \
+ PN_NWAY_CAP100FULL|PN_NWAY_CAP100HALF|PN_NWAY_CAP100T4| \
+ PN_NWAY_AUTONEGRSTR)
+
+#define PN_NWAY_MODE_10HD \
+ (PN_NWAY_CAP10HALF|PN_NWAY_CAP10FULL| \
+ PN_NWAY_CAP100FULL|PN_NWAY_CAP100HALF|PN_NWAY_CAP100T4| \
+ PN_NWAY_AUILOWCUR|PN_NWAY_TPEXTEND|PN_NWAY_POLARITY| \
+ PN_NWAY_TP)
+
+#define PN_NWAY_MODE_10FD \
+ (PN_NWAY_CAP10HALF|PN_NWAY_CAP10FULL| \
+ PN_NWAY_CAP100FULL|PN_NWAY_CAP100HALF|PN_NWAY_CAP100T4| \
+ PN_NWAY_AUILOWCUR|PN_NWAY_TPEXTEND|PN_NWAY_POLARITY| \
+ PN_NWAY_TP|PN_NWAY_DUPLEX)
+
+#define PN_NWAY_MODE_100HD \
+ (PN_NWAY_CAP10HALF|PN_NWAY_CAP10FULL| \
+ PN_NWAY_CAP100FULL|PN_NWAY_CAP100HALF|PN_NWAY_CAP100T4| \
+ PN_NWAY_AUILOWCUR|PN_NWAY_TPEXTEND|PN_NWAY_POLARITY| \
+ PN_NWAY_TP|PN_NWAY_SPEEDSEL)
+
+#define PN_NWAY_MODE_100FD \
+ (PN_NWAY_CAP10HALF|PN_NWAY_CAP10FULL| \
+ PN_NWAY_CAP100FULL|PN_NWAY_CAP100HALF|PN_NWAY_CAP100T4| \
+ PN_NWAY_AUILOWCUR|PN_NWAY_TPEXTEND|PN_NWAY_POLARITY| \
+ PN_NWAY_TP|PN_NWAY_SPEEDSEL|PN_NWAY_DUPLEX)
+
+#define PN_NWAY_MODE_100T4 PN_NWAY_MODE_100HD
+
+#define PN_NWAY_LPAR \
+ (PN_NWAY_LPAR10HALF|PN_NWAY_LPAR10FULL|PN_NWAY_LPAR100HALF| \
+ PN_NWAY_LPAR100FULL|PN_NWAY_LPAR100T4)
+
+/*
* Size of a setup frame.
*/
#define PN_SFRAME_LEN 192
@@ -443,6 +484,7 @@ struct pn_softc {
#define PN_169_REV 32
#define PN_169B_REV 33
u_int8_t pn_promisc_war;
+ u_int8_t pn_cachesize;
struct pn_chain_onefrag *pn_promisc_bug_save;
unsigned char *pn_promisc_buf;
#endif
@@ -483,6 +525,15 @@ struct pn_softc {
#define PN_DEVICEID_PNIC_II 0xc115
/*
+ * The 82c168 chip has the same PCI vendor/device ID as the
+ * 82c169, but a different revision. Assume that any revision
+ * between 0x10 an 0x1F is an 82c168.
+ */
+#define PN_REVMASK 0xF0
+#define PN_REVID_82C168 0x10
+#define PN_REVID_82C169 0x20
+
+/*
* Texas Instruments PHY identifiers
*/
#define TI_PHY_VENDORID 0x4000
@@ -525,6 +576,7 @@ struct pn_softc {
#define PN_PCI_STATUS 0x06
#define PN_PCI_REVISION 0x08
#define PN_PCI_CLASSCODE 0x09
+#define PN_PCI_CACHELEN 0x0C
#define PN_PCI_LATENCY_TIMER 0x0D
#define PN_PCI_HEADER_TYPE 0x0E
#define PN_PCI_LOIO 0x10
OpenPOWER on IntegriCloud