Annotation of sys/dev/ic/elink3.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: elink3.c,v 1.69 2007/01/19 01:33:44 krw Exp $ */
! 2: /* $NetBSD: elink3.c,v 1.32 1997/05/14 00:22:00 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996, 1997 Jonathan Stone <jonathan@NetBSD.org>
! 6: * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. All advertising materials mentioning features or use of this software
! 18: * must display the following acknowledgement:
! 19: * This product includes software developed by Herb Peyerl.
! 20: * 4. The name of Herb Peyerl may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #include "bpfilter.h"
! 36:
! 37: #include <sys/param.h>
! 38: #include <sys/systm.h>
! 39: #include <sys/mbuf.h>
! 40: #include <sys/socket.h>
! 41: #include <sys/ioctl.h>
! 42: #include <sys/errno.h>
! 43: #include <sys/syslog.h>
! 44: #include <sys/selinfo.h>
! 45: #include <sys/timeout.h>
! 46: #include <sys/device.h>
! 47:
! 48: #include <net/if.h>
! 49: #include <net/if_dl.h>
! 50: #include <net/if_types.h>
! 51: #include <net/netisr.h>
! 52: #include <net/if_media.h>
! 53:
! 54: #ifdef INET
! 55: #include <netinet/in.h>
! 56: #include <netinet/in_systm.h>
! 57: #include <netinet/in_var.h>
! 58: #include <netinet/ip.h>
! 59: #include <netinet/if_ether.h>
! 60: #endif
! 61:
! 62: #if NBPFILTER > 0
! 63: #include <net/bpf.h>
! 64: #endif
! 65:
! 66: #include <machine/cpu.h>
! 67: #include <machine/bus.h>
! 68:
! 69: #include <dev/mii/mii.h>
! 70: #include <dev/mii/miivar.h>
! 71:
! 72: #include <dev/ic/elink3var.h>
! 73: #include <dev/ic/elink3reg.h>
! 74:
! 75: /*
! 76: * Structure to map media-present bits in boards to
! 77: * ifmedia codes and printable media names. Used for table-driven
! 78: * ifmedia initialization.
! 79: */
! 80: struct ep_media {
! 81: int epm_eeprom_data; /* bitmask for eeprom config */
! 82: int epm_conn; /* sc->ep_connectors code for medium */
! 83: char *epm_name; /* name of medium */
! 84: int epm_ifmedia; /* ifmedia word for medium */
! 85: int epm_ifdata;
! 86: };
! 87:
! 88: /*
! 89: * ep_media table for Vortex/Demon/Boomerang:
! 90: * map from media-present bits in register RESET_OPTIONS+2
! 91: * to ifmedia "media words" and printable names.
! 92: *
! 93: * XXX indexed directly by INTERNAL_CONFIG default_media field,
! 94: * (i.e., EPMEDIA_ constants) forcing order of entries.
! 95: * Note that 3 is reserved.
! 96: */
! 97: const struct ep_media ep_vortex_media[8] = {
! 98: { EP_PCI_UTP, EPC_UTP, "utp", IFM_ETHER|IFM_10_T,
! 99: EPMEDIA_10BASE_T },
! 100: { EP_PCI_AUI, EPC_AUI, "aui", IFM_ETHER|IFM_10_5,
! 101: EPMEDIA_AUI },
! 102: { 0, 0, "reserved", IFM_NONE, EPMEDIA_RESV1 },
! 103: { EP_PCI_BNC, EPC_BNC, "bnc", IFM_ETHER|IFM_10_2,
! 104: EPMEDIA_10BASE_2 },
! 105: { EP_PCI_100BASE_TX, EPC_100TX, "100-TX", IFM_ETHER|IFM_100_TX,
! 106: EPMEDIA_100BASE_TX },
! 107: { EP_PCI_100BASE_FX, EPC_100FX, "100-FX", IFM_ETHER|IFM_100_FX,
! 108: EPMEDIA_100BASE_FX },
! 109: { EP_PCI_100BASE_MII,EPC_MII, "mii", IFM_ETHER|IFM_100_TX,
! 110: EPMEDIA_MII },
! 111: { EP_PCI_100BASE_T4, EPC_100T4, "100-T4", IFM_ETHER|IFM_100_T4,
! 112: EPMEDIA_100BASE_T4 }
! 113: };
! 114:
! 115: /*
! 116: * ep_media table for 3c509/3c509b/3c579/3c589:
! 117: * map from media-present bits in register CNFG_CNTRL
! 118: * (window 0, offset ?) to ifmedia "media words" and printable names.
! 119: */
! 120: struct ep_media ep_isa_media[3] = {
! 121: { EP_W0_CC_UTP, EPC_UTP, "utp", IFM_ETHER|IFM_10_T, EPMEDIA_10BASE_T },
! 122: { EP_W0_CC_AUI, EPC_AUI, "aui", IFM_ETHER|IFM_10_5, EPMEDIA_AUI },
! 123: { EP_W0_CC_BNC, EPC_BNC, "bnc", IFM_ETHER|IFM_10_2, EPMEDIA_10BASE_2 },
! 124: };
! 125:
! 126: /* Map vortex reset_options bits to if_media codes. */
! 127: const u_int ep_default_to_media[8] = {
! 128: IFM_ETHER | IFM_10_T,
! 129: IFM_ETHER | IFM_10_5,
! 130: 0, /* reserved by 3Com */
! 131: IFM_ETHER | IFM_10_2,
! 132: IFM_ETHER | IFM_100_TX,
! 133: IFM_ETHER | IFM_100_FX,
! 134: IFM_ETHER | IFM_100_TX, /* XXX really MII: need to talk to PHY */
! 135: IFM_ETHER | IFM_100_T4,
! 136: };
! 137:
! 138: struct cfdriver ep_cd = {
! 139: NULL, "ep", DV_IFNET
! 140: };
! 141:
! 142: void ep_vortex_probemedia(struct ep_softc *sc);
! 143: void ep_isa_probemedia(struct ep_softc *sc);
! 144:
! 145: void eptxstat(struct ep_softc *);
! 146: int epstatus(struct ep_softc *);
! 147: int epioctl(struct ifnet *, u_long, caddr_t);
! 148: void epstart(struct ifnet *);
! 149: void epwatchdog(struct ifnet *);
! 150: void epreset(struct ep_softc *);
! 151: void epread(struct ep_softc *);
! 152: struct mbuf *epget(struct ep_softc *, int);
! 153: void epmbuffill(void *);
! 154: void epmbufempty(struct ep_softc *);
! 155: void epsetfilter(struct ep_softc *);
! 156: void ep_roadrunner_mii_enable(struct ep_softc *);
! 157: int epsetmedia(struct ep_softc *, int);
! 158:
! 159: /* ifmedia callbacks */
! 160: int ep_media_change(struct ifnet *);
! 161: void ep_media_status(struct ifnet *, struct ifmediareq *);
! 162:
! 163: /* MII callbacks */
! 164: int ep_mii_readreg(struct device *, int, int);
! 165: void ep_mii_writereg(struct device *, int, int, int);
! 166: void ep_statchg(struct device *);
! 167:
! 168: void ep_mii_setbit(struct ep_softc *, u_int16_t);
! 169: void ep_mii_clrbit(struct ep_softc *, u_int16_t);
! 170: u_int16_t ep_mii_readbit(struct ep_softc *, u_int16_t);
! 171: void ep_mii_sync(struct ep_softc *);
! 172: void ep_mii_sendbits(struct ep_softc *, u_int32_t, int);
! 173:
! 174: int epbusyeeprom(struct ep_softc *);
! 175: u_int16_t ep_read_eeprom(struct ep_softc *, u_int16_t);
! 176:
! 177: static inline void ep_reset_cmd(struct ep_softc *sc, u_int cmd,u_int arg);
! 178: static inline void ep_finish_reset(bus_space_tag_t, bus_space_handle_t);
! 179: static inline void ep_discard_rxtop(bus_space_tag_t, bus_space_handle_t);
! 180: static __inline int ep_w1_reg(struct ep_softc *, int);
! 181:
! 182: /*
! 183: * Issue a (reset) command, and be sure it has completed.
! 184: * Used for global reset, TX_RESET, RX_RESET.
! 185: */
! 186: static inline void
! 187: ep_reset_cmd(sc, cmd, arg)
! 188: struct ep_softc *sc;
! 189: u_int cmd, arg;
! 190: {
! 191: bus_space_tag_t iot = sc->sc_iot;
! 192: bus_space_handle_t ioh = sc->sc_ioh;
! 193:
! 194: bus_space_write_2(iot, ioh, cmd, arg);
! 195: ep_finish_reset(iot, ioh);
! 196: }
! 197:
! 198: /*
! 199: * Wait for any pending reset to complete.
! 200: */
! 201: static inline void
! 202: ep_finish_reset(iot, ioh)
! 203: bus_space_tag_t iot;
! 204: bus_space_handle_t ioh;
! 205: {
! 206: int i;
! 207:
! 208: for (i = 0; i < 10000; i++) {
! 209: if ((bus_space_read_2(iot, ioh, EP_STATUS) &
! 210: S_COMMAND_IN_PROGRESS) == 0)
! 211: break;
! 212: DELAY(10);
! 213: }
! 214: }
! 215:
! 216: static inline void
! 217: ep_discard_rxtop(iot, ioh)
! 218: bus_space_tag_t iot;
! 219: bus_space_handle_t ioh;
! 220: {
! 221: int i;
! 222:
! 223: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
! 224:
! 225: /*
! 226: * Spin for about 1 msec, to avoid forcing a DELAY() between
! 227: * every received packet (adding latency and limiting pkt-recv rate).
! 228: * On PCI, at 4 30-nsec PCI bus cycles for a read, 8000 iterations
! 229: * is about right.
! 230: */
! 231: for (i = 0; i < 8000; i++) {
! 232: if ((bus_space_read_2(iot, ioh, EP_STATUS) &
! 233: S_COMMAND_IN_PROGRESS) == 0)
! 234: return;
! 235: }
! 236:
! 237: /* not fast enough, do DELAY()s */
! 238: ep_finish_reset(iot, ioh);
! 239: }
! 240:
! 241: /*
! 242: * Some chips (i.e., 3c574 RoadRunner) have Window 1 registers offset.
! 243: */
! 244: static __inline int
! 245: ep_w1_reg(sc, reg)
! 246: struct ep_softc *sc;
! 247: int reg;
! 248: {
! 249: switch (sc->ep_chipset) {
! 250: case EP_CHIPSET_ROADRUNNER:
! 251: switch (reg) {
! 252: case EP_W1_FREE_TX:
! 253: case EP_W1_RUNNER_RDCTL:
! 254: case EP_W1_RUNNER_WRCTL:
! 255: return (reg);
! 256: }
! 257: return (reg + 0x10);
! 258: }
! 259: return (reg);
! 260: }
! 261:
! 262: /*
! 263: * Back-end attach and configure.
! 264: */
! 265: void
! 266: epconfig(sc, chipset, enaddr)
! 267: struct ep_softc *sc;
! 268: u_short chipset;
! 269: u_int8_t *enaddr;
! 270: {
! 271: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 272: bus_space_tag_t iot = sc->sc_iot;
! 273: bus_space_handle_t ioh = sc->sc_ioh;
! 274: u_int16_t i;
! 275:
! 276: sc->ep_chipset = chipset;
! 277:
! 278: /*
! 279: * We could have been groveling around in other register
! 280: * windows in the front-end; make sure we're in window 0
! 281: * to read the EEPROM.
! 282: */
! 283: GO_WINDOW(0);
! 284:
! 285: if (enaddr == NULL) {
! 286: /*
! 287: * Read the station address from the eeprom.
! 288: */
! 289: for (i = 0; i < 3; i++) {
! 290: u_int16_t x = ep_read_eeprom(sc, i);
! 291:
! 292: sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
! 293: sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
! 294: }
! 295: } else {
! 296: bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
! 297: }
! 298:
! 299: printf(" address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
! 300: if (sc->ep_flags & EP_FLAGS_MII)
! 301: printf("\n");
! 302: else
! 303: printf(", ");
! 304:
! 305: /*
! 306: * Vortex-based (3c59x pci,eisa) cards allow FDDI-sized (4500) byte
! 307: * packets. Commands only take an 11-bit parameter, and 11 bits
! 308: * isn't enough to hold a full-size packet length.
! 309: * Commands to these cards implicitly upshift a packet size
! 310: * or threshold by 2 bits.
! 311: * To detect cards with large-packet support, we probe by setting
! 312: * the transmit threshold register, then change windows and
! 313: * read back the threshold register directly, and see if the
! 314: * threshold value was shifted or not.
! 315: */
! 316: bus_space_write_2(iot, ioh, EP_COMMAND,
! 317: SET_TX_AVAIL_THRESH | EP_LARGEWIN_PROBE );
! 318: GO_WINDOW(5);
! 319: i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH);
! 320: GO_WINDOW(1);
! 321: switch (i) {
! 322: case EP_LARGEWIN_PROBE:
! 323: case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK):
! 324: sc->txashift = 0;
! 325: break;
! 326:
! 327: case (EP_LARGEWIN_PROBE << 2):
! 328: sc->txashift = 2;
! 329: /* XXX does the 3c515 support Vortex-style RESET_OPTIONS? */
! 330: break;
! 331:
! 332: default:
! 333: printf("wrote %x to TX_AVAIL_THRESH, read back %x. "
! 334: "Interface disabled\n", EP_THRESH_DISABLE, (int) i);
! 335: return;
! 336: }
! 337:
! 338: timeout_set(&sc->sc_epmbuffill_tmo, epmbuffill, sc);
! 339:
! 340: /*
! 341: * Ensure Tx-available interrupts are enabled for
! 342: * start the interface.
! 343: * XXX should be in epinit()?
! 344: */
! 345: bus_space_write_2(iot, ioh, EP_COMMAND,
! 346: SET_TX_AVAIL_THRESH | (1600 >> sc->txashift));
! 347:
! 348: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
! 349: ifp->if_softc = sc;
! 350: ifp->if_start = epstart;
! 351: ifp->if_ioctl = epioctl;
! 352: ifp->if_watchdog = epwatchdog;
! 353: ifp->if_flags =
! 354: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
! 355: IFQ_SET_READY(&ifp->if_snd);
! 356:
! 357: if_attach(ifp);
! 358: ether_ifattach(ifp);
! 359:
! 360: /*
! 361: * Finish configuration:
! 362: * determine chipset if the front-end couldn't do so,
! 363: * show board details, set media.
! 364: */
! 365:
! 366: GO_WINDOW(0);
! 367:
! 368: ifmedia_init(&sc->sc_mii.mii_media, 0, ep_media_change,
! 369: ep_media_status);
! 370: sc->sc_mii.mii_ifp = ifp;
! 371: sc->sc_mii.mii_readreg = ep_mii_readreg;
! 372: sc->sc_mii.mii_writereg = ep_mii_writereg;
! 373: sc->sc_mii.mii_statchg = ep_statchg;
! 374:
! 375: /*
! 376: * If we've got an indirect (ISA, PCMCIA?) board, the chipset
! 377: * is unknown. If the board has large-packet support, it's a
! 378: * Vortex/Boomerang, otherwise it's a 3c509.
! 379: * XXX use eeprom capability word instead?
! 380: */
! 381: if (sc->ep_chipset == EP_CHIPSET_UNKNOWN && sc->txashift) {
! 382: printf("warning: unknown chipset, possibly 3c515?\n");
! 383: #ifdef notyet
! 384: sc->sc_chipset = EP_CHIPSET_VORTEX;
! 385: #endif /* notyet */
! 386: }
! 387:
! 388: /*
! 389: * Ascertain which media types are present and inform ifmedia.
! 390: */
! 391: switch (sc->ep_chipset) {
! 392: case EP_CHIPSET_ROADRUNNER:
! 393: if (sc->ep_flags & EP_FLAGS_MII) {
! 394: ep_roadrunner_mii_enable(sc);
! 395: GO_WINDOW(0);
! 396: }
! 397: /* FALLTHROUGH */
! 398:
! 399: case EP_CHIPSET_BOOMERANG:
! 400: /*
! 401: * If the device has MII, probe it. We won't be using
! 402: * any `native' media in this case, only PHYs. If
! 403: * we don't, just treat the Boomerang like the Vortex.
! 404: */
! 405: if (sc->ep_flags & EP_FLAGS_MII) {
! 406: mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff,
! 407: MII_PHY_ANY, MII_OFFSET_ANY, 0);
! 408: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
! 409: ifmedia_add(&sc->sc_mii.mii_media,
! 410: IFM_ETHER|IFM_NONE, 0, NULL);
! 411: ifmedia_set(&sc->sc_mii.mii_media,
! 412: IFM_ETHER|IFM_NONE);
! 413: } else {
! 414: ifmedia_set(&sc->sc_mii.mii_media,
! 415: IFM_ETHER|IFM_AUTO);
! 416: }
! 417: break;
! 418: }
! 419: /* FALLTHROUGH */
! 420:
! 421: /* on a direct bus, the attach routine can tell, but check anyway. */
! 422: case EP_CHIPSET_VORTEX:
! 423: case EP_CHIPSET_BOOMERANG2:
! 424: ep_vortex_probemedia(sc);
! 425: break;
! 426:
! 427: /* on ISA we can't yet tell 3c509 from 3c515. Assume the former. */
! 428: case EP_CHIPSET_3C509:
! 429: default:
! 430: ep_isa_probemedia(sc);
! 431: break;
! 432: }
! 433:
! 434: GO_WINDOW(1); /* Window 1 is operating window */
! 435:
! 436: sc->tx_start_thresh = 20; /* probably a good starting point. */
! 437:
! 438: ep_reset_cmd(sc, EP_COMMAND, RX_RESET);
! 439: ep_reset_cmd(sc, EP_COMMAND, TX_RESET);
! 440: }
! 441:
! 442: int
! 443: ep_detach(self)
! 444: struct device *self;
! 445: {
! 446: struct ep_softc *sc = (struct ep_softc *)self;
! 447: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 448:
! 449: if (sc->ep_flags & EP_FLAGS_MII)
! 450: mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
! 451:
! 452: ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
! 453:
! 454: ether_ifdetach(ifp);
! 455: if_detach(ifp);
! 456:
! 457: return (0);
! 458: }
! 459:
! 460: /*
! 461: * Find supported media on 3c509-generation hardware that doesn't have
! 462: * a "reset_options" register in window 3.
! 463: * Use the config_cntrl register in window 0 instead.
! 464: * Used on original, 10Mbit ISA (3c509), 3c509B, and pre-Demon EISA cards
! 465: * that implement CONFIG_CTRL. We don't have a good way to set the
! 466: * default active medium; punt to ifconfig instead.
! 467: *
! 468: * XXX what about 3c515, pcmcia 10/100?
! 469: */
! 470: void
! 471: ep_isa_probemedia(sc)
! 472: struct ep_softc *sc;
! 473: {
! 474: bus_space_tag_t iot = sc->sc_iot;
! 475: bus_space_handle_t ioh = sc->sc_ioh;
! 476: struct ifmedia *ifm = &sc->sc_mii.mii_media;
! 477: int conn, i;
! 478: u_int16_t ep_w0_config, port;
! 479:
! 480: conn = 0;
! 481: GO_WINDOW(0);
! 482: ep_w0_config = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL);
! 483: for (i = 0; i < 3; i++) {
! 484: struct ep_media * epm = ep_isa_media + i;
! 485:
! 486: if ((ep_w0_config & epm->epm_eeprom_data) != 0) {
! 487: ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_ifdata, 0);
! 488: if (conn)
! 489: printf("/");
! 490: printf("%s", epm->epm_name);
! 491: conn |= epm->epm_conn;
! 492: }
! 493: }
! 494: sc->ep_connectors = conn;
! 495:
! 496: /* get default medium from EEPROM */
! 497: if (epbusyeeprom(sc))
! 498: return; /* XXX why is eeprom busy? */
! 499: bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
! 500: READ_EEPROM | EEPROM_ADDR_CFG);
! 501: if (epbusyeeprom(sc))
! 502: return; /* XXX why is eeprom busy? */
! 503: port = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
! 504: port = port >> 14;
! 505:
! 506: printf(" (default %s)\n", ep_vortex_media[port].epm_name);
! 507:
! 508: /* tell ifconfig what currently-active media is. */
! 509: ifmedia_set(ifm, ep_default_to_media[port]);
! 510:
! 511: /* XXX autoselect not yet implemented */
! 512: }
! 513:
! 514:
! 515: /*
! 516: * Find media present on large-packet-capable elink3 devices.
! 517: * Show onboard configuration of large-packet-capable elink3 devices
! 518: * (Demon, Vortex, Boomerang), which do not implement CONFIG_CTRL in window 0.
! 519: * Use media and card-version info in window 3 instead.
! 520: *
! 521: * XXX how much of this works with 3c515, pcmcia 10/100?
! 522: */
! 523: void
! 524: ep_vortex_probemedia(sc)
! 525: struct ep_softc *sc;
! 526: {
! 527: bus_space_tag_t iot = sc->sc_iot;
! 528: bus_space_handle_t ioh = sc->sc_ioh;
! 529: struct ifmedia *ifm = &sc->sc_mii.mii_media;
! 530: u_int config1, conn;
! 531: int reset_options;
! 532: int default_media; /* 3-bit encoding of default (EEPROM) media */
! 533: int autoselect; /* boolean: should default to autoselect */
! 534: const char *medium_name;
! 535: register int i;
! 536:
! 537: GO_WINDOW(3);
! 538: config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2);
! 539: reset_options = (int)bus_space_read_1(iot, ioh, EP_W3_RESET_OPTIONS);
! 540: GO_WINDOW(0);
! 541:
! 542: default_media = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
! 543: autoselect = (config1 & CONFIG_AUTOSELECT) >> CONFIG_AUTOSELECT_SHIFT;
! 544:
! 545: /* set available media options */
! 546: conn = 0;
! 547: for (i = 0; i < 8; i++) {
! 548: const struct ep_media *epm = ep_vortex_media + i;
! 549:
! 550: if ((reset_options & epm->epm_eeprom_data) != 0) {
! 551: if (conn)
! 552: printf("/");
! 553: printf("%s", epm->epm_name);
! 554: conn |= epm->epm_conn;
! 555: ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_ifdata, 0);
! 556: }
! 557: }
! 558:
! 559: sc->ep_connectors = conn;
! 560:
! 561: /* Show eeprom's idea of default media. */
! 562: medium_name = (default_media > 8)
! 563: ? "(unknown/impossible media)"
! 564: : ep_vortex_media[default_media].epm_name;
! 565: printf(" default %s%s",
! 566: medium_name, (autoselect) ? "/autoselect" : "");
! 567: /* sc->sc_media = ep_vortex_media[default_media].epm_ifdata;*/
! 568:
! 569: #ifdef notyet
! 570: /*
! 571: * Set default: either the active interface the card
! 572: * reads from the EEPROM, or if autoselect is true,
! 573: * whatever we find is actually connected.
! 574: *
! 575: * XXX autoselect not yet implemented.
! 576: */
! 577: #endif /* notyet */
! 578:
! 579: /* tell ifconfig what currently-active media is. */
! 580: ifmedia_set(ifm, ep_default_to_media[default_media]);
! 581: }
! 582:
! 583: /*
! 584: * Bring device up.
! 585: *
! 586: * The order in here seems important. Otherwise we may not receive
! 587: * interrupts. ?!
! 588: */
! 589: void
! 590: epinit(sc)
! 591: register struct ep_softc *sc;
! 592: {
! 593: register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 594: bus_space_tag_t iot = sc->sc_iot;
! 595: bus_space_handle_t ioh = sc->sc_ioh;
! 596: int i;
! 597:
! 598: /* make sure any pending reset has completed before touching board */
! 599: ep_finish_reset(iot, ioh);
! 600:
! 601: /* cancel any pending I/O */
! 602: epstop(sc);
! 603:
! 604: if (sc->bustype != EP_BUS_PCI) {
! 605: GO_WINDOW(0);
! 606: bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, 0);
! 607: bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
! 608: }
! 609:
! 610: if (sc->bustype == EP_BUS_PCMCIA) {
! 611: bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00);
! 612: }
! 613:
! 614: GO_WINDOW(2);
! 615: for (i = 0; i < 6; i++) /* Reload the ether_addr. */
! 616: bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
! 617: sc->sc_arpcom.ac_enaddr[i]);
! 618:
! 619: if (sc->bustype == EP_BUS_PCI || sc->bustype == EP_BUS_EISA)
! 620: /*
! 621: * Reset the station-address receive filter.
! 622: * A bug workaround for busmastering (Vortex, Demon) cards.
! 623: */
! 624: for (i = 0; i < 6; i++)
! 625: bus_space_write_1(iot, ioh, EP_W2_RECVMASK_0 + i, 0);
! 626:
! 627: ep_reset_cmd(sc, EP_COMMAND, RX_RESET);
! 628: ep_reset_cmd(sc, EP_COMMAND, TX_RESET);
! 629:
! 630: GO_WINDOW(1); /* Window 1 is operating window */
! 631: for (i = 0; i < 31; i++)
! 632: bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS));
! 633:
! 634: /* Set threshold for for Tx-space available interrupt. */
! 635: bus_space_write_2(iot, ioh, EP_COMMAND,
! 636: SET_TX_AVAIL_THRESH | (1600 >> sc->txashift));
! 637:
! 638: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
! 639: /* Enable options in the PCMCIA LAN COR register, via
! 640: * RoadRunner Window 1.
! 641: *
! 642: * XXX MAGIC CONSTANTS!
! 643: */
! 644: u_int16_t cor;
! 645:
! 646: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, (1 << 11));
! 647:
! 648: cor = bus_space_read_2(iot, ioh, 0) & ~0x30;
! 649: bus_space_write_2(iot, ioh, 0, cor);
! 650:
! 651: bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0);
! 652: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
! 653:
! 654: if (sc->ep_flags & EP_FLAGS_MII) {
! 655: ep_roadrunner_mii_enable(sc);
! 656: GO_WINDOW(1);
! 657: }
! 658: }
! 659:
! 660: /* Enable interrupts. */
! 661: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK |
! 662: S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
! 663: bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK |
! 664: S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
! 665:
! 666: /*
! 667: * Attempt to get rid of any stray interrupts that occurred during
! 668: * configuration. On the i386 this isn't possible because one may
! 669: * already be queued. However, a single stray interrupt is
! 670: * unimportant.
! 671: */
! 672: bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff);
! 673:
! 674: epsetfilter(sc);
! 675: epsetmedia(sc, sc->sc_mii.mii_media.ifm_cur->ifm_data);
! 676:
! 677: bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
! 678: bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
! 679:
! 680: epmbuffill(sc);
! 681:
! 682: /* Interface is now `running', with no output active. */
! 683: ifp->if_flags |= IFF_RUNNING;
! 684: ifp->if_flags &= ~IFF_OACTIVE;
! 685:
! 686: /* Attempt to start output, if any. */
! 687: epstart(ifp);
! 688: }
! 689:
! 690: /*
! 691: * Set multicast receive filter.
! 692: * elink3 hardware has no selective multicast filter in hardware.
! 693: * Enable reception of all multicasts and filter in software.
! 694: */
! 695: void
! 696: epsetfilter(sc)
! 697: register struct ep_softc *sc;
! 698: {
! 699: register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 700:
! 701: GO_WINDOW(1); /* Window 1 is operating window */
! 702: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER |
! 703: FIL_INDIVIDUAL | FIL_BRDCST |
! 704: ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) |
! 705: ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
! 706: }
! 707:
! 708:
! 709: int
! 710: ep_media_change(ifp)
! 711: struct ifnet *ifp;
! 712: {
! 713: register struct ep_softc *sc = ifp->if_softc;
! 714:
! 715: return epsetmedia(sc, sc->sc_mii.mii_media.ifm_cur->ifm_data);
! 716: }
! 717:
! 718: /*
! 719: * Reset and enable the MII on the RoadRunner.
! 720: */
! 721: void
! 722: ep_roadrunner_mii_enable(sc)
! 723: struct ep_softc *sc;
! 724: {
! 725: bus_space_tag_t iot = sc->sc_iot;
! 726: bus_space_handle_t ioh = sc->sc_ioh;
! 727:
! 728: GO_WINDOW(3);
! 729: bus_space_write_2(iot, ioh, EP_W3_RESET_OPTIONS,
! 730: EP_PCI_100BASE_MII|EP_RUNNER_ENABLE_MII);
! 731: delay(1000);
! 732: bus_space_write_2(iot, ioh, EP_W3_RESET_OPTIONS,
! 733: EP_PCI_100BASE_MII|EP_RUNNER_MII_RESET|EP_RUNNER_ENABLE_MII);
! 734: ep_reset_cmd(sc, EP_COMMAND, TX_RESET);
! 735: ep_reset_cmd(sc, EP_COMMAND, RX_RESET);
! 736: delay(1000);
! 737: bus_space_write_2(iot, ioh, EP_W3_RESET_OPTIONS,
! 738: EP_PCI_100BASE_MII|EP_RUNNER_ENABLE_MII);
! 739: }
! 740:
! 741: /*
! 742: * Set active media to a specific given EPMEDIA_<> value.
! 743: * For vortex/demon/boomerang cards, update media field in w3_internal_config,
! 744: * and power on selected transceiver.
! 745: * For 3c509-generation cards (3c509/3c579/3c589/3c509B),
! 746: * update media field in w0_address_config, and power on selected xcvr.
! 747: */
! 748: int
! 749: epsetmedia(sc, medium)
! 750: struct ep_softc *sc;
! 751: int medium;
! 752: {
! 753: bus_space_tag_t iot = sc->sc_iot;
! 754: bus_space_handle_t ioh = sc->sc_ioh;
! 755: int w4_media;
! 756: int config0, config1;
! 757:
! 758: /*
! 759: * you can `ifconfig (link0|-link0) ep0' to get the following
! 760: * behaviour:
! 761: * -link0 disable AUI/UTP. enable BNC.
! 762: * link0 disable BNC. enable AUI.
! 763: * link1 if the card has a UTP connector, and link0 is
! 764: * set too, then you get the UTP port.
! 765: */
! 766:
! 767: /*
! 768: * First, change the media-control bits in EP_W4_MEDIA_TYPE.
! 769: */
! 770:
! 771: /* Turn everything off. First turn off linkbeat and UTP. */
! 772: GO_WINDOW(4);
! 773: w4_media = bus_space_read_2(iot, ioh, EP_W4_MEDIA_TYPE);
! 774: w4_media = w4_media & ~(ENABLE_UTP|SQE_ENABLE);
! 775: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, w4_media);
! 776:
! 777: /* Turn off coax */
! 778: bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
! 779: delay(1000);
! 780:
! 781: /* If the device has MII, select it, and then tell the
! 782: * PHY which media to use.
! 783: */
! 784: if (sc->ep_flags & EP_FLAGS_MII) {
! 785: int config0, config1;
! 786:
! 787: GO_WINDOW(3);
! 788:
! 789: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
! 790: int resopt;
! 791:
! 792: resopt = bus_space_read_2(iot, ioh,
! 793: EP_W3_RESET_OPTIONS);
! 794: bus_space_write_2(iot, ioh, EP_W3_RESET_OPTIONS,
! 795: resopt | EP_RUNNER_ENABLE_MII);
! 796: }
! 797:
! 798: config0 = (u_int)bus_space_read_2(iot, ioh,
! 799: EP_W3_INTERNAL_CONFIG);
! 800: config1 = (u_int)bus_space_read_2(iot, ioh,
! 801: EP_W3_INTERNAL_CONFIG + 2);
! 802:
! 803: config1 = config1 & ~CONFIG_MEDIAMASK;
! 804: config1 |= (EPMEDIA_MII << CONFIG_MEDIAMASK_SHIFT);
! 805:
! 806: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0);
! 807: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1);
! 808: GO_WINDOW(1); /* back to operating window */
! 809:
! 810: mii_mediachg(&sc->sc_mii);
! 811: return (0);
! 812: }
! 813:
! 814: /*
! 815: * Now turn on the selected media/transceiver.
! 816: */
! 817: GO_WINDOW(4);
! 818: switch (medium) {
! 819: case EPMEDIA_10BASE_T:
! 820: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, (ENABLE_UTP |
! 821: (sc->bustype == EP_BUS_PCMCIA ? MEDIA_LED : 0)));
! 822: break;
! 823:
! 824: case EPMEDIA_10BASE_2:
! 825: bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER);
! 826: DELAY(1000); /* 50ms not enough? */
! 827: break;
! 828:
! 829: /* XXX following only for new-generation cards */
! 830: case EPMEDIA_100BASE_TX:
! 831: case EPMEDIA_100BASE_FX:
! 832: case EPMEDIA_100BASE_T4: /* XXX check documentation */
! 833: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
! 834: w4_media | LINKBEAT_ENABLE);
! 835: DELAY(1000); /* not strictly necessary? */
! 836: break;
! 837:
! 838: case EPMEDIA_AUI:
! 839: bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
! 840: w4_media | SQE_ENABLE);
! 841: DELAY(1000); /* not strictly necessary? */
! 842: break;
! 843: case EPMEDIA_MII:
! 844: break;
! 845: default:
! 846: #if defined(EP_DEBUG)
! 847: printf("%s unknown media 0x%x\n", sc->sc_dev.dv_xname, medium);
! 848: #endif
! 849: break;
! 850:
! 851: }
! 852:
! 853: /*
! 854: * Tell the chip which PHY [sic] to use.
! 855: */
! 856: switch (sc->ep_chipset) {
! 857: case EP_CHIPSET_VORTEX:
! 858: case EP_CHIPSET_BOOMERANG2:
! 859: GO_WINDOW(3);
! 860: config0 = (u_int)bus_space_read_2(iot, ioh,
! 861: EP_W3_INTERNAL_CONFIG);
! 862: config1 = (u_int)bus_space_read_2(iot, ioh,
! 863: EP_W3_INTERNAL_CONFIG + 2);
! 864:
! 865: #if defined(EP_DEBUG)
! 866: printf("%s: read 0x%x, 0x%x from EP_W3_CONFIG register\n",
! 867: sc->sc_dev.dv_xname, config0, config1);
! 868: #endif
! 869: config1 = config1 & ~CONFIG_MEDIAMASK;
! 870: config1 |= (medium << CONFIG_MEDIAMASK_SHIFT);
! 871:
! 872: #if defined(EP_DEBUG)
! 873: printf("epsetmedia: %s: medium 0x%x, 0x%x to EP_W3_CONFIG\n",
! 874: sc->sc_dev.dv_xname, medium, config1);
! 875: #endif
! 876: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0);
! 877: bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1);
! 878: break;
! 879:
! 880: default:
! 881: GO_WINDOW(0);
! 882: config0 = bus_space_read_2(iot, ioh, EP_W0_ADDRESS_CFG);
! 883: config0 &= 0x3fff;
! 884: bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,
! 885: config0 | (medium << 14));
! 886: DELAY(1000);
! 887: break;
! 888: }
! 889:
! 890: GO_WINDOW(1); /* Window 1 is operating window */
! 891: return (0);
! 892: }
! 893:
! 894:
! 895: /*
! 896: * Get currently-selected media from card.
! 897: * (if_media callback, may be called before interface is brought up).
! 898: */
! 899: void
! 900: ep_media_status(ifp, req)
! 901: struct ifnet *ifp;
! 902: struct ifmediareq *req;
! 903: {
! 904: register struct ep_softc *sc = ifp->if_softc;
! 905: bus_space_tag_t iot = sc->sc_iot;
! 906: bus_space_handle_t ioh = sc->sc_ioh;
! 907: u_int config1;
! 908: u_int ep_mediastatus;
! 909:
! 910: /*
! 911: * If we have MII, go ask the PHY what's going on.
! 912: */
! 913: if (sc->ep_flags & EP_FLAGS_MII) {
! 914: mii_pollstat(&sc->sc_mii);
! 915: req->ifm_active = sc->sc_mii.mii_media_active;
! 916: req->ifm_status = sc->sc_mii.mii_media_status;
! 917: return;
! 918: }
! 919:
! 920: /* XXX read from softc when we start autosensing media */
! 921: req->ifm_active = sc->sc_mii.mii_media.ifm_cur->ifm_media;
! 922:
! 923: switch (sc->ep_chipset) {
! 924: case EP_CHIPSET_VORTEX:
! 925: case EP_CHIPSET_BOOMERANG:
! 926: GO_WINDOW(3);
! 927: delay(5000);
! 928:
! 929: config1 = bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2);
! 930: GO_WINDOW(1);
! 931:
! 932: config1 =
! 933: (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
! 934: req->ifm_active = ep_default_to_media[config1];
! 935:
! 936: /* XXX check full-duplex bits? */
! 937:
! 938: GO_WINDOW(4);
! 939: req->ifm_status = IFM_AVALID; /* XXX */
! 940: ep_mediastatus = bus_space_read_2(iot, ioh, EP_W4_MEDIA_TYPE);
! 941: if (ep_mediastatus & LINKBEAT_DETECT)
! 942: req->ifm_status |= IFM_ACTIVE; /* XXX automedia */
! 943:
! 944: break;
! 945:
! 946: case EP_CHIPSET_UNKNOWN:
! 947: case EP_CHIPSET_3C509:
! 948: req->ifm_status = 0; /* XXX */
! 949: break;
! 950:
! 951: default:
! 952: printf("%s: media_status on unknown chipset 0x%x\n",
! 953: ifp->if_xname, sc->ep_chipset);
! 954: break;
! 955: }
! 956:
! 957: /* XXX look for softc heartbeat for other chips or media */
! 958:
! 959: GO_WINDOW(1);
! 960: return;
! 961: }
! 962:
! 963:
! 964:
! 965: /*
! 966: * Start outputting on the interface.
! 967: * Always called as splnet().
! 968: */
! 969: void
! 970: epstart(ifp)
! 971: struct ifnet *ifp;
! 972: {
! 973: register struct ep_softc *sc = ifp->if_softc;
! 974: bus_space_tag_t iot = sc->sc_iot;
! 975: bus_space_handle_t ioh = sc->sc_ioh;
! 976: struct mbuf *m, *m0;
! 977: int sh, len, pad, txreg;
! 978:
! 979: /* Don't transmit if interface is busy or not running */
! 980: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
! 981: return;
! 982:
! 983: startagain:
! 984: /* Sneak a peek at the next packet */
! 985: IFQ_POLL(&ifp->if_snd, m0);
! 986: if (m0 == NULL)
! 987: return;
! 988:
! 989: /* We need to use m->m_pkthdr.len, so require the header */
! 990: if ((m0->m_flags & M_PKTHDR) == 0)
! 991: panic("epstart: no header mbuf");
! 992: len = m0->m_pkthdr.len;
! 993:
! 994: pad = (4 - len) & 3;
! 995:
! 996: /*
! 997: * The 3c509 automatically pads short packets to minimum ethernet
! 998: * length, but we drop packets that are too large. Perhaps we should
! 999: * truncate them instead?
! 1000: */
! 1001: if (len + pad > ETHER_MAX_LEN) {
! 1002: /* packet is obviously too large: toss it */
! 1003: ++ifp->if_oerrors;
! 1004: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 1005: m_freem(m0);
! 1006: goto readcheck;
! 1007: }
! 1008:
! 1009: if (bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_FREE_TX)) <
! 1010: len + pad + 4) {
! 1011: bus_space_write_2(iot, ioh, EP_COMMAND,
! 1012: SET_TX_AVAIL_THRESH | ((len + pad + 4) >> sc->txashift));
! 1013: /* not enough room in FIFO */
! 1014: ifp->if_flags |= IFF_OACTIVE;
! 1015: return;
! 1016: } else {
! 1017: bus_space_write_2(iot, ioh, EP_COMMAND,
! 1018: SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
! 1019: }
! 1020:
! 1021: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 1022: if (m0 == NULL)
! 1023: return;
! 1024:
! 1025: bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
! 1026: ((len / 4 + sc->tx_start_thresh) /*>> sc->txashift*/));
! 1027:
! 1028: #if NBPFILTER > 0
! 1029: if (ifp->if_bpf)
! 1030: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
! 1031: #endif
! 1032:
! 1033: /*
! 1034: * Do the output at splhigh() so that an interrupt from another device
! 1035: * won't cause a FIFO underrun.
! 1036: */
! 1037: sh = splhigh();
! 1038:
! 1039: txreg = ep_w1_reg(sc, EP_W1_TX_PIO_WR_1);
! 1040:
! 1041: bus_space_write_2(iot, ioh, txreg, len);
! 1042: bus_space_write_2(iot, ioh, txreg, 0xffff); /* Second is meaningless */
! 1043: if (EP_IS_BUS_32(sc->bustype)) {
! 1044: for (m = m0; m; ) {
! 1045: if (m->m_len > 3)
! 1046: bus_space_write_raw_multi_4(iot, ioh, txreg,
! 1047: mtod(m, u_int8_t *), m->m_len & ~3);
! 1048: if (m->m_len & 3)
! 1049: bus_space_write_multi_1(iot, ioh, txreg,
! 1050: mtod(m, u_int8_t *) + (m->m_len & ~3),
! 1051: m->m_len & 3);
! 1052: MFREE(m, m0);
! 1053: m = m0;
! 1054: }
! 1055: } else {
! 1056: for (m = m0; m; ) {
! 1057: if (m->m_len > 1)
! 1058: bus_space_write_raw_multi_2(iot, ioh, txreg,
! 1059: mtod(m, u_int8_t *), m->m_len & ~1);
! 1060: if (m->m_len & 1)
! 1061: bus_space_write_1(iot, ioh, txreg,
! 1062: *(mtod(m, u_int8_t *) + m->m_len - 1));
! 1063: MFREE(m, m0);
! 1064: m = m0;
! 1065: }
! 1066: }
! 1067: while (pad--)
! 1068: bus_space_write_1(iot, ioh, txreg, 0);
! 1069:
! 1070: splx(sh);
! 1071:
! 1072: ++ifp->if_opackets;
! 1073:
! 1074: readcheck:
! 1075: if ((bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS)) &
! 1076: ERR_INCOMPLETE) == 0) {
! 1077: /* We received a complete packet. */
! 1078: u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS);
! 1079:
! 1080: if ((status & S_INTR_LATCH) == 0) {
! 1081: /*
! 1082: * No interrupt, read the packet and continue
! 1083: * Is this supposed to happen? Is my motherboard
! 1084: * completely busted?
! 1085: */
! 1086: epread(sc);
! 1087: } else
! 1088: /* Got an interrupt, return to get it serviced. */
! 1089: return;
! 1090: } else {
! 1091: /* Check if we are stuck and reset [see XXX comment] */
! 1092: if (epstatus(sc)) {
! 1093: #ifdef EP_DEBUG
! 1094: if (ifp->if_flags & IFF_DEBUG)
! 1095: printf("%s: adapter reset\n",
! 1096: sc->sc_dev.dv_xname);
! 1097: #endif
! 1098: epreset(sc);
! 1099: }
! 1100: }
! 1101:
! 1102: goto startagain;
! 1103: }
! 1104:
! 1105:
! 1106: /*
! 1107: * XXX: The 3c509 card can get in a mode where both the fifo status bit
! 1108: * FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
! 1109: * We detect this situation and we reset the adapter.
! 1110: * It happens at times when there is a lot of broadcast traffic
! 1111: * on the cable (once in a blue moon).
! 1112: */
! 1113: int
! 1114: epstatus(sc)
! 1115: register struct ep_softc *sc;
! 1116: {
! 1117: bus_space_tag_t iot = sc->sc_iot;
! 1118: bus_space_handle_t ioh = sc->sc_ioh;
! 1119: u_int16_t fifost;
! 1120:
! 1121: /*
! 1122: * Check the FIFO status and act accordingly
! 1123: */
! 1124: GO_WINDOW(4);
! 1125: fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG);
! 1126: GO_WINDOW(1);
! 1127:
! 1128: if (fifost & FIFOS_RX_UNDERRUN) {
! 1129: #ifdef EP_DEBUG
! 1130: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
! 1131: printf("%s: RX underrun\n", sc->sc_dev.dv_xname);
! 1132: #endif
! 1133: epreset(sc);
! 1134: return 0;
! 1135: }
! 1136:
! 1137: if (fifost & FIFOS_RX_STATUS_OVERRUN) {
! 1138: #ifdef EP_DEBUG
! 1139: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
! 1140: printf("%s: RX Status overrun\n", sc->sc_dev.dv_xname);
! 1141: #endif
! 1142: return 1;
! 1143: }
! 1144:
! 1145: if (fifost & FIFOS_RX_OVERRUN) {
! 1146: #ifdef EP_DEBUG
! 1147: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
! 1148: printf("%s: RX overrun\n", sc->sc_dev.dv_xname);
! 1149: #endif
! 1150: return 1;
! 1151: }
! 1152:
! 1153: if (fifost & FIFOS_TX_OVERRUN) {
! 1154: #ifdef EP_DEBUG
! 1155: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
! 1156: printf("%s: TX overrun\n", sc->sc_dev.dv_xname);
! 1157: #endif
! 1158: epreset(sc);
! 1159: return 0;
! 1160: }
! 1161:
! 1162: return 0;
! 1163: }
! 1164:
! 1165:
! 1166: void
! 1167: eptxstat(sc)
! 1168: register struct ep_softc *sc;
! 1169: {
! 1170: bus_space_tag_t iot = sc->sc_iot;
! 1171: bus_space_handle_t ioh = sc->sc_ioh;
! 1172: int i;
! 1173:
! 1174: /*
! 1175: * We need to read+write TX_STATUS until we get a 0 status
! 1176: * in order to turn off the interrupt flag.
! 1177: */
! 1178: while ((i = bus_space_read_1(iot, ioh,
! 1179: ep_w1_reg(sc, EP_W1_TX_STATUS))) & TXS_COMPLETE) {
! 1180: bus_space_write_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS),
! 1181: 0x0);
! 1182:
! 1183: if (i & TXS_JABBER) {
! 1184: ++sc->sc_arpcom.ac_if.if_oerrors;
! 1185: #ifdef EP_DEBUG
! 1186: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
! 1187: printf("%s: jabber (%x)\n",
! 1188: sc->sc_dev.dv_xname, i);
! 1189: #endif
! 1190: epreset(sc);
! 1191: } else if (i & TXS_UNDERRUN) {
! 1192: ++sc->sc_arpcom.ac_if.if_oerrors;
! 1193: #ifdef EP_DEBUG
! 1194: if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
! 1195: printf("%s: fifo underrun (%x) @%d\n",
! 1196: sc->sc_dev.dv_xname, i,
! 1197: sc->tx_start_thresh);
! 1198: #endif
! 1199: if (sc->tx_succ_ok < 100)
! 1200: sc->tx_start_thresh = min(ETHER_MAX_LEN,
! 1201: sc->tx_start_thresh + 20);
! 1202: sc->tx_succ_ok = 0;
! 1203: epreset(sc);
! 1204: } else if (i & TXS_MAX_COLLISION) {
! 1205: ++sc->sc_arpcom.ac_if.if_collisions;
! 1206: bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
! 1207: sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
! 1208: } else
! 1209: sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
! 1210: }
! 1211: }
! 1212:
! 1213: int
! 1214: epintr(arg)
! 1215: void *arg;
! 1216: {
! 1217: register struct ep_softc *sc = arg;
! 1218: bus_space_tag_t iot = sc->sc_iot;
! 1219: bus_space_handle_t ioh = sc->sc_ioh;
! 1220: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1221: u_int16_t status;
! 1222: int ret = 0;
! 1223:
! 1224: for (;;) {
! 1225: bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
! 1226:
! 1227: status = bus_space_read_2(iot, ioh, EP_STATUS);
! 1228:
! 1229: if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
! 1230: S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
! 1231: break;
! 1232:
! 1233: ret = 1;
! 1234:
! 1235: /*
! 1236: * Acknowledge any interrupts. It's important that we do this
! 1237: * first, since there would otherwise be a race condition.
! 1238: * Due to the i386 interrupt queueing, we may get spurious
! 1239: * interrupts occasionally.
! 1240: */
! 1241: bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | status);
! 1242:
! 1243: if (status & S_RX_COMPLETE)
! 1244: epread(sc);
! 1245: if (status & S_TX_AVAIL) {
! 1246: ifp->if_flags &= ~IFF_OACTIVE;
! 1247: epstart(ifp);
! 1248: }
! 1249: if (status & S_CARD_FAILURE) {
! 1250: epreset(sc);
! 1251: return (1);
! 1252: }
! 1253: if (status & S_TX_COMPLETE) {
! 1254: eptxstat(sc);
! 1255: epstart(ifp);
! 1256: }
! 1257: }
! 1258:
! 1259: /* no more interrupts */
! 1260: return (ret);
! 1261: }
! 1262:
! 1263: void
! 1264: epread(sc)
! 1265: register struct ep_softc *sc;
! 1266: {
! 1267: bus_space_tag_t iot = sc->sc_iot;
! 1268: bus_space_handle_t ioh = sc->sc_ioh;
! 1269: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1270: struct mbuf *m;
! 1271: int len;
! 1272:
! 1273: len = bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS));
! 1274:
! 1275: again:
! 1276: #ifdef EP_DEBUG
! 1277: if (ifp->if_flags & IFF_DEBUG) {
! 1278: int err = len & ERR_MASK;
! 1279: char *s = NULL;
! 1280:
! 1281: if (len & ERR_INCOMPLETE)
! 1282: s = "incomplete packet";
! 1283: else if (err == ERR_OVERRUN)
! 1284: s = "packet overrun";
! 1285: else if (err == ERR_RUNT)
! 1286: s = "runt packet";
! 1287: else if (err == ERR_ALIGNMENT)
! 1288: s = "bad alignment";
! 1289: else if (err == ERR_CRC)
! 1290: s = "bad crc";
! 1291: else if (err == ERR_OVERSIZE)
! 1292: s = "oversized packet";
! 1293: else if (err == ERR_DRIBBLE)
! 1294: s = "dribble bits";
! 1295:
! 1296: if (s)
! 1297: printf("%s: %s\n", sc->sc_dev.dv_xname, s);
! 1298: }
! 1299: #endif
! 1300:
! 1301: if (len & ERR_INCOMPLETE)
! 1302: return;
! 1303:
! 1304: if (len & ERR_RX) {
! 1305: ++ifp->if_ierrors;
! 1306: goto abort;
! 1307: }
! 1308:
! 1309: len &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */
! 1310:
! 1311: /* Pull packet off interface. */
! 1312: m = epget(sc, len);
! 1313: if (m == NULL) {
! 1314: ifp->if_ierrors++;
! 1315: goto abort;
! 1316: }
! 1317:
! 1318: ++ifp->if_ipackets;
! 1319:
! 1320: #if NBPFILTER > 0
! 1321: /*
! 1322: * Check if there's a BPF listener on this interface.
! 1323: * If so, hand off the raw packet to BPF.
! 1324: */
! 1325: if (ifp->if_bpf)
! 1326: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 1327: #endif
! 1328:
! 1329: ether_input_mbuf(ifp, m);
! 1330:
! 1331: /*
! 1332: * In periods of high traffic we can actually receive enough
! 1333: * packets so that the fifo overrun bit will be set at this point,
! 1334: * even though we just read a packet. In this case we
! 1335: * are not going to receive any more interrupts. We check for
! 1336: * this condition and read again until the fifo is not full.
! 1337: * We could simplify this test by not using epstatus(), but
! 1338: * rechecking the RX_STATUS register directly. This test could
! 1339: * result in unnecessary looping in cases where there is a new
! 1340: * packet but the fifo is not full, but it will not fix the
! 1341: * stuck behavior.
! 1342: *
! 1343: * Even with this improvement, we still get packet overrun errors
! 1344: * which are hurting performance. Maybe when I get some more time
! 1345: * I'll modify epread() so that it can handle RX_EARLY interrupts.
! 1346: */
! 1347: if (epstatus(sc)) {
! 1348: len = bus_space_read_2(iot, ioh,
! 1349: ep_w1_reg(sc, EP_W1_RX_STATUS));
! 1350: /* Check if we are stuck and reset [see XXX comment] */
! 1351: if (len & ERR_INCOMPLETE) {
! 1352: #ifdef EP_DEBUG
! 1353: if (ifp->if_flags & IFF_DEBUG)
! 1354: printf("%s: adapter reset\n",
! 1355: sc->sc_dev.dv_xname);
! 1356: #endif
! 1357: epreset(sc);
! 1358: return;
! 1359: }
! 1360: goto again;
! 1361: }
! 1362:
! 1363: return;
! 1364:
! 1365: abort:
! 1366: ep_discard_rxtop(iot, ioh);
! 1367: }
! 1368:
! 1369: struct mbuf *
! 1370: epget(sc, totlen)
! 1371: struct ep_softc *sc;
! 1372: int totlen;
! 1373: {
! 1374: bus_space_tag_t iot = sc->sc_iot;
! 1375: bus_space_handle_t ioh = sc->sc_ioh;
! 1376: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1377: struct mbuf *top, **mp, *m;
! 1378: int len, pad, sh, rxreg;
! 1379:
! 1380: m = sc->mb[sc->next_mb];
! 1381: sc->mb[sc->next_mb] = NULL;
! 1382: if (m == NULL) {
! 1383: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 1384: if (m == NULL)
! 1385: return (NULL);
! 1386: } else {
! 1387: /* If the queue is no longer full, refill. */
! 1388: if (sc->last_mb == sc->next_mb)
! 1389: timeout_add(&sc->sc_epmbuffill_tmo, 1);
! 1390: /* Convert one of our saved mbuf's. */
! 1391: sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
! 1392: m->m_data = m->m_pktdat;
! 1393: m->m_flags = M_PKTHDR;
! 1394: m_tag_init(m);
! 1395: m->m_pkthdr.csum_flags = 0;
! 1396: }
! 1397: m->m_pkthdr.rcvif = ifp;
! 1398: m->m_pkthdr.len = totlen;
! 1399: pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
! 1400: len = MHLEN;
! 1401: if (totlen >= MINCLSIZE) {
! 1402: MCLGET(m, M_DONTWAIT);
! 1403: if (m->m_flags & M_EXT)
! 1404: len = MCLBYTES;
! 1405: }
! 1406: m->m_data += pad;
! 1407: len -= pad;
! 1408: top = 0;
! 1409: mp = ⊤
! 1410:
! 1411: /*
! 1412: * We read the packet at splhigh() so that an interrupt from another
! 1413: * device doesn't cause the card's buffer to overflow while we're
! 1414: * reading it. We may still lose packets at other times.
! 1415: */
! 1416: sh = splhigh();
! 1417:
! 1418: rxreg = ep_w1_reg(sc, EP_W1_RX_PIO_RD_1);
! 1419:
! 1420: while (totlen > 0) {
! 1421: if (top) {
! 1422: m = sc->mb[sc->next_mb];
! 1423: sc->mb[sc->next_mb] = NULL;
! 1424: if (m == NULL) {
! 1425: MGET(m, M_DONTWAIT, MT_DATA);
! 1426: if (m == NULL) {
! 1427: splx(sh);
! 1428: m_freem(top);
! 1429: return (NULL);
! 1430: }
! 1431: } else
! 1432: sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
! 1433:
! 1434: len = MLEN;
! 1435: }
! 1436: if (top && totlen >= MINCLSIZE) {
! 1437: MCLGET(m, M_DONTWAIT);
! 1438: if (m->m_flags & M_EXT)
! 1439: len = MCLBYTES;
! 1440: }
! 1441: len = min(totlen, len);
! 1442: if (EP_IS_BUS_32(sc->bustype)) {
! 1443: if (len > 3) {
! 1444: len &= ~3;
! 1445: bus_space_read_raw_multi_4(iot, ioh, rxreg,
! 1446: mtod(m, u_int8_t *), len);
! 1447: } else
! 1448: bus_space_read_multi_1(iot, ioh, rxreg,
! 1449: mtod(m, u_int8_t *), len);
! 1450: } else {
! 1451: if (len > 1) {
! 1452: len &= ~1;
! 1453: bus_space_read_raw_multi_2(iot, ioh, rxreg,
! 1454: mtod(m, u_int8_t *), len);
! 1455: } else
! 1456: *(mtod(m, u_int8_t *)) =
! 1457: bus_space_read_1(iot, ioh, rxreg);
! 1458: }
! 1459: m->m_len = len;
! 1460: totlen -= len;
! 1461: *mp = m;
! 1462: mp = &m->m_next;
! 1463: }
! 1464:
! 1465: ep_discard_rxtop(iot, ioh);
! 1466:
! 1467: splx(sh);
! 1468:
! 1469: return top;
! 1470: }
! 1471:
! 1472: int
! 1473: epioctl(ifp, cmd, data)
! 1474: register struct ifnet *ifp;
! 1475: u_long cmd;
! 1476: caddr_t data;
! 1477: {
! 1478: struct ep_softc *sc = ifp->if_softc;
! 1479: struct ifaddr *ifa = (struct ifaddr *)data;
! 1480: struct ifreq *ifr = (struct ifreq *)data;
! 1481: int s, error = 0;
! 1482:
! 1483: s = splnet();
! 1484:
! 1485: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
! 1486: splx(s);
! 1487: return error;
! 1488: }
! 1489:
! 1490: switch (cmd) {
! 1491:
! 1492: case SIOCSIFADDR:
! 1493: ifp->if_flags |= IFF_UP;
! 1494:
! 1495: switch (ifa->ifa_addr->sa_family) {
! 1496: #ifdef INET
! 1497: case AF_INET:
! 1498: epinit(sc);
! 1499: arp_ifinit(&sc->sc_arpcom, ifa);
! 1500: break;
! 1501: #endif
! 1502: default:
! 1503: epinit(sc);
! 1504: break;
! 1505: }
! 1506: break;
! 1507:
! 1508: case SIOCSIFMEDIA:
! 1509: case SIOCGIFMEDIA:
! 1510: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
! 1511: break;
! 1512:
! 1513: case SIOCSIFMTU:
! 1514: if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
! 1515: error = EINVAL;
! 1516: } else if (ifp->if_mtu != ifr->ifr_mtu) {
! 1517: ifp->if_mtu = ifr->ifr_mtu;
! 1518: }
! 1519: break;
! 1520:
! 1521: case SIOCSIFFLAGS:
! 1522: if ((ifp->if_flags & IFF_UP) == 0 &&
! 1523: (ifp->if_flags & IFF_RUNNING) != 0) {
! 1524: /*
! 1525: * If interface is marked down and it is running, then
! 1526: * stop it.
! 1527: */
! 1528: epstop(sc);
! 1529: ifp->if_flags &= ~IFF_RUNNING;
! 1530: } else if ((ifp->if_flags & IFF_UP) != 0 &&
! 1531: (ifp->if_flags & IFF_RUNNING) == 0) {
! 1532: /*
! 1533: * If interface is marked up and it is stopped, then
! 1534: * start it.
! 1535: */
! 1536: epinit(sc);
! 1537: } else if ((ifp->if_flags & IFF_UP) != 0) {
! 1538: /*
! 1539: * Reset the interface to pick up changes in any other
! 1540: * flags that affect hardware registers.
! 1541: */
! 1542: epinit(sc);
! 1543: }
! 1544: break;
! 1545:
! 1546: case SIOCADDMULTI:
! 1547: case SIOCDELMULTI:
! 1548: error = (cmd == SIOCADDMULTI) ?
! 1549: ether_addmulti(ifr, &sc->sc_arpcom) :
! 1550: ether_delmulti(ifr, &sc->sc_arpcom);
! 1551:
! 1552: if (error == ENETRESET) {
! 1553: /*
! 1554: * Multicast list has changed; set the hardware filter
! 1555: * accordingly.
! 1556: */
! 1557: if (ifp->if_flags & IFF_RUNNING)
! 1558: epreset(sc);
! 1559: error = 0;
! 1560: }
! 1561: break;
! 1562:
! 1563: default:
! 1564: error = EINVAL;
! 1565: break;
! 1566: }
! 1567:
! 1568: splx(s);
! 1569: return (error);
! 1570: }
! 1571:
! 1572: void
! 1573: epreset(sc)
! 1574: struct ep_softc *sc;
! 1575: {
! 1576: int s;
! 1577:
! 1578: s = splnet();
! 1579: epinit(sc);
! 1580: splx(s);
! 1581: }
! 1582:
! 1583: void
! 1584: epwatchdog(ifp)
! 1585: struct ifnet *ifp;
! 1586: {
! 1587: struct ep_softc *sc = ifp->if_softc;
! 1588:
! 1589: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
! 1590: ++sc->sc_arpcom.ac_if.if_oerrors;
! 1591:
! 1592: epreset(sc);
! 1593: }
! 1594:
! 1595: void
! 1596: epstop(sc)
! 1597: register struct ep_softc *sc;
! 1598: {
! 1599: bus_space_tag_t iot = sc->sc_iot;
! 1600: bus_space_handle_t ioh = sc->sc_ioh;
! 1601:
! 1602: if (sc->ep_flags & EP_FLAGS_MII) {
! 1603: mii_down(&sc->sc_mii);
! 1604: }
! 1605:
! 1606: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
! 1607: /* Clear the FIFO buffer count, thus halting
! 1608: * any currently-running transactions.
! 1609: */
! 1610: GO_WINDOW(1); /* sanity */
! 1611: bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0);
! 1612: bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
! 1613: }
! 1614:
! 1615: bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
! 1616: ep_discard_rxtop(iot, ioh);
! 1617:
! 1618: bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
! 1619: bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
! 1620:
! 1621: ep_reset_cmd(sc, EP_COMMAND, RX_RESET);
! 1622: ep_reset_cmd(sc, EP_COMMAND, TX_RESET);
! 1623:
! 1624: bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
! 1625: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
! 1626: bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
! 1627: bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
! 1628:
! 1629: epmbufempty(sc);
! 1630: }
! 1631:
! 1632: /*
! 1633: * We get eeprom data from the id_port given an offset into the
! 1634: * eeprom. Basically; after the ID_sequence is sent to all of
! 1635: * the cards; they enter the ID_CMD state where they will accept
! 1636: * command requests. 0x80-0xbf loads the eeprom data. We then
! 1637: * read the port 16 times and with every read; the cards check
! 1638: * for contention (ie: if one card writes a 0 bit and another
! 1639: * writes a 1 bit then the host sees a 0. At the end of the cycle;
! 1640: * each card compares the data on the bus; if there is a difference
! 1641: * then that card goes into ID_WAIT state again). In the meantime;
! 1642: * one bit of data is returned in the AX register which is conveniently
! 1643: * returned to us by bus_space_read_1(). Hence; we read 16 times getting one
! 1644: * bit of data with each read.
! 1645: *
! 1646: * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
! 1647: */
! 1648: u_int16_t
! 1649: epreadeeprom(iot, ioh, offset)
! 1650: bus_space_tag_t iot;
! 1651: bus_space_handle_t ioh;
! 1652: int offset;
! 1653: {
! 1654: u_int16_t data = 0;
! 1655: int i;
! 1656:
! 1657: bus_space_write_1(iot, ioh, 0, 0x80 + offset);
! 1658: delay(1000);
! 1659: for (i = 0; i < 16; i++)
! 1660: data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
! 1661: return (data);
! 1662: }
! 1663:
! 1664: int
! 1665: epbusyeeprom(sc)
! 1666: struct ep_softc *sc;
! 1667: {
! 1668: bus_space_tag_t iot = sc->sc_iot;
! 1669: bus_space_handle_t ioh = sc->sc_ioh;
! 1670: int i = 100, j;
! 1671:
! 1672: while (i--) {
! 1673: j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND);
! 1674: if (j & EEPROM_BUSY)
! 1675: delay(100);
! 1676: else
! 1677: break;
! 1678: }
! 1679: if (!i) {
! 1680: printf("\n%s: eeprom failed to come ready\n",
! 1681: sc->sc_dev.dv_xname);
! 1682: return (1);
! 1683: }
! 1684: if (sc->bustype != EP_BUS_PCMCIA && sc->bustype != EP_BUS_PCI &&
! 1685: (j & EEPROM_TST_MODE)) {
! 1686: printf("\n%s: erase pencil mark, or disable PnP mode!\n",
! 1687: sc->sc_dev.dv_xname);
! 1688: return (1);
! 1689: }
! 1690: return (0);
! 1691: }
! 1692:
! 1693: u_int16_t
! 1694: ep_read_eeprom(sc, offset)
! 1695: struct ep_softc *sc;
! 1696: u_int16_t offset;
! 1697: {
! 1698: u_int16_t readcmd;
! 1699:
! 1700: /*
! 1701: * RoadRunner has a larger EEPROM, so a different read command
! 1702: * is required.
! 1703: */
! 1704: if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER)
! 1705: readcmd = READ_EEPROM_RR;
! 1706: else
! 1707: readcmd = READ_EEPROM;
! 1708:
! 1709: if (epbusyeeprom(sc))
! 1710: return (0); /* XXX why is eeprom busy? */
! 1711: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W0_EEPROM_COMMAND,
! 1712: readcmd | offset);
! 1713: if (epbusyeeprom(sc))
! 1714: return (0); /* XXX why is eeprom busy? */
! 1715:
! 1716: return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W0_EEPROM_DATA));
! 1717: }
! 1718:
! 1719: void
! 1720: epmbuffill(v)
! 1721: void *v;
! 1722: {
! 1723: struct ep_softc *sc = v;
! 1724: int s, i;
! 1725:
! 1726: s = splnet();
! 1727: i = sc->last_mb;
! 1728: do {
! 1729: if (sc->mb[i] == NULL)
! 1730: MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
! 1731: if (sc->mb[i] == NULL)
! 1732: break;
! 1733: i = (i + 1) % MAX_MBS;
! 1734: } while (i != sc->next_mb);
! 1735: sc->last_mb = i;
! 1736: /* If the queue was not filled, try again. */
! 1737: if (sc->last_mb != sc->next_mb)
! 1738: timeout_add(&sc->sc_epmbuffill_tmo, 1);
! 1739: splx(s);
! 1740: }
! 1741:
! 1742: void
! 1743: epmbufempty(sc)
! 1744: struct ep_softc *sc;
! 1745: {
! 1746: int s, i;
! 1747:
! 1748: s = splnet();
! 1749: for (i = 0; i<MAX_MBS; i++) {
! 1750: if (sc->mb[i]) {
! 1751: m_freem(sc->mb[i]);
! 1752: sc->mb[i] = NULL;
! 1753: }
! 1754: }
! 1755: sc->last_mb = sc->next_mb = 0;
! 1756: timeout_del(&sc->sc_epmbuffill_tmo);
! 1757: splx(s);
! 1758: }
! 1759:
! 1760: void
! 1761: ep_mii_setbit(sc, bit)
! 1762: struct ep_softc *sc;
! 1763: u_int16_t bit;
! 1764: {
! 1765: u_int16_t val;
! 1766:
! 1767: /* We assume we're already in Window 4 */
! 1768: val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT);
! 1769: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT,
! 1770: val | bit);
! 1771: }
! 1772:
! 1773: void
! 1774: ep_mii_clrbit(sc, bit)
! 1775: struct ep_softc *sc;
! 1776: u_int16_t bit;
! 1777: {
! 1778: u_int16_t val;
! 1779:
! 1780: /* We assume we're already in Window 4 */
! 1781: val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT);
! 1782: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT,
! 1783: val & ~bit);
! 1784: }
! 1785:
! 1786: u_int16_t
! 1787: ep_mii_readbit(sc, bit)
! 1788: struct ep_softc *sc;
! 1789: u_int16_t bit;
! 1790: {
! 1791:
! 1792: /* We assume we're already in Window 4 */
! 1793: return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT) &
! 1794: bit);
! 1795: }
! 1796:
! 1797: void
! 1798: ep_mii_sync(sc)
! 1799: struct ep_softc *sc;
! 1800: {
! 1801: int i;
! 1802:
! 1803: /* We assume we're already in Window 4 */
! 1804: ep_mii_clrbit(sc, PHYSMGMT_DIR);
! 1805: for (i = 0; i < 32; i++) {
! 1806: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1807: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1808: }
! 1809: }
! 1810:
! 1811: void
! 1812: ep_mii_sendbits(sc, data, nbits)
! 1813: struct ep_softc *sc;
! 1814: u_int32_t data;
! 1815: int nbits;
! 1816: {
! 1817: int i;
! 1818:
! 1819: /* We assume we're already in Window 4 */
! 1820: ep_mii_setbit(sc, PHYSMGMT_DIR);
! 1821: for (i = 1 << (nbits - 1); i; i = i >> 1) {
! 1822: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1823: ep_mii_readbit(sc, PHYSMGMT_CLK);
! 1824: if (data & i)
! 1825: ep_mii_setbit(sc, PHYSMGMT_DATA);
! 1826: else
! 1827: ep_mii_clrbit(sc, PHYSMGMT_DATA);
! 1828: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1829: ep_mii_readbit(sc, PHYSMGMT_CLK);
! 1830: }
! 1831: }
! 1832:
! 1833: int
! 1834: ep_mii_readreg(self, phy, reg)
! 1835: struct device *self;
! 1836: int phy, reg;
! 1837: {
! 1838: struct ep_softc *sc = (struct ep_softc *)self;
! 1839: int val = 0, i, err;
! 1840:
! 1841: /*
! 1842: * Read the PHY register by manually driving the MII control lines.
! 1843: */
! 1844:
! 1845: GO_WINDOW(4);
! 1846:
! 1847: bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT, 0);
! 1848:
! 1849: ep_mii_sync(sc);
! 1850: ep_mii_sendbits(sc, MII_COMMAND_START, 2);
! 1851: ep_mii_sendbits(sc, MII_COMMAND_READ, 2);
! 1852: ep_mii_sendbits(sc, phy, 5);
! 1853: ep_mii_sendbits(sc, reg, 5);
! 1854:
! 1855: ep_mii_clrbit(sc, PHYSMGMT_DIR);
! 1856: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1857: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1858: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1859:
! 1860: err = ep_mii_readbit(sc, PHYSMGMT_DATA);
! 1861: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1862:
! 1863: /* Even if an error occurs, must still clock out the cycle. */
! 1864: for (i = 0; i < 16; i++) {
! 1865: val <<= 1;
! 1866: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1867: if (err == 0 && ep_mii_readbit(sc, PHYSMGMT_DATA))
! 1868: val |= 1;
! 1869: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1870: }
! 1871: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1872: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1873:
! 1874: GO_WINDOW(1); /* back to operating window */
! 1875:
! 1876: return (err ? 0 : val);
! 1877: }
! 1878:
! 1879: void
! 1880: ep_mii_writereg(self, phy, reg, val)
! 1881: struct device *self;
! 1882: int phy, reg, val;
! 1883: {
! 1884: struct ep_softc *sc = (struct ep_softc *)self;
! 1885:
! 1886: /*
! 1887: * Write the PHY register by manually driving the MII control lines.
! 1888: */
! 1889:
! 1890: GO_WINDOW(4);
! 1891:
! 1892: ep_mii_sync(sc);
! 1893: ep_mii_sendbits(sc, MII_COMMAND_START, 2);
! 1894: ep_mii_sendbits(sc, MII_COMMAND_WRITE, 2);
! 1895: ep_mii_sendbits(sc, phy, 5);
! 1896: ep_mii_sendbits(sc, reg, 5);
! 1897: ep_mii_sendbits(sc, MII_COMMAND_ACK, 2);
! 1898: ep_mii_sendbits(sc, val, 16);
! 1899:
! 1900: ep_mii_clrbit(sc, PHYSMGMT_CLK);
! 1901: ep_mii_setbit(sc, PHYSMGMT_CLK);
! 1902:
! 1903: GO_WINDOW(1); /* back to operating window */
! 1904: }
! 1905:
! 1906: void
! 1907: ep_statchg(self)
! 1908: struct device *self;
! 1909: {
! 1910: struct ep_softc *sc = (struct ep_softc *)self;
! 1911: bus_space_tag_t iot = sc->sc_iot;
! 1912: bus_space_handle_t ioh = sc->sc_ioh;
! 1913: int mctl;
! 1914:
! 1915: /* XXX Update ifp->if_baudrate */
! 1916:
! 1917: GO_WINDOW(3);
! 1918: mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL);
! 1919: if (sc->sc_mii.mii_media_active & IFM_FDX)
! 1920: mctl |= MAC_CONTROL_FDX;
! 1921: else
! 1922: mctl &= ~MAC_CONTROL_FDX;
! 1923: bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl);
! 1924: GO_WINDOW(1); /* back to operating window */
! 1925: }
CVSweb