Annotation of sys/dev/pci/if_lge.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_lge.c,v 1.45 2006/10/25 02:37:50 brad Exp $ */
! 2: /*
! 3: * Copyright (c) 2001 Wind River Systems
! 4: * Copyright (c) 1997, 1998, 1999, 2000, 2001
! 5: * Bill Paul <william.paul@windriver.com>. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Bill Paul.
! 18: * 4. Neither the name of the author nor the names of any co-contributors
! 19: * may be used to endorse or promote products derived from this software
! 20: * without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
! 23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 25: * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
! 26: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 27: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 28: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 32: * THE POSSIBILITY OF SUCH DAMAGE.
! 33: *
! 34: * $FreeBSD: src/sys/dev/lge/if_lge.c,v 1.6 2001/06/20 19:47:55 bmilekic Exp $
! 35: */
! 36:
! 37: /*
! 38: * Level 1 LXT1001 gigabit ethernet driver for FreeBSD. Public
! 39: * documentation not available, but ask me nicely.
! 40: *
! 41: * Written by Bill Paul <william.paul@windriver.com>
! 42: * Wind River Systems
! 43: */
! 44:
! 45: /*
! 46: * The Level 1 chip is used on some D-Link, SMC and Addtron NICs.
! 47: * It's a 64-bit PCI part that supports TCP/IP checksum offload,
! 48: * VLAN tagging/insertion, GMII and TBI (1000baseX) ports. There
! 49: * are three supported methods for data transfer between host and
! 50: * NIC: programmed I/O, traditional scatter/gather DMA and Packet
! 51: * Propulsion Technology (tm) DMA. The latter mechanism is a form
! 52: * of double buffer DMA where the packet data is copied to a
! 53: * pre-allocated DMA buffer who's physical address has been loaded
! 54: * into a table at device initialization time. The rationale is that
! 55: * the virtual to physical address translation needed for normal
! 56: * scatter/gather DMA is more expensive than the data copy needed
! 57: * for double buffering. This may be true in Windows NT and the like,
! 58: * but it isn't true for us, at least on the x86 arch. This driver
! 59: * uses the scatter/gather I/O method for both TX and RX.
! 60: *
! 61: * The LXT1001 only supports TCP/IP checksum offload on receive.
! 62: * Also, the VLAN tagging is done using a 16-entry table which allows
! 63: * the chip to perform hardware filtering based on VLAN tags. Sadly,
! 64: * our vlan support doesn't currently play well with this kind of
! 65: * hardware support.
! 66: *
! 67: * Special thanks to:
! 68: * - Jeff James at Intel, for arranging to have the LXT1001 manual
! 69: * released (at long last)
! 70: * - Beny Chen at D-Link, for actually sending it to me
! 71: * - Brad Short and Keith Alexis at SMC, for sending me sample
! 72: * SMC9462SX and SMC9462TX adapters for testing
! 73: * - Paul Saab at Y!, for not killing me (though it remains to be seen
! 74: * if in fact he did me much of a favor)
! 75: */
! 76:
! 77: #include "bpfilter.h"
! 78:
! 79: #include <sys/param.h>
! 80: #include <sys/systm.h>
! 81: #include <sys/sockio.h>
! 82: #include <sys/mbuf.h>
! 83: #include <sys/malloc.h>
! 84: #include <sys/kernel.h>
! 85: #include <sys/device.h>
! 86: #include <sys/socket.h>
! 87:
! 88: #include <net/if.h>
! 89: #include <net/if_dl.h>
! 90: #include <net/if_media.h>
! 91:
! 92: #ifdef INET
! 93: #include <netinet/in.h>
! 94: #include <netinet/in_systm.h>
! 95: #include <netinet/in_var.h>
! 96: #include <netinet/ip.h>
! 97: #include <netinet/if_ether.h>
! 98: #endif
! 99:
! 100: #if NBPFILTER > 0
! 101: #include <net/bpf.h>
! 102: #endif
! 103:
! 104: #include <uvm/uvm_extern.h> /* for vtophys */
! 105: #define VTOPHYS(v) vtophys((vaddr_t)(v))
! 106:
! 107: #include <dev/pci/pcireg.h>
! 108: #include <dev/pci/pcivar.h>
! 109: #include <dev/pci/pcidevs.h>
! 110:
! 111: #include <dev/mii/mii.h>
! 112: #include <dev/mii/miivar.h>
! 113:
! 114: #define LGE_USEIOSPACE
! 115:
! 116: #include <dev/pci/if_lgereg.h>
! 117:
! 118: int lge_probe(struct device *, void *, void *);
! 119: void lge_attach(struct device *, struct device *, void *);
! 120:
! 121: struct cfattach lge_ca = {
! 122: sizeof(struct lge_softc), lge_probe, lge_attach
! 123: };
! 124:
! 125: struct cfdriver lge_cd = {
! 126: 0, "lge", DV_IFNET
! 127: };
! 128:
! 129: int lge_alloc_jumbo_mem(struct lge_softc *);
! 130: void *lge_jalloc(struct lge_softc *);
! 131: void lge_jfree(caddr_t, u_int, void *);
! 132:
! 133: int lge_newbuf(struct lge_softc *, struct lge_rx_desc *,
! 134: struct mbuf *);
! 135: int lge_encap(struct lge_softc *, struct mbuf *, u_int32_t *);
! 136: void lge_rxeof(struct lge_softc *, int);
! 137: void lge_txeof(struct lge_softc *);
! 138: int lge_intr(void *);
! 139: void lge_tick(void *);
! 140: void lge_start(struct ifnet *);
! 141: int lge_ioctl(struct ifnet *, u_long, caddr_t);
! 142: void lge_init(void *);
! 143: void lge_stop(struct lge_softc *);
! 144: void lge_watchdog(struct ifnet *);
! 145: void lge_shutdown(void *);
! 146: int lge_ifmedia_upd(struct ifnet *);
! 147: void lge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
! 148:
! 149: void lge_eeprom_getword(struct lge_softc *, int, u_int16_t *);
! 150: void lge_read_eeprom(struct lge_softc *, caddr_t, int, int, int);
! 151:
! 152: int lge_miibus_readreg(struct device *, int, int);
! 153: void lge_miibus_writereg(struct device *, int, int, int);
! 154: void lge_miibus_statchg(struct device *);
! 155:
! 156: void lge_setmulti(struct lge_softc *);
! 157: void lge_reset(struct lge_softc *);
! 158: int lge_list_rx_init(struct lge_softc *);
! 159: int lge_list_tx_init(struct lge_softc *);
! 160:
! 161: #ifdef LGE_DEBUG
! 162: #define DPRINTF(x) if (lgedebug) printf x
! 163: #define DPRINTFN(n,x) if (lgedebug >= (n)) printf x
! 164: int lgedebug = 0;
! 165: #else
! 166: #define DPRINTF(x)
! 167: #define DPRINTFN(n,x)
! 168: #endif
! 169:
! 170: const struct pci_matchid lge_devices[] = {
! 171: { PCI_VENDOR_LEVEL1, PCI_PRODUCT_LEVEL1_LXT1001 }
! 172: };
! 173:
! 174: #define LGE_SETBIT(sc, reg, x) \
! 175: CSR_WRITE_4(sc, reg, \
! 176: CSR_READ_4(sc, reg) | (x))
! 177:
! 178: #define LGE_CLRBIT(sc, reg, x) \
! 179: CSR_WRITE_4(sc, reg, \
! 180: CSR_READ_4(sc, reg) & ~(x))
! 181:
! 182: #define SIO_SET(x) \
! 183: CSR_WRITE_4(sc, LGE_MEAR, CSR_READ_4(sc, LGE_MEAR) | x)
! 184:
! 185: #define SIO_CLR(x) \
! 186: CSR_WRITE_4(sc, LGE_MEAR, CSR_READ_4(sc, LGE_MEAR) & ~x)
! 187:
! 188: /*
! 189: * Read a word of data stored in the EEPROM at address 'addr.'
! 190: */
! 191: void
! 192: lge_eeprom_getword(struct lge_softc *sc, int addr, u_int16_t *dest)
! 193: {
! 194: int i;
! 195: u_int32_t val;
! 196:
! 197: CSR_WRITE_4(sc, LGE_EECTL, LGE_EECTL_CMD_READ|
! 198: LGE_EECTL_SINGLEACCESS|((addr >> 1) << 8));
! 199:
! 200: for (i = 0; i < LGE_TIMEOUT; i++)
! 201: if (!(CSR_READ_4(sc, LGE_EECTL) & LGE_EECTL_CMD_READ))
! 202: break;
! 203:
! 204: if (i == LGE_TIMEOUT) {
! 205: printf("%s: EEPROM read timed out\n", sc->sc_dv.dv_xname);
! 206: return;
! 207: }
! 208:
! 209: val = CSR_READ_4(sc, LGE_EEDATA);
! 210:
! 211: if (addr & 1)
! 212: *dest = (val >> 16) & 0xFFFF;
! 213: else
! 214: *dest = val & 0xFFFF;
! 215: }
! 216:
! 217: /*
! 218: * Read a sequence of words from the EEPROM.
! 219: */
! 220: void
! 221: lge_read_eeprom(struct lge_softc *sc, caddr_t dest, int off,
! 222: int cnt, int swap)
! 223: {
! 224: int i;
! 225: u_int16_t word = 0, *ptr;
! 226:
! 227: for (i = 0; i < cnt; i++) {
! 228: lge_eeprom_getword(sc, off + i, &word);
! 229: ptr = (u_int16_t *)(dest + (i * 2));
! 230: if (swap)
! 231: *ptr = ntohs(word);
! 232: else
! 233: *ptr = word;
! 234: }
! 235: }
! 236:
! 237: int
! 238: lge_miibus_readreg(struct device *dev, int phy, int reg)
! 239: {
! 240: struct lge_softc *sc = (struct lge_softc *)dev;
! 241: int i;
! 242:
! 243: /*
! 244: * If we have a non-PCS PHY, pretend that the internal
! 245: * autoneg stuff at PHY address 0 isn't there so that
! 246: * the miibus code will find only the GMII PHY.
! 247: */
! 248: if (sc->lge_pcs == 0 && phy == 0)
! 249: return (0);
! 250:
! 251: CSR_WRITE_4(sc, LGE_GMIICTL, (phy << 8) | reg | LGE_GMIICMD_READ);
! 252:
! 253: for (i = 0; i < LGE_TIMEOUT; i++)
! 254: if (!(CSR_READ_4(sc, LGE_GMIICTL) & LGE_GMIICTL_CMDBUSY))
! 255: break;
! 256:
! 257: if (i == LGE_TIMEOUT) {
! 258: printf("%s: PHY read timed out\n", sc->sc_dv.dv_xname);
! 259: return (0);
! 260: }
! 261:
! 262: return (CSR_READ_4(sc, LGE_GMIICTL) >> 16);
! 263: }
! 264:
! 265: void
! 266: lge_miibus_writereg(struct device *dev, int phy, int reg, int data)
! 267: {
! 268: struct lge_softc *sc = (struct lge_softc *)dev;
! 269: int i;
! 270:
! 271: CSR_WRITE_4(sc, LGE_GMIICTL,
! 272: (data << 16) | (phy << 8) | reg | LGE_GMIICMD_WRITE);
! 273:
! 274: for (i = 0; i < LGE_TIMEOUT; i++)
! 275: if (!(CSR_READ_4(sc, LGE_GMIICTL) & LGE_GMIICTL_CMDBUSY))
! 276: break;
! 277:
! 278: if (i == LGE_TIMEOUT) {
! 279: printf("%s: PHY write timed out\n", sc->sc_dv.dv_xname);
! 280: }
! 281: }
! 282:
! 283: void
! 284: lge_miibus_statchg(struct device *dev)
! 285: {
! 286: struct lge_softc *sc = (struct lge_softc *)dev;
! 287: struct mii_data *mii = &sc->lge_mii;
! 288:
! 289: LGE_CLRBIT(sc, LGE_GMIIMODE, LGE_GMIIMODE_SPEED);
! 290: switch (IFM_SUBTYPE(mii->mii_media_active)) {
! 291: case IFM_1000_T:
! 292: case IFM_1000_SX:
! 293: LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_1000);
! 294: break;
! 295: case IFM_100_TX:
! 296: LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_100);
! 297: break;
! 298: case IFM_10_T:
! 299: LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_10);
! 300: break;
! 301: default:
! 302: /*
! 303: * Choose something, even if it's wrong. Clearing
! 304: * all the bits will hose autoneg on the internal
! 305: * PHY.
! 306: */
! 307: LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_1000);
! 308: break;
! 309: }
! 310:
! 311: if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
! 312: LGE_SETBIT(sc, LGE_GMIIMODE, LGE_GMIIMODE_FDX);
! 313: } else {
! 314: LGE_CLRBIT(sc, LGE_GMIIMODE, LGE_GMIIMODE_FDX);
! 315: }
! 316: }
! 317:
! 318: void
! 319: lge_setmulti(struct lge_softc *sc)
! 320: {
! 321: struct arpcom *ac = &sc->arpcom;
! 322: struct ifnet *ifp = &ac->ac_if;
! 323: struct ether_multi *enm;
! 324: struct ether_multistep step;
! 325: u_int32_t h = 0, hashes[2] = { 0, 0 };
! 326:
! 327: /* Make sure multicast hash table is enabled. */
! 328: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_MCAST);
! 329:
! 330: allmulti:
! 331: if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
! 332: CSR_WRITE_4(sc, LGE_MAR0, 0xFFFFFFFF);
! 333: CSR_WRITE_4(sc, LGE_MAR1, 0xFFFFFFFF);
! 334: return;
! 335: }
! 336:
! 337: /* first, zot all the existing hash bits */
! 338: CSR_WRITE_4(sc, LGE_MAR0, 0);
! 339: CSR_WRITE_4(sc, LGE_MAR1, 0);
! 340:
! 341: /* now program new ones */
! 342: ETHER_FIRST_MULTI(step, ac, enm);
! 343: while (enm != NULL) {
! 344: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
! 345: ifp->if_flags |= IFF_ALLMULTI;
! 346: goto allmulti;
! 347: }
! 348: h = (ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26) &
! 349: 0x0000003F;
! 350: if (h < 32)
! 351: hashes[0] |= (1 << h);
! 352: else
! 353: hashes[1] |= (1 << (h - 32));
! 354: ETHER_NEXT_MULTI(step, enm);
! 355: }
! 356:
! 357: CSR_WRITE_4(sc, LGE_MAR0, hashes[0]);
! 358: CSR_WRITE_4(sc, LGE_MAR1, hashes[1]);
! 359: }
! 360:
! 361: void
! 362: lge_reset(struct lge_softc *sc)
! 363: {
! 364: int i;
! 365:
! 366: LGE_SETBIT(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL0|LGE_MODE1_SOFTRST);
! 367:
! 368: for (i = 0; i < LGE_TIMEOUT; i++) {
! 369: if (!(CSR_READ_4(sc, LGE_MODE1) & LGE_MODE1_SOFTRST))
! 370: break;
! 371: }
! 372:
! 373: if (i == LGE_TIMEOUT)
! 374: printf("%s: reset never completed\n", sc->sc_dv.dv_xname);
! 375:
! 376: /* Wait a little while for the chip to get its brains in order. */
! 377: DELAY(1000);
! 378: }
! 379:
! 380: /*
! 381: * Probe for a Level 1 chip. Check the PCI vendor and device
! 382: * IDs against our list and return a device name if we find a match.
! 383: */
! 384: int
! 385: lge_probe(struct device *parent, void *match, void *aux)
! 386: {
! 387: return (pci_matchbyid((struct pci_attach_args *)aux, lge_devices,
! 388: sizeof(lge_devices)/sizeof(lge_devices[0])));
! 389: }
! 390:
! 391: /*
! 392: * Attach the interface. Allocate softc structures, do ifmedia
! 393: * setup and ethernet/BPF attach.
! 394: */
! 395: void
! 396: lge_attach(struct device *parent, struct device *self, void *aux)
! 397: {
! 398: struct lge_softc *sc = (struct lge_softc *)self;
! 399: struct pci_attach_args *pa = aux;
! 400: pci_chipset_tag_t pc = pa->pa_pc;
! 401: pci_intr_handle_t ih;
! 402: const char *intrstr = NULL;
! 403: bus_size_t size;
! 404: bus_dma_segment_t seg;
! 405: bus_dmamap_t dmamap;
! 406: int rseg;
! 407: u_char eaddr[ETHER_ADDR_LEN];
! 408: pcireg_t command;
! 409: #ifndef LGE_USEIOSPACE
! 410: pcireg_t memtype;
! 411: #endif
! 412: struct ifnet *ifp;
! 413: caddr_t kva;
! 414:
! 415: /*
! 416: * Handle power management nonsense.
! 417: */
! 418: DPRINTFN(5, ("Preparing for conf read\n"));
! 419: command = pci_conf_read(pc, pa->pa_tag, LGE_PCI_CAPID) & 0x000000FF;
! 420: if (command == 0x01) {
! 421: command = pci_conf_read(pc, pa->pa_tag, LGE_PCI_PWRMGMTCTRL);
! 422: if (command & LGE_PSTATE_MASK) {
! 423: pcireg_t iobase, membase, irq;
! 424:
! 425: /* Save important PCI config data. */
! 426: iobase = pci_conf_read(pc, pa->pa_tag, LGE_PCI_LOIO);
! 427: membase = pci_conf_read(pc, pa->pa_tag, LGE_PCI_LOMEM);
! 428: irq = pci_conf_read(pc, pa->pa_tag, LGE_PCI_INTLINE);
! 429:
! 430: /* Reset the power state. */
! 431: printf("%s: chip is in D%d power mode "
! 432: "-- setting to D0\n", sc->sc_dv.dv_xname,
! 433: command & LGE_PSTATE_MASK);
! 434: command &= 0xFFFFFFFC;
! 435: pci_conf_write(pc, pa->pa_tag,
! 436: LGE_PCI_PWRMGMTCTRL, command);
! 437:
! 438: /* Restore PCI config data. */
! 439: pci_conf_write(pc, pa->pa_tag, LGE_PCI_LOIO, iobase);
! 440: pci_conf_write(pc, pa->pa_tag, LGE_PCI_LOMEM, membase);
! 441: pci_conf_write(pc, pa->pa_tag, LGE_PCI_INTLINE, irq);
! 442: }
! 443: }
! 444:
! 445: /*
! 446: * Map control/status registers.
! 447: */
! 448: DPRINTFN(5, ("Map control/status regs\n"));
! 449:
! 450: DPRINTFN(5, ("pci_mapreg_map\n"));
! 451: #ifdef LGE_USEIOSPACE
! 452: if (pci_mapreg_map(pa, LGE_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
! 453: &sc->lge_btag, &sc->lge_bhandle, NULL, &size, 0)) {
! 454: printf(": can't map i/o space\n");
! 455: return;
! 456: }
! 457: #else
! 458: memtype = pci_mapreg_type(pc, pa->pa_tag, LGE_PCI_LOMEM);
! 459: switch (memtype) {
! 460: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
! 461: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
! 462: if (pci_mapreg_map(pa, LGE_PCI_LOMEM,
! 463: memtype, 0, &sc->lge_btag, &sc->lge_bhandle,
! 464: NULL, &size, 0) == 0)
! 465: break;
! 466: default:
! 467: printf(": can't map mem space\n");
! 468: return;
! 469: }
! 470: #endif
! 471:
! 472: DPRINTFN(5, ("pci_intr_map\n"));
! 473: if (pci_intr_map(pa, &ih)) {
! 474: printf(": couldn't map interrupt\n");
! 475: goto fail_1;
! 476: }
! 477:
! 478: DPRINTFN(5, ("pci_intr_string\n"));
! 479: intrstr = pci_intr_string(pc, ih);
! 480: DPRINTFN(5, ("pci_intr_establish\n"));
! 481: sc->lge_intrhand = pci_intr_establish(pc, ih, IPL_NET, lge_intr, sc,
! 482: sc->sc_dv.dv_xname);
! 483: if (sc->lge_intrhand == NULL) {
! 484: printf(": couldn't establish interrupt");
! 485: if (intrstr != NULL)
! 486: printf(" at %s", intrstr);
! 487: printf("\n");
! 488: goto fail_1;
! 489: }
! 490: printf(": %s", intrstr);
! 491:
! 492: /* Reset the adapter. */
! 493: DPRINTFN(5, ("lge_reset\n"));
! 494: lge_reset(sc);
! 495:
! 496: /*
! 497: * Get station address from the EEPROM.
! 498: */
! 499: DPRINTFN(5, ("lge_read_eeprom\n"));
! 500: lge_read_eeprom(sc, (caddr_t)&eaddr[0], LGE_EE_NODEADDR_0, 1, 0);
! 501: lge_read_eeprom(sc, (caddr_t)&eaddr[2], LGE_EE_NODEADDR_1, 1, 0);
! 502: lge_read_eeprom(sc, (caddr_t)&eaddr[4], LGE_EE_NODEADDR_2, 1, 0);
! 503:
! 504: /*
! 505: * A Level 1 chip was detected. Inform the world.
! 506: */
! 507: printf(", address %s\n", ether_sprintf(eaddr));
! 508:
! 509: bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
! 510:
! 511: sc->sc_dmatag = pa->pa_dmat;
! 512: DPRINTFN(5, ("bus_dmamem_alloc\n"));
! 513: if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct lge_list_data),
! 514: PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
! 515: printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname);
! 516: goto fail_2;
! 517: }
! 518: DPRINTFN(5, ("bus_dmamem_map\n"));
! 519: if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
! 520: sizeof(struct lge_list_data), &kva,
! 521: BUS_DMA_NOWAIT)) {
! 522: printf("%s: can't map dma buffers (%d bytes)\n",
! 523: sc->sc_dv.dv_xname, sizeof(struct lge_list_data));
! 524: goto fail_3;
! 525: }
! 526: DPRINTFN(5, ("bus_dmamem_create\n"));
! 527: if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct lge_list_data), 1,
! 528: sizeof(struct lge_list_data), 0,
! 529: BUS_DMA_NOWAIT, &dmamap)) {
! 530: printf("%s: can't create dma map\n", sc->sc_dv.dv_xname);
! 531: goto fail_4;
! 532: }
! 533: DPRINTFN(5, ("bus_dmamem_load\n"));
! 534: if (bus_dmamap_load(sc->sc_dmatag, dmamap, kva,
! 535: sizeof(struct lge_list_data), NULL,
! 536: BUS_DMA_NOWAIT)) {
! 537: goto fail_5;
! 538: }
! 539:
! 540: DPRINTFN(5, ("bzero\n"));
! 541: sc->lge_ldata = (struct lge_list_data *)kva;
! 542: bzero(sc->lge_ldata, sizeof(struct lge_list_data));
! 543:
! 544: /* Try to allocate memory for jumbo buffers. */
! 545: DPRINTFN(5, ("lge_alloc_jumbo_mem\n"));
! 546: if (lge_alloc_jumbo_mem(sc)) {
! 547: printf("%s: jumbo buffer allocation failed\n",
! 548: sc->sc_dv.dv_xname);
! 549: goto fail_5;
! 550: }
! 551:
! 552: ifp = &sc->arpcom.ac_if;
! 553: ifp->if_softc = sc;
! 554: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 555: ifp->if_ioctl = lge_ioctl;
! 556: ifp->if_start = lge_start;
! 557: ifp->if_watchdog = lge_watchdog;
! 558: ifp->if_baudrate = 1000000000;
! 559: ifp->if_hardmtu = LGE_JUMBO_MTU;
! 560: IFQ_SET_MAXLEN(&ifp->if_snd, LGE_TX_LIST_CNT - 1);
! 561: IFQ_SET_READY(&ifp->if_snd);
! 562: DPRINTFN(5, ("bcopy\n"));
! 563: bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
! 564:
! 565: ifp->if_capabilities = IFCAP_VLAN_MTU;
! 566:
! 567: if (CSR_READ_4(sc, LGE_GMIIMODE) & LGE_GMIIMODE_PCSENH)
! 568: sc->lge_pcs = 1;
! 569: else
! 570: sc->lge_pcs = 0;
! 571:
! 572: /*
! 573: * Do MII setup.
! 574: */
! 575: DPRINTFN(5, ("mii setup\n"));
! 576: sc->lge_mii.mii_ifp = ifp;
! 577: sc->lge_mii.mii_readreg = lge_miibus_readreg;
! 578: sc->lge_mii.mii_writereg = lge_miibus_writereg;
! 579: sc->lge_mii.mii_statchg = lge_miibus_statchg;
! 580: ifmedia_init(&sc->lge_mii.mii_media, 0, lge_ifmedia_upd,
! 581: lge_ifmedia_sts);
! 582: mii_attach(&sc->sc_dv, &sc->lge_mii, 0xffffffff, MII_PHY_ANY,
! 583: MII_OFFSET_ANY, 0);
! 584:
! 585: if (LIST_FIRST(&sc->lge_mii.mii_phys) == NULL) {
! 586: printf("%s: no PHY found!\n", sc->sc_dv.dv_xname);
! 587: ifmedia_add(&sc->lge_mii.mii_media, IFM_ETHER|IFM_MANUAL,
! 588: 0, NULL);
! 589: ifmedia_set(&sc->lge_mii.mii_media, IFM_ETHER|IFM_MANUAL);
! 590: } else {
! 591: DPRINTFN(5, ("ifmedia_set\n"));
! 592: ifmedia_set(&sc->lge_mii.mii_media, IFM_ETHER|IFM_AUTO);
! 593: }
! 594:
! 595: /*
! 596: * Call MI attach routine.
! 597: */
! 598: DPRINTFN(5, ("if_attach\n"));
! 599: if_attach(ifp);
! 600: DPRINTFN(5, ("ether_ifattach\n"));
! 601: ether_ifattach(ifp);
! 602: DPRINTFN(5, ("timeout_set\n"));
! 603: timeout_set(&sc->lge_timeout, lge_tick, sc);
! 604: timeout_add(&sc->lge_timeout, hz);
! 605: return;
! 606:
! 607: fail_5:
! 608: bus_dmamap_destroy(sc->sc_dmatag, dmamap);
! 609:
! 610: fail_4:
! 611: bus_dmamem_unmap(sc->sc_dmatag, kva,
! 612: sizeof(struct lge_list_data));
! 613:
! 614: fail_3:
! 615: bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
! 616:
! 617: fail_2:
! 618: pci_intr_disestablish(pc, sc->lge_intrhand);
! 619:
! 620: fail_1:
! 621: bus_space_unmap(sc->lge_btag, sc->lge_bhandle, size);
! 622: }
! 623:
! 624: /*
! 625: * Initialize the transmit descriptors.
! 626: */
! 627: int
! 628: lge_list_tx_init(struct lge_softc *sc)
! 629: {
! 630: struct lge_list_data *ld;
! 631: struct lge_ring_data *cd;
! 632: int i;
! 633:
! 634: cd = &sc->lge_cdata;
! 635: ld = sc->lge_ldata;
! 636: for (i = 0; i < LGE_TX_LIST_CNT; i++) {
! 637: ld->lge_tx_list[i].lge_mbuf = NULL;
! 638: ld->lge_tx_list[i].lge_ctl = 0;
! 639: }
! 640:
! 641: cd->lge_tx_prod = cd->lge_tx_cons = 0;
! 642:
! 643: return (0);
! 644: }
! 645:
! 646:
! 647: /*
! 648: * Initialize the RX descriptors and allocate mbufs for them. Note that
! 649: * we arralge the descriptors in a closed ring, so that the last descriptor
! 650: * points back to the first.
! 651: */
! 652: int
! 653: lge_list_rx_init(struct lge_softc *sc)
! 654: {
! 655: struct lge_list_data *ld;
! 656: struct lge_ring_data *cd;
! 657: int i;
! 658:
! 659: ld = sc->lge_ldata;
! 660: cd = &sc->lge_cdata;
! 661:
! 662: cd->lge_rx_prod = cd->lge_rx_cons = 0;
! 663:
! 664: CSR_WRITE_4(sc, LGE_RXDESC_ADDR_HI, 0);
! 665:
! 666: for (i = 0; i < LGE_RX_LIST_CNT; i++) {
! 667: if (CSR_READ_1(sc, LGE_RXCMDFREE_8BIT) == 0)
! 668: break;
! 669: if (lge_newbuf(sc, &ld->lge_rx_list[i], NULL) == ENOBUFS)
! 670: return (ENOBUFS);
! 671: }
! 672:
! 673: /* Clear possible 'rx command queue empty' interrupt. */
! 674: CSR_READ_4(sc, LGE_ISR);
! 675:
! 676: return (0);
! 677: }
! 678:
! 679: /*
! 680: * Initialize an RX descriptor and attach an MBUF cluster.
! 681: */
! 682: int
! 683: lge_newbuf(struct lge_softc *sc, struct lge_rx_desc *c, struct mbuf *m)
! 684: {
! 685: struct mbuf *m_new = NULL;
! 686:
! 687: if (m == NULL) {
! 688: caddr_t buf = NULL;
! 689:
! 690: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
! 691: if (m_new == NULL)
! 692: return (ENOBUFS);
! 693:
! 694: /* Allocate the jumbo buffer */
! 695: buf = lge_jalloc(sc);
! 696: if (buf == NULL) {
! 697: m_freem(m_new);
! 698: return (ENOBUFS);
! 699: }
! 700:
! 701: /* Attach the buffer to the mbuf */
! 702: m_new->m_len = m_new->m_pkthdr.len = LGE_JLEN;
! 703: MEXTADD(m_new, buf, LGE_JLEN, 0, lge_jfree, sc);
! 704: } else {
! 705: /*
! 706: * We're re-using a previously allocated mbuf;
! 707: * be sure to re-init pointers and lengths to
! 708: * default values.
! 709: */
! 710: m_new = m;
! 711: m_new->m_len = m_new->m_pkthdr.len = LGE_JLEN;
! 712: m_new->m_data = m_new->m_ext.ext_buf;
! 713: }
! 714:
! 715: /*
! 716: * Adjust alignment so packet payload begins on a
! 717: * longword boundary. Mandatory for Alpha, useful on
! 718: * x86 too.
! 719: */
! 720: m_adj(m_new, ETHER_ALIGN);
! 721:
! 722: c->lge_mbuf = m_new;
! 723: c->lge_fragptr_hi = 0;
! 724: c->lge_fragptr_lo = VTOPHYS(mtod(m_new, caddr_t));
! 725: c->lge_fraglen = m_new->m_len;
! 726: c->lge_ctl = m_new->m_len | LGE_RXCTL_WANTINTR | LGE_FRAGCNT(1);
! 727: c->lge_sts = 0;
! 728:
! 729: /*
! 730: * Put this buffer in the RX command FIFO. To do this,
! 731: * we just write the physical address of the descriptor
! 732: * into the RX descriptor address registers. Note that
! 733: * there are two registers, one high DWORD and one low
! 734: * DWORD, which lets us specify a 64-bit address if
! 735: * desired. We only use a 32-bit address for now.
! 736: * Writing to the low DWORD register is what actually
! 737: * causes the command to be issued, so we do that
! 738: * last.
! 739: */
! 740: CSR_WRITE_4(sc, LGE_RXDESC_ADDR_LO, VTOPHYS(c));
! 741: LGE_INC(sc->lge_cdata.lge_rx_prod, LGE_RX_LIST_CNT);
! 742:
! 743: return (0);
! 744: }
! 745:
! 746: int
! 747: lge_alloc_jumbo_mem(struct lge_softc *sc)
! 748: {
! 749: caddr_t ptr, kva;
! 750: bus_dma_segment_t seg;
! 751: bus_dmamap_t dmamap;
! 752: int i, rseg, state, error;
! 753: struct lge_jpool_entry *entry;
! 754:
! 755: state = error = 0;
! 756:
! 757: /* Grab a big chunk o' storage. */
! 758: if (bus_dmamem_alloc(sc->sc_dmatag, LGE_JMEM, PAGE_SIZE, 0,
! 759: &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
! 760: printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname);
! 761: return (ENOBUFS);
! 762: }
! 763:
! 764: state = 1;
! 765: if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, LGE_JMEM, &kva,
! 766: BUS_DMA_NOWAIT)) {
! 767: printf("%s: can't map dma buffers (%d bytes)\n",
! 768: sc->sc_dv.dv_xname, LGE_JMEM);
! 769: error = ENOBUFS;
! 770: goto out;
! 771: }
! 772:
! 773: state = 2;
! 774: if (bus_dmamap_create(sc->sc_dmatag, LGE_JMEM, 1,
! 775: LGE_JMEM, 0, BUS_DMA_NOWAIT, &dmamap)) {
! 776: printf("%s: can't create dma map\n", sc->sc_dv.dv_xname);
! 777: error = ENOBUFS;
! 778: goto out;
! 779: }
! 780:
! 781: state = 3;
! 782: if (bus_dmamap_load(sc->sc_dmatag, dmamap, kva, LGE_JMEM,
! 783: NULL, BUS_DMA_NOWAIT)) {
! 784: printf("%s: can't load dma map\n", sc->sc_dv.dv_xname);
! 785: error = ENOBUFS;
! 786: goto out;
! 787: }
! 788:
! 789: state = 4;
! 790: sc->lge_cdata.lge_jumbo_buf = (caddr_t)kva;
! 791: DPRINTFN(1,("lge_jumbo_buf = 0x%08X\n", sc->lge_cdata.lge_jumbo_buf));
! 792: DPRINTFN(1,("LGE_JLEN = 0x%08X\n", LGE_JLEN));
! 793:
! 794: LIST_INIT(&sc->lge_jfree_listhead);
! 795: LIST_INIT(&sc->lge_jinuse_listhead);
! 796:
! 797: /*
! 798: * Now divide it up into 9K pieces and save the addresses
! 799: * in an array.
! 800: */
! 801: ptr = sc->lge_cdata.lge_jumbo_buf;
! 802: for (i = 0; i < LGE_JSLOTS; i++) {
! 803: sc->lge_cdata.lge_jslots[i] = ptr;
! 804: ptr += LGE_JLEN;
! 805: entry = malloc(sizeof(struct lge_jpool_entry),
! 806: M_DEVBUF, M_NOWAIT);
! 807: if (entry == NULL) {
! 808: sc->lge_cdata.lge_jumbo_buf = NULL;
! 809: printf("%s: no memory for jumbo buffer queue!\n",
! 810: sc->sc_dv.dv_xname);
! 811: error = ENOBUFS;
! 812: goto out;
! 813: }
! 814: entry->slot = i;
! 815: LIST_INSERT_HEAD(&sc->lge_jfree_listhead,
! 816: entry, jpool_entries);
! 817: }
! 818: out:
! 819: if (error != 0) {
! 820: switch (state) {
! 821: case 4:
! 822: bus_dmamap_unload(sc->sc_dmatag, dmamap);
! 823: case 3:
! 824: bus_dmamap_destroy(sc->sc_dmatag, dmamap);
! 825: case 2:
! 826: bus_dmamem_unmap(sc->sc_dmatag, kva, LGE_JMEM);
! 827: case 1:
! 828: bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
! 829: break;
! 830: default:
! 831: break;
! 832: }
! 833: }
! 834:
! 835: return (error);
! 836: }
! 837:
! 838: /*
! 839: * Allocate a jumbo buffer.
! 840: */
! 841: void *
! 842: lge_jalloc(struct lge_softc *sc)
! 843: {
! 844: struct lge_jpool_entry *entry;
! 845:
! 846: entry = LIST_FIRST(&sc->lge_jfree_listhead);
! 847:
! 848: if (entry == NULL)
! 849: return (NULL);
! 850:
! 851: LIST_REMOVE(entry, jpool_entries);
! 852: LIST_INSERT_HEAD(&sc->lge_jinuse_listhead, entry, jpool_entries);
! 853: return (sc->lge_cdata.lge_jslots[entry->slot]);
! 854: }
! 855:
! 856: /*
! 857: * Release a jumbo buffer.
! 858: */
! 859: void
! 860: lge_jfree(caddr_t buf, u_int size, void *arg)
! 861: {
! 862: struct lge_softc *sc;
! 863: int i;
! 864: struct lge_jpool_entry *entry;
! 865:
! 866: /* Extract the softc struct pointer. */
! 867: sc = (struct lge_softc *)arg;
! 868:
! 869: if (sc == NULL)
! 870: panic("lge_jfree: can't find softc pointer!");
! 871:
! 872: /* calculate the slot this buffer belongs to */
! 873: i = ((vaddr_t)buf - (vaddr_t)sc->lge_cdata.lge_jumbo_buf) / LGE_JLEN;
! 874:
! 875: if ((i < 0) || (i >= LGE_JSLOTS))
! 876: panic("lge_jfree: asked to free buffer that we don't manage!");
! 877:
! 878: entry = LIST_FIRST(&sc->lge_jinuse_listhead);
! 879: if (entry == NULL)
! 880: panic("lge_jfree: buffer not in use!");
! 881: entry->slot = i;
! 882: LIST_REMOVE(entry, jpool_entries);
! 883: LIST_INSERT_HEAD(&sc->lge_jfree_listhead, entry, jpool_entries);
! 884: }
! 885:
! 886: /*
! 887: * A frame has been uploaded: pass the resulting mbuf chain up to
! 888: * the higher level protocols.
! 889: */
! 890: void
! 891: lge_rxeof(struct lge_softc *sc, int cnt)
! 892: {
! 893: struct mbuf *m;
! 894: struct ifnet *ifp;
! 895: struct lge_rx_desc *cur_rx;
! 896: int c, i, total_len = 0;
! 897: u_int32_t rxsts, rxctl;
! 898:
! 899: ifp = &sc->arpcom.ac_if;
! 900:
! 901: /* Find out how many frames were processed. */
! 902: c = cnt;
! 903: i = sc->lge_cdata.lge_rx_cons;
! 904:
! 905: /* Suck them in. */
! 906: while(c) {
! 907: struct mbuf *m0 = NULL;
! 908:
! 909: cur_rx = &sc->lge_ldata->lge_rx_list[i];
! 910: rxctl = cur_rx->lge_ctl;
! 911: rxsts = cur_rx->lge_sts;
! 912: m = cur_rx->lge_mbuf;
! 913: cur_rx->lge_mbuf = NULL;
! 914: total_len = LGE_RXBYTES(cur_rx);
! 915: LGE_INC(i, LGE_RX_LIST_CNT);
! 916: c--;
! 917:
! 918: /*
! 919: * If an error occurs, update stats, clear the
! 920: * status word and leave the mbuf cluster in place:
! 921: * it should simply get re-used next time this descriptor
! 922: * comes up in the ring.
! 923: */
! 924: if (rxctl & LGE_RXCTL_ERRMASK) {
! 925: ifp->if_ierrors++;
! 926: lge_newbuf(sc, &LGE_RXTAIL(sc), m);
! 927: continue;
! 928: }
! 929:
! 930: if (lge_newbuf(sc, &LGE_RXTAIL(sc), NULL) == ENOBUFS) {
! 931: m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN,
! 932: ifp, NULL);
! 933: lge_newbuf(sc, &LGE_RXTAIL(sc), m);
! 934: if (m0 == NULL) {
! 935: ifp->if_ierrors++;
! 936: continue;
! 937: }
! 938: m = m0;
! 939: } else {
! 940: m->m_pkthdr.rcvif = ifp;
! 941: m->m_pkthdr.len = m->m_len = total_len;
! 942: }
! 943:
! 944: ifp->if_ipackets++;
! 945:
! 946: #if NBPFILTER > 0
! 947: /*
! 948: * Handle BPF listeners. Let the BPF user see the packet.
! 949: */
! 950: if (ifp->if_bpf)
! 951: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 952: #endif
! 953:
! 954: /* Do IP checksum checking. */
! 955: if (rxsts & LGE_RXSTS_ISIP) {
! 956: if (!(rxsts & LGE_RXSTS_IPCSUMERR))
! 957: m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
! 958: }
! 959: if (rxsts & LGE_RXSTS_ISTCP) {
! 960: if (!(rxsts & LGE_RXSTS_TCPCSUMERR))
! 961: m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
! 962: }
! 963: if (rxsts & LGE_RXSTS_ISUDP) {
! 964: if (!(rxsts & LGE_RXSTS_UDPCSUMERR))
! 965: m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
! 966: }
! 967:
! 968: ether_input_mbuf(ifp, m);
! 969: }
! 970:
! 971: sc->lge_cdata.lge_rx_cons = i;
! 972: }
! 973:
! 974: /*
! 975: * A frame was downloaded to the chip. It's safe for us to clean up
! 976: * the list buffers.
! 977: */
! 978:
! 979: void
! 980: lge_txeof(struct lge_softc *sc)
! 981: {
! 982: struct lge_tx_desc *cur_tx = NULL;
! 983: struct ifnet *ifp;
! 984: u_int32_t idx, txdone;
! 985:
! 986: ifp = &sc->arpcom.ac_if;
! 987:
! 988: /* Clear the timeout timer. */
! 989: ifp->if_timer = 0;
! 990:
! 991: /*
! 992: * Go through our tx list and free mbufs for those
! 993: * frames that have been transmitted.
! 994: */
! 995: idx = sc->lge_cdata.lge_tx_cons;
! 996: txdone = CSR_READ_1(sc, LGE_TXDMADONE_8BIT);
! 997:
! 998: while (idx != sc->lge_cdata.lge_tx_prod && txdone) {
! 999: cur_tx = &sc->lge_ldata->lge_tx_list[idx];
! 1000:
! 1001: ifp->if_opackets++;
! 1002: if (cur_tx->lge_mbuf != NULL) {
! 1003: m_freem(cur_tx->lge_mbuf);
! 1004: cur_tx->lge_mbuf = NULL;
! 1005: }
! 1006: cur_tx->lge_ctl = 0;
! 1007:
! 1008: txdone--;
! 1009: LGE_INC(idx, LGE_TX_LIST_CNT);
! 1010: ifp->if_timer = 0;
! 1011: }
! 1012:
! 1013: sc->lge_cdata.lge_tx_cons = idx;
! 1014:
! 1015: if (cur_tx != NULL)
! 1016: ifp->if_flags &= ~IFF_OACTIVE;
! 1017: }
! 1018:
! 1019: void
! 1020: lge_tick(void *xsc)
! 1021: {
! 1022: struct lge_softc *sc = xsc;
! 1023: struct mii_data *mii = &sc->lge_mii;
! 1024: struct ifnet *ifp = &sc->arpcom.ac_if;
! 1025: int s;
! 1026:
! 1027: s = splnet();
! 1028:
! 1029: CSR_WRITE_4(sc, LGE_STATSIDX, LGE_STATS_SINGLE_COLL_PKTS);
! 1030: ifp->if_collisions += CSR_READ_4(sc, LGE_STATSVAL);
! 1031: CSR_WRITE_4(sc, LGE_STATSIDX, LGE_STATS_MULTI_COLL_PKTS);
! 1032: ifp->if_collisions += CSR_READ_4(sc, LGE_STATSVAL);
! 1033:
! 1034: if (!sc->lge_link) {
! 1035: mii_tick(mii);
! 1036: if (mii->mii_media_status & IFM_ACTIVE &&
! 1037: IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
! 1038: sc->lge_link++;
! 1039: if (!IFQ_IS_EMPTY(&ifp->if_snd))
! 1040: lge_start(ifp);
! 1041: }
! 1042: }
! 1043:
! 1044: timeout_add(&sc->lge_timeout, hz);
! 1045:
! 1046: splx(s);
! 1047: }
! 1048:
! 1049: int
! 1050: lge_intr(void *arg)
! 1051: {
! 1052: struct lge_softc *sc;
! 1053: struct ifnet *ifp;
! 1054: u_int32_t status;
! 1055: int claimed = 0;
! 1056:
! 1057: sc = arg;
! 1058: ifp = &sc->arpcom.ac_if;
! 1059:
! 1060: /* Supress unwanted interrupts */
! 1061: if (!(ifp->if_flags & IFF_UP)) {
! 1062: lge_stop(sc);
! 1063: return (0);
! 1064: }
! 1065:
! 1066: for (;;) {
! 1067: /*
! 1068: * Reading the ISR register clears all interrupts, and
! 1069: * clears the 'interrupts enabled' bit in the IMR
! 1070: * register.
! 1071: */
! 1072: status = CSR_READ_4(sc, LGE_ISR);
! 1073:
! 1074: if ((status & LGE_INTRS) == 0)
! 1075: break;
! 1076:
! 1077: claimed = 1;
! 1078:
! 1079: if ((status & (LGE_ISR_TXCMDFIFO_EMPTY|LGE_ISR_TXDMA_DONE)))
! 1080: lge_txeof(sc);
! 1081:
! 1082: if (status & LGE_ISR_RXDMA_DONE)
! 1083: lge_rxeof(sc, LGE_RX_DMACNT(status));
! 1084:
! 1085: if (status & LGE_ISR_RXCMDFIFO_EMPTY)
! 1086: lge_init(sc);
! 1087:
! 1088: if (status & LGE_ISR_PHY_INTR) {
! 1089: sc->lge_link = 0;
! 1090: timeout_del(&sc->lge_timeout);
! 1091: lge_tick(sc);
! 1092: }
! 1093: }
! 1094:
! 1095: /* Re-enable interrupts. */
! 1096: CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_SETRST_CTL0|LGE_IMR_INTR_ENB);
! 1097:
! 1098: if (!IFQ_IS_EMPTY(&ifp->if_snd))
! 1099: lge_start(ifp);
! 1100:
! 1101: return (claimed);
! 1102: }
! 1103:
! 1104: /*
! 1105: * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
! 1106: * pointers to the fragment pointers.
! 1107: */
! 1108: int
! 1109: lge_encap(struct lge_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
! 1110: {
! 1111: struct lge_frag *f = NULL;
! 1112: struct lge_tx_desc *cur_tx;
! 1113: struct mbuf *m;
! 1114: int frag = 0, tot_len = 0;
! 1115:
! 1116: /*
! 1117: * Start packing the mbufs in this chain into
! 1118: * the fragment pointers. Stop when we run out
! 1119: * of fragments or hit the end of the mbuf chain.
! 1120: */
! 1121: m = m_head;
! 1122: cur_tx = &sc->lge_ldata->lge_tx_list[*txidx];
! 1123: frag = 0;
! 1124:
! 1125: for (m = m_head; m != NULL; m = m->m_next) {
! 1126: if (m->m_len != 0) {
! 1127: tot_len += m->m_len;
! 1128: f = &cur_tx->lge_frags[frag];
! 1129: f->lge_fraglen = m->m_len;
! 1130: f->lge_fragptr_lo = VTOPHYS(mtod(m, vaddr_t));
! 1131: f->lge_fragptr_hi = 0;
! 1132: frag++;
! 1133: }
! 1134: }
! 1135:
! 1136: if (m != NULL)
! 1137: return (ENOBUFS);
! 1138:
! 1139: cur_tx->lge_mbuf = m_head;
! 1140: cur_tx->lge_ctl = LGE_TXCTL_WANTINTR|LGE_FRAGCNT(frag)|tot_len;
! 1141: LGE_INC((*txidx), LGE_TX_LIST_CNT);
! 1142:
! 1143: /* Queue for transmit */
! 1144: CSR_WRITE_4(sc, LGE_TXDESC_ADDR_LO, VTOPHYS(cur_tx));
! 1145:
! 1146: return (0);
! 1147: }
! 1148:
! 1149: /*
! 1150: * Main transmit routine. To avoid having to do mbuf copies, we put pointers
! 1151: * to the mbuf data regions directly in the transmit lists. We also save a
! 1152: * copy of the pointers since the transmit list fragment pointers are
! 1153: * physical addresses.
! 1154: */
! 1155:
! 1156: void
! 1157: lge_start(struct ifnet *ifp)
! 1158: {
! 1159: struct lge_softc *sc;
! 1160: struct mbuf *m_head = NULL;
! 1161: u_int32_t idx;
! 1162: int pkts = 0;
! 1163:
! 1164: sc = ifp->if_softc;
! 1165:
! 1166: if (!sc->lge_link)
! 1167: return;
! 1168:
! 1169: idx = sc->lge_cdata.lge_tx_prod;
! 1170:
! 1171: if (ifp->if_flags & IFF_OACTIVE)
! 1172: return;
! 1173:
! 1174: while(sc->lge_ldata->lge_tx_list[idx].lge_mbuf == NULL) {
! 1175: if (CSR_READ_1(sc, LGE_TXCMDFREE_8BIT) == 0)
! 1176: break;
! 1177:
! 1178: IFQ_POLL(&ifp->if_snd, m_head);
! 1179: if (m_head == NULL)
! 1180: break;
! 1181:
! 1182: if (lge_encap(sc, m_head, &idx)) {
! 1183: ifp->if_flags |= IFF_OACTIVE;
! 1184: break;
! 1185: }
! 1186:
! 1187: /* now we are committed to transmit the packet */
! 1188: IFQ_DEQUEUE(&ifp->if_snd, m_head);
! 1189: pkts++;
! 1190:
! 1191: #if NBPFILTER > 0
! 1192: /*
! 1193: * If there's a BPF listener, bounce a copy of this frame
! 1194: * to him.
! 1195: */
! 1196: if (ifp->if_bpf)
! 1197: bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
! 1198: #endif
! 1199: }
! 1200: if (pkts == 0)
! 1201: return;
! 1202:
! 1203: sc->lge_cdata.lge_tx_prod = idx;
! 1204:
! 1205: /*
! 1206: * Set a timeout in case the chip goes out to lunch.
! 1207: */
! 1208: ifp->if_timer = 5;
! 1209: }
! 1210:
! 1211: void
! 1212: lge_init(void *xsc)
! 1213: {
! 1214: struct lge_softc *sc = xsc;
! 1215: struct ifnet *ifp = &sc->arpcom.ac_if;
! 1216: int s;
! 1217:
! 1218: s = splnet();
! 1219:
! 1220: /*
! 1221: * Cancel pending I/O and free all RX/TX buffers.
! 1222: */
! 1223: lge_stop(sc);
! 1224: lge_reset(sc);
! 1225:
! 1226: /* Set MAC address */
! 1227: CSR_WRITE_4(sc, LGE_PAR0, *(u_int32_t *)(&sc->arpcom.ac_enaddr[0]));
! 1228: CSR_WRITE_4(sc, LGE_PAR1, *(u_int32_t *)(&sc->arpcom.ac_enaddr[4]));
! 1229:
! 1230: /* Init circular RX list. */
! 1231: if (lge_list_rx_init(sc) == ENOBUFS) {
! 1232: printf("%s: initialization failed: no "
! 1233: "memory for rx buffers\n", sc->sc_dv.dv_xname);
! 1234: lge_stop(sc);
! 1235: splx(s);
! 1236: return;
! 1237: }
! 1238:
! 1239: /*
! 1240: * Init tx descriptors.
! 1241: */
! 1242: lge_list_tx_init(sc);
! 1243:
! 1244: /* Set initial value for MODE1 register. */
! 1245: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_UCAST|
! 1246: LGE_MODE1_TX_CRC|LGE_MODE1_TXPAD|
! 1247: LGE_MODE1_RX_FLOWCTL|LGE_MODE1_SETRST_CTL0|
! 1248: LGE_MODE1_SETRST_CTL1|LGE_MODE1_SETRST_CTL2);
! 1249:
! 1250: /* If we want promiscuous mode, set the allframes bit. */
! 1251: if (ifp->if_flags & IFF_PROMISC) {
! 1252: CSR_WRITE_4(sc, LGE_MODE1,
! 1253: LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_PROMISC);
! 1254: } else {
! 1255: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_PROMISC);
! 1256: }
! 1257:
! 1258: /*
! 1259: * Set the capture broadcast bit to capture broadcast frames.
! 1260: */
! 1261: if (ifp->if_flags & IFF_BROADCAST) {
! 1262: CSR_WRITE_4(sc, LGE_MODE1,
! 1263: LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_BCAST);
! 1264: } else {
! 1265: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_BCAST);
! 1266: }
! 1267:
! 1268: /* Packet padding workaround? */
! 1269: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RMVPAD);
! 1270:
! 1271: /* No error frames */
! 1272: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_ERRPKTS);
! 1273:
! 1274: /* Receive large frames */
! 1275: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_GIANTS);
! 1276:
! 1277: /* Workaround: disable RX/TX flow control */
! 1278: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_TX_FLOWCTL);
! 1279: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_FLOWCTL);
! 1280:
! 1281: /* Make sure to strip CRC from received frames */
! 1282: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_CRC);
! 1283:
! 1284: /* Turn off magic packet mode */
! 1285: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_MPACK_ENB);
! 1286:
! 1287: /* Turn off all VLAN stuff */
! 1288: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_VLAN_RX|LGE_MODE1_VLAN_TX|
! 1289: LGE_MODE1_VLAN_STRIP|LGE_MODE1_VLAN_INSERT);
! 1290:
! 1291: /* Workarond: FIFO overflow */
! 1292: CSR_WRITE_2(sc, LGE_RXFIFO_HIWAT, 0x3FFF);
! 1293: CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_SETRST_CTL1|LGE_IMR_RXFIFO_WAT);
! 1294:
! 1295: /*
! 1296: * Load the multicast filter.
! 1297: */
! 1298: lge_setmulti(sc);
! 1299:
! 1300: /*
! 1301: * Enable hardware checksum validation for all received IPv4
! 1302: * packets, do not reject packets with bad checksums.
! 1303: */
! 1304: CSR_WRITE_4(sc, LGE_MODE2, LGE_MODE2_RX_IPCSUM|
! 1305: LGE_MODE2_RX_TCPCSUM|LGE_MODE2_RX_UDPCSUM|
! 1306: LGE_MODE2_RX_ERRCSUM);
! 1307:
! 1308: /*
! 1309: * Enable the delivery of PHY interrupts based on
! 1310: * link/speed/duplex status chalges.
! 1311: */
! 1312: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL0|LGE_MODE1_GMIIPOLL);
! 1313:
! 1314: /* Enable receiver and transmitter. */
! 1315: CSR_WRITE_4(sc, LGE_RXDESC_ADDR_HI, 0);
! 1316: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_ENB);
! 1317:
! 1318: CSR_WRITE_4(sc, LGE_TXDESC_ADDR_HI, 0);
! 1319: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_TX_ENB);
! 1320:
! 1321: /*
! 1322: * Enable interrupts.
! 1323: */
! 1324: CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_SETRST_CTL0|
! 1325: LGE_IMR_SETRST_CTL1|LGE_IMR_INTR_ENB|LGE_INTRS);
! 1326:
! 1327: lge_ifmedia_upd(ifp);
! 1328:
! 1329: ifp->if_flags |= IFF_RUNNING;
! 1330: ifp->if_flags &= ~IFF_OACTIVE;
! 1331:
! 1332: splx(s);
! 1333:
! 1334: timeout_add(&sc->lge_timeout, hz);
! 1335: }
! 1336:
! 1337: /*
! 1338: * Set media options.
! 1339: */
! 1340: int
! 1341: lge_ifmedia_upd(struct ifnet *ifp)
! 1342: {
! 1343: struct lge_softc *sc = ifp->if_softc;
! 1344: struct mii_data *mii = &sc->lge_mii;
! 1345:
! 1346: sc->lge_link = 0;
! 1347: if (mii->mii_instance) {
! 1348: struct mii_softc *miisc;
! 1349: LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
! 1350: mii_phy_reset(miisc);
! 1351: }
! 1352: mii_mediachg(mii);
! 1353:
! 1354: return (0);
! 1355: }
! 1356:
! 1357: /*
! 1358: * Report current media status.
! 1359: */
! 1360: void
! 1361: lge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
! 1362: {
! 1363: struct lge_softc *sc = ifp->if_softc;
! 1364: struct mii_data *mii = &sc->lge_mii;
! 1365:
! 1366: mii_pollstat(mii);
! 1367: ifmr->ifm_active = mii->mii_media_active;
! 1368: ifmr->ifm_status = mii->mii_media_status;
! 1369: }
! 1370:
! 1371: int
! 1372: lge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
! 1373: {
! 1374: struct lge_softc *sc = ifp->if_softc;
! 1375: struct ifreq *ifr = (struct ifreq *) data;
! 1376: struct ifaddr *ifa = (struct ifaddr *)data;
! 1377: struct mii_data *mii;
! 1378: int s, error = 0;
! 1379:
! 1380: s = splnet();
! 1381:
! 1382: switch(command) {
! 1383: case SIOCSIFADDR:
! 1384: ifp->if_flags |= IFF_UP;
! 1385: if (!(ifp->if_flags & IFF_RUNNING))
! 1386: lge_init(sc);
! 1387: #ifdef INET
! 1388: if (ifa->ifa_addr->sa_family == AF_INET)
! 1389: arp_ifinit(&sc->arpcom, ifa);
! 1390: #endif /* INET */
! 1391: break;
! 1392: case SIOCSIFMTU:
! 1393: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
! 1394: error = EINVAL;
! 1395: else if (ifp->if_mtu != ifr->ifr_mtu)
! 1396: ifp->if_mtu = ifr->ifr_mtu;
! 1397: break;
! 1398: case SIOCSIFFLAGS:
! 1399: if (ifp->if_flags & IFF_UP) {
! 1400: if (ifp->if_flags & IFF_RUNNING &&
! 1401: ifp->if_flags & IFF_PROMISC &&
! 1402: !(sc->lge_if_flags & IFF_PROMISC)) {
! 1403: CSR_WRITE_4(sc, LGE_MODE1,
! 1404: LGE_MODE1_SETRST_CTL1|
! 1405: LGE_MODE1_RX_PROMISC);
! 1406: lge_setmulti(sc);
! 1407: } else if (ifp->if_flags & IFF_RUNNING &&
! 1408: !(ifp->if_flags & IFF_PROMISC) &&
! 1409: sc->lge_if_flags & IFF_PROMISC) {
! 1410: CSR_WRITE_4(sc, LGE_MODE1,
! 1411: LGE_MODE1_RX_PROMISC);
! 1412: lge_setmulti(sc);
! 1413: } else if (ifp->if_flags & IFF_RUNNING &&
! 1414: (ifp->if_flags ^ sc->lge_if_flags) & IFF_ALLMULTI) {
! 1415: lge_setmulti(sc);
! 1416: } else {
! 1417: if (!(ifp->if_flags & IFF_RUNNING))
! 1418: lge_init(sc);
! 1419: }
! 1420: } else {
! 1421: if (ifp->if_flags & IFF_RUNNING)
! 1422: lge_stop(sc);
! 1423: }
! 1424: sc->lge_if_flags = ifp->if_flags;
! 1425: break;
! 1426: case SIOCADDMULTI:
! 1427: case SIOCDELMULTI:
! 1428: error = (command == SIOCADDMULTI)
! 1429: ? ether_addmulti(ifr, &sc->arpcom)
! 1430: : ether_delmulti(ifr, &sc->arpcom);
! 1431:
! 1432: if (error == ENETRESET) {
! 1433: if (ifp->if_flags & IFF_RUNNING)
! 1434: lge_setmulti(sc);
! 1435: error = 0;
! 1436: }
! 1437: break;
! 1438: case SIOCGIFMEDIA:
! 1439: case SIOCSIFMEDIA:
! 1440: mii = &sc->lge_mii;
! 1441: error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
! 1442: break;
! 1443: default:
! 1444: error = ENOTTY;
! 1445: break;
! 1446: }
! 1447:
! 1448: splx(s);
! 1449:
! 1450: return (error);
! 1451: }
! 1452:
! 1453: void
! 1454: lge_watchdog(struct ifnet *ifp)
! 1455: {
! 1456: struct lge_softc *sc;
! 1457:
! 1458: sc = ifp->if_softc;
! 1459:
! 1460: ifp->if_oerrors++;
! 1461: printf("%s: watchdog timeout\n", sc->sc_dv.dv_xname);
! 1462:
! 1463: lge_stop(sc);
! 1464: lge_reset(sc);
! 1465: lge_init(sc);
! 1466:
! 1467: if (!IFQ_IS_EMPTY(&ifp->if_snd))
! 1468: lge_start(ifp);
! 1469: }
! 1470:
! 1471: /*
! 1472: * Stop the adapter and free any mbufs allocated to the
! 1473: * RX and TX lists.
! 1474: */
! 1475: void
! 1476: lge_stop(struct lge_softc *sc)
! 1477: {
! 1478: int i;
! 1479: struct ifnet *ifp;
! 1480:
! 1481: ifp = &sc->arpcom.ac_if;
! 1482: ifp->if_timer = 0;
! 1483: timeout_del(&sc->lge_timeout);
! 1484:
! 1485: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 1486:
! 1487: CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_INTR_ENB);
! 1488:
! 1489: /* Disable receiver and transmitter. */
! 1490: CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_ENB|LGE_MODE1_TX_ENB);
! 1491: sc->lge_link = 0;
! 1492:
! 1493: /*
! 1494: * Free data in the RX lists.
! 1495: */
! 1496: for (i = 0; i < LGE_RX_LIST_CNT; i++) {
! 1497: if (sc->lge_ldata->lge_rx_list[i].lge_mbuf != NULL) {
! 1498: m_freem(sc->lge_ldata->lge_rx_list[i].lge_mbuf);
! 1499: sc->lge_ldata->lge_rx_list[i].lge_mbuf = NULL;
! 1500: }
! 1501: }
! 1502: bzero((char *)&sc->lge_ldata->lge_rx_list,
! 1503: sizeof(sc->lge_ldata->lge_rx_list));
! 1504:
! 1505: /*
! 1506: * Free the TX list buffers.
! 1507: */
! 1508: for (i = 0; i < LGE_TX_LIST_CNT; i++) {
! 1509: if (sc->lge_ldata->lge_tx_list[i].lge_mbuf != NULL) {
! 1510: m_freem(sc->lge_ldata->lge_tx_list[i].lge_mbuf);
! 1511: sc->lge_ldata->lge_tx_list[i].lge_mbuf = NULL;
! 1512: }
! 1513: }
! 1514:
! 1515: bzero((char *)&sc->lge_ldata->lge_tx_list,
! 1516: sizeof(sc->lge_ldata->lge_tx_list));
! 1517: }
! 1518:
! 1519: /*
! 1520: * Stop all chip I/O so that the kernel's probe routines don't
! 1521: * get confused by errant DMAs when rebooting.
! 1522: */
! 1523: void
! 1524: lge_shutdown(void *xsc)
! 1525: {
! 1526: struct lge_softc *sc = (struct lge_softc *)xsc;
! 1527:
! 1528: lge_reset(sc);
! 1529: lge_stop(sc);
! 1530: }
CVSweb