* 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

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_NET = $(X86_ONLY)3com $(X86_ONLY)atheros813x
$(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)marvell_yukon $(X86_ONLY)nforce $(X86_ONLY)pcnet pegasus
$(X86_ONLY)rtl8139 $(X86_ONLY)rtl81xx sis900

View File

@ -1,4 +1,3 @@
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 pci ;

View File

@ -1,3 +1,4 @@
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 xl ;

View File

@ -14,13 +14,6 @@
* 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 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
* ``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
* 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 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
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -68,7 +56,7 @@
*/
#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
@ -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_attach(device_t);
struct bmtphy_softc {
struct mii_softc mii_sc;
int mii_model;
};
static device_method_t bmtphy_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bmtphy_probe),
@ -112,81 +105,73 @@ static devclass_t bmtphy_devclass;
static driver_t bmtphy_driver = {
"bmtphy",
bmtphy_methods,
sizeof(struct mii_softc)
sizeof(struct bmtphy_softc)
};
DRIVER_MODULE(bmtphy, miibus, bmtphy_driver, bmtphy_devclass, 0, 0);
static int bmtphy_service(struct mii_softc *, struct mii_data *, int);
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
bmtphy_probe(device_t dev)
{
struct mii_attach_args *ma;
int rval;
ma = device_get_ivars(dev);
rval = BUS_PROBE_DEFAULT;
/* Let exphy(4) take precedence for these. */
rval = mii_phy_dev_probe(dev, bmtphys_lp, BUS_PROBE_LOW_PRIORITY);
if (rval <= 0)
return (rval);
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 (mii_phy_dev_probe(dev, bmtphys_dp, BUS_PROBE_DEFAULT));
}
static int
bmtphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
struct bmtphy_softc *bsc;
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
bsc = device_get_softc(dev);
sc = &bsc->mii_sc;
ma = device_get_ivars(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);
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_service = bmtphy_service;
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 =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
bmtphy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
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");
MIIBUS_MEDIAINIT(sc->mii_dev);
@ -197,31 +182,12 @@ bmtphy_attach(device_t dev)
static int
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) {
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;
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.
*/
@ -232,11 +198,6 @@ bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
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)
return (0);
break;
@ -247,16 +208,15 @@ bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
bmtphy_status(struct mii_softc *sc)
{
struct mii_data *mii;
struct ifmedia_entry *ife;
int bmsr, bmcr, aux_csr;
struct mii_data *mii;
struct ifmedia_entry *ife;
int bmsr, bmcr, aux_csr;
mii = sc->mii_pdata;
ife = mii->mii_media.ifm_cur;
@ -265,7 +225,6 @@ bmtphy_status(struct mii_softc *sc)
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
@ -291,12 +250,45 @@ bmtphy_status(struct mii_softc *sc)
return;
}
aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
if (aux_csr & AUX_CSR_SPEED)
mii->mii_media_active |= IFM_100_TX;
else
mii->mii_media_active |= IFM_10_T;
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
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);
}
}

View File

@ -13,13 +13,6 @@
* 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 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
* ``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
*
* $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_

View File

@ -16,13 +16,6 @@
* 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 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
* ``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
* 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 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
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -67,7 +55,7 @@
*/
#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
@ -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 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
exphy_probe(dev)
device_t dev;
exphy_probe(device_t dev)
{
struct mii_attach_args *ma;
device_t parent;
ma = device_get_ivars(dev);
parent = device_get_parent(device_get_parent(dev));
/*
* 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);
/*
* 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);
if (strcmp(device_get_name(device_get_parent(device_get_parent(dev))),
"xl") == 0)
return (mii_phy_dev_probe(dev, exphys, BUS_PROBE_DEFAULT));
return (ENXIO);
}
static int
exphy_attach(dev)
device_t dev;
exphy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
@ -158,62 +135,39 @@ exphy_attach(dev)
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev);
/*
* 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);
}
mii = ma->mii_data;
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_service = exphy_service;
sc->mii_pdata = mii;
mii->mii_instance++;
/*
* The 3Com PHY can never be isolated.
*/
sc->mii_flags |= MIIF_NOISOLATE;
#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),
BMCR_LOOP|BMCR_S100);
MII_MEDIA_100_TX);
exphy_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, " ");
mii_phy_add_media(sc);
printf("\n");
#undef ADD
MIIBUS_MEDIAINIT(sc->mii_dev);
return(0);
return (0);
}
static int
exphy_service(sc, mii, cmd)
struct mii_softc *sc;
struct mii_data *mii;
int cmd;
exphy_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 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) {
case MII_POLLSTAT:
@ -236,12 +190,6 @@ exphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 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
* kicked; it continues in the background.

View File

@ -16,13 +16,6 @@
* 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 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
* ``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
* 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 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
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -67,7 +55,7 @@
*/
#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
@ -134,7 +122,7 @@ ukphy_attach(device_t dev)
sc = device_get_softc(dev);
ma = device_get_ivars(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);
if (bootverbose)
@ -142,17 +130,17 @@ ukphy_attach(device_t dev)
MII_OUI(ma->mii_id1, 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_service = ukphy_service;
sc->mii_pdata = mii;
mii->mii_instance++;
sc->mii_flags |= MIIF_NOMANPAUSE;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
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, " ");
@ -168,29 +156,12 @@ ukphy_attach(device_t dev)
static int
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) {
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;
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.
*/
@ -201,11 +172,6 @@ ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
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)
return (0);
break;

View File

@ -16,13 +16,6 @@
* 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 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
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@ -38,7 +31,7 @@
*/
#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.
@ -111,19 +104,26 @@ ukphy_status(struct mii_softc *phy)
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;
else if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4;
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;
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;
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;
}

View File

@ -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 ;
UsePrivateHeaders net system ;

View File

@ -31,7 +31,7 @@
*/
#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
@ -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
* support the PCI "boomerang" chips even though they work with the
* "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
@ -142,7 +139,7 @@ MODULE_DEPEND(xl, miibus, 1, 1, 1);
/* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
#include <pci/if_xlreg.h>
#include <dev/xl/if_xlreg.h>
/*
* 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.
*/
static struct xl_type xl_devs[] = {
static const struct xl_type xl_devs[] = {
{ TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT,
"3Com 3c900-TPO Etherlink XL" },
{ 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 void xl_stats_update(void *);
static void xl_stats_update_locked(struct xl_softc *);
static int xl_encap(struct xl_softc *, struct xl_chain *, struct mbuf *);
static void xl_rxeof(struct xl_softc *);
static int xl_encap(struct xl_softc *, struct xl_chain *, struct mbuf **);
static int xl_rxeof(struct xl_softc *);
static void xl_rxeof_task(void *, int);
static int xl_rx_resync(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_stop(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_resume(device_t);
static void xl_setwol(struct xl_softc *);
#ifdef DEVICE_POLLING
static void 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(struct ifnet *ifp, enum poll_cmd cmd, int count);
static int xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
#endif
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_xcvr(struct xl_softc *, 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
static void xl_testpacket(struct xl_softc *);
#endif
@ -319,7 +315,6 @@ static driver_t xl_driver = {
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(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;
}
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
* 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);
/*
* 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));
frame.mii_phyaddr = phy;
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);
if ((sc->xl_flags & XL_FLAG_PHYOK) == 0 && phy != 24)
return (0);
bzero((char *)&frame, sizeof(frame));
frame.mii_phyaddr = phy;
frame.mii_regaddr = reg;
@ -613,6 +555,7 @@ xl_miibus_statchg(device_t dev)
{
struct xl_softc *sc;
struct mii_data *mii;
uint8_t macctl;
sc = device_get_softc(dev);
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. */
XL_SEL_WIN(3);
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX);
else
CSR_WRITE_1(sc, XL_W3_MAC_CTRL,
(CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX));
macctl = CSR_READ_1(sc, XL_W3_MAC_CTRL);
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
macctl &= ~XL_MACCTRL_FLOW_CONTROL_ENB;
}
} 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;
}
IF_ADDR_LOCK(ifp);
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
mcnt++;
IF_ADDR_UNLOCK(ifp);
if_maddr_runlock(ifp);
if (mcnt)
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);
/* now program new ones */
IF_ADDR_LOCK(ifp);
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
@ -834,7 +788,7 @@ xl_setmulti_hash(struct xl_softc *sc)
h | XL_CMD_RX_SET_HASH | XL_HASH_SET);
mcnt++;
}
IF_ADDR_UNLOCK(ifp);
if_maddr_runlock(ifp);
if (mcnt)
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);
}
#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
xl_setcfg(struct xl_softc *sc)
{
@ -1052,7 +980,7 @@ xl_reset(struct xl_softc *sc)
static int
xl_probe(device_t dev)
{
struct xl_type *t;
const struct xl_type *t;
t = xl_devs;
@ -1217,16 +1145,16 @@ static int
xl_attach(device_t dev)
{
u_char eaddr[ETHER_ADDR_LEN];
u_int16_t xcvr[2];
u_int16_t sinfo2, xcvr[2];
struct xl_softc *sc;
struct ifnet *ifp;
int media;
int unit, error = 0, rid, res;
int media, pmcap;
int error = 0, phy, rid, res, unit;
uint16_t did;
sc = device_get_softc(dev);
sc->xl_dev = dev;
unit = device_get_unit(dev);
mtx_init(&sc->xl_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
@ -1369,7 +1297,6 @@ xl_attach(device_t dev)
goto fail;
}
sc->xl_unit = unit;
callout_init_mtx(&sc->xl_stat_callout, &sc->xl_mtx, 0);
TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc);
@ -1478,6 +1405,18 @@ xl_attach(device_t dev)
else
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. */
sc->xl_tx_thresh = XL_MIN_FRAMELEN;
@ -1492,6 +1431,8 @@ xl_attach(device_t dev)
ifp->if_capabilities |= IFCAP_HWCSUM;
#endif
}
if ((sc->xl_flags & XL_FLAG_WOL) != 0)
ifp->if_capabilities |= IFCAP_WOL_MAGIC;
ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
@ -1525,10 +1466,20 @@ xl_attach(device_t dev)
if (bootverbose)
device_printf(dev, "found MII/AUTO\n");
xl_setcfg(sc);
if (mii_phy_probe(dev, &sc->xl_miibus,
xl_ifmedia_upd, xl_ifmedia_sts)) {
device_printf(dev, "no PHY found!\n");
error = ENXIO;
/*
* Attach PHYs only at MII address 24 if !XL_FLAG_PHYOK.
* This is to guard against problems with certain 3Com ASIC
* 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 done;
@ -1708,7 +1659,6 @@ xl_detach(device_t dev)
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
XL_LOCK(sc);
xl_reset(sc);
xl_stop(sc);
XL_UNLOCK(sc);
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;
bus_dmamap_t map;
int error;
u_int32_t baddr;
bus_dma_segment_t segs[1];
int error, nseg;
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. */
m_adj(m_new, ETHER_ALIGN);
error = bus_dmamap_load_mbuf(sc->xl_mtag, sc->xl_tmpmap, m_new,
xl_dma_map_rxbuf, &baddr, BUS_DMA_NOWAIT);
error = bus_dmamap_load_mbuf_sg(sc->xl_mtag, sc->xl_tmpmap, m_new,
segs, &nseg, BUS_DMA_NOWAIT);
if (error) {
m_freem(m_new);
device_printf(sc->xl_dev, "can't map mbuf (error %d)\n",
error);
return (error);
}
KASSERT(nseg == 1,
("%s: too many DMA segments (%d)", __func__, nseg));
bus_dmamap_unload(sc->xl_mtag, 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_ptr->xl_frag.xl_len = htole32(m_new->m_len | XL_LAST_FRAG);
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);
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
* the higher level protocols.
*/
static void
static int
xl_rxeof(struct xl_softc *sc)
{
struct mbuf *m;
struct ifnet *ifp = sc->xl_ifp;
struct xl_chain_onefrag *cur_rx;
int total_len = 0;
int rx_npkts = 0;
u_int32_t rxstat;
XL_LOCK_ASSERT(sc);
@ -2061,6 +2014,7 @@ again:
XL_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
XL_LOCK(sc);
rx_npkts++;
/*
* If we are running from the taskqueue, the interface
@ -2068,7 +2022,7 @@ again:
* packet up the network stack.
*/
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);
goto again;
}
return (rx_npkts);
}
/*
@ -2142,13 +2097,13 @@ xl_txeof(struct xl_softc *sc)
m_freem(cur_tx->xl_mbuf);
cur_tx->xl_mbuf = NULL;
ifp->if_opackets++;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
cur_tx->xl_next = sc->xl_cdata.xl_tx_free;
sc->xl_cdata.xl_tx_free = cur_tx;
}
if (sc->xl_cdata.xl_tx_head == NULL) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->xl_wdog_timer = 0;
sc->xl_cdata.xl_tx_tail = NULL;
} else {
@ -2174,7 +2129,6 @@ xl_txeof_90xB(struct xl_softc *sc)
BUS_DMASYNC_POSTREAD);
idx = sc->xl_cdata.xl_tx_cons;
while (idx != sc->xl_cdata.xl_tx_prod) {
cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
if (!(le32toh(cur_tx->xl_ptr->xl_status) &
@ -2286,6 +2240,7 @@ xl_intr(void *arg)
}
#endif
#ifndef __HAIKU__
while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS &&
status != 0xFFFF) {
@ -2293,6 +2248,9 @@ xl_intr(void *arg)
status = atomic_get((int32 *)&sc->xl_intr_status);
while (true) {
#endif
CSR_WRITE_2(sc, XL_COMMAND,
XL_CMD_INTR_ACK|(status & XL_INTRS));
if (status & XL_STAT_UP_COMPLETE) {
int curpkts;
@ -2317,7 +2275,7 @@ xl_intr(void *arg)
}
if (status & XL_STAT_ADFAIL) {
xl_reset(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc);
}
@ -2347,26 +2305,29 @@ xl_intr(void *arg)
}
#ifdef DEVICE_POLLING
static void
static int
xl_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct xl_softc *sc = ifp->if_softc;
int rx_npkts = 0;
XL_LOCK(sc);
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);
return (rx_npkts);
}
static void
static int
xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct xl_softc *sc = ifp->if_softc;
int rx_npkts;
XL_LOCK_ASSERT(sc);
sc->rxcycles = count;
xl_rxeof(sc);
rx_npkts = xl_rxeof(sc);
if (sc->xl_type == XL_TYPE_905B)
xl_txeof_90xB(sc);
else
@ -2393,7 +2354,7 @@ xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
}
if (status & XL_STAT_ADFAIL) {
xl_reset(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
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 */
@ -2475,26 +2437,21 @@ xl_stats_update_locked(struct xl_softc *sc)
* pointers to the fragment pointers.
*/
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;
u_int32_t status;
struct mbuf *m_new;
struct ifnet *ifp = sc->xl_ifp;
int error, i, nseg, total_len;
u_int32_t status;
XL_LOCK_ASSERT(sc);
/*
* Start packing the mbufs in this chain into
* 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);
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 && error != EFBIG) {
m_freem(m_head);
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.
*/
if (error) {
struct mbuf *m_new;
m_new = m_defrag(m_head, M_DONTWAIT);
m_new = m_collapse(*m_head, M_DONTWAIT, XL_MAXFRAGS);
if (m_new == NULL) {
m_freem(m_head);
return (1);
} else {
m_head = m_new;
m_freem(*m_head);
*m_head = NULL;
return (ENOBUFS);
}
*m_head = m_new;
error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map,
m_head, xl_dma_map_txbuf, c->xl_ptr, BUS_DMA_NOWAIT);
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_freem(*m_head);
*m_head = NULL;
if_printf(ifp, "can't map mbuf (error %d)\n", error);
return (1);
return (error);
}
}
KASSERT(nseg <= XL_MAXFRAGS,
("%s: too many DMA segments (%d)", __func__, nseg));
if (nseg == 0) {
m_freem(*m_head);
*m_head = NULL;
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) {
status = XL_TXSTAT_RND_DEFEAT;
#ifndef XL905B_TXCSUM_BROKEN
if (m_head->m_pkthdr.csum_flags) {
if (m_head->m_pkthdr.csum_flags & CSUM_IP)
if ((*m_head)->m_pkthdr.csum_flags) {
if ((*m_head)->m_pkthdr.csum_flags & CSUM_IP)
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;
if (m_head->m_pkthdr.csum_flags & CSUM_UDP)
if ((*m_head)->m_pkthdr.csum_flags & CSUM_UDP)
status |= XL_TXSTAT_UDPCKSUM;
}
#endif
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);
return (0);
}
@ -2574,12 +2553,14 @@ xl_start_locked(struct ifnet *ifp)
struct xl_softc *sc = ifp->if_softc;
struct mbuf *m_head = NULL;
struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
struct xl_chain *prev_tx;
u_int32_t status;
int error;
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,
* punt.
@ -2595,20 +2576,23 @@ xl_start_locked(struct ifnet *ifp)
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);
if (m_head == NULL)
break;
/* Pick a descriptor off the free list. */
prev_tx = cur_tx;
cur_tx = sc->xl_cdata.xl_tx_free;
/* Pack the data into the descriptor. */
error = xl_encap(sc, cur_tx, m_head);
error = xl_encap(sc, cur_tx, &m_head);
if (error) {
cur_tx = prev_tx;
continue;
if (m_head == NULL)
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;
@ -2638,7 +2622,7 @@ xl_start_locked(struct ifnet *ifp)
* Place the request for the upload interrupt
* in the last descriptor in the chain. This way, if
* 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.
*/
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 mbuf *m_head = NULL;
struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
struct xl_chain *prev_tx;
int error, idx;
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;
idx = sc->xl_cdata.xl_tx_prod;
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) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
@ -2723,14 +2707,16 @@ xl_start_90xB_locked(struct ifnet *ifp)
if (m_head == NULL)
break;
prev_tx = cur_tx;
cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
/* Pack the data into the descriptor. */
error = xl_encap(sc, cur_tx, m_head);
error = xl_encap(sc, cur_tx, &m_head);
if (error) {
cur_tx = prev_tx;
continue;
if (m_head == NULL)
break;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
break;
}
/* Chain it together. */
@ -2758,7 +2744,7 @@ xl_start_90xB_locked(struct ifnet *ifp)
* Place the request for the upload interrupt
* in the last descriptor in the chain. This way, if
* 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.
*/
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);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
return;
/*
* Cancel pending I/O and free all RX/TX buffers.
*/
xl_stop(sc);
/* Reset the chip to a known state. */
xl_reset(sc);
if (sc->xl_miibus == NULL) {
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
xl_wait(sc);
@ -2812,6 +2803,15 @@ xl_init_locked(struct xl_softc *sc)
if (sc->xl_miibus != NULL)
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 */
XL_SEL_WIN(2);
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_5:
xl_setmode(sc, ifm->ifm_media);
XL_UNLOCK(sc);
return (0);
break;
default:
break;
}
if (sc->xl_media & XL_MEDIAOPT_MII ||
sc->xl_media & XL_MEDIAOPT_BTX ||
sc->xl_media & XL_MEDIAOPT_BT4) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc);
} else {
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 ifreq *ifr = (struct ifreq *) data;
int error = 0;
int error = 0, mask;
struct mii_data *mii = NULL;
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,
XL_CMD_RX_SET_FILT|rxfilt);
XL_SEL_WIN(7);
} else {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
xl_init_locked(sc);
}
} else
xl_init_locked(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
xl_stop(sc);
@ -3196,41 +3193,50 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
&mii->mii_media, command);
break;
case SIOCSIFCAP:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
error = ether_poll_register(xl_poll, ifp);
if (error)
return(error);
XL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
ifp->if_capenable |= IFCAP_POLLING;
XL_UNLOCK(sc);
return (error);
}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
error = ether_poll_deregister(ifp);
/* Enable interrupts. */
XL_LOCK(sc);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS);
if (sc->xl_flags & XL_FLAG_FUNCREG)
bus_space_write_4(sc->xl_ftag, sc->xl_fhandle,
4, 0x8000);
ifp->if_capenable &= ~IFCAP_POLLING;
XL_UNLOCK(sc);
return (error);
if ((mask & IFCAP_POLLING) != 0 &&
(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);
if (error)
break;
XL_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
ifp->if_capenable |= IFCAP_POLLING;
XL_UNLOCK(sc);
} else {
error = ether_poll_deregister(ifp);
/* Enable interrupts. */
XL_LOCK(sc);
CSR_WRITE_2(sc, XL_COMMAND,
XL_CMD_INTR_ACK | 0xFF);
CSR_WRITE_2(sc, XL_COMMAND,
XL_CMD_INTR_ENB | XL_INTRS);
if (sc->xl_flags & XL_FLAG_FUNCREG)
bus_space_write_4(sc->xl_ftag,
sc->xl_fhandle, 4, 0x8000);
XL_UNLOCK(sc);
}
}
#endif /* DEVICE_POLLING */
XL_LOCK(sc);
ifp->if_capenable = ifr->ifr_reqcap;
if (ifp->if_capenable & IFCAP_TXCSUM)
ifp->if_hwassist = XL905B_CSUM_FEATURES;
else
ifp->if_hwassist = 0;
if ((mask & IFCAP_TXCSUM) != 0 &&
(ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
ifp->if_capenable ^= IFCAP_TXCSUM;
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
ifp->if_hwassist |= XL905B_CSUM_FEATURES;
else
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);
break;
default:
@ -3246,12 +3252,31 @@ xl_watchdog(struct xl_softc *sc)
{
struct ifnet *ifp = sc->xl_ifp;
u_int16_t status = 0;
int misintr;
XL_LOCK_ASSERT(sc);
if (sc->xl_wdog_timer == 0 || --sc->xl_wdog_timer != 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++;
XL_SEL_WIN(4);
status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
@ -3261,10 +3286,7 @@ xl_watchdog(struct xl_softc *sc)
device_printf(sc->xl_dev,
"no carrier - transceiver cable problem?\n");
xl_txeoc(sc);
xl_txeof(sc);
xl_rxeof(sc);
xl_reset(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
xl_init_locked(sc);
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
* get confused by errant DMAs when rebooting.
*/
static void
static int
xl_shutdown(device_t dev)
{
struct xl_softc *sc;
sc = device_get_softc(dev);
XL_LOCK(sc);
xl_reset(sc);
xl_stop(sc);
XL_UNLOCK(sc);
return (xl_suspend(dev));
}
static int
@ -3376,6 +3392,7 @@ xl_suspend(device_t dev)
XL_LOCK(sc);
xl_stop(sc);
xl_setwol(sc);
XL_UNLOCK(sc);
return (0);
@ -3392,11 +3409,43 @@ xl_resume(device_t dev)
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_UNLOCK(sc);
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);
}

View File

@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* 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 */
@ -81,6 +81,17 @@
#define XL_CAPS_100MBPS 0x1000
#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_MAX_FRAMELEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN)
@ -408,7 +419,12 @@
#define XL_W7_BM_LEN 0x06
#define XL_W7_BM_STATUS 0x0B
#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
*/
@ -486,6 +502,7 @@ struct xl_chain_onefrag {
struct xl_chain_data {
struct xl_chain_onefrag xl_rx_chain[XL_RX_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;
@ -576,6 +593,7 @@ struct xl_mii_frame {
#define XL_FLAG_NO_XCVR_PWR 0x0080
#define XL_FLAG_USE_MMIO 0x0100
#define XL_FLAG_NO_MMIO 0x0200
#define XL_FLAG_WOL 0x0400
#define XL_NO_XCVR_PWR_MAGICBITS 0x0900
@ -589,16 +607,16 @@ struct xl_softc {
struct resource *xl_irq;
struct resource *xl_res;
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_dmamap_t xl_tmpmap; /* spare DMA map */
u_int8_t xl_unit; /* interface number */
u_int8_t xl_type;
u_int32_t xl_xcvr;
u_int16_t xl_media;
u_int16_t xl_caps;
u_int8_t xl_stats_no_timeout;
u_int16_t xl_tx_thresh;
int xl_pmcap;
int xl_if_flags;
struct xl_list_data xl_ldata;
struct xl_chain_data xl_cdata;

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 ipro1000 ;
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 sis900 ;
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 ;
# 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 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 marvell_yukon ;
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 ;
# 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 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 ;

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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
;

View File

@ -0,0 +1,82 @@
/*
* Copyright 2007, Axel Dörfler, axeld@pinc-software.de. 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

View File

@ -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 ;

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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
@ -45,7 +45,9 @@
#define FXP_CSR_FLASHCONTROL 12 /* flash control (2 bytes) */
#define FXP_CSR_EEPROMCONTROL 14 /* eeprom control (2 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) */
/*
@ -223,7 +225,7 @@ struct fxp_cb_config {
/* Bytes 22 - 31 -- i82550 only */
u_int __FXP_BITFIELD3(gamla_rx:1,
vlan_drop_en:1,
vlan_strip_en:1,
:6);
uint8_t pad[9];
};
@ -287,12 +289,12 @@ struct fxp_cb_tx {
/*
* The following structure isn't actually part of the TxCB,
* unless the extended TxCB feature is being used. In this
* case, the first two elements of the structure below are
* case, the first two elements of the structure below are
* fetched along with the TxCB.
*/
union {
struct fxp_ipcb ipcb;
struct fxp_tbd tbd[FXP_NTXSEG];
struct fxp_tbd tbd[FXP_NTXSEG + 1];
} tx_cb_u;
};
@ -376,6 +378,7 @@ struct fxp_rfa {
#define FXP_RFA_STATUS_RNR 0x0200 /* no resources */
#define FXP_RFA_STATUS_ALIGN 0x0400 /* alignment 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_C 0x8000 /* packet reception complete */
#define FXP_RFA_CONTROL_SF 0x08 /* simple/flexible memory mode */
@ -416,11 +419,19 @@ struct fxp_stats {
uint32_t rx_overrun_errors;
uint32_t rx_cdt_errors;
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 reserved0;
uint32_t reserved1;
uint32_t reserved2;
};
#define FXP_STATS_DUMP_COMPLETE 0xa005
#define FXP_STATS_DR_COMPLETE 0xa007
/*
* Serial EEPROM control register bits
*/

View File

@ -1,13 +1,13 @@
/*-
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 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.
@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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.
*/
#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.
@ -86,16 +92,16 @@
/*
* Default maximum time, in microseconds, that an interrupt may be delayed
* in an attempt to coalesce interrupts. This is only effective if the Intel
* in an attempt to coalesce interrupts. This is only effective if the Intel
* microcode is loaded, and may be changed via either loader tunables or
* sysctl. See also the CPUSAVER_DWORD entry in rcvbundl.h.
*/
#define TUNABLE_INT_DELAY 1000
/*
* Default number of packets that will be bundled, before an interrupt is
* Default number of packets that will be bundled, before an interrupt is
* generated. This is only effective if the Intel microcode is loaded, and
* may be changed via either loader tunables or sysctl. This may not be
* may be changed via either loader tunables or sysctl. This may not be
* present in all microcode revisions, see also the CPUSAVER_BUNDLE_MAX_DWORD
* entry in rcvbundl.h.
*/
@ -136,6 +142,37 @@ struct fxp_desc_list {
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
* for functional grouping.
@ -145,8 +182,10 @@ struct fxp_softc {
struct resource *fxp_res[2]; /* I/O and IRQ resources */
struct resource_spec *fxp_spec; /* the resource spec we used */
void *ih; /* interrupt handler cookie */
const struct fxp_ident *ident;
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_dmamap_t fxp_smap; /* bus DMA map for stats */
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 */
struct fxp_desc_list fxp_desc; /* descriptors management struct */
int maxtxseg; /* maximum # of TX segments */
int maxsegsize; /* maximum size of a TX segment */
int tx_queued; /* # of active TxCB's */
int need_mcsetup; /* multicast filter needs programming */
struct fxp_stats *fxp_stats; /* Pointer to interface stats */
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 */
struct callout stat_ch; /* stat callout */
int watchdog_timer; /* seconds until chip reset */
@ -170,13 +210,13 @@ struct fxp_softc {
device_t dev;
int tunable_int_delay; /* interrupt delay value for ucode */
int tunable_bundle_max; /* max # frames per interrupt (ucode) */
int tunable_noflow; /* flow control disabled */
int rnr; /* RNR events */
int eeprom_size; /* size of serial EEPROM */
int suspended; /* 0 = normal 1 = suspended or dead */
int cu_resume_bug;
int revision;
int flags;
int if_flags;
uint8_t rfa_size;
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_SERIAL_MEDIA 0x0010 /* 10Mbps serial interface */
#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_UCODE 0x0100 /* ucode is loaded */
#define FXP_FLAG_DEFERRED_RNR 0x0200 /* DEVICE_POLLING deferred RNR */
#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_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. */
#define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg)

View File

@ -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.
*/
/*
* $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

View File

@ -29,7 +29,7 @@
*/
#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
@ -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 void inphy_status(struct mii_softc *);
static void inphy_reset(struct mii_softc *);
static const struct mii_phydesc inphys[] = {
MII_PHY_DESC(INTEL, I82553C),
@ -104,20 +105,22 @@ inphy_attach(device_t dev)
sc = device_get_softc(dev);
ma = device_get_ivars(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);
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_service = inphy_service;
sc->mii_pdata = mii;
mii->mii_instance++;
sc->mii_flags |= MIIF_NOMANPAUSE;
ifmedia_add(&mii->mii_media,
IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
MII_MEDIA_100_TX, NULL);
mii_phy_reset(sc);
inphy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " ");
@ -132,22 +135,12 @@ inphy_attach(device_t dev)
static int
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) {
case MII_POLLSTAT:
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
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.
*/
@ -158,8 +151,6 @@ inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
case MII_TICK:
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@ -209,7 +200,21 @@ inphy_status(struct mii_softc *sc)
else
mii->mii_media_active |= IFM_10_T;
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
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);
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* 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 */

View File

@ -31,7 +31,7 @@
*/
#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
@ -109,8 +109,13 @@ rlphy_probe(device_t dev)
int rv;
rv = mii_phy_dev_probe(dev, rlphys, BUS_PROBE_DEFAULT);
#ifdef __HAIKU__
if (rv == BUS_PROBE_DEFAULT)
return (rv);
#else
if (rv <= 0)
return (rv);
#endif
nic = device_get_name(device_get_parent(device_get_parent(dev)));
if (strcmp(nic, "rl") == 0 || strcmp(nic, "re") == 0)
@ -129,7 +134,7 @@ rlphy_attach(device_t dev)
sc = device_get_softc(dev);
ma = device_get_ivars(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
@ -139,23 +144,17 @@ rlphy_attach(device_t dev)
if (mii_phy_dev_probe(dev, rlphys, 0) == 0)
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);
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_service = rlphy_service;
sc->mii_pdata = mii;
mii->mii_instance++;
/*
* The RealTek PHY can never be isolated.
*/
sc->mii_flags |= MIIF_NOISOLATE;
#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);
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, " ");
mii_phy_add_media(sc);
printf("\n");
@ -178,13 +176,6 @@ rlphy_attach(device_t dev)
static int
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) {
case MII_POLLSTAT:
@ -261,16 +252,16 @@ rlphy_status(struct mii_softc *phy)
if ((anlpar = PHY_READ(phy, MII_ANAR) &
PHY_READ(phy, MII_ANLPAR))) {
if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD)
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;
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;
mii->mii_media_active |= IFM_10_T|IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
return;
@ -314,6 +305,7 @@ rlphy_status(struct mii_softc *phy)
else
mii->mii_media_active |= IFM_100_TX;
}
mii->mii_media_active |= IFM_HDX;
} else
mii->mii_media_active = ife->ifm_media;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -600,6 +600,25 @@ pci_get_domain(device_t dev)
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
pci_get_bus(device_t dev)

View File

@ -133,7 +133,9 @@ model ATHEROS F2 0x0002 Atheros F2 10/100 PHY
model BROADCOM 3C905B 0x0012 3c905B 10/100 internal PHY
model BROADCOM 3C905C 0x0017 3c905C 10/100 internal 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 BCM5222 0x0032 BCM5222 Dual 10/100 PHY
model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY
model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY
model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY

View File

@ -32,6 +32,8 @@ uint16_t pci_get_device(device_t dev);
uint16_t pci_get_subvendor(device_t dev);
uint16_t pci_get_subdevice(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);
void pci_write_config(device_t dev, int reg, uint32_t val, int width);

View File

@ -258,6 +258,7 @@ uint64_t ifmedia_baudrate(int);
*/
#define IFM_FDX 0x00100000 /* Force full 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_FLAG1 0x02000000 /* Driver defined flag */
#define IFM_FLAG2 0x04000000 /* Driver defined flag */

View File

@ -45,6 +45,7 @@ struct __system_init {
struct __system_init __uninit_##uniquifier = { (system_init_func_t) func }
#define TUNABLE_INT(path, var)
#define TUNABLE_INT_FETCH(path, var)
extern int ticks;

View File

@ -17,5 +17,6 @@
typedef int boolean_t;
typedef __const char* c_caddr_t;
typedef uint64_t u_quad_t;
#endif

View File

@ -551,3 +551,54 @@ mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv)
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 */
}