Annotation of sys/arch/sparc/dev/be.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: be.c,v 1.40 2006/05/27 23:59:07 jason Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1998 Theo de Raadt and Jason L. Wright.
! 5: * 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: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
! 20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 26: */
! 27:
! 28: #include <sys/param.h>
! 29: #include <sys/systm.h>
! 30: #include <sys/kernel.h>
! 31: #include <sys/errno.h>
! 32: #include <sys/ioctl.h>
! 33: #include <sys/mbuf.h>
! 34: #include <sys/socket.h>
! 35: #include <sys/syslog.h>
! 36: #include <sys/device.h>
! 37: #include <sys/malloc.h>
! 38: #include <sys/timeout.h>
! 39:
! 40: #include <net/if.h>
! 41: #include <net/if_dl.h>
! 42: #include <net/if_types.h>
! 43: #include <net/netisr.h>
! 44: #include <net/if_media.h>
! 45:
! 46: #ifdef INET
! 47: #include <netinet/in.h>
! 48: #include <netinet/in_systm.h>
! 49: #include <netinet/in_var.h>
! 50: #include <netinet/ip.h>
! 51: #include <netinet/if_ether.h>
! 52: #endif
! 53:
! 54: #include "bpfilter.h"
! 55: #if NBPFILTER > 0
! 56: #include <net/bpf.h>
! 57: #include <net/bpfdesc.h>
! 58: #endif
! 59:
! 60: #include <machine/autoconf.h>
! 61: #include <machine/cpu.h>
! 62:
! 63: #include <sparc/dev/sbusvar.h>
! 64: #include <sparc/dev/dmareg.h>
! 65: #include <sparc/dev/dmavar.h>
! 66:
! 67: #include <sparc/dev/qecvar.h>
! 68: #include <sparc/dev/qecreg.h>
! 69: #include <sparc/dev/bereg.h>
! 70: #include <sparc/dev/bevar.h>
! 71:
! 72: int bematch(struct device *, void *, void *);
! 73: void beattach(struct device *, struct device *, void *);
! 74:
! 75: void beinit(struct besoftc *);
! 76: void bestart(struct ifnet *);
! 77: void bestop(struct besoftc *);
! 78: void bewatchdog(struct ifnet *);
! 79: int beioctl(struct ifnet *, u_long, caddr_t);
! 80: void bereset(struct besoftc *);
! 81:
! 82: int beintr(void *);
! 83: int berint(struct besoftc *);
! 84: int betint(struct besoftc *);
! 85: int beqint(struct besoftc *, u_int32_t);
! 86: int beeint(struct besoftc *, u_int32_t);
! 87: void be_read(struct besoftc *, int, int);
! 88:
! 89: void be_tcvr_idle(struct besoftc *);
! 90: void be_tcvr_init(struct besoftc *);
! 91: void be_tcvr_write(struct besoftc *, u_int8_t, u_int16_t);
! 92: void be_tcvr_write_bit(struct besoftc *, int);
! 93: int be_tcvr_read_bit1(struct besoftc *);
! 94: int be_tcvr_read_bit2(struct besoftc *);
! 95: int be_tcvr_read(struct besoftc *, u_int8_t);
! 96: void be_ifmedia_sts(struct ifnet *, struct ifmediareq *);
! 97: int be_ifmedia_upd(struct ifnet *);
! 98: void be_mcreset(struct besoftc *);
! 99: void betick(void *);
! 100: void be_tx_harvest(struct besoftc *);
! 101:
! 102: struct cfdriver be_cd = {
! 103: NULL, "be", DV_IFNET
! 104: };
! 105:
! 106: struct cfattach be_ca = {
! 107: sizeof(struct besoftc), bematch, beattach
! 108: };
! 109:
! 110: int
! 111: bematch(parent, vcf, aux)
! 112: struct device *parent;
! 113: void *vcf, *aux;
! 114: {
! 115: struct cfdata *cf = vcf;
! 116: struct confargs *ca = aux;
! 117: register struct romaux *ra = &ca->ca_ra;
! 118:
! 119: if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
! 120: return (0);
! 121: return (1);
! 122: }
! 123:
! 124: void
! 125: beattach(parent, self, aux)
! 126: struct device *parent, *self;
! 127: void *aux;
! 128: {
! 129: struct qec_softc *qec = (struct qec_softc *)parent;
! 130: struct besoftc *sc = (struct besoftc *)self;
! 131: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 132: struct confargs *ca = aux;
! 133: struct bootpath *bp;
! 134: extern void myetheraddr(u_char *);
! 135: int pri, bmsr;
! 136:
! 137: if (ca->ca_ra.ra_nintr != 1) {
! 138: printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
! 139: return;
! 140: }
! 141: pri = ca->ca_ra.ra_intr[0].int_pri;
! 142: sc->sc_rev = getpropint(ca->ca_ra.ra_node, "board-version", -1);
! 143:
! 144: timeout_set(&sc->sc_tick, betick, sc);
! 145:
! 146: sc->sc_cr = mapiodev(&ca->ca_ra.ra_reg[0], 0, sizeof(struct be_cregs));
! 147: sc->sc_br = mapiodev(&ca->ca_ra.ra_reg[1], 0, sizeof(struct be_bregs));
! 148: sc->sc_tr = mapiodev(&ca->ca_ra.ra_reg[2], 0, sizeof(struct be_tregs));
! 149: sc->sc_qec = qec;
! 150: sc->sc_qr = qec->sc_regs;
! 151: bestop(sc);
! 152:
! 153: sc->sc_channel = getpropint(ca->ca_ra.ra_node, "channel#", -1);
! 154: if (sc->sc_channel == -1)
! 155: sc->sc_channel = 0;
! 156:
! 157: sc->sc_burst = getpropint(ca->ca_ra.ra_node, "burst-sizes", -1);
! 158: if (sc->sc_burst == -1)
! 159: sc->sc_burst = qec->sc_burst;
! 160:
! 161: /* Clamp at parent's burst sizes */
! 162: sc->sc_burst &= qec->sc_burst;
! 163:
! 164: sc->sc_ih.ih_fun = beintr;
! 165: sc->sc_ih.ih_arg = sc;
! 166: intr_establish(pri, &sc->sc_ih, IPL_NET, sc->sc_dev.dv_xname);
! 167:
! 168: myetheraddr(sc->sc_arpcom.ac_enaddr);
! 169:
! 170: be_tcvr_init(sc);
! 171:
! 172: ifmedia_init(&sc->sc_ifmedia, 0, be_ifmedia_upd, be_ifmedia_sts);
! 173: bmsr = be_tcvr_read(sc, PHY_BMSR);
! 174: if (bmsr == BE_TCVR_READ_INVALID)
! 175: return;
! 176:
! 177: if (bmsr & PHY_BMSR_10BASET_HALF) {
! 178: ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
! 179: ifmedia_add(&sc->sc_ifmedia,
! 180: IFM_ETHER | IFM_10_T | IFM_HDX, 0, NULL);
! 181: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
! 182: }
! 183:
! 184: if (bmsr & PHY_BMSR_10BASET_FULL) {
! 185: ifmedia_add(&sc->sc_ifmedia,
! 186: IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
! 187: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX;
! 188: }
! 189:
! 190: if (bmsr & PHY_BMSR_100BASETX_HALF) {
! 191: ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL);
! 192: ifmedia_add(&sc->sc_ifmedia,
! 193: IFM_ETHER | IFM_100_TX | IFM_HDX, 0, NULL);
! 194: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX;
! 195: }
! 196:
! 197: if (bmsr & PHY_BMSR_100BASETX_FULL) {
! 198: ifmedia_add(&sc->sc_ifmedia,
! 199: IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL);
! 200: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX;
! 201: }
! 202:
! 203: if (bmsr & PHY_BMSR_100BASET4) {
! 204: ifmedia_add(&sc->sc_ifmedia,
! 205: IFM_ETHER | IFM_100_T4, 0, NULL);
! 206: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_T4;
! 207: }
! 208:
! 209: if (bmsr & PHY_BMSR_ANC) {
! 210: ifmedia_add(&sc->sc_ifmedia,
! 211: IFM_ETHER | IFM_AUTO, 0, NULL);
! 212: sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
! 213: }
! 214:
! 215: ifmedia_set(&sc->sc_ifmedia, sc->sc_ifmedia.ifm_media);
! 216:
! 217: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
! 218: ifp->if_softc = sc;
! 219: ifp->if_start = bestart;
! 220: ifp->if_ioctl = beioctl;
! 221: ifp->if_watchdog = bewatchdog;
! 222: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
! 223: IFF_MULTICAST;
! 224:
! 225: IFQ_SET_MAXLEN(&ifp->if_snd, BE_TX_RING_SIZE);
! 226: IFQ_SET_READY(&ifp->if_snd);
! 227:
! 228: /* Attach the interface. */
! 229: if_attach(ifp);
! 230: ether_ifattach(ifp);
! 231:
! 232: printf(" pri %d: rev %x address %s\n", pri, sc->sc_rev,
! 233: ether_sprintf(sc->sc_arpcom.ac_enaddr));
! 234:
! 235: bp = ca->ca_ra.ra_bp;
! 236: if (bp != NULL && strcmp(bp->name, "be") == 0 &&
! 237: sc->sc_dev.dv_unit == bp->val[1])
! 238: bp->dev = &sc->sc_dev;
! 239: }
! 240:
! 241: /*
! 242: * Start output on interface.
! 243: * We make two assumptions here:
! 244: * 1) that the current priority is set to splnet _before_ this code
! 245: * is called *and* is returned to the appropriate priority after
! 246: * return
! 247: * 2) that the IFF_OACTIVE flag is checked before this code is called
! 248: * (i.e. that the output part of the interface is idle)
! 249: */
! 250: void
! 251: bestart(ifp)
! 252: struct ifnet *ifp;
! 253: {
! 254: struct besoftc *sc = (struct besoftc *)ifp->if_softc;
! 255: struct mbuf *m;
! 256: int bix, len, cnt;
! 257:
! 258: if (sc->sc_no_td > 0) {
! 259: /* Try to free previous stuff */
! 260: be_tx_harvest(sc);
! 261: }
! 262:
! 263: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
! 264: return;
! 265:
! 266: bix = sc->sc_last_td;
! 267: cnt = sc->sc_no_td;
! 268:
! 269: for (;;) {
! 270: IFQ_POLL(&ifp->if_snd, m);
! 271: if (m == NULL)
! 272: break;
! 273:
! 274: IFQ_DEQUEUE(&ifp->if_snd, m);
! 275:
! 276: #if NBPFILTER > 0
! 277: /*
! 278: * If BPF is listening on this interface, let it see the
! 279: * packet before we commit it to the wire.
! 280: */
! 281: if (ifp->if_bpf)
! 282: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
! 283: #endif
! 284:
! 285: /*
! 286: * Copy the mbuf chain into the transmit buffer.
! 287: */
! 288: len = qec_put(sc->sc_bufs->tx_buf[bix & BE_TX_RING_MASK], m);
! 289:
! 290: /*
! 291: * Initialize transmit registers and start transmission
! 292: */
! 293: sc->sc_desc->be_txd[bix].tx_flags =
! 294: BE_TXD_OWN | BE_TXD_SOP | BE_TXD_EOP |
! 295: (len & BE_TXD_LENGTH);
! 296: sc->sc_cr->ctrl = BE_CR_CTRL_TWAKEUP;
! 297:
! 298: if (++bix == BE_TX_RING_MAXSIZE)
! 299: bix = 0;
! 300:
! 301: if (++cnt == BE_TX_RING_SIZE) {
! 302: ifp->if_flags |= IFF_OACTIVE;
! 303: break;
! 304: }
! 305: }
! 306:
! 307: if (cnt > BE_TX_HIGH_WATER) {
! 308: /* turn on interrupt */
! 309: sc->sc_tx_intr = 1;
! 310: sc->sc_cr->timask = 0;
! 311: }
! 312:
! 313: if (cnt != sc->sc_no_td) {
! 314: ifp->if_timer = 5;
! 315: sc->sc_last_td = bix;
! 316: sc->sc_no_td = cnt;
! 317: }
! 318: }
! 319:
! 320: void
! 321: bestop(sc)
! 322: struct besoftc *sc;
! 323: {
! 324: int tries;
! 325:
! 326: sc->sc_arpcom.ac_if.if_timer = 0;
! 327: if (timeout_pending(&sc->sc_tick))
! 328: timeout_del(&sc->sc_tick);
! 329:
! 330: tries = 32;
! 331: sc->sc_br->tx_cfg = 0;
! 332: while (sc->sc_br->tx_cfg != 0 && --tries)
! 333: DELAY(20);
! 334:
! 335: tries = 32;
! 336: sc->sc_br->rx_cfg = 0;
! 337: while (sc->sc_br->rx_cfg != 0 && --tries)
! 338: DELAY(20);
! 339: }
! 340:
! 341: /*
! 342: * Reset interface.
! 343: */
! 344: void
! 345: bereset(sc)
! 346: struct besoftc *sc;
! 347: {
! 348: int s;
! 349:
! 350: s = splnet();
! 351: bestop(sc);
! 352: beinit(sc);
! 353: splx(s);
! 354: }
! 355:
! 356: void
! 357: bewatchdog(ifp)
! 358: struct ifnet *ifp;
! 359: {
! 360: struct besoftc *sc = ifp->if_softc;
! 361:
! 362: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
! 363: ++sc->sc_arpcom.ac_if.if_oerrors;
! 364:
! 365: bereset(sc);
! 366: }
! 367:
! 368: int
! 369: beintr(v)
! 370: void *v;
! 371: {
! 372: struct besoftc *sc = (struct besoftc *)v;
! 373: u_int32_t whyq, whyb, whyc;
! 374: int r = 0;
! 375:
! 376: whyq = sc->sc_qr->stat; /* qec status */
! 377: whyc = sc->sc_cr->stat; /* be channel status */
! 378: whyb = sc->sc_br->stat; /* be status */
! 379:
! 380: if (whyq & QEC_STAT_BM)
! 381: r |= beeint(sc, whyb);
! 382:
! 383: if (whyq & QEC_STAT_ER)
! 384: r |= beqint(sc, whyc);
! 385:
! 386: if (sc->sc_tx_intr && (whyq & QEC_STAT_TX) && (whyc & BE_CR_STAT_TXIRQ))
! 387: r |= betint(sc);
! 388:
! 389: if (whyq & QEC_STAT_RX && whyc & BE_CR_STAT_RXIRQ)
! 390: r |= berint(sc);
! 391:
! 392: return (r);
! 393: }
! 394:
! 395: /*
! 396: * QEC Interrupt.
! 397: */
! 398: int
! 399: beqint(sc, why)
! 400: struct besoftc *sc;
! 401: u_int32_t why;
! 402: {
! 403: int r = 0, rst = 0;
! 404:
! 405: if (why & BE_CR_STAT_TXIRQ)
! 406: r |= 1;
! 407: if (why & BE_CR_STAT_RXIRQ)
! 408: r |= 1;
! 409:
! 410: if (why & BE_CR_STAT_ERRORS) {
! 411: r |= 1;
! 412: rst = 1;
! 413: }
! 414:
! 415: if (rst || r == 0) {
! 416: printf("%s:%s qstat=%b\n", sc->sc_dev.dv_xname,
! 417: (r) ? "" : " unexpected",
! 418: why, BE_CR_STAT_BITS);
! 419: printf("%s: resetting\n", sc->sc_dev.dv_xname);
! 420: bereset(sc);
! 421: }
! 422:
! 423: return r;
! 424: }
! 425:
! 426: /*
! 427: * Error interrupt.
! 428: */
! 429: int
! 430: beeint(sc, why)
! 431: struct besoftc *sc;
! 432: u_int32_t why;
! 433: {
! 434: int r = 0;
! 435:
! 436: if (why & (BE_BR_STAT_RFIFOVF | BE_BR_STAT_TFIFO_UND |
! 437: BE_BR_STAT_MAXPKTERR)) {
! 438: r |= 1;
! 439: }
! 440:
! 441: printf("%s:%s stat=%b\n", sc->sc_dev.dv_xname,
! 442: (r) ? "" : " unexpected", why, BE_BR_STAT_BITS);
! 443:
! 444: printf("%s: resetting\n", sc->sc_dev.dv_xname);
! 445: bereset(sc);
! 446:
! 447: return r;
! 448: }
! 449:
! 450: void
! 451: be_tx_harvest(sc)
! 452: struct besoftc *sc;
! 453: {
! 454: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 455: int bix, cnt;
! 456: struct be_txd txd;
! 457:
! 458: bix = sc->sc_first_td;
! 459: cnt = sc->sc_no_td;
! 460:
! 461: for (;;) {
! 462: if (cnt <= 0)
! 463: break;
! 464:
! 465: txd.tx_flags = sc->sc_desc->be_txd[bix].tx_flags;
! 466:
! 467: if (txd.tx_flags & BE_TXD_OWN)
! 468: break;
! 469:
! 470: ifp->if_opackets++;
! 471:
! 472: if (++bix == BE_TX_RING_MAXSIZE)
! 473: bix = 0;
! 474:
! 475: --cnt;
! 476: }
! 477:
! 478: if (cnt <= 0)
! 479: ifp->if_timer = 0;
! 480:
! 481: if (sc->sc_no_td != cnt) {
! 482: sc->sc_first_td = bix;
! 483: sc->sc_no_td = cnt;
! 484: ifp->if_flags &= ~IFF_OACTIVE;
! 485: }
! 486:
! 487: if (sc->sc_no_td < BE_TX_LOW_WATER) {
! 488: /* turn off interrupt */
! 489: sc->sc_tx_intr = 0;
! 490: sc->sc_cr->timask = 0xffffffff;
! 491: }
! 492: }
! 493:
! 494: /*
! 495: * Transmit interrupt.
! 496: */
! 497: int
! 498: betint(sc)
! 499: struct besoftc *sc;
! 500: {
! 501: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 502:
! 503: bestart(ifp);
! 504: return (1);
! 505: }
! 506:
! 507: /*
! 508: * Receive interrupt.
! 509: */
! 510: int
! 511: berint(sc)
! 512: struct besoftc *sc;
! 513: {
! 514: int bix, len;
! 515:
! 516: bix = sc->sc_last_rd;
! 517:
! 518: /*
! 519: * Process all buffers with valid data.
! 520: */
! 521: for (;;) {
! 522: if (sc->sc_desc->be_rxd[bix].rx_flags & BE_RXD_OWN)
! 523: break;
! 524:
! 525: len = sc->sc_desc->be_rxd[bix].rx_flags & BE_RXD_LENGTH;
! 526: be_read(sc, bix, len);
! 527:
! 528: sc->sc_desc->be_rxd[(bix + BE_RX_RING_SIZE) & BE_RX_RING_MAXMASK].rx_flags =
! 529: BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH);
! 530:
! 531: if (++bix == BE_RX_RING_MAXSIZE)
! 532: bix = 0;
! 533: }
! 534:
! 535: sc->sc_last_rd = bix;
! 536:
! 537: return 1;
! 538: }
! 539:
! 540: void
! 541: betick(vsc)
! 542: void *vsc;
! 543: {
! 544: struct besoftc *sc = vsc;
! 545: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 546: struct be_bregs *br = sc->sc_br;
! 547: int s;
! 548:
! 549: s = splnet();
! 550: /*
! 551: * Get collision counters
! 552: */
! 553: ifp->if_collisions += br->nc_ctr + br->fc_ctr + br->ex_ctr + br->lt_ctr;
! 554: br->nc_ctr = 0;
! 555: br->fc_ctr = 0;
! 556: br->ex_ctr = 0;
! 557: br->lt_ctr = 0;
! 558: bestart(ifp);
! 559: splx(s);
! 560: timeout_add(&sc->sc_tick, hz);
! 561: }
! 562:
! 563: int
! 564: beioctl(ifp, cmd, data)
! 565: struct ifnet *ifp;
! 566: u_long cmd;
! 567: caddr_t data;
! 568: {
! 569: struct besoftc *sc = ifp->if_softc;
! 570: struct ifaddr *ifa = (struct ifaddr *)data;
! 571: struct ifreq *ifr = (struct ifreq *)data;
! 572: int s, error = 0;
! 573:
! 574: s = splnet();
! 575:
! 576: switch (cmd) {
! 577: case SIOCSIFADDR:
! 578: ifp->if_flags |= IFF_UP;
! 579: switch (ifa->ifa_addr->sa_family) {
! 580: #ifdef INET
! 581: case AF_INET:
! 582: beinit(sc);
! 583: arp_ifinit(&sc->sc_arpcom, ifa);
! 584: break;
! 585: #endif /* INET */
! 586: default:
! 587: beinit(sc);
! 588: break;
! 589: }
! 590: break;
! 591:
! 592: case SIOCSIFFLAGS:
! 593: if ((ifp->if_flags & IFF_UP) == 0 &&
! 594: (ifp->if_flags & IFF_RUNNING) != 0) {
! 595: /*
! 596: * If interface is marked down and it is running, then
! 597: * stop it.
! 598: */
! 599: bestop(sc);
! 600: ifp->if_flags &= ~IFF_RUNNING;
! 601: } else if ((ifp->if_flags & IFF_UP) != 0 &&
! 602: (ifp->if_flags & IFF_RUNNING) == 0) {
! 603: /*
! 604: * If interface is marked up and it is stopped, then
! 605: * start it.
! 606: */
! 607: beinit(sc);
! 608: } else {
! 609: /*
! 610: * Reset the interface to pick up changes in any other
! 611: * flags that affect hardware registers.
! 612: */
! 613: bestop(sc);
! 614: beinit(sc);
! 615: }
! 616: break;
! 617:
! 618: case SIOCADDMULTI:
! 619: case SIOCDELMULTI:
! 620: error = (cmd == SIOCADDMULTI) ?
! 621: ether_addmulti(ifr, &sc->sc_arpcom):
! 622: ether_delmulti(ifr, &sc->sc_arpcom);
! 623:
! 624: if (error == ENETRESET) {
! 625: /*
! 626: * Multicast list has changed; set the hardware filter
! 627: * accordingly.
! 628: */
! 629: if (ifp->if_flags & IFF_RUNNING)
! 630: be_mcreset(sc);
! 631: error = 0;
! 632: }
! 633: break;
! 634: case SIOCGIFMEDIA:
! 635: case SIOCSIFMEDIA:
! 636: error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
! 637: break;
! 638: default:
! 639: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
! 640: splx(s);
! 641: return error;
! 642: }
! 643: error = ENOTTY;
! 644: break;
! 645: }
! 646: splx(s);
! 647: return error;
! 648: }
! 649:
! 650: void
! 651: beinit(sc)
! 652: struct besoftc *sc;
! 653: {
! 654: struct be_bregs *br = sc->sc_br;
! 655: struct be_cregs *cr = sc->sc_cr;
! 656: struct qec_softc *qec = sc->sc_qec;
! 657: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 658: int s = splnet();
! 659: int i;
! 660:
! 661: /*
! 662: * Allocate descriptor ring and buffers, if not already done
! 663: */
! 664: if (sc->sc_desc == NULL)
! 665: sc->sc_desc_dva = (struct be_desc *) dvma_malloc(
! 666: sizeof(struct be_desc), &sc->sc_desc, M_NOWAIT);
! 667: if (sc->sc_bufs == NULL)
! 668: sc->sc_bufs_dva = (struct be_bufs *) dvma_malloc(
! 669: sizeof(struct be_bufs), &sc->sc_bufs, M_NOWAIT);
! 670:
! 671: for (i = 0; i < BE_TX_RING_MAXSIZE; i++) {
! 672: sc->sc_desc->be_txd[i].tx_addr =
! 673: (u_int32_t)sc->sc_bufs_dva->tx_buf[i & BE_TX_RING_MASK];
! 674: sc->sc_desc->be_txd[i].tx_flags = 0;
! 675: }
! 676: for (i = 0; i < BE_RX_RING_MAXSIZE; i++) {
! 677: sc->sc_desc->be_rxd[i].rx_addr =
! 678: (u_int32_t)sc->sc_bufs_dva->rx_buf[i & BE_RX_RING_MASK];
! 679: if (i < BE_RX_RING_SIZE)
! 680: sc->sc_desc->be_rxd[i].rx_flags =
! 681: BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH);
! 682: else
! 683: sc->sc_desc->be_rxd[i].rx_flags = 0;
! 684: }
! 685:
! 686: sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
! 687: sc->sc_last_rd = 0;
! 688:
! 689: be_tcvr_init(sc);
! 690:
! 691: be_ifmedia_upd(ifp);
! 692:
! 693: bestop(sc);
! 694:
! 695: br->mac_addr2 = (sc->sc_arpcom.ac_enaddr[4] << 8) |
! 696: sc->sc_arpcom.ac_enaddr[5];
! 697: br->mac_addr1 = (sc->sc_arpcom.ac_enaddr[2] << 8) |
! 698: sc->sc_arpcom.ac_enaddr[3];
! 699: br->mac_addr0 = (sc->sc_arpcom.ac_enaddr[0] << 8) |
! 700: sc->sc_arpcom.ac_enaddr[1];
! 701:
! 702: br->rx_cfg = BE_BR_RXCFG_HENABLE | BE_BR_RXCFG_FIFO;
! 703:
! 704: be_mcreset(sc);
! 705:
! 706: DELAY(20);
! 707:
! 708: br->tx_cfg = BE_BR_TXCFG_FIFO;
! 709: br->rand_seed = 0xbd;
! 710:
! 711: br->xif_cfg = BE_BR_XCFG_ODENABLE | BE_BR_XCFG_RESV;
! 712:
! 713: cr->rxds = (u_int32_t)sc->sc_desc_dva->be_rxd;
! 714: cr->txds = (u_int32_t)sc->sc_desc_dva->be_txd;
! 715:
! 716: cr->rxwbufptr = cr->rxrbufptr = sc->sc_channel * qec->sc_msize;
! 717: cr->txwbufptr = cr->txrbufptr = cr->rxrbufptr + qec->sc_rsize;
! 718:
! 719: /*
! 720: * Turn off counter expiration interrupts as well as
! 721: * 'gotframe' and 'sentframe'
! 722: */
! 723: br->imask = BE_BR_IMASK_GOTFRAME |
! 724: BE_BR_IMASK_RCNTEXP |
! 725: BE_BR_IMASK_ACNTEXP |
! 726: BE_BR_IMASK_CCNTEXP |
! 727: BE_BR_IMASK_LCNTEXP |
! 728: BE_BR_IMASK_CVCNTEXP |
! 729: BE_BR_IMASK_SENTFRAME |
! 730: BE_BR_IMASK_NCNTEXP |
! 731: BE_BR_IMASK_ECNTEXP |
! 732: BE_BR_IMASK_LCCNTEXP |
! 733: BE_BR_IMASK_FCNTEXP |
! 734: BE_BR_IMASK_DTIMEXP;
! 735:
! 736: cr->rimask = 0;
! 737:
! 738: /* disable tx interrupts initially */
! 739: cr->timask = 0xffffffff;
! 740: sc->sc_tx_intr = 0;
! 741:
! 742: cr->qmask = 0;
! 743: cr->bmask = 0;
! 744:
! 745: br->jsize = 4;
! 746:
! 747: cr->ccnt = 0;
! 748:
! 749: br->tx_cfg |= BE_BR_TXCFG_ENABLE;
! 750: br->rx_cfg |= BE_BR_RXCFG_ENABLE;
! 751:
! 752: ifp->if_flags |= IFF_RUNNING;
! 753: ifp->if_flags &= ~IFF_OACTIVE;
! 754: splx(s);
! 755:
! 756: timeout_add(&sc->sc_tick, hz);
! 757: bestart(ifp);
! 758: }
! 759:
! 760: /*
! 761: * Set the tcvr to an idle state
! 762: */
! 763: void
! 764: be_tcvr_idle(sc)
! 765: struct besoftc *sc;
! 766: {
! 767: struct be_tregs *tr = sc->sc_tr;
! 768: volatile u_int32_t x;
! 769: int i = 20;
! 770:
! 771: while (i--) {
! 772: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
! 773: MGMT_PAL_OENAB;
! 774: x = tr->mgmt_pal;
! 775: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
! 776: MGMT_PAL_OENAB | MGMT_PAL_DCLOCK;
! 777: x = tr->mgmt_pal;
! 778: }
! 779: }
! 780:
! 781: /*
! 782: * Initialize the transceiver and figure out whether we're using the
! 783: * external or internal one.
! 784: */
! 785: void
! 786: be_tcvr_init(sc)
! 787: struct besoftc *sc;
! 788: {
! 789: volatile u_int32_t x;
! 790: struct be_tregs *tr = sc->sc_tr;
! 791:
! 792: be_tcvr_idle(sc);
! 793:
! 794: if (sc->sc_rev != 1) {
! 795: printf("%s: rev %d PAL not supported.\n",
! 796: sc->sc_dev.dv_xname,
! 797: sc->sc_rev);
! 798: return;
! 799: }
! 800:
! 801: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
! 802: x = tr->mgmt_pal;
! 803:
! 804: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO;
! 805: x = tr->mgmt_pal;
! 806: DELAY(200);
! 807:
! 808: if (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) {
! 809: sc->sc_tcvr_type = BE_TCVR_EXTERNAL;
! 810: tr->tcvr_pal = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE |
! 811: TCVR_PAL_LTENABLE);
! 812: x = tr->tcvr_pal;
! 813: }
! 814: else if (tr->mgmt_pal & MGMT_PAL_INT_MDIO) {
! 815: sc->sc_tcvr_type = BE_TCVR_INTERNAL;
! 816: tr->tcvr_pal = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE |
! 817: TCVR_PAL_LTENABLE | TCVR_PAL_SERIAL);
! 818: x = tr->tcvr_pal;
! 819: }
! 820: else {
! 821: printf("%s: no internal or external transceiver found.\n",
! 822: sc->sc_dev.dv_xname);
! 823: }
! 824: }
! 825:
! 826: int
! 827: be_tcvr_read(sc, reg)
! 828: struct besoftc *sc;
! 829: u_int8_t reg;
! 830: {
! 831: int phy, i;
! 832: u_int32_t ret = 0;
! 833:
! 834: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL)
! 835: phy = BE_PHY_INTERNAL;
! 836: else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL)
! 837: phy = BE_PHY_EXTERNAL;
! 838: else {
! 839: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
! 840: return BE_TCVR_READ_INVALID;
! 841: }
! 842:
! 843: be_tcvr_idle(sc);
! 844:
! 845: be_tcvr_write_bit(sc, 0);
! 846: be_tcvr_write_bit(sc, 1);
! 847: be_tcvr_write_bit(sc, 1);
! 848: be_tcvr_write_bit(sc, 0);
! 849:
! 850: for (i = 4; i >= 0; i--)
! 851: be_tcvr_write_bit(sc, (phy >> i) & 1);
! 852:
! 853: for (i = 4; i >= 0; i--)
! 854: be_tcvr_write_bit(sc, (reg >> i) & 1);
! 855:
! 856: if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
! 857: (void) be_tcvr_read_bit2(sc);
! 858: (void) be_tcvr_read_bit2(sc);
! 859:
! 860: for (i = 15; i >= 0; i--) {
! 861: int b;
! 862:
! 863: b = be_tcvr_read_bit2(sc);
! 864: ret |= (b & 1) << i;
! 865: }
! 866:
! 867: (void) be_tcvr_read_bit2(sc);
! 868: (void) be_tcvr_read_bit2(sc);
! 869: (void) be_tcvr_read_bit2(sc);
! 870: }
! 871: else {
! 872: (void) be_tcvr_read_bit1(sc);
! 873: (void) be_tcvr_read_bit1(sc);
! 874:
! 875: for (i = 15; i >= 0; i--) {
! 876: int b;
! 877:
! 878: b = be_tcvr_read_bit1(sc);
! 879: ret |= (b & 1) << i;
! 880: }
! 881:
! 882: (void) be_tcvr_read_bit1(sc);
! 883: (void) be_tcvr_read_bit1(sc);
! 884: (void) be_tcvr_read_bit1(sc);
! 885: }
! 886: return ret;
! 887: }
! 888:
! 889: int
! 890: be_tcvr_read_bit1(sc)
! 891: struct besoftc *sc;
! 892: {
! 893: volatile u_int32_t x;
! 894: struct be_tregs *tr = sc->sc_tr;
! 895: int ret = 0;
! 896:
! 897: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
! 898: tr->mgmt_pal = MGMT_PAL_EXT_MDIO;
! 899: x = tr->mgmt_pal;
! 900: tr->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
! 901: x = tr->mgmt_pal;
! 902: DELAY(20);
! 903: ret = (tr->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
! 904: } else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
! 905: tr->mgmt_pal = MGMT_PAL_INT_MDIO;
! 906: x = tr->mgmt_pal;
! 907: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
! 908: x = tr->mgmt_pal;
! 909: DELAY(20);
! 910: ret = (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
! 911: } else {
! 912: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
! 913: }
! 914: return (ret & 1);
! 915: }
! 916:
! 917: int
! 918: be_tcvr_read_bit2(sc)
! 919: struct besoftc *sc;
! 920: {
! 921: volatile u_int32_t x;
! 922: struct be_tregs *tr = sc->sc_tr;
! 923: int ret = 0;
! 924:
! 925: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
! 926: tr->mgmt_pal = MGMT_PAL_EXT_MDIO;
! 927: x = tr->mgmt_pal;
! 928: DELAY(20);
! 929: ret = (tr->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
! 930: tr->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
! 931: x = tr->mgmt_pal;
! 932: } else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
! 933: tr->mgmt_pal = MGMT_PAL_INT_MDIO;
! 934: x = tr->mgmt_pal;
! 935: DELAY(20);
! 936: ret = (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
! 937: tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
! 938: x = tr->mgmt_pal;
! 939: } else {
! 940: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
! 941: }
! 942: return ret;
! 943: }
! 944:
! 945: void
! 946: be_tcvr_write(sc, reg, val)
! 947: struct besoftc *sc;
! 948: u_int8_t reg;
! 949: u_int16_t val;
! 950: {
! 951: int phy, i;
! 952:
! 953: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL)
! 954: phy = BE_PHY_INTERNAL;
! 955: else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL)
! 956: phy = BE_PHY_EXTERNAL;
! 957: else {
! 958: printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
! 959: return;
! 960: }
! 961:
! 962: be_tcvr_idle(sc);
! 963:
! 964: be_tcvr_write_bit(sc, 0);
! 965: be_tcvr_write_bit(sc, 1);
! 966: be_tcvr_write_bit(sc, 0);
! 967: be_tcvr_write_bit(sc, 1);
! 968:
! 969: for (i = 4; i >= 0; i--)
! 970: be_tcvr_write_bit(sc, (phy >> i) & 1);
! 971:
! 972: for (i = 4; i >= 0; i--)
! 973: be_tcvr_write_bit(sc, (reg >> i) & 1);
! 974:
! 975: be_tcvr_write_bit(sc, 1);
! 976: be_tcvr_write_bit(sc, 0);
! 977:
! 978: for (i = 15; i >= 0; i--)
! 979: be_tcvr_write_bit(sc, (val >> i) & 1);
! 980: }
! 981:
! 982: void
! 983: be_tcvr_write_bit(sc, bit)
! 984: struct besoftc *sc;
! 985: int bit;
! 986: {
! 987: volatile u_int32_t x;
! 988:
! 989: if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
! 990: bit = ((bit & 1) << 3) | MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO;
! 991: sc->sc_tr->mgmt_pal = bit;
! 992: x = sc->sc_tr->mgmt_pal;
! 993: sc->sc_tr->mgmt_pal = bit | MGMT_PAL_DCLOCK;
! 994: x = sc->sc_tr->mgmt_pal;
! 995: } else {
! 996: bit = ((bit & 1) << 2) | MGMT_PAL_OENAB | MGMT_PAL_INT_MDIO;
! 997: sc->sc_tr->mgmt_pal = bit;
! 998: x = sc->sc_tr->mgmt_pal;
! 999: sc->sc_tr->mgmt_pal = bit | MGMT_PAL_DCLOCK;
! 1000: x = sc->sc_tr->mgmt_pal;
! 1001: }
! 1002: }
! 1003:
! 1004: /*
! 1005: * Pass a packet to the higher levels.
! 1006: */
! 1007: void
! 1008: be_read(sc, idx, len)
! 1009: struct besoftc *sc;
! 1010: int idx, len;
! 1011: {
! 1012: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1013: struct mbuf *m;
! 1014:
! 1015: if (len <= sizeof(struct ether_header) ||
! 1016: len > ETHERMTU + sizeof(struct ether_header)) {
! 1017:
! 1018: printf("%s: invalid packet size %d; dropping\n",
! 1019: ifp->if_xname, len);
! 1020:
! 1021: ifp->if_ierrors++;
! 1022: return;
! 1023: }
! 1024:
! 1025: /*
! 1026: * Pull packet off interface.
! 1027: */
! 1028: m = qec_get(ifp, sc->sc_bufs->rx_buf[idx & BE_RX_RING_MASK], len);
! 1029: if (m == NULL) {
! 1030: ifp->if_ierrors++;
! 1031: return;
! 1032: }
! 1033: ifp->if_ipackets++;
! 1034:
! 1035:
! 1036: #if NBPFILTER > 0
! 1037: /*
! 1038: * Check if there's a BPF listener on this interface.
! 1039: * If so, hand off the raw packet to BPF.
! 1040: */
! 1041: if (ifp->if_bpf)
! 1042: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 1043: #endif
! 1044: /* Pass the packet up. */
! 1045: ether_input_mbuf(ifp, m);
! 1046: }
! 1047:
! 1048: /*
! 1049: * Get current media settings.
! 1050: */
! 1051: void
! 1052: be_ifmedia_sts(ifp, ifmr)
! 1053: struct ifnet *ifp;
! 1054: struct ifmediareq *ifmr;
! 1055: {
! 1056: struct besoftc *sc = ifp->if_softc;
! 1057: int bmcr, bmsr;
! 1058:
! 1059: bmcr = be_tcvr_read(sc, PHY_BMCR);
! 1060:
! 1061: switch (bmcr & (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX)) {
! 1062: case (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX):
! 1063: ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
! 1064: break;
! 1065: case PHY_BMCR_SPEED:
! 1066: ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_HDX;
! 1067: break;
! 1068: case PHY_BMCR_DUPLEX:
! 1069: ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_FDX;
! 1070: break;
! 1071: case 0:
! 1072: ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_HDX;
! 1073: break;
! 1074: }
! 1075:
! 1076: bmsr = be_tcvr_read(sc, PHY_BMSR);
! 1077: if (bmsr & PHY_BMSR_LINKSTATUS)
! 1078: ifmr->ifm_status |= IFM_AVALID | IFM_ACTIVE;
! 1079: else {
! 1080: ifmr->ifm_status |= IFM_AVALID;
! 1081: ifmr->ifm_status &= ~IFM_ACTIVE;
! 1082: }
! 1083: }
! 1084:
! 1085: /*
! 1086: * Set media options.
! 1087: */
! 1088: int
! 1089: be_ifmedia_upd(ifp)
! 1090: struct ifnet *ifp;
! 1091: {
! 1092: struct besoftc *sc = ifp->if_softc;
! 1093: struct ifmedia *ifm = &sc->sc_ifmedia;
! 1094: int bmcr, tries;
! 1095:
! 1096: if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
! 1097: return (EINVAL);
! 1098:
! 1099: be_tcvr_write(sc, PHY_BMCR,
! 1100: PHY_BMCR_LOOPBACK | PHY_BMCR_PDOWN | PHY_BMCR_ISOLATE);
! 1101: be_tcvr_write(sc, PHY_BMCR, PHY_BMCR_RESET);
! 1102:
! 1103: for (tries = 16; tries >= 0; tries--) {
! 1104: bmcr = be_tcvr_read(sc, PHY_BMCR);
! 1105: if ((bmcr & PHY_BMCR_RESET) == 0)
! 1106: break;
! 1107: DELAY(20);
! 1108: }
! 1109: if (tries == 0) {
! 1110: printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname);
! 1111: return (EIO);
! 1112: }
! 1113:
! 1114: bmcr = be_tcvr_read(sc, PHY_BMCR);
! 1115:
! 1116: if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_T4) {
! 1117: bmcr |= PHY_BMCR_SPEED;
! 1118: bmcr &= ~PHY_BMCR_DUPLEX;
! 1119: }
! 1120:
! 1121: if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
! 1122: bmcr |= PHY_BMCR_SPEED;
! 1123: }
! 1124:
! 1125: if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) {
! 1126: bmcr &= ~PHY_BMCR_SPEED;
! 1127: }
! 1128:
! 1129: if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
! 1130: bmcr |= PHY_BMCR_DUPLEX;
! 1131: sc->sc_br->tx_cfg |= BE_BR_TXCFG_FULLDPLX;
! 1132: }
! 1133: else {
! 1134: bmcr &= ~PHY_BMCR_DUPLEX;
! 1135: sc->sc_br->tx_cfg &= ~BE_BR_TXCFG_FULLDPLX;
! 1136: }
! 1137:
! 1138: be_tcvr_write(sc, PHY_BMCR, bmcr & (~PHY_BMCR_ISOLATE));
! 1139:
! 1140: for (tries = 32; tries >= 0; tries--) {
! 1141: bmcr = be_tcvr_read(sc, PHY_BMCR);
! 1142: if ((bmcr & PHY_BMCR_ISOLATE) == 0)
! 1143: break;
! 1144: DELAY(20);
! 1145: }
! 1146: if (tries == 0) {
! 1147: printf("%s: bmcr unisolate failed\n", sc->sc_dev.dv_xname);
! 1148: return (EIO);
! 1149: }
! 1150:
! 1151: return (0);
! 1152: }
! 1153:
! 1154: void
! 1155: be_mcreset(sc)
! 1156: struct besoftc *sc;
! 1157: {
! 1158: struct arpcom *ac = &sc->sc_arpcom;
! 1159: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1160: struct be_bregs *br = sc->sc_br;
! 1161: u_int32_t crc;
! 1162: u_int16_t hash[4];
! 1163: u_int8_t octet;
! 1164: int i, j;
! 1165: struct ether_multi *enm;
! 1166: struct ether_multistep step;
! 1167:
! 1168: if (ifp->if_flags & IFF_PROMISC) {
! 1169: br->rx_cfg |= BE_BR_RXCFG_PMISC;
! 1170: return;
! 1171: }
! 1172: else
! 1173: br->rx_cfg &= ~BE_BR_RXCFG_PMISC;
! 1174:
! 1175: if (ifp->if_flags & IFF_ALLMULTI) {
! 1176: br->htable3 = 0xffff;
! 1177: br->htable2 = 0xffff;
! 1178: br->htable1 = 0xffff;
! 1179: br->htable0 = 0xffff;
! 1180: return;
! 1181: }
! 1182:
! 1183: hash[3] = hash[2] = hash[1] = hash[0] = 0;
! 1184:
! 1185: ETHER_FIRST_MULTI(step, ac, enm);
! 1186: while (enm != NULL) {
! 1187: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
! 1188: /*
! 1189: * We must listen to a range of multicast
! 1190: * addresses. For now, just accept all
! 1191: * multicasts, rather than trying to set only
! 1192: * those filter bits needed to match the range.
! 1193: * (At this time, the only use of address
! 1194: * ranges is for IP multicast routing, for
! 1195: * which the range is big enough to require
! 1196: * all bits set.)
! 1197: */
! 1198: br->htable3 = 0xffff;
! 1199: br->htable2 = 0xffff;
! 1200: br->htable1 = 0xffff;
! 1201: br->htable0 = 0xffff;
! 1202: ifp->if_flags |= IFF_ALLMULTI;
! 1203: return;
! 1204: }
! 1205:
! 1206: crc = 0xffffffff;
! 1207:
! 1208: for (i = 0; i < ETHER_ADDR_LEN; i++) {
! 1209: octet = enm->enm_addrlo[i];
! 1210:
! 1211: for (j = 0; j < 8; j++) {
! 1212: if ((crc & 1) ^ (octet & 1)) {
! 1213: crc >>= 1;
! 1214: crc ^= MC_POLY_LE;
! 1215: }
! 1216: else
! 1217: crc >>= 1;
! 1218: octet >>= 1;
! 1219: }
! 1220: }
! 1221:
! 1222: crc >>= 26;
! 1223: hash[crc >> 4] |= 1 << (crc & 0xf);
! 1224: ETHER_NEXT_MULTI(step, enm);
! 1225: }
! 1226:
! 1227: br->htable3 = hash[3];
! 1228: br->htable2 = hash[2];
! 1229: br->htable1 = hash[1];
! 1230: br->htable0 = hash[0];
! 1231: ifp->if_flags &= ~IFF_ALLMULTI;
! 1232: }
CVSweb