* Network driver for DEC/21143 and K° ("dc") ported from FreeBSD 8.2;

* Network drivers for 3com, ipro100, rtl8139 are updated from FreeBSD 8.2 Release branch;
* Some functions, defines and typedef required by updated and fresh ported FreeBSD
  drivers were added into freebsd_compat layer.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42393 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Siarzhuk Zharski
2011-07-08 23:00:38 +00:00
parent eb5c4b0745
commit 698b6790bc
44 changed files with 9831 additions and 1936 deletions
+1 -1
View File
@@ -169,7 +169,7 @@ SYSTEM_ADD_ONS_DRIVERS_GRAPHICS = $(X86_ONLY)radeon $(X86_ONLY)nvidia
SYSTEM_ADD_ONS_DRIVERS_MIDI = emuxki usb_midi ; SYSTEM_ADD_ONS_DRIVERS_MIDI = emuxki usb_midi ;
SYSTEM_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com $(X86_ONLY)atheros813x SYSTEM_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com $(X86_ONLY)atheros813x
$(X86_ONLY)ar81xx $(X86_ONLY)attansic_l1 $(X86_ONLY)attansic_l2 $(X86_ONLY)ar81xx $(X86_ONLY)attansic_l1 $(X86_ONLY)attansic_l2
$(X86_ONLY)broadcom440x $(X86_ONLY)broadcom570x etherpci $(X86_ONLY)broadcom440x $(X86_ONLY)broadcom570x $(X86_ONLY)dec21xxx etherpci
$(X86_ONLY)ipro100 $(X86_ONLY)ipro1000 $(X86_ONLY)jmicron2x0 $(X86_ONLY)ipro100 $(X86_ONLY)ipro1000 $(X86_ONLY)jmicron2x0
$(X86_ONLY)marvell_yukon $(X86_ONLY)nforce $(X86_ONLY)pcnet pegasus $(X86_ONLY)marvell_yukon $(X86_ONLY)nforce $(X86_ONLY)pcnet pegasus
$(X86_ONLY)rtl8139 $(X86_ONLY)rtl81xx sis900 $(X86_ONLY)rtl8139 $(X86_ONLY)rtl81xx sis900
@@ -1,4 +1,3 @@
SubDir HAIKU_TOP src add-ons kernel drivers network 3com ; SubDir HAIKU_TOP src add-ons kernel drivers network 3com ;
SubInclude HAIKU_TOP src add-ons kernel drivers network 3com dev ; SubInclude HAIKU_TOP src add-ons kernel drivers network 3com dev ;
SubInclude HAIKU_TOP src add-ons kernel drivers network 3com pci ;
@@ -1,3 +1,4 @@
SubDir HAIKU_TOP src add-ons kernel drivers network 3com dev ; SubDir HAIKU_TOP src add-ons kernel drivers network 3com dev ;
SubInclude HAIKU_TOP src add-ons kernel drivers network 3com dev mii ; SubInclude HAIKU_TOP src add-ons kernel drivers network 3com dev mii ;
SubInclude HAIKU_TOP src add-ons kernel drivers network 3com dev xl ;
@@ -14,13 +14,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -46,11 +39,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -68,7 +56,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/bmtphy.c,v 1.9.2.1 2006/08/08 04:37:18 yongari Exp $"); __FBSDID("$FreeBSD: src/sys/dev/mii/bmtphy.c,v 1.12.10.8.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* Driver for the Broadcom BCM5201/BCM5202 "Mini-Theta" PHYs. This also * Driver for the Broadcom BCM5201/BCM5202 "Mini-Theta" PHYs. This also
@@ -97,6 +85,11 @@ __FBSDID("$FreeBSD: src/sys/dev/mii/bmtphy.c,v 1.9.2.1 2006/08/08 04:37:18 yonga
static int bmtphy_probe(device_t); static int bmtphy_probe(device_t);
static int bmtphy_attach(device_t); static int bmtphy_attach(device_t);
struct bmtphy_softc {
struct mii_softc mii_sc;
int mii_model;
};
static device_method_t bmtphy_methods[] = { static device_method_t bmtphy_methods[] = {
/* Device interface */ /* Device interface */
DEVMETHOD(device_probe, bmtphy_probe), DEVMETHOD(device_probe, bmtphy_probe),
@@ -112,81 +105,73 @@ static devclass_t bmtphy_devclass;
static driver_t bmtphy_driver = { static driver_t bmtphy_driver = {
"bmtphy", "bmtphy",
bmtphy_methods, bmtphy_methods,
sizeof(struct mii_softc) sizeof(struct bmtphy_softc)
}; };
DRIVER_MODULE(bmtphy, miibus, bmtphy_driver, bmtphy_devclass, 0, 0); DRIVER_MODULE(bmtphy, miibus, bmtphy_driver, bmtphy_devclass, 0, 0);
static int bmtphy_service(struct mii_softc *, struct mii_data *, int); static int bmtphy_service(struct mii_softc *, struct mii_data *, int);
static void bmtphy_status(struct mii_softc *); static void bmtphy_status(struct mii_softc *);
static void bmtphy_reset(struct mii_softc *);
static const struct mii_phydesc bmtphys_dp[] = {
MII_PHY_DESC(BROADCOM, BCM4401),
MII_PHY_DESC(BROADCOM, BCM5201),
MII_PHY_DESC(BROADCOM, BCM5214),
MII_PHY_DESC(BROADCOM, BCM5221),
MII_PHY_DESC(BROADCOM, BCM5222),
MII_PHY_END
};
static const struct mii_phydesc bmtphys_lp[] = {
MII_PHY_DESC(BROADCOM, 3C905B),
MII_PHY_DESC(BROADCOM, 3C905C),
MII_PHY_END
};
static int static int
bmtphy_probe(device_t dev) bmtphy_probe(device_t dev)
{ {
struct mii_attach_args *ma;
int rval; int rval;
ma = device_get_ivars(dev); /* Let exphy(4) take precedence for these. */
rval = BUS_PROBE_DEFAULT; rval = mii_phy_dev_probe(dev, bmtphys_lp, BUS_PROBE_LOW_PRIORITY);
if (rval <= 0)
if (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_BROADCOM)
return (ENXIO);
switch (MII_MODEL(ma->mii_id2)) {
case MII_MODEL_BROADCOM_3C905B:
device_set_desc(dev, MII_STR_BROADCOM_3C905B);
rval = BUS_PROBE_LOW_PRIORITY; /* Let exphy take precedence. */
break;
case MII_MODEL_BROADCOM_3C905C:
device_set_desc(dev, MII_STR_BROADCOM_3C905C);
rval = BUS_PROBE_LOW_PRIORITY; /* Let exphy take precedence. */
break;
case MII_MODEL_BROADCOM_BCM5201:
device_set_desc(dev, MII_STR_BROADCOM_BCM5201);
break;
case MII_MODEL_BROADCOM_BCM5221:
device_set_desc(dev, MII_STR_BROADCOM_BCM5221);
break;
case MII_MODEL_BROADCOM_BCM4401:
device_set_desc(dev, MII_STR_BROADCOM_BCM4401);
break;
default:
return (ENXIO);
}
return (rval); return (rval);
return (mii_phy_dev_probe(dev, bmtphys_dp, BUS_PROBE_DEFAULT));
} }
static int static int
bmtphy_attach(device_t dev) bmtphy_attach(device_t dev)
{ {
struct bmtphy_softc *bsc;
struct mii_softc *sc; struct mii_softc *sc;
struct mii_attach_args *ma; struct mii_attach_args *ma;
struct mii_data *mii; struct mii_data *mii;
sc = device_get_softc(dev); bsc = device_get_softc(dev);
sc = &bsc->mii_sc;
ma = device_get_ivars(dev); ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev); sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev); mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_inst = mii->mii_instance; sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno; sc->mii_phy = ma->mii_phyno;
sc->mii_service = bmtphy_service; sc->mii_service = bmtphy_service;
sc->mii_pdata = mii; sc->mii_pdata = mii;
mii_phy_reset(sc); sc->mii_flags |= MIIF_NOMANPAUSE;
mii->mii_instance++; bsc->mii_model = MII_MODEL(ma->mii_id2);
sc->mii_capabilities = bmtphy_reset(sc);
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " "); device_printf(dev, " ");
if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
printf("no media present");
else
mii_phy_add_media(sc); mii_phy_add_media(sc);
printf("\n"); printf("\n");
MIIBUS_MEDIAINIT(sc->mii_dev); MIIBUS_MEDIAINIT(sc->mii_dev);
@@ -197,31 +182,12 @@ bmtphy_attach(device_t dev)
static int static int
bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{ {
struct ifmedia_entry *ife;
int reg;
ife = mii->mii_media.ifm_cur;
switch (cmd) { switch (cmd) {
case MII_POLLSTAT: case MII_POLLSTAT:
/*
* If we're not polling our PHY instance, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break; break;
case MII_MEDIACHG: case MII_MEDIACHG:
/*
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, MII_BMCR);
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
/* /*
* If the interface is not up, don't do anything. * If the interface is not up, don't do anything.
*/ */
@@ -232,11 +198,6 @@ bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break; break;
case MII_TICK: case MII_TICK:
/*
* If we're not currently selected, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
if (mii_phy_tick(sc) == EJUSTRETURN) if (mii_phy_tick(sc) == EJUSTRETURN)
return (0); return (0);
break; break;
@@ -247,7 +208,6 @@ bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
/* Callback if something changed. */ /* Callback if something changed. */
mii_phy_update(sc, cmd); mii_phy_update(sc, cmd);
return (0); return (0);
} }
@@ -265,7 +225,6 @@ bmtphy_status(struct mii_softc *sc)
mii->mii_media_active = IFM_ETHER; mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
if (bmsr & BMSR_LINK) if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE; mii->mii_media_status |= IFM_ACTIVE;
@@ -291,12 +250,45 @@ bmtphy_status(struct mii_softc *sc)
return; return;
} }
aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
if (aux_csr & AUX_CSR_SPEED) if (aux_csr & AUX_CSR_SPEED)
mii->mii_media_active |= IFM_100_TX; mii->mii_media_active |= IFM_100_TX;
else else
mii->mii_media_active |= IFM_10_T; mii->mii_media_active |= IFM_10_T;
if (aux_csr & AUX_CSR_FDX) if (aux_csr & AUX_CSR_FDX)
mii->mii_media_active |= IFM_FDX; mii->mii_media_active |=
IFM_FDX | mii_phy_flowstatus(sc);
else
mii->mii_media_active |= IFM_HDX;
} else } else
mii->mii_media_active = ife->ifm_media; mii->mii_media_active = ife->ifm_media;
} }
static void
bmtphy_reset(struct mii_softc *sc)
{
struct bmtphy_softc *bsc;
u_int16_t data;
bsc = (struct bmtphy_softc *)sc;
mii_phy_reset(sc);
if (bsc->mii_model == MII_MODEL_BROADCOM_BCM5221) {
/* Enable shadow register mode. */
data = PHY_READ(sc, 0x1f);
PHY_WRITE(sc, 0x1f, data | 0x0080);
/* Enable APD (Auto PowerDetect). */
data = PHY_READ(sc, MII_BMTPHY_AUX2);
PHY_WRITE(sc, MII_BMTPHY_AUX2, data | 0x0020);
/* Enable clocks across APD for Auto-MDIX functionality. */
data = PHY_READ(sc, MII_BMTPHY_INTR);
PHY_WRITE(sc, MII_BMTPHY_INTR, data | 0x0004);
/* Disable shadow register mode. */
data = PHY_READ(sc, 0x1f);
PHY_WRITE(sc, 0x1f, data & ~0x0080);
}
}
@@ -13,13 +13,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -35,7 +28,7 @@
* *
* from NetBSD: bmtphyreg.h,v 1.1 2001/06/02 21:42:10 thorpej Exp * from NetBSD: bmtphyreg.h,v 1.1 2001/06/02 21:42:10 thorpej Exp
* *
* $FreeBSD: src/sys/dev/mii/bmtphyreg.h,v 1.2 2005/01/06 01:42:55 imp Exp $ * $FreeBSD: src/sys/dev/mii/bmtphyreg.h,v 1.2.22.2.2.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
#ifndef _DEV_MII_BMTPHYREG_H_ #ifndef _DEV_MII_BMTPHYREG_H_
@@ -16,13 +16,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -48,11 +41,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -67,7 +55,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/exphy.c,v 1.19.2.1 2006/08/08 04:37:18 yongari Exp $"); __FBSDID("$FreeBSD: src/sys/dev/mii/exphy.c,v 1.23.10.5.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* driver for 3Com internal PHYs * driver for 3Com internal PHYs
@@ -114,42 +102,31 @@ DRIVER_MODULE(xlphy, miibus, exphy_driver, exphy_devclass, 0, 0);
static int exphy_service(struct mii_softc *, struct mii_data *, int); static int exphy_service(struct mii_softc *, struct mii_data *, int);
static void exphy_reset(struct mii_softc *); static void exphy_reset(struct mii_softc *);
/*
* Some 3Com internal PHYs report zero for OUI and model, others use
* actual values.
* Note that the 3Com internal PHYs having OUI 0x105a and model 0 are
* handled fine by ukphy(4); they can be isolated and don't require
* special treatment after reset.
*/
static const struct mii_phydesc exphys[] = {
{ 0, 0, "3Com internal media interface" },
MII_PHY_DESC(BROADCOM, 3C905C),
MII_PHY_END
};
static int static int
exphy_probe(dev) exphy_probe(device_t dev)
device_t dev;
{ {
struct mii_attach_args *ma;
device_t parent;
ma = device_get_ivars(dev); if (strcmp(device_get_name(device_get_parent(device_get_parent(dev))),
parent = device_get_parent(device_get_parent(dev)); "xl") == 0)
return (mii_phy_dev_probe(dev, exphys, BUS_PROBE_DEFAULT));
/*
* Argh, 3Com PHY reports oui == 0 model == 0!
*/
if ((MII_OUI(ma->mii_id1, ma->mii_id2) != 0 ||
MII_MODEL(ma->mii_id2) != 0) &&
(MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_BROADCOM ||
MII_MODEL(ma->mii_id2) != MII_MODEL_BROADCOM_3C905C))
return (ENXIO); return (ENXIO);
/*
* Make sure the parent is an `ex'.
*/
if (strcmp(device_get_name(parent), "xl") != 0)
return (ENXIO);
if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0)
device_set_desc(dev, "3Com internal media interface");
else
device_set_desc(dev, MII_STR_BROADCOM_3C905C);
return (BUS_PROBE_DEFAULT);
} }
static int static int
exphy_attach(dev) exphy_attach(device_t dev)
device_t dev;
{ {
struct mii_softc *sc; struct mii_softc *sc;
struct mii_attach_args *ma; struct mii_attach_args *ma;
@@ -158,41 +135,28 @@ exphy_attach(dev)
sc = device_get_softc(dev); sc = device_get_softc(dev);
ma = device_get_ivars(dev); ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev); sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev); mii = ma->mii_data;
/*
* The 3Com PHY can never be isolated, so never allow non-zero
* instances!
*/
if (mii->mii_instance != 0) {
device_printf(dev, "ignoring this PHY, non-zero instance\n");
return(ENXIO);
}
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_inst = mii->mii_instance; sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno; sc->mii_phy = ma->mii_phyno;
sc->mii_service = exphy_service; sc->mii_service = exphy_service;
sc->mii_pdata = mii; sc->mii_pdata = mii;
mii->mii_instance++;
/*
* The 3Com PHY can never be isolated.
*/
sc->mii_flags |= MIIF_NOISOLATE; sc->mii_flags |= MIIF_NOISOLATE;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
#if 0 /* See above. */
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
#endif
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100); MII_MEDIA_100_TX);
exphy_reset(sc); exphy_reset(sc);
sc->mii_capabilities = sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " "); device_printf(dev, " ");
mii_phy_add_media(sc); mii_phy_add_media(sc);
printf("\n"); printf("\n");
@@ -202,18 +166,8 @@ exphy_attach(dev)
} }
static int static int
exphy_service(sc, mii, cmd) exphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
struct mii_softc *sc;
struct mii_data *mii;
int cmd;
{ {
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
/*
* We can't isolate the 3Com PHY, so it has to be the only one!
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
panic("exphy_service: can't isolate 3Com PHY");
switch (cmd) { switch (cmd) {
case MII_POLLSTAT: case MII_POLLSTAT:
@@ -236,12 +190,6 @@ exphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0) if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0); return (0);
/*
* Only used for autonegotiation.
*/
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
break;
/* /*
* The 3Com PHY's autonegotiation doesn't need to be * The 3Com PHY's autonegotiation doesn't need to be
* kicked; it continues in the background. * kicked; it continues in the background.
@@ -16,13 +16,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -48,11 +41,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -67,7 +55,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.20 2007/01/20 00:52:29 marius Exp $"); __FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.20.10.6.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* driver for generic unknown PHYs * driver for generic unknown PHYs
@@ -134,7 +122,7 @@ ukphy_attach(device_t dev)
sc = device_get_softc(dev); sc = device_get_softc(dev);
ma = device_get_ivars(dev); ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev); sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev); mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
if (bootverbose) if (bootverbose)
@@ -142,17 +130,17 @@ ukphy_attach(device_t dev)
MII_OUI(ma->mii_id1, ma->mii_id2), MII_OUI(ma->mii_id1, ma->mii_id2),
MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2)); MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2));
sc->mii_inst = mii->mii_instance; sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno; sc->mii_phy = ma->mii_phyno;
sc->mii_service = ukphy_service; sc->mii_service = ukphy_service;
sc->mii_pdata = mii; sc->mii_pdata = mii;
mii->mii_instance++; sc->mii_flags |= MIIF_NOMANPAUSE;
mii_phy_reset(sc); mii_phy_reset(sc);
sc->mii_capabilities = sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_EXTSTAT) if (sc->mii_capabilities & BMSR_EXTSTAT)
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
device_printf(dev, " "); device_printf(dev, " ");
@@ -168,29 +156,12 @@ ukphy_attach(device_t dev)
static int static int
ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{ {
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) { switch (cmd) {
case MII_POLLSTAT: case MII_POLLSTAT:
/*
* If we're not polling our PHY instance, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break; break;
case MII_MEDIACHG: case MII_MEDIACHG:
/*
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, MII_BMCR);
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
/* /*
* If the interface is not up, don't do anything. * If the interface is not up, don't do anything.
*/ */
@@ -201,11 +172,6 @@ ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break; break;
case MII_TICK: case MII_TICK:
/*
* If we're not currently selected, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
if (mii_phy_tick(sc) == EJUSTRETURN) if (mii_phy_tick(sc) == EJUSTRETURN)
return (0); return (0);
break; break;
@@ -16,13 +16,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -38,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy_subr.c,v 1.8.8.1 2006/07/19 04:40:26 yongari Exp $"); __FBSDID("$FreeBSD: src/sys/dev/mii/ukphy_subr.c,v 1.10.2.4.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* Subroutines shared by the ukphy driver and other PHY drivers. * Subroutines shared by the ukphy driver and other PHY drivers.
@@ -111,19 +104,26 @@ ukphy_status(struct mii_softc *phy)
mii->mii_media_active |= IFM_1000_T|IFM_FDX; mii->mii_media_active |= IFM_1000_T|IFM_FDX;
else if ((gtcr & GTCR_ADV_1000THDX) && else if ((gtcr & GTCR_ADV_1000THDX) &&
(gtsr & GTSR_LP_1000THDX)) (gtsr & GTSR_LP_1000THDX))
mii->mii_media_active |= IFM_1000_T; mii->mii_media_active |= IFM_1000_T|IFM_HDX;
else if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD) else if (anlpar & ANLPAR_TX_FD)
mii->mii_media_active |= IFM_100_TX|IFM_FDX; mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4|IFM_HDX;
else if (anlpar & ANLPAR_TX) else if (anlpar & ANLPAR_TX)
mii->mii_media_active |= IFM_100_TX; mii->mii_media_active |= IFM_100_TX|IFM_HDX;
else if (anlpar & ANLPAR_10_FD) else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T|IFM_FDX; mii->mii_media_active |= IFM_10_T|IFM_FDX;
else if (anlpar & ANLPAR_10) else if (anlpar & ANLPAR_10)
mii->mii_media_active |= IFM_10_T; mii->mii_media_active |= IFM_10_T|IFM_HDX;
else else
mii->mii_media_active |= IFM_NONE; mii->mii_media_active |= IFM_NONE;
if ((mii->mii_media_active & IFM_1000_T) != 0 &&
(gtsr & GTSR_MS_RES) != 0)
mii->mii_media_active |= IFM_ETH_MASTER;
if ((mii->mii_media_active & IFM_FDX) != 0)
mii->mii_media_active |= mii_phy_flowstatus(phy);
} else } else
mii->mii_media_active = ife->ifm_media; mii->mii_media_active = ife->ifm_media;
} }
@@ -1,6 +1,6 @@
SubDir HAIKU_TOP src add-ons kernel drivers network 3com pci ; SubDir HAIKU_TOP src add-ons kernel drivers network 3com dev xl ;
UseHeaders [ FDirName $(SUBDIR) .. ] : true ; UseHeaders [ FDirName $(SUBDIR) .. .. ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ; UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
UsePrivateHeaders net system ; UsePrivateHeaders net system ;
@@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/pci/if_xl.c,v 1.210 2007/08/06 14:26:03 rwatson Exp $"); __FBSDID("$FreeBSD: src/sys/dev/xl/if_xl.c,v 1.8.2.7.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* 3Com 3c90x Etherlink XL PCI NIC driver * 3Com 3c90x Etherlink XL PCI NIC driver
@@ -96,9 +96,6 @@ __FBSDID("$FreeBSD: src/sys/pci/if_xl.c,v 1.210 2007/08/06 14:26:03 rwatson Exp
* Since using bus master DMA is a big win, we use this driver to * Since using bus master DMA is a big win, we use this driver to
* support the PCI "boomerang" chips even though they work with the * support the PCI "boomerang" chips even though they work with the
* "vortex" driver in order to obtain better performance. * "vortex" driver in order to obtain better performance.
*
* This driver is in the /sys/pci directory because it only supports
* PCI-based NICs.
*/ */
#ifdef HAVE_KERNEL_OPTION_HEADERS #ifdef HAVE_KERNEL_OPTION_HEADERS
@@ -142,7 +139,7 @@ MODULE_DEPEND(xl, miibus, 1, 1, 1);
/* "device miibus" required. See GENERIC if you get errors here. */ /* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h" #include "miibus_if.h"
#include <pci/if_xlreg.h> #include <dev/xl/if_xlreg.h>
/* /*
* TX Checksumming is disabled by default for two reasons: * TX Checksumming is disabled by default for two reasons:
@@ -163,7 +160,7 @@ MODULE_DEPEND(xl, miibus, 1, 1, 1);
/* /*
* Various supported device vendors/types and their names. * Various supported device vendors/types and their names.
*/ */
static struct xl_type xl_devs[] = { static const struct xl_type xl_devs[] = {
{ TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT, { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT,
"3Com 3c900-TPO Etherlink XL" }, "3Com 3c900-TPO Etherlink XL" },
{ TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT_COMBO, { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT_COMBO,
@@ -230,8 +227,8 @@ static int xl_detach(device_t);
static int xl_newbuf(struct xl_softc *, struct xl_chain_onefrag *); static int xl_newbuf(struct xl_softc *, struct xl_chain_onefrag *);
static void xl_stats_update(void *); static void xl_stats_update(void *);
static void xl_stats_update_locked(struct xl_softc *); static void xl_stats_update_locked(struct xl_softc *);
static int xl_encap(struct xl_softc *, struct xl_chain *, struct mbuf *); static int xl_encap(struct xl_softc *, struct xl_chain *, struct mbuf **);
static void xl_rxeof(struct xl_softc *); static int xl_rxeof(struct xl_softc *);
static void xl_rxeof_task(void *, int); static void xl_rxeof_task(void *, int);
static int xl_rx_resync(struct xl_softc *); static int xl_rx_resync(struct xl_softc *);
static void xl_txeof(struct xl_softc *); static void xl_txeof(struct xl_softc *);
@@ -246,13 +243,14 @@ static void xl_init(void *);
static void xl_init_locked(struct xl_softc *); static void xl_init_locked(struct xl_softc *);
static void xl_stop(struct xl_softc *); static void xl_stop(struct xl_softc *);
static int xl_watchdog(struct xl_softc *); static int xl_watchdog(struct xl_softc *);
static void xl_shutdown(device_t); static int xl_shutdown(device_t);
static int xl_suspend(device_t); static int xl_suspend(device_t);
static int xl_resume(device_t); static int xl_resume(device_t);
static void xl_setwol(struct xl_softc *);
#ifdef DEVICE_POLLING #ifdef DEVICE_POLLING
static void xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count); static int xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
static void xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count); static int xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif #endif
static int xl_ifmedia_upd(struct ifnet *); static int xl_ifmedia_upd(struct ifnet *);
@@ -278,8 +276,6 @@ static void xl_mediacheck(struct xl_softc *);
static void xl_choose_media(struct xl_softc *sc, int *media); static void xl_choose_media(struct xl_softc *sc, int *media);
static void xl_choose_xcvr(struct xl_softc *, int); static void xl_choose_xcvr(struct xl_softc *, int);
static void xl_dma_map_addr(void *, bus_dma_segment_t *, int, int); static void xl_dma_map_addr(void *, bus_dma_segment_t *, int, int);
static void xl_dma_map_rxbuf(void *, bus_dma_segment_t *, int, bus_size_t, int);
static void xl_dma_map_txbuf(void *, bus_dma_segment_t *, int, bus_size_t, int);
#ifdef notdef #ifdef notdef
static void xl_testpacket(struct xl_softc *); static void xl_testpacket(struct xl_softc *);
#endif #endif
@@ -319,7 +315,6 @@ static driver_t xl_driver = {
static devclass_t xl_devclass; static devclass_t xl_devclass;
DRIVER_MODULE(xl, cardbus, xl_driver, xl_devclass, 0, 0);
DRIVER_MODULE(xl, pci, xl_driver, xl_devclass, 0, 0); DRIVER_MODULE(xl, pci, xl_driver, xl_devclass, 0, 0);
DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, 0, 0); DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, 0, 0);
@@ -332,46 +327,6 @@ xl_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
*paddr = segs->ds_addr; *paddr = segs->ds_addr;
} }
static void
xl_dma_map_rxbuf(void *arg, bus_dma_segment_t *segs, int nseg,
bus_size_t mapsize, int error)
{
u_int32_t *paddr;
if (error)
return;
KASSERT(nseg == 1, ("xl_dma_map_rxbuf: too many DMA segments"));
paddr = arg;
*paddr = segs->ds_addr;
}
static void
xl_dma_map_txbuf(void *arg, bus_dma_segment_t *segs, int nseg,
bus_size_t mapsize, int error)
{
struct xl_list *l;
int i, total_len;
if (error)
return;
KASSERT(nseg <= XL_MAXFRAGS, ("too many DMA segments"));
total_len = 0;
l = arg;
for (i = 0; i < nseg; i++) {
KASSERT(segs[i].ds_len <= MCLBYTES, ("segment size too large"));
l->xl_frag[i].xl_addr = htole32(segs[i].ds_addr);
l->xl_frag[i].xl_len = htole32(segs[i].ds_len);
total_len += segs[i].ds_len;
}
l->xl_frag[nseg - 1].xl_len = htole32(segs[nseg - 1].ds_len |
XL_LAST_FRAG);
l->xl_status = htole32(total_len);
l->xl_next = 0;
}
/* /*
* Murphy's law says that it's possible the chip can wedge and * Murphy's law says that it's possible the chip can wedge and
* the 'command in progress' bit may never clear. Hence, we wait * the 'command in progress' bit may never clear. Hence, we wait
@@ -568,16 +523,6 @@ xl_miibus_readreg(device_t dev, int phy, int reg)
sc = device_get_softc(dev); sc = device_get_softc(dev);
/*
* Pretend that PHYs are only available at MII address 24.
* This is to guard against problems with certain 3Com ASIC
* revisions that incorrectly map the internal transceiver
* control registers at all MII addresses. This can cause
* the miibus code to attach the same PHY several times over.
*/
if ((sc->xl_flags & XL_FLAG_PHYOK) == 0 && phy != 24)
return (0);
bzero((char *)&frame, sizeof(frame)); bzero((char *)&frame, sizeof(frame));
frame.mii_phyaddr = phy; frame.mii_phyaddr = phy;
frame.mii_regaddr = reg; frame.mii_regaddr = reg;
@@ -595,9 +540,6 @@ xl_miibus_writereg(device_t dev, int phy, int reg, int data)
sc = device_get_softc(dev); sc = device_get_softc(dev);
if ((sc->xl_flags & XL_FLAG_PHYOK) == 0 && phy != 24)
return (0);
bzero((char *)&frame, sizeof(frame)); bzero((char *)&frame, sizeof(frame));
frame.mii_phyaddr = phy; frame.mii_phyaddr = phy;
frame.mii_regaddr = reg; frame.mii_regaddr = reg;
@@ -613,6 +555,7 @@ xl_miibus_statchg(device_t dev)
{ {
struct xl_softc *sc; struct xl_softc *sc;
struct mii_data *mii; struct mii_data *mii;
uint8_t macctl;
sc = device_get_softc(dev); sc = device_get_softc(dev);
mii = device_get_softc(sc->xl_miibus); mii = device_get_softc(sc->xl_miibus);
@@ -621,11 +564,22 @@ xl_miibus_statchg(device_t dev)
/* Set ASIC's duplex mode to match the PHY. */ /* Set ASIC's duplex mode to match the PHY. */
XL_SEL_WIN(3); XL_SEL_WIN(3);
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) macctl = CSR_READ_1(sc, XL_W3_MAC_CTRL);
CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX); if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
macctl |= XL_MACCTRL_DUPLEX;
if (sc->xl_type == XL_TYPE_905B) {
if ((IFM_OPTIONS(mii->mii_media_active) &
IFM_ETH_RXPAUSE) != 0)
macctl |= XL_MACCTRL_FLOW_CONTROL_ENB;
else else
CSR_WRITE_1(sc, XL_W3_MAC_CTRL, macctl &= ~XL_MACCTRL_FLOW_CONTROL_ENB;
(CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX)); }
} else {
macctl &= ~XL_MACCTRL_DUPLEX;
if (sc->xl_type == XL_TYPE_905B)
macctl &= ~XL_MACCTRL_FLOW_CONTROL_ENB;
}
CSR_WRITE_1(sc, XL_W3_MAC_CTRL, macctl);
} }
/* /*
@@ -770,10 +724,10 @@ xl_setmulti(struct xl_softc *sc)
return; return;
} }
IF_ADDR_LOCK(ifp); if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
mcnt++; mcnt++;
IF_ADDR_UNLOCK(ifp); if_maddr_runlock(ifp);
if (mcnt) if (mcnt)
rxfilt |= XL_RXFILTER_ALLMULTI; rxfilt |= XL_RXFILTER_ALLMULTI;
@@ -812,7 +766,7 @@ xl_setmulti_hash(struct xl_softc *sc)
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i);
/* now program new ones */ /* now program new ones */
IF_ADDR_LOCK(ifp); if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK) if (ifma->ifma_addr->sa_family != AF_LINK)
continue; continue;
@@ -834,7 +788,7 @@ xl_setmulti_hash(struct xl_softc *sc)
h | XL_CMD_RX_SET_HASH | XL_HASH_SET); h | XL_CMD_RX_SET_HASH | XL_HASH_SET);
mcnt++; mcnt++;
} }
IF_ADDR_UNLOCK(ifp); if_maddr_runlock(ifp);
if (mcnt) if (mcnt)
rxfilt |= XL_RXFILTER_MULTIHASH; rxfilt |= XL_RXFILTER_MULTIHASH;
@@ -844,32 +798,6 @@ xl_setmulti_hash(struct xl_softc *sc)
CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT);
} }
#ifdef notdef
static void
xl_testpacket(struct xl_softc *sc)
{
struct mbuf *m;
struct ifnet *ifp = sc->xl_ifp;
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL)
return;
bcopy(IF_LLADDR(sc->xl_ifp),
mtod(m, struct ether_header *)->ether_dhost, ETHER_ADDR_LEN);
bcopy(IF_LLADDR(sc->xl_ifp),
mtod(m, struct ether_header *)->ether_shost, ETHER_ADDR_LEN);
mtod(m, struct ether_header *)->ether_type = htons(3);
mtod(m, unsigned char *)[14] = 0;
mtod(m, unsigned char *)[15] = 0;
mtod(m, unsigned char *)[16] = 0xE3;
m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
IFQ_ENQUEUE(&ifp->if_snd, m);
xl_start(ifp);
}
#endif
static void static void
xl_setcfg(struct xl_softc *sc) xl_setcfg(struct xl_softc *sc)
{ {
@@ -1052,7 +980,7 @@ xl_reset(struct xl_softc *sc)
static int static int
xl_probe(device_t dev) xl_probe(device_t dev)
{ {
struct xl_type *t; const struct xl_type *t;
t = xl_devs; t = xl_devs;
@@ -1217,11 +1145,11 @@ static int
xl_attach(device_t dev) xl_attach(device_t dev)
{ {
u_char eaddr[ETHER_ADDR_LEN]; u_char eaddr[ETHER_ADDR_LEN];
u_int16_t xcvr[2]; u_int16_t sinfo2, xcvr[2];
struct xl_softc *sc; struct xl_softc *sc;
struct ifnet *ifp; struct ifnet *ifp;
int media; int media, pmcap;
int unit, error = 0, rid, res; int error = 0, phy, rid, res, unit;
uint16_t did; uint16_t did;
sc = device_get_softc(dev); sc = device_get_softc(dev);
@@ -1369,7 +1297,6 @@ xl_attach(device_t dev)
goto fail; goto fail;
} }
sc->xl_unit = unit;
callout_init_mtx(&sc->xl_stat_callout, &sc->xl_mtx, 0); callout_init_mtx(&sc->xl_stat_callout, &sc->xl_mtx, 0);
TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc); TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc);
@@ -1478,6 +1405,18 @@ xl_attach(device_t dev)
else else
sc->xl_type = XL_TYPE_90X; sc->xl_type = XL_TYPE_90X;
/* Check availability of WOL. */
if ((sc->xl_caps & XL_CAPS_PWRMGMT) != 0 &&
pci_find_extcap(dev, PCIY_PMG, &pmcap) == 0) {
sc->xl_pmcap = pmcap;
sc->xl_flags |= XL_FLAG_WOL;
sinfo2 = 0;
xl_read_eeprom(sc, (caddr_t)&sinfo2, XL_EE_SOFTINFO2, 1, 0);
if ((sinfo2 & XL_SINFO2_AUX_WOL_CON) == 0 && bootverbose)
device_printf(dev,
"No auxiliary remote wakeup connector!\n");
}
/* Set the TX start threshold for best performance. */ /* Set the TX start threshold for best performance. */
sc->xl_tx_thresh = XL_MIN_FRAMELEN; sc->xl_tx_thresh = XL_MIN_FRAMELEN;
@@ -1492,6 +1431,8 @@ xl_attach(device_t dev)
ifp->if_capabilities |= IFCAP_HWCSUM; ifp->if_capabilities |= IFCAP_HWCSUM;
#endif #endif
} }
if ((sc->xl_flags & XL_FLAG_WOL) != 0)
ifp->if_capabilities |= IFCAP_WOL_MAGIC;
ifp->if_capenable = ifp->if_capabilities; ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING #ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING; ifp->if_capabilities |= IFCAP_POLLING;
@@ -1525,10 +1466,20 @@ xl_attach(device_t dev)
if (bootverbose) if (bootverbose)
device_printf(dev, "found MII/AUTO\n"); device_printf(dev, "found MII/AUTO\n");
xl_setcfg(sc); xl_setcfg(sc);
if (mii_phy_probe(dev, &sc->xl_miibus, /*
xl_ifmedia_upd, xl_ifmedia_sts)) { * Attach PHYs only at MII address 24 if !XL_FLAG_PHYOK.
device_printf(dev, "no PHY found!\n"); * This is to guard against problems with certain 3Com ASIC
error = ENXIO; * revisions that incorrectly map the internal transceiver
* control registers at all MII addresses.
*/
phy = MII_PHY_ANY;
if ((sc->xl_flags & XL_FLAG_PHYOK) == 0)
phy = 24;
error = mii_attach(dev, &sc->xl_miibus, ifp, xl_ifmedia_upd,
xl_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY,
sc->xl_type == XL_TYPE_905B ? MIIF_DOPAUSE : 0);
if (error != 0) {
device_printf(dev, "attaching PHYs failed\n");
goto fail; goto fail;
} }
goto done; goto done;
@@ -1708,7 +1659,6 @@ xl_detach(device_t dev)
/* These should only be active if attach succeeded */ /* These should only be active if attach succeeded */
if (device_is_attached(dev)) { if (device_is_attached(dev)) {
XL_LOCK(sc); XL_LOCK(sc);
xl_reset(sc);
xl_stop(sc); xl_stop(sc);
XL_UNLOCK(sc); XL_UNLOCK(sc);
taskqueue_drain(taskqueue_swi, &sc->xl_task); taskqueue_drain(taskqueue_swi, &sc->xl_task);
@@ -1890,8 +1840,8 @@ xl_newbuf(struct xl_softc *sc, struct xl_chain_onefrag *c)
{ {
struct mbuf *m_new = NULL; struct mbuf *m_new = NULL;
bus_dmamap_t map; bus_dmamap_t map;
int error; bus_dma_segment_t segs[1];
u_int32_t baddr; int error, nseg;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
@@ -1904,14 +1854,16 @@ xl_newbuf(struct xl_softc *sc, struct xl_chain_onefrag *c)
/* Force longword alignment for packet payload. */ /* Force longword alignment for packet payload. */
m_adj(m_new, ETHER_ALIGN); m_adj(m_new, ETHER_ALIGN);
error = bus_dmamap_load_mbuf(sc->xl_mtag, sc->xl_tmpmap, m_new, error = bus_dmamap_load_mbuf_sg(sc->xl_mtag, sc->xl_tmpmap, m_new,
xl_dma_map_rxbuf, &baddr, BUS_DMA_NOWAIT); segs, &nseg, BUS_DMA_NOWAIT);
if (error) { if (error) {
m_freem(m_new); m_freem(m_new);
device_printf(sc->xl_dev, "can't map mbuf (error %d)\n", device_printf(sc->xl_dev, "can't map mbuf (error %d)\n",
error); error);
return (error); return (error);
} }
KASSERT(nseg == 1,
("%s: too many DMA segments (%d)", __func__, nseg));
bus_dmamap_unload(sc->xl_mtag, c->xl_map); bus_dmamap_unload(sc->xl_mtag, c->xl_map);
map = c->xl_map; map = c->xl_map;
@@ -1920,7 +1872,7 @@ xl_newbuf(struct xl_softc *sc, struct xl_chain_onefrag *c)
c->xl_mbuf = m_new; c->xl_mbuf = m_new;
c->xl_ptr->xl_frag.xl_len = htole32(m_new->m_len | XL_LAST_FRAG); c->xl_ptr->xl_frag.xl_len = htole32(m_new->m_len | XL_LAST_FRAG);
c->xl_ptr->xl_status = 0; c->xl_ptr->xl_status = 0;
c->xl_ptr->xl_frag.xl_addr = htole32(baddr); c->xl_ptr->xl_frag.xl_addr = htole32(segs->ds_addr);
bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREREAD); bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREREAD);
return (0); return (0);
} }
@@ -1953,13 +1905,14 @@ xl_rx_resync(struct xl_softc *sc)
* A frame has been uploaded: pass the resulting mbuf chain up to * A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols. * the higher level protocols.
*/ */
static void static int
xl_rxeof(struct xl_softc *sc) xl_rxeof(struct xl_softc *sc)
{ {
struct mbuf *m; struct mbuf *m;
struct ifnet *ifp = sc->xl_ifp; struct ifnet *ifp = sc->xl_ifp;
struct xl_chain_onefrag *cur_rx; struct xl_chain_onefrag *cur_rx;
int total_len = 0; int total_len = 0;
int rx_npkts = 0;
u_int32_t rxstat; u_int32_t rxstat;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
@@ -2061,6 +2014,7 @@ again:
XL_UNLOCK(sc); XL_UNLOCK(sc);
(*ifp->if_input)(ifp, m); (*ifp->if_input)(ifp, m);
XL_LOCK(sc); XL_LOCK(sc);
rx_npkts++;
/* /*
* If we are running from the taskqueue, the interface * If we are running from the taskqueue, the interface
@@ -2068,7 +2022,7 @@ again:
* packet up the network stack. * packet up the network stack.
*/ */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return; return (rx_npkts);
} }
/* /*
@@ -2092,6 +2046,7 @@ again:
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
goto again; goto again;
} }
return (rx_npkts);
} }
/* /*
@@ -2142,13 +2097,13 @@ xl_txeof(struct xl_softc *sc)
m_freem(cur_tx->xl_mbuf); m_freem(cur_tx->xl_mbuf);
cur_tx->xl_mbuf = NULL; cur_tx->xl_mbuf = NULL;
ifp->if_opackets++; ifp->if_opackets++;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
cur_tx->xl_next = sc->xl_cdata.xl_tx_free; cur_tx->xl_next = sc->xl_cdata.xl_tx_free;
sc->xl_cdata.xl_tx_free = cur_tx; sc->xl_cdata.xl_tx_free = cur_tx;
} }
if (sc->xl_cdata.xl_tx_head == NULL) { if (sc->xl_cdata.xl_tx_head == NULL) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->xl_wdog_timer = 0; sc->xl_wdog_timer = 0;
sc->xl_cdata.xl_tx_tail = NULL; sc->xl_cdata.xl_tx_tail = NULL;
} else { } else {
@@ -2174,7 +2129,6 @@ xl_txeof_90xB(struct xl_softc *sc)
BUS_DMASYNC_POSTREAD); BUS_DMASYNC_POSTREAD);
idx = sc->xl_cdata.xl_tx_cons; idx = sc->xl_cdata.xl_tx_cons;
while (idx != sc->xl_cdata.xl_tx_prod) { while (idx != sc->xl_cdata.xl_tx_prod) {
cur_tx = &sc->xl_cdata.xl_tx_chain[idx]; cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
if (!(le32toh(cur_tx->xl_ptr->xl_status) & if (!(le32toh(cur_tx->xl_ptr->xl_status) &
@@ -2286,6 +2240,7 @@ xl_intr(void *arg)
} }
#endif #endif
#ifndef __HAIKU__ #ifndef __HAIKU__
while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS &&
status != 0xFFFF) { status != 0xFFFF) {
@@ -2293,6 +2248,9 @@ xl_intr(void *arg)
status = atomic_get((int32 *)&sc->xl_intr_status); status = atomic_get((int32 *)&sc->xl_intr_status);
while (true) { while (true) {
#endif #endif
CSR_WRITE_2(sc, XL_COMMAND,
XL_CMD_INTR_ACK|(status & XL_INTRS));
if (status & XL_STAT_UP_COMPLETE) { if (status & XL_STAT_UP_COMPLETE) {
int curpkts; int curpkts;
@@ -2317,7 +2275,7 @@ xl_intr(void *arg)
} }
if (status & XL_STAT_ADFAIL) { if (status & XL_STAT_ADFAIL) {
xl_reset(sc); ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc); xl_init_locked(sc);
} }
@@ -2347,26 +2305,29 @@ xl_intr(void *arg)
} }
#ifdef DEVICE_POLLING #ifdef DEVICE_POLLING
static void static int
xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{ {
struct xl_softc *sc = ifp->if_softc; struct xl_softc *sc = ifp->if_softc;
int rx_npkts = 0;
XL_LOCK(sc); XL_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) if (ifp->if_drv_flags & IFF_DRV_RUNNING)
xl_poll_locked(ifp, cmd, count); rx_npkts = xl_poll_locked(ifp, cmd, count);
XL_UNLOCK(sc); XL_UNLOCK(sc);
return (rx_npkts);
} }
static void static int
xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{ {
struct xl_softc *sc = ifp->if_softc; struct xl_softc *sc = ifp->if_softc;
int rx_npkts;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
sc->rxcycles = count; sc->rxcycles = count;
xl_rxeof(sc); rx_npkts = xl_rxeof(sc);
if (sc->xl_type == XL_TYPE_905B) if (sc->xl_type == XL_TYPE_905B)
xl_txeof_90xB(sc); xl_txeof_90xB(sc);
else else
@@ -2393,7 +2354,7 @@ xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
} }
if (status & XL_STAT_ADFAIL) { if (status & XL_STAT_ADFAIL) {
xl_reset(sc); ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc); xl_init_locked(sc);
} }
@@ -2404,6 +2365,7 @@ xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
} }
} }
} }
return (rx_npkts);
} }
#endif /* DEVICE_POLLING */ #endif /* DEVICE_POLLING */
@@ -2475,26 +2437,21 @@ xl_stats_update_locked(struct xl_softc *sc)
* pointers to the fragment pointers. * pointers to the fragment pointers.
*/ */
static int static int
xl_encap(struct xl_softc *sc, struct xl_chain *c, struct mbuf *m_head) xl_encap(struct xl_softc *sc, struct xl_chain *c, struct mbuf **m_head)
{ {
int error; struct mbuf *m_new;
u_int32_t status;
struct ifnet *ifp = sc->xl_ifp; struct ifnet *ifp = sc->xl_ifp;
int error, i, nseg, total_len;
u_int32_t status;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
/* error = bus_dmamap_load_mbuf_sg(sc->xl_mtag, c->xl_map, *m_head,
* Start packing the mbufs in this chain into sc->xl_cdata.xl_tx_segs, &nseg, BUS_DMA_NOWAIT);
* the fragment pointers. Stop when we run out
* of fragments or hit the end of the mbuf chain.
*/
error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map, m_head,
xl_dma_map_txbuf, c->xl_ptr, BUS_DMA_NOWAIT);
if (error && error != EFBIG) { if (error && error != EFBIG) {
m_freem(m_head);
if_printf(ifp, "can't map mbuf (error %d)\n", error); if_printf(ifp, "can't map mbuf (error %d)\n", error);
return (1); return (error);
} }
/* /*
@@ -2506,42 +2463,64 @@ xl_encap(struct xl_softc *sc, struct xl_chain *c, struct mbuf *m_head)
* and would waste cycles. * and would waste cycles.
*/ */
if (error) { if (error) {
struct mbuf *m_new; m_new = m_collapse(*m_head, M_DONTWAIT, XL_MAXFRAGS);
m_new = m_defrag(m_head, M_DONTWAIT);
if (m_new == NULL) { if (m_new == NULL) {
m_freem(m_head); m_freem(*m_head);
return (1); *m_head = NULL;
} else { return (ENOBUFS);
m_head = m_new; }
*m_head = m_new;
error = bus_dmamap_load_mbuf_sg(sc->xl_mtag, c->xl_map,
*m_head, sc->xl_cdata.xl_tx_segs, &nseg, BUS_DMA_NOWAIT);
if (error) {
m_freem(*m_head);
*m_head = NULL;
if_printf(ifp, "can't map mbuf (error %d)\n", error);
return (error);
}
} }
error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map, KASSERT(nseg <= XL_MAXFRAGS,
m_head, xl_dma_map_txbuf, c->xl_ptr, BUS_DMA_NOWAIT); ("%s: too many DMA segments (%d)", __func__, nseg));
if (error) { if (nseg == 0) {
m_freem(m_head); m_freem(*m_head);
if_printf(ifp, "can't map mbuf (error %d)\n", error); *m_head = NULL;
return (1); return (EIO);
} }
total_len = 0;
for (i = 0; i < nseg; i++) {
KASSERT(sc->xl_cdata.xl_tx_segs[i].ds_len <= MCLBYTES,
("segment size too large"));
c->xl_ptr->xl_frag[i].xl_addr =
htole32(sc->xl_cdata.xl_tx_segs[i].ds_addr);
c->xl_ptr->xl_frag[i].xl_len =
htole32(sc->xl_cdata.xl_tx_segs[i].ds_len);
total_len += sc->xl_cdata.xl_tx_segs[i].ds_len;
} }
c->xl_ptr->xl_frag[nseg - 1].xl_len =
htole32(sc->xl_cdata.xl_tx_segs[nseg - 1].ds_len | XL_LAST_FRAG);
c->xl_ptr->xl_status = htole32(total_len);
c->xl_ptr->xl_next = 0;
if (sc->xl_type == XL_TYPE_905B) { if (sc->xl_type == XL_TYPE_905B) {
status = XL_TXSTAT_RND_DEFEAT; status = XL_TXSTAT_RND_DEFEAT;
#ifndef XL905B_TXCSUM_BROKEN #ifndef XL905B_TXCSUM_BROKEN
if (m_head->m_pkthdr.csum_flags) { if ((*m_head)->m_pkthdr.csum_flags) {
if (m_head->m_pkthdr.csum_flags & CSUM_IP) if ((*m_head)->m_pkthdr.csum_flags & CSUM_IP)
status |= XL_TXSTAT_IPCKSUM; status |= XL_TXSTAT_IPCKSUM;
if (m_head->m_pkthdr.csum_flags & CSUM_TCP) if ((*m_head)->m_pkthdr.csum_flags & CSUM_TCP)
status |= XL_TXSTAT_TCPCKSUM; status |= XL_TXSTAT_TCPCKSUM;
if (m_head->m_pkthdr.csum_flags & CSUM_UDP) if ((*m_head)->m_pkthdr.csum_flags & CSUM_UDP)
status |= XL_TXSTAT_UDPCKSUM; status |= XL_TXSTAT_UDPCKSUM;
} }
#endif #endif
c->xl_ptr->xl_status = htole32(status); c->xl_ptr->xl_status = htole32(status);
} }
c->xl_mbuf = m_head; c->xl_mbuf = *m_head;
bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREWRITE);
return (0); return (0);
} }
@@ -2574,12 +2553,14 @@ xl_start_locked(struct ifnet *ifp)
struct xl_softc *sc = ifp->if_softc; struct xl_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL; struct mbuf *m_head = NULL;
struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx; struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
struct xl_chain *prev_tx;
u_int32_t status; u_int32_t status;
int error; int error;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
return;
/* /*
* Check for an available queue slot. If there are none, * Check for an available queue slot. If there are none,
* punt. * punt.
@@ -2595,20 +2576,23 @@ xl_start_locked(struct ifnet *ifp)
start_tx = sc->xl_cdata.xl_tx_free; start_tx = sc->xl_cdata.xl_tx_free;
while (sc->xl_cdata.xl_tx_free != NULL) { for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
sc->xl_cdata.xl_tx_free != NULL;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL) if (m_head == NULL)
break; break;
/* Pick a descriptor off the free list. */ /* Pick a descriptor off the free list. */
prev_tx = cur_tx;
cur_tx = sc->xl_cdata.xl_tx_free; cur_tx = sc->xl_cdata.xl_tx_free;
/* Pack the data into the descriptor. */ /* Pack the data into the descriptor. */
error = xl_encap(sc, cur_tx, m_head); error = xl_encap(sc, cur_tx, &m_head);
if (error) { if (error) {
cur_tx = prev_tx; if (m_head == NULL)
continue; break;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
break;
} }
sc->xl_cdata.xl_tx_free = cur_tx->xl_next; sc->xl_cdata.xl_tx_free = cur_tx->xl_next;
@@ -2638,7 +2622,7 @@ xl_start_locked(struct ifnet *ifp)
* Place the request for the upload interrupt * Place the request for the upload interrupt
* in the last descriptor in the chain. This way, if * in the last descriptor in the chain. This way, if
* we're chaining several packets at once, we'll only * we're chaining several packets at once, we'll only
* get an interupt once for the whole chain rather than * get an interrupt once for the whole chain rather than
* once for each packet. * once for each packet.
*/ */
cur_tx->xl_ptr->xl_status = htole32(le32toh(cur_tx->xl_ptr->xl_status) | cur_tx->xl_ptr->xl_status = htole32(le32toh(cur_tx->xl_ptr->xl_status) |
@@ -2701,19 +2685,19 @@ xl_start_90xB_locked(struct ifnet *ifp)
struct xl_softc *sc = ifp->if_softc; struct xl_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL; struct mbuf *m_head = NULL;
struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx; struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
struct xl_chain *prev_tx;
int error, idx; int error, idx;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
if (ifp->if_drv_flags & IFF_DRV_OACTIVE) if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
return; return;
idx = sc->xl_cdata.xl_tx_prod; idx = sc->xl_cdata.xl_tx_prod;
start_tx = &sc->xl_cdata.xl_tx_chain[idx]; start_tx = &sc->xl_cdata.xl_tx_chain[idx];
while (sc->xl_cdata.xl_tx_chain[idx].xl_mbuf == NULL) { for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
sc->xl_cdata.xl_tx_chain[idx].xl_mbuf == NULL;) {
if ((XL_TX_LIST_CNT - sc->xl_cdata.xl_tx_cnt) < 3) { if ((XL_TX_LIST_CNT - sc->xl_cdata.xl_tx_cnt) < 3) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE; ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break; break;
@@ -2723,14 +2707,16 @@ xl_start_90xB_locked(struct ifnet *ifp)
if (m_head == NULL) if (m_head == NULL)
break; break;
prev_tx = cur_tx;
cur_tx = &sc->xl_cdata.xl_tx_chain[idx]; cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
/* Pack the data into the descriptor. */ /* Pack the data into the descriptor. */
error = xl_encap(sc, cur_tx, m_head); error = xl_encap(sc, cur_tx, &m_head);
if (error) { if (error) {
cur_tx = prev_tx; if (m_head == NULL)
continue; break;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
break;
} }
/* Chain it together. */ /* Chain it together. */
@@ -2758,7 +2744,7 @@ xl_start_90xB_locked(struct ifnet *ifp)
* Place the request for the upload interrupt * Place the request for the upload interrupt
* in the last descriptor in the chain. This way, if * in the last descriptor in the chain. This way, if
* we're chaining several packets at once, we'll only * we're chaining several packets at once, we'll only
* get an interupt once for the whole chain rather than * get an interrupt once for the whole chain rather than
* once for each packet. * once for each packet.
*/ */
cur_tx->xl_ptr->xl_status = htole32(le32toh(cur_tx->xl_ptr->xl_status) | cur_tx->xl_ptr->xl_status = htole32(le32toh(cur_tx->xl_ptr->xl_status) |
@@ -2796,11 +2782,16 @@ xl_init_locked(struct xl_softc *sc)
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
return;
/* /*
* Cancel pending I/O and free all RX/TX buffers. * Cancel pending I/O and free all RX/TX buffers.
*/ */
xl_stop(sc); xl_stop(sc);
/* Reset the chip to a known state. */
xl_reset(sc);
if (sc->xl_miibus == NULL) { if (sc->xl_miibus == NULL) {
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
xl_wait(sc); xl_wait(sc);
@@ -2812,6 +2803,15 @@ xl_init_locked(struct xl_softc *sc)
if (sc->xl_miibus != NULL) if (sc->xl_miibus != NULL)
mii = device_get_softc(sc->xl_miibus); mii = device_get_softc(sc->xl_miibus);
/*
* Clear WOL status and disable all WOL feature as WOL
* would interfere Rx operation under normal environments.
*/
if ((sc->xl_flags & XL_FLAG_WOL) != 0) {
XL_SEL_WIN(7);
CSR_READ_2(sc, XL_W7_BM_PME);
CSR_WRITE_2(sc, XL_W7_BM_PME, 0);
}
/* Init our MAC address */ /* Init our MAC address */
XL_SEL_WIN(2); XL_SEL_WIN(2);
for (i = 0; i < ETHER_ADDR_LEN; i++) { for (i = 0; i < ETHER_ADDR_LEN; i++) {
@@ -3037,15 +3037,14 @@ xl_ifmedia_upd(struct ifnet *ifp)
case IFM_10_2: case IFM_10_2:
case IFM_10_5: case IFM_10_5:
xl_setmode(sc, ifm->ifm_media); xl_setmode(sc, ifm->ifm_media);
XL_UNLOCK(sc);
return (0); return (0);
break;
default:
break;
} }
if (sc->xl_media & XL_MEDIAOPT_MII || if (sc->xl_media & XL_MEDIAOPT_MII ||
sc->xl_media & XL_MEDIAOPT_BTX || sc->xl_media & XL_MEDIAOPT_BTX ||
sc->xl_media & XL_MEDIAOPT_BT4) { sc->xl_media & XL_MEDIAOPT_BT4) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc); xl_init_locked(sc);
} else { } else {
xl_setmode(sc, ifm->ifm_media); xl_setmode(sc, ifm->ifm_media);
@@ -3136,7 +3135,7 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{ {
struct xl_softc *sc = ifp->if_softc; struct xl_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data; struct ifreq *ifr = (struct ifreq *) data;
int error = 0; int error = 0, mask;
struct mii_data *mii = NULL; struct mii_data *mii = NULL;
u_int8_t rxfilt; u_int8_t rxfilt;
@@ -3161,10 +3160,8 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
CSR_WRITE_2(sc, XL_COMMAND, CSR_WRITE_2(sc, XL_COMMAND,
XL_CMD_RX_SET_FILT|rxfilt); XL_CMD_RX_SET_FILT|rxfilt);
XL_SEL_WIN(7); XL_SEL_WIN(7);
} else { } else
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
xl_init_locked(sc); xl_init_locked(sc);
}
} else { } else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) if (ifp->if_drv_flags & IFF_DRV_RUNNING)
xl_stop(sc); xl_stop(sc);
@@ -3196,41 +3193,50 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
&mii->mii_media, command); &mii->mii_media, command);
break; break;
case SIOCSIFCAP: case SIOCSIFCAP:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING #ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING && if ((mask & IFCAP_POLLING) != 0 &&
!(ifp->if_capenable & IFCAP_POLLING)) { (ifp->if_capabilities & IFCAP_POLLING) != 0) {
ifp->if_capenable ^= IFCAP_POLLING;
if ((ifp->if_capenable & IFCAP_POLLING) != 0) {
error = ether_poll_register(xl_poll, ifp); error = ether_poll_register(xl_poll, ifp);
if (error) if (error)
return(error); break;
XL_LOCK(sc); XL_LOCK(sc);
/* Disable interrupts */ /* Disable interrupts */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
ifp->if_capenable |= IFCAP_POLLING; ifp->if_capenable |= IFCAP_POLLING;
XL_UNLOCK(sc); XL_UNLOCK(sc);
return (error); } else {
}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
error = ether_poll_deregister(ifp); error = ether_poll_deregister(ifp);
/* Enable interrupts. */ /* Enable interrupts. */
XL_LOCK(sc); XL_LOCK(sc);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF); CSR_WRITE_2(sc, XL_COMMAND,
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); XL_CMD_INTR_ACK | 0xFF);
CSR_WRITE_2(sc, XL_COMMAND,
XL_CMD_INTR_ENB | XL_INTRS);
if (sc->xl_flags & XL_FLAG_FUNCREG) if (sc->xl_flags & XL_FLAG_FUNCREG)
bus_space_write_4(sc->xl_ftag, sc->xl_fhandle, bus_space_write_4(sc->xl_ftag,
4, 0x8000); sc->xl_fhandle, 4, 0x8000);
ifp->if_capenable &= ~IFCAP_POLLING;
XL_UNLOCK(sc); XL_UNLOCK(sc);
return (error); }
} }
#endif /* DEVICE_POLLING */ #endif /* DEVICE_POLLING */
XL_LOCK(sc); XL_LOCK(sc);
ifp->if_capenable = ifr->ifr_reqcap; if ((mask & IFCAP_TXCSUM) != 0 &&
if (ifp->if_capenable & IFCAP_TXCSUM) (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
ifp->if_hwassist = XL905B_CSUM_FEATURES; ifp->if_capenable ^= IFCAP_TXCSUM;
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
ifp->if_hwassist |= XL905B_CSUM_FEATURES;
else else
ifp->if_hwassist = 0; ifp->if_hwassist &= ~XL905B_CSUM_FEATURES;
}
if ((mask & IFCAP_RXCSUM) != 0 &&
(ifp->if_capabilities & IFCAP_RXCSUM) != 0)
ifp->if_capenable ^= IFCAP_RXCSUM;
if ((mask & IFCAP_WOL_MAGIC) != 0 &&
(ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0)
ifp->if_capenable ^= IFCAP_WOL_MAGIC;
XL_UNLOCK(sc); XL_UNLOCK(sc);
break; break;
default: default:
@@ -3246,12 +3252,31 @@ xl_watchdog(struct xl_softc *sc)
{ {
struct ifnet *ifp = sc->xl_ifp; struct ifnet *ifp = sc->xl_ifp;
u_int16_t status = 0; u_int16_t status = 0;
int misintr;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
if (sc->xl_wdog_timer == 0 || --sc->xl_wdog_timer != 0) if (sc->xl_wdog_timer == 0 || --sc->xl_wdog_timer != 0)
return (0); return (0);
xl_rxeof(sc);
xl_txeoc(sc);
misintr = 0;
if (sc->xl_type == XL_TYPE_905B) {
xl_txeof_90xB(sc);
if (sc->xl_cdata.xl_tx_cnt == 0)
misintr++;
} else {
xl_txeof(sc);
if (sc->xl_cdata.xl_tx_head == NULL)
misintr++;
}
if (misintr != 0) {
device_printf(sc->xl_dev,
"watchdog timeout (missed Tx interrupts) -- recovering\n");
return (0);
}
ifp->if_oerrors++; ifp->if_oerrors++;
XL_SEL_WIN(4); XL_SEL_WIN(4);
status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS); status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
@@ -3261,10 +3286,7 @@ xl_watchdog(struct xl_softc *sc)
device_printf(sc->xl_dev, device_printf(sc->xl_dev,
"no carrier - transceiver cable problem?\n"); "no carrier - transceiver cable problem?\n");
xl_txeoc(sc); ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_txeof(sc);
xl_rxeof(sc);
xl_reset(sc);
xl_init_locked(sc); xl_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
@@ -3354,17 +3376,11 @@ xl_stop(struct xl_softc *sc)
* Stop all chip I/O so that the kernel's probe routines don't * Stop all chip I/O so that the kernel's probe routines don't
* get confused by errant DMAs when rebooting. * get confused by errant DMAs when rebooting.
*/ */
static void static int
xl_shutdown(device_t dev) xl_shutdown(device_t dev)
{ {
struct xl_softc *sc;
sc = device_get_softc(dev); return (xl_suspend(dev));
XL_LOCK(sc);
xl_reset(sc);
xl_stop(sc);
XL_UNLOCK(sc);
} }
static int static int
@@ -3376,6 +3392,7 @@ xl_suspend(device_t dev)
XL_LOCK(sc); XL_LOCK(sc);
xl_stop(sc); xl_stop(sc);
xl_setwol(sc);
XL_UNLOCK(sc); XL_UNLOCK(sc);
return (0); return (0);
@@ -3392,11 +3409,43 @@ xl_resume(device_t dev)
XL_LOCK(sc); XL_LOCK(sc);
xl_reset(sc); if (ifp->if_flags & IFF_UP) {
if (ifp->if_flags & IFF_UP) ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc); xl_init_locked(sc);
}
XL_UNLOCK(sc); XL_UNLOCK(sc);
return (0); return (0);
} }
static void
xl_setwol(struct xl_softc *sc)
{
struct ifnet *ifp;
u_int16_t cfg, pmstat;
if ((sc->xl_flags & XL_FLAG_WOL) == 0)
return;
ifp = sc->xl_ifp;
XL_SEL_WIN(7);
/* Clear any pending PME events. */
CSR_READ_2(sc, XL_W7_BM_PME);
cfg = 0;
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
cfg |= XL_BM_PME_MAGIC;
CSR_WRITE_2(sc, XL_W7_BM_PME, cfg);
/* Enable RX. */
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE);
/* Request PME. */
pmstat = pci_read_config(sc->xl_dev,
sc->xl_pmcap + PCIR_POWER_STATUS, 2);
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
pmstat |= PCIM_PSTAT_PMEENABLE;
else
pmstat &= ~PCIM_PSTAT_PMEENABLE;
pci_write_config(sc->xl_dev,
sc->xl_pmcap + PCIR_POWER_STATUS, pmstat, 2);
}
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
* *
* $FreeBSD: src/sys/pci/if_xlreg.h,v 1.59 2006/12/06 02:18:41 marius Exp $ * $FreeBSD: src/sys/dev/xl/if_xlreg.h,v 1.1.2.2.2.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
#define XL_EE_READ 0x0080 /* read, 5 bit address */ #define XL_EE_READ 0x0080 /* read, 5 bit address */
@@ -81,6 +81,17 @@
#define XL_CAPS_100MBPS 0x1000 #define XL_CAPS_100MBPS 0x1000
#define XL_CAPS_PWRMGMT 0x2000 #define XL_CAPS_PWRMGMT 0x2000
/*
* Bits in the software information 2 word
*/
#define XL_SINFO2_FIXED_BCAST_RX_BUG 0x0002
#define XL_SINFO2_FIXED_ENDEC_LOOP_BUG 0x0004
#define XL_SINFO2_AUX_WOL_CON 0x0008
#define XL_SINFO2_PME_PULSED 0x0010
#define XL_SINFO2_FIXED_MWI_BUG 0x0020
#define XL_SINFO2_WOL_AFTER_PWR_LOSS 0x0040
#define XL_SINFO2_AUTO_RST_TO_D0 0x0080
#define XL_PACKET_SIZE 1540 #define XL_PACKET_SIZE 1540
#define XL_MAX_FRAMELEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) #define XL_MAX_FRAMELEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN)
@@ -408,7 +419,12 @@
#define XL_W7_BM_LEN 0x06 #define XL_W7_BM_LEN 0x06
#define XL_W7_BM_STATUS 0x0B #define XL_W7_BM_STATUS 0x0B
#define XL_W7_BM_TIMEr 0x0A #define XL_W7_BM_TIMEr 0x0A
#define XL_W7_BM_PME 0x0C
#define XL_BM_PME_WAKE 0x0001
#define XL_BM_PME_MAGIC 0x0002
#define XL_BM_PME_LINKCHG 0x0004
#define XL_BM_PME_WAKETIMER 0x0008
/* /*
* bus master control registers * bus master control registers
*/ */
@@ -486,6 +502,7 @@ struct xl_chain_onefrag {
struct xl_chain_data { struct xl_chain_data {
struct xl_chain_onefrag xl_rx_chain[XL_RX_LIST_CNT]; struct xl_chain_onefrag xl_rx_chain[XL_RX_LIST_CNT];
struct xl_chain xl_tx_chain[XL_TX_LIST_CNT]; struct xl_chain xl_tx_chain[XL_TX_LIST_CNT];
bus_dma_segment_t xl_tx_segs[XL_MAXFRAGS];
struct xl_chain_onefrag *xl_rx_head; struct xl_chain_onefrag *xl_rx_head;
@@ -576,6 +593,7 @@ struct xl_mii_frame {
#define XL_FLAG_NO_XCVR_PWR 0x0080 #define XL_FLAG_NO_XCVR_PWR 0x0080
#define XL_FLAG_USE_MMIO 0x0100 #define XL_FLAG_USE_MMIO 0x0100
#define XL_FLAG_NO_MMIO 0x0200 #define XL_FLAG_NO_MMIO 0x0200
#define XL_FLAG_WOL 0x0400
#define XL_NO_XCVR_PWR_MAGICBITS 0x0900 #define XL_NO_XCVR_PWR_MAGICBITS 0x0900
@@ -589,16 +607,16 @@ struct xl_softc {
struct resource *xl_irq; struct resource *xl_irq;
struct resource *xl_res; struct resource *xl_res;
device_t xl_miibus; device_t xl_miibus;
struct xl_type *xl_info; /* 3Com adapter info */ const struct xl_type *xl_info; /* 3Com adapter info */
bus_dma_tag_t xl_mtag; bus_dma_tag_t xl_mtag;
bus_dmamap_t xl_tmpmap; /* spare DMA map */ bus_dmamap_t xl_tmpmap; /* spare DMA map */
u_int8_t xl_unit; /* interface number */
u_int8_t xl_type; u_int8_t xl_type;
u_int32_t xl_xcvr; u_int32_t xl_xcvr;
u_int16_t xl_media; u_int16_t xl_media;
u_int16_t xl_caps; u_int16_t xl_caps;
u_int8_t xl_stats_no_timeout; u_int8_t xl_stats_no_timeout;
u_int16_t xl_tx_thresh; u_int16_t xl_tx_thresh;
int xl_pmcap;
int xl_if_flags; int xl_if_flags;
struct xl_list_data xl_ldata; struct xl_list_data xl_ldata;
struct xl_chain_data xl_cdata; struct xl_chain_data xl_cdata;
+4 -3
View File
@@ -3,7 +3,6 @@ SubDir HAIKU_TOP src add-ons kernel drivers network ;
SubInclude HAIKU_TOP src add-ons kernel drivers network etherpci ; SubInclude HAIKU_TOP src add-ons kernel drivers network etherpci ;
SubInclude HAIKU_TOP src add-ons kernel drivers network ipro1000 ; SubInclude HAIKU_TOP src add-ons kernel drivers network ipro1000 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network pegasus ; SubInclude HAIKU_TOP src add-ons kernel drivers network pegasus ;
SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8139 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8169 ; SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8169 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network sis900 ; SubInclude HAIKU_TOP src add-ons kernel drivers network sis900 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network usb_asix ; SubInclude HAIKU_TOP src add-ons kernel drivers network usb_asix ;
@@ -14,10 +13,8 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network vlance ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wb840 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wb840 ;
# FreeBSD 7 drivers # FreeBSD 7 drivers
SubInclude HAIKU_TOP src add-ons kernel drivers network 3com ;
SubInclude HAIKU_TOP src add-ons kernel drivers network broadcom440x ; SubInclude HAIKU_TOP src add-ons kernel drivers network broadcom440x ;
SubInclude HAIKU_TOP src add-ons kernel drivers network broadcom570x ; SubInclude HAIKU_TOP src add-ons kernel drivers network broadcom570x ;
SubInclude HAIKU_TOP src add-ons kernel drivers network ipro100 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network jmicron2x0 ; SubInclude HAIKU_TOP src add-ons kernel drivers network jmicron2x0 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network marvell_yukon ; SubInclude HAIKU_TOP src add-ons kernel drivers network marvell_yukon ;
SubInclude HAIKU_TOP src add-ons kernel drivers network nforce ; SubInclude HAIKU_TOP src add-ons kernel drivers network nforce ;
@@ -33,7 +30,11 @@ SubIncludeGPL HAIKU_TOP src add-ons kernel drivers network bcm440x ;
SubIncludeGPL HAIKU_TOP src add-ons kernel drivers network bcm570x ; SubIncludeGPL HAIKU_TOP src add-ons kernel drivers network bcm570x ;
# FreeBSD 8 drivers # FreeBSD 8 drivers
SubInclude HAIKU_TOP src add-ons kernel drivers network 3com ;
SubInclude HAIKU_TOP src add-ons kernel drivers network atheros813x ; SubInclude HAIKU_TOP src add-ons kernel drivers network atheros813x ;
SubInclude HAIKU_TOP src add-ons kernel drivers network ipro100 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network dec21xxx ;
SubInclude HAIKU_TOP src add-ons kernel drivers network rtl8139 ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ;
@@ -0,0 +1,3 @@
SubDir HAIKU_TOP src add-ons kernel drivers network dec21xxx ;
SubInclude HAIKU_TOP src add-ons kernel drivers network dec21xxx dev ;
@@ -0,0 +1,4 @@
SubDir HAIKU_TOP src add-ons kernel drivers network dec21xxx dev ;
SubInclude HAIKU_TOP src add-ons kernel drivers network dec21xxx dev mii ;
SubInclude HAIKU_TOP src add-ons kernel drivers network dec21xxx dev dc ;
@@ -0,0 +1,15 @@
SubDir HAIKU_TOP src add-ons kernel drivers network dec21xxx dev dc ;
UseHeaders [ FDirName $(SUBDIR) .. .. ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
UsePrivateHeaders net ;
UsePrivateKernelHeaders ;
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] ;
KernelAddon dec21xxx :
if_dc.c
glue.c
: libfreebsd_network.a dec21xxx_mii.a
;
@@ -0,0 +1,82 @@
/*
* Copyright 2007, Axel Dörfler, [email protected]. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#include <sys/bus.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include "if_dcreg.h"
HAIKU_FBSD_DRIVER_GLUE(dec21xxx, dc, pci)
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE | FBSD_SWI_TASKQUEUE);
extern driver_t *DRIVER_MODULE_NAME(acphy, miibus);
extern driver_t *DRIVER_MODULE_NAME(amphy, miibus);
extern driver_t *DRIVER_MODULE_NAME(dcphy, miibus);
extern driver_t *DRIVER_MODULE_NAME(pnphy, miibus);
extern driver_t *DRIVER_MODULE_NAME(ukphy, miibus);
driver_t *
__haiku_select_miibus_driver(device_t dev)
{
driver_t *drivers[] = {
DRIVER_MODULE_NAME(acphy, miibus),
DRIVER_MODULE_NAME(amphy, miibus),
DRIVER_MODULE_NAME(dcphy, miibus),
DRIVER_MODULE_NAME(pnphy, miibus),
DRIVER_MODULE_NAME(ukphy, miibus),
NULL
};
return __haiku_probe_miibus(dev, drivers);
}
int
HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)
{
struct dc_softc *sc = device_get_softc(dev);
uint16_t status;
HAIKU_INTR_REGISTER_STATE;
HAIKU_INTR_REGISTER_ENTER();
status = CSR_READ_4(sc, DC_ISR);
if (status == 0xffff) {
HAIKU_INTR_REGISTER_LEAVE();
return 0;
}
if (status != 0 && (status & DC_INTRS) == 0) {
CSR_WRITE_4(sc, DC_ISR, status);
HAIKU_INTR_REGISTER_LEAVE();
return 0;
}
if ((status & DC_INTRS) == 0) {
HAIKU_INTR_REGISTER_LEAVE();
return 0;
}
CSR_WRITE_4(sc, DC_IMR, 0);
HAIKU_INTR_REGISTER_LEAVE();
return 1;
}
void
HAIKU_REENABLE_INTERRUPTS(device_t dev)
{
struct dc_softc *sc = device_get_softc(dev);
DC_LOCK(sc);
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
DC_UNLOCK(sc);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,26 @@
SubDir HAIKU_TOP src add-ons kernel drivers network dec21xxx dev mii ;
UseHeaders [ FDirName $(SUBDIR) .. .. ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ]
: true ;
UsePrivateHeaders net system ;
UsePrivateKernelHeaders ;
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] ;
KernelStaticLibrary dec21xxx_mii.a
:
acphy.c
amphy.c
dcphy.c
pnphy.c
ukphy.c
ukphy_subr.c
;
ObjectHdrs [ FGristFiles acphy$(SUFOBJ) amphy$(SUFOBJ) dcphy$(SUFOBJ)
pnphy$(SUFOBJ) ukphy$(SUFOBJ) ]
: [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR) libs compat freebsd_network ] ;
Includes [ FGristFiles dcphy.c pnphy.c ]
: <src!libs!compat!freebsd_network>miidevs.h ;
@@ -0,0 +1,261 @@
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 1997 Manuel Bouyer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/acphy.c,v 1.21.10.6.2.1 2010/12/21 17:09:25 kensmith Exp $");
/*
* Driver for Altima AC101 10/100 PHY
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miidevs.h"
#include <dev/mii/acphyreg.h>
#include "miibus_if.h"
static int acphy_probe(device_t);
static int acphy_attach(device_t);
static device_method_t acphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, acphy_probe),
DEVMETHOD(device_attach, acphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{ 0, 0 }
};
static devclass_t acphy_devclass;
static driver_t acphy_driver = {
"acphy",
acphy_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(acphy, miibus, acphy_driver, acphy_devclass, 0, 0);
static int acphy_service(struct mii_softc *, struct mii_data *, int);
static void acphy_reset(struct mii_softc *);
static void acphy_status(struct mii_softc *);
static const struct mii_phydesc acphys[] = {
MII_PHY_DESC(xxALTIMA, AC101),
MII_PHY_DESC(xxALTIMA, AC101L),
/* XXX This is reported to work, but it's not from any data sheet. */
MII_PHY_DESC(xxALTIMA, ACXXX),
MII_PHY_END
};
static int
acphy_probe(device_t dev)
{
return (mii_phy_dev_probe(dev, acphys, BUS_PROBE_DEFAULT));
}
static int
acphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = acphy_service;
sc->mii_pdata = mii;
acphy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " ");
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
if ((PHY_READ(sc, MII_ACPHY_MCTL) & AC_MCTL_FX_SEL) != 0) {
sc->mii_flags |= MIIF_HAVEFIBER;
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst),
MII_MEDIA_100_TX);
printf("100baseFX, ");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst),
MII_MEDIA_100_TX_FDX);
printf("100baseFX-FDX, ");
}
#undef ADD
mii_phy_add_media(sc);
printf("\n");
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
}
static int
acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
int reg;
switch (cmd) {
case MII_POLLSTAT:
break;
case MII_MEDIACHG:
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
/* Wake & deisolate up if necessary */
reg = PHY_READ(sc, MII_BMCR);
if (reg & (BMCR_ISO | BMCR_PDOWN))
PHY_WRITE(sc, MII_BMCR, reg & ~(BMCR_ISO | BMCR_PDOWN));
mii_phy_setmedia(sc);
break;
case MII_TICK:
/*
* Is the interface even up?
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0);
/*
* This PHY's autonegotiation doesn't need to be kicked.
*/
break;
}
/* Update the media status. */
acphy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
acphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int bmsr, bmcr, diag;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, MII_BMSR) |
PHY_READ(sc, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
return;
}
if (bmcr & BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
if (bmcr & BMCR_AUTOEN) {
if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
diag = PHY_READ(sc, MII_ACPHY_DIAG);
if (diag & AC_DIAG_SPEED)
mii->mii_media_active |= IFM_100_TX;
else
mii->mii_media_active |= IFM_10_T;
if (diag & AC_DIAG_DUPLEX)
mii->mii_media_active |= IFM_FDX;
else
mii->mii_media_active |= IFM_HDX;
} else
mii->mii_media_active = ife->ifm_media;
}
static void
acphy_reset(struct mii_softc *sc)
{
mii_phy_reset(sc);
PHY_WRITE(sc, MII_ACPHY_INT, 0);
}
@@ -0,0 +1,77 @@
/*-
* Copyright (c) 2001 Semen Ustimenko (semenu@FreeBSD.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/dev/mii/acphyreg.h,v 1.2.10.1.6.1 2010/12/21 17:09:25 kensmith Exp $
*/
#ifndef _DEV_MII_ACPHYREG_H_
#define _DEV_MII_ACPHYREG_H_
/*
* Register definitions for the Altima Communications AC101
*/
#define MII_ACPHY_POL 0x10 /* Polarity int level */
/* High byte is interrupt mask register */
#define MII_ACPHY_INT 0x11 /* Interrupt control/status */
#define AC_INT_ACOMP 0x0001 /* Autoneg complete */
#define AC_INT_REM_FLT 0x0002 /* Remote fault */
#define AC_INT_LINK_DOWN 0x0004 /* Link not OK */
#define AC_INT_LP_ACK 0x0008 /* FLP ack recved */
#define AC_INT_PD_FLT 0x0010 /* Parallel detect fault */
#define AC_INT_PAGE_RECV 0x0020 /* New page recved */
#define AC_INT_RX_ER 0x0040 /* RX_ER transitions high */
#define AC_INT_JAB 0x0080 /* Jabber detected */
#define MII_ACPHY_DIAG 0x12 /* Diagnostic */
#define AC_DIAG_RX_LOCK 0x0100
#define AC_DIAG_RX_PASS 0x0200
#define AC_DIAG_SPEED 0x0400 /* Aneg speed result */
#define AC_DIAG_DUPLEX 0x0800 /* Aneg duplex result */
#define MII_ACPHY_PWRLOOP 0x13 /* Power/Loopback */
#define MII_ACPHY_CBLMEAS 0x14 /* Cable meas. */
#define MII_ACPHY_MCTL 0x15 /* Mode control */
#define AC_MCTL_FX_SEL 0x0001 /* FX mode */
#define AC_MCTL_BYP_PCS 0x0002 /* Bypass PCS */
#define AC_MCTL_SCRMBL 0x0004 /* Data scrambling */
#define AC_MCTL_REM_LOOP 0x0008 /* Remote loopback */
#define AC_MCTL_DIS_WDT 0x0010 /* Disable watchdog timer */
#define AC_MCTL_DIS_REC 0x0020 /* Disable recv error counter */
#define AC_MCTL_REC_FULL 0x0040 /* Recv error counter full */
#define AC_MCTL_FRC_FEF 0x0080 /* Force Far End Fault Insert. */
#define AC_MCTL_DIS_FEF 0x0100 /* Disable FEF Insertion */
#define AC_MCTL_LED_SEL 0x0200 /* Compat LED config */
#define AC_MCTL_ALED_SEL 0x0400 /* ActLED RX&TX - RX only */
#define AC_MCTL_10BT_SEL 0x0800 /* Enable 7-wire interface */
#define AC_MCTL_DIS_JAB 0x1000 /* Disable jabber */
#define AC_MCTL_FRC_LINK 0x2000 /* Force TX link up */
#define AC_MCTL_DIS_NLP 0x4000 /* Disable NLP check */
#define MII_ACPHY_REC 0x18 /* Recv error counter */
#endif /* _DEV_MII_ACPHYREG_H_ */
@@ -0,0 +1,236 @@
/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/amphy.c,v 1.24.2.5.2.1 2010/12/21 17:09:25 kensmith Exp $");
/*
* driver for AMD AM79c873 PHYs
* This driver also works for Davicom DM910{1,2} PHYs, which appear
* to be AM79c873 workalikes.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miidevs.h"
#include <dev/mii/amphyreg.h>
#include "miibus_if.h"
static int amphy_probe(device_t);
static int amphy_attach(device_t);
static device_method_t amphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, amphy_probe),
DEVMETHOD(device_attach, amphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{ 0, 0 }
};
static devclass_t amphy_devclass;
static driver_t amphy_driver = {
"amphy",
amphy_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(amphy, miibus, amphy_driver, amphy_devclass, 0, 0);
static int amphy_service(struct mii_softc *, struct mii_data *, int);
static void amphy_status(struct mii_softc *);
static const struct mii_phydesc amphys[] = {
MII_PHY_DESC(DAVICOM, DM9102),
MII_PHY_DESC(xxAMD, 79C873),
MII_PHY_DESC(xxDAVICOM, DM9101),
MII_PHY_END
};
static int
amphy_probe(device_t dev)
{
return (mii_phy_dev_probe(dev, amphys, BUS_PROBE_DEFAULT));
}
static int
amphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = amphy_service;
sc->mii_pdata = mii;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
#if 0
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
MII_MEDIA_100_TX);
#endif
mii_phy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " ");
mii_phy_add_media(sc);
printf("\n");
#undef ADD
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
}
static int
amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
switch (cmd) {
case MII_POLLSTAT:
break;
case MII_MEDIACHG:
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
mii_phy_setmedia(sc);
break;
case MII_TICK:
if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
}
/* Update the media status. */
amphy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
amphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int bmsr, bmcr, par, anlpar;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, MII_BMSR) |
PHY_READ(sc, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
return;
}
if (bmcr & BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
if (bmcr & BMCR_AUTOEN) {
/*
* The PAR status bits are only valid if autonegotiation
* has completed (or it's disabled).
*/
if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
if (PHY_READ(sc, MII_ANER) & ANER_LPAN) {
anlpar = PHY_READ(sc, MII_ANAR) &
PHY_READ(sc, MII_ANLPAR);
if (anlpar & ANLPAR_TX_FD)
mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4|IFM_HDX;
else if (anlpar & ANLPAR_TX)
mii->mii_media_active |= IFM_100_TX|IFM_HDX;
else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T|IFM_FDX;
else if (anlpar & ANLPAR_10)
mii->mii_media_active |= IFM_10_T|IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
return;
}
/*
* Link partner is not capable of autonegotiation.
*/
par = PHY_READ(sc, MII_AMPHY_DSCSR);
if (par & DSCSR_100FDX)
mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (par & DSCSR_100HDX)
mii->mii_media_active |= IFM_100_TX|IFM_HDX;
else if (par & DSCSR_10FDX)
mii->mii_media_active |= IFM_10_T|IFM_HDX;
else if (par & DSCSR_10HDX)
mii->mii_media_active |= IFM_10_T|IFM_HDX;
} else
mii->mii_media_active = ife->ifm_media;
}
@@ -0,0 +1,84 @@
/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/dev/mii/amphyreg.h,v 1.2.22.1.6.1 2010/12/21 17:09:25 kensmith Exp $
*/
#ifndef _DEV_MII_AMTPHYREG_H_
#define _DEV_MII_AMTPHYREG_H_
/*
* AMD Am79C873 registers.
*/
#define MII_AMPHY_DSCR 0x10 /* Specified configuration register */a
#define DSCR_BP4B5B 0x8000 /* Bypass 4B5B encoding */
#define DSCR_BPSCR 0x4000 /* Bypass scrambler */
#define DSCR_BPALIGN 0x2000 /* Bypass symbol alignment */
#define DSCR_REPEATER 0x0800 /* Repeater mode */
#define DSCR_TX 0x0400 /* TX/FX mode control */
#define DSCR_UTP 0x0200 /* UTP/STP mode control */
#define DSCR_CLK25MDIS 0x0100 /* CLK25M disable */
#define DSCR_FGLNKTX 0x0080 /* Force good link at 100baseTX */
#define DSCR_LINKLEDCTL 0x0020 /* Link LED control */
#define DSCR_FDXLEDCTL 0x0010 /* FDX LED control */
#define DSCR_SMRTS 0x0008 /* Reset state machine */
#define DSCR_MFPSC 0x0004 /* Preamble surpression control */
#define DSCR_SLEEP 0x0002 /* Sleep mode */
#define DSCR_RLOUT 0x0001 /* Remote loopout control */
#define MII_AMPHY_DSCSR 0x11 /* Specified configuration and status */
#define DSCSR_100FDX 0x8000 /* 100MBps full duplex */
#define DSCSR_100HDX 0x4000 /* 100Mbps half duplex */
#define DSCSR_10FDX 0x2000 /* 10Mbps full duplex */
#define DSCSR_10HDX 0x1000 /* 10Mbps half duplex */
#define DSCSR_PADDR 0x01F0 /* PHY address */
#define DSCSR_ASTAT 0x000F /* Autonegotiation status */
#define ASTAT_COMPLETE 0x8
#define ASTAT_PDLINK_READY_FAIL 0x7
#define ASTAT_PDLINK_READY 0x6
#define ASTAT_CONSTMATCH_FAIL 0x5
#define ASTAT_CONSTMATCH 0x4
#define ASTAT_ACKMATCH_FAIL 0x3
#define ASTAT_ACKMATCH 0x2
#define ASTAT_ABILITYMATCH 0x1
#define ASTAT_IDLE 0x0
#define MII_AMPHY_T10CSRSCR 0x12 /* 10baseT configuration/status */
#define T10CSRSCR_LPEN 0x4000 /* Link pulse enable */
#define T10CSRSCR_HBE 0x2000 /* Heartbeat enable */
#define T10CSRSCR_JABEN 0x0800 /* Jabber enable */
#define T10CSRSCR_SER 0x0400 /* Serial mode enable */
#define T10CSRSCR_POLR 0x0001 /* Polarity reversed */
#endif /* _DEV_MII_AMTPHYREG_H_ */
@@ -0,0 +1,421 @@
/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/dc/dcphy.c,v 1.35.2.5.2.1 2010/12/21 17:09:25 kensmith Exp $");
/*
* Pseudo-driver for internal NWAY support on DEC 21143 and workalike
* controllers. Technically we're abusing the miibus code to handle
* media selection and NWAY support here since there is no MII
* interface. However the logical operations are roughly the same,
* and the alternative is to create a fake MII interface in the driver,
* which is harder to do.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miidevs.h"
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <dev/pci/pcivar.h>
#include <dev/dc/if_dcreg.h>
#include "miibus_if.h"
#define DC_SETBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, \
CSR_READ_4(sc, reg) | x)
#define DC_CLRBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, \
CSR_READ_4(sc, reg) & ~x)
#define MIIF_AUTOTIMEOUT 0x0004
/*
* This is the subsystem ID for the built-in 21143 ethernet
* in several Compaq Presario systems. Apparently these are
* 10Mbps only, so we need to treat them specially.
*/
#define COMPAQ_PRESARIO_ID 0xb0bb0e11
static int dcphy_probe(device_t);
static int dcphy_attach(device_t);
static device_method_t dcphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, dcphy_probe),
DEVMETHOD(device_attach, dcphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{ 0, 0 }
};
static devclass_t dcphy_devclass;
static driver_t dcphy_driver = {
"dcphy",
dcphy_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(dcphy, miibus, dcphy_driver, dcphy_devclass, 0, 0);
static int dcphy_service(struct mii_softc *, struct mii_data *, int);
static void dcphy_status(struct mii_softc *);
static void dcphy_reset(struct mii_softc *);
static int dcphy_auto(struct mii_softc *);
static int
dcphy_probe(device_t dev)
{
struct mii_attach_args *ma;
ma = device_get_ivars(dev);
/*
* The dc driver will report the 21143 vendor and device
* ID to let us know that it wants us to attach.
*/
if (ma->mii_id1 != DC_VENDORID_DEC ||
ma->mii_id2 != DC_DEVICEID_21143)
return (ENXIO);
device_set_desc(dev, "Intel 21143 NWAY media interface");
return (BUS_PROBE_DEFAULT);
}
static int
dcphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
struct dc_softc *dc_sc;
device_t brdev;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = dcphy_service;
sc->mii_pdata = mii;
/*
* Apparently, we can neither isolate nor do loopback.
*/
sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
/*dcphy_reset(sc);*/
dc_sc = mii->mii_ifp->if_softc;
CSR_WRITE_4(dc_sc, DC_10BTSTAT, 0);
CSR_WRITE_4(dc_sc, DC_10BTCTRL, 0);
brdev = device_get_parent(sc->mii_dev);
switch (pci_get_subdevice(brdev) << 16 | pci_get_subvendor(brdev)) {
case COMPAQ_PRESARIO_ID:
/* Example of how to only allow 10Mbps modes. */
sc->mii_capabilities = BMSR_ANEG | BMSR_10TFDX | BMSR_10THDX;
break;
default:
if (dc_sc->dc_pmode == DC_PMODE_SIA)
sc->mii_capabilities =
BMSR_ANEG | BMSR_10TFDX | BMSR_10THDX;
else
sc->mii_capabilities =
BMSR_ANEG | BMSR_100TXFDX | BMSR_100TXHDX |
BMSR_10TFDX | BMSR_10THDX;
break;
}
sc->mii_capabilities &= ma->mii_capmask;
device_printf(dev, " ");
mii_phy_add_media(sc);
printf("\n");
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
}
static int
dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct dc_softc *dc_sc;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
u_int32_t mode;
dc_sc = mii->mii_ifp->if_softc;
switch (cmd) {
case MII_POLLSTAT:
break;
case MII_MEDIACHG:
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
mii->mii_media_active = IFM_NONE;
mode = CSR_READ_4(dc_sc, DC_NETCFG);
mode &= ~(DC_NETCFG_FULLDUPLEX | DC_NETCFG_PORTSEL |
DC_NETCFG_PCS | DC_NETCFG_SCRAMBLER | DC_NETCFG_SPEEDSEL);
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/*dcphy_reset(sc);*/
(void) dcphy_auto(sc);
break;
case IFM_100_T4:
/*
* XXX Not supported as a manual setting right now.
*/
return (EINVAL);
case IFM_100_TX:
dcphy_reset(sc);
DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
mode |= DC_NETCFG_PORTSEL | DC_NETCFG_PCS |
DC_NETCFG_SCRAMBLER;
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
mode |= DC_NETCFG_FULLDUPLEX;
else
mode &= ~DC_NETCFG_FULLDUPLEX;
CSR_WRITE_4(dc_sc, DC_NETCFG, mode);
break;
case IFM_10_T:
DC_CLRBIT(dc_sc, DC_SIARESET, DC_SIA_RESET);
DC_CLRBIT(dc_sc, DC_10BTCTRL, 0xFFFF);
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
DC_SETBIT(dc_sc, DC_10BTCTRL, 0x7F3D);
else
DC_SETBIT(dc_sc, DC_10BTCTRL, 0x7F3F);
DC_SETBIT(dc_sc, DC_SIARESET, DC_SIA_RESET);
DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
mode &= ~DC_NETCFG_PORTSEL;
mode |= DC_NETCFG_SPEEDSEL;
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
mode |= DC_NETCFG_FULLDUPLEX;
else
mode &= ~DC_NETCFG_FULLDUPLEX;
CSR_WRITE_4(dc_sc, DC_NETCFG, mode);
break;
default:
return (EINVAL);
}
break;
case MII_TICK:
/*
* Is the interface even up?
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0);
/*
* Only used for autonegotiation.
*/
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
break;
reg = CSR_READ_4(dc_sc, DC_10BTSTAT);
if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))
break;
/*
* Only retry autonegotiation every 5 seconds.
*
* Otherwise, fall through to calling dcphy_status()
* since real Intel 21143 chips don't show valid link
* status until autonegotiation is switched off, and
* that only happens in dcphy_status(). Without this,
* successful autonegotiation is never recognised on
* these chips.
*/
if (++sc->mii_ticks <= 50)
break;
sc->mii_ticks = 0;
dcphy_auto(sc);
break;
}
/* Update the media status. */
dcphy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
dcphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
int reg, anlpar, tstat = 0;
struct dc_softc *dc_sc;
dc_sc = mii->mii_ifp->if_softc;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return;
reg = CSR_READ_4(dc_sc, DC_10BTSTAT);
if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))
mii->mii_media_status |= IFM_ACTIVE;
if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL) {
/* Erg, still trying, I guess... */
tstat = CSR_READ_4(dc_sc, DC_10BTSTAT);
if ((tstat & DC_TSTAT_ANEGSTAT) != DC_ASTAT_AUTONEGCMP) {
if ((DC_IS_MACRONIX(dc_sc) || DC_IS_PNICII(dc_sc)) &&
(tstat & DC_TSTAT_ANEGSTAT) == DC_ASTAT_DISABLE)
goto skip;
mii->mii_media_active |= IFM_NONE;
return;
}
if (tstat & DC_TSTAT_LP_CAN_NWAY) {
anlpar = tstat >> 16;
if (anlpar & ANLPAR_TX_FD &&
sc->mii_capabilities & BMSR_100TXFDX)
mii->mii_media_active |= IFM_100_TX | IFM_FDX;
else if (anlpar & ANLPAR_T4 &&
sc->mii_capabilities & BMSR_100T4)
mii->mii_media_active |= IFM_100_T4 | IFM_HDX;
else if (anlpar & ANLPAR_TX &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_TX | IFM_HDX;
else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T | IFM_FDX;
else if (anlpar & ANLPAR_10)
mii->mii_media_active |= IFM_10_T | IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
if (DC_IS_INTEL(dc_sc))
DC_CLRBIT(dc_sc, DC_10BTCTRL,
DC_TCTL_AUTONEGENBL);
return;
}
/*
* If the other side doesn't support NWAY, then the
* best we can do is determine if we have a 10Mbps or
* 100Mbps link. There's no way to know if the link
* is full or half duplex, so we default to half duplex
* and hope that the user is clever enough to manually
* change the media settings if we're wrong.
*/
if (!(reg & DC_TSTAT_LS100))
mii->mii_media_active |= IFM_100_TX | IFM_HDX;
else if (!(reg & DC_TSTAT_LS10))
mii->mii_media_active |= IFM_10_T | IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
if (DC_IS_INTEL(dc_sc))
DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
return;
}
skip:
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;
else
mii->mii_media_active |= IFM_HDX;
}
static int
dcphy_auto(struct mii_softc *mii)
{
struct dc_softc *sc;
sc = mii->mii_pdata->mii_ifp->if_softc;
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
if (mii->mii_capabilities & BMSR_100TXHDX)
CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF);
else
CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFF);
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
DC_SETBIT(sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
DC_SETBIT(sc, DC_10BTSTAT, DC_ASTAT_TXDISABLE);
return (EJUSTRETURN);
}
static void
dcphy_reset(struct mii_softc *mii)
{
struct dc_softc *sc;
sc = mii->mii_pdata->mii_ifp->if_softc;
DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
DELAY(1000);
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
}
@@ -0,0 +1,241 @@
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/dc/pnphy.c,v 1.23.2.5.2.1 2010/12/21 17:09:25 kensmith Exp $");
/*
* Pseudo-driver for media selection on the Lite-On PNIC 82c168
* chip. The NWAY support on this chip is horribly broken, so we
* only support manual mode selection. This is lame, but getting
* NWAY to work right is amazingly difficult.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miidevs.h"
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <dev/dc/if_dcreg.h>
#include "miibus_if.h"
#define DC_SETBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, \
CSR_READ_4(sc, reg) | x)
#define DC_CLRBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, \
CSR_READ_4(sc, reg) & ~x)
static int pnphy_probe(device_t);
static int pnphy_attach(device_t);
static device_method_t pnphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, pnphy_probe),
DEVMETHOD(device_attach, pnphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{ 0, 0 }
};
static devclass_t pnphy_devclass;
static driver_t pnphy_driver = {
"pnphy",
pnphy_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(pnphy, miibus, pnphy_driver, pnphy_devclass, 0, 0);
static int pnphy_service(struct mii_softc *, struct mii_data *, int);
static void pnphy_status(struct mii_softc *);
static int
pnphy_probe(device_t dev)
{
struct mii_attach_args *ma;
ma = device_get_ivars(dev);
/*
* The dc driver will report the 82c168 vendor and device
* ID to let us know that it wants us to attach.
*/
if (ma->mii_id1 != DC_VENDORID_LO ||
ma->mii_id2 != DC_DEVICEID_82C168)
return (ENXIO);
device_set_desc(dev, "PNIC 82c168 media interface");
return (BUS_PROBE_DEFAULT);
}
static int
pnphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = pnphy_service;
sc->mii_pdata = mii;
/*
* Apparently, we can neither isolate nor do loopback.
*/
sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
sc->mii_capabilities =
BMSR_100TXFDX | BMSR_100TXHDX | BMSR_10TFDX | BMSR_10THDX;
sc->mii_capabilities &= ma->mii_capmask;
device_printf(dev, " ");
mii_phy_add_media(sc);
printf("\n");
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
}
static int
pnphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
switch (cmd) {
case MII_POLLSTAT:
break;
case MII_MEDIACHG:
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/* NWAY is busted on this chip */
case IFM_100_T4:
/*
* XXX Not supported as a manual setting right now.
*/
return (EINVAL);
case IFM_100_TX:
mii->mii_media_active = IFM_ETHER | IFM_100_TX;
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
mii->mii_media_active |= IFM_FDX;
MIIBUS_STATCHG(sc->mii_dev);
return (0);
case IFM_10_T:
mii->mii_media_active = IFM_ETHER | IFM_10_T;
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
mii->mii_media_active |= IFM_FDX;
MIIBUS_STATCHG(sc->mii_dev);
return (0);
default:
return (EINVAL);
}
break;
case MII_TICK:
/*
* Is the interface even up?
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0);
break;
}
/* Update the media status. */
pnphy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
pnphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
int reg;
struct dc_softc *dc_sc;
dc_sc = mii->mii_ifp->if_softc;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
reg = CSR_READ_4(dc_sc, DC_ISR);
if (!(reg & DC_ISR_LINKFAIL))
mii->mii_media_status |= IFM_ACTIVE;
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;
else
mii->mii_media_active |= IFM_HDX;
}
@@ -0,0 +1,186 @@
/* $NetBSD: ukphy.c,v 1.2 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center, and by Frank van der Linden.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 1997 Manuel Bouyer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.20.10.6.2.1 2010/12/21 17:09:25 kensmith Exp $");
/*
* driver for generic unknown PHYs
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miibus_if.h"
static int ukphy_probe(device_t);
static int ukphy_attach(device_t);
static device_method_t ukphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, ukphy_probe),
DEVMETHOD(device_attach, ukphy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{ 0, 0 }
};
static devclass_t ukphy_devclass;
static driver_t ukphy_driver = {
"ukphy",
ukphy_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(ukphy, miibus, ukphy_driver, ukphy_devclass, 0, 0);
static int ukphy_service(struct mii_softc *, struct mii_data *, int);
static int
ukphy_probe(device_t dev)
{
/*
* We know something is here, so always match at a low priority.
*/
device_set_desc(dev, "Generic IEEE 802.3u media interface");
return (BUS_PROBE_GENERIC);
}
static int
ukphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
if (bootverbose)
device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n",
MII_OUI(ma->mii_id1, ma->mii_id2),
MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2));
sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = ukphy_service;
sc->mii_pdata = mii;
sc->mii_flags |= MIIF_NOMANPAUSE;
mii_phy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_EXTSTAT)
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
device_printf(dev, " ");
mii_phy_add_media(sc);
printf("\n");
MIIBUS_MEDIAINIT(sc->mii_dev);
mii_phy_setmedia(sc);
return (0);
}
static int
ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
switch (cmd) {
case MII_POLLSTAT:
break;
case MII_MEDIACHG:
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
mii_phy_setmedia(sc);
break;
case MII_TICK:
if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
}
/* Update the media status. */
ukphy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
@@ -0,0 +1,129 @@
/* $NetBSD: ukphy_subr.c,v 1.2 1998/11/05 04:08:02 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center, and by Frank van der Linden.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy_subr.c,v 1.10.2.4.2.1 2010/12/21 17:09:25 kensmith Exp $");
/*
* Subroutines shared by the ukphy driver and other PHY drivers.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miibus_if.h"
/*
* Media status subroutine. If a PHY driver does media detection simply
* by decoding the NWay autonegotiation, use this routine.
*/
void
ukphy_status(struct mii_softc *phy)
{
struct mii_data *mii = phy->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int bmsr, bmcr, anlpar, gtcr, gtsr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(phy, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
return;
}
if (bmcr & BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
if (bmcr & BMCR_AUTOEN) {
/*
* NWay autonegotiation takes the highest-order common
* bit of the ANAR and ANLPAR (i.e. best media advertised
* both by us and our link partner).
*/
if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR);
if ((phy->mii_flags & MIIF_HAVE_GTCR) != 0 &&
(phy->mii_extcapabilities &
(EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) {
gtcr = PHY_READ(phy, MII_100T2CR);
gtsr = PHY_READ(phy, MII_100T2SR);
} else
gtcr = gtsr = 0;
if ((gtcr & GTCR_ADV_1000TFDX) && (gtsr & GTSR_LP_1000TFDX))
mii->mii_media_active |= IFM_1000_T|IFM_FDX;
else if ((gtcr & GTCR_ADV_1000THDX) &&
(gtsr & GTSR_LP_1000THDX))
mii->mii_media_active |= IFM_1000_T|IFM_HDX;
else if (anlpar & ANLPAR_TX_FD)
mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4|IFM_HDX;
else if (anlpar & ANLPAR_TX)
mii->mii_media_active |= IFM_100_TX|IFM_HDX;
else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T|IFM_FDX;
else if (anlpar & ANLPAR_10)
mii->mii_media_active |= IFM_10_T|IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
if ((mii->mii_media_active & IFM_1000_T) != 0 &&
(gtsr & GTSR_MS_RES) != 0)
mii->mii_media_active |= IFM_ETH_MASTER;
if ((mii->mii_media_active & IFM_FDX) != 0)
mii->mii_media_active |= mii_phy_flowstatus(phy);
} else
mii->mii_media_active = ife->ifm_media;
}
File diff suppressed because it is too large Load Diff
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $FreeBSD: src/sys/dev/fxp/if_fxpreg.h,v 1.39 2005/04/22 13:05:53 mux Exp $ * $FreeBSD: src/sys/dev/fxp/if_fxpreg.h,v 1.43.2.3.2.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
#define FXP_VENDORID_INTEL 0x8086 #define FXP_VENDORID_INTEL 0x8086
@@ -45,7 +45,9 @@
#define FXP_CSR_FLASHCONTROL 12 /* flash control (2 bytes) */ #define FXP_CSR_FLASHCONTROL 12 /* flash control (2 bytes) */
#define FXP_CSR_EEPROMCONTROL 14 /* eeprom control (2 bytes) */ #define FXP_CSR_EEPROMCONTROL 14 /* eeprom control (2 bytes) */
#define FXP_CSR_MDICONTROL 16 /* mdi control (4 bytes) */ #define FXP_CSR_MDICONTROL 16 /* mdi control (4 bytes) */
#define FXP_CSR_FLOWCONTROL 0x19 /* flow control (2 bytes) */ #define FXP_CSR_FC_THRESH 0x19 /* flow control (1 byte) */
#define FXP_CSR_FC_STATUS 0x1A /* flow control status (1 byte) */
#define FXP_CSR_PMDR 0x1B /* power management driver (1 byte) */
#define FXP_CSR_GENCONTROL 0x1C /* general control (1 byte) */ #define FXP_CSR_GENCONTROL 0x1C /* general control (1 byte) */
/* /*
@@ -223,7 +225,7 @@ struct fxp_cb_config {
/* Bytes 22 - 31 -- i82550 only */ /* Bytes 22 - 31 -- i82550 only */
u_int __FXP_BITFIELD3(gamla_rx:1, u_int __FXP_BITFIELD3(gamla_rx:1,
vlan_drop_en:1, vlan_strip_en:1,
:6); :6);
uint8_t pad[9]; uint8_t pad[9];
}; };
@@ -292,7 +294,7 @@ struct fxp_cb_tx {
*/ */
union { union {
struct fxp_ipcb ipcb; struct fxp_ipcb ipcb;
struct fxp_tbd tbd[FXP_NTXSEG]; struct fxp_tbd tbd[FXP_NTXSEG + 1];
} tx_cb_u; } tx_cb_u;
}; };
@@ -376,6 +378,7 @@ struct fxp_rfa {
#define FXP_RFA_STATUS_RNR 0x0200 /* no resources */ #define FXP_RFA_STATUS_RNR 0x0200 /* no resources */
#define FXP_RFA_STATUS_ALIGN 0x0400 /* alignment error */ #define FXP_RFA_STATUS_ALIGN 0x0400 /* alignment error */
#define FXP_RFA_STATUS_CRC 0x0800 /* CRC error */ #define FXP_RFA_STATUS_CRC 0x0800 /* CRC error */
#define FXP_RFA_STATUS_VLAN 0x1000 /* VLAN tagged frame */
#define FXP_RFA_STATUS_OK 0x2000 /* packet received okay */ #define FXP_RFA_STATUS_OK 0x2000 /* packet received okay */
#define FXP_RFA_STATUS_C 0x8000 /* packet reception complete */ #define FXP_RFA_STATUS_C 0x8000 /* packet reception complete */
#define FXP_RFA_CONTROL_SF 0x08 /* simple/flexible memory mode */ #define FXP_RFA_CONTROL_SF 0x08 /* simple/flexible memory mode */
@@ -416,7 +419,15 @@ struct fxp_stats {
uint32_t rx_overrun_errors; uint32_t rx_overrun_errors;
uint32_t rx_cdt_errors; uint32_t rx_cdt_errors;
uint32_t rx_shortframes; uint32_t rx_shortframes;
uint32_t tx_pause;
uint32_t rx_pause;
uint32_t rx_controls;
uint16_t tx_tco;
uint16_t rx_tco;
uint32_t completion_status; uint32_t completion_status;
uint32_t reserved0;
uint32_t reserved1;
uint32_t reserved2;
}; };
#define FXP_STATS_DUMP_COMPLETE 0xa005 #define FXP_STATS_DUMP_COMPLETE 0xa005
#define FXP_STATS_DR_COMPLETE 0xa007 #define FXP_STATS_DR_COMPLETE 0xa007
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $FreeBSD: src/sys/dev/fxp/if_fxpvar.h,v 1.40 2006/11/30 14:58:01 glebius Exp $ * $FreeBSD: src/sys/dev/fxp/if_fxpvar.h,v 1.49.2.4.2.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
/* /*
@@ -38,6 +38,12 @@
* This must be a power of two. * This must be a power of two.
*/ */
#define FXP_NTXCB 128 #define FXP_NTXCB 128
#define FXP_NTXCB_HIWAT ((FXP_NTXCB * 7) / 10)
/*
* Maximum size of a DMA segment.
*/
#define FXP_TSO_SEGSIZE 4096
/* /*
* Size of the TxCB list. * Size of the TxCB list.
@@ -136,6 +142,37 @@ struct fxp_desc_list {
bus_dma_tag_t rx_tag; bus_dma_tag_t rx_tag;
}; };
struct fxp_ident {
uint16_t devid;
int16_t revid; /* -1 matches anything */
uint8_t ich;
const char *name;
};
struct fxp_hwstats {
uint32_t tx_good;
uint32_t tx_maxcols;
uint32_t tx_latecols;
uint32_t tx_underruns;
uint32_t tx_lostcrs;
uint32_t tx_deffered;
uint32_t tx_single_collisions;
uint32_t tx_multiple_collisions;
uint32_t tx_total_collisions;
uint32_t tx_pause;
uint32_t tx_tco;
uint32_t rx_good;
uint32_t rx_crc_errors;
uint32_t rx_alignment_errors;
uint32_t rx_rnr_errors;
uint32_t rx_overrun_errors;
uint32_t rx_cdt_errors;
uint32_t rx_shortframes;
uint32_t rx_pause;
uint32_t rx_controls;
uint32_t rx_tco;
};
/* /*
* NOTE: Elements are ordered for optimal cacheline behavior, and NOT * NOTE: Elements are ordered for optimal cacheline behavior, and NOT
* for functional grouping. * for functional grouping.
@@ -145,8 +182,10 @@ struct fxp_softc {
struct resource *fxp_res[2]; /* I/O and IRQ resources */ struct resource *fxp_res[2]; /* I/O and IRQ resources */
struct resource_spec *fxp_spec; /* the resource spec we used */ struct resource_spec *fxp_spec; /* the resource spec we used */
void *ih; /* interrupt handler cookie */ void *ih; /* interrupt handler cookie */
const struct fxp_ident *ident;
struct mtx sc_mtx; struct mtx sc_mtx;
bus_dma_tag_t fxp_mtag; /* bus DMA tag for mbufs */ bus_dma_tag_t fxp_txmtag; /* bus DMA tag for Tx mbufs */
bus_dma_tag_t fxp_rxmtag; /* bus DMA tag for Rx mbufs */
bus_dma_tag_t fxp_stag; /* bus DMA tag for stats */ bus_dma_tag_t fxp_stag; /* bus DMA tag for stats */
bus_dmamap_t fxp_smap; /* bus DMA map for stats */ bus_dmamap_t fxp_smap; /* bus DMA map for stats */
bus_dma_tag_t cbl_tag; /* DMA tag for the TxCB list */ bus_dma_tag_t cbl_tag; /* DMA tag for the TxCB list */
@@ -156,10 +195,11 @@ struct fxp_softc {
bus_dmamap_t spare_map; /* spare DMA map */ bus_dmamap_t spare_map; /* spare DMA map */
struct fxp_desc_list fxp_desc; /* descriptors management struct */ struct fxp_desc_list fxp_desc; /* descriptors management struct */
int maxtxseg; /* maximum # of TX segments */ int maxtxseg; /* maximum # of TX segments */
int maxsegsize; /* maximum size of a TX segment */
int tx_queued; /* # of active TxCB's */ int tx_queued; /* # of active TxCB's */
int need_mcsetup; /* multicast filter needs programming */
struct fxp_stats *fxp_stats; /* Pointer to interface stats */ struct fxp_stats *fxp_stats; /* Pointer to interface stats */
uint32_t stats_addr; /* DMA address of the stats structure */ uint32_t stats_addr; /* DMA address of the stats structure */
struct fxp_hwstats fxp_hwstats;
int rx_idle_secs; /* # of seconds RX has been idle */ int rx_idle_secs; /* # of seconds RX has been idle */
struct callout stat_ch; /* stat callout */ struct callout stat_ch; /* stat callout */
int watchdog_timer; /* seconds until chip reset */ int watchdog_timer; /* seconds until chip reset */
@@ -170,13 +210,13 @@ struct fxp_softc {
device_t dev; device_t dev;
int tunable_int_delay; /* interrupt delay value for ucode */ int tunable_int_delay; /* interrupt delay value for ucode */
int tunable_bundle_max; /* max # frames per interrupt (ucode) */ int tunable_bundle_max; /* max # frames per interrupt (ucode) */
int tunable_noflow; /* flow control disabled */
int rnr; /* RNR events */ int rnr; /* RNR events */
int eeprom_size; /* size of serial EEPROM */ int eeprom_size; /* size of serial EEPROM */
int suspended; /* 0 = normal 1 = suspended or dead */ int suspended; /* 0 = normal 1 = suspended or dead */
int cu_resume_bug; int cu_resume_bug;
int revision; int revision;
int flags; int flags;
int if_flags;
uint8_t rfa_size; uint8_t rfa_size;
uint32_t tx_cmd; uint32_t tx_cmd;
}; };
@@ -187,12 +227,15 @@ struct fxp_softc {
#define FXP_FLAG_EXT_TXCB 0x0008 /* enable use of extended TXCB */ #define FXP_FLAG_EXT_TXCB 0x0008 /* enable use of extended TXCB */
#define FXP_FLAG_SERIAL_MEDIA 0x0010 /* 10Mbps serial interface */ #define FXP_FLAG_SERIAL_MEDIA 0x0010 /* 10Mbps serial interface */
#define FXP_FLAG_LONG_PKT_EN 0x0020 /* enable long packet reception */ #define FXP_FLAG_LONG_PKT_EN 0x0020 /* enable long packet reception */
#define FXP_FLAG_ALL_MCAST 0x0040 /* accept all multicast frames */
#define FXP_FLAG_CU_RESUME_BUG 0x0080 /* requires workaround for CU_RESUME */ #define FXP_FLAG_CU_RESUME_BUG 0x0080 /* requires workaround for CU_RESUME */
#define FXP_FLAG_UCODE 0x0100 /* ucode is loaded */ #define FXP_FLAG_UCODE 0x0100 /* ucode is loaded */
#define FXP_FLAG_DEFERRED_RNR 0x0200 /* DEVICE_POLLING deferred RNR */ #define FXP_FLAG_DEFERRED_RNR 0x0200 /* DEVICE_POLLING deferred RNR */
#define FXP_FLAG_EXT_RFA 0x0400 /* extended RFDs for csum offload */ #define FXP_FLAG_EXT_RFA 0x0400 /* extended RFDs for csum offload */
#define FXP_FLAG_SAVE_BAD 0x0800 /* save bad pkts: bad size, CRC, etc */ #define FXP_FLAG_SAVE_BAD 0x0800 /* save bad pkts: bad size, CRC, etc */
#define FXP_FLAG_82559_RXCSUM 0x1000 /* 82559 compatible RX checksum */
#define FXP_FLAG_WOLCAP 0x2000 /* WOL capability */
#define FXP_FLAG_WOL 0x4000 /* WOL active */
#define FXP_FLAG_RXBUG 0x8000 /* Rx lock-up bug */
/* Macros to ease CSR access. */ /* Macros to ease CSR access. */
#define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg) #define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg)
@@ -29,7 +29,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* /*
* $FreeBSD: src/sys/dev/fxp/rcvbundl.h,v 1.3 2005/04/21 19:34:57 mux Exp $ * $FreeBSD: src/sys/dev/fxp/rcvbundl.h,v 1.3.22.1.6.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
/* /*
rcvbundl.h rcvbundl.h
@@ -29,7 +29,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/inphy.c,v 1.17 2007/01/12 22:27:46 marius Exp $"); __FBSDID("$FreeBSD: src/sys/dev/mii/inphy.c,v 1.17.10.7.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* driver for Intel 82553 and 82555 PHYs * driver for Intel 82553 and 82555 PHYs
@@ -77,6 +77,7 @@ DRIVER_MODULE(inphy, miibus, inphy_driver, inphy_devclass, 0, 0);
static int inphy_service(struct mii_softc *, struct mii_data *, int); static int inphy_service(struct mii_softc *, struct mii_data *, int);
static void inphy_status(struct mii_softc *); static void inphy_status(struct mii_softc *);
static void inphy_reset(struct mii_softc *);
static const struct mii_phydesc inphys[] = { static const struct mii_phydesc inphys[] = {
MII_PHY_DESC(INTEL, I82553C), MII_PHY_DESC(INTEL, I82553C),
@@ -104,20 +105,22 @@ inphy_attach(device_t dev)
sc = device_get_softc(dev); sc = device_get_softc(dev);
ma = device_get_ivars(dev); ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev); sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev); mii = ma->mii_data;
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_inst = mii->mii_instance; sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno; sc->mii_phy = ma->mii_phyno;
sc->mii_service = inphy_service; sc->mii_service = inphy_service;
sc->mii_pdata = mii; sc->mii_pdata = mii;
mii->mii_instance++;
sc->mii_flags |= MIIF_NOMANPAUSE;
ifmedia_add(&mii->mii_media, ifmedia_add(&mii->mii_media,
IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
MII_MEDIA_100_TX, NULL); MII_MEDIA_100_TX, NULL);
mii_phy_reset(sc); inphy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " "); device_printf(dev, " ");
@@ -132,22 +135,12 @@ inphy_attach(device_t dev)
static int static int
inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{ {
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) { switch (cmd) {
case MII_POLLSTAT: case MII_POLLSTAT:
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break; break;
case MII_MEDIACHG: case MII_MEDIACHG:
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, MII_BMCR);
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
/* /*
* If the interface is not up, don't do anything. * If the interface is not up, don't do anything.
*/ */
@@ -158,8 +151,6 @@ inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break; break;
case MII_TICK: case MII_TICK:
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
if (mii_phy_tick(sc) == EJUSTRETURN) if (mii_phy_tick(sc) == EJUSTRETURN)
return (0); return (0);
break; break;
@@ -209,7 +200,21 @@ inphy_status(struct mii_softc *sc)
else else
mii->mii_media_active |= IFM_10_T; mii->mii_media_active |= IFM_10_T;
if (scr & SCR_FDX) if (scr & SCR_FDX)
mii->mii_media_active |= IFM_FDX; mii->mii_media_active |=
IFM_FDX | mii_phy_flowstatus(sc);
else
mii->mii_media_active |= IFM_HDX;
} else } else
mii->mii_media_active = ife->ifm_media; mii->mii_media_active = ife->ifm_media;
} }
static void
inphy_reset(struct mii_softc *sc)
{
mii_phy_reset(sc);
/* Ensure Bay flow control is disabled. */
PHY_WRITE(sc, MII_INPHY_SCR,
PHY_READ(sc, MII_INPHY_SCR) & ~SCR_FLOWCTL);
}
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $FreeBSD: src/sys/dev/mii/inphyreg.h,v 1.1 2001/03/12 02:41:57 jlemon Exp $ * $FreeBSD: src/sys/dev/mii/inphyreg.h,v 1.1.38.1.6.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
#define MII_INPHY_SCR 0x10 /* status and control register */ #define MII_INPHY_SCR 0x10 /* status and control register */
@@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/mii/rlphy.c,v 1.31 2007/06/06 07:07:23 yongari Exp $"); __FBSDID("$FreeBSD: src/sys/dev/mii/rlphy.c,v 1.32.2.5.2.1 2010/12/21 17:09:25 kensmith Exp $");
/* /*
* driver for RealTek 8139 internal PHYs * driver for RealTek 8139 internal PHYs
@@ -109,8 +109,13 @@ rlphy_probe(device_t dev)
int rv; int rv;
rv = mii_phy_dev_probe(dev, rlphys, BUS_PROBE_DEFAULT); rv = mii_phy_dev_probe(dev, rlphys, BUS_PROBE_DEFAULT);
#ifdef __HAIKU__
if (rv == BUS_PROBE_DEFAULT) if (rv == BUS_PROBE_DEFAULT)
return (rv); return (rv);
#else
if (rv <= 0)
return (rv);
#endif
nic = device_get_name(device_get_parent(device_get_parent(dev))); nic = device_get_name(device_get_parent(device_get_parent(dev)));
if (strcmp(nic, "rl") == 0 || strcmp(nic, "re") == 0) if (strcmp(nic, "rl") == 0 || strcmp(nic, "re") == 0)
@@ -129,7 +134,7 @@ rlphy_attach(device_t dev)
sc = device_get_softc(dev); sc = device_get_softc(dev);
ma = device_get_ivars(dev); ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev); sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev); mii = ma->mii_data;
/* /*
* Check whether we're the RTL8201L PHY and remember so the status * Check whether we're the RTL8201L PHY and remember so the status
@@ -139,23 +144,17 @@ rlphy_attach(device_t dev)
if (mii_phy_dev_probe(dev, rlphys, 0) == 0) if (mii_phy_dev_probe(dev, rlphys, 0) == 0)
rsc->sc_is_RTL8201L++; rsc->sc_is_RTL8201L++;
/*
* The RealTek PHY can never be isolated, so never allow non-zero
* instances!
*/
if (mii->mii_instance != 0) {
device_printf(dev, "ignoring this PHY, non-zero instance\n");
return (ENXIO);
}
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_inst = mii->mii_instance; sc->mii_flags = miibus_get_flags(dev);
sc->mii_inst = mii->mii_instance++;
sc->mii_phy = ma->mii_phyno; sc->mii_phy = ma->mii_phyno;
sc->mii_service = rlphy_service; sc->mii_service = rlphy_service;
sc->mii_pdata = mii; sc->mii_pdata = mii;
mii->mii_instance++;
/*
* The RealTek PHY can never be isolated.
*/
sc->mii_flags |= MIIF_NOISOLATE; sc->mii_flags |= MIIF_NOISOLATE;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
@@ -165,8 +164,7 @@ rlphy_attach(device_t dev)
mii_phy_reset(sc); mii_phy_reset(sc);
sc->mii_capabilities = sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " "); device_printf(dev, " ");
mii_phy_add_media(sc); mii_phy_add_media(sc);
printf("\n"); printf("\n");
@@ -178,13 +176,6 @@ rlphy_attach(device_t dev)
static int static int
rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{ {
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
/*
* We can't isolate the RealTek PHY, so it has to be the only one!
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
panic("rlphy_service: can't isolate RealTek PHY");
switch (cmd) { switch (cmd) {
case MII_POLLSTAT: case MII_POLLSTAT:
@@ -261,16 +252,16 @@ rlphy_status(struct mii_softc *phy)
if ((anlpar = PHY_READ(phy, MII_ANAR) & if ((anlpar = PHY_READ(phy, MII_ANAR) &
PHY_READ(phy, MII_ANLPAR))) { PHY_READ(phy, MII_ANLPAR))) {
if (anlpar & ANLPAR_T4) if (anlpar & ANLPAR_TX_FD)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD)
mii->mii_media_active |= IFM_100_TX|IFM_FDX; mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4|IFM_HDX;
else if (anlpar & ANLPAR_TX) else if (anlpar & ANLPAR_TX)
mii->mii_media_active |= IFM_100_TX; mii->mii_media_active |= IFM_100_TX|IFM_HDX;
else if (anlpar & ANLPAR_10_FD) else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T|IFM_FDX; mii->mii_media_active |= IFM_10_T|IFM_FDX;
else if (anlpar & ANLPAR_10) else if (anlpar & ANLPAR_10)
mii->mii_media_active |= IFM_10_T; mii->mii_media_active |= IFM_10_T|IFM_HDX;
else else
mii->mii_media_active |= IFM_NONE; mii->mii_media_active |= IFM_NONE;
return; return;
@@ -314,6 +305,7 @@ rlphy_status(struct mii_softc *phy)
else else
mii->mii_media_active |= IFM_100_TX; mii->mii_media_active |= IFM_100_TX;
} }
mii->mii_media_active |= IFM_HDX;
} else } else
mii->mii_media_active = ife->ifm_media; mii->mii_media_active = ife->ifm_media;
} }
File diff suppressed because it is too large Load Diff
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
* *
* $FreeBSD: src/sys/pci/if_rlreg.h,v 1.67.2.2 2007/12/15 02:57:18 yongari Exp $ * $FreeBSD: src/sys/pci/if_rlreg.h,v 1.97.2.8.2.1 2010/12/21 17:09:25 kensmith Exp $
*/ */
/* /*
@@ -76,7 +76,11 @@
#define RL_EECMD 0x0050 /* EEPROM command register */ #define RL_EECMD 0x0050 /* EEPROM command register */
#define RL_CFG0 0x0051 /* config register #0 */ #define RL_CFG0 0x0051 /* config register #0 */
#define RL_CFG1 0x0052 /* config register #1 */ #define RL_CFG1 0x0052 /* config register #1 */
/* 0053-0057 reserved */ #define RL_CFG2 0x0053 /* config register #2 */
#define RL_CFG3 0x0054 /* config register #3 */
#define RL_CFG4 0x0055 /* config register #4 */
#define RL_CFG5 0x0056 /* config register #5 */
/* 0057 reserved */
#define RL_MEDIASTAT 0x0058 /* media status register (8139) */ #define RL_MEDIASTAT 0x0058 /* media status register (8139) */
/* 0059-005A reserved */ /* 0059-005A reserved */
#define RL_MII 0x005A /* 8129 chip only */ #define RL_MII 0x005A /* 8129 chip only */
@@ -121,14 +125,18 @@
/* /*
* Registers specific to the 8169 gigE chip * Registers specific to the 8169 gigE chip
*/ */
#define RL_GTXSTART 0x0038 /* 8 bits */
#define RL_TIMERINT_8169 0x0058 /* different offset than 8139 */ #define RL_TIMERINT_8169 0x0058 /* different offset than 8139 */
#define RL_PHYAR 0x0060 #define RL_PHYAR 0x0060
#define RL_TBICSR 0x0064 #define RL_TBICSR 0x0064
#define RL_TBI_ANAR 0x0068 #define RL_TBI_ANAR 0x0068
#define RL_TBI_LPAR 0x006A #define RL_TBI_LPAR 0x006A
#define RL_GMEDIASTAT 0x006C /* 8 bits */ #define RL_GMEDIASTAT 0x006C /* 8 bits */
#define RL_MACDBG 0x006D /* 8 bits, 8168C SPIN2 only */
#define RL_GPIO 0x006E /* 8 bits, 8168C SPIN2 only */
#define RL_PMCH 0x006F /* 8 bits */
#define RL_MAXRXPKTLEN 0x00DA /* 16 bits, chip multiplies by 8 */ #define RL_MAXRXPKTLEN 0x00DA /* 16 bits, chip multiplies by 8 */
#define RL_GTXSTART 0x0038 /* 16 bits */ #define RL_INTRMOD 0x00E2 /* 16 bits */
/* /*
* TX config register bits * TX config register bits
@@ -148,15 +156,25 @@
/* Known revision codes. */ /* Known revision codes. */
#define RL_HWREV_8169 0x00000000 #define RL_HWREV_8169 0x00000000
#define RL_HWREV_8110S 0x00800000 #define RL_HWREV_8169S 0x00800000
#define RL_HWREV_8169S 0x04000000 #define RL_HWREV_8110S 0x04000000
#define RL_HWREV_8169_8110SB 0x10000000 #define RL_HWREV_8169_8110SB 0x10000000
#define RL_HWREV_8169_8110SC 0x18000000 #define RL_HWREV_8169_8110SC 0x18000000
#define RL_HWREV_8102EL 0x24800000
#define RL_HWREV_8102EL_SPIN1 0x24C00000
#define RL_HWREV_8168D 0x28000000
#define RL_HWREV_8168DP 0x28800000
#define RL_HWREV_8168E 0x2C000000
#define RL_HWREV_8168_SPIN1 0x30000000 #define RL_HWREV_8168_SPIN1 0x30000000
#define RL_HWREV_8100E 0x30800000 #define RL_HWREV_8100E 0x30800000
#define RL_HWREV_8101E 0x34000000 #define RL_HWREV_8101E 0x34000000
#define RL_HWREV_8102E 0x34800000
#define RL_HWREV_8103E 0x34C00000
#define RL_HWREV_8168_SPIN2 0x38000000 #define RL_HWREV_8168_SPIN2 0x38000000
#define RL_HWREV_8168_SPIN3 0x38400000 #define RL_HWREV_8168_SPIN3 0x38400000
#define RL_HWREV_8168C 0x3C000000
#define RL_HWREV_8168C_SPIN2 0x3C400000
#define RL_HWREV_8168CP 0x3C800000
#define RL_HWREV_8139 0x60000000 #define RL_HWREV_8139 0x60000000
#define RL_HWREV_8139A 0x70000000 #define RL_HWREV_8139A 0x70000000
#define RL_HWREV_8139AG 0x70800000 #define RL_HWREV_8139AG 0x70800000
@@ -165,8 +183,10 @@
#define RL_HWREV_8139C 0x74000000 #define RL_HWREV_8139C 0x74000000
#define RL_HWREV_8139D 0x74400000 #define RL_HWREV_8139D 0x74400000
#define RL_HWREV_8139CPLUS 0x74800000 #define RL_HWREV_8139CPLUS 0x74800000
#define RL_HWREV_8101 0x74c00000 #define RL_HWREV_8101 0x74C00000
#define RL_HWREV_8100 0x78800000 #define RL_HWREV_8100 0x78800000
#define RL_HWREV_8169_8110SBL 0x7CC00000
#define RL_HWREV_8169_8110SCE 0x98000000
#define RL_TXDMA_16BYTES 0x00000000 #define RL_TXDMA_16BYTES 0x00000000
#define RL_TXDMA_32BYTES 0x00000100 #define RL_TXDMA_32BYTES 0x00000100
@@ -297,7 +317,29 @@
#define RL_CMD_TX_ENB 0x0004 #define RL_CMD_TX_ENB 0x0004
#define RL_CMD_RX_ENB 0x0008 #define RL_CMD_RX_ENB 0x0008
#define RL_CMD_RESET 0x0010 #define RL_CMD_RESET 0x0010
#define RL_CMD_STOPREQ 0x0080
/*
* Twister register values. These are completely undocumented and derived
* from public sources.
*/
#define RL_CSCFG_LINK_OK 0x0400
#define RL_CSCFG_CHANGE 0x0800
#define RL_CSCFG_STATUS 0xf000
#define RL_CSCFG_ROW3 0x7000
#define RL_CSCFG_ROW2 0x3000
#define RL_CSCFG_ROW1 0x1000
#define RL_CSCFG_LINK_DOWN_OFF_CMD 0x03c0
#define RL_CSCFG_LINK_DOWN_CMD 0xf3c0
#define RL_NWAYTST_RESET 0
#define RL_NWAYTST_CBL_TEST 0x20
#define RL_PARA78 0x78
#define RL_PARA78_DEF 0x78fa8388
#define RL_PARA7C 0x7C
#define RL_PARA7C_DEF 0xcb38de43
#define RL_PARA7C_RETUNE 0xfb38de03
/* /*
* EEPROM control register * EEPROM control register
*/ */
@@ -359,15 +401,50 @@
* Config 1 register * Config 1 register
*/ */
#define RL_CFG1_PWRDWN 0x01 #define RL_CFG1_PWRDWN 0x01
#define RL_CFG1_PME 0x01
#define RL_CFG1_SLEEP 0x02 #define RL_CFG1_SLEEP 0x02
#define RL_CFG1_VPDEN 0x02
#define RL_CFG1_IOMAP 0x04 #define RL_CFG1_IOMAP 0x04
#define RL_CFG1_MEMMAP 0x08 #define RL_CFG1_MEMMAP 0x08
#define RL_CFG1_RSVD 0x10 #define RL_CFG1_RSVD 0x10
#define RL_CFG1_LWACT 0x10
#define RL_CFG1_DRVLOAD 0x20 #define RL_CFG1_DRVLOAD 0x20
#define RL_CFG1_LED0 0x40 #define RL_CFG1_LED0 0x40
#define RL_CFG1_FULLDUPLEX 0x40 /* 8129 only */ #define RL_CFG1_FULLDUPLEX 0x40 /* 8129 only */
#define RL_CFG1_LED1 0x80 #define RL_CFG1_LED1 0x80
/*
* Config 2 register
*/
#define RL_CFG2_PCI33MHZ 0x00
#define RL_CFG2_PCI66MHZ 0x01
#define RL_CFG2_PCI64BIT 0x08
#define RL_CFG2_AUXPWR 0x10
#define RL_CFG2_MSI 0x20
/*
* Config 3 register
*/
#define RL_CFG3_GRANTSEL 0x80
#define RL_CFG3_WOL_MAGIC 0x20
#define RL_CFG3_WOL_LINK 0x10
#define RL_CFG3_FAST_B2B 0x01
/*
* Config 4 register
*/
#define RL_CFG4_LWPTN 0x04
#define RL_CFG4_LWPME 0x10
/*
* Config 5 register
*/
#define RL_CFG5_WOL_BCAST 0x40
#define RL_CFG5_WOL_MCAST 0x20
#define RL_CFG5_WOL_UCAST 0x10
#define RL_CFG5_WOL_LANWAKE 0x02
#define RL_CFG5_PME_STS 0x01
/* /*
* 8139C+ register definitions * 8139C+ register definitions
*/ */
@@ -403,6 +480,15 @@
#define RL_CPLUSCMD_PCI_DAC 0x0010 /* PCI dual-address cycle only */ #define RL_CPLUSCMD_PCI_DAC 0x0010 /* PCI dual-address cycle only */
#define RL_CPLUSCMD_RXCSUM_ENB 0x0020 /* enable RX checksum offload */ #define RL_CPLUSCMD_RXCSUM_ENB 0x0020 /* enable RX checksum offload */
#define RL_CPLUSCMD_VLANSTRIP 0x0040 /* enable VLAN tag stripping */ #define RL_CPLUSCMD_VLANSTRIP 0x0040 /* enable VLAN tag stripping */
#define RL_CPLUSCMD_MACSTAT_DIS 0x0080 /* 8168B/C/CP */
#define RL_CPLUSCMD_ASF 0x0100 /* 8168C/CP */
#define RL_CPLUSCMD_DBG_SEL 0x0200 /* 8168C/CP */
#define RL_CPLUSCMD_FORCE_TXFC 0x0400 /* 8168C/CP */
#define RL_CPLUSCMD_FORCE_RXFC 0x0800 /* 8168C/CP */
#define RL_CPLUSCMD_FORCE_HDPX 0x1000 /* 8168C/CP */
#define RL_CPLUSCMD_NORMAL_MODE 0x2000 /* 8168C/CP */
#define RL_CPLUSCMD_DBG_ENB 0x4000 /* 8168C/CP */
#define RL_CPLUSCMD_BIST_ENB 0x8000 /* 8168C/CP */
/* C+ early transmit threshold */ /* C+ early transmit threshold */
@@ -447,6 +533,11 @@
#define RL_RXBUFLEN (1 << ((RL_RX_BUF_SZ >> 11) + 13)) #define RL_RXBUFLEN (1 << ((RL_RX_BUF_SZ >> 11) + 13))
#define RL_TX_LIST_CNT 4 #define RL_TX_LIST_CNT 4
#define RL_MIN_FRAMELEN 60 #define RL_MIN_FRAMELEN 60
#define RL_TX_8139_BUF_ALIGN 4
#define RL_RX_8139_BUF_ALIGN 8
#define RL_RX_8139_BUF_RESERVE sizeof(int64_t)
#define RL_RX_8139_BUF_GUARD_SZ \
(ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + RL_RX_8139_BUF_RESERVE)
#define RL_TXTHRESH(x) ((x) << 11) #define RL_TXTHRESH(x) ((x) << 11)
#define RL_TX_THRESH_INIT 96 #define RL_TX_THRESH_INIT 96
#define RL_RX_FIFOTHRESH RL_RXFIFO_NOTHRESH #define RL_RX_FIFOTHRESH RL_RXFIFO_NOTHRESH
@@ -458,14 +549,23 @@
#define RL_ETHER_ALIGN 2 #define RL_ETHER_ALIGN 2
/*
* re(4) hardware ip4csum-tx could be mangled with 28 bytes or less IP packets.
*/
#define RL_IP4CSUMTX_MINLEN 28
#define RL_IP4CSUMTX_PADLEN (ETHER_HDR_LEN + RL_IP4CSUMTX_MINLEN)
struct rl_chain_data { struct rl_chain_data {
uint16_t cur_rx; uint16_t cur_rx;
uint8_t *rl_rx_buf; uint8_t *rl_rx_buf;
uint8_t *rl_rx_buf_ptr; uint8_t *rl_rx_buf_ptr;
bus_dmamap_t rl_rx_dmamap;
struct mbuf *rl_tx_chain[RL_TX_LIST_CNT]; struct mbuf *rl_tx_chain[RL_TX_LIST_CNT];
bus_dmamap_t rl_tx_dmamap[RL_TX_LIST_CNT]; bus_dmamap_t rl_tx_dmamap[RL_TX_LIST_CNT];
bus_dma_tag_t rl_tx_tag;
bus_dma_tag_t rl_rx_tag;
bus_dmamap_t rl_rx_dmamap;
bus_addr_t rl_rx_buf_paddr;
uint8_t last_tx; uint8_t last_tx;
uint8_t cur_tx; uint8_t cur_tx;
}; };
@@ -553,6 +653,10 @@ struct rl_desc {
#define RL_TDESC_VLANCTL_TAG 0x00020000 /* Insert VLAN tag */ #define RL_TDESC_VLANCTL_TAG 0x00020000 /* Insert VLAN tag */
#define RL_TDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */ #define RL_TDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */
/* RTL8168C/RTL8168CP/RTL8111C/RTL8111CP */
#define RL_TDESC_CMD_UDPCSUMV2 0x80000000
#define RL_TDESC_CMD_TCPCSUMV2 0x40000000
#define RL_TDESC_CMD_IPCSUMV2 0x20000000
/* /*
* Error bits are valid only on the last descriptor of a frame * Error bits are valid only on the last descriptor of a frame
@@ -590,6 +694,8 @@ struct rl_desc {
#define RL_RDESC_STAT_RUNT 0x00080000 /* runt packet received */ #define RL_RDESC_STAT_RUNT 0x00080000 /* runt packet received */
#define RL_RDESC_STAT_CRCERR 0x00040000 /* CRC error */ #define RL_RDESC_STAT_CRCERR 0x00040000 /* CRC error */
#define RL_RDESC_STAT_PROTOID 0x00030000 /* Protocol type */ #define RL_RDESC_STAT_PROTOID 0x00030000 /* Protocol type */
#define RL_RDESC_STAT_UDP 0x00020000 /* UDP, 8168C/CP, 8111C/CP */
#define RL_RDESC_STAT_TCP 0x00010000 /* TCP, 8168C/CP, 8111C/CP */
#define RL_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */ #define RL_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */
#define RL_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */ #define RL_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */
#define RL_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */ #define RL_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */
@@ -601,6 +707,9 @@ struct rl_desc {
#define RL_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available #define RL_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available
(rl_vlandata valid)*/ (rl_vlandata valid)*/
#define RL_RDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */ #define RL_RDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */
/* RTL8168C/RTL8168CP/RTL8111C/RTL8111CP */
#define RL_RDESC_IPV6 0x80000000
#define RL_RDESC_IPV4 0x40000000
#define RL_PROTOID_NONIP 0x00000000 #define RL_PROTOID_NONIP 0x00000000
#define RL_PROTOID_TCPIP 0x00010000 #define RL_PROTOID_TCPIP 0x00010000
@@ -615,19 +724,16 @@ struct rl_desc {
* Statistics counter structure (8139C+ and 8169 only) * Statistics counter structure (8139C+ and 8169 only)
*/ */
struct rl_stats { struct rl_stats {
uint32_t rl_tx_pkts_lo; uint64_t rl_tx_pkts;
uint32_t rl_tx_pkts_hi; uint64_t rl_rx_pkts;
uint32_t rl_tx_errs_lo; uint64_t rl_tx_errs;
uint32_t rl_tx_errs_hi; uint32_t rl_rx_errs;
uint32_t rl_tx_errs;
uint16_t rl_missed_pkts; uint16_t rl_missed_pkts;
uint16_t rl_rx_framealign_errs; uint16_t rl_rx_framealign_errs;
uint32_t rl_tx_onecoll; uint32_t rl_tx_onecoll;
uint32_t rl_tx_multicolls; uint32_t rl_tx_multicolls;
uint32_t rl_rx_ucasts_hi; uint64_t rl_rx_ucasts;
uint32_t rl_rx_ucasts_lo; uint64_t rl_rx_bcasts;
uint32_t rl_rx_bcasts_lo;
uint32_t rl_rx_bcasts_hi;
uint32_t rl_rx_mcasts; uint32_t rl_rx_mcasts;
uint16_t rl_tx_aborts; uint16_t rl_tx_aborts;
uint16_t rl_rx_underruns; uint16_t rl_rx_underruns;
@@ -636,24 +742,36 @@ struct rl_stats {
/* /*
* Rx/Tx descriptor parameters (8139C+ and 8169 only) * Rx/Tx descriptor parameters (8139C+ and 8169 only)
* *
* Tx/Rx count must be equal. Shared code like re_dma_map_desc assumes this. * 8139C+
* Buffers must be a multiple of 8 bytes. Currently limit to 64 descriptors * Number of descriptors supported : up to 64
* due to the 8139C+. We need to put the number of descriptors in the ring * Descriptor alignment : 256 bytes
* structure and use that value instead. * Tx buffer : At least 4 bytes in length.
* Rx buffer : At least 8 bytes in length and 8 bytes alignment required.
*
* 8169
* Number of descriptors supported : up to 1024
* Descriptor alignment : 256 bytes
* Tx buffer : At least 4 bytes in length.
* Rx buffer : At least 8 bytes in length and 8 bytes alignment required.
*/ */
#ifndef __NO_STRICT_ALIGNMENT #ifndef __NO_STRICT_ALIGNMENT
#define RE_FIXUP_RX 1 #define RE_FIXUP_RX 1
#endif #endif
#define RL_TX_DESC_CNT 64 #define RL_8169_TX_DESC_CNT 256
#define RL_TX_DESC_THLD 4 #define RL_8169_RX_DESC_CNT 256
#define RL_RX_DESC_CNT RL_TX_DESC_CNT #define RL_8139_TX_DESC_CNT 64
#define RL_8139_RX_DESC_CNT 64
#define RL_TX_DESC_CNT RL_8169_TX_DESC_CNT
#define RL_RX_DESC_CNT RL_8169_RX_DESC_CNT
#define RL_NTXSEGS 32
#define RL_RX_LIST_SZ (RL_RX_DESC_CNT * sizeof(struct rl_desc))
#define RL_TX_LIST_SZ (RL_TX_DESC_CNT * sizeof(struct rl_desc))
#define RL_RING_ALIGN 256 #define RL_RING_ALIGN 256
#define RL_DUMP_ALIGN 64
#define RL_IFQ_MAXLEN 512 #define RL_IFQ_MAXLEN 512
#define RL_DESC_INC(x) (x = (x + 1) % RL_TX_DESC_CNT) #define RL_TX_DESC_NXT(sc,x) ((x + 1) & ((sc)->rl_ldata.rl_tx_desc_cnt - 1))
#define RL_TX_DESC_PRV(sc,x) ((x - 1) & ((sc)->rl_ldata.rl_tx_desc_cnt - 1))
#define RL_RX_DESC_NXT(sc,x) ((x + 1) & ((sc)->rl_ldata.rl_rx_desc_cnt - 1))
#define RL_OWN(x) (le32toh((x)->rl_cmdstat) & RL_RDESC_STAT_OWN) #define RL_OWN(x) (le32toh((x)->rl_cmdstat) & RL_RDESC_STAT_OWN)
#define RL_RXBYTES(x) (le32toh((x)->rl_cmdstat) & sc->rl_rxlenmask) #define RL_RXBYTES(x) (le32toh((x)->rl_cmdstat) & sc->rl_rxlenmask)
#define RL_PKTSZ(x) ((x)/* >> 3*/) #define RL_PKTSZ(x) ((x)/* >> 3*/)
@@ -665,34 +783,48 @@ struct rl_stats {
#define RE_RX_DESC_BUFLEN MCLBYTES #define RE_RX_DESC_BUFLEN MCLBYTES
#endif #endif
#define RL_MSI_MESSAGES 2 #define RL_MSI_MESSAGES 1
#define RL_ADDR_LO(y) ((uint64_t) (y) & 0xFFFFFFFF) #define RL_ADDR_LO(y) ((uint64_t) (y) & 0xFFFFFFFF)
#define RL_ADDR_HI(y) ((uint64_t) (y) >> 32) #define RL_ADDR_HI(y) ((uint64_t) (y) >> 32)
/*
* The number of bits reserved for MSS in RealTek controllers is
* 11bits. This limits the maximum interface MTU size in TSO case
* as upper stack should not generate TCP segments with MSS greater
* than the limit.
*/
#define RL_TSO_MTU (2047 - ETHER_HDR_LEN - ETHER_CRC_LEN)
/* see comment in dev/re/if_re.c */ /* see comment in dev/re/if_re.c */
#define RL_JUMBO_FRAMELEN 7440 #define RL_JUMBO_FRAMELEN 7440
#define RL_JUMBO_MTU (RL_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN) #define RL_JUMBO_MTU (RL_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
#define RL_MAX_FRAMELEN \
(ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
struct rl_softc; struct rl_txdesc {
struct mbuf *tx_m;
bus_dmamap_t tx_dmamap;
};
struct rl_dmaload_arg { struct rl_rxdesc {
int rl_idx; struct mbuf *rx_m;
int rl_maxsegs; bus_dmamap_t rx_dmamap;
uint32_t rl_flags; bus_size_t rx_size;
struct rl_desc *rl_ring;
}; };
struct rl_list_data { struct rl_list_data {
struct mbuf *rl_tx_mbuf[RL_TX_DESC_CNT]; struct rl_txdesc rl_tx_desc[RL_TX_DESC_CNT];
struct mbuf *rl_rx_mbuf[RL_RX_DESC_CNT]; struct rl_rxdesc rl_rx_desc[RL_RX_DESC_CNT];
int rl_tx_desc_cnt;
int rl_rx_desc_cnt;
int rl_tx_prodidx; int rl_tx_prodidx;
int rl_rx_prodidx; int rl_rx_prodidx;
int rl_tx_considx; int rl_tx_considx;
int rl_tx_free; int rl_tx_free;
bus_dmamap_t rl_tx_dmamap[RL_TX_DESC_CNT]; bus_dma_tag_t rl_tx_mtag; /* mbuf TX mapping tag */
bus_dmamap_t rl_rx_dmamap[RL_RX_DESC_CNT]; bus_dma_tag_t rl_rx_mtag; /* mbuf RX mapping tag */
bus_dma_tag_t rl_mtag; /* mbuf mapping tag */ bus_dmamap_t rl_rx_sparemap;
bus_dma_tag_t rl_stag; /* stats mapping tag */ bus_dma_tag_t rl_stag; /* stats mapping tag */
bus_dmamap_t rl_smap; /* stats map */ bus_dmamap_t rl_smap; /* stats map */
struct rl_stats *rl_stats; struct rl_stats *rl_stats;
@@ -707,17 +839,20 @@ struct rl_list_data {
bus_addr_t rl_tx_list_addr; bus_addr_t rl_tx_list_addr;
}; };
enum rl_twist { DONE, CHK_LINK, FIND_ROW, SET_PARAM, RECHK_LONG, RETUNE };
struct rl_softc { struct rl_softc {
struct ifnet *rl_ifp; /* interface info */ struct ifnet *rl_ifp; /* interface info */
bus_space_handle_t rl_bhandle; /* bus space handle */ bus_space_handle_t rl_bhandle; /* bus space handle */
bus_space_tag_t rl_btag; /* bus space tag */ bus_space_tag_t rl_btag; /* bus space tag */
device_t rl_dev; device_t rl_dev;
struct resource *rl_res; struct resource *rl_res;
int rl_res_id;
int rl_res_type;
struct resource *rl_irq[RL_MSI_MESSAGES]; struct resource *rl_irq[RL_MSI_MESSAGES];
void *rl_intrhand[RL_MSI_MESSAGES]; void *rl_intrhand[RL_MSI_MESSAGES];
device_t rl_miibus; device_t rl_miibus;
bus_dma_tag_t rl_parent_tag; bus_dma_tag_t rl_parent_tag;
bus_dma_tag_t rl_tag;
uint8_t rl_type; uint8_t rl_type;
int rl_eecmd_read; int rl_eecmd_read;
int rl_eewidth; int rl_eewidth;
@@ -734,6 +869,10 @@ struct rl_softc {
uint32_t rl_rxlenmask; uint32_t rl_rxlenmask;
int rl_testmode; int rl_testmode;
int rl_if_flags; int rl_if_flags;
int rl_twister_enable;
enum rl_twist rl_twister;
int rl_twist_row;
int rl_twist_col;
int suspended; /* 0 = normal 1 = suspended */ int suspended; /* 0 = normal 1 = suspended */
#ifdef DEVICE_POLLING #ifdef DEVICE_POLLING
int rxcycles; int rxcycles;
@@ -742,10 +881,23 @@ struct rl_softc {
struct task rl_txtask; struct task rl_txtask;
struct task rl_inttask; struct task rl_inttask;
struct mtx rl_intlock;
int rl_txstart; int rl_txstart;
int rl_link; uint32_t rl_flags;
int rl_msi; #define RL_FLAG_MSI 0x0001
#define RL_FLAG_AUTOPAD 0x0002
#define RL_FLAG_PHYWAKE_PM 0x0004
#define RL_FLAG_PHYWAKE 0x0008
#define RL_FLAG_NOJUMBO 0x0010
#define RL_FLAG_PAR 0x0020
#define RL_FLAG_DESCV2 0x0040
#define RL_FLAG_MACSTAT 0x0080
#define RL_FLAG_FASTETHER 0x0100
#define RL_FLAG_CMDSTOP 0x0200
#define RL_FLAG_MACRESET 0x0400
#define RL_FLAG_WOLRXENB 0x1000
#define RL_FLAG_MACSLEEP 0x2000
#define RL_FLAG_PCIE 0x4000
#define RL_FLAG_LINK 0x8000
}; };
#define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx) #define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx)
@@ -790,6 +942,7 @@ struct rl_softc {
CSR_WRITE_4(sc, offset, CSR_READ_4(sc, offset) & ~(val)) CSR_WRITE_4(sc, offset, CSR_READ_4(sc, offset) & ~(val))
#define RL_TIMEOUT 1000 #define RL_TIMEOUT 1000
#define RL_PHY_TIMEOUT 2000
/* /*
* General constants that are fun to know. * General constants that are fun to know.
@@ -801,6 +954,7 @@ struct rl_softc {
/* /*
* RealTek chip device IDs. * RealTek chip device IDs.
*/ */
#define RT_DEVICEID_8139D 0x8039
#define RT_DEVICEID_8129 0x8129 #define RT_DEVICEID_8129 0x8129
#define RT_DEVICEID_8101E 0x8136 #define RT_DEVICEID_8101E 0x8136
#define RT_DEVICEID_8138 0x8138 #define RT_DEVICEID_8138 0x8138
@@ -959,38 +1113,3 @@ struct rl_softc {
/* US Robotics 997902 device ID */ /* US Robotics 997902 device ID */
#define USR_DEVICEID_997902 0x0116 #define USR_DEVICEID_997902 0x0116
/*
* PCI low memory base and low I/O base register, and
* other PCI registers.
*/
#define RL_PCI_VENDOR_ID 0x00
#define RL_PCI_DEVICE_ID 0x02
#define RL_PCI_COMMAND 0x04
#define RL_PCI_STATUS 0x06
#define RL_PCI_CLASSCODE 0x09
#define RL_PCI_LATENCY_TIMER 0x0D
#define RL_PCI_HEADER_TYPE 0x0E
#define RL_PCI_LOIO 0x10
#define RL_PCI_LOMEM 0x14
#define RL_PCI_BIOSROM 0x30
#define RL_PCI_INTLINE 0x3C
#define RL_PCI_INTPIN 0x3D
#define RL_PCI_MINGNT 0x3E
#define RL_PCI_MINLAT 0x0F
#define RL_PCI_RESETOPT 0x48
#define RL_PCI_EEPROM_DATA 0x4C
#define RL_PCI_CAPID 0x50 /* 8 bits */
#define RL_PCI_NEXTPTR 0x51 /* 8 bits */
#define RL_PCI_PWRMGMTCAP 0x52 /* 16 bits */
#define RL_PCI_PWRMGMTCTRL 0x54 /* 16 bits */
#define RL_PSTATE_MASK 0x0003
#define RL_PSTATE_D0 0x0000
#define RL_PSTATE_D1 0x0002
#define RL_PSTATE_D2 0x0002
#define RL_PSTATE_D3 0x0003
#define RL_PME_EN 0x0010
#define RL_PME_STATUS 0x8000
+19
View File
@@ -600,6 +600,25 @@ pci_get_domain(device_t dev)
return 0; return 0;
} }
uint32_t
pci_get_devid(device_t dev)
{
return pci_read_config(dev, PCI_device_id, 2) << 16 |
pci_read_config(dev, PCI_vendor_id, 2);
}
uint8_t
pci_get_cachelnsz(device_t dev)
{
return pci_read_config(dev, PCI_line_size, 1);
}
uint8_t *
pci_get_ether(device_t dev)
{
/* used in if_dc to get the MAC from CardBus CIS for Xircom card */
return NULL; /* NULL is handled in the caller correctly */
}
uint8_t uint8_t
pci_get_bus(device_t dev) pci_get_bus(device_t dev)
@@ -133,7 +133,9 @@ model ATHEROS F2 0x0002 Atheros F2 10/100 PHY
model BROADCOM 3C905B 0x0012 3c905B 10/100 internal PHY model BROADCOM 3C905B 0x0012 3c905B 10/100 internal PHY
model BROADCOM 3C905C 0x0017 3c905C 10/100 internal PHY model BROADCOM 3C905C 0x0017 3c905C 10/100 internal PHY
model BROADCOM BCM5201 0x0021 BCM5201 10/100baseTX PHY model BROADCOM BCM5201 0x0021 BCM5201 10/100baseTX PHY
model BROADCOM BCM5214 0x0028 BCM5214 Quad 10/100 PHY
model BROADCOM BCM5221 0x001e BCM5221 10/100baseTX PHY model BROADCOM BCM5221 0x001e BCM5221 10/100baseTX PHY
model BROADCOM BCM5222 0x0032 BCM5222 Dual 10/100 PHY
model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY
model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY
model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY
@@ -32,6 +32,8 @@ uint16_t pci_get_device(device_t dev);
uint16_t pci_get_subvendor(device_t dev); uint16_t pci_get_subvendor(device_t dev);
uint16_t pci_get_subdevice(device_t dev); uint16_t pci_get_subdevice(device_t dev);
uint8_t pci_get_revid(device_t dev); uint8_t pci_get_revid(device_t dev);
uint8_t pci_get_cachelnsz(device_t dev);
uint8_t *pci_get_ether(device_t dev);
uint32_t pci_read_config(device_t dev, int reg, int width); uint32_t pci_read_config(device_t dev, int reg, int width);
void pci_write_config(device_t dev, int reg, uint32_t val, int width); void pci_write_config(device_t dev, int reg, uint32_t val, int width);
@@ -258,6 +258,7 @@ uint64_t ifmedia_baudrate(int);
*/ */
#define IFM_FDX 0x00100000 /* Force full duplex */ #define IFM_FDX 0x00100000 /* Force full duplex */
#define IFM_HDX 0x00200000 /* Force half duplex */ #define IFM_HDX 0x00200000 /* Force half duplex */
#define IFM_FLOW 0x00400000 /* Enable hardware flow control */
#define IFM_FLAG0 0x01000000 /* Driver defined flag */ #define IFM_FLAG0 0x01000000 /* Driver defined flag */
#define IFM_FLAG1 0x02000000 /* Driver defined flag */ #define IFM_FLAG1 0x02000000 /* Driver defined flag */
#define IFM_FLAG2 0x04000000 /* Driver defined flag */ #define IFM_FLAG2 0x04000000 /* Driver defined flag */
@@ -45,6 +45,7 @@ struct __system_init {
struct __system_init __uninit_##uniquifier = { (system_init_func_t) func } struct __system_init __uninit_##uniquifier = { (system_init_func_t) func }
#define TUNABLE_INT(path, var) #define TUNABLE_INT(path, var)
#define TUNABLE_INT_FETCH(path, var)
extern int ticks; extern int ticks;
@@ -17,5 +17,6 @@
typedef int boolean_t; typedef int boolean_t;
typedef __const char* c_caddr_t; typedef __const char* c_caddr_t;
typedef uint64_t u_quad_t;
#endif #endif
@@ -551,3 +551,54 @@ mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv)
return (ENXIO); return (ENXIO);
} }
/*
* Return the flow control status flag from MII_ANAR & MII_ANLPAR.
*/
u_int
mii_phy_flowstatus(struct mii_softc *sc)
{
int anar, anlpar;
if ((sc->mii_flags & MIIF_DOPAUSE) == 0)
return (0);
anar = PHY_READ(sc, MII_ANAR);
anlpar = PHY_READ(sc, MII_ANLPAR);
/*
* Check for 1000BASE-X. Autonegotiation is a bit
* different on such devices.
*/
if ((sc->mii_flags & MIIF_IS_1000X) != 0) {
anar <<= 3;
anlpar <<= 3;
}
if ((anar & ANAR_PAUSE_SYM) != 0 && (anlpar & ANLPAR_PAUSE_SYM) != 0)
return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE);
if ((anar & ANAR_PAUSE_SYM) == 0) {
if ((anar & ANAR_PAUSE_ASYM) != 0 &&
(anlpar & ANLPAR_PAUSE_TOWARDS) != 0)
return (IFM_FLOW | IFM_ETH_TXPAUSE);
else
return (0);
}
if ((anar & ANAR_PAUSE_ASYM) == 0) {
if ((anlpar & ANLPAR_PAUSE_SYM) != 0)
return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE);
else
return (0);
}
switch ((anlpar & ANLPAR_PAUSE_TOWARDS)) {
case ANLPAR_PAUSE_NONE:
return (0);
case ANLPAR_PAUSE_ASYM:
return (IFM_FLOW | IFM_ETH_RXPAUSE);
default:
return (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
}
/* NOTREACHED */
}