Annotation of sys/dev/ic/fxp.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: fxp.c,v 1.87 2007/06/06 09:43:44 henning Exp $ */
! 2: /* $NetBSD: if_fxp.c,v 1.2 1997/06/05 02:01:55 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995, David Greenman
! 6: * All rights reserved.
! 7: *
! 8: * Modifications to support NetBSD:
! 9: * Copyright (c) 1997 Jason R. Thorpe. All rights reserved.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice unmodified, this list of conditions, and the following
! 16: * 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: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: *
! 33: * Id: if_fxp.c,v 1.55 1998/08/04 08:53:12 dg Exp
! 34: */
! 35:
! 36: /*
! 37: * Intel EtherExpress Pro/100B PCI Fast Ethernet driver
! 38: */
! 39:
! 40: #include "bpfilter.h"
! 41:
! 42: #include <sys/param.h>
! 43: #include <sys/systm.h>
! 44: #include <sys/mbuf.h>
! 45: #include <sys/malloc.h>
! 46: #include <sys/kernel.h>
! 47: #include <sys/socket.h>
! 48: #include <sys/syslog.h>
! 49: #include <sys/timeout.h>
! 50:
! 51: #include <net/if.h>
! 52: #include <net/if_dl.h>
! 53: #include <net/if_media.h>
! 54: #include <net/if_types.h>
! 55:
! 56: #ifdef INET
! 57: #include <netinet/in.h>
! 58: #include <netinet/in_systm.h>
! 59: #include <netinet/in_var.h>
! 60: #include <netinet/ip.h>
! 61: #endif
! 62:
! 63: #if NBPFILTER > 0
! 64: #include <net/bpf.h>
! 65: #endif
! 66:
! 67: #include <sys/ioctl.h>
! 68: #include <sys/errno.h>
! 69: #include <sys/device.h>
! 70:
! 71: #include <netinet/if_ether.h>
! 72:
! 73: #include <machine/cpu.h>
! 74: #include <machine/bus.h>
! 75: #include <machine/intr.h>
! 76:
! 77: #include <dev/mii/miivar.h>
! 78:
! 79: #include <dev/ic/fxpreg.h>
! 80: #include <dev/ic/fxpvar.h>
! 81:
! 82: /*
! 83: * NOTE! On the Alpha, we have an alignment constraint. The
! 84: * card DMAs the packet immediately following the RFA. However,
! 85: * the first thing in the packet is a 14-byte Ethernet header.
! 86: * This means that the packet is misaligned. To compensate,
! 87: * we actually offset the RFA 2 bytes into the cluster. This
! 88: * aligns the packet after the Ethernet header at a 32-bit
! 89: * boundary. HOWEVER! This means that the RFA is misaligned!
! 90: */
! 91: #define RFA_ALIGNMENT_FUDGE (2 + sizeof(bus_dmamap_t *))
! 92:
! 93: /*
! 94: * Inline function to copy a 16-bit aligned 32-bit quantity.
! 95: */
! 96: static __inline void fxp_lwcopy(volatile u_int32_t *,
! 97: volatile u_int32_t *);
! 98:
! 99: static __inline void
! 100: fxp_lwcopy(volatile u_int32_t *src, volatile u_int32_t *dst)
! 101: {
! 102: volatile u_int16_t *a = (u_int16_t *)src;
! 103: volatile u_int16_t *b = (u_int16_t *)dst;
! 104:
! 105: b[0] = a[0];
! 106: b[1] = a[1];
! 107: }
! 108:
! 109: /*
! 110: * Template for default configuration parameters.
! 111: * See struct fxp_cb_config for the bit definitions.
! 112: * Note, cb_command is filled in later.
! 113: */
! 114: static u_char fxp_cb_config_template[] = {
! 115: 0x0, 0x0, /* cb_status */
! 116: 0x0, 0x0, /* cb_command */
! 117: 0xff, 0xff, 0xff, 0xff, /* link_addr */
! 118: 0x16, /* 0 Byte count. */
! 119: 0x08, /* 1 Fifo limit */
! 120: 0x00, /* 2 Adaptive ifs */
! 121: 0x00, /* 3 ctrl0 */
! 122: 0x00, /* 4 rx_dma_bytecount */
! 123: 0x80, /* 5 tx_dma_bytecount */
! 124: 0xb2, /* 6 ctrl 1*/
! 125: 0x03, /* 7 ctrl 2*/
! 126: 0x01, /* 8 mediatype */
! 127: 0x00, /* 9 void2 */
! 128: 0x26, /* 10 ctrl3 */
! 129: 0x00, /* 11 linear priority */
! 130: 0x60, /* 12 interfrm_spacing */
! 131: 0x00, /* 13 void31 */
! 132: 0xf2, /* 14 void32 */
! 133: 0x48, /* 15 promiscuous */
! 134: 0x00, /* 16 void41 */
! 135: 0x40, /* 17 void42 */
! 136: 0xf3, /* 18 stripping */
! 137: 0x00, /* 19 fdx_pin */
! 138: 0x3f, /* 20 multi_ia */
! 139: 0x05 /* 21 mc_all */
! 140: };
! 141:
! 142: void fxp_eeprom_shiftin(struct fxp_softc *, int, int);
! 143: void fxp_eeprom_putword(struct fxp_softc *, int, u_int16_t);
! 144: void fxp_write_eeprom(struct fxp_softc *, u_short *, int, int);
! 145: int fxp_mediachange(struct ifnet *);
! 146: void fxp_mediastatus(struct ifnet *, struct ifmediareq *);
! 147: void fxp_scb_wait(struct fxp_softc *);
! 148: void fxp_start(struct ifnet *);
! 149: int fxp_ioctl(struct ifnet *, u_long, caddr_t);
! 150: void fxp_init(void *);
! 151: void fxp_load_ucode(struct fxp_softc *);
! 152: void fxp_stop(struct fxp_softc *, int);
! 153: void fxp_watchdog(struct ifnet *);
! 154: int fxp_add_rfabuf(struct fxp_softc *, struct mbuf *);
! 155: int fxp_mdi_read(struct device *, int, int);
! 156: void fxp_mdi_write(struct device *, int, int, int);
! 157: void fxp_autosize_eeprom(struct fxp_softc *);
! 158: void fxp_statchg(struct device *);
! 159: void fxp_read_eeprom(struct fxp_softc *, u_int16_t *,
! 160: int, int);
! 161: void fxp_stats_update(void *);
! 162: void fxp_mc_setup(struct fxp_softc *, int);
! 163: void fxp_scb_cmd(struct fxp_softc *, u_int8_t);
! 164:
! 165: /*
! 166: * Set initial transmit threshold at 64 (512 bytes). This is
! 167: * increased by 64 (512 bytes) at a time, to maximum of 192
! 168: * (1536 bytes), if an underrun occurs.
! 169: */
! 170: static int tx_threshold = 64;
! 171:
! 172: /*
! 173: * Interrupts coalescing code params
! 174: */
! 175: int fxp_int_delay = FXP_INT_DELAY;
! 176: int fxp_bundle_max = FXP_BUNDLE_MAX;
! 177: int fxp_min_size_mask = FXP_MIN_SIZE_MASK;
! 178:
! 179: /*
! 180: * TxCB list index mask. This is used to do list wrap-around.
! 181: */
! 182: #define FXP_TXCB_MASK (FXP_NTXCB - 1)
! 183:
! 184: /*
! 185: * Maximum number of seconds that the receiver can be idle before we
! 186: * assume it's dead and attempt to reset it by reprogramming the
! 187: * multicast filter. This is part of a work-around for a bug in the
! 188: * NIC. See fxp_stats_update().
! 189: */
! 190: #define FXP_MAX_RX_IDLE 15
! 191:
! 192: /*
! 193: * Wait for the previous command to be accepted (but not necessarily
! 194: * completed).
! 195: */
! 196: void
! 197: fxp_scb_wait(struct fxp_softc *sc)
! 198: {
! 199: int i = 10000;
! 200:
! 201: while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i)
! 202: DELAY(2);
! 203: if (i == 0)
! 204: printf("%s: warning: SCB timed out\n", sc->sc_dev.dv_xname);
! 205: }
! 206:
! 207: void
! 208: fxp_eeprom_shiftin(struct fxp_softc *sc, int data, int length)
! 209: {
! 210: u_int16_t reg;
! 211: int x;
! 212:
! 213: /*
! 214: * Shift in data.
! 215: */
! 216: for (x = 1 << (length - 1); x; x >>= 1) {
! 217: if (data & x)
! 218: reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
! 219: else
! 220: reg = FXP_EEPROM_EECS;
! 221: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 222: DELAY(1);
! 223: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg | FXP_EEPROM_EESK);
! 224: DELAY(1);
! 225: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 226: DELAY(1);
! 227: }
! 228: }
! 229:
! 230: void
! 231: fxp_eeprom_putword(struct fxp_softc *sc, int offset, u_int16_t data)
! 232: {
! 233: int i;
! 234:
! 235: /*
! 236: * Erase/write enable.
! 237: */
! 238: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 239: fxp_eeprom_shiftin(sc, 0x4, 3);
! 240: fxp_eeprom_shiftin(sc, 0x03 << (sc->eeprom_size - 2), sc->eeprom_size);
! 241: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
! 242: DELAY(1);
! 243: /*
! 244: * Shift in write opcode, address, data.
! 245: */
! 246: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 247: fxp_eeprom_shiftin(sc, FXP_EEPROM_OPC_WRITE, 3);
! 248: fxp_eeprom_shiftin(sc, offset, sc->eeprom_size);
! 249: fxp_eeprom_shiftin(sc, data, 16);
! 250: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
! 251: DELAY(1);
! 252: /*
! 253: * Wait for EEPROM to finish up.
! 254: */
! 255: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 256: DELAY(1);
! 257: for (i = 0; i < 1000; i++) {
! 258: if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO)
! 259: break;
! 260: DELAY(50);
! 261: }
! 262: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
! 263: DELAY(1);
! 264: /*
! 265: * Erase/write disable.
! 266: */
! 267: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 268: fxp_eeprom_shiftin(sc, 0x4, 3);
! 269: fxp_eeprom_shiftin(sc, 0, sc->eeprom_size);
! 270: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
! 271: DELAY(1);
! 272: }
! 273:
! 274: void
! 275: fxp_write_eeprom(struct fxp_softc *sc, u_short *data, int offset, int words)
! 276: {
! 277: int i;
! 278:
! 279: for (i = 0; i < words; i++)
! 280: fxp_eeprom_putword(sc, offset + i, data[i]);
! 281: }
! 282:
! 283: /*************************************************************
! 284: * Operating system-specific autoconfiguration glue
! 285: *************************************************************/
! 286:
! 287: void fxp_shutdown(void *);
! 288: void fxp_power(int, void *);
! 289:
! 290: struct cfdriver fxp_cd = {
! 291: NULL, "fxp", DV_IFNET
! 292: };
! 293:
! 294: /*
! 295: * Device shutdown routine. Called at system shutdown after sync. The
! 296: * main purpose of this routine is to shut off receiver DMA so that
! 297: * kernel memory doesn't get clobbered during warmboot.
! 298: */
! 299: void
! 300: fxp_shutdown(void *sc)
! 301: {
! 302: fxp_stop((struct fxp_softc *) sc, 0);
! 303: }
! 304:
! 305: /*
! 306: * Power handler routine. Called when the system is transitioning
! 307: * into/out of power save modes. As with fxp_shutdown, the main
! 308: * purpose of this routine is to shut off receiver DMA so it doesn't
! 309: * clobber kernel memory at the wrong time.
! 310: */
! 311: void
! 312: fxp_power(int why, void *arg)
! 313: {
! 314: struct fxp_softc *sc = arg;
! 315: struct ifnet *ifp;
! 316: int s;
! 317:
! 318: s = splnet();
! 319: if (why != PWR_RESUME)
! 320: fxp_stop(sc, 0);
! 321: else {
! 322: ifp = &sc->sc_arpcom.ac_if;
! 323: if (ifp->if_flags & IFF_UP)
! 324: fxp_init(sc);
! 325: }
! 326: splx(s);
! 327: }
! 328:
! 329: /*************************************************************
! 330: * End of operating system-specific autoconfiguration glue
! 331: *************************************************************/
! 332:
! 333: /*
! 334: * Do generic parts of attach.
! 335: */
! 336: int
! 337: fxp_attach(struct fxp_softc *sc, const char *intrstr)
! 338: {
! 339: struct ifnet *ifp;
! 340: struct mbuf *m;
! 341: bus_dmamap_t rxmap;
! 342: u_int16_t data;
! 343: u_int8_t enaddr[6];
! 344: int i, err;
! 345:
! 346: /*
! 347: * Reset to a stable state.
! 348: */
! 349: CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET);
! 350: DELAY(10);
! 351:
! 352: if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct fxp_ctrl),
! 353: PAGE_SIZE, 0, &sc->sc_cb_seg, 1, &sc->sc_cb_nseg, BUS_DMA_NOWAIT))
! 354: goto fail;
! 355: if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cb_seg, sc->sc_cb_nseg,
! 356: sizeof(struct fxp_ctrl), (caddr_t *)&sc->sc_ctrl,
! 357: BUS_DMA_NOWAIT)) {
! 358: bus_dmamem_free(sc->sc_dmat, &sc->sc_cb_seg, sc->sc_cb_nseg);
! 359: goto fail;
! 360: }
! 361: if (bus_dmamap_create(sc->sc_dmat, sizeof(struct fxp_ctrl),
! 362: 1, sizeof(struct fxp_ctrl), 0, BUS_DMA_NOWAIT,
! 363: &sc->tx_cb_map)) {
! 364: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_ctrl,
! 365: sizeof(struct fxp_ctrl));
! 366: bus_dmamem_free(sc->sc_dmat, &sc->sc_cb_seg, sc->sc_cb_nseg);
! 367: goto fail;
! 368: }
! 369: if (bus_dmamap_load(sc->sc_dmat, sc->tx_cb_map, (caddr_t)sc->sc_ctrl,
! 370: sizeof(struct fxp_ctrl), NULL, BUS_DMA_NOWAIT)) {
! 371: bus_dmamap_destroy(sc->sc_dmat, sc->tx_cb_map);
! 372: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_ctrl,
! 373: sizeof(struct fxp_ctrl));
! 374: bus_dmamem_free(sc->sc_dmat, &sc->sc_cb_seg, sc->sc_cb_nseg);
! 375: goto fail;
! 376: }
! 377:
! 378: for (i = 0; i < FXP_NTXCB; i++) {
! 379: if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
! 380: FXP_NTXSEG, MCLBYTES, 0, 0, &sc->txs[i].tx_map)) != 0) {
! 381: printf("%s: unable to create tx dma map %d, error %d\n",
! 382: sc->sc_dev.dv_xname, i, err);
! 383: goto fail;
! 384: }
! 385: sc->txs[i].tx_mbuf = NULL;
! 386: sc->txs[i].tx_cb = sc->sc_ctrl->tx_cb + i;
! 387: sc->txs[i].tx_off = offsetof(struct fxp_ctrl, tx_cb[i]);
! 388: sc->txs[i].tx_next = &sc->txs[(i + 1) & FXP_TXCB_MASK];
! 389: }
! 390: bzero(sc->sc_ctrl, sizeof(struct fxp_ctrl));
! 391:
! 392: /*
! 393: * Pre-allocate some receive buffers.
! 394: */
! 395: sc->sc_rxfree = 0;
! 396: for (i = 0; i < FXP_NRFABUFS_MIN; i++) {
! 397: if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
! 398: MCLBYTES, 0, 0, &sc->sc_rxmaps[i])) != 0) {
! 399: printf("%s: unable to create rx dma map %d, error %d\n",
! 400: sc->sc_dev.dv_xname, i, err);
! 401: goto fail;
! 402: }
! 403: sc->rx_bufs++;
! 404: }
! 405: for (i = 0; i < FXP_NRFABUFS_MIN; i++)
! 406: if (fxp_add_rfabuf(sc, NULL) != 0)
! 407: goto fail;
! 408:
! 409: /*
! 410: * Find out how large of an SEEPROM we have.
! 411: */
! 412: fxp_autosize_eeprom(sc);
! 413:
! 414: /*
! 415: * Get info about the primary PHY
! 416: */
! 417: fxp_read_eeprom(sc, (u_int16_t *)&data, 6, 1);
! 418: sc->phy_primary_addr = data & 0xff;
! 419: sc->phy_primary_device = (data >> 8) & 0x3f;
! 420: sc->phy_10Mbps_only = data >> 15;
! 421:
! 422: /*
! 423: * Only 82558 and newer cards can do this.
! 424: */
! 425: if (sc->sc_revision >= FXP_REV_82558_A4) {
! 426: sc->sc_int_delay = fxp_int_delay;
! 427: sc->sc_bundle_max = fxp_bundle_max;
! 428: sc->sc_min_size_mask = fxp_min_size_mask;
! 429: }
! 430: /*
! 431: * Read MAC address.
! 432: */
! 433: fxp_read_eeprom(sc, (u_int16_t *)enaddr, 0, 3);
! 434:
! 435: ifp = &sc->sc_arpcom.ac_if;
! 436: bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
! 437: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
! 438: ifp->if_softc = sc;
! 439: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 440: ifp->if_ioctl = fxp_ioctl;
! 441: ifp->if_start = fxp_start;
! 442: ifp->if_watchdog = fxp_watchdog;
! 443: IFQ_SET_MAXLEN(&ifp->if_snd, FXP_NTXCB - 1);
! 444: IFQ_SET_READY(&ifp->if_snd);
! 445:
! 446: ifp->if_capabilities = IFCAP_VLAN_MTU;
! 447:
! 448: printf(": %s, address %s\n", intrstr,
! 449: ether_sprintf(sc->sc_arpcom.ac_enaddr));
! 450:
! 451: if (sc->sc_flags & FXPF_DISABLE_STANDBY) {
! 452: fxp_read_eeprom(sc, &data, 10, 1);
! 453: if (data & 0x02) { /* STB enable */
! 454: u_int16_t cksum;
! 455: int i;
! 456:
! 457: printf("%s: Disabling dynamic standby mode in EEPROM",
! 458: sc->sc_dev.dv_xname);
! 459: data &= ~0x02;
! 460: fxp_write_eeprom(sc, &data, 10, 1);
! 461: printf(", New ID 0x%x", data);
! 462: cksum = 0;
! 463: for (i = 0; i < (1 << sc->eeprom_size) - 1; i++) {
! 464: fxp_read_eeprom(sc, &data, i, 1);
! 465: cksum += data;
! 466: }
! 467: i = (1 << sc->eeprom_size) - 1;
! 468: cksum = 0xBABA - cksum;
! 469: fxp_read_eeprom(sc, &data, i, 1);
! 470: fxp_write_eeprom(sc, &cksum, i, 1);
! 471: printf(", cksum @ 0x%x: 0x%x -> 0x%x\n",
! 472: i, data, cksum);
! 473: }
! 474: }
! 475:
! 476: /* Receiver lock-up workaround detection. */
! 477: fxp_read_eeprom(sc, &data, 3, 1);
! 478: if ((data & 0x03) != 0x03)
! 479: sc->sc_flags |= FXPF_RECV_WORKAROUND;
! 480:
! 481: /*
! 482: * Initialize our media structures and probe the MII.
! 483: */
! 484: sc->sc_mii.mii_ifp = ifp;
! 485: sc->sc_mii.mii_readreg = fxp_mdi_read;
! 486: sc->sc_mii.mii_writereg = fxp_mdi_write;
! 487: sc->sc_mii.mii_statchg = fxp_statchg;
! 488: ifmedia_init(&sc->sc_mii.mii_media, 0, fxp_mediachange,
! 489: fxp_mediastatus);
! 490: mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
! 491: MII_OFFSET_ANY, MIIF_NOISOLATE);
! 492: /* If no phy found, just use auto mode */
! 493: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
! 494: ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL,
! 495: 0, NULL);
! 496: printf("%s: no phy found, using manual mode\n",
! 497: sc->sc_dev.dv_xname);
! 498: }
! 499:
! 500: if (ifmedia_match(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL, 0))
! 501: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL);
! 502: else if (ifmedia_match(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO, 0))
! 503: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
! 504: else
! 505: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T);
! 506:
! 507: /*
! 508: * Attach the interface.
! 509: */
! 510: if_attach(ifp);
! 511: ether_ifattach(ifp);
! 512:
! 513: /*
! 514: * Add shutdown hook so that DMA is disabled prior to reboot. Not
! 515: * doing so could allow DMA to corrupt kernel memory during the
! 516: * reboot before the driver initializes.
! 517: */
! 518: sc->sc_sdhook = shutdownhook_establish(fxp_shutdown, sc);
! 519:
! 520: /*
! 521: * Add suspend hook, for similiar reasons..
! 522: */
! 523: sc->sc_powerhook = powerhook_establish(fxp_power, sc);
! 524:
! 525: /*
! 526: * Initialize timeout for statistics update.
! 527: */
! 528: timeout_set(&sc->stats_update_to, fxp_stats_update, sc);
! 529:
! 530: return (0);
! 531:
! 532: fail:
! 533: printf("%s: Failed to malloc memory\n", sc->sc_dev.dv_xname);
! 534: if (sc->tx_cb_map != NULL) {
! 535: bus_dmamap_unload(sc->sc_dmat, sc->tx_cb_map);
! 536: bus_dmamap_destroy(sc->sc_dmat, sc->tx_cb_map);
! 537: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_ctrl,
! 538: sizeof(struct fxp_cb_tx) * FXP_NTXCB);
! 539: bus_dmamem_free(sc->sc_dmat, &sc->sc_cb_seg, sc->sc_cb_nseg);
! 540: }
! 541: m = sc->rfa_headm;
! 542: while (m != NULL) {
! 543: rxmap = *((bus_dmamap_t *)m->m_ext.ext_buf);
! 544: bus_dmamap_unload(sc->sc_dmat, rxmap);
! 545: FXP_RXMAP_PUT(sc, rxmap);
! 546: m = m_free(m);
! 547: }
! 548: return (ENOMEM);
! 549: }
! 550:
! 551: /*
! 552: * From NetBSD:
! 553: *
! 554: * Figure out EEPROM size.
! 555: *
! 556: * 559's can have either 64-word or 256-word EEPROMs, the 558
! 557: * datasheet only talks about 64-word EEPROMs, and the 557 datasheet
! 558: * talks about the existence of 16 to 256 word EEPROMs.
! 559: *
! 560: * The only known sizes are 64 and 256, where the 256 version is used
! 561: * by CardBus cards to store CIS information.
! 562: *
! 563: * The address is shifted in msb-to-lsb, and after the last
! 564: * address-bit the EEPROM is supposed to output a `dummy zero' bit,
! 565: * after which follows the actual data. We try to detect this zero, by
! 566: * probing the data-out bit in the EEPROM control register just after
! 567: * having shifted in a bit. If the bit is zero, we assume we've
! 568: * shifted enough address bits. The data-out should be tri-state,
! 569: * before this, which should translate to a logical one.
! 570: *
! 571: * Other ways to do this would be to try to read a register with known
! 572: * contents with a varying number of address bits, but no such
! 573: * register seem to be available. The high bits of register 10 are 01
! 574: * on the 558 and 559, but apparently not on the 557.
! 575: *
! 576: * The Linux driver computes a checksum on the EEPROM data, but the
! 577: * value of this checksum is not very well documented.
! 578: */
! 579: void
! 580: fxp_autosize_eeprom(struct fxp_softc *sc)
! 581: {
! 582: u_int16_t reg;
! 583: int x;
! 584:
! 585: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 586: /*
! 587: * Shift in read opcode.
! 588: */
! 589: for (x = 3; x > 0; x--) {
! 590: if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
! 591: reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
! 592: } else {
! 593: reg = FXP_EEPROM_EECS;
! 594: }
! 595: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 596: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
! 597: reg | FXP_EEPROM_EESK);
! 598: DELAY(4);
! 599: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 600: DELAY(4);
! 601: }
! 602: /*
! 603: * Shift in address.
! 604: * Wait for the dummy zero following a correct address shift.
! 605: */
! 606: for (x = 1; x <= 8; x++) {
! 607: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 608: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
! 609: FXP_EEPROM_EECS | FXP_EEPROM_EESK);
! 610: DELAY(4);
! 611: if ((CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) & FXP_EEPROM_EEDO) == 0)
! 612: break;
! 613: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 614: DELAY(4);
! 615: }
! 616: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
! 617: DELAY(4);
! 618: sc->eeprom_size = x;
! 619: }
! 620:
! 621: /*
! 622: * Read from the serial EEPROM. Basically, you manually shift in
! 623: * the read opcode (one bit at a time) and then shift in the address,
! 624: * and then you shift out the data (all of this one bit at a time).
! 625: * The word size is 16 bits, so you have to provide the address for
! 626: * every 16 bits of data.
! 627: */
! 628: void
! 629: fxp_read_eeprom(struct fxp_softc *sc, u_short *data, int offset,
! 630: int words)
! 631: {
! 632: u_int16_t reg;
! 633: int i, x;
! 634:
! 635: for (i = 0; i < words; i++) {
! 636: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
! 637: /*
! 638: * Shift in read opcode.
! 639: */
! 640: for (x = 3; x > 0; x--) {
! 641: if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
! 642: reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
! 643: } else {
! 644: reg = FXP_EEPROM_EECS;
! 645: }
! 646: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 647: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
! 648: reg | FXP_EEPROM_EESK);
! 649: DELAY(4);
! 650: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 651: DELAY(4);
! 652: }
! 653: /*
! 654: * Shift in address.
! 655: */
! 656: for (x = sc->eeprom_size; x > 0; x--) {
! 657: if ((i + offset) & (1 << (x - 1))) {
! 658: reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
! 659: } else {
! 660: reg = FXP_EEPROM_EECS;
! 661: }
! 662: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 663: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
! 664: reg | FXP_EEPROM_EESK);
! 665: DELAY(4);
! 666: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 667: DELAY(4);
! 668: }
! 669: reg = FXP_EEPROM_EECS;
! 670: data[i] = 0;
! 671: /*
! 672: * Shift out data.
! 673: */
! 674: for (x = 16; x > 0; x--) {
! 675: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
! 676: reg | FXP_EEPROM_EESK);
! 677: DELAY(4);
! 678: if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) &
! 679: FXP_EEPROM_EEDO)
! 680: data[i] |= (1 << (x - 1));
! 681: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
! 682: DELAY(4);
! 683: }
! 684: data[i] = letoh16(data[i]);
! 685: CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
! 686: DELAY(4);
! 687: }
! 688: }
! 689:
! 690: /*
! 691: * Start packet transmission on the interface.
! 692: */
! 693: void
! 694: fxp_start(struct ifnet *ifp)
! 695: {
! 696: struct fxp_softc *sc = ifp->if_softc;
! 697: struct fxp_txsw *txs = sc->sc_cbt_prod;
! 698: struct fxp_cb_tx *txc;
! 699: struct mbuf *m0, *m = NULL;
! 700: int cnt = sc->sc_cbt_cnt, seg;
! 701:
! 702: if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING)
! 703: return;
! 704:
! 705: while (1) {
! 706: if (cnt >= (FXP_NTXCB - 2)) {
! 707: ifp->if_flags |= IFF_OACTIVE;
! 708: break;
! 709: }
! 710:
! 711: txs = txs->tx_next;
! 712:
! 713: IFQ_POLL(&ifp->if_snd, m0);
! 714: if (m0 == NULL)
! 715: break;
! 716:
! 717: if (bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map,
! 718: m0, BUS_DMA_NOWAIT) != 0) {
! 719: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 720: if (m == NULL)
! 721: break;
! 722: if (m0->m_pkthdr.len > MHLEN) {
! 723: MCLGET(m, M_DONTWAIT);
! 724: if (!(m->m_flags & M_EXT)) {
! 725: m_freem(m);
! 726: break;
! 727: }
! 728: }
! 729: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
! 730: m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
! 731: if (bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map,
! 732: m, BUS_DMA_NOWAIT) != 0) {
! 733: m_freem(m);
! 734: break;
! 735: }
! 736: }
! 737:
! 738: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 739: if (m != NULL) {
! 740: m_freem(m0);
! 741: m0 = m;
! 742: m = NULL;
! 743: }
! 744:
! 745: txs->tx_mbuf = m0;
! 746:
! 747: #if NBPFILTER > 0
! 748: if (ifp->if_bpf)
! 749: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
! 750: #endif
! 751:
! 752: FXP_MBUF_SYNC(sc, txs->tx_map, BUS_DMASYNC_PREWRITE);
! 753:
! 754: txc = txs->tx_cb;
! 755: txc->tbd_number = txs->tx_map->dm_nsegs;
! 756: txc->cb_status = 0;
! 757: txc->cb_command = htole16(FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF);
! 758: txc->tx_threshold = tx_threshold;
! 759: for (seg = 0; seg < txs->tx_map->dm_nsegs; seg++) {
! 760: txc->tbd[seg].tb_addr =
! 761: htole32(txs->tx_map->dm_segs[seg].ds_addr);
! 762: txc->tbd[seg].tb_size =
! 763: htole32(txs->tx_map->dm_segs[seg].ds_len);
! 764: }
! 765: FXP_TXCB_SYNC(sc, txs,
! 766: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 767:
! 768: ++cnt;
! 769: sc->sc_cbt_prod = txs;
! 770: }
! 771:
! 772: if (cnt != sc->sc_cbt_cnt) {
! 773: /* We enqueued at least one. */
! 774: ifp->if_timer = 5;
! 775:
! 776: txs = sc->sc_cbt_prod;
! 777: txs = txs->tx_next;
! 778: sc->sc_cbt_prod = txs;
! 779: txs->tx_cb->cb_command =
! 780: htole16(FXP_CB_COMMAND_I | FXP_CB_COMMAND_NOP | FXP_CB_COMMAND_S);
! 781: FXP_TXCB_SYNC(sc, txs,
! 782: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 783:
! 784: FXP_TXCB_SYNC(sc, sc->sc_cbt_prev,
! 785: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 786: sc->sc_cbt_prev->tx_cb->cb_command &=
! 787: htole16(~(FXP_CB_COMMAND_S | FXP_CB_COMMAND_I));
! 788: FXP_TXCB_SYNC(sc, sc->sc_cbt_prev,
! 789: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 790:
! 791: sc->sc_cbt_prev = txs;
! 792:
! 793: fxp_scb_wait(sc);
! 794: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME);
! 795:
! 796: sc->sc_cbt_cnt = cnt + 1;
! 797: }
! 798: }
! 799:
! 800: /*
! 801: * Process interface interrupts.
! 802: */
! 803: int
! 804: fxp_intr(void *arg)
! 805: {
! 806: struct fxp_softc *sc = arg;
! 807: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 808: u_int8_t statack;
! 809: bus_dmamap_t rxmap;
! 810: int claimed = 0;
! 811: int rnr = 0;
! 812:
! 813: /*
! 814: * If the interface isn't running, don't try to
! 815: * service the interrupt.. just ack it and bail.
! 816: */
! 817: if ((ifp->if_flags & IFF_RUNNING) == 0) {
! 818: statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK);
! 819: if (statack) {
! 820: claimed = 1;
! 821: CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);
! 822: }
! 823: return claimed;
! 824: }
! 825:
! 826: while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) {
! 827: claimed = 1;
! 828: rnr = (statack & (FXP_SCB_STATACK_RNR |
! 829: FXP_SCB_STATACK_SWI)) ? 1 : 0;
! 830: /*
! 831: * First ACK all the interrupts in this pass.
! 832: */
! 833: CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);
! 834:
! 835: /*
! 836: * Free any finished transmit mbuf chains.
! 837: */
! 838: if (statack & (FXP_SCB_STATACK_CXTNO|FXP_SCB_STATACK_CNA)) {
! 839: int txcnt = sc->sc_cbt_cnt;
! 840: struct fxp_txsw *txs = sc->sc_cbt_cons;
! 841:
! 842: FXP_TXCB_SYNC(sc, txs,
! 843: BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
! 844:
! 845: while ((txcnt > 0) &&
! 846: ((txs->tx_cb->cb_status & htole16(FXP_CB_STATUS_C)) ||
! 847: (txs->tx_cb->cb_command & htole16(FXP_CB_COMMAND_NOP)))) {
! 848: if (txs->tx_mbuf != NULL) {
! 849: FXP_MBUF_SYNC(sc, txs->tx_map,
! 850: BUS_DMASYNC_POSTWRITE);
! 851: bus_dmamap_unload(sc->sc_dmat,
! 852: txs->tx_map);
! 853: m_freem(txs->tx_mbuf);
! 854: txs->tx_mbuf = NULL;
! 855: }
! 856: --txcnt;
! 857: txs = txs->tx_next;
! 858: FXP_TXCB_SYNC(sc, txs,
! 859: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 860: }
! 861: sc->sc_cbt_cons = txs;
! 862: sc->sc_cbt_cnt = txcnt;
! 863: ifp->if_timer = 0;
! 864: ifp->if_flags &= ~IFF_OACTIVE;
! 865:
! 866: if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
! 867: /*
! 868: * Try to start more packets transmitting.
! 869: */
! 870: fxp_start(ifp);
! 871: }
! 872: }
! 873: /*
! 874: * Process receiver interrupts. If a Receive Unit
! 875: * not ready (RNR) condition exists, get whatever
! 876: * packets we can and re-start the receiver.
! 877: */
! 878: if (statack & (FXP_SCB_STATACK_FR | FXP_SCB_STATACK_RNR |
! 879: FXP_SCB_STATACK_SWI)) {
! 880: struct mbuf *m;
! 881: u_int8_t *rfap;
! 882: rcvloop:
! 883: m = sc->rfa_headm;
! 884: rfap = m->m_ext.ext_buf + RFA_ALIGNMENT_FUDGE;
! 885: rxmap = *((bus_dmamap_t *)m->m_ext.ext_buf);
! 886: bus_dmamap_sync(sc->sc_dmat, rxmap,
! 887: 0, MCLBYTES, BUS_DMASYNC_POSTREAD |
! 888: BUS_DMASYNC_POSTWRITE);
! 889:
! 890: if (*(u_int16_t *)(rfap +
! 891: offsetof(struct fxp_rfa, rfa_status)) &
! 892: htole16(FXP_RFA_STATUS_C)) {
! 893: if (*(u_int16_t *)(rfap +
! 894: offsetof(struct fxp_rfa, rfa_status)) &
! 895: htole16(FXP_RFA_STATUS_RNR))
! 896: rnr = 1;
! 897:
! 898: /*
! 899: * Remove first packet from the chain.
! 900: */
! 901: sc->rfa_headm = m->m_next;
! 902: m->m_next = NULL;
! 903:
! 904: /*
! 905: * Add a new buffer to the receive chain.
! 906: * If this fails, the old buffer is recycled
! 907: * instead.
! 908: */
! 909: if (fxp_add_rfabuf(sc, m) == 0) {
! 910: u_int16_t total_len;
! 911:
! 912: total_len = htole16(*(u_int16_t *)(rfap +
! 913: offsetof(struct fxp_rfa,
! 914: actual_size))) &
! 915: (MCLBYTES - 1);
! 916: if (total_len <
! 917: sizeof(struct ether_header)) {
! 918: m_freem(m);
! 919: goto rcvloop;
! 920: }
! 921: if (*(u_int16_t *)(rfap +
! 922: offsetof(struct fxp_rfa,
! 923: rfa_status)) &
! 924: htole16(FXP_RFA_STATUS_CRC)) {
! 925: m_freem(m);
! 926: goto rcvloop;
! 927: }
! 928:
! 929: m->m_pkthdr.rcvif = ifp;
! 930: m->m_pkthdr.len = m->m_len =
! 931: total_len;
! 932: #if NBPFILTER > 0
! 933: if (ifp->if_bpf)
! 934: bpf_mtap(ifp->if_bpf, m,
! 935: BPF_DIRECTION_IN);
! 936: #endif /* NBPFILTER > 0 */
! 937: ether_input_mbuf(ifp, m);
! 938: }
! 939: goto rcvloop;
! 940: }
! 941: }
! 942: if (rnr) {
! 943: rxmap = *((bus_dmamap_t *)
! 944: sc->rfa_headm->m_ext.ext_buf);
! 945: fxp_scb_wait(sc);
! 946: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL,
! 947: rxmap->dm_segs[0].ds_addr +
! 948: RFA_ALIGNMENT_FUDGE);
! 949: fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START);
! 950:
! 951: }
! 952: }
! 953: return (claimed);
! 954: }
! 955:
! 956: /*
! 957: * Update packet in/out/collision statistics. The i82557 doesn't
! 958: * allow you to access these counters without doing a fairly
! 959: * expensive DMA to get _all_ of the statistics it maintains, so
! 960: * we do this operation here only once per second. The statistics
! 961: * counters in the kernel are updated from the previous dump-stats
! 962: * DMA and then a new dump-stats DMA is started. The on-chip
! 963: * counters are zeroed when the DMA completes. If we can't start
! 964: * the DMA immediately, we don't wait - we just prepare to read
! 965: * them again next time.
! 966: */
! 967: void
! 968: fxp_stats_update(void *arg)
! 969: {
! 970: struct fxp_softc *sc = arg;
! 971: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 972: struct fxp_stats *sp = &sc->sc_ctrl->stats;
! 973: int s;
! 974:
! 975: FXP_STATS_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 976: ifp->if_opackets += letoh32(sp->tx_good);
! 977: ifp->if_collisions += letoh32(sp->tx_total_collisions);
! 978: if (sp->rx_good) {
! 979: ifp->if_ipackets += letoh32(sp->rx_good);
! 980: sc->rx_idle_secs = 0;
! 981: } else if (sc->sc_flags & FXPF_RECV_WORKAROUND)
! 982: sc->rx_idle_secs++;
! 983: ifp->if_ierrors +=
! 984: letoh32(sp->rx_crc_errors) +
! 985: letoh32(sp->rx_alignment_errors) +
! 986: letoh32(sp->rx_rnr_errors) +
! 987: letoh32(sp->rx_overrun_errors);
! 988: /*
! 989: * If any transmit underruns occurred, bump up the transmit
! 990: * threshold by another 512 bytes (64 * 8).
! 991: */
! 992: if (sp->tx_underruns) {
! 993: ifp->if_oerrors += letoh32(sp->tx_underruns);
! 994: if (tx_threshold < 192)
! 995: tx_threshold += 64;
! 996: }
! 997: s = splnet();
! 998: /*
! 999: * If we haven't received any packets in FXP_MAX_RX_IDLE seconds,
! 1000: * then assume the receiver has locked up and attempt to clear
! 1001: * the condition by reprogramming the multicast filter. This is
! 1002: * a work-around for a bug in the 82557 where the receiver locks
! 1003: * up if it gets certain types of garbage in the synchronization
! 1004: * bits prior to the packet header. This bug is supposed to only
! 1005: * occur in 10Mbps mode, but has been seen to occur in 100Mbps
! 1006: * mode as well (perhaps due to a 10/100 speed transition).
! 1007: */
! 1008: if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) {
! 1009: sc->rx_idle_secs = 0;
! 1010: fxp_init(sc);
! 1011: splx(s);
! 1012: return;
! 1013: }
! 1014: /*
! 1015: * If there is no pending command, start another stats
! 1016: * dump. Otherwise punt for now.
! 1017: */
! 1018: FXP_STATS_SYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1019: if (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) == 0) {
! 1020: /*
! 1021: * Start another stats dump.
! 1022: */
! 1023: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMPRESET);
! 1024: } else {
! 1025: /*
! 1026: * A previous command is still waiting to be accepted.
! 1027: * Just zero our copy of the stats and wait for the
! 1028: * next timer event to update them.
! 1029: */
! 1030: sp->tx_good = 0;
! 1031: sp->tx_underruns = 0;
! 1032: sp->tx_total_collisions = 0;
! 1033:
! 1034: sp->rx_good = 0;
! 1035: sp->rx_crc_errors = 0;
! 1036: sp->rx_alignment_errors = 0;
! 1037: sp->rx_rnr_errors = 0;
! 1038: sp->rx_overrun_errors = 0;
! 1039: }
! 1040:
! 1041: /* Tick the MII clock. */
! 1042: mii_tick(&sc->sc_mii);
! 1043:
! 1044: splx(s);
! 1045: /*
! 1046: * Schedule another timeout one second from now.
! 1047: */
! 1048: timeout_add(&sc->stats_update_to, hz);
! 1049: }
! 1050:
! 1051: /*
! 1052: * Stop the interface. Cancels the statistics updater and resets
! 1053: * the interface.
! 1054: */
! 1055: void
! 1056: fxp_stop(struct fxp_softc *sc, int drain)
! 1057: {
! 1058: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1059: int i;
! 1060:
! 1061: /*
! 1062: * Turn down interface (done early to avoid bad interactions
! 1063: * between panics, shutdown hooks, and the watchdog timer)
! 1064: */
! 1065: ifp->if_timer = 0;
! 1066: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 1067:
! 1068: /*
! 1069: * Cancel stats updater.
! 1070: */
! 1071: timeout_del(&sc->stats_update_to);
! 1072: mii_down(&sc->sc_mii);
! 1073:
! 1074: /*
! 1075: * Issue software reset.
! 1076: */
! 1077: CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
! 1078: DELAY(10);
! 1079:
! 1080: /*
! 1081: * Release any xmit buffers.
! 1082: */
! 1083: for (i = 0; i < FXP_NTXCB; i++) {
! 1084: if (sc->txs[i].tx_mbuf != NULL) {
! 1085: bus_dmamap_unload(sc->sc_dmat, sc->txs[i].tx_map);
! 1086: m_freem(sc->txs[i].tx_mbuf);
! 1087: sc->txs[i].tx_mbuf = NULL;
! 1088: }
! 1089: }
! 1090: sc->sc_cbt_cnt = 0;
! 1091:
! 1092: if (drain) {
! 1093: bus_dmamap_t rxmap;
! 1094: struct mbuf *m;
! 1095:
! 1096: /*
! 1097: * Free all the receive buffers then reallocate/reinitialize
! 1098: */
! 1099: m = sc->rfa_headm;
! 1100: while (m != NULL) {
! 1101: rxmap = *((bus_dmamap_t *)m->m_ext.ext_buf);
! 1102: bus_dmamap_unload(sc->sc_dmat, rxmap);
! 1103: FXP_RXMAP_PUT(sc, rxmap);
! 1104: m = m_free(m);
! 1105: sc->rx_bufs--;
! 1106: }
! 1107: sc->rfa_headm = NULL;
! 1108: sc->rfa_tailm = NULL;
! 1109: for (i = 0; i < FXP_NRFABUFS_MIN; i++) {
! 1110: if (fxp_add_rfabuf(sc, NULL) != 0) {
! 1111: /*
! 1112: * This "can't happen" - we're at splnet()
! 1113: * and we just freed all the buffers we need
! 1114: * above.
! 1115: */
! 1116: panic("fxp_stop: no buffers!");
! 1117: }
! 1118: sc->rx_bufs++;
! 1119: }
! 1120: }
! 1121: }
! 1122:
! 1123: /*
! 1124: * Watchdog/transmission transmit timeout handler. Called when a
! 1125: * transmission is started on the interface, but no interrupt is
! 1126: * received before the timeout. This usually indicates that the
! 1127: * card has wedged for some reason.
! 1128: */
! 1129: void
! 1130: fxp_watchdog(struct ifnet *ifp)
! 1131: {
! 1132: struct fxp_softc *sc = ifp->if_softc;
! 1133:
! 1134: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
! 1135: ifp->if_oerrors++;
! 1136:
! 1137: fxp_init(sc);
! 1138: }
! 1139:
! 1140: /*
! 1141: * Submit a command to the i82557.
! 1142: */
! 1143: void
! 1144: fxp_scb_cmd(struct fxp_softc *sc, u_int8_t cmd)
! 1145: {
! 1146: CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, cmd);
! 1147: }
! 1148:
! 1149: void
! 1150: fxp_init(void *xsc)
! 1151: {
! 1152: struct fxp_softc *sc = xsc;
! 1153: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1154: struct fxp_cb_config *cbp;
! 1155: struct fxp_cb_ias *cb_ias;
! 1156: struct fxp_cb_tx *txp;
! 1157: bus_dmamap_t rxmap;
! 1158: int i, prm, save_bf, lrxen, allm, s, bufs;
! 1159:
! 1160: s = splnet();
! 1161:
! 1162: /*
! 1163: * Cancel any pending I/O
! 1164: */
! 1165: fxp_stop(sc, 0);
! 1166:
! 1167: /*
! 1168: * Initialize base of CBL and RFA memory. Loading with zero
! 1169: * sets it up for regular linear addressing.
! 1170: */
! 1171: fxp_scb_wait(sc);
! 1172: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0);
! 1173: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_BASE);
! 1174:
! 1175: fxp_scb_wait(sc);
! 1176: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0);
! 1177: fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_BASE);
! 1178:
! 1179: #ifndef SMALL_KERNEL
! 1180: fxp_load_ucode(sc);
! 1181: #endif
! 1182: /* Once through to set flags */
! 1183: fxp_mc_setup(sc, 0);
! 1184:
! 1185: /*
! 1186: * In order to support receiving 802.1Q VLAN frames, we have to
! 1187: * enable "save bad frames", since they are 4 bytes larger than
! 1188: * the normal Ethernet maximum frame length. On i82558 and later,
! 1189: * we have a better mechanism for this.
! 1190: */
! 1191: save_bf = 0;
! 1192: lrxen = 0;
! 1193:
! 1194: if (sc->sc_revision >= FXP_REV_82558_A4)
! 1195: lrxen = 1;
! 1196: else
! 1197: save_bf = 1;
! 1198:
! 1199: /*
! 1200: * Initialize base of dump-stats buffer.
! 1201: */
! 1202: fxp_scb_wait(sc);
! 1203: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL,
! 1204: sc->tx_cb_map->dm_segs->ds_addr +
! 1205: offsetof(struct fxp_ctrl, stats));
! 1206: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMP_ADR);
! 1207:
! 1208: cbp = &sc->sc_ctrl->u.cfg;
! 1209: /*
! 1210: * This bcopy is kind of disgusting, but there are a bunch of must be
! 1211: * zero and must be one bits in this structure and this is the easiest
! 1212: * way to initialize them all to proper values.
! 1213: */
! 1214: bcopy(fxp_cb_config_template, (void *)&cbp->cb_status,
! 1215: sizeof(fxp_cb_config_template));
! 1216:
! 1217: prm = (ifp->if_flags & IFF_PROMISC) ? 1 : 0;
! 1218: allm = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
! 1219:
! 1220: #if 0
! 1221: cbp->cb_status = 0;
! 1222: cbp->cb_command = FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL;
! 1223: cbp->link_addr = 0xffffffff; /* (no) next command */
! 1224: cbp->byte_count = 22; /* (22) bytes to config */
! 1225: cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */
! 1226: cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */
! 1227: cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */
! 1228: cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */
! 1229: cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */
! 1230: cbp->dma_bce = 0; /* (disable) dma max counters */
! 1231: cbp->late_scb = 0; /* (don't) defer SCB update */
! 1232: cbp->tno_int = 0; /* (disable) tx not okay interrupt */
! 1233: cbp->ci_int = 1; /* interrupt on CU idle */
! 1234: cbp->save_bf = save_bf ? 1 : prm; /* save bad frames */
! 1235: cbp->disc_short_rx = !prm; /* discard short packets */
! 1236: cbp->underrun_retry = 1; /* retry mode (1) on DMA underrun */
! 1237: cbp->mediatype = !sc->phy_10Mbps_only; /* interface mode */
! 1238: cbp->nsai = 1; /* (don't) disable source addr insert */
! 1239: cbp->preamble_length = 2; /* (7 byte) preamble */
! 1240: cbp->loopback = 0; /* (don't) loopback */
! 1241: cbp->linear_priority = 0; /* (normal CSMA/CD operation) */
! 1242: cbp->linear_pri_mode = 0; /* (wait after xmit only) */
! 1243: cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */
! 1244: cbp->promiscuous = prm; /* promiscuous mode */
! 1245: cbp->bcast_disable = 0; /* (don't) disable broadcasts */
! 1246: cbp->crscdt = 0; /* (CRS only) */
! 1247: cbp->stripping = !prm; /* truncate rx packet to byte count */
! 1248: cbp->padding = 1; /* (do) pad short tx packets */
! 1249: cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */
! 1250: cbp->long_rx = lrxen; /* (enable) long packets */
! 1251: cbp->force_fdx = 0; /* (don't) force full duplex */
! 1252: cbp->fdx_pin_en = 1; /* (enable) FDX# pin */
! 1253: cbp->multi_ia = 0; /* (don't) accept multiple IAs */
! 1254: cbp->mc_all = allm;
! 1255: #else
! 1256: cbp->cb_command = htole16(FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL);
! 1257: if (allm)
! 1258: cbp->mc_all |= 0x08; /* accept all multicasts */
! 1259: else
! 1260: cbp->mc_all &= ~0x08; /* reject all multicasts */
! 1261:
! 1262: if (prm) {
! 1263: cbp->promiscuous |= 1; /* promiscuous mode */
! 1264: cbp->ctrl2 &= ~0x01; /* save short packets */
! 1265: cbp->stripping &= ~0x01; /* don't truncate rx packets */
! 1266: } else {
! 1267: cbp->promiscuous &= ~1; /* no promiscuous mode */
! 1268: cbp->ctrl2 |= 0x01; /* discard short packets */
! 1269: cbp->stripping |= 0x01; /* truncate rx packets */
! 1270: }
! 1271:
! 1272: if (prm || save_bf)
! 1273: cbp->ctrl1 |= 0x80; /* save bad frames */
! 1274: else
! 1275: cbp->ctrl1 &= ~0x80; /* discard bad frames */
! 1276:
! 1277: if (sc->sc_flags & FXPF_MWI_ENABLE)
! 1278: cbp->ctrl0 |= 0x01; /* enable PCI MWI command */
! 1279:
! 1280: if(!sc->phy_10Mbps_only) /* interface mode */
! 1281: cbp->mediatype |= 0x01;
! 1282: else
! 1283: cbp->mediatype &= ~0x01;
! 1284:
! 1285: if(lrxen) /* long packets */
! 1286: cbp->stripping |= 0x08;
! 1287: else
! 1288: cbp->stripping &= ~0x08;
! 1289:
! 1290: cbp->tx_dma_bytecount = 0; /* (no) tx DMA max, dma_dce = 0 ??? */
! 1291: cbp->ctrl1 |= 0x08; /* ci_int = 1 */
! 1292: cbp->ctrl3 |= 0x08; /* nsai */
! 1293: cbp->fifo_limit = 0x08; /* tx and rx fifo limit */
! 1294: cbp->fdx_pin |= 0x80; /* Enable full duplex setting by pin */
! 1295: #endif
! 1296:
! 1297: /*
! 1298: * Start the config command/DMA.
! 1299: */
! 1300: fxp_scb_wait(sc);
! 1301: FXP_CFG_SYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1302: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->tx_cb_map->dm_segs->ds_addr +
! 1303: offsetof(struct fxp_ctrl, u.cfg));
! 1304: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
! 1305: /* ...and wait for it to complete. */
! 1306: do {
! 1307: DELAY(1);
! 1308: FXP_CFG_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1309: } while ((cbp->cb_status & htole16(FXP_CB_STATUS_C)) == 0);
! 1310:
! 1311: /*
! 1312: * Now initialize the station address.
! 1313: */
! 1314: cb_ias = &sc->sc_ctrl->u.ias;
! 1315: cb_ias->cb_status = htole16(0);
! 1316: cb_ias->cb_command = htole16(FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL);
! 1317: cb_ias->link_addr = htole32(0xffffffff);
! 1318: bcopy(sc->sc_arpcom.ac_enaddr, (void *)cb_ias->macaddr,
! 1319: sizeof(sc->sc_arpcom.ac_enaddr));
! 1320:
! 1321: /*
! 1322: * Start the IAS (Individual Address Setup) command/DMA.
! 1323: */
! 1324: fxp_scb_wait(sc);
! 1325: FXP_IAS_SYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1326: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->tx_cb_map->dm_segs->ds_addr +
! 1327: offsetof(struct fxp_ctrl, u.ias));
! 1328: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
! 1329: /* ...and wait for it to complete. */
! 1330: do {
! 1331: DELAY(1);
! 1332: FXP_IAS_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1333: } while (!(cb_ias->cb_status & htole16(FXP_CB_STATUS_C)));
! 1334:
! 1335: /* Again, this time really upload the multicast addresses */
! 1336: fxp_mc_setup(sc, 1);
! 1337:
! 1338: /*
! 1339: * Initialize transmit control block (TxCB) list.
! 1340: */
! 1341: bzero(sc->sc_ctrl->tx_cb, sizeof(struct fxp_cb_tx) * FXP_NTXCB);
! 1342: txp = sc->sc_ctrl->tx_cb;
! 1343: for (i = 0; i < FXP_NTXCB; i++) {
! 1344: txp[i].cb_command = htole16(FXP_CB_COMMAND_NOP);
! 1345: txp[i].link_addr = htole32(sc->tx_cb_map->dm_segs->ds_addr +
! 1346: offsetof(struct fxp_ctrl, tx_cb[(i + 1) & FXP_TXCB_MASK]));
! 1347: txp[i].tbd_array_addr =htole32(sc->tx_cb_map->dm_segs->ds_addr +
! 1348: offsetof(struct fxp_ctrl, tx_cb[i].tbd[0]));
! 1349: }
! 1350: /*
! 1351: * Set the suspend flag on the first TxCB and start the control
! 1352: * unit. It will execute the NOP and then suspend.
! 1353: */
! 1354: sc->sc_cbt_prev = sc->sc_cbt_prod = sc->sc_cbt_cons = sc->txs;
! 1355: sc->sc_cbt_cnt = 1;
! 1356: sc->sc_ctrl->tx_cb[0].cb_command = htole16(FXP_CB_COMMAND_NOP |
! 1357: FXP_CB_COMMAND_S | FXP_CB_COMMAND_I);
! 1358: bus_dmamap_sync(sc->sc_dmat, sc->tx_cb_map, 0,
! 1359: sc->tx_cb_map->dm_mapsize,
! 1360: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1361:
! 1362: fxp_scb_wait(sc);
! 1363: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->tx_cb_map->dm_segs->ds_addr +
! 1364: offsetof(struct fxp_ctrl, tx_cb[0]));
! 1365: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
! 1366:
! 1367: /*
! 1368: * Initialize receiver buffer area - RFA.
! 1369: */
! 1370: if (ifp->if_flags & IFF_UP)
! 1371: bufs = FXP_NRFABUFS_MAX;
! 1372: else
! 1373: bufs = FXP_NRFABUFS_MIN;
! 1374: if (sc->rx_bufs > bufs) {
! 1375: while (sc->rfa_headm != NULL && sc->rx_bufs-- > bufs) {
! 1376: rxmap = *((bus_dmamap_t *)sc->rfa_headm->m_ext.ext_buf);
! 1377: bus_dmamap_unload(sc->sc_dmat, rxmap);
! 1378: FXP_RXMAP_PUT(sc, rxmap);
! 1379: sc->rfa_headm = m_free(sc->rfa_headm);
! 1380: }
! 1381: } else if (sc->rx_bufs < bufs) {
! 1382: int err, tmp_rx_bufs = sc->rx_bufs;
! 1383: for (i = sc->rx_bufs; i < bufs; i++) {
! 1384: if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
! 1385: MCLBYTES, 0, 0, &sc->sc_rxmaps[i])) != 0) {
! 1386: printf("%s: unable to create rx dma map %d, "
! 1387: "error %d\n", sc->sc_dev.dv_xname, i, err);
! 1388: break;
! 1389: }
! 1390: sc->rx_bufs++;
! 1391: }
! 1392: for (i = tmp_rx_bufs; i < sc->rx_bufs; i++)
! 1393: if (fxp_add_rfabuf(sc, NULL) != 0)
! 1394: break;
! 1395: }
! 1396: fxp_scb_wait(sc);
! 1397:
! 1398: /*
! 1399: * Set current media.
! 1400: */
! 1401: mii_mediachg(&sc->sc_mii);
! 1402:
! 1403: ifp->if_flags |= IFF_RUNNING;
! 1404: ifp->if_flags &= ~IFF_OACTIVE;
! 1405:
! 1406: /*
! 1407: * Request a software generated interrupt that will be used to
! 1408: * (re)start the RU processing. If we direct the chip to start
! 1409: * receiving from the start of queue now, instead of letting the
! 1410: * interrupt handler first process all received packets, we run
! 1411: * the risk of having it overwrite mbuf clusters while they are
! 1412: * being processed or after they have been returned to the pool.
! 1413: */
! 1414: CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTRCNTL_REQUEST_SWI);
! 1415: splx(s);
! 1416:
! 1417: /*
! 1418: * Start stats updater.
! 1419: */
! 1420: timeout_add(&sc->stats_update_to, hz);
! 1421: }
! 1422:
! 1423: /*
! 1424: * Change media according to request.
! 1425: */
! 1426: int
! 1427: fxp_mediachange(struct ifnet *ifp)
! 1428: {
! 1429: struct fxp_softc *sc = ifp->if_softc;
! 1430: struct mii_data *mii = &sc->sc_mii;
! 1431:
! 1432: if (mii->mii_instance) {
! 1433: struct mii_softc *miisc;
! 1434: LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
! 1435: mii_phy_reset(miisc);
! 1436: }
! 1437: mii_mediachg(&sc->sc_mii);
! 1438: return (0);
! 1439: }
! 1440:
! 1441: /*
! 1442: * Notify the world which media we're using.
! 1443: */
! 1444: void
! 1445: fxp_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
! 1446: {
! 1447: struct fxp_softc *sc = ifp->if_softc;
! 1448:
! 1449: mii_pollstat(&sc->sc_mii);
! 1450: ifmr->ifm_status = sc->sc_mii.mii_media_status;
! 1451: ifmr->ifm_active = sc->sc_mii.mii_media_active;
! 1452: }
! 1453:
! 1454: /*
! 1455: * Add a buffer to the end of the RFA buffer list.
! 1456: * Return 0 if successful, 1 for failure. A failure results in
! 1457: * adding the 'oldm' (if non-NULL) on to the end of the list -
! 1458: * tossing out its old contents and recycling it.
! 1459: * The RFA struct is stuck at the beginning of mbuf cluster and the
! 1460: * data pointer is fixed up to point just past it.
! 1461: */
! 1462: int
! 1463: fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm)
! 1464: {
! 1465: u_int32_t v;
! 1466: struct mbuf *m;
! 1467: u_int8_t *rfap;
! 1468: bus_dmamap_t rxmap = NULL;
! 1469:
! 1470: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 1471: if (m != NULL) {
! 1472: MCLGET(m, M_DONTWAIT);
! 1473: if ((m->m_flags & M_EXT) == 0) {
! 1474: m_freem(m);
! 1475: if (oldm == NULL)
! 1476: return 1;
! 1477: m = oldm;
! 1478: m->m_data = m->m_ext.ext_buf;
! 1479: }
! 1480: if (oldm == NULL) {
! 1481: rxmap = FXP_RXMAP_GET(sc);
! 1482: *((bus_dmamap_t *)m->m_ext.ext_buf) = rxmap;
! 1483: bus_dmamap_load(sc->sc_dmat, rxmap,
! 1484: m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
! 1485: BUS_DMA_NOWAIT);
! 1486: } else if (oldm == m)
! 1487: rxmap = *((bus_dmamap_t *)oldm->m_ext.ext_buf);
! 1488: else {
! 1489: rxmap = *((bus_dmamap_t *)oldm->m_ext.ext_buf);
! 1490: bus_dmamap_unload(sc->sc_dmat, rxmap);
! 1491: bus_dmamap_load(sc->sc_dmat, rxmap,
! 1492: m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
! 1493: BUS_DMA_NOWAIT);
! 1494: *mtod(m, bus_dmamap_t *) = rxmap;
! 1495: }
! 1496: } else {
! 1497: if (oldm == NULL)
! 1498: return 1;
! 1499: m = oldm;
! 1500: m->m_data = m->m_ext.ext_buf;
! 1501: rxmap = *mtod(m, bus_dmamap_t *);
! 1502: }
! 1503:
! 1504: /*
! 1505: * Move the data pointer up so that the incoming data packet
! 1506: * will be 32-bit aligned.
! 1507: */
! 1508: m->m_data += RFA_ALIGNMENT_FUDGE;
! 1509:
! 1510: /*
! 1511: * Get a pointer to the base of the mbuf cluster and move
! 1512: * data start past it.
! 1513: */
! 1514: rfap = m->m_data;
! 1515: m->m_data += sizeof(struct fxp_rfa);
! 1516: *(u_int16_t *)(rfap + offsetof(struct fxp_rfa, size)) =
! 1517: htole16(MCLBYTES - sizeof(struct fxp_rfa) - RFA_ALIGNMENT_FUDGE);
! 1518:
! 1519: /*
! 1520: * Initialize the rest of the RFA. Note that since the RFA
! 1521: * is misaligned, we cannot store values directly. Instead,
! 1522: * we use an optimized, inline copy.
! 1523: */
! 1524: *(u_int16_t *)(rfap + offsetof(struct fxp_rfa, rfa_status)) = 0;
! 1525: *(u_int16_t *)(rfap + offsetof(struct fxp_rfa, rfa_control)) =
! 1526: htole16(FXP_RFA_CONTROL_EL);
! 1527: *(u_int16_t *)(rfap + offsetof(struct fxp_rfa, actual_size)) = 0;
! 1528:
! 1529: v = -1;
! 1530: fxp_lwcopy(&v,
! 1531: (u_int32_t *)(rfap + offsetof(struct fxp_rfa, link_addr)));
! 1532: fxp_lwcopy(&v,
! 1533: (u_int32_t *)(rfap + offsetof(struct fxp_rfa, rbd_addr)));
! 1534:
! 1535: bus_dmamap_sync(sc->sc_dmat, rxmap, 0, MCLBYTES,
! 1536: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1537:
! 1538: /*
! 1539: * If there are other buffers already on the list, attach this
! 1540: * one to the end by fixing up the tail to point to this one.
! 1541: */
! 1542: if (sc->rfa_headm != NULL) {
! 1543: sc->rfa_tailm->m_next = m;
! 1544: v = htole32(rxmap->dm_segs[0].ds_addr + RFA_ALIGNMENT_FUDGE);
! 1545: rfap = sc->rfa_tailm->m_ext.ext_buf + RFA_ALIGNMENT_FUDGE;
! 1546: fxp_lwcopy(&v,
! 1547: (u_int32_t *)(rfap + offsetof(struct fxp_rfa, link_addr)));
! 1548: *(u_int16_t *)(rfap + offsetof(struct fxp_rfa, rfa_control)) &=
! 1549: htole16((u_int16_t)~FXP_RFA_CONTROL_EL);
! 1550: /* XXX we only need to sync the control struct */
! 1551: bus_dmamap_sync(sc->sc_dmat,
! 1552: *((bus_dmamap_t *)sc->rfa_tailm->m_ext.ext_buf), 0,
! 1553: MCLBYTES, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1554: } else
! 1555: sc->rfa_headm = m;
! 1556:
! 1557: sc->rfa_tailm = m;
! 1558:
! 1559: return (m == oldm);
! 1560: }
! 1561:
! 1562: int
! 1563: fxp_mdi_read(struct device *self, int phy, int reg)
! 1564: {
! 1565: struct fxp_softc *sc = (struct fxp_softc *)self;
! 1566: int count = 10000;
! 1567: int value;
! 1568:
! 1569: CSR_WRITE_4(sc, FXP_CSR_MDICONTROL,
! 1570: (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21));
! 1571:
! 1572: while (((value = CSR_READ_4(sc, FXP_CSR_MDICONTROL)) & 0x10000000) == 0
! 1573: && count--)
! 1574: DELAY(10);
! 1575:
! 1576: if (count <= 0)
! 1577: printf("%s: fxp_mdi_read: timed out\n", sc->sc_dev.dv_xname);
! 1578:
! 1579: return (value & 0xffff);
! 1580: }
! 1581:
! 1582: void
! 1583: fxp_statchg(struct device *self)
! 1584: {
! 1585: /* Nothing to do. */
! 1586: }
! 1587:
! 1588: void
! 1589: fxp_mdi_write(struct device *self, int phy, int reg, int value)
! 1590: {
! 1591: struct fxp_softc *sc = (struct fxp_softc *)self;
! 1592: int count = 10000;
! 1593:
! 1594: CSR_WRITE_4(sc, FXP_CSR_MDICONTROL,
! 1595: (FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21) |
! 1596: (value & 0xffff));
! 1597:
! 1598: while((CSR_READ_4(sc, FXP_CSR_MDICONTROL) & 0x10000000) == 0 &&
! 1599: count--)
! 1600: DELAY(10);
! 1601:
! 1602: if (count <= 0)
! 1603: printf("%s: fxp_mdi_write: timed out\n", sc->sc_dev.dv_xname);
! 1604: }
! 1605:
! 1606: int
! 1607: fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
! 1608: {
! 1609: struct fxp_softc *sc = ifp->if_softc;
! 1610: struct ifreq *ifr = (struct ifreq *)data;
! 1611: struct ifaddr *ifa = (struct ifaddr *)data;
! 1612: int s, error = 0;
! 1613:
! 1614: s = splnet();
! 1615:
! 1616: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
! 1617: splx(s);
! 1618: return (error);
! 1619: }
! 1620:
! 1621: switch (command) {
! 1622: case SIOCSIFADDR:
! 1623: ifp->if_flags |= IFF_UP;
! 1624: if (!(ifp->if_flags & IFF_RUNNING))
! 1625: fxp_init(sc);
! 1626: #ifdef INET
! 1627: if (ifa->ifa_addr->sa_family == AF_INET)
! 1628: arp_ifinit(&sc->sc_arpcom, ifa);
! 1629: #endif
! 1630: break;
! 1631:
! 1632: case SIOCSIFMTU:
! 1633: if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN)
! 1634: error = EINVAL;
! 1635: else if (ifp->if_mtu != ifr->ifr_mtu)
! 1636: ifp->if_mtu = ifr->ifr_mtu;
! 1637: break;
! 1638:
! 1639: case SIOCSIFFLAGS:
! 1640: /*
! 1641: * If interface is marked up and not running, then start it.
! 1642: * If it is marked down and running, stop it.
! 1643: * XXX If it's up then re-initialize it. This is so flags
! 1644: * such as IFF_PROMISC are handled.
! 1645: */
! 1646: if (ifp->if_flags & IFF_UP)
! 1647: fxp_init(sc);
! 1648: else if (ifp->if_flags & IFF_RUNNING)
! 1649: fxp_stop(sc, 1);
! 1650: break;
! 1651:
! 1652: case SIOCADDMULTI:
! 1653: case SIOCDELMULTI:
! 1654: error = (command == SIOCADDMULTI) ?
! 1655: ether_addmulti(ifr, &sc->sc_arpcom) :
! 1656: ether_delmulti(ifr, &sc->sc_arpcom);
! 1657: if (error == ENETRESET) {
! 1658: /*
! 1659: * Multicast list has changed; set the hardware
! 1660: * filter accordingly.
! 1661: */
! 1662: if (ifp->if_flags & IFF_RUNNING)
! 1663: fxp_init(sc);
! 1664: error = 0;
! 1665: }
! 1666: break;
! 1667:
! 1668: case SIOCSIFMEDIA:
! 1669: case SIOCGIFMEDIA:
! 1670: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
! 1671: break;
! 1672:
! 1673: default:
! 1674: error = EINVAL;
! 1675: }
! 1676: splx(s);
! 1677: return (error);
! 1678: }
! 1679:
! 1680: /*
! 1681: * Program the multicast filter.
! 1682: *
! 1683: * We have an artificial restriction that the multicast setup command
! 1684: * must be the first command in the chain, so we take steps to ensure
! 1685: * this. By requiring this, it allows us to keep up the performance of
! 1686: * the pre-initialized command ring (esp. link pointers) by not actually
! 1687: * inserting the mcsetup command in the ring - i.e. its link pointer
! 1688: * points to the TxCB ring, but the mcsetup descriptor itself is not part
! 1689: * of it. We then can do 'CU_START' on the mcsetup descriptor and have it
! 1690: * lead into the regular TxCB ring when it completes.
! 1691: *
! 1692: * This function must be called at splnet.
! 1693: */
! 1694: void
! 1695: fxp_mc_setup(struct fxp_softc *sc, int doit)
! 1696: {
! 1697: struct fxp_cb_mcs *mcsp = &sc->sc_ctrl->u.mcs;
! 1698: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1699: struct ether_multistep step;
! 1700: struct ether_multi *enm;
! 1701: int nmcasts;
! 1702:
! 1703: /*
! 1704: * Initialize multicast setup descriptor.
! 1705: */
! 1706: mcsp->cb_status = htole16(0);
! 1707: mcsp->cb_command = htole16(FXP_CB_COMMAND_MCAS | FXP_CB_COMMAND_EL);
! 1708: mcsp->link_addr = htole32(-1);
! 1709:
! 1710: nmcasts = 0;
! 1711: if (!(ifp->if_flags & IFF_ALLMULTI)) {
! 1712: ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
! 1713: while (enm != NULL) {
! 1714: if (nmcasts >= MAXMCADDR) {
! 1715: ifp->if_flags |= IFF_ALLMULTI;
! 1716: nmcasts = 0;
! 1717: break;
! 1718: }
! 1719:
! 1720: /* Punt on ranges. */
! 1721: if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
! 1722: sizeof(enm->enm_addrlo)) != 0) {
! 1723: ifp->if_flags |= IFF_ALLMULTI;
! 1724: nmcasts = 0;
! 1725: break;
! 1726: }
! 1727: bcopy(enm->enm_addrlo,
! 1728: (void *)&mcsp->mc_addr[nmcasts][0], ETHER_ADDR_LEN);
! 1729: nmcasts++;
! 1730: ETHER_NEXT_MULTI(step, enm);
! 1731: }
! 1732: }
! 1733: if (doit == 0)
! 1734: return;
! 1735: mcsp->mc_cnt = htole16(nmcasts * ETHER_ADDR_LEN);
! 1736:
! 1737: /*
! 1738: * Wait until command unit is not active. This should never
! 1739: * be the case when nothing is queued, but make sure anyway.
! 1740: */
! 1741: while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) != FXP_SCB_CUS_IDLE);
! 1742:
! 1743: /*
! 1744: * Start the multicast setup command.
! 1745: */
! 1746: fxp_scb_wait(sc);
! 1747: FXP_MCS_SYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1748: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->tx_cb_map->dm_segs->ds_addr +
! 1749: offsetof(struct fxp_ctrl, u.mcs));
! 1750: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
! 1751:
! 1752: do {
! 1753: DELAY(1);
! 1754: FXP_MCS_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1755: } while (!(mcsp->cb_status & htole16(FXP_CB_STATUS_C)));
! 1756: }
! 1757:
! 1758: #ifndef SMALL_KERNEL
! 1759: #include <dev/microcode/fxp/rcvbundl.h>
! 1760: struct ucode {
! 1761: u_int16_t revision;
! 1762: u_int16_t int_delay_offset;
! 1763: u_int16_t bundle_max_offset;
! 1764: u_int16_t min_size_mask_offset;
! 1765: const char *uname;
! 1766: } const ucode_table[] = {
! 1767: { FXP_REV_82558_A4, D101_CPUSAVER_DWORD,
! 1768: 0, 0,
! 1769: "fxp-d101a" },
! 1770:
! 1771: { FXP_REV_82558_B0, D101_CPUSAVER_DWORD,
! 1772: 0, 0,
! 1773: "fxp-d101b0" },
! 1774:
! 1775: { FXP_REV_82559_A0, D101M_CPUSAVER_DWORD,
! 1776: D101M_CPUSAVER_BUNDLE_MAX_DWORD, D101M_CPUSAVER_MIN_SIZE_DWORD,
! 1777: "fxp-d101ma" },
! 1778:
! 1779: { FXP_REV_82559S_A, D101S_CPUSAVER_DWORD,
! 1780: D101S_CPUSAVER_BUNDLE_MAX_DWORD, D101S_CPUSAVER_MIN_SIZE_DWORD,
! 1781: "fxp-d101s" },
! 1782:
! 1783: { FXP_REV_82550, D102_B_CPUSAVER_DWORD,
! 1784: D102_B_CPUSAVER_BUNDLE_MAX_DWORD, D102_B_CPUSAVER_MIN_SIZE_DWORD,
! 1785: "fxp-d102" },
! 1786:
! 1787: { FXP_REV_82550_C, D102_C_CPUSAVER_DWORD,
! 1788: D102_C_CPUSAVER_BUNDLE_MAX_DWORD, D102_C_CPUSAVER_MIN_SIZE_DWORD,
! 1789: "fxp-d102c" },
! 1790:
! 1791: { FXP_REV_82551_F, D102_E_CPUSAVER_DWORD,
! 1792: D102_E_CPUSAVER_BUNDLE_MAX_DWORD, D102_E_CPUSAVER_MIN_SIZE_DWORD,
! 1793: "fxp-d102e" },
! 1794:
! 1795: { FXP_REV_82551_10, D102_E_CPUSAVER_DWORD,
! 1796: D102_E_CPUSAVER_BUNDLE_MAX_DWORD, D102_E_CPUSAVER_MIN_SIZE_DWORD,
! 1797: "fxp-d102e" },
! 1798:
! 1799: { 0, 0,
! 1800: 0, 0,
! 1801: NULL }
! 1802: };
! 1803:
! 1804: void
! 1805: fxp_load_ucode(struct fxp_softc *sc)
! 1806: {
! 1807: const struct ucode *uc;
! 1808: struct fxp_cb_ucode *cbp = &sc->sc_ctrl->u.code;
! 1809: int i, error;
! 1810: u_int32_t *ucode_buf;
! 1811: size_t ucode_len;
! 1812:
! 1813: if (sc->sc_flags & FXPF_UCODE)
! 1814: return;
! 1815:
! 1816: for (uc = ucode_table; uc->revision != 0; uc++)
! 1817: if (sc->sc_revision == uc->revision)
! 1818: break;
! 1819: if (uc->revision == NULL)
! 1820: return; /* no ucode for this chip is found */
! 1821:
! 1822: error = loadfirmware(uc->uname, (u_char **)&ucode_buf, &ucode_len);
! 1823: if (error) {
! 1824: printf("%s: failed loadfirmware of file %s: errno %d\n",
! 1825: sc->sc_dev.dv_xname, uc->uname, error);
! 1826: sc->sc_flags |= FXPF_UCODE;
! 1827: return;
! 1828: }
! 1829:
! 1830: cbp->cb_status = 0;
! 1831: cbp->cb_command = htole16(FXP_CB_COMMAND_UCODE|FXP_CB_COMMAND_EL);
! 1832: cbp->link_addr = 0xffffffff; /* (no) next command */
! 1833: for (i = 0; i < (ucode_len / sizeof(u_int32_t)); i++)
! 1834: cbp->ucode[i] = ucode_buf[i];
! 1835:
! 1836: if (uc->int_delay_offset)
! 1837: *((u_int16_t *)&cbp->ucode[uc->int_delay_offset]) =
! 1838: htole16(sc->sc_int_delay + sc->sc_int_delay / 2);
! 1839:
! 1840: if (uc->bundle_max_offset)
! 1841: *((u_int16_t *)&cbp->ucode[uc->bundle_max_offset]) =
! 1842: htole16(sc->sc_bundle_max);
! 1843:
! 1844: if (uc->min_size_mask_offset)
! 1845: *((u_int16_t *)&cbp->ucode[uc->min_size_mask_offset]) =
! 1846: htole16(sc->sc_min_size_mask);
! 1847:
! 1848: FXP_UCODE_SYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1849:
! 1850: /*
! 1851: * Download the ucode to the chip.
! 1852: */
! 1853: fxp_scb_wait(sc);
! 1854: CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->tx_cb_map->dm_segs->ds_addr
! 1855: + offsetof(struct fxp_ctrl, u.code));
! 1856: fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
! 1857:
! 1858: /* ...and wait for it to complete. */
! 1859: i = 10000;
! 1860: do {
! 1861: DELAY(2);
! 1862: FXP_UCODE_SYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1863: } while (((cbp->cb_status & htole16(FXP_CB_STATUS_C)) == 0) && --i);
! 1864: if (i == 0) {
! 1865: printf("%s: timeout loading microcode\n", sc->sc_dev.dv_xname);
! 1866: free(ucode_buf, M_DEVBUF);
! 1867: return;
! 1868: }
! 1869:
! 1870: #ifdef DEBUG
! 1871: printf("%s: microcode loaded, int_delay: %d usec",
! 1872: sc->sc_dev.dv_xname, sc->sc_int_delay);
! 1873:
! 1874: if (uc->bundle_max_offset)
! 1875: printf(", bundle_max %d\n", sc->sc_bundle_max);
! 1876: else
! 1877: printf("\n");
! 1878: #endif
! 1879:
! 1880: free(ucode_buf, M_DEVBUF);
! 1881: sc->sc_flags |= FXPF_UCODE;
! 1882: }
! 1883: #endif /* SMALL_KERNEL */
CVSweb