xlphy.c revision 109514
122347Spst/* $NetBSD: exphy.c,v 1.16 1999/04/23 04:24:32 thorpej Exp $ */ 222347Spst 329964Sache/*- 429964Sache * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 522347Spst * All rights reserved. 622347Spst * 722347Spst * This code is derived from software contributed to The NetBSD Foundation 822347Spst * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 922347Spst * NASA Ames Research Center, and by Frank van der Linden. 1022347Spst * 1122347Spst * Redistribution and use in source and binary forms, with or without 1222347Spst * modification, are permitted provided that the following conditions 1322347Spst * are met: 1422347Spst * 1. Redistributions of source code must retain the above copyright 1522347Spst * notice, this list of conditions and the following disclaimer. 1622347Spst * 2. Redistributions in binary form must reproduce the above copyright 1722347Spst * notice, this list of conditions and the following disclaimer in the 1822347Spst * documentation and/or other materials provided with the distribution. 1922347Spst * 3. All advertising materials mentioning features or use of this software 2022347Spst * must display the following acknowledgement: 2122347Spst * This product includes software developed by the NetBSD 2222347Spst * Foundation, Inc. and its contributors. 2322347Spst * 4. Neither the name of The NetBSD Foundation nor the names of its 2422347Spst * contributors may be used to endorse or promote products derived 2522347Spst * from this software without specific prior written permission. 2622347Spst * 2722347Spst * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2822347Spst * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2922347Spst * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3022347Spst * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3122347Spst * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3222347Spst * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3322347Spst * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3422347Spst * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3522347Spst * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3622347Spst * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3722347Spst * POSSIBILITY OF SUCH DAMAGE. 3822347Spst */ 3922347Spst 4022347Spst/* 4122347Spst * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 4222347Spst * 4322347Spst * Redistribution and use in source and binary forms, with or without 4422347Spst * modification, are permitted provided that the following conditions 4522347Spst * are met: 4622347Spst * 1. Redistributions of source code must retain the above copyright 4722347Spst * notice, this list of conditions and the following disclaimer. 4822347Spst * 2. Redistributions in binary form must reproduce the above copyright 4922347Spst * notice, this list of conditions and the following disclaimer in the 5022347Spst * documentation and/or other materials provided with the distribution. 5122347Spst * 3. All advertising materials mentioning features or use of this software 5222347Spst * must display the following acknowledgement: 5322347Spst * This product includes software developed by Manuel Bouyer. 5422347Spst * 4. The name of the author may not be used to endorse or promote products 5522347Spst * derived from this software without specific prior written permission. 5622347Spst * 5722347Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 5822347Spst * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 5922347Spst * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 6022347Spst * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 6122347Spst * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 6222347Spst * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 6322347Spst * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 6422347Spst * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 6522347Spst * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 6622347Spst * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6722347Spst */ 6822347Spst 6922347Spst/* 7022347Spst * driver for 3Com internal PHYs 7122347Spst */ 7222347Spst 7322347Spst#include <sys/param.h> 7422347Spst#include <sys/systm.h> 7522347Spst#include <sys/kernel.h> 7622347Spst#include <sys/socket.h> 7722347Spst#include <sys/module.h> 7822347Spst#include <sys/bus.h> 7922347Spst 8022347Spst#include <net/if.h> 8122347Spst#include <net/if_media.h> 8222347Spst 8322347Spst#include <dev/mii/mii.h> 8422347Spst#include <dev/mii/miivar.h> 8522347Spst#include "miidevs.h" 8622347Spst 8722347Spst#include "miibus_if.h" 8822347Spst 8922347Spst#if !defined(lint) 9022347Spststatic const char rcsid[] = 9122347Spst "$FreeBSD: head/sys/dev/mii/exphy.c 109514 2003-01-19 02:59:34Z obrien $"; 9222347Spst#endif 9322347Spst 9422347Spststatic int exphy_probe(device_t); 9522347Spststatic int exphy_attach(device_t); 9622347Spst 9722347Spststatic device_method_t exphy_methods[] = { 9822347Spst /* device interface */ 9922347Spst DEVMETHOD(device_probe, exphy_probe), 10022347Spst DEVMETHOD(device_attach, exphy_attach), 10122347Spst DEVMETHOD(device_detach, mii_phy_detach), 10222347Spst DEVMETHOD(device_shutdown, bus_generic_shutdown), 10322347Spst { 0, 0 } 10422347Spst}; 10522347Spst 10622347Spststatic devclass_t exphy_devclass; 10722347Spst 10822347Spststatic driver_t exphy_driver = { 10922347Spst "xlphy", 11022347Spst exphy_methods, 11122347Spst sizeof(struct mii_softc) 11222347Spst}; 11322347Spst 11422347SpstDRIVER_MODULE(xlphy, miibus, exphy_driver, exphy_devclass, 0, 0); 11522347Spst 11622347Spststatic int exphy_service(struct mii_softc *, struct mii_data *, int); 11722347Spststatic void exphy_reset(struct mii_softc *); 11822347Spst 11922347Spststatic int 12022347Spstexphy_probe(dev) 12122347Spst device_t dev; 12222347Spst{ 12322347Spst struct mii_attach_args *ma; 12422347Spst device_t parent; 12522347Spst 12622347Spst ma = device_get_ivars(dev); 12722347Spst parent = device_get_parent(device_get_parent(dev)); 12822347Spst 12922347Spst /* 13022347Spst * Argh, 3Com PHY reports oui == 0 model == 0! 13122347Spst */ 13222347Spst if ((MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || 13322347Spst MII_MODEL(ma->mii_id2) != 0) && 13422347Spst (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_BROADCOM || 13522347Spst MII_MODEL(ma->mii_id2) != MII_MODEL_BROADCOM_3C905C)) 13622347Spst return (ENXIO); 13722347Spst 13822347Spst /* 13922347Spst * Make sure the parent is an `ex'. 14022347Spst */ 14122347Spst if (strcmp(device_get_name(parent), "xl") != 0) 14222347Spst return (ENXIO); 14322347Spst 14422347Spst if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0) 14522347Spst device_set_desc(dev, "3Com internal media interface"); 14622347Spst else 14722347Spst device_set_desc(dev, MII_STR_BROADCOM_3C905C); 14822347Spst 14922347Spst return (0); 15022347Spst} 15122347Spst 15222347Spststatic int 15322347Spstexphy_attach(dev) 15422347Spst device_t dev; 15522347Spst{ 15622347Spst struct mii_softc *sc; 15722347Spst struct mii_attach_args *ma; 15822347Spst struct mii_data *mii; 15922347Spst 16022347Spst sc = device_get_softc(dev); 16122347Spst ma = device_get_ivars(dev); 16222347Spst sc->mii_dev = device_get_parent(dev); 16322347Spst mii = device_get_softc(sc->mii_dev); 16422347Spst 16522347Spst /* 16622347Spst * The 3Com PHY can never be isolated, so never allow non-zero 16722347Spst * instances! 16822347Spst */ 16922347Spst if (mii->mii_instance != 0) { 17022347Spst device_printf(dev, "ignoring this PHY, non-zero instance\n"); 17122347Spst return(ENXIO); 17222347Spst } 17322347Spst 17422347Spst LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 17522347Spst 17622347Spst sc->mii_inst = mii->mii_instance; 17722347Spst sc->mii_phy = ma->mii_phyno; 17822347Spst sc->mii_service = exphy_service; 17922347Spst sc->mii_pdata = mii; 18022347Spst mii->mii_instance++; 18122347Spst 18222347Spst sc->mii_flags |= MIIF_NOISOLATE; 18322347Spst 18422347Spst#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 18522347Spst 18622347Spst#if 0 /* See above. */ 18722347Spst ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 18822347Spst BMCR_ISO); 18922347Spst#endif 19022347Spst 19122347Spst ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), 19222347Spst BMCR_LOOP|BMCR_S100); 19322347Spst 19422347Spst exphy_reset(sc); 19522347Spst 19622347Spst sc->mii_capabilities = 19722347Spst PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 19822347Spst device_printf(dev, " "); 19922347Spst mii_phy_add_media(sc); 20022347Spst printf("\n"); 20122347Spst#undef ADD 20222347Spst MIIBUS_MEDIAINIT(sc->mii_dev); 20322347Spst return(0); 20422347Spst} 20522347Spst 20622347Spststatic int 20722347Spstexphy_service(sc, mii, cmd) 20822347Spst struct mii_softc *sc; 20922347Spst struct mii_data *mii; 21022347Spst int cmd; 21122347Spst{ 21222347Spst struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 21322347Spst 21422347Spst /* 21522347Spst * We can't isolate the 3Com PHY, so it has to be the only one! 21622347Spst */ 21722347Spst if (IFM_INST(ife->ifm_media) != sc->mii_inst) 21822347Spst panic("exphy_service: can't isolate 3Com PHY"); 21922347Spst 22022347Spst switch (cmd) { 22122347Spst case MII_POLLSTAT: 22222347Spst break; 22322347Spst 22422347Spst case MII_MEDIACHG: 22522347Spst /* 22622347Spst * If the interface is not up, don't do anything. 22722347Spst */ 22822347Spst if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 22922347Spst break; 23022347Spst 23122347Spst mii_phy_setmedia(sc); 23222347Spst break; 23322347Spst 23422347Spst case MII_TICK: 23522347Spst /* 23622347Spst * Is the interface even up? 23722347Spst */ 23822347Spst if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 23922347Spst return (0); 24022347Spst 24122347Spst /* 24222347Spst * Only used for autonegotiation. 24322347Spst */ 24422347Spst if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 24522347Spst break; 24622347Spst 24722347Spst /* 24822347Spst * The 3Com PHY's autonegotiation doesn't need to be 24922347Spst * kicked; it continues in the background. 25022347Spst */ 25122347Spst break; 25222347Spst } 25322347Spst 25422347Spst /* Update the media status. */ 25522347Spst ukphy_status(sc); 25622347Spst 25722347Spst /* Callback if something changed. */ 25822347Spst mii_phy_update(sc, cmd); 25922347Spst return (0); 26022347Spst} 26122347Spst 26222347Spststatic void 26322347Spstexphy_reset(struct mii_softc *sc) 26422347Spst{ 26522347Spst 26622347Spst mii_phy_reset(sc); 26722347Spst 26822347Spst /* 26922347Spst * XXX 3Com PHY doesn't set the BMCR properly after 27022347Spst * XXX reset, which breaks autonegotiation. 27122347Spst */ 27222347Spst PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX); 27322347Spst} 27422347Spst