Annotation of sys/dev/mii/tlphy.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: tlphy.c,v 1.18 2006/12/27 19:11:09 kettenis Exp $ */
! 2: /* $NetBSD: tlphy.c,v 1.26 2000/07/04 03:29:00 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
! 10: * NASA Ames Research Center.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by the NetBSD
! 23: * Foundation, Inc. and its contributors.
! 24: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 25: * contributors may be used to endorse or promote products derived
! 26: * from this software without specific prior written permission.
! 27: *
! 28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 38: * POSSIBILITY OF SUCH DAMAGE.
! 39: */
! 40:
! 41: /*
! 42: * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
! 43: *
! 44: * Redistribution and use in source and binary forms, with or without
! 45: * modification, are permitted provided that the following conditions
! 46: * are met:
! 47: * 1. Redistributions of source code must retain the above copyright
! 48: * notice, this list of conditions and the following disclaimer.
! 49: * 2. Redistributions in binary form must reproduce the above copyright
! 50: * notice, this list of conditions and the following disclaimer in the
! 51: * documentation and/or other materials provided with the distribution.
! 52: * 3. All advertising materials mentioning features or use of this software
! 53: * must display the following acknowledgement:
! 54: * This product includes software developed by Manuel Bouyer.
! 55: * 4. The name of the author may not be used to endorse or promote products
! 56: * derived from this software without specific prior written permission.
! 57: *
! 58: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 59: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 60: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 61: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 62: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 63: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 64: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 65: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 66: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 67: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 68: */
! 69:
! 70: /*
! 71: * Driver for Texas Instruments's ThunderLAN PHYs
! 72: */
! 73:
! 74: #include <sys/param.h>
! 75: #include <sys/systm.h>
! 76: #include <sys/kernel.h>
! 77: #include <sys/device.h>
! 78: #include <sys/socket.h>
! 79: #include <sys/errno.h>
! 80:
! 81: #include <machine/bus.h>
! 82:
! 83: #include <net/if.h>
! 84: #include <net/if_media.h>
! 85:
! 86: #include <netinet/in.h>
! 87: #include <netinet/if_ether.h>
! 88:
! 89: #include <dev/mii/mii.h>
! 90: #include <dev/mii/miivar.h>
! 91: #include <dev/mii/miidevs.h>
! 92:
! 93: #include <dev/mii/tlphyreg.h>
! 94: #include <dev/mii/tlphyvar.h>
! 95:
! 96: /* ThunderLAN PHY can only be on a ThunderLAN */
! 97: #include <dev/pci/if_tlreg.h>
! 98:
! 99: struct tlphy_softc {
! 100: struct mii_softc sc_mii; /* generic PHY */
! 101: int sc_tlphycap;
! 102: int sc_need_acomp;
! 103: };
! 104:
! 105: struct cfdriver tlphy_cd = {
! 106: NULL, "tlphy", DV_DULL
! 107: };
! 108:
! 109: int tlphymatch(struct device *, void *, void *);
! 110: void tlphyattach(struct device *, struct device *, void *);
! 111:
! 112: struct cfattach tlphy_ca = {
! 113: sizeof(struct tlphy_softc), tlphymatch, tlphyattach, mii_phy_detach,
! 114: mii_phy_activate
! 115: };
! 116:
! 117: int tlphy_service(struct mii_softc *, struct mii_data *, int);
! 118: int tlphy_mii_phy_auto(struct tlphy_softc *, int);
! 119: void tlphy_acomp(struct tlphy_softc *);
! 120: void tlphy_status(struct mii_softc *);
! 121:
! 122: const struct mii_phy_funcs tlphy_funcs = {
! 123: tlphy_service, tlphy_status, mii_phy_reset,
! 124: };
! 125:
! 126: static const struct mii_phydesc tlphys[] = {
! 127: { MII_OUI_xxTI, MII_MODEL_xxTI_TLAN10T,
! 128: MII_STR_xxTI_TLAN10T },
! 129:
! 130: { 0, 0,
! 131: NULL },
! 132: };
! 133:
! 134: int
! 135: tlphymatch(struct device *parent, void *match, void *aux)
! 136: {
! 137: struct mii_attach_args *ma = aux;
! 138:
! 139: if (mii_phy_match(ma, tlphys) != NULL)
! 140: return (10);
! 141:
! 142: return (0);
! 143: }
! 144:
! 145: void
! 146: tlphyattach(struct device *parent, struct device *self, void *aux)
! 147: {
! 148: struct tlphy_softc *sc = (struct tlphy_softc *)self;
! 149: struct tl_softc *tlsc = (struct tl_softc *)self->dv_parent;
! 150: struct mii_attach_args *ma = aux;
! 151: struct mii_data *mii = ma->mii_data;
! 152: const struct mii_phydesc *mpd;
! 153:
! 154: mpd = mii_phy_match(ma, tlphys);
! 155: printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
! 156:
! 157: sc->sc_mii.mii_inst = mii->mii_instance;
! 158: sc->sc_mii.mii_phy = ma->mii_phyno;
! 159: sc->sc_mii.mii_funcs = &tlphy_funcs;
! 160: sc->sc_mii.mii_pdata = mii;
! 161: sc->sc_mii.mii_flags = ma->mii_flags;
! 162:
! 163: sc->sc_mii.mii_flags &= ~MIIF_NOISOLATE;
! 164: PHY_RESET(&sc->sc_mii);
! 165: sc->sc_mii.mii_flags |= MIIF_NOISOLATE;
! 166:
! 167: /*
! 168: * Note that if we're on a device that also supports 100baseTX,
! 169: * we are not going to want to use the built-in 10baseT port,
! 170: * since there will be another PHY on the MII wired up to the
! 171: * UTP connector. The parent indicates this to us by specifying
! 172: * the TLPHY_MEDIA_NO_10_T bit.
! 173: */
! 174: sc->sc_tlphycap = tlsc->tl_product->tp_tlphymedia;
! 175: if ((sc->sc_tlphycap & TLPHY_MEDIA_NO_10_T) == 0)
! 176: sc->sc_mii.mii_capabilities =
! 177: PHY_READ(&sc->sc_mii, MII_BMSR) & ma->mii_capmask;
! 178: else
! 179: sc->sc_mii.mii_capabilities = 0;
! 180:
! 181:
! 182: if (sc->sc_tlphycap & TLPHY_MEDIA_10_2)
! 183: ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER,
! 184: IFM_10_2, 0, sc->sc_mii.mii_inst), 0, NULL);
! 185: if (sc->sc_tlphycap & TLPHY_MEDIA_10_5)
! 186: ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER,
! 187: IFM_10_5, 0, sc->sc_mii.mii_inst), 0, NULL);
! 188: if (sc->sc_mii.mii_capabilities & BMSR_MEDIAMASK)
! 189: mii_phy_add_media(&sc->sc_mii);
! 190: }
! 191:
! 192: int
! 193: tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd)
! 194: {
! 195: struct tlphy_softc *sc = (struct tlphy_softc *)self;
! 196: struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
! 197: int reg;
! 198:
! 199: if ((sc->sc_mii.mii_dev.dv_flags & DVF_ACTIVE) == 0)
! 200: return (ENXIO);
! 201:
! 202: if ((sc->sc_mii.mii_flags & MIIF_DOINGAUTO) == 0 && sc->sc_need_acomp)
! 203: tlphy_acomp(sc);
! 204:
! 205: switch (cmd) {
! 206: case MII_POLLSTAT:
! 207: /*
! 208: * If we're not polling our PHY instance, just return.
! 209: */
! 210: if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst)
! 211: return (0);
! 212: break;
! 213:
! 214: case MII_MEDIACHG:
! 215: /*
! 216: * If the media indicates a different PHY instance,
! 217: * isolate ourselves.
! 218: */
! 219: if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst) {
! 220: reg = PHY_READ(&sc->sc_mii, MII_BMCR);
! 221: PHY_WRITE(&sc->sc_mii, MII_BMCR, reg | BMCR_ISO);
! 222: return (0);
! 223: }
! 224:
! 225: /*
! 226: * If the interface is not up, don't do anything.
! 227: */
! 228: if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
! 229: break;
! 230:
! 231: switch (IFM_SUBTYPE(ife->ifm_media)) {
! 232: case IFM_AUTO:
! 233: /*
! 234: * The ThunderLAN PHY doesn't self-configure after
! 235: * an autonegotiation cycle, so there's no such
! 236: * thing as "already in auto mode".
! 237: */
! 238: (void) tlphy_mii_phy_auto(sc, 1);
! 239: break;
! 240: case IFM_10_2:
! 241: case IFM_10_5:
! 242: PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
! 243: PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, CTRL_AUISEL);
! 244: delay(100000);
! 245: break;
! 246: default:
! 247: PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, 0);
! 248: delay(100000);
! 249: mii_phy_setmedia(&sc->sc_mii);
! 250: }
! 251: break;
! 252:
! 253: case MII_TICK:
! 254: /*
! 255: * XXX WHAT ABOUT CHECKING LINK ON THE BNC/AUI?!
! 256: */
! 257:
! 258: /*
! 259: * If we're not currently selected, just return.
! 260: */
! 261: if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst)
! 262: return (0);
! 263:
! 264: if (mii_phy_tick(&sc->sc_mii) == EJUSTRETURN)
! 265: return (0);
! 266: break;
! 267:
! 268: case MII_DOWN:
! 269: mii_phy_down(&sc->sc_mii);
! 270: return (0);
! 271: }
! 272:
! 273: /* Update the media status. */
! 274: mii_phy_status(&sc->sc_mii);
! 275:
! 276: /* Callback if something changed. */
! 277: mii_phy_update(&sc->sc_mii, cmd);
! 278: return (0);
! 279: }
! 280:
! 281: void
! 282: tlphy_status(struct mii_softc *physc)
! 283: {
! 284: struct tlphy_softc *sc = (void *) physc;
! 285: struct mii_data *mii = sc->sc_mii.mii_pdata;
! 286: int bmsr, bmcr, tlctrl;
! 287:
! 288: mii->mii_media_status = IFM_AVALID;
! 289: mii->mii_media_active = IFM_ETHER;
! 290:
! 291: bmcr = PHY_READ(&sc->sc_mii, MII_BMCR);
! 292: if (bmcr & BMCR_ISO) {
! 293: mii->mii_media_active |= IFM_NONE;
! 294: mii->mii_media_status = 0;
! 295: return;
! 296: }
! 297:
! 298: tlctrl = PHY_READ(&sc->sc_mii, MII_TLPHY_CTRL);
! 299: if (tlctrl & CTRL_AUISEL) {
! 300: mii->mii_media_status = 0;
! 301: mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media;
! 302: return;
! 303: }
! 304:
! 305: bmsr = PHY_READ(&sc->sc_mii, MII_BMSR) |
! 306: PHY_READ(&sc->sc_mii, MII_BMSR);
! 307: if (bmsr & BMSR_LINK)
! 308: mii->mii_media_status |= IFM_ACTIVE;
! 309:
! 310: if (bmcr & BMCR_LOOP)
! 311: mii->mii_media_active |= IFM_LOOP;
! 312:
! 313: /*
! 314: * Grr, braindead ThunderLAN PHY doesn't have any way to
! 315: * tell which media is actually active. (Note it also
! 316: * doesn't self-configure after autonegotiation.) We
! 317: * just have to report what's in the BMCR.
! 318: */
! 319: if (bmcr & BMCR_FDX)
! 320: mii->mii_media_active |= IFM_FDX;
! 321: else
! 322: mii->mii_media_active |= IFM_HDX;
! 323: mii->mii_media_active |= IFM_10_T;
! 324: }
! 325:
! 326: int
! 327: tlphy_mii_phy_auto(struct tlphy_softc *sc, int waitfor)
! 328: {
! 329: int error;
! 330:
! 331: switch ((error = mii_phy_auto(&sc->sc_mii, waitfor))) {
! 332: case EIO:
! 333: /*
! 334: * Just assume we're not in full-duplex mode.
! 335: * XXX Check link and try AUI/BNC?
! 336: */
! 337: PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
! 338: break;
! 339:
! 340: case EJUSTRETURN:
! 341: /* Flag that we need to program when it completes. */
! 342: sc->sc_need_acomp = 1;
! 343: break;
! 344:
! 345: default:
! 346: tlphy_acomp(sc);
! 347: }
! 348:
! 349: return (error);
! 350: }
! 351:
! 352: void
! 353: tlphy_acomp(struct tlphy_softc *sc)
! 354: {
! 355: int aner, anlpar;
! 356:
! 357: sc->sc_need_acomp = 0;
! 358:
! 359: /*
! 360: * Grr, braindead ThunderLAN PHY doesn't self-configure
! 361: * after autonegotiation. We have to do it ourselves
! 362: * based on the link partner status.
! 363: */
! 364:
! 365: aner = PHY_READ(&sc->sc_mii, MII_ANER);
! 366: if (aner & ANER_LPAN) {
! 367: anlpar = PHY_READ(&sc->sc_mii, MII_ANLPAR) &
! 368: PHY_READ(&sc->sc_mii, MII_ANAR);
! 369: if (anlpar & ANAR_10_FD) {
! 370: PHY_WRITE(&sc->sc_mii, MII_BMCR, BMCR_FDX);
! 371: return;
! 372: }
! 373: }
! 374: PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
! 375: }
CVSweb