xlphy.c revision 109514
150120Swpaul/* $NetBSD: exphy.c,v 1.16 1999/04/23 04:24:32 thorpej Exp $ */ 250120Swpaul 350120Swpaul/*- 450120Swpaul * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 550120Swpaul * All rights reserved. 650120Swpaul * 750120Swpaul * This code is derived from software contributed to The NetBSD Foundation 850120Swpaul * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 950120Swpaul * NASA Ames Research Center, and by Frank van der Linden. 1050120Swpaul * 1150120Swpaul * Redistribution and use in source and binary forms, with or without 1250120Swpaul * modification, are permitted provided that the following conditions 1350120Swpaul * are met: 1450120Swpaul * 1. Redistributions of source code must retain the above copyright 1550120Swpaul * notice, this list of conditions and the following disclaimer. 1650120Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1750120Swpaul * notice, this list of conditions and the following disclaimer in the 1850120Swpaul * documentation and/or other materials provided with the distribution. 1950120Swpaul * 3. All advertising materials mentioning features or use of this software 2050120Swpaul * must display the following acknowledgement: 2150120Swpaul * This product includes software developed by the NetBSD 2250120Swpaul * Foundation, Inc. and its contributors. 2350120Swpaul * 4. Neither the name of The NetBSD Foundation nor the names of its 2450120Swpaul * contributors may be used to endorse or promote products derived 2550120Swpaul * from this software without specific prior written permission. 2650120Swpaul * 2750120Swpaul * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2850120Swpaul * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2950120Swpaul * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3050120Swpaul * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3150120Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3250120Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3350120Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3450120Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3550120Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3650120Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3750120Swpaul * POSSIBILITY OF SUCH DAMAGE. 3850120Swpaul */ 3950120Swpaul 4050120Swpaul/* 4150120Swpaul * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 4250120Swpaul * 4350120Swpaul * Redistribution and use in source and binary forms, with or without 4450120Swpaul * modification, are permitted provided that the following conditions 4550120Swpaul * are met: 4650120Swpaul * 1. Redistributions of source code must retain the above copyright 4750120Swpaul * notice, this list of conditions and the following disclaimer. 4850120Swpaul * 2. Redistributions in binary form must reproduce the above copyright 4950120Swpaul * notice, this list of conditions and the following disclaimer in the 5050120Swpaul * documentation and/or other materials provided with the distribution. 5150120Swpaul * 3. All advertising materials mentioning features or use of this software 5250120Swpaul * must display the following acknowledgement: 5350120Swpaul * This product includes software developed by Manuel Bouyer. 5450120Swpaul * 4. The name of the author may not be used to endorse or promote products 5550120Swpaul * derived from this software without specific prior written permission. 5650120Swpaul * 5750120Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 5850120Swpaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 5950120Swpaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 6050120Swpaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 6150120Swpaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 6250120Swpaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 6350120Swpaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 6450120Swpaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 6550120Swpaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 6650120Swpaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6750120Swpaul */ 6850120Swpaul 6950120Swpaul/* 7050120Swpaul * driver for 3Com internal PHYs 7150120Swpaul */ 7250120Swpaul 7350120Swpaul#include <sys/param.h> 7450120Swpaul#include <sys/systm.h> 7550120Swpaul#include <sys/kernel.h> 7650120Swpaul#include <sys/socket.h> 7750120Swpaul#include <sys/module.h> 7850120Swpaul#include <sys/bus.h> 7950120Swpaul 8050120Swpaul#include <net/if.h> 8150120Swpaul#include <net/if_media.h> 8250120Swpaul 8350120Swpaul#include <dev/mii/mii.h> 8450120Swpaul#include <dev/mii/miivar.h> 85109514Sobrien#include "miidevs.h" 8650120Swpaul 8750120Swpaul#include "miibus_if.h" 8850120Swpaul 8950120Swpaul#if !defined(lint) 9050120Swpaulstatic const char rcsid[] = 9150758Swpaul "$FreeBSD: head/sys/dev/mii/exphy.c 109514 2003-01-19 02:59:34Z obrien $"; 9250120Swpaul#endif 9350120Swpaul 94105135Salfredstatic int exphy_probe(device_t); 95105135Salfredstatic int exphy_attach(device_t); 9650120Swpaul 9750120Swpaulstatic device_method_t exphy_methods[] = { 9850120Swpaul /* device interface */ 9950120Swpaul DEVMETHOD(device_probe, exphy_probe), 10050120Swpaul DEVMETHOD(device_attach, exphy_attach), 10195722Sphk DEVMETHOD(device_detach, mii_phy_detach), 10250120Swpaul DEVMETHOD(device_shutdown, bus_generic_shutdown), 10350120Swpaul { 0, 0 } 10450120Swpaul}; 10550120Swpaul 10650120Swpaulstatic devclass_t exphy_devclass; 10750120Swpaul 10850120Swpaulstatic driver_t exphy_driver = { 10950120Swpaul "xlphy", 11050120Swpaul exphy_methods, 11150120Swpaul sizeof(struct mii_softc) 11250120Swpaul}; 11350120Swpaul 11450120SwpaulDRIVER_MODULE(xlphy, miibus, exphy_driver, exphy_devclass, 0, 0); 11550120Swpaul 11692739Salfredstatic int exphy_service(struct mii_softc *, struct mii_data *, int); 11792739Salfredstatic void exphy_reset(struct mii_softc *); 11850120Swpaul 119105135Salfredstatic int 120105135Salfredexphy_probe(dev) 12150120Swpaul device_t dev; 12250120Swpaul{ 12350120Swpaul struct mii_attach_args *ma; 12450120Swpaul device_t parent; 12550120Swpaul 12650120Swpaul ma = device_get_ivars(dev); 12750120Swpaul parent = device_get_parent(device_get_parent(dev)); 12850120Swpaul 12950120Swpaul /* 13050120Swpaul * Argh, 3Com PHY reports oui == 0 model == 0! 13150120Swpaul */ 13250577Swpaul if ((MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || 13350577Swpaul MII_MODEL(ma->mii_id2) != 0) && 13450577Swpaul (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_BROADCOM || 13599439Sbenno MII_MODEL(ma->mii_id2) != MII_MODEL_BROADCOM_3C905C)) 13650120Swpaul return (ENXIO); 13750120Swpaul 13850120Swpaul /* 13950120Swpaul * Make sure the parent is an `ex'. 14050120Swpaul */ 14150120Swpaul if (strcmp(device_get_name(parent), "xl") != 0) 14250120Swpaul return (ENXIO); 14350120Swpaul 14450577Swpaul if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0) 14550577Swpaul device_set_desc(dev, "3Com internal media interface"); 14650577Swpaul else 14799439Sbenno device_set_desc(dev, MII_STR_BROADCOM_3C905C); 14850120Swpaul 14950120Swpaul return (0); 15050120Swpaul} 15150120Swpaul 152105135Salfredstatic int 153105135Salfredexphy_attach(dev) 15450120Swpaul device_t dev; 15550120Swpaul{ 15650120Swpaul struct mii_softc *sc; 15750120Swpaul struct mii_attach_args *ma; 15850120Swpaul struct mii_data *mii; 15950120Swpaul 16050120Swpaul sc = device_get_softc(dev); 16150120Swpaul ma = device_get_ivars(dev); 16250120Swpaul sc->mii_dev = device_get_parent(dev); 16350120Swpaul mii = device_get_softc(sc->mii_dev); 16450120Swpaul 16550120Swpaul /* 16650120Swpaul * The 3Com PHY can never be isolated, so never allow non-zero 16750120Swpaul * instances! 16850120Swpaul */ 16950120Swpaul if (mii->mii_instance != 0) { 17050120Swpaul device_printf(dev, "ignoring this PHY, non-zero instance\n"); 17150120Swpaul return(ENXIO); 17250120Swpaul } 17350120Swpaul 17450758Swpaul LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 17550758Swpaul 17650758Swpaul sc->mii_inst = mii->mii_instance; 17750758Swpaul sc->mii_phy = ma->mii_phyno; 17850758Swpaul sc->mii_service = exphy_service; 17950758Swpaul sc->mii_pdata = mii; 18050120Swpaul mii->mii_instance++; 18150120Swpaul 18250120Swpaul sc->mii_flags |= MIIF_NOISOLATE; 18350120Swpaul 18450120Swpaul#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 18550120Swpaul 18650120Swpaul#if 0 /* See above. */ 18750120Swpaul ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 18850120Swpaul BMCR_ISO); 18950120Swpaul#endif 19050120Swpaul 19150120Swpaul ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), 19250120Swpaul BMCR_LOOP|BMCR_S100); 19350120Swpaul 19450120Swpaul exphy_reset(sc); 19550120Swpaul 19650120Swpaul sc->mii_capabilities = 19750120Swpaul PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 19850120Swpaul device_printf(dev, " "); 19995723Sphk mii_phy_add_media(sc); 20050120Swpaul printf("\n"); 20150120Swpaul#undef ADD 20250120Swpaul MIIBUS_MEDIAINIT(sc->mii_dev); 20350120Swpaul return(0); 20450120Swpaul} 20550120Swpaul 20684145Sjlemonstatic int 20750120Swpaulexphy_service(sc, mii, cmd) 20850120Swpaul struct mii_softc *sc; 20950120Swpaul struct mii_data *mii; 21050120Swpaul int cmd; 21150120Swpaul{ 21250120Swpaul struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 21350120Swpaul 21450120Swpaul /* 21550120Swpaul * We can't isolate the 3Com PHY, so it has to be the only one! 21650120Swpaul */ 21750120Swpaul if (IFM_INST(ife->ifm_media) != sc->mii_inst) 21850120Swpaul panic("exphy_service: can't isolate 3Com PHY"); 21950120Swpaul 22050120Swpaul switch (cmd) { 22150120Swpaul case MII_POLLSTAT: 22250120Swpaul break; 22350120Swpaul 22450120Swpaul case MII_MEDIACHG: 22550120Swpaul /* 22650120Swpaul * If the interface is not up, don't do anything. 22750120Swpaul */ 22850120Swpaul if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 22950120Swpaul break; 23050120Swpaul 23195723Sphk mii_phy_setmedia(sc); 23250120Swpaul break; 23350120Swpaul 23450120Swpaul case MII_TICK: 23550120Swpaul /* 23684145Sjlemon * Is the interface even up? 23750120Swpaul */ 23884145Sjlemon if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 23950120Swpaul return (0); 24050120Swpaul 24150120Swpaul /* 24284145Sjlemon * Only used for autonegotiation. 24350120Swpaul */ 24484145Sjlemon if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 24584145Sjlemon break; 24650120Swpaul 24750120Swpaul /* 24850120Swpaul * The 3Com PHY's autonegotiation doesn't need to be 24950120Swpaul * kicked; it continues in the background. 25050120Swpaul */ 25150120Swpaul break; 25250120Swpaul } 25350120Swpaul 25450120Swpaul /* Update the media status. */ 25550120Swpaul ukphy_status(sc); 25650120Swpaul 25750120Swpaul /* Callback if something changed. */ 25884145Sjlemon mii_phy_update(sc, cmd); 25950120Swpaul return (0); 26050120Swpaul} 26150120Swpaul 26284145Sjlemonstatic void 26395723Sphkexphy_reset(struct mii_softc *sc) 26450120Swpaul{ 26550120Swpaul 26650120Swpaul mii_phy_reset(sc); 26750120Swpaul 26850120Swpaul /* 26950120Swpaul * XXX 3Com PHY doesn't set the BMCR properly after 27050120Swpaul * XXX reset, which breaks autonegotiation. 27150120Swpaul */ 27250120Swpaul PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX); 27350120Swpaul} 274