Annotation of sys/arch/vax/if/sgec.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sgec.c,v 1.15 2006/08/31 22:10:57 miod Exp $ */
! 2: /* $NetBSD: sgec.c,v 1.5 2000/06/04 02:14:14 matt Exp $ */
! 3: /*
! 4: * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. All advertising materials mentioning features or use of this software
! 15: * must display the following acknowledgement:
! 16: * This product includes software developed at Ludd, University of
! 17: * Lule}, Sweden and its contributors.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: /*
! 34: * Driver for the SGEC (Second Generation Ethernet Controller), sitting
! 35: * on for example the VAX 4000/300 (KA670).
! 36: *
! 37: * The SGEC looks like a mixture of the DEQNA and the TULIP. Fun toy.
! 38: *
! 39: * Even though the chip is capable to use virtual addresses (read the
! 40: * System Page Table directly) this driver doesn't do so, and there
! 41: * is no benefit in doing it either in NetBSD of today.
! 42: *
! 43: * Things that is still to do:
! 44: * Collect statistics.
! 45: * Use imperfect filtering when many multicast addresses.
! 46: */
! 47:
! 48: #include "bpfilter.h"
! 49:
! 50: #include <sys/param.h>
! 51: #include <sys/mbuf.h>
! 52: #include <sys/socket.h>
! 53: #include <sys/device.h>
! 54: #include <sys/systm.h>
! 55: #include <sys/sockio.h>
! 56:
! 57: #include <net/if.h>
! 58: #include <net/if_dl.h>
! 59:
! 60: #include <netinet/in.h>
! 61: #include <netinet/if_ether.h>
! 62:
! 63: #if NBPFILTER > 0
! 64: #include <net/bpf.h>
! 65: #include <net/bpfdesc.h>
! 66: #endif
! 67:
! 68: #include <machine/bus.h>
! 69:
! 70: #include <vax/if/sgecreg.h>
! 71: #include <vax/if/sgecvar.h>
! 72:
! 73: void sgec_rxintr(struct ze_softc *);
! 74: void sgec_txintr(struct ze_softc *);
! 75: void zeinit(struct ze_softc *);
! 76: int zeioctl(struct ifnet *, u_long, caddr_t);
! 77: void zekick(struct ze_softc *);
! 78: int zereset(struct ze_softc *);
! 79: void zestart(struct ifnet *);
! 80: void zetimeout(struct ifnet *);
! 81: int ze_add_rxbuf(struct ze_softc *, int);
! 82: void ze_setup(struct ze_softc *);
! 83:
! 84: struct cfdriver ze_cd = {
! 85: NULL, "ze", DV_IFNET
! 86: };
! 87:
! 88: #define ZE_WCSR(csr, val) \
! 89: bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val)
! 90: #define ZE_RCSR(csr) \
! 91: bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr)
! 92:
! 93: /*
! 94: * Interface exists: make available by filling in network interface
! 95: * record. System will initialize the interface when it is ready
! 96: * to accept packets.
! 97: */
! 98: void
! 99: sgec_attach(sc)
! 100: struct ze_softc *sc;
! 101: {
! 102: struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
! 103: struct ze_tdes *tp;
! 104: struct ze_rdes *rp;
! 105: bus_dma_segment_t seg;
! 106: int i, s, rseg, error;
! 107:
! 108: /*
! 109: * Allocate DMA safe memory for descriptors and setup memory.
! 110: */
! 111: if ((error = bus_dmamem_alloc(sc->sc_dmat,
! 112: sizeof(struct ze_cdata), NBPG, 0, &seg, 1, &rseg,
! 113: BUS_DMA_NOWAIT)) != 0) {
! 114: printf(": unable to allocate control data, error = %d\n",
! 115: error);
! 116: goto fail_0;
! 117: }
! 118:
! 119: if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
! 120: sizeof(struct ze_cdata), (caddr_t *)&sc->sc_zedata,
! 121: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
! 122: printf(": unable to map control data, error = %d\n", error);
! 123: goto fail_1;
! 124: }
! 125:
! 126: if ((error = bus_dmamap_create(sc->sc_dmat,
! 127: sizeof(struct ze_cdata), 1,
! 128: sizeof(struct ze_cdata), 0, BUS_DMA_NOWAIT,
! 129: &sc->sc_cmap)) != 0) {
! 130: printf(": unable to create control data DMA map, error = %d\n",
! 131: error);
! 132: goto fail_2;
! 133: }
! 134:
! 135: if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
! 136: sc->sc_zedata, sizeof(struct ze_cdata), NULL,
! 137: BUS_DMA_NOWAIT)) != 0) {
! 138: printf(": unable to load control data DMA map, error = %d\n",
! 139: error);
! 140: goto fail_3;
! 141: }
! 142:
! 143: /*
! 144: * Zero the newly allocated memory.
! 145: */
! 146: bzero(sc->sc_zedata, sizeof(struct ze_cdata));
! 147: /*
! 148: * Create the transmit descriptor DMA maps.
! 149: */
! 150: for (i = 0; i < TXDESCS; i++) {
! 151: if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
! 152: 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
! 153: &sc->sc_xmtmap[i]))) {
! 154: printf(": unable to create tx DMA map %d, error = %d\n",
! 155: i, error);
! 156: goto fail_4;
! 157: }
! 158: }
! 159:
! 160: /*
! 161: * Create receive buffer DMA maps.
! 162: */
! 163: for (i = 0; i < RXDESCS; i++) {
! 164: if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
! 165: MCLBYTES, 0, BUS_DMA_NOWAIT,
! 166: &sc->sc_rcvmap[i]))) {
! 167: printf(": unable to create rx DMA map %d, error = %d\n",
! 168: i, error);
! 169: goto fail_5;
! 170: }
! 171: }
! 172: /*
! 173: * Pre-allocate the receive buffers.
! 174: */
! 175: s = splnet();
! 176: for (i = 0; i < RXDESCS; i++) {
! 177: if ((error = ze_add_rxbuf(sc, i)) != 0) {
! 178: printf(": unable to allocate or map rx buffer %d\n,"
! 179: " error = %d\n", i, error);
! 180: goto fail_6;
! 181: }
! 182: }
! 183: splx(s);
! 184:
! 185: /*
! 186: * Create ring loops of the buffer chains.
! 187: * This is only done once.
! 188: */
! 189: sc->sc_pzedata = (struct ze_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
! 190:
! 191: rp = sc->sc_zedata->zc_recv;
! 192: rp[RXDESCS].ze_framelen = ZE_FRAMELEN_OW;
! 193: rp[RXDESCS].ze_rdes1 = ZE_RDES1_CA;
! 194: rp[RXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_recv;
! 195:
! 196: tp = sc->sc_zedata->zc_xmit;
! 197: tp[TXDESCS].ze_tdr = ZE_TDR_OW;
! 198: tp[TXDESCS].ze_tdes1 = ZE_TDES1_CA;
! 199: tp[TXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_xmit;
! 200:
! 201: if (zereset(sc))
! 202: return;
! 203:
! 204: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
! 205: ifp->if_softc = sc;
! 206: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 207: ifp->if_start = zestart;
! 208: ifp->if_ioctl = zeioctl;
! 209: ifp->if_watchdog = zetimeout;
! 210:
! 211: /*
! 212: * Attach the interface.
! 213: */
! 214: if_attach(ifp);
! 215: ether_ifattach(ifp);
! 216:
! 217: printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
! 218: return;
! 219:
! 220: /*
! 221: * Free any resources we've allocated during the failed attach
! 222: * attempt. Do this in reverse order and fall through.
! 223: */
! 224: fail_6:
! 225: for (i = 0; i < RXDESCS; i++) {
! 226: if (sc->sc_rxmbuf[i] != NULL) {
! 227: bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
! 228: m_freem(sc->sc_rxmbuf[i]);
! 229: }
! 230: }
! 231: fail_5:
! 232: for (i = 0; i < RXDESCS; i++) {
! 233: if (sc->sc_xmtmap[i] != NULL)
! 234: bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
! 235: }
! 236: fail_4:
! 237: for (i = 0; i < TXDESCS; i++) {
! 238: if (sc->sc_rcvmap[i] != NULL)
! 239: bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
! 240: }
! 241: bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
! 242: fail_3:
! 243: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
! 244: fail_2:
! 245: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_zedata,
! 246: sizeof(struct ze_cdata));
! 247: fail_1:
! 248: bus_dmamem_free(sc->sc_dmat, &seg, rseg);
! 249: fail_0:
! 250: return;
! 251: }
! 252:
! 253: /*
! 254: * Initialization of interface.
! 255: */
! 256: void
! 257: zeinit(sc)
! 258: struct ze_softc *sc;
! 259: {
! 260: struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
! 261: struct ze_cdata *zc = sc->sc_zedata;
! 262: int i;
! 263:
! 264: /*
! 265: * Reset the interface.
! 266: */
! 267: if (zereset(sc))
! 268: return;
! 269:
! 270: sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
! 271: /*
! 272: * Release and init transmit descriptors.
! 273: */
! 274: for (i = 0; i < TXDESCS; i++) {
! 275: if (sc->sc_txmbuf[i]) {
! 276: bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
! 277: m_freem(sc->sc_txmbuf[i]);
! 278: sc->sc_txmbuf[i] = 0;
! 279: }
! 280: zc->zc_xmit[i].ze_tdr = 0; /* Clear valid bit */
! 281: }
! 282:
! 283:
! 284: /*
! 285: * Init receive descriptors.
! 286: */
! 287: for (i = 0; i < RXDESCS; i++)
! 288: zc->zc_recv[i].ze_framelen = ZE_FRAMELEN_OW;
! 289: sc->sc_nextrx = 0;
! 290:
! 291: ZE_WCSR(ZE_CSR6, ZE_NICSR6_IE | ZE_NICSR6_BL_8 | ZE_NICSR6_ST |
! 292: ZE_NICSR6_SR | ZE_NICSR6_DC);
! 293:
! 294: ifp->if_flags |= IFF_RUNNING;
! 295: ifp->if_flags &= ~IFF_OACTIVE;
! 296:
! 297: /*
! 298: * Send a setup frame.
! 299: * This will start the transmit machinery as well.
! 300: */
! 301: ze_setup(sc);
! 302:
! 303: }
! 304:
! 305: /*
! 306: * Kick off the transmit logic, if it is stopped.
! 307: * On the VXT2000 we need to always reprogram CSR4,
! 308: * so stop it unconditionnaly.
! 309: */
! 310: void
! 311: zekick(struct ze_softc *sc)
! 312: {
! 313: u_int csr5;
! 314:
! 315: csr5 = ZE_RCSR(ZE_CSR5);
! 316: if (ISSET(sc->sc_flags, SGECF_VXTQUIRKS)) {
! 317: if ((csr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN) {
! 318: ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) & ~ZE_NICSR6_ST);
! 319: while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) !=
! 320: ZE_NICSR5_TS_STOP)
! 321: DELAY(10);
! 322: }
! 323: ZE_WCSR(ZE_CSR4,
! 324: (vaddr_t)&sc->sc_pzedata->zc_xmit[sc->sc_nexttx]);
! 325: ZE_WCSR(ZE_CSR1, ZE_NICSR1_TXPD);
! 326: if ((csr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN) {
! 327: ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) | ZE_NICSR6_ST);
! 328: while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) ==
! 329: ZE_NICSR5_TS_STOP)
! 330: DELAY(10);
! 331: }
! 332: } else {
! 333: if ((csr5 & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN)
! 334: ZE_WCSR(ZE_CSR1, ZE_NICSR1_TXPD);
! 335: }
! 336: }
! 337:
! 338: /*
! 339: * Start output on interface.
! 340: */
! 341: void
! 342: zestart(ifp)
! 343: struct ifnet *ifp;
! 344: {
! 345: struct ze_softc *sc = ifp->if_softc;
! 346: struct ze_cdata *zc = sc->sc_zedata;
! 347: paddr_t buffer;
! 348: struct mbuf *m, *m0;
! 349: int idx, len, s, i, totlen, error;
! 350: int old_inq = sc->sc_inq;
! 351: short orword;
! 352:
! 353: s = splnet();
! 354: while (sc->sc_inq < (TXDESCS - 1)) {
! 355: if (ISSET(sc->sc_flags, SGECF_SETUP)) {
! 356: ze_setup(sc);
! 357: continue;
! 358: }
! 359: idx = sc->sc_nexttx;
! 360: IF_DEQUEUE(&sc->sc_if.if_snd, m);
! 361: if (m == 0)
! 362: goto out;
! 363: /*
! 364: * Count number of mbufs in chain.
! 365: * Always do DMA directly from mbufs, therefore the transmit
! 366: * ring is really big.
! 367: */
! 368: for (m0 = m, i = 0; m0; m0 = m0->m_next)
! 369: if (m0->m_len)
! 370: i++;
! 371: if (i >= TXDESCS)
! 372: panic("zestart"); /* XXX */
! 373:
! 374: if ((i + sc->sc_inq) >= (TXDESCS - 1)) {
! 375: IF_PREPEND(&sc->sc_if.if_snd, m);
! 376: ifp->if_flags |= IFF_OACTIVE;
! 377: goto out;
! 378: }
! 379:
! 380: #if NBPFILTER > 0
! 381: if (ifp->if_bpf)
! 382: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
! 383: #endif
! 384: /*
! 385: * m now points to a mbuf chain that can be loaded.
! 386: * Loop around and set it.
! 387: */
! 388: totlen = 0;
! 389: for (m0 = m; m0; m0 = m0->m_next) {
! 390: error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx],
! 391: mtod(m0, void *), m0->m_len, 0, 0);
! 392: buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr;
! 393: len = m0->m_len;
! 394: if (len == 0)
! 395: continue;
! 396:
! 397: totlen += len;
! 398: /* Word alignment calc */
! 399: orword = 0;
! 400: if (totlen == len)
! 401: orword = ZE_TDES1_FS;
! 402: if (totlen == m->m_pkthdr.len) {
! 403: if (totlen < ETHER_ADDR_LEN)
! 404: len += (ETHER_ADDR_LEN - totlen);
! 405: orword |= ZE_TDES1_LS;
! 406: sc->sc_txmbuf[idx] = m;
! 407: }
! 408: zc->zc_xmit[idx].ze_bufsize = len;
! 409: zc->zc_xmit[idx].ze_bufaddr = (char *)buffer;
! 410: zc->zc_xmit[idx].ze_tdes1 = orword | ZE_TDES1_IC;
! 411: zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
! 412:
! 413: if (++idx == TXDESCS)
! 414: idx = 0;
! 415: sc->sc_inq++;
! 416: }
! 417: #ifdef DIAGNOSTIC
! 418: if (totlen != m->m_pkthdr.len)
! 419: panic("zestart: len fault");
! 420: #endif
! 421:
! 422: /*
! 423: * Kick off the transmit logic, if it is stopped.
! 424: */
! 425: zekick(sc);
! 426: sc->sc_nexttx = idx;
! 427: }
! 428: if (sc->sc_inq == (TXDESCS - 1))
! 429: ifp->if_flags |= IFF_OACTIVE;
! 430:
! 431: out: if (old_inq < sc->sc_inq)
! 432: ifp->if_timer = 5; /* If transmit logic dies */
! 433: splx(s);
! 434: }
! 435:
! 436: void
! 437: sgec_rxintr(struct ze_softc *sc)
! 438: {
! 439: struct ze_cdata *zc = sc->sc_zedata;
! 440: struct ifnet *ifp = &sc->sc_if;
! 441: struct ether_header *eh;
! 442: struct mbuf *m;
! 443: u_short rdes0;
! 444: int len;
! 445:
! 446: while ((zc->zc_recv[sc->sc_nextrx].ze_framelen &
! 447: ZE_FRAMELEN_OW) == 0) {
! 448: rdes0 = zc->zc_recv[sc->sc_nextrx].ze_rdes0;
! 449: if (rdes0 & ZE_RDES0_ES) {
! 450: rdes0 &= ~ZE_RDES0_TL; /* not really an error */
! 451: if ((rdes0 & (ZE_RDES0_OF | ZE_RDES0_CE | ZE_RDES0_CS |
! 452: ZE_RDES0_LE | ZE_RDES0_RF)) == 0)
! 453: rdes0 &= ~ZE_RDES0_ES;
! 454: }
! 455: if (rdes0 & ZE_RDES0_ES) {
! 456: ifp->if_ierrors++;
! 457: if (rdes0 & ZE_RDES0_CS)
! 458: ifp->if_collisions++;
! 459: m = NULL;
! 460: } else {
! 461: ifp->if_ipackets++;
! 462: m = sc->sc_rxmbuf[sc->sc_nextrx];
! 463: len = zc->zc_recv[sc->sc_nextrx].ze_framelen;
! 464: }
! 465: ze_add_rxbuf(sc, sc->sc_nextrx);
! 466: if (m != NULL) {
! 467: m->m_pkthdr.rcvif = ifp;
! 468: m->m_pkthdr.len = m->m_len = len;
! 469: eh = mtod(m, struct ether_header *);
! 470: #if NBPFILTER > 0
! 471: if (ifp->if_bpf) {
! 472: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 473: if ((ifp->if_flags & IFF_PROMISC) != 0 &&
! 474: ((eh->ether_dhost[0] & 1) == 0) &&
! 475: bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
! 476: ETHER_ADDR_LEN) != 0) {
! 477: m_freem(m);
! 478: continue;
! 479: }
! 480: }
! 481: #endif
! 482: /*
! 483: * ALLMULTI means PROMISC in this driver.
! 484: */
! 485: if ((ifp->if_flags & IFF_ALLMULTI) &&
! 486: ((eh->ether_dhost[0] & 1) == 0) &&
! 487: bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
! 488: ETHER_ADDR_LEN)) {
! 489: m_freem(m);
! 490: continue;
! 491: }
! 492: ether_input_mbuf(ifp, m);
! 493: }
! 494: if (++sc->sc_nextrx == RXDESCS)
! 495: sc->sc_nextrx = 0;
! 496: }
! 497: }
! 498:
! 499: void
! 500: sgec_txintr(struct ze_softc *sc)
! 501: {
! 502: struct ze_cdata *zc = sc->sc_zedata;
! 503: struct ifnet *ifp = &sc->sc_if;
! 504: u_short tdes0;
! 505:
! 506: while ((zc->zc_xmit[sc->sc_lastack].ze_tdr & ZE_TDR_OW) == 0) {
! 507: int idx = sc->sc_lastack;
! 508:
! 509: if (sc->sc_lastack == sc->sc_nexttx)
! 510: break;
! 511: sc->sc_inq--;
! 512: if (++sc->sc_lastack == TXDESCS)
! 513: sc->sc_lastack = 0;
! 514:
! 515: if ((zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_DT) ==
! 516: ZE_TDES1_DT_SETUP) {
! 517: continue;
! 518: }
! 519:
! 520: tdes0 = zc->zc_xmit[idx].ze_tdes0;
! 521: if (tdes0 & ZE_TDES0_ES) {
! 522: if (tdes0 & ZE_TDES0_TO)
! 523: printf("%s: transmit watchdog timeout\n",
! 524: sc->sc_dev.dv_xname);
! 525: if (tdes0 & (ZE_TDES0_LO | ZE_TDES0_NC))
! 526: printf("%s: no carrier\n",
! 527: sc->sc_dev.dv_xname);
! 528: if (tdes0 & ZE_TDES0_EC) {
! 529: printf("%s: excessive collisions, tdr %d\n",
! 530: sc->sc_dev.dv_xname,
! 531: zc->zc_xmit[idx].ze_tdr & ~ZE_TDR_OW);
! 532: ifp->if_collisions += 16;
! 533: } else if (tdes0 & ZE_TDES0_LC)
! 534: ifp->if_collisions +=
! 535: (tdes0 & ZE_TDES0_CC) >> 3;
! 536: if (tdes0 & ZE_TDES0_UF)
! 537: printf("%s: underflow\n", sc->sc_dev.dv_xname);
! 538: ifp->if_oerrors++;
! 539: if (tdes0 & (ZE_TDES0_TO | ZE_TDES0_UF))
! 540: zeinit(sc);
! 541: } else {
! 542: if (zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_LS)
! 543: ifp->if_opackets++;
! 544: bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
! 545: if (sc->sc_txmbuf[idx]) {
! 546: m_freem(sc->sc_txmbuf[idx]);
! 547: sc->sc_txmbuf[idx] = 0;
! 548: }
! 549: }
! 550: }
! 551: if (sc->sc_inq == 0)
! 552: ifp->if_timer = 0;
! 553: ifp->if_flags &= ~IFF_OACTIVE;
! 554: zestart(ifp); /* Put in more in queue */
! 555: }
! 556:
! 557: int
! 558: sgec_intr(sc)
! 559: struct ze_softc *sc;
! 560: {
! 561: int s, csr;
! 562:
! 563: csr = ZE_RCSR(ZE_CSR5);
! 564: if ((csr & ZE_NICSR5_IS) == 0) /* Wasn't we */
! 565: return 0;
! 566:
! 567: /*
! 568: * On some systems, interrupts are handled at spl4, this can end up
! 569: * in pool corruption.
! 570: */
! 571: s = splnet();
! 572:
! 573: ZE_WCSR(ZE_CSR5, csr);
! 574:
! 575: if (csr & ZE_NICSR5_ME) {
! 576: printf("%s: memory error, resetting\n", sc->sc_dev.dv_xname);
! 577: zeinit(sc);
! 578: return (1);
! 579: }
! 580:
! 581: if (csr & ZE_NICSR5_RI)
! 582: sgec_rxintr(sc);
! 583:
! 584: if (csr & ZE_NICSR5_TI)
! 585: sgec_txintr(sc);
! 586:
! 587: splx(s);
! 588:
! 589: return 1;
! 590: }
! 591:
! 592: /*
! 593: * Process an ioctl request.
! 594: */
! 595: int
! 596: zeioctl(ifp, cmd, data)
! 597: struct ifnet *ifp;
! 598: u_long cmd;
! 599: caddr_t data;
! 600: {
! 601: struct ze_softc *sc = ifp->if_softc;
! 602: struct ifreq *ifr = (struct ifreq *)data;
! 603: struct ifaddr *ifa = (struct ifaddr *)data;
! 604: int s = splnet(), error = 0;
! 605:
! 606: switch (cmd) {
! 607:
! 608: case SIOCSIFADDR:
! 609: ifp->if_flags |= IFF_UP;
! 610: switch(ifa->ifa_addr->sa_family) {
! 611: #ifdef INET
! 612: case AF_INET:
! 613: zeinit(sc);
! 614: arp_ifinit(&sc->sc_ac, ifa);
! 615: break;
! 616: #endif
! 617: }
! 618: break;
! 619:
! 620: case SIOCSIFFLAGS:
! 621: if ((ifp->if_flags & IFF_UP) == 0 &&
! 622: (ifp->if_flags & IFF_RUNNING) != 0) {
! 623: /*
! 624: * If interface is marked down and it is running,
! 625: * stop it. (by disabling receive mechanism).
! 626: */
! 627: ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) &
! 628: ~(ZE_NICSR6_ST|ZE_NICSR6_SR));
! 629: ifp->if_flags &= ~IFF_RUNNING;
! 630: } else if ((ifp->if_flags & IFF_UP) != 0 &&
! 631: (ifp->if_flags & IFF_RUNNING) == 0) {
! 632: /*
! 633: * If interface it marked up and it is stopped, then
! 634: * start it.
! 635: */
! 636: zeinit(sc);
! 637: } else if ((ifp->if_flags & IFF_UP) != 0) {
! 638: /*
! 639: * Send a new setup packet to match any new changes.
! 640: * (Like IFF_PROMISC etc)
! 641: */
! 642: ze_setup(sc);
! 643: }
! 644: break;
! 645:
! 646: case SIOCADDMULTI:
! 647: case SIOCDELMULTI:
! 648: /*
! 649: * Update our multicast list.
! 650: */
! 651: error = (cmd == SIOCADDMULTI) ?
! 652: ether_addmulti(ifr, &sc->sc_ac):
! 653: ether_delmulti(ifr, &sc->sc_ac);
! 654:
! 655: if (error == ENETRESET) {
! 656: /*
! 657: * Multicast list has changed; set the hardware filter
! 658: * accordingly.
! 659: */
! 660: if (ifp->if_flags & IFF_RUNNING)
! 661: ze_setup(sc);
! 662: error = 0;
! 663: }
! 664: break;
! 665:
! 666: default:
! 667: error = EINVAL;
! 668:
! 669: }
! 670: splx(s);
! 671: return (error);
! 672: }
! 673:
! 674: /*
! 675: * Add a receive buffer to the indicated descriptor.
! 676: */
! 677: int
! 678: ze_add_rxbuf(sc, i)
! 679: struct ze_softc *sc;
! 680: int i;
! 681: {
! 682: struct mbuf *m;
! 683: struct ze_rdes *rp;
! 684: int error;
! 685:
! 686: splassert(IPL_NET);
! 687:
! 688: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 689: if (m == NULL)
! 690: return (ENOBUFS);
! 691:
! 692: MCLGET(m, M_DONTWAIT);
! 693: if ((m->m_flags & M_EXT) == 0) {
! 694: m_freem(m);
! 695: return (ENOBUFS);
! 696: }
! 697:
! 698: if (sc->sc_rxmbuf[i] != NULL)
! 699: bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]);
! 700:
! 701: error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i],
! 702: m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
! 703: if (error)
! 704: panic("%s: can't load rx DMA map %d, error = %d",
! 705: sc->sc_dev.dv_xname, i, error);
! 706: sc->sc_rxmbuf[i] = m;
! 707:
! 708: bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0,
! 709: sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
! 710:
! 711: /*
! 712: * We know that the mbuf cluster is page aligned. Also, be sure
! 713: * that the IP header will be longword aligned.
! 714: */
! 715: m->m_data += 2;
! 716: rp = &sc->sc_zedata->zc_recv[i];
! 717: rp->ze_bufsize = (m->m_ext.ext_size - 2);
! 718: rp->ze_bufaddr = (char *)sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2;
! 719: rp->ze_framelen = ZE_FRAMELEN_OW;
! 720:
! 721: return (0);
! 722: }
! 723:
! 724: /*
! 725: * Create a setup packet and put in queue for sending.
! 726: */
! 727: void
! 728: ze_setup(sc)
! 729: struct ze_softc *sc;
! 730: {
! 731: struct ether_multi *enm;
! 732: struct ether_multistep step;
! 733: struct ze_cdata *zc = sc->sc_zedata;
! 734: struct ifnet *ifp = &sc->sc_if;
! 735: u_int8_t *enaddr = sc->sc_ac.ac_enaddr;
! 736: int j, idx, s, reg;
! 737:
! 738: s = splnet();
! 739: if (sc->sc_inq == (TXDESCS - 1)) {
! 740: SET(sc->sc_flags, SGECF_SETUP);
! 741: splx(s);
! 742: return;
! 743: }
! 744: CLR(sc->sc_flags, SGECF_SETUP);
! 745:
! 746: /*
! 747: * Init the setup packet with valid info.
! 748: */
! 749: memset(zc->zc_setup, 0xff, sizeof(zc->zc_setup)); /* Broadcast */
! 750: bcopy(enaddr, zc->zc_setup, ETHER_ADDR_LEN);
! 751:
! 752: /*
! 753: * Multicast handling. The SGEC can handle up to 16 direct
! 754: * ethernet addresses.
! 755: */
! 756: j = 16;
! 757: ifp->if_flags &= ~IFF_ALLMULTI;
! 758: ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
! 759: while (enm != NULL) {
! 760: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
! 761: ifp->if_flags |= IFF_ALLMULTI;
! 762: break;
! 763: }
! 764: bcopy(enm->enm_addrlo, &zc->zc_setup[j], ETHER_ADDR_LEN);
! 765: j += 8;
! 766: ETHER_NEXT_MULTI(step, enm);
! 767: if ((enm != NULL)&& (j == 128)) {
! 768: ifp->if_flags |= IFF_ALLMULTI;
! 769: break;
! 770: }
! 771: }
! 772:
! 773: /*
! 774: * Fiddle with the receive logic.
! 775: */
! 776: reg = ZE_RCSR(ZE_CSR6);
! 777: DELAY(10);
! 778: ZE_WCSR(ZE_CSR6, reg & ~ZE_NICSR6_SR); /* Stop rx */
! 779: while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_RS) != ZE_NICSR5_RS_STOP)
! 780: DELAY(10);
! 781: reg &= ~ZE_NICSR6_AF;
! 782: if (ifp->if_flags & IFF_PROMISC)
! 783: reg |= ZE_NICSR6_AF_PROM;
! 784: else if (ifp->if_flags & IFF_ALLMULTI)
! 785: reg |= ZE_NICSR6_AF_ALLM;
! 786: DELAY(10);
! 787: ZE_WCSR(ZE_CSR6, reg);
! 788: while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_RS) == ZE_NICSR5_RS_STOP)
! 789: DELAY(10);
! 790: /*
! 791: * Only send a setup packet if needed.
! 792: */
! 793: if ((ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) == 0) {
! 794: idx = sc->sc_nexttx;
! 795: zc->zc_xmit[idx].ze_tdes1 = ZE_TDES1_DT_SETUP;
! 796: zc->zc_xmit[idx].ze_bufsize = 128;
! 797: zc->zc_xmit[idx].ze_bufaddr = sc->sc_pzedata->zc_setup;
! 798: zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
! 799:
! 800: zekick(sc);
! 801:
! 802: sc->sc_inq++;
! 803: if (++sc->sc_nexttx == TXDESCS)
! 804: sc->sc_nexttx = 0;
! 805: }
! 806: splx(s);
! 807: }
! 808:
! 809: /*
! 810: * Check for dead transmit logic.
! 811: */
! 812: void
! 813: zetimeout(ifp)
! 814: struct ifnet *ifp;
! 815: {
! 816: struct ze_softc *sc = ifp->if_softc;
! 817:
! 818: if (sc->sc_inq == 0)
! 819: return;
! 820:
! 821: printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
! 822: /*
! 823: * Do a reset of interface, to get it going again.
! 824: * Will it work by just restart the transmit logic?
! 825: */
! 826: zeinit(sc);
! 827: }
! 828:
! 829: /*
! 830: * Reset chip:
! 831: * Set/reset the reset flag.
! 832: * Write interrupt vector.
! 833: * Write ring buffer addresses.
! 834: * Write SBR.
! 835: */
! 836: int
! 837: zereset(sc)
! 838: struct ze_softc *sc;
! 839: {
! 840: int reg, i, s;
! 841:
! 842: ZE_WCSR(ZE_CSR6, ZE_NICSR6_RE);
! 843: DELAY(50000);
! 844: if (ZE_RCSR(ZE_CSR5) & ZE_NICSR5_SF) {
! 845: printf("%s: selftest failed\n", sc->sc_dev.dv_xname);
! 846: return 1;
! 847: }
! 848:
! 849: /*
! 850: * Get the vector that were set at match time, and remember it.
! 851: * WHICH VECTOR TO USE? Take one unused. XXX
! 852: * Funny way to set vector described in the programmers manual.
! 853: */
! 854: reg = ZE_NICSR0_IPL14 | sc->sc_intvec | ZE_NICSR0_MBO; /* SYNC/ASYNC??? */
! 855: i = 10;
! 856: s = splnet();
! 857: do {
! 858: if (i-- == 0) {
! 859: printf("Failing SGEC CSR0 init\n");
! 860: splx(s);
! 861: return 1;
! 862: }
! 863: ZE_WCSR(ZE_CSR0, reg);
! 864: } while (ZE_RCSR(ZE_CSR0) != reg);
! 865: splx(s);
! 866:
! 867: ZE_WCSR(ZE_CSR3, (vaddr_t)sc->sc_pzedata->zc_recv);
! 868: ZE_WCSR(ZE_CSR4, (vaddr_t)sc->sc_pzedata->zc_xmit);
! 869: return 0;
! 870: }
CVSweb