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 * 2050120Swpaul * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2150120Swpaul * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2250120Swpaul * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2350120Swpaul * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2450120Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2550120Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2650120Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2750120Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2850120Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2950120Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3050120Swpaul * POSSIBILITY OF SUCH DAMAGE. 3150120Swpaul */ 3250120Swpaul 33139749Simp/*- 3450120Swpaul * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 3550120Swpaul * 3650120Swpaul * Redistribution and use in source and binary forms, with or without 3750120Swpaul * modification, are permitted provided that the following conditions 3850120Swpaul * are met: 3950120Swpaul * 1. Redistributions of source code must retain the above copyright 4050120Swpaul * notice, this list of conditions and the following disclaimer. 4150120Swpaul * 2. Redistributions in binary form must reproduce the above copyright 4250120Swpaul * notice, this list of conditions and the following disclaimer in the 4350120Swpaul * documentation and/or other materials provided with the distribution. 4450120Swpaul * 4550120Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4650120Swpaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 4750120Swpaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 4850120Swpaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 4950120Swpaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5050120Swpaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5150120Swpaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5250120Swpaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5350120Swpaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5450120Swpaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5550120Swpaul */ 5650120Swpaul 57129844Smarius#include <sys/cdefs.h> 58129844Smarius__FBSDID("$FreeBSD$"); 59129844Smarius 6050120Swpaul/* 6150120Swpaul * driver for 3Com internal PHYs 6250120Swpaul */ 6350120Swpaul 6450120Swpaul#include <sys/param.h> 6550120Swpaul#include <sys/systm.h> 6650120Swpaul#include <sys/kernel.h> 6750120Swpaul#include <sys/socket.h> 6850120Swpaul#include <sys/module.h> 6950120Swpaul#include <sys/bus.h> 7050120Swpaul 7150120Swpaul#include <net/if.h> 7250120Swpaul#include <net/if_media.h> 7350120Swpaul 7450120Swpaul#include <dev/mii/mii.h> 7550120Swpaul#include <dev/mii/miivar.h> 76109514Sobrien#include "miidevs.h" 7750120Swpaul 7850120Swpaul#include "miibus_if.h" 7950120Swpaul 80226154Smariusstatic int xlphy_probe(device_t); 81226154Smariusstatic int xlphy_attach(device_t); 8250120Swpaul 83226154Smariusstatic device_method_t xlphy_methods[] = { 8450120Swpaul /* device interface */ 85226154Smarius DEVMETHOD(device_probe, xlphy_probe), 86226154Smarius DEVMETHOD(device_attach, xlphy_attach), 8795722Sphk DEVMETHOD(device_detach, mii_phy_detach), 8850120Swpaul DEVMETHOD(device_shutdown, bus_generic_shutdown), 89229093Shselasky DEVMETHOD_END 9050120Swpaul}; 9150120Swpaul 92226154Smariusstatic devclass_t xlphy_devclass; 9350120Swpaul 94226154Smariusstatic driver_t xlphy_driver = { 9550120Swpaul "xlphy", 96226154Smarius xlphy_methods, 9750120Swpaul sizeof(struct mii_softc) 9850120Swpaul}; 9950120Swpaul 100226154SmariusDRIVER_MODULE(xlphy, miibus, xlphy_driver, xlphy_devclass, 0, 0); 10150120Swpaul 102226154Smariusstatic int xlphy_service(struct mii_softc *, struct mii_data *, int); 103226154Smariusstatic void xlphy_reset(struct mii_softc *); 10450120Swpaul 105165988Smarius/* 106165988Smarius * Some 3Com internal PHYs report zero for OUI and model, others use 107165988Smarius * actual values. 108165988Smarius * Note that the 3Com internal PHYs having OUI 0x105a and model 0 are 109165988Smarius * handled fine by ukphy(4); they can be isolated and don't require 110165988Smarius * special treatment after reset. 111165988Smarius */ 112226154Smariusstatic const struct mii_phydesc xlphys[] = { 113165988Smarius { 0, 0, "3Com internal media interface" }, 114221407Smarius MII_PHY_DESC(xxBROADCOM, 3C905C), 115165988Smarius MII_PHY_END 116165988Smarius}; 117221407Smarius 118226154Smariusstatic const struct mii_phy_funcs xlphy_funcs = { 119226154Smarius xlphy_service, 120221407Smarius ukphy_status, 121226154Smarius xlphy_reset 122221407Smarius}; 123221407Smarius 124105135Salfredstatic int 125226154Smariusxlphy_probe(device_t dev) 12650120Swpaul{ 12750120Swpaul 128165988Smarius if (strcmp(device_get_name(device_get_parent(device_get_parent(dev))), 129165988Smarius "xl") == 0) 130226154Smarius return (mii_phy_dev_probe(dev, xlphys, BUS_PROBE_DEFAULT)); 131165988Smarius return (ENXIO); 13250120Swpaul} 13350120Swpaul 134105135Salfredstatic int 135226154Smariusxlphy_attach(device_t dev) 13650120Swpaul{ 13750120Swpaul 138213364Smarius /* 139213364Smarius * The 3Com PHY can never be isolated. 140213364Smarius */ 141221407Smarius mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, 142226154Smarius &xlphy_funcs, 1); 143165988Smarius return (0); 14450120Swpaul} 14550120Swpaul 14684145Sjlemonstatic int 147226154Smariusxlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 14850120Swpaul{ 14950120Swpaul 15050120Swpaul switch (cmd) { 15150120Swpaul case MII_POLLSTAT: 15250120Swpaul break; 15350120Swpaul 15450120Swpaul case MII_MEDIACHG: 15550120Swpaul /* 15650120Swpaul * If the interface is not up, don't do anything. 15750120Swpaul */ 15850120Swpaul if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 15950120Swpaul break; 16050120Swpaul 16195723Sphk mii_phy_setmedia(sc); 16250120Swpaul break; 16350120Swpaul 16450120Swpaul case MII_TICK: 16550120Swpaul /* 16684145Sjlemon * Is the interface even up? 16750120Swpaul */ 16884145Sjlemon if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 16950120Swpaul return (0); 17050120Swpaul 17150120Swpaul /* 17250120Swpaul * The 3Com PHY's autonegotiation doesn't need to be 17350120Swpaul * kicked; it continues in the background. 17450120Swpaul */ 17550120Swpaul break; 17650120Swpaul } 17750120Swpaul 17850120Swpaul /* Update the media status. */ 179221407Smarius PHY_STATUS(sc); 18050120Swpaul 18150120Swpaul /* Callback if something changed. */ 18284145Sjlemon mii_phy_update(sc, cmd); 18350120Swpaul return (0); 18450120Swpaul} 18550120Swpaul 18684145Sjlemonstatic void 187226154Smariusxlphy_reset(struct mii_softc *sc) 18850120Swpaul{ 18950120Swpaul 19050120Swpaul mii_phy_reset(sc); 19150120Swpaul 19250120Swpaul /* 19350120Swpaul * XXX 3Com PHY doesn't set the BMCR properly after 19450120Swpaul * XXX reset, which breaks autonegotiation. 19550120Swpaul */ 19650120Swpaul PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX); 19750120Swpaul} 198