pnaphy.c revision 95702
190926Snectar/* 2233294Sstas * Copyright (c) 2000 Berkeley Software Design, Inc. 3233294Sstas * Copyright (c) 1997, 1998, 1999, 2000 4233294Sstas * Bill Paul <wpaul@osd.bsdi.com>. All rights reserved. 590926Snectar * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 990926Snectar * 1. Redistributions of source code must retain the above copyright 10233294Sstas * notice, this list of conditions and the following disclaimer. 11233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 1290926Snectar * notice, this list of conditions and the following disclaimer in the 13233294Sstas * documentation and/or other materials provided with the distribution. 14233294Sstas * 3. All advertising materials mentioning features or use of this software 15233294Sstas * must display the following acknowledgement: 1690926Snectar * This product includes software developed by Bill Paul. 17233294Sstas * 4. Neither the name of the author nor the names of any co-contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2090926Snectar * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 25233294Sstas * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26233294Sstas * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27233294Sstas * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28233294Sstas * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29233294Sstas * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30233294Sstas * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31233294Sstas * THE POSSIBILITY OF SUCH DAMAGE. 3290926Snectar * 3390926Snectar * $FreeBSD: head/sys/dev/mii/pnaphy.c 95702 2002-04-29 05:32:44Z phk $ 3490926Snectar */ 3590926Snectar 36233294Sstas/* 3790926Snectar * driver for homePNA PHYs 3890926Snectar * This is really just a stub that allows us to identify homePNA-based 39233294Sstas * transceicers and display the link status. MII-based homePNA PHYs 4090926Snectar * only support one media type and no autonegotiation. If we were 4190926Snectar * really clever, we could tweak some of the vendor-specific registers 4290926Snectar * to optimize the link. 4390926Snectar */ 4490926Snectar 4590926Snectar#include <sys/param.h> 4690926Snectar#include <sys/systm.h> 4790926Snectar#include <sys/kernel.h> 4890926Snectar#include <sys/malloc.h> 4990926Snectar#include <sys/socket.h> 50178825Sdfr#include <sys/errno.h> 5190926Snectar#include <sys/module.h> 5290926Snectar#include <sys/bus.h> 5390926Snectar 5490926Snectar#include <net/if.h> 5590926Snectar#include <net/if_media.h> 5690926Snectar 57178825Sdfr 5890926Snectar#include <dev/mii/mii.h> 5990926Snectar#include <dev/mii/miivar.h> 6090926Snectar#include <dev/mii/miidevs.h> 6190926Snectar 6290926Snectar#include "miibus_if.h" 6390926Snectar 6490926Snectar#if !defined(lint) 6590926Snectarstatic const char rcsid[] = 6690926Snectar "$FreeBSD: head/sys/dev/mii/pnaphy.c 95702 2002-04-29 05:32:44Z phk $"; 6790926Snectar#endif 6890926Snectar 6990926Snectarstatic int pnaphy_probe (device_t); 7090926Snectarstatic int pnaphy_attach (device_t); 7190926Snectarstatic int pnaphy_detach (device_t); 7290926Snectar 7390926Snectarstatic device_method_t pnaphy_methods[] = { 7490926Snectar /* device interface */ 7590926Snectar DEVMETHOD(device_probe, pnaphy_probe), 7690926Snectar DEVMETHOD(device_attach, pnaphy_attach), 7790926Snectar DEVMETHOD(device_detach, pnaphy_detach), 78178825Sdfr DEVMETHOD(device_shutdown, bus_generic_shutdown), 79178825Sdfr { 0, 0 } 8090926Snectar}; 8190926Snectar 8290926Snectarstatic devclass_t pnaphy_devclass; 8390926Snectar 8490926Snectarstatic driver_t pnaphy_driver = { 8590926Snectar "pnaphy", 8690926Snectar pnaphy_methods, 8790926Snectar sizeof(struct mii_softc) 8890926Snectar}; 8990926Snectar 9090926SnectarDRIVER_MODULE(pnaphy, miibus, pnaphy_driver, pnaphy_devclass, 0, 0); 9190926Snectar 92233294Sstasstatic int pnaphy_service(struct mii_softc *, struct mii_data *,int); 93233294Sstas 94233294Sstasstatic int 95233294Sstaspnaphy_probe(dev) 96233294Sstas device_t dev; 97233294Sstas{ 98233294Sstas 99233294Sstas struct mii_attach_args *ma; 100233294Sstas 10190926Snectar ma = device_get_ivars(dev); 10290926Snectar 10390926Snectar if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_AMD && 10490926Snectar MII_MODEL(ma->mii_id2) == MII_MODEL_AMD_79c978) { 10590926Snectar device_set_desc(dev, MII_STR_AMD_79c978); 10690926Snectar return(0); 10790926Snectar } 10890926Snectar 10990926Snectar return(ENXIO); 11090926Snectar} 111178825Sdfr 11290926Snectarstatic int 11390926Snectarpnaphy_attach(dev) 114 device_t dev; 115{ 116 struct mii_softc *sc; 117 struct mii_attach_args *ma; 118 struct mii_data *mii; 119 const char *sep = ""; 120 121 sc = device_get_softc(dev); 122 ma = device_get_ivars(dev); 123 sc->mii_dev = device_get_parent(dev); 124 mii = device_get_softc(sc->mii_dev); 125 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 126 127 sc->mii_inst = mii->mii_instance; 128 sc->mii_phy = ma->mii_phyno; 129 sc->mii_service = pnaphy_service; 130 sc->mii_pdata = mii; 131 132 mii->mii_instance++; 133 134 sc->mii_flags |= MIIF_NOISOLATE; 135 136#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 137#define PRINT(s) printf("%s%s", sep, s); sep = ", " 138 139 mii_phy_reset(sc); 140 141 sc->mii_capabilities = 142 PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 143 device_printf(dev, " "); 144 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) 145 printf("no media present"); 146 else { 147 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, sc->mii_inst), 0); 148 PRINT("HomePNA"); 149 } 150 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 151 BMCR_ISO); 152 153 printf("\n"); 154 155#undef ADD 156#undef PRINT 157 158 MIIBUS_MEDIAINIT(sc->mii_dev); 159 160 return(0); 161} 162 163static int pnaphy_detach(dev) 164 device_t dev; 165{ 166 struct mii_softc *sc; 167 struct mii_data *mii; 168 169 sc = device_get_softc(dev); 170 mii = device_get_softc(device_get_parent(dev)); 171 mii_phy_auto_stop(sc); 172 sc->mii_dev = NULL; 173 LIST_REMOVE(sc, mii_list); 174 175 return(0); 176} 177 178int 179pnaphy_service(sc, mii, cmd) 180 struct mii_softc *sc; 181 struct mii_data *mii; 182 int cmd; 183{ 184 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 185 int reg; 186 187 switch (cmd) { 188 case MII_POLLSTAT: 189 /* 190 * If we're not polling our PHY instance, just return. 191 */ 192 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 193 return (0); 194 break; 195 196 case MII_MEDIACHG: 197 /* 198 * If the media indicates a different PHY instance, 199 * isolate ourselves. 200 */ 201 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 202 reg = PHY_READ(sc, MII_BMCR); 203 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 204 return (0); 205 } 206 207 /* 208 * If the interface is not up, don't do anything. 209 */ 210 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 211 break; 212 213 switch (IFM_SUBTYPE(ife->ifm_media)) { 214 case IFM_AUTO: 215 case IFM_10_T: 216 case IFM_100_TX: 217 case IFM_100_T4: 218 return (EINVAL); 219 default: 220 /* 221 * BMCR data is stored in the ifmedia entry. 222 */ 223 PHY_WRITE(sc, MII_ANAR, 224 mii_anar(ife->ifm_media)); 225 PHY_WRITE(sc, MII_BMCR, ife->ifm_data); 226 } 227 break; 228 229 case MII_TICK: 230 /* 231 * If we're not currently selected, just return. 232 */ 233 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 234 return (0); 235 if (mii_phy_tick(sc) == EJUSTRETURN) 236 return (0); 237 break; 238 } 239 240 /* Update the media status. */ 241 ukphy_status(sc); 242 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) 243 mii->mii_media_active = IFM_ETHER|IFM_HPNA_1; 244 245 /* Callback if something changed. */ 246 mii_phy_update(sc, cmd); 247 return (0); 248} 249