xlphy.c revision 99439
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> 8550120Swpaul#include <dev/mii/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 99439 2002-07-05 11:02:17Z benno $"; 9250120Swpaul#endif 9350120Swpaul 9492739Salfredstatic int exphy_probe (device_t); 9592739Salfredstatic 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 11950120Swpaulstatic int exphy_probe(dev) 12050120Swpaul device_t dev; 12150120Swpaul{ 12250120Swpaul struct mii_attach_args *ma; 12350120Swpaul device_t parent; 12450120Swpaul 12550120Swpaul ma = device_get_ivars(dev); 12650120Swpaul parent = device_get_parent(device_get_parent(dev)); 12750120Swpaul 12850120Swpaul /* 12950120Swpaul * Argh, 3Com PHY reports oui == 0 model == 0! 13050120Swpaul */ 13150577Swpaul if ((MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || 13250577Swpaul MII_MODEL(ma->mii_id2) != 0) && 13350577Swpaul (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_BROADCOM || 13499439Sbenno MII_MODEL(ma->mii_id2) != MII_MODEL_BROADCOM_3C905C)) 13550120Swpaul return (ENXIO); 13650120Swpaul 13750120Swpaul /* 13850120Swpaul * Make sure the parent is an `ex'. 13950120Swpaul */ 14050120Swpaul if (strcmp(device_get_name(parent), "xl") != 0) 14150120Swpaul return (ENXIO); 14250120Swpaul 14350577Swpaul if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0) 14450577Swpaul device_set_desc(dev, "3Com internal media interface"); 14550577Swpaul else 14699439Sbenno device_set_desc(dev, MII_STR_BROADCOM_3C905C); 14750120Swpaul 14850120Swpaul return (0); 14950120Swpaul} 15050120Swpaul 15150120Swpaulstatic int exphy_attach(dev) 15250120Swpaul device_t dev; 15350120Swpaul{ 15450120Swpaul struct mii_softc *sc; 15550120Swpaul struct mii_attach_args *ma; 15650120Swpaul struct mii_data *mii; 15750120Swpaul 15850120Swpaul sc = device_get_softc(dev); 15950120Swpaul ma = device_get_ivars(dev); 16050120Swpaul sc->mii_dev = device_get_parent(dev); 16150120Swpaul mii = device_get_softc(sc->mii_dev); 16250120Swpaul 16350120Swpaul /* 16450120Swpaul * The 3Com PHY can never be isolated, so never allow non-zero 16550120Swpaul * instances! 16650120Swpaul */ 16750120Swpaul if (mii->mii_instance != 0) { 16850120Swpaul device_printf(dev, "ignoring this PHY, non-zero instance\n"); 16950120Swpaul return(ENXIO); 17050120Swpaul } 17150120Swpaul 17250758Swpaul LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 17350758Swpaul 17450758Swpaul sc->mii_inst = mii->mii_instance; 17550758Swpaul sc->mii_phy = ma->mii_phyno; 17650758Swpaul sc->mii_service = exphy_service; 17750758Swpaul sc->mii_pdata = mii; 17850120Swpaul mii->mii_instance++; 17950120Swpaul 18050120Swpaul sc->mii_flags |= MIIF_NOISOLATE; 18150120Swpaul 18250120Swpaul#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 18350120Swpaul 18450120Swpaul#if 0 /* See above. */ 18550120Swpaul ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 18650120Swpaul BMCR_ISO); 18750120Swpaul#endif 18850120Swpaul 18950120Swpaul ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), 19050120Swpaul BMCR_LOOP|BMCR_S100); 19150120Swpaul 19250120Swpaul exphy_reset(sc); 19350120Swpaul 19450120Swpaul sc->mii_capabilities = 19550120Swpaul PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 19650120Swpaul device_printf(dev, " "); 19795723Sphk mii_phy_add_media(sc); 19850120Swpaul printf("\n"); 19950120Swpaul#undef ADD 20050120Swpaul MIIBUS_MEDIAINIT(sc->mii_dev); 20150120Swpaul return(0); 20250120Swpaul} 20350120Swpaul 20484145Sjlemonstatic int 20550120Swpaulexphy_service(sc, mii, cmd) 20650120Swpaul struct mii_softc *sc; 20750120Swpaul struct mii_data *mii; 20850120Swpaul int cmd; 20950120Swpaul{ 21050120Swpaul struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 21150120Swpaul 21250120Swpaul /* 21350120Swpaul * We can't isolate the 3Com PHY, so it has to be the only one! 21450120Swpaul */ 21550120Swpaul if (IFM_INST(ife->ifm_media) != sc->mii_inst) 21650120Swpaul panic("exphy_service: can't isolate 3Com PHY"); 21750120Swpaul 21850120Swpaul switch (cmd) { 21950120Swpaul case MII_POLLSTAT: 22050120Swpaul break; 22150120Swpaul 22250120Swpaul case MII_MEDIACHG: 22350120Swpaul /* 22450120Swpaul * If the interface is not up, don't do anything. 22550120Swpaul */ 22650120Swpaul if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 22750120Swpaul break; 22850120Swpaul 22995723Sphk mii_phy_setmedia(sc); 23050120Swpaul break; 23150120Swpaul 23250120Swpaul case MII_TICK: 23350120Swpaul /* 23484145Sjlemon * Is the interface even up? 23550120Swpaul */ 23684145Sjlemon if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 23750120Swpaul return (0); 23850120Swpaul 23950120Swpaul /* 24084145Sjlemon * Only used for autonegotiation. 24150120Swpaul */ 24284145Sjlemon if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 24384145Sjlemon break; 24450120Swpaul 24550120Swpaul /* 24650120Swpaul * The 3Com PHY's autonegotiation doesn't need to be 24750120Swpaul * kicked; it continues in the background. 24850120Swpaul */ 24950120Swpaul break; 25050120Swpaul } 25150120Swpaul 25250120Swpaul /* Update the media status. */ 25350120Swpaul ukphy_status(sc); 25450120Swpaul 25550120Swpaul /* Callback if something changed. */ 25684145Sjlemon mii_phy_update(sc, cmd); 25750120Swpaul return (0); 25850120Swpaul} 25950120Swpaul 26084145Sjlemonstatic void 26195723Sphkexphy_reset(struct mii_softc *sc) 26250120Swpaul{ 26350120Swpaul 26450120Swpaul mii_phy_reset(sc); 26550120Swpaul 26650120Swpaul /* 26750120Swpaul * XXX 3Com PHY doesn't set the BMCR properly after 26850120Swpaul * XXX reset, which breaks autonegotiation. 26950120Swpaul */ 27050120Swpaul PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX); 27150120Swpaul} 272