mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-12 09:58:36 +00:00
Convert the Adaptec and Winbond drivers to miibus.
This commit is contained in:
parent
4af396a52d
commit
4ae17070a2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=50675
@ -108,13 +108,16 @@
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
|
||||
#include "miibus_if.h"
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#define SF_USEIOSPACE
|
||||
|
||||
/* #define SF_BACKGROUND_AUTONEG */
|
||||
|
||||
#include <pci/if_sfreg.h>
|
||||
|
||||
#ifndef lint
|
||||
@ -128,10 +131,6 @@ static struct sf_type sf_devs[] = {
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static struct sf_type sf_phys[] = {
|
||||
{ 0, 0, "<MII-compliant physical interface>" }
|
||||
};
|
||||
|
||||
static int sf_probe __P((device_t));
|
||||
static int sf_attach __P((device_t));
|
||||
static int sf_detach __P((device_t));
|
||||
@ -166,12 +165,9 @@ static int sf_setvlan __P((struct sf_softc *, int, u_int32_t));
|
||||
static u_int8_t sf_read_eeprom __P((struct sf_softc *, int));
|
||||
static u_int32_t sf_calchash __P((caddr_t));
|
||||
|
||||
static int sf_phy_readreg __P((struct sf_softc *, int));
|
||||
static void sf_phy_writereg __P((struct sf_softc *, int, int));
|
||||
static void sf_autoneg_xmit __P((struct sf_softc *));
|
||||
static void sf_autoneg_mii __P((struct sf_softc *, int, int));
|
||||
static void sf_getmode_mii __P((struct sf_softc *));
|
||||
static void sf_setmode_mii __P((struct sf_softc *, int));
|
||||
static int sf_miibus_readreg __P((device_t, int, int));
|
||||
static int sf_miibus_writereg __P((device_t, int, int, int));
|
||||
static void sf_miibus_statchg __P((device_t));
|
||||
|
||||
static u_int32_t csr_read_4 __P((struct sf_softc *, int));
|
||||
static void csr_write_4 __P((struct sf_softc *, int, u_int32_t));
|
||||
@ -190,6 +186,16 @@ static device_method_t sf_methods[] = {
|
||||
DEVMETHOD(device_attach, sf_attach),
|
||||
DEVMETHOD(device_detach, sf_detach),
|
||||
DEVMETHOD(device_shutdown, sf_shutdown),
|
||||
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
||||
|
||||
/* MII interface */
|
||||
DEVMETHOD(miibus_readreg, sf_miibus_readreg),
|
||||
DEVMETHOD(miibus_writereg, sf_miibus_writereg),
|
||||
DEVMETHOD(miibus_statchg, sf_miibus_statchg),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -202,6 +208,7 @@ static driver_t sf_driver = {
|
||||
static devclass_t sf_devclass;
|
||||
|
||||
DRIVER_MODULE(sf, pci, sf_driver, sf_devclass, 0, 0);
|
||||
DRIVER_MODULE(miibus, sf, miibus_driver, miibus_devclass, 0, 0);
|
||||
|
||||
#define SF_SETBIT(sc, reg, x) \
|
||||
csr_write_4(sc, reg, csr_read_4(sc, reg) | x)
|
||||
@ -353,15 +360,18 @@ static int sf_setvlan(sc, idx, vlan)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sf_phy_readreg(sc, reg)
|
||||
struct sf_softc *sc;
|
||||
int reg;
|
||||
static int sf_miibus_readreg(dev, phy, reg)
|
||||
device_t dev;
|
||||
int phy, reg;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
int i;
|
||||
u_int32_t val = 0;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
for (i = 0; i < SF_TIMEOUT; i++) {
|
||||
val = csr_read_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg));
|
||||
val = csr_read_4(sc, SF_PHY_REG(phy, reg));
|
||||
if (val & SF_MII_DATAVALID)
|
||||
break;
|
||||
}
|
||||
@ -375,21 +385,42 @@ static int sf_phy_readreg(sc, reg)
|
||||
return(val & 0x0000FFFF);
|
||||
}
|
||||
|
||||
static void sf_phy_writereg(sc, reg, val)
|
||||
struct sf_softc *sc;
|
||||
int reg, val;
|
||||
static int sf_miibus_writereg(dev, phy, reg, val)
|
||||
device_t dev;
|
||||
int phy, reg, val;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
int i;
|
||||
int busy;
|
||||
|
||||
csr_write_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg), val);
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
csr_write_4(sc, SF_PHY_REG(phy, reg), val);
|
||||
|
||||
for (i = 0; i < SF_TIMEOUT; i++) {
|
||||
busy = csr_read_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg));
|
||||
busy = csr_read_4(sc, SF_PHY_REG(phy, reg));
|
||||
if (!(busy & SF_MII_BUSY))
|
||||
break;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void sf_miibus_statchg(dev)
|
||||
device_t dev;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -447,310 +478,6 @@ static void sf_setmulti(sc)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate an autonegotiation session.
|
||||
*/
|
||||
static void sf_autoneg_xmit(sc)
|
||||
struct sf_softc *sc;
|
||||
{
|
||||
u_int16_t phy_sts;
|
||||
|
||||
sf_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET);
|
||||
DELAY(500);
|
||||
while(sf_phy_readreg(sc, PHY_BMCR)
|
||||
& PHY_BMCR_RESET);
|
||||
|
||||
phy_sts = sf_phy_readreg(sc, PHY_BMCR);
|
||||
phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR;
|
||||
sf_phy_writereg(sc, PHY_BMCR, phy_sts);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke autonegotiation on a PHY.
|
||||
*/
|
||||
static void sf_autoneg_mii(sc, flag, verbose)
|
||||
struct sf_softc *sc;
|
||||
int flag;
|
||||
int verbose;
|
||||
{
|
||||
u_int16_t phy_sts = 0, media, advert, ability;
|
||||
struct ifnet *ifp;
|
||||
struct ifmedia *ifm;
|
||||
|
||||
ifm = &sc->ifmedia;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
ifm->ifm_media = IFM_ETHER | IFM_AUTO;
|
||||
|
||||
#ifndef FORCE_AUTONEG_TFOUR
|
||||
/*
|
||||
* First, see if autoneg is supported. If not, there's
|
||||
* no point in continuing.
|
||||
*/
|
||||
phy_sts = sf_phy_readreg(sc, PHY_BMSR);
|
||||
if (!(phy_sts & PHY_BMSR_CANAUTONEG)) {
|
||||
if (verbose)
|
||||
printf("sf%d: autonegotiation not supported\n",
|
||||
sc->sf_unit);
|
||||
ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (flag) {
|
||||
case SF_FLAG_FORCEDELAY:
|
||||
/*
|
||||
* XXX Never use this option anywhere but in the probe
|
||||
* routine: making the kernel stop dead in its tracks
|
||||
* for three whole seconds after we've gone multi-user
|
||||
* is really bad manners.
|
||||
*/
|
||||
sf_autoneg_xmit(sc);
|
||||
DELAY(5000000);
|
||||
break;
|
||||
case SF_FLAG_SCHEDDELAY:
|
||||
/*
|
||||
* Wait for the transmitter to go idle before starting
|
||||
* an autoneg session, otherwise sf_start() may clobber
|
||||
* our timeout, and we don't want to allow transmission
|
||||
* during an autoneg session since that can screw it up.
|
||||
*/
|
||||
if (sc->sf_tx_cnt) {
|
||||
sc->sf_want_auto = 1;
|
||||
return;
|
||||
}
|
||||
sf_autoneg_xmit(sc);
|
||||
ifp->if_timer = 5;
|
||||
sc->sf_autoneg = 1;
|
||||
sc->sf_want_auto = 0;
|
||||
return;
|
||||
break;
|
||||
case SF_FLAG_DELAYTIMEO:
|
||||
ifp->if_timer = 0;
|
||||
sc->sf_autoneg = 0;
|
||||
break;
|
||||
default:
|
||||
printf("sf%d: invalid autoneg flag: %d\n", sc->sf_unit, flag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) {
|
||||
if (verbose)
|
||||
printf("sf%d: autoneg complete, ", sc->sf_unit);
|
||||
phy_sts = sf_phy_readreg(sc, PHY_BMSR);
|
||||
} else {
|
||||
if (verbose)
|
||||
printf("sf%d: autoneg not complete, ", sc->sf_unit);
|
||||
}
|
||||
|
||||
media = sf_phy_readreg(sc, PHY_BMCR);
|
||||
|
||||
/* Link is good. Report modes and set duplex mode. */
|
||||
if (sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) {
|
||||
if (verbose)
|
||||
printf("link status good ");
|
||||
advert = sf_phy_readreg(sc, PHY_ANAR);
|
||||
ability = sf_phy_readreg(sc, PHY_LPAR);
|
||||
|
||||
if (advert & PHY_ANAR_100BT4 && ability & PHY_ANAR_100BT4) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_100_T4;
|
||||
media |= PHY_BMCR_SPEEDSEL;
|
||||
media &= ~PHY_BMCR_DUPLEX;
|
||||
printf("(100baseT4)\n");
|
||||
} else if (advert & PHY_ANAR_100BTXFULL &&
|
||||
ability & PHY_ANAR_100BTXFULL) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
media |= PHY_BMCR_SPEEDSEL;
|
||||
media |= PHY_BMCR_DUPLEX;
|
||||
printf("(full-duplex, 100Mbps)\n");
|
||||
} else if (advert & PHY_ANAR_100BTXHALF &&
|
||||
ability & PHY_ANAR_100BTXHALF) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX;
|
||||
media |= PHY_BMCR_SPEEDSEL;
|
||||
media &= ~PHY_BMCR_DUPLEX;
|
||||
printf("(half-duplex, 100Mbps)\n");
|
||||
} else if (advert & PHY_ANAR_10BTFULL &&
|
||||
ability & PHY_ANAR_10BTFULL) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX;
|
||||
media &= ~PHY_BMCR_SPEEDSEL;
|
||||
media |= PHY_BMCR_DUPLEX;
|
||||
printf("(full-duplex, 10Mbps)\n");
|
||||
} else if (advert & PHY_ANAR_10BTHALF &&
|
||||
ability & PHY_ANAR_10BTHALF) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
media &= ~PHY_BMCR_SPEEDSEL;
|
||||
media &= ~PHY_BMCR_DUPLEX;
|
||||
printf("(half-duplex, 10Mbps)\n");
|
||||
}
|
||||
|
||||
media &= ~PHY_BMCR_AUTONEGENBL;
|
||||
|
||||
/* Set ASIC's duplex mode to match the PHY. */
|
||||
sf_phy_writereg(sc, PHY_BMCR, media);
|
||||
if ((media & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
} else {
|
||||
if (verbose)
|
||||
printf("no carrier\n");
|
||||
}
|
||||
|
||||
sf_init(sc);
|
||||
|
||||
if (sc->sf_tx_pend) {
|
||||
sc->sf_autoneg = 0;
|
||||
sc->sf_tx_pend = 0;
|
||||
sf_start(ifp);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void sf_getmode_mii(sc)
|
||||
struct sf_softc *sc;
|
||||
{
|
||||
u_int16_t bmsr;
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
bmsr = sf_phy_readreg(sc, PHY_BMSR);
|
||||
if (bootverbose)
|
||||
printf("sf%d: PHY status word: %x\n", sc->sf_unit, bmsr);
|
||||
|
||||
/* fallback */
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
|
||||
if (bmsr & PHY_BMSR_10BTHALF) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 10Mbps half-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_10BTFULL) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 10Mbps full-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX;
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_100BTXHALF) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 100Mbps half-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifp->if_baudrate = 100000000;
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX;
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_100BTXFULL) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 100Mbps full-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifp->if_baudrate = 100000000;
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
}
|
||||
|
||||
/* Some also support 100BaseT4. */
|
||||
if (bmsr & PHY_BMSR_100BT4) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 100baseT4 mode supported\n", sc->sf_unit);
|
||||
ifp->if_baudrate = 100000000;
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_T4, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_T4;
|
||||
#ifdef FORCE_AUTONEG_TFOUR
|
||||
if (bootverbose)
|
||||
printf("sf%d: forcing on autoneg support for BT4\n",
|
||||
sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0 NULL):
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_AUTO;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_CANAUTONEG) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: autoneg supported\n", sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_AUTO;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set speed and duplex mode.
|
||||
*/
|
||||
static void sf_setmode_mii(sc, media)
|
||||
struct sf_softc *sc;
|
||||
int media;
|
||||
{
|
||||
u_int16_t bmcr;
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
/*
|
||||
* If an autoneg session is in progress, stop it.
|
||||
*/
|
||||
if (sc->sf_autoneg) {
|
||||
printf("sf%d: canceling autoneg session\n", sc->sf_unit);
|
||||
ifp->if_timer = sc->sf_autoneg = sc->sf_want_auto = 0;
|
||||
bmcr = sf_phy_readreg(sc, PHY_BMCR);
|
||||
bmcr &= ~PHY_BMCR_AUTONEGENBL;
|
||||
sf_phy_writereg(sc, PHY_BMCR, bmcr);
|
||||
}
|
||||
|
||||
printf("sf%d: selecting MII, ", sc->sf_unit);
|
||||
|
||||
bmcr = sf_phy_readreg(sc, PHY_BMCR);
|
||||
|
||||
bmcr &= ~(PHY_BMCR_AUTONEGENBL|PHY_BMCR_SPEEDSEL|
|
||||
PHY_BMCR_DUPLEX|PHY_BMCR_LOOPBK);
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_100_T4) {
|
||||
printf("100Mbps/T4, half-duplex\n");
|
||||
bmcr |= PHY_BMCR_SPEEDSEL;
|
||||
bmcr &= ~PHY_BMCR_DUPLEX;
|
||||
}
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_100_TX) {
|
||||
printf("100Mbps, ");
|
||||
bmcr |= PHY_BMCR_SPEEDSEL;
|
||||
}
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_10_T) {
|
||||
printf("10Mbps, ");
|
||||
bmcr &= ~PHY_BMCR_SPEEDSEL;
|
||||
}
|
||||
|
||||
if ((media & IFM_GMASK) == IFM_FDX) {
|
||||
printf("full duplex\n");
|
||||
bmcr |= PHY_BMCR_DUPLEX;
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
printf("half duplex\n");
|
||||
bmcr &= ~PHY_BMCR_DUPLEX;
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
|
||||
sf_phy_writereg(sc, PHY_BMCR, bmcr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set media options.
|
||||
*/
|
||||
@ -758,19 +485,11 @@ static int sf_ifmedia_upd(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct ifmedia *ifm;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
ifm = &sc->ifmedia;
|
||||
|
||||
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
|
||||
return(EINVAL);
|
||||
|
||||
if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
|
||||
sf_autoneg_mii(sc, SF_FLAG_SCHEDDELAY, 1);
|
||||
else {
|
||||
sf_setmode_mii(sc, ifm->ifm_media);
|
||||
}
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -783,42 +502,14 @@ static void sf_ifmedia_sts(ifp, ifmr)
|
||||
struct ifmediareq *ifmr;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
u_int16_t advert = 0, ability = 0;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
ifmr->ifm_active = IFM_ETHER;
|
||||
|
||||
if (!(sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) {
|
||||
if (sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_SPEEDSEL)
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_TX;
|
||||
else
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T;
|
||||
if (sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_DUPLEX)
|
||||
ifmr->ifm_active |= IFM_FDX;
|
||||
else
|
||||
ifmr->ifm_active |= IFM_HDX;
|
||||
return;
|
||||
}
|
||||
|
||||
ability = sf_phy_readreg(sc, PHY_LPAR);
|
||||
advert = sf_phy_readreg(sc, PHY_ANAR);
|
||||
if (advert & PHY_ANAR_100BT4 &&
|
||||
ability & PHY_ANAR_100BT4) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_T4;
|
||||
} else if (advert & PHY_ANAR_100BTXFULL &&
|
||||
ability & PHY_ANAR_100BTXFULL) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
} else if (advert & PHY_ANAR_100BTXHALF &&
|
||||
ability & PHY_ANAR_100BTXHALF) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_TX|IFM_HDX;
|
||||
} else if (advert & PHY_ANAR_10BTFULL &&
|
||||
ability & PHY_ANAR_10BTFULL) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T|IFM_FDX;
|
||||
} else if (advert & PHY_ANAR_10BTHALF &&
|
||||
ability & PHY_ANAR_10BTHALF) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
}
|
||||
mii_pollstat(mii);
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -830,6 +521,7 @@ static int sf_ioctl(ifp, command, data)
|
||||
{
|
||||
struct sf_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
struct mii_data *mii;
|
||||
int s, error = 0;
|
||||
|
||||
s = splimp();
|
||||
@ -856,7 +548,8 @@ static int sf_ioctl(ifp, command, data)
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
case SIOCSIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
@ -961,9 +654,6 @@ static int sf_attach(dev)
|
||||
u_int32_t command;
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int media = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
struct sf_type *p;
|
||||
u_int16_t phy_vid, phy_did, phy_sts;
|
||||
int unit, rid, error = 0;
|
||||
|
||||
s = splimp();
|
||||
@ -1079,7 +769,7 @@ static int sf_attach(dev)
|
||||
|
||||
/* Allocate the descriptor queues. */
|
||||
sc->sf_ldata = contigmalloc(sizeof(struct sf_list_data), M_DEVBUF,
|
||||
M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
|
||||
M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0);
|
||||
|
||||
if (sc->sf_ldata == NULL) {
|
||||
printf("sf%d: no memory for list buffers!\n", unit);
|
||||
@ -1092,44 +782,9 @@ static int sf_attach(dev)
|
||||
|
||||
bzero(sc->sf_ldata, sizeof(struct sf_list_data));
|
||||
|
||||
if (bootverbose)
|
||||
printf("sf%d: probing for a PHY\n", sc->sf_unit);
|
||||
for (i = SF_PHYADDR_MIN; i < SF_PHYADDR_MAX + 1; i++) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: checking address: %d\n",
|
||||
sc->sf_unit, i);
|
||||
sc->sf_phy_addr = i;
|
||||
sf_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET);
|
||||
DELAY(500);
|
||||
while(sf_phy_readreg(sc, PHY_BMCR)
|
||||
& PHY_BMCR_RESET);
|
||||
if ((phy_sts = sf_phy_readreg(sc, PHY_BMSR)))
|
||||
break;
|
||||
}
|
||||
if (phy_sts) {
|
||||
phy_vid = sf_phy_readreg(sc, PHY_VENID);
|
||||
phy_did = sf_phy_readreg(sc, PHY_DEVID);
|
||||
if (bootverbose)
|
||||
printf("sf%d: found PHY at address %d, ",
|
||||
sc->sf_unit, sc->sf_phy_addr);
|
||||
if (bootverbose)
|
||||
printf("vendor id: %x device id: %x\n",
|
||||
phy_vid, phy_did);
|
||||
p = sf_phys;
|
||||
while(p->sf_vid) {
|
||||
if (phy_vid == p->sf_vid &&
|
||||
(phy_did | 0x000F) == p->sf_did) {
|
||||
sc->sf_pinfo = p;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (sc->sf_pinfo == NULL)
|
||||
sc->sf_pinfo = &sf_phys[PHY_UNKNOWN];
|
||||
if (bootverbose)
|
||||
printf("sf%d: PHY type: %s\n",
|
||||
sc->sf_unit, sc->sf_pinfo->sf_name);
|
||||
} else {
|
||||
/* Do MII setup. */
|
||||
if (mii_phy_probe(dev, &sc->sf_miibus,
|
||||
sf_ifmedia_upd, sf_ifmedia_sts)) {
|
||||
printf("sf%d: MII without any phy!\n", sc->sf_unit);
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
|
||||
@ -1153,23 +808,6 @@ static int sf_attach(dev)
|
||||
ifp->if_baudrate = 10000000;
|
||||
ifp->if_snd.ifq_maxlen = SF_TX_DLIST_CNT - 1;
|
||||
|
||||
/*
|
||||
* Do ifmedia setup.
|
||||
*/
|
||||
ifmedia_init(&sc->ifmedia, 0, sf_ifmedia_upd, sf_ifmedia_sts);
|
||||
|
||||
sf_getmode_mii(sc);
|
||||
if (cold) {
|
||||
sf_autoneg_mii(sc, SF_FLAG_FORCEDELAY, 1);
|
||||
sf_stop(sc);
|
||||
} else {
|
||||
sf_init(sc);
|
||||
sf_autoneg_mii(sc, SF_FLAG_SCHEDDELAY, 1);
|
||||
}
|
||||
|
||||
media = sc->ifmedia.ifm_media;
|
||||
ifmedia_set(&sc->ifmedia, media);
|
||||
|
||||
/*
|
||||
* Call MI attach routines.
|
||||
*/
|
||||
@ -1200,12 +838,14 @@ static int sf_detach(dev)
|
||||
if_detach(ifp);
|
||||
sf_stop(sc);
|
||||
|
||||
bus_generic_detach(dev);
|
||||
device_delete_child(dev, sc->sf_miibus);
|
||||
|
||||
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
|
||||
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
|
||||
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
ifmedia_removeall(&sc->ifmedia);
|
||||
|
||||
splx(s);
|
||||
|
||||
@ -1490,12 +1130,14 @@ static void sf_init(xsc)
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
struct mii_data *mii;
|
||||
int i, s;
|
||||
|
||||
s = splimp();
|
||||
|
||||
sc = xsc;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
sf_stop(sc);
|
||||
sf_reset(sc);
|
||||
@ -1573,7 +1215,7 @@ static void sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
|
||||
|
||||
/* Make sure the duplex mode is set correctly. */
|
||||
if ((sc->ifmedia.ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
if ((mii->mii_media.ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
@ -1587,6 +1229,8 @@ static void sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RX_ENB|SF_ETHCTL_RXDMA_ENB);
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB);
|
||||
|
||||
mii_mediachg(mii);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
|
||||
@ -1673,11 +1317,6 @@ static void sf_start(ifp)
|
||||
if (ifp->if_flags & IFF_OACTIVE)
|
||||
return;
|
||||
|
||||
if (sc->sf_autoneg) {
|
||||
sc->sf_tx_pend = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
txprod = csr_read_4(sc, SF_TXDQ_PRODIDX);
|
||||
i = SF_IDX_HI(txprod) >> 4;
|
||||
|
||||
@ -1768,6 +1407,7 @@ static void sf_stats_update(xsc)
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
struct mii_data *mii;
|
||||
struct sf_stats stats;
|
||||
u_int32_t *ptr;
|
||||
int i, s;
|
||||
@ -1776,6 +1416,7 @@ static void sf_stats_update(xsc)
|
||||
|
||||
sc = xsc;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
ptr = (u_int32_t *)&stats;
|
||||
for (i = 0; i < sizeof(stats)/sizeof(u_int32_t); i++)
|
||||
@ -1789,6 +1430,8 @@ static void sf_stats_update(xsc)
|
||||
ifp->if_collisions += stats.sf_tx_single_colls +
|
||||
stats.sf_tx_multi_colls + stats.sf_tx_excess_colls;
|
||||
|
||||
mii_tick(mii);
|
||||
|
||||
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);
|
||||
|
||||
splx(s);
|
||||
@ -1803,22 +1446,9 @@ static void sf_watchdog(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
if (sc->sf_autoneg) {
|
||||
sf_autoneg_mii(sc, SF_FLAG_DELAYTIMEO, 1);
|
||||
if (!(ifp->if_flags & IFF_UP))
|
||||
sf_stop(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp->if_oerrors++;
|
||||
printf("sf%d: watchdog timeout\n", sc->sf_unit);
|
||||
|
||||
if (sc->sf_pinfo != NULL) {
|
||||
if (!(sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
|
||||
printf("sf%d: no carrier - transceiver "
|
||||
"cable problem?\n", sc->sf_unit);
|
||||
}
|
||||
|
||||
sf_stop(sc);
|
||||
sf_reset(sc);
|
||||
sf_init(sc);
|
||||
|
@ -1010,20 +1010,14 @@ struct sf_list_data {
|
||||
|
||||
struct sf_softc {
|
||||
struct arpcom arpcom; /* interface info */
|
||||
struct ifmedia ifmedia; /* media info */
|
||||
bus_space_handle_t sf_bhandle; /* bus space handle */
|
||||
bus_space_tag_t sf_btag; /* bus space tag */
|
||||
void *sf_intrhand; /* interrupt handler cookie */
|
||||
struct resource *sf_irq; /* irq resource descriptor */
|
||||
struct resource *sf_res; /* mem/ioport resource */
|
||||
struct sf_type *sf_info; /* Starfire adapter info */
|
||||
struct sf_type *sf_pinfo; /* phy info */
|
||||
device_t sf_miibus;
|
||||
u_int8_t sf_unit; /* interface number */
|
||||
u_int8_t sf_type;
|
||||
u_int8_t sf_phy_addr; /* PHY address */
|
||||
u_int8_t sf_tx_pend; /* TX pending */
|
||||
u_int8_t sf_want_auto;
|
||||
u_int8_t sf_autoneg;
|
||||
struct sf_list_data *sf_ldata;
|
||||
int sf_tx_cnt;
|
||||
struct callout_handle sf_stat_ch;
|
||||
@ -1031,140 +1025,6 @@ struct sf_softc {
|
||||
|
||||
#define SF_TIMEOUT 1000
|
||||
|
||||
#define SF_FLAG_FORCEDELAY 1
|
||||
#define SF_FLAG_SCHEDDELAY 2
|
||||
#define SF_FLAG_DELAYTIMEO 3
|
||||
|
||||
/*
|
||||
* Texas Instruments PHY identifiers
|
||||
*/
|
||||
#define TI_PHY_VENDORID 0x4000
|
||||
#define TI_PHY_10BT 0x501F
|
||||
#define TI_PHY_100VGPMI 0x502F
|
||||
|
||||
/*
|
||||
* These ID values are for the NS DP83840A 10/100 PHY
|
||||
*/
|
||||
#define NS_PHY_VENDORID 0x2000
|
||||
#define NS_PHY_83840A 0x5C0F
|
||||
|
||||
/*
|
||||
* Level 1 10/100 PHY
|
||||
*/
|
||||
#define LEVEL1_PHY_VENDORID 0x7810
|
||||
#define LEVEL1_PHY_LXT970 0x000F
|
||||
|
||||
/*
|
||||
* Intel 82555 10/100 PHY
|
||||
*/
|
||||
#define INTEL_PHY_VENDORID 0x0A28
|
||||
#define INTEL_PHY_82555 0x015F
|
||||
|
||||
/*
|
||||
* SEEQ 80220 10/100 PHY
|
||||
*/
|
||||
#define SEEQ_PHY_VENDORID 0x0016
|
||||
#define SEEQ_PHY_80220 0xF83F
|
||||
|
||||
#define PHY_UNKNOWN 6
|
||||
|
||||
#define SF_PHYADDR_MIN 0x00
|
||||
#define SF_PHYADDR_MAX 0x1F
|
||||
|
||||
#define PHY_BMCR 0x00
|
||||
#define PHY_BMSR 0x01
|
||||
#define PHY_VENID 0x02
|
||||
#define PHY_DEVID 0x03
|
||||
#define PHY_ANAR 0x04
|
||||
#define PHY_LPAR 0x05
|
||||
#define PHY_ANEXP 0x06
|
||||
|
||||
#define PHY_ANAR_NEXTPAGE 0x8000
|
||||
#define PHY_ANAR_RSVD0 0x4000
|
||||
#define PHY_ANAR_TLRFLT 0x2000
|
||||
#define PHY_ANAR_RSVD1 0x1000
|
||||
#define PHY_ANAR_RSVD2 0x0800
|
||||
#define PHY_ANAR_RSVD3 0x0400
|
||||
#define PHY_ANAR_100BT4 0x0200
|
||||
#define PHY_ANAR_100BTXFULL 0x0100
|
||||
#define PHY_ANAR_100BTXHALF 0x0080
|
||||
#define PHY_ANAR_10BTFULL 0x0040
|
||||
#define PHY_ANAR_10BTHALF 0x0020
|
||||
#define PHY_ANAR_PROTO4 0x0010
|
||||
#define PHY_ANAR_PROTO3 0x0008
|
||||
#define PHY_ANAR_PROTO2 0x0004
|
||||
#define PHY_ANAR_PROTO1 0x0002
|
||||
#define PHY_ANAR_PROTO0 0x0001
|
||||
|
||||
/*
|
||||
* These are the register definitions for the PHY (physical layer
|
||||
* interface chip).
|
||||
*/
|
||||
/*
|
||||
* PHY BMCR Basic Mode Control Register
|
||||
*/
|
||||
#define PHY_BMCR_RESET 0x8000
|
||||
#define PHY_BMCR_LOOPBK 0x4000
|
||||
#define PHY_BMCR_SPEEDSEL 0x2000
|
||||
#define PHY_BMCR_AUTONEGENBL 0x1000
|
||||
#define PHY_BMCR_RSVD0 0x0800 /* write as zero */
|
||||
#define PHY_BMCR_ISOLATE 0x0400
|
||||
#define PHY_BMCR_AUTONEGRSTR 0x0200
|
||||
#define PHY_BMCR_DUPLEX 0x0100
|
||||
#define PHY_BMCR_COLLTEST 0x0080
|
||||
#define PHY_BMCR_RSVD1 0x0040 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD2 0x0020 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD3 0x0010 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD4 0x0008 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD5 0x0004 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD6 0x0002 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD7 0x0001 /* write as zero, don't care */
|
||||
/*
|
||||
* RESET: 1 == software reset, 0 == normal operation
|
||||
* Resets status and control registers to default values.
|
||||
* Relatches all hardware config values.
|
||||
*
|
||||
* LOOPBK: 1 == loopback operation enabled, 0 == normal operation
|
||||
*
|
||||
* SPEEDSEL: 1 == 100Mb/s, 0 == 10Mb/s
|
||||
* Link speed is selected byt his bit or if auto-negotiation if bit
|
||||
* 12 (AUTONEGENBL) is set (in which case the value of this register
|
||||
* is ignored).
|
||||
*
|
||||
* AUTONEGENBL: 1 == Autonegotiation enabled, 0 == Autonegotiation disabled
|
||||
* Bits 8 and 13 are ignored when autoneg is set, otherwise bits 8 and 13
|
||||
* determine speed and mode. Should be cleared and then set if PHY configured
|
||||
* for no autoneg on startup.
|
||||
*
|
||||
* ISOLATE: 1 == isolate PHY from MII, 0 == normal operation
|
||||
*
|
||||
* AUTONEGRSTR: 1 == restart autonegotiation, 0 = normal operation
|
||||
*
|
||||
* DUPLEX: 1 == full duplex mode, 0 == half duplex mode
|
||||
*
|
||||
* COLLTEST: 1 == collision test enabled, 0 == normal operation
|
||||
*/
|
||||
|
||||
/*
|
||||
* PHY, BMSR Basic Mode Status Register
|
||||
*/
|
||||
#define PHY_BMSR_100BT4 0x8000
|
||||
#define PHY_BMSR_100BTXFULL 0x4000
|
||||
#define PHY_BMSR_100BTXHALF 0x2000
|
||||
#define PHY_BMSR_10BTFULL 0x1000
|
||||
#define PHY_BMSR_10BTHALF 0x0800
|
||||
#define PHY_BMSR_RSVD1 0x0400 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD2 0x0200 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD3 0x0100 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD4 0x0080 /* write as zero, don't care */
|
||||
#define PHY_BMSR_MFPRESUP 0x0040
|
||||
#define PHY_BMSR_AUTONEGCOMP 0x0020
|
||||
#define PHY_BMSR_REMFAULT 0x0010
|
||||
#define PHY_BMSR_CANAUTONEG 0x0008
|
||||
#define PHY_BMSR_LINKSTAT 0x0004
|
||||
#define PHY_BMSR_JABBER 0x0002
|
||||
#define PHY_BMSR_EXTENDED 0x0001
|
||||
|
||||
#ifdef __alpha__
|
||||
#undef vtophys
|
||||
#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
|
||||
|
@ -4,7 +4,10 @@ S = ${.CURDIR}/../..
|
||||
.PATH: $S/pci
|
||||
KMOD = sf
|
||||
SRCS = if_sf.c sf.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h
|
||||
SRCS += miibus_if.h
|
||||
CLEANFILES += sf.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h
|
||||
CLEANFILES += miibus_if.h
|
||||
|
||||
CFLAGS += ${DEBUG_FLAGS}
|
||||
|
||||
sf.h:
|
||||
@ -25,4 +28,7 @@ bus_if.h: $S/kern/makedevops.pl $S/kern/bus_if.m
|
||||
pci_if.h: $S/kern/makedevops.pl $S/pci/pci_if.m
|
||||
perl $S/kern/makedevops.pl -h $S/pci/pci_if.m
|
||||
|
||||
miibus_if.h: $S/kern/makedevops.pl $S/dev/mii/miibus_if.m
|
||||
perl $S/kern/makedevops.pl -h $S/dev/mii/miibus_if.m
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -3,8 +3,10 @@
|
||||
S = ${.CURDIR}/../..
|
||||
.PATH: $S/pci
|
||||
KMOD = wb
|
||||
SRCS = if_wb.c wb.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h
|
||||
CLEANFILES += wb.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h
|
||||
SRCS = if_wb.c wb.h bpf.h opt_bdg.h device_if.h
|
||||
SRCS += bus_if.h miibus_if.h pci_if.h
|
||||
CLEANFILES += wb.h bpf.h opt_bdg.h device_if.h
|
||||
CLEANFILES += bus_if.h miibus_if.h pci_if.h
|
||||
CFLAGS += ${DEBUG_FLAGS}
|
||||
|
||||
wb.h:
|
||||
@ -25,4 +27,7 @@ bus_if.h: $S/kern/makedevops.pl $S/kern/bus_if.m
|
||||
pci_if.h: $S/kern/makedevops.pl $S/pci/pci_if.m
|
||||
perl $S/kern/makedevops.pl -h $S/pci/pci_if.m
|
||||
|
||||
miibus_if.h: $S/kern/makedevops.pl $S/dev/mii/miibus_if.m
|
||||
perl $S/kern/makedevops.pl -h $S/dev/mii/miibus_if.m
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
528
sys/pci/if_sf.c
528
sys/pci/if_sf.c
@ -108,13 +108,16 @@
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
|
||||
#include "miibus_if.h"
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#define SF_USEIOSPACE
|
||||
|
||||
/* #define SF_BACKGROUND_AUTONEG */
|
||||
|
||||
#include <pci/if_sfreg.h>
|
||||
|
||||
#ifndef lint
|
||||
@ -128,10 +131,6 @@ static struct sf_type sf_devs[] = {
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static struct sf_type sf_phys[] = {
|
||||
{ 0, 0, "<MII-compliant physical interface>" }
|
||||
};
|
||||
|
||||
static int sf_probe __P((device_t));
|
||||
static int sf_attach __P((device_t));
|
||||
static int sf_detach __P((device_t));
|
||||
@ -166,12 +165,9 @@ static int sf_setvlan __P((struct sf_softc *, int, u_int32_t));
|
||||
static u_int8_t sf_read_eeprom __P((struct sf_softc *, int));
|
||||
static u_int32_t sf_calchash __P((caddr_t));
|
||||
|
||||
static int sf_phy_readreg __P((struct sf_softc *, int));
|
||||
static void sf_phy_writereg __P((struct sf_softc *, int, int));
|
||||
static void sf_autoneg_xmit __P((struct sf_softc *));
|
||||
static void sf_autoneg_mii __P((struct sf_softc *, int, int));
|
||||
static void sf_getmode_mii __P((struct sf_softc *));
|
||||
static void sf_setmode_mii __P((struct sf_softc *, int));
|
||||
static int sf_miibus_readreg __P((device_t, int, int));
|
||||
static int sf_miibus_writereg __P((device_t, int, int, int));
|
||||
static void sf_miibus_statchg __P((device_t));
|
||||
|
||||
static u_int32_t csr_read_4 __P((struct sf_softc *, int));
|
||||
static void csr_write_4 __P((struct sf_softc *, int, u_int32_t));
|
||||
@ -190,6 +186,16 @@ static device_method_t sf_methods[] = {
|
||||
DEVMETHOD(device_attach, sf_attach),
|
||||
DEVMETHOD(device_detach, sf_detach),
|
||||
DEVMETHOD(device_shutdown, sf_shutdown),
|
||||
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
||||
|
||||
/* MII interface */
|
||||
DEVMETHOD(miibus_readreg, sf_miibus_readreg),
|
||||
DEVMETHOD(miibus_writereg, sf_miibus_writereg),
|
||||
DEVMETHOD(miibus_statchg, sf_miibus_statchg),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -202,6 +208,7 @@ static driver_t sf_driver = {
|
||||
static devclass_t sf_devclass;
|
||||
|
||||
DRIVER_MODULE(sf, pci, sf_driver, sf_devclass, 0, 0);
|
||||
DRIVER_MODULE(miibus, sf, miibus_driver, miibus_devclass, 0, 0);
|
||||
|
||||
#define SF_SETBIT(sc, reg, x) \
|
||||
csr_write_4(sc, reg, csr_read_4(sc, reg) | x)
|
||||
@ -353,15 +360,18 @@ static int sf_setvlan(sc, idx, vlan)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sf_phy_readreg(sc, reg)
|
||||
struct sf_softc *sc;
|
||||
int reg;
|
||||
static int sf_miibus_readreg(dev, phy, reg)
|
||||
device_t dev;
|
||||
int phy, reg;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
int i;
|
||||
u_int32_t val = 0;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
for (i = 0; i < SF_TIMEOUT; i++) {
|
||||
val = csr_read_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg));
|
||||
val = csr_read_4(sc, SF_PHY_REG(phy, reg));
|
||||
if (val & SF_MII_DATAVALID)
|
||||
break;
|
||||
}
|
||||
@ -375,21 +385,42 @@ static int sf_phy_readreg(sc, reg)
|
||||
return(val & 0x0000FFFF);
|
||||
}
|
||||
|
||||
static void sf_phy_writereg(sc, reg, val)
|
||||
struct sf_softc *sc;
|
||||
int reg, val;
|
||||
static int sf_miibus_writereg(dev, phy, reg, val)
|
||||
device_t dev;
|
||||
int phy, reg, val;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
int i;
|
||||
int busy;
|
||||
|
||||
csr_write_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg), val);
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
csr_write_4(sc, SF_PHY_REG(phy, reg), val);
|
||||
|
||||
for (i = 0; i < SF_TIMEOUT; i++) {
|
||||
busy = csr_read_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg));
|
||||
busy = csr_read_4(sc, SF_PHY_REG(phy, reg));
|
||||
if (!(busy & SF_MII_BUSY))
|
||||
break;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void sf_miibus_statchg(dev)
|
||||
device_t dev;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -447,310 +478,6 @@ static void sf_setmulti(sc)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate an autonegotiation session.
|
||||
*/
|
||||
static void sf_autoneg_xmit(sc)
|
||||
struct sf_softc *sc;
|
||||
{
|
||||
u_int16_t phy_sts;
|
||||
|
||||
sf_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET);
|
||||
DELAY(500);
|
||||
while(sf_phy_readreg(sc, PHY_BMCR)
|
||||
& PHY_BMCR_RESET);
|
||||
|
||||
phy_sts = sf_phy_readreg(sc, PHY_BMCR);
|
||||
phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR;
|
||||
sf_phy_writereg(sc, PHY_BMCR, phy_sts);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke autonegotiation on a PHY.
|
||||
*/
|
||||
static void sf_autoneg_mii(sc, flag, verbose)
|
||||
struct sf_softc *sc;
|
||||
int flag;
|
||||
int verbose;
|
||||
{
|
||||
u_int16_t phy_sts = 0, media, advert, ability;
|
||||
struct ifnet *ifp;
|
||||
struct ifmedia *ifm;
|
||||
|
||||
ifm = &sc->ifmedia;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
ifm->ifm_media = IFM_ETHER | IFM_AUTO;
|
||||
|
||||
#ifndef FORCE_AUTONEG_TFOUR
|
||||
/*
|
||||
* First, see if autoneg is supported. If not, there's
|
||||
* no point in continuing.
|
||||
*/
|
||||
phy_sts = sf_phy_readreg(sc, PHY_BMSR);
|
||||
if (!(phy_sts & PHY_BMSR_CANAUTONEG)) {
|
||||
if (verbose)
|
||||
printf("sf%d: autonegotiation not supported\n",
|
||||
sc->sf_unit);
|
||||
ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (flag) {
|
||||
case SF_FLAG_FORCEDELAY:
|
||||
/*
|
||||
* XXX Never use this option anywhere but in the probe
|
||||
* routine: making the kernel stop dead in its tracks
|
||||
* for three whole seconds after we've gone multi-user
|
||||
* is really bad manners.
|
||||
*/
|
||||
sf_autoneg_xmit(sc);
|
||||
DELAY(5000000);
|
||||
break;
|
||||
case SF_FLAG_SCHEDDELAY:
|
||||
/*
|
||||
* Wait for the transmitter to go idle before starting
|
||||
* an autoneg session, otherwise sf_start() may clobber
|
||||
* our timeout, and we don't want to allow transmission
|
||||
* during an autoneg session since that can screw it up.
|
||||
*/
|
||||
if (sc->sf_tx_cnt) {
|
||||
sc->sf_want_auto = 1;
|
||||
return;
|
||||
}
|
||||
sf_autoneg_xmit(sc);
|
||||
ifp->if_timer = 5;
|
||||
sc->sf_autoneg = 1;
|
||||
sc->sf_want_auto = 0;
|
||||
return;
|
||||
break;
|
||||
case SF_FLAG_DELAYTIMEO:
|
||||
ifp->if_timer = 0;
|
||||
sc->sf_autoneg = 0;
|
||||
break;
|
||||
default:
|
||||
printf("sf%d: invalid autoneg flag: %d\n", sc->sf_unit, flag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) {
|
||||
if (verbose)
|
||||
printf("sf%d: autoneg complete, ", sc->sf_unit);
|
||||
phy_sts = sf_phy_readreg(sc, PHY_BMSR);
|
||||
} else {
|
||||
if (verbose)
|
||||
printf("sf%d: autoneg not complete, ", sc->sf_unit);
|
||||
}
|
||||
|
||||
media = sf_phy_readreg(sc, PHY_BMCR);
|
||||
|
||||
/* Link is good. Report modes and set duplex mode. */
|
||||
if (sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) {
|
||||
if (verbose)
|
||||
printf("link status good ");
|
||||
advert = sf_phy_readreg(sc, PHY_ANAR);
|
||||
ability = sf_phy_readreg(sc, PHY_LPAR);
|
||||
|
||||
if (advert & PHY_ANAR_100BT4 && ability & PHY_ANAR_100BT4) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_100_T4;
|
||||
media |= PHY_BMCR_SPEEDSEL;
|
||||
media &= ~PHY_BMCR_DUPLEX;
|
||||
printf("(100baseT4)\n");
|
||||
} else if (advert & PHY_ANAR_100BTXFULL &&
|
||||
ability & PHY_ANAR_100BTXFULL) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
media |= PHY_BMCR_SPEEDSEL;
|
||||
media |= PHY_BMCR_DUPLEX;
|
||||
printf("(full-duplex, 100Mbps)\n");
|
||||
} else if (advert & PHY_ANAR_100BTXHALF &&
|
||||
ability & PHY_ANAR_100BTXHALF) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX;
|
||||
media |= PHY_BMCR_SPEEDSEL;
|
||||
media &= ~PHY_BMCR_DUPLEX;
|
||||
printf("(half-duplex, 100Mbps)\n");
|
||||
} else if (advert & PHY_ANAR_10BTFULL &&
|
||||
ability & PHY_ANAR_10BTFULL) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX;
|
||||
media &= ~PHY_BMCR_SPEEDSEL;
|
||||
media |= PHY_BMCR_DUPLEX;
|
||||
printf("(full-duplex, 10Mbps)\n");
|
||||
} else if (advert & PHY_ANAR_10BTHALF &&
|
||||
ability & PHY_ANAR_10BTHALF) {
|
||||
ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
media &= ~PHY_BMCR_SPEEDSEL;
|
||||
media &= ~PHY_BMCR_DUPLEX;
|
||||
printf("(half-duplex, 10Mbps)\n");
|
||||
}
|
||||
|
||||
media &= ~PHY_BMCR_AUTONEGENBL;
|
||||
|
||||
/* Set ASIC's duplex mode to match the PHY. */
|
||||
sf_phy_writereg(sc, PHY_BMCR, media);
|
||||
if ((media & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
} else {
|
||||
if (verbose)
|
||||
printf("no carrier\n");
|
||||
}
|
||||
|
||||
sf_init(sc);
|
||||
|
||||
if (sc->sf_tx_pend) {
|
||||
sc->sf_autoneg = 0;
|
||||
sc->sf_tx_pend = 0;
|
||||
sf_start(ifp);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void sf_getmode_mii(sc)
|
||||
struct sf_softc *sc;
|
||||
{
|
||||
u_int16_t bmsr;
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
bmsr = sf_phy_readreg(sc, PHY_BMSR);
|
||||
if (bootverbose)
|
||||
printf("sf%d: PHY status word: %x\n", sc->sf_unit, bmsr);
|
||||
|
||||
/* fallback */
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
|
||||
if (bmsr & PHY_BMSR_10BTHALF) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 10Mbps half-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_10BTFULL) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 10Mbps full-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX;
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_100BTXHALF) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 100Mbps half-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifp->if_baudrate = 100000000;
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX;
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_100BTXFULL) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 100Mbps full-duplex mode supported\n",
|
||||
sc->sf_unit);
|
||||
ifp->if_baudrate = 100000000;
|
||||
ifmedia_add(&sc->ifmedia,
|
||||
IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
}
|
||||
|
||||
/* Some also support 100BaseT4. */
|
||||
if (bmsr & PHY_BMSR_100BT4) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: 100baseT4 mode supported\n", sc->sf_unit);
|
||||
ifp->if_baudrate = 100000000;
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_T4, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_T4;
|
||||
#ifdef FORCE_AUTONEG_TFOUR
|
||||
if (bootverbose)
|
||||
printf("sf%d: forcing on autoneg support for BT4\n",
|
||||
sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0 NULL):
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_AUTO;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (bmsr & PHY_BMSR_CANAUTONEG) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: autoneg supported\n", sc->sf_unit);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
|
||||
sc->ifmedia.ifm_media = IFM_ETHER|IFM_AUTO;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set speed and duplex mode.
|
||||
*/
|
||||
static void sf_setmode_mii(sc, media)
|
||||
struct sf_softc *sc;
|
||||
int media;
|
||||
{
|
||||
u_int16_t bmcr;
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
/*
|
||||
* If an autoneg session is in progress, stop it.
|
||||
*/
|
||||
if (sc->sf_autoneg) {
|
||||
printf("sf%d: canceling autoneg session\n", sc->sf_unit);
|
||||
ifp->if_timer = sc->sf_autoneg = sc->sf_want_auto = 0;
|
||||
bmcr = sf_phy_readreg(sc, PHY_BMCR);
|
||||
bmcr &= ~PHY_BMCR_AUTONEGENBL;
|
||||
sf_phy_writereg(sc, PHY_BMCR, bmcr);
|
||||
}
|
||||
|
||||
printf("sf%d: selecting MII, ", sc->sf_unit);
|
||||
|
||||
bmcr = sf_phy_readreg(sc, PHY_BMCR);
|
||||
|
||||
bmcr &= ~(PHY_BMCR_AUTONEGENBL|PHY_BMCR_SPEEDSEL|
|
||||
PHY_BMCR_DUPLEX|PHY_BMCR_LOOPBK);
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_100_T4) {
|
||||
printf("100Mbps/T4, half-duplex\n");
|
||||
bmcr |= PHY_BMCR_SPEEDSEL;
|
||||
bmcr &= ~PHY_BMCR_DUPLEX;
|
||||
}
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_100_TX) {
|
||||
printf("100Mbps, ");
|
||||
bmcr |= PHY_BMCR_SPEEDSEL;
|
||||
}
|
||||
|
||||
if (IFM_SUBTYPE(media) == IFM_10_T) {
|
||||
printf("10Mbps, ");
|
||||
bmcr &= ~PHY_BMCR_SPEEDSEL;
|
||||
}
|
||||
|
||||
if ((media & IFM_GMASK) == IFM_FDX) {
|
||||
printf("full duplex\n");
|
||||
bmcr |= PHY_BMCR_DUPLEX;
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
printf("half duplex\n");
|
||||
bmcr &= ~PHY_BMCR_DUPLEX;
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
|
||||
sf_phy_writereg(sc, PHY_BMCR, bmcr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set media options.
|
||||
*/
|
||||
@ -758,19 +485,11 @@ static int sf_ifmedia_upd(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct ifmedia *ifm;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
ifm = &sc->ifmedia;
|
||||
|
||||
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
|
||||
return(EINVAL);
|
||||
|
||||
if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
|
||||
sf_autoneg_mii(sc, SF_FLAG_SCHEDDELAY, 1);
|
||||
else {
|
||||
sf_setmode_mii(sc, ifm->ifm_media);
|
||||
}
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -783,42 +502,14 @@ static void sf_ifmedia_sts(ifp, ifmr)
|
||||
struct ifmediareq *ifmr;
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
u_int16_t advert = 0, ability = 0;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
ifmr->ifm_active = IFM_ETHER;
|
||||
|
||||
if (!(sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) {
|
||||
if (sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_SPEEDSEL)
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_TX;
|
||||
else
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T;
|
||||
if (sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_DUPLEX)
|
||||
ifmr->ifm_active |= IFM_FDX;
|
||||
else
|
||||
ifmr->ifm_active |= IFM_HDX;
|
||||
return;
|
||||
}
|
||||
|
||||
ability = sf_phy_readreg(sc, PHY_LPAR);
|
||||
advert = sf_phy_readreg(sc, PHY_ANAR);
|
||||
if (advert & PHY_ANAR_100BT4 &&
|
||||
ability & PHY_ANAR_100BT4) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_T4;
|
||||
} else if (advert & PHY_ANAR_100BTXFULL &&
|
||||
ability & PHY_ANAR_100BTXFULL) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
} else if (advert & PHY_ANAR_100BTXHALF &&
|
||||
ability & PHY_ANAR_100BTXHALF) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_100_TX|IFM_HDX;
|
||||
} else if (advert & PHY_ANAR_10BTFULL &&
|
||||
ability & PHY_ANAR_10BTFULL) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T|IFM_FDX;
|
||||
} else if (advert & PHY_ANAR_10BTHALF &&
|
||||
ability & PHY_ANAR_10BTHALF) {
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T|IFM_HDX;
|
||||
}
|
||||
mii_pollstat(mii);
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -830,6 +521,7 @@ static int sf_ioctl(ifp, command, data)
|
||||
{
|
||||
struct sf_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
struct mii_data *mii;
|
||||
int s, error = 0;
|
||||
|
||||
s = splimp();
|
||||
@ -856,7 +548,8 @@ static int sf_ioctl(ifp, command, data)
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
case SIOCSIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
@ -961,9 +654,6 @@ static int sf_attach(dev)
|
||||
u_int32_t command;
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
int media = IFM_ETHER|IFM_100_TX|IFM_FDX;
|
||||
struct sf_type *p;
|
||||
u_int16_t phy_vid, phy_did, phy_sts;
|
||||
int unit, rid, error = 0;
|
||||
|
||||
s = splimp();
|
||||
@ -1079,7 +769,7 @@ static int sf_attach(dev)
|
||||
|
||||
/* Allocate the descriptor queues. */
|
||||
sc->sf_ldata = contigmalloc(sizeof(struct sf_list_data), M_DEVBUF,
|
||||
M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
|
||||
M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0);
|
||||
|
||||
if (sc->sf_ldata == NULL) {
|
||||
printf("sf%d: no memory for list buffers!\n", unit);
|
||||
@ -1092,44 +782,9 @@ static int sf_attach(dev)
|
||||
|
||||
bzero(sc->sf_ldata, sizeof(struct sf_list_data));
|
||||
|
||||
if (bootverbose)
|
||||
printf("sf%d: probing for a PHY\n", sc->sf_unit);
|
||||
for (i = SF_PHYADDR_MIN; i < SF_PHYADDR_MAX + 1; i++) {
|
||||
if (bootverbose)
|
||||
printf("sf%d: checking address: %d\n",
|
||||
sc->sf_unit, i);
|
||||
sc->sf_phy_addr = i;
|
||||
sf_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET);
|
||||
DELAY(500);
|
||||
while(sf_phy_readreg(sc, PHY_BMCR)
|
||||
& PHY_BMCR_RESET);
|
||||
if ((phy_sts = sf_phy_readreg(sc, PHY_BMSR)))
|
||||
break;
|
||||
}
|
||||
if (phy_sts) {
|
||||
phy_vid = sf_phy_readreg(sc, PHY_VENID);
|
||||
phy_did = sf_phy_readreg(sc, PHY_DEVID);
|
||||
if (bootverbose)
|
||||
printf("sf%d: found PHY at address %d, ",
|
||||
sc->sf_unit, sc->sf_phy_addr);
|
||||
if (bootverbose)
|
||||
printf("vendor id: %x device id: %x\n",
|
||||
phy_vid, phy_did);
|
||||
p = sf_phys;
|
||||
while(p->sf_vid) {
|
||||
if (phy_vid == p->sf_vid &&
|
||||
(phy_did | 0x000F) == p->sf_did) {
|
||||
sc->sf_pinfo = p;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (sc->sf_pinfo == NULL)
|
||||
sc->sf_pinfo = &sf_phys[PHY_UNKNOWN];
|
||||
if (bootverbose)
|
||||
printf("sf%d: PHY type: %s\n",
|
||||
sc->sf_unit, sc->sf_pinfo->sf_name);
|
||||
} else {
|
||||
/* Do MII setup. */
|
||||
if (mii_phy_probe(dev, &sc->sf_miibus,
|
||||
sf_ifmedia_upd, sf_ifmedia_sts)) {
|
||||
printf("sf%d: MII without any phy!\n", sc->sf_unit);
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
|
||||
@ -1153,23 +808,6 @@ static int sf_attach(dev)
|
||||
ifp->if_baudrate = 10000000;
|
||||
ifp->if_snd.ifq_maxlen = SF_TX_DLIST_CNT - 1;
|
||||
|
||||
/*
|
||||
* Do ifmedia setup.
|
||||
*/
|
||||
ifmedia_init(&sc->ifmedia, 0, sf_ifmedia_upd, sf_ifmedia_sts);
|
||||
|
||||
sf_getmode_mii(sc);
|
||||
if (cold) {
|
||||
sf_autoneg_mii(sc, SF_FLAG_FORCEDELAY, 1);
|
||||
sf_stop(sc);
|
||||
} else {
|
||||
sf_init(sc);
|
||||
sf_autoneg_mii(sc, SF_FLAG_SCHEDDELAY, 1);
|
||||
}
|
||||
|
||||
media = sc->ifmedia.ifm_media;
|
||||
ifmedia_set(&sc->ifmedia, media);
|
||||
|
||||
/*
|
||||
* Call MI attach routines.
|
||||
*/
|
||||
@ -1200,12 +838,14 @@ static int sf_detach(dev)
|
||||
if_detach(ifp);
|
||||
sf_stop(sc);
|
||||
|
||||
bus_generic_detach(dev);
|
||||
device_delete_child(dev, sc->sf_miibus);
|
||||
|
||||
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
|
||||
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
|
||||
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
ifmedia_removeall(&sc->ifmedia);
|
||||
|
||||
splx(s);
|
||||
|
||||
@ -1490,12 +1130,14 @@ static void sf_init(xsc)
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
struct mii_data *mii;
|
||||
int i, s;
|
||||
|
||||
s = splimp();
|
||||
|
||||
sc = xsc;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
sf_stop(sc);
|
||||
sf_reset(sc);
|
||||
@ -1573,7 +1215,7 @@ static void sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
|
||||
|
||||
/* Make sure the duplex mode is set correctly. */
|
||||
if ((sc->ifmedia.ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
if ((mii->mii_media.ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
@ -1587,6 +1229,8 @@ static void sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RX_ENB|SF_ETHCTL_RXDMA_ENB);
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB);
|
||||
|
||||
mii_mediachg(mii);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
|
||||
@ -1673,11 +1317,6 @@ static void sf_start(ifp)
|
||||
if (ifp->if_flags & IFF_OACTIVE)
|
||||
return;
|
||||
|
||||
if (sc->sf_autoneg) {
|
||||
sc->sf_tx_pend = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
txprod = csr_read_4(sc, SF_TXDQ_PRODIDX);
|
||||
i = SF_IDX_HI(txprod) >> 4;
|
||||
|
||||
@ -1768,6 +1407,7 @@ static void sf_stats_update(xsc)
|
||||
{
|
||||
struct sf_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
struct mii_data *mii;
|
||||
struct sf_stats stats;
|
||||
u_int32_t *ptr;
|
||||
int i, s;
|
||||
@ -1776,6 +1416,7 @@ static void sf_stats_update(xsc)
|
||||
|
||||
sc = xsc;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
|
||||
ptr = (u_int32_t *)&stats;
|
||||
for (i = 0; i < sizeof(stats)/sizeof(u_int32_t); i++)
|
||||
@ -1789,6 +1430,8 @@ static void sf_stats_update(xsc)
|
||||
ifp->if_collisions += stats.sf_tx_single_colls +
|
||||
stats.sf_tx_multi_colls + stats.sf_tx_excess_colls;
|
||||
|
||||
mii_tick(mii);
|
||||
|
||||
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);
|
||||
|
||||
splx(s);
|
||||
@ -1803,22 +1446,9 @@ static void sf_watchdog(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
if (sc->sf_autoneg) {
|
||||
sf_autoneg_mii(sc, SF_FLAG_DELAYTIMEO, 1);
|
||||
if (!(ifp->if_flags & IFF_UP))
|
||||
sf_stop(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
ifp->if_oerrors++;
|
||||
printf("sf%d: watchdog timeout\n", sc->sf_unit);
|
||||
|
||||
if (sc->sf_pinfo != NULL) {
|
||||
if (!(sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
|
||||
printf("sf%d: no carrier - transceiver "
|
||||
"cable problem?\n", sc->sf_unit);
|
||||
}
|
||||
|
||||
sf_stop(sc);
|
||||
sf_reset(sc);
|
||||
sf_init(sc);
|
||||
|
@ -1010,20 +1010,14 @@ struct sf_list_data {
|
||||
|
||||
struct sf_softc {
|
||||
struct arpcom arpcom; /* interface info */
|
||||
struct ifmedia ifmedia; /* media info */
|
||||
bus_space_handle_t sf_bhandle; /* bus space handle */
|
||||
bus_space_tag_t sf_btag; /* bus space tag */
|
||||
void *sf_intrhand; /* interrupt handler cookie */
|
||||
struct resource *sf_irq; /* irq resource descriptor */
|
||||
struct resource *sf_res; /* mem/ioport resource */
|
||||
struct sf_type *sf_info; /* Starfire adapter info */
|
||||
struct sf_type *sf_pinfo; /* phy info */
|
||||
device_t sf_miibus;
|
||||
u_int8_t sf_unit; /* interface number */
|
||||
u_int8_t sf_type;
|
||||
u_int8_t sf_phy_addr; /* PHY address */
|
||||
u_int8_t sf_tx_pend; /* TX pending */
|
||||
u_int8_t sf_want_auto;
|
||||
u_int8_t sf_autoneg;
|
||||
struct sf_list_data *sf_ldata;
|
||||
int sf_tx_cnt;
|
||||
struct callout_handle sf_stat_ch;
|
||||
@ -1031,140 +1025,6 @@ struct sf_softc {
|
||||
|
||||
#define SF_TIMEOUT 1000
|
||||
|
||||
#define SF_FLAG_FORCEDELAY 1
|
||||
#define SF_FLAG_SCHEDDELAY 2
|
||||
#define SF_FLAG_DELAYTIMEO 3
|
||||
|
||||
/*
|
||||
* Texas Instruments PHY identifiers
|
||||
*/
|
||||
#define TI_PHY_VENDORID 0x4000
|
||||
#define TI_PHY_10BT 0x501F
|
||||
#define TI_PHY_100VGPMI 0x502F
|
||||
|
||||
/*
|
||||
* These ID values are for the NS DP83840A 10/100 PHY
|
||||
*/
|
||||
#define NS_PHY_VENDORID 0x2000
|
||||
#define NS_PHY_83840A 0x5C0F
|
||||
|
||||
/*
|
||||
* Level 1 10/100 PHY
|
||||
*/
|
||||
#define LEVEL1_PHY_VENDORID 0x7810
|
||||
#define LEVEL1_PHY_LXT970 0x000F
|
||||
|
||||
/*
|
||||
* Intel 82555 10/100 PHY
|
||||
*/
|
||||
#define INTEL_PHY_VENDORID 0x0A28
|
||||
#define INTEL_PHY_82555 0x015F
|
||||
|
||||
/*
|
||||
* SEEQ 80220 10/100 PHY
|
||||
*/
|
||||
#define SEEQ_PHY_VENDORID 0x0016
|
||||
#define SEEQ_PHY_80220 0xF83F
|
||||
|
||||
#define PHY_UNKNOWN 6
|
||||
|
||||
#define SF_PHYADDR_MIN 0x00
|
||||
#define SF_PHYADDR_MAX 0x1F
|
||||
|
||||
#define PHY_BMCR 0x00
|
||||
#define PHY_BMSR 0x01
|
||||
#define PHY_VENID 0x02
|
||||
#define PHY_DEVID 0x03
|
||||
#define PHY_ANAR 0x04
|
||||
#define PHY_LPAR 0x05
|
||||
#define PHY_ANEXP 0x06
|
||||
|
||||
#define PHY_ANAR_NEXTPAGE 0x8000
|
||||
#define PHY_ANAR_RSVD0 0x4000
|
||||
#define PHY_ANAR_TLRFLT 0x2000
|
||||
#define PHY_ANAR_RSVD1 0x1000
|
||||
#define PHY_ANAR_RSVD2 0x0800
|
||||
#define PHY_ANAR_RSVD3 0x0400
|
||||
#define PHY_ANAR_100BT4 0x0200
|
||||
#define PHY_ANAR_100BTXFULL 0x0100
|
||||
#define PHY_ANAR_100BTXHALF 0x0080
|
||||
#define PHY_ANAR_10BTFULL 0x0040
|
||||
#define PHY_ANAR_10BTHALF 0x0020
|
||||
#define PHY_ANAR_PROTO4 0x0010
|
||||
#define PHY_ANAR_PROTO3 0x0008
|
||||
#define PHY_ANAR_PROTO2 0x0004
|
||||
#define PHY_ANAR_PROTO1 0x0002
|
||||
#define PHY_ANAR_PROTO0 0x0001
|
||||
|
||||
/*
|
||||
* These are the register definitions for the PHY (physical layer
|
||||
* interface chip).
|
||||
*/
|
||||
/*
|
||||
* PHY BMCR Basic Mode Control Register
|
||||
*/
|
||||
#define PHY_BMCR_RESET 0x8000
|
||||
#define PHY_BMCR_LOOPBK 0x4000
|
||||
#define PHY_BMCR_SPEEDSEL 0x2000
|
||||
#define PHY_BMCR_AUTONEGENBL 0x1000
|
||||
#define PHY_BMCR_RSVD0 0x0800 /* write as zero */
|
||||
#define PHY_BMCR_ISOLATE 0x0400
|
||||
#define PHY_BMCR_AUTONEGRSTR 0x0200
|
||||
#define PHY_BMCR_DUPLEX 0x0100
|
||||
#define PHY_BMCR_COLLTEST 0x0080
|
||||
#define PHY_BMCR_RSVD1 0x0040 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD2 0x0020 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD3 0x0010 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD4 0x0008 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD5 0x0004 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD6 0x0002 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD7 0x0001 /* write as zero, don't care */
|
||||
/*
|
||||
* RESET: 1 == software reset, 0 == normal operation
|
||||
* Resets status and control registers to default values.
|
||||
* Relatches all hardware config values.
|
||||
*
|
||||
* LOOPBK: 1 == loopback operation enabled, 0 == normal operation
|
||||
*
|
||||
* SPEEDSEL: 1 == 100Mb/s, 0 == 10Mb/s
|
||||
* Link speed is selected byt his bit or if auto-negotiation if bit
|
||||
* 12 (AUTONEGENBL) is set (in which case the value of this register
|
||||
* is ignored).
|
||||
*
|
||||
* AUTONEGENBL: 1 == Autonegotiation enabled, 0 == Autonegotiation disabled
|
||||
* Bits 8 and 13 are ignored when autoneg is set, otherwise bits 8 and 13
|
||||
* determine speed and mode. Should be cleared and then set if PHY configured
|
||||
* for no autoneg on startup.
|
||||
*
|
||||
* ISOLATE: 1 == isolate PHY from MII, 0 == normal operation
|
||||
*
|
||||
* AUTONEGRSTR: 1 == restart autonegotiation, 0 = normal operation
|
||||
*
|
||||
* DUPLEX: 1 == full duplex mode, 0 == half duplex mode
|
||||
*
|
||||
* COLLTEST: 1 == collision test enabled, 0 == normal operation
|
||||
*/
|
||||
|
||||
/*
|
||||
* PHY, BMSR Basic Mode Status Register
|
||||
*/
|
||||
#define PHY_BMSR_100BT4 0x8000
|
||||
#define PHY_BMSR_100BTXFULL 0x4000
|
||||
#define PHY_BMSR_100BTXHALF 0x2000
|
||||
#define PHY_BMSR_10BTFULL 0x1000
|
||||
#define PHY_BMSR_10BTHALF 0x0800
|
||||
#define PHY_BMSR_RSVD1 0x0400 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD2 0x0200 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD3 0x0100 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD4 0x0080 /* write as zero, don't care */
|
||||
#define PHY_BMSR_MFPRESUP 0x0040
|
||||
#define PHY_BMSR_AUTONEGCOMP 0x0020
|
||||
#define PHY_BMSR_REMFAULT 0x0010
|
||||
#define PHY_BMSR_CANAUTONEG 0x0008
|
||||
#define PHY_BMSR_LINKSTAT 0x0004
|
||||
#define PHY_BMSR_JABBER 0x0002
|
||||
#define PHY_BMSR_EXTENDED 0x0001
|
||||
|
||||
#ifdef __alpha__
|
||||
#undef vtophys
|
||||
#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
|
||||
|
750
sys/pci/if_wb.c
750
sys/pci/if_wb.c
File diff suppressed because it is too large
Load Diff
@ -69,6 +69,7 @@
|
||||
#define WB_BUSCTL_CACHEALIGN 0x0000C000
|
||||
#define WB_BUSCTL_DES_BIGENDIAN 0x00100000
|
||||
#define WB_BUSCTL_WAIT 0x00200000
|
||||
#define WB_BUSCTL_MUSTBEONE 0x00400000
|
||||
|
||||
#define WB_SKIPLEN_1LONG 0x00000004
|
||||
#define WB_SKIPLEN_2LONG 0x00000008
|
||||
@ -76,6 +77,7 @@
|
||||
#define WB_SKIPLEN_4LONG 0x00000020
|
||||
#define WB_SKIPLEN_5LONG 0x00000040
|
||||
|
||||
#define WB_CACHEALIGN_NONE 0x00000000
|
||||
#define WB_CACHEALIGN_8LONG 0x00004000
|
||||
#define WB_CACHEALIGN_16LONG 0x00008000
|
||||
#define WB_CACHEALIGN_32LONG 0x0000C000
|
||||
@ -297,7 +299,14 @@ struct wb_txdesc {
|
||||
|
||||
#define WB_UNSENT 0x1234
|
||||
|
||||
#define WB_BUFBYTES (1024 * sizeof(u_int32_t))
|
||||
|
||||
struct wb_buf {
|
||||
u_int32_t wb_data[1024];
|
||||
};
|
||||
|
||||
struct wb_list_data {
|
||||
struct wb_buf wb_rxbufs[WB_RX_LIST_CNT];
|
||||
struct wb_desc wb_rx_list[WB_RX_LIST_CNT];
|
||||
struct wb_txdesc wb_tx_list[WB_TX_LIST_CNT];
|
||||
};
|
||||
@ -312,6 +321,7 @@ struct wb_chain {
|
||||
struct wb_chain_onefrag {
|
||||
struct wb_desc *wb_ptr;
|
||||
struct mbuf *wb_mbuf;
|
||||
void *wb_buf;
|
||||
struct wb_chain_onefrag *wb_nextdesc;
|
||||
u_int8_t wb_rlast;
|
||||
};
|
||||
@ -351,30 +361,23 @@ struct wb_mii_frame {
|
||||
#define WB_MII_WRITEOP 0x01
|
||||
#define WB_MII_TURNAROUND 0x02
|
||||
|
||||
#define WB_FLAG_FORCEDELAY 1
|
||||
#define WB_FLAG_SCHEDDELAY 2
|
||||
#define WB_FLAG_DELAYTIMEO 3
|
||||
|
||||
struct wb_softc {
|
||||
struct arpcom arpcom; /* interface info */
|
||||
struct ifmedia ifmedia; /* media info */
|
||||
device_t wb_miibus;
|
||||
bus_space_handle_t wb_bhandle;
|
||||
bus_space_tag_t wb_btag;
|
||||
struct resource *wb_res;
|
||||
struct resource *wb_irq;
|
||||
void *wb_intrhand;
|
||||
struct wb_type *wb_info; /* Winbond adapter info */
|
||||
struct wb_type *wb_pinfo; /* phy info */
|
||||
u_int8_t wb_unit; /* interface number */
|
||||
u_int8_t wb_type;
|
||||
u_int8_t wb_phy_addr; /* PHY address */
|
||||
u_int8_t wb_tx_pend; /* TX pending */
|
||||
u_int8_t wb_want_auto;
|
||||
u_int8_t wb_autoneg;
|
||||
u_int16_t wb_txthresh;
|
||||
int wb_cachesize;
|
||||
caddr_t wb_ldata_ptr;
|
||||
struct wb_list_data *wb_ldata;
|
||||
struct wb_chain_data wb_cdata;
|
||||
struct callout_handle wb_stat_ch;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -418,42 +421,9 @@ struct wb_softc {
|
||||
*/
|
||||
#define CP_DEVICEID_RL100 0x2011
|
||||
|
||||
/*
|
||||
* Texas Instruments PHY identifiers
|
||||
*/
|
||||
#define TI_PHY_VENDORID 0x4000
|
||||
#define TI_PHY_10BT 0x501F
|
||||
#define TI_PHY_100VGPMI 0x502F
|
||||
|
||||
/*
|
||||
* These ID values are for the NS DP83840A 10/100 PHY
|
||||
*/
|
||||
#define NS_PHY_VENDORID 0x2000
|
||||
#define NS_PHY_83840A 0x5C0F
|
||||
|
||||
/*
|
||||
* Level 1 10/100 PHY
|
||||
*/
|
||||
#define LEVEL1_PHY_VENDORID 0x7810
|
||||
#define LEVEL1_PHY_LXT970 0x000F
|
||||
|
||||
/*
|
||||
* Intel 82555 10/100 PHY
|
||||
*/
|
||||
#define INTEL_PHY_VENDORID 0x0A28
|
||||
#define INTEL_PHY_82555 0x015F
|
||||
|
||||
/*
|
||||
* SEEQ 80220 10/100 PHY
|
||||
*/
|
||||
#define SEEQ_PHY_VENDORID 0x0016
|
||||
#define SEEQ_PHY_80220 0xF83F
|
||||
|
||||
|
||||
/*
|
||||
* PCI low memory base and low I/O base register, and
|
||||
* other PCI registers. Note: some are only available on
|
||||
* the 3c905B, in particular those that related to power management.
|
||||
* other PCI registers.
|
||||
*/
|
||||
|
||||
#define WB_PCI_VENDOR_ID 0x00
|
||||
@ -461,6 +431,7 @@ struct wb_softc {
|
||||
#define WB_PCI_COMMAND 0x04
|
||||
#define WB_PCI_STATUS 0x06
|
||||
#define WB_PCI_CLASSCODE 0x09
|
||||
#define WB_PCI_CACHELEN 0x0C
|
||||
#define WB_PCI_LATENCY_TIMER 0x0D
|
||||
#define WB_PCI_HEADER_TYPE 0x0E
|
||||
#define WB_PCI_LOIO 0x10
|
||||
@ -487,105 +458,6 @@ struct wb_softc {
|
||||
#define WB_PME_EN 0x0010
|
||||
#define WB_PME_STATUS 0x8000
|
||||
|
||||
#define PHY_UNKNOWN 6
|
||||
|
||||
#define WB_PHYADDR_MIN 0x00
|
||||
#define WB_PHYADDR_MAX 0x1F
|
||||
|
||||
#define PHY_BMCR 0x00
|
||||
#define PHY_BMSR 0x01
|
||||
#define PHY_VENID 0x02
|
||||
#define PHY_DEVID 0x03
|
||||
#define PHY_ANAR 0x04
|
||||
#define PHY_LPAR 0x05
|
||||
#define PHY_ANEXP 0x06
|
||||
|
||||
#define PHY_ANAR_NEXTPAGE 0x8000
|
||||
#define PHY_ANAR_RSVD0 0x4000
|
||||
#define PHY_ANAR_TLRFLT 0x2000
|
||||
#define PHY_ANAR_RSVD1 0x1000
|
||||
#define PHY_ANAR_RSVD2 0x0800
|
||||
#define PHY_ANAR_RSVD3 0x0400
|
||||
#define PHY_ANAR_100BT4 0x0200
|
||||
#define PHY_ANAR_100BTXFULL 0x0100
|
||||
#define PHY_ANAR_100BTXHALF 0x0080
|
||||
#define PHY_ANAR_10BTFULL 0x0040
|
||||
#define PHY_ANAR_10BTHALF 0x0020
|
||||
#define PHY_ANAR_PROTO4 0x0010
|
||||
#define PHY_ANAR_PROTO3 0x0008
|
||||
#define PHY_ANAR_PROTO2 0x0004
|
||||
#define PHY_ANAR_PROTO1 0x0002
|
||||
#define PHY_ANAR_PROTO0 0x0001
|
||||
|
||||
/*
|
||||
* These are the register definitions for the PHY (physical layer
|
||||
* interface chip).
|
||||
*/
|
||||
/*
|
||||
* PHY BMCR Basic Mode Control Register
|
||||
*/
|
||||
#define PHY_BMCR_RESET 0x8000
|
||||
#define PHY_BMCR_LOOPBK 0x4000
|
||||
#define PHY_BMCR_SPEEDSEL 0x2000
|
||||
#define PHY_BMCR_AUTONEGENBL 0x1000
|
||||
#define PHY_BMCR_RSVD0 0x0800 /* write as zero */
|
||||
#define PHY_BMCR_ISOLATE 0x0400
|
||||
#define PHY_BMCR_AUTONEGRSTR 0x0200
|
||||
#define PHY_BMCR_DUPLEX 0x0100
|
||||
#define PHY_BMCR_COLLTEST 0x0080
|
||||
#define PHY_BMCR_RSVD1 0x0040 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD2 0x0020 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD3 0x0010 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD4 0x0008 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD5 0x0004 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD6 0x0002 /* write as zero, don't care */
|
||||
#define PHY_BMCR_RSVD7 0x0001 /* write as zero, don't care */
|
||||
/*
|
||||
* RESET: 1 == software reset, 0 == normal operation
|
||||
* Resets status and control registers to default values.
|
||||
* Relatches all hardware config values.
|
||||
*
|
||||
* LOOPBK: 1 == loopback operation enabled, 0 == normal operation
|
||||
*
|
||||
* SPEEDSEL: 1 == 100Mb/s, 0 == 10Mb/s
|
||||
* Link speed is selected byt his bit or if auto-negotiation if bit
|
||||
* 12 (AUTONEGENBL) is set (in which case the value of this register
|
||||
* is ignored).
|
||||
*
|
||||
* AUTONEGENBL: 1 == Autonegotiation enabled, 0 == Autonegotiation disabled
|
||||
* Bits 8 and 13 are ignored when autoneg is set, otherwise bits 8 and 13
|
||||
* determine speed and mode. Should be cleared and then set if PHY configured
|
||||
* for no autoneg on startup.
|
||||
*
|
||||
* ISOLATE: 1 == isolate PHY from MII, 0 == normal operation
|
||||
*
|
||||
* AUTONEGRSTR: 1 == restart autonegotiation, 0 = normal operation
|
||||
*
|
||||
* DUPLEX: 1 == full duplex mode, 0 == half duplex mode
|
||||
*
|
||||
* COLLTEST: 1 == collision test enabled, 0 == normal operation
|
||||
*/
|
||||
|
||||
/*
|
||||
* PHY, BMSR Basic Mode Status Register
|
||||
*/
|
||||
#define PHY_BMSR_100BT4 0x8000
|
||||
#define PHY_BMSR_100BTXFULL 0x4000
|
||||
#define PHY_BMSR_100BTXHALF 0x2000
|
||||
#define PHY_BMSR_10BTFULL 0x1000
|
||||
#define PHY_BMSR_10BTHALF 0x0800
|
||||
#define PHY_BMSR_RSVD1 0x0400 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD2 0x0200 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD3 0x0100 /* write as zero, don't care */
|
||||
#define PHY_BMSR_RSVD4 0x0080 /* write as zero, don't care */
|
||||
#define PHY_BMSR_MFPRESUP 0x0040
|
||||
#define PHY_BMSR_AUTONEGCOMP 0x0020
|
||||
#define PHY_BMSR_REMFAULT 0x0010
|
||||
#define PHY_BMSR_CANAUTONEG 0x0008
|
||||
#define PHY_BMSR_LINKSTAT 0x0004
|
||||
#define PHY_BMSR_JABBER 0x0002
|
||||
#define PHY_BMSR_EXTENDED 0x0001
|
||||
|
||||
#ifdef __alpha__
|
||||
#undef vtophys
|
||||
#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
|
||||
|
Loading…
Reference in New Issue
Block a user