[BACK]Return to hme.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / dev

Annotation of sys/arch/sparc/dev/hme.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: hme.c,v 1.55 2006/06/25 21:53:44 brad Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 1998 Jason L. Wright (jason@thought.net)
                      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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: /*
                     30:  * Driver for the Happy Meal (hme) ethernet boards
                     31:  * Based on information gleaned from reading the
                     32:  *     S/Linux driver by David Miller
                     33:  *
                     34:  * Thanks go to the University of North Carolina at Greensboro, Systems
                     35:  * and Networks Department for some of the resources used to develop
                     36:  * this driver.
                     37:  */
                     38:
                     39: #include "bpfilter.h"
                     40: #include "vlan.h"
                     41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/errno.h>
                     46: #include <sys/ioctl.h>
                     47: #include <sys/mbuf.h>
                     48: #include <sys/socket.h>
                     49: #include <sys/syslog.h>
                     50: #include <sys/device.h>
                     51: #include <sys/malloc.h>
                     52:
                     53: #include <net/if.h>
                     54: #include <net/if_dl.h>
                     55: #include <net/if_types.h>
                     56: #include <net/netisr.h>
                     57: #include <net/if_media.h>
                     58:
                     59: #ifdef INET
                     60: #include <netinet/in.h>
                     61: #include <netinet/in_systm.h>
                     62: #include <netinet/in_var.h>
                     63: #include <netinet/ip.h>
                     64: #include <netinet/if_ether.h>
                     65: #include <netinet/tcp.h>
                     66: #include <netinet/udp.h>
                     67: #endif
                     68:
                     69: #if NBPFILTER > 0
                     70: #include <net/bpf.h>
                     71: #include <net/bpfdesc.h>
                     72: #endif
                     73:
                     74: #include <machine/autoconf.h>
                     75: #include <sparc/cpu.h>
                     76: #include <sparc/sparc/cpuvar.h>
                     77: #include <sparc/dev/sbusvar.h>
                     78: #include <sparc/dev/dmareg.h>  /* for SBUS_BURST_* */
                     79: #include <dev/mii/mii.h>
                     80: #include <dev/mii/miivar.h>
                     81: #include <sparc/dev/hmereg.h>
                     82: #include <sparc/dev/hmevar.h>
                     83:
                     84: int    hmematch(struct device *, void *, void *);
                     85: void   hmeattach(struct device *, struct device *, void *);
                     86: void   hmewatchdog(struct ifnet *);
                     87: int    hmeintr(void *);
                     88: int    hmeioctl(struct ifnet *, u_long, caddr_t);
                     89: void   hmereset(struct hme_softc *);
                     90: void   hmestart(struct ifnet *);
                     91: void   hmestop(struct hme_softc *);
                     92: void   hmeinit(struct hme_softc *);
                     93: void   hme_meminit(struct hme_softc *);
                     94:
                     95: void   hme_tcvr_bb_writeb(struct hme_softc *, int);
                     96: int    hme_tcvr_bb_readb(struct hme_softc *, int);
                     97:
                     98: void   hme_poll_stop(struct hme_softc *sc);
                     99:
                    100: int    hme_rint(struct hme_softc *);
                    101: int    hme_tint(struct hme_softc *);
                    102: int    hme_mint(struct hme_softc *, u_int32_t);
                    103: int    hme_eint(struct hme_softc *, u_int32_t);
                    104:
                    105: /* TCP/UDP checksum offload support */
                    106: void   hme_rxcksum(struct mbuf *, u_int32_t);
                    107:
                    108: void   hme_reset_rx(struct hme_softc *);
                    109: void   hme_reset_tx(struct hme_softc *);
                    110:
                    111: void   hme_read(struct hme_softc *, int, int, u_int32_t);
                    112: int    hme_put(struct hme_softc *, int, struct mbuf *);
                    113:
                    114: /*
                    115:  * ifmedia glue
                    116:  */
                    117: int    hme_mediachange(struct ifnet *);
                    118: void   hme_mediastatus(struct ifnet *, struct ifmediareq *);
                    119:
                    120: /*
                    121:  * mii glue
                    122:  */
                    123: int    hme_mii_read(struct device *, int, int);
                    124: void   hme_mii_write(struct device *, int, int, int);
                    125: void   hme_mii_statchg(struct device *);
                    126:
                    127: void   hme_mcreset(struct hme_softc *);
                    128:
                    129: struct cfattach hme_ca = {
                    130:        sizeof (struct hme_softc), hmematch, hmeattach
                    131: };
                    132:
                    133: struct cfdriver hme_cd = {
                    134:        NULL, "hme", DV_IFNET
                    135: };
                    136:
                    137: int
                    138: hmematch(parent, vcf, aux)
                    139:        struct device *parent;
                    140:        void *vcf, *aux;
                    141: {
                    142:        struct cfdata *cf = vcf;
                    143:        struct confargs *ca = aux;
                    144:        register struct romaux *ra = &ca->ca_ra;
                    145:
                    146:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
                    147:            strcmp("SUNW,hme", ra->ra_name) &&
                    148:            strcmp("SUNW,qfe", ra->ra_name)) {
                    149:                return (0);
                    150:        }
                    151:        if (!sbus_testdma((struct sbus_softc *)parent, ca))
                    152:                return(0);
                    153:        return (1);
                    154: }
                    155:
                    156: void
                    157: hmeattach(parent, self, aux)
                    158:        struct device *parent, *self;
                    159:        void *aux;
                    160: {
                    161:        struct confargs *ca = aux;
                    162:        struct hme_softc *sc = (struct hme_softc *)self;
                    163:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    164:        int pri;
                    165:        struct bootpath *bp;
                    166:        /* XXX the following declaration should be elsewhere */
                    167:        extern void myetheraddr(u_char *);
                    168:
                    169:        if (ca->ca_ra.ra_nintr != 1) {
                    170:                printf(": expected 1 interrupt, got %d\n",
                    171:                        ca->ca_ra.ra_nintr);
                    172:                return;
                    173:        }
                    174:        pri = ca->ca_ra.ra_intr[0].int_pri;
                    175:
                    176:        /* map registers */
                    177:        if (ca->ca_ra.ra_nreg != 5) {
                    178:                printf(": expected 5 registers, got %d\n", ca->ca_ra.ra_nreg);
                    179:                return;
                    180:        }
                    181:        sc->sc_gr = mapiodev(&(ca->ca_ra.ra_reg[0]), 0,
                    182:                        ca->ca_ra.ra_reg[0].rr_len);
                    183:        sc->sc_txr = mapiodev(&(ca->ca_ra.ra_reg[1]), 0,
                    184:                        ca->ca_ra.ra_reg[1].rr_len);
                    185:        sc->sc_rxr = mapiodev(&(ca->ca_ra.ra_reg[2]), 0,
                    186:                        ca->ca_ra.ra_reg[2].rr_len);
                    187:        sc->sc_cr = mapiodev(&(ca->ca_ra.ra_reg[3]), 0,
                    188:                        ca->ca_ra.ra_reg[3].rr_len);
                    189:        sc->sc_tcvr = mapiodev(&(ca->ca_ra.ra_reg[4]), 0,
                    190:                        ca->ca_ra.ra_reg[4].rr_len);
                    191:
                    192:        sc->sc_node = ca->ca_ra.ra_node;
                    193:
                    194:        sc->sc_rev = getpropint(ca->ca_ra.ra_node, "hm-rev", -1);
                    195:        if (sc->sc_rev == 0xff)
                    196:                sc->sc_rev = 0xa0;
                    197:        if (sc->sc_rev == 0x20 || sc->sc_rev == 0x21)
                    198:                sc->sc_flags = HME_FLAG_20_21;
                    199:        else if (sc->sc_rev != 0xa0)
                    200:                sc->sc_flags = HME_FLAG_NOT_A0;
                    201:
                    202:        sc->sc_burst = getpropint(ca->ca_ra.ra_node, "burst-sizes", -1);
                    203:        if (sc->sc_burst == -1)
                    204:                sc->sc_burst = ((struct sbus_softc *)parent)->sc_burst;
                    205:
                    206:        /* Clamp at parent's burst sizes */
                    207:        sc->sc_burst &= ((struct sbus_softc *)parent)->sc_burst;
                    208:
                    209:        hme_meminit(sc);
                    210:
                    211:        sc->sc_ih.ih_fun = hmeintr;
                    212:        sc->sc_ih.ih_arg = sc;
                    213:        intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_NET,
                    214:            self->dv_xname);
                    215:
                    216:        /*
                    217:         * Get MAC address from card if 'local-mac-address' property exists.
                    218:         * Otherwise, use the machine's builtin MAC.
                    219:         */
                    220:        if (getprop(ca->ca_ra.ra_node, "local-mac-address",
                    221:            sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0) {
                    222:                myetheraddr(sc->sc_arpcom.ac_enaddr);
                    223:        }
                    224:
                    225:        printf(" pri %d: address %s rev %d\n", pri,
                    226:            ether_sprintf(sc->sc_arpcom.ac_enaddr), sc->sc_rev);
                    227:
                    228:        sc->sc_mii.mii_ifp = ifp;
                    229:        sc->sc_mii.mii_readreg = hme_mii_read;
                    230:        sc->sc_mii.mii_writereg = hme_mii_write;
                    231:        sc->sc_mii.mii_statchg = hme_mii_statchg;
                    232:        ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, hme_mediachange,
                    233:            hme_mediastatus);
                    234:        mii_phy_probe(self, &sc->sc_mii, 0xffffffff);
                    235:
                    236:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
                    237:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE,
                    238:                    0, NULL);
                    239:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE);
                    240:        }
                    241:        else
                    242:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
                    243:
                    244:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    245:        ifp->if_softc = sc;
                    246:        ifp->if_start = hmestart;
                    247:        ifp->if_ioctl = hmeioctl;
                    248:        ifp->if_watchdog = hmewatchdog;
                    249:        ifp->if_flags =
                    250:                IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    251:        sc->sc_if_flags = ifp->if_flags;
                    252:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    253:        IFQ_SET_MAXLEN(&ifp->if_snd, HME_TX_RING_SIZE);
                    254:        IFQ_SET_READY(&ifp->if_snd);
                    255:
                    256:        /* Attach the interface. */
                    257:        if_attach(ifp);
                    258:        ether_ifattach(ifp);
                    259:
                    260:        bp = ca->ca_ra.ra_bp;
                    261:        if (bp != NULL && sc->sc_dev.dv_unit == bp->val[1] &&
                    262:            ((strcmp(bp->name, hme_cd.cd_name) == 0) ||
                    263:             (strcmp(bp->name, "qfe") == 0) ||
                    264:             (strcmp(bp->name, "SUNW,hme") == 0)))
                    265:                bp->dev = &sc->sc_dev;
                    266: }
                    267:
                    268: /*
                    269:  * Start output on interface.
                    270:  * We make two assumptions here:
                    271:  *  1) that the current priority is set to splnet _before_ this code
                    272:  *     is called *and* is returned to the appropriate priority after
                    273:  *     return
                    274:  *  2) that the IFF_OACTIVE flag is checked before this code is called
                    275:  *     (i.e. that the output part of the interface is idle)
                    276:  */
                    277: void
                    278: hmestart(ifp)
                    279:        struct ifnet *ifp;
                    280: {
                    281:        struct hme_softc *sc = ifp->if_softc;
                    282:        struct mbuf *m;
                    283:        int bix, len;
                    284:
                    285:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    286:                return;
                    287:
                    288:        bix = sc->sc_last_td;
                    289:
                    290:        for (;;) {
                    291:                IFQ_DEQUEUE(&ifp->if_snd, m);
                    292:                if (m == NULL)
                    293:                        break;
                    294: #if NBPFILTER > 0
                    295:                /*
                    296:                 * If BPF is listening on this interface, let it see the
                    297:                 * packet before we commit it to the wire.
                    298:                 */
                    299:                if (ifp->if_bpf)
                    300:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
                    301: #endif
                    302:
                    303:                /*
                    304:                 * Copy the mbuf chain into the transmit buffer.
                    305:                 */
                    306:                len = hme_put(sc, bix, m);
                    307:
                    308:                /*
                    309:                 * Initialize transmit registers and start transmission.
                    310:                 */
                    311:                sc->sc_desc->hme_txd[bix].tx_flags =
                    312:                    HME_TXD_OWN | HME_TXD_SOP | HME_TXD_EOP |
                    313:                    (len & HME_TXD_SIZE);
                    314:                sc->sc_txr->tx_pnding = TXR_TP_DMAWAKEUP;
                    315:
                    316:                if (++bix == HME_TX_RING_SIZE)
                    317:                        bix = 0;
                    318:
                    319:                if (++sc->sc_no_td == HME_TX_RING_SIZE) {
                    320:                        ifp->if_flags |= IFF_OACTIVE;
                    321:                        break;
                    322:                }
                    323:        }
                    324:
                    325:        sc->sc_last_td = bix;
                    326: }
                    327:
                    328: #define MAX_STOP_TRIES 16
                    329:
                    330: void
                    331: hmestop(sc)
                    332:        struct hme_softc *sc;
                    333: {
                    334:        int tries = 0;
                    335:
                    336:        sc->sc_gr->reset = GR_RESET_ALL;
                    337:        while (sc->sc_gr->reset && (++tries != MAX_STOP_TRIES))
                    338:                DELAY(20);
                    339:        if (tries == MAX_STOP_TRIES)
                    340:                printf("%s: stop failed\n", sc->sc_dev.dv_xname);
                    341:        sc->sc_mii.mii_media_status &= ~IFM_ACTIVE;
                    342: }
                    343:
                    344: /*
                    345:  * Reset interface.
                    346:  */
                    347: void
                    348: hmereset(sc)
                    349:        struct hme_softc *sc;
                    350: {
                    351:        int s;
                    352:
                    353:        s = splnet();
                    354:        hmestop(sc);
                    355:        hmeinit(sc);
                    356:        splx(s);
                    357: }
                    358:
                    359: /*
                    360:  * Device timeout/watchdog routine. Entered if the device neglects to generate
                    361:  * an interrupt after a transmit has been started on it.
                    362:  */
                    363: void
                    364: hmewatchdog(ifp)
                    365:        struct ifnet *ifp;
                    366: {
                    367:        struct hme_softc *sc = ifp->if_softc;
                    368:
                    369:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    370:        ++sc->sc_arpcom.ac_if.if_oerrors;
                    371:
                    372:        hmereset(sc);
                    373: }
                    374:
                    375: int
                    376: hmeioctl(ifp, cmd, data)
                    377:        struct ifnet *ifp;
                    378:        u_long cmd;
                    379:        caddr_t data;
                    380: {
                    381:        struct hme_softc *sc = ifp->if_softc;
                    382:        struct ifaddr *ifa = (struct ifaddr *)data;
                    383:        struct ifreq *ifr = (struct ifreq *)data;
                    384:        int s, error = 0;
                    385:
                    386:        s = splnet();
                    387:
                    388:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
                    389:                splx(s);
                    390:                return (error);
                    391:        }
                    392:
                    393:        switch (cmd) {
                    394:        case SIOCSIFADDR:
                    395:                switch (ifa->ifa_addr->sa_family) {
                    396: #ifdef INET
                    397:                case AF_INET:
                    398:                        if (ifp->if_flags & IFF_UP)
                    399:                                hme_mcreset(sc);
                    400:                        else {
                    401:                                ifp->if_flags |= IFF_UP;
                    402:                                hmeinit(sc);
                    403:                        }
                    404:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    405:                        break;
                    406: #endif /* INET */
                    407:                default:
                    408:                        ifp->if_flags |= IFF_UP;
                    409:                        hmeinit(sc);
                    410:                        break;
                    411:                }
                    412:                break;
                    413:
                    414:        case SIOCSIFFLAGS:
                    415:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    416:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    417:                        /*
                    418:                         * If interface is marked down and it is running, then
                    419:                         * stop it.
                    420:                         */
                    421:                        hmestop(sc);
                    422:                        ifp->if_flags &= ~IFF_RUNNING;
                    423:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    424:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                    425:                        /*
                    426:                         * If interface is marked up and it is stopped, then
                    427:                         * start it.
                    428:                         */
                    429:                        hmeinit(sc);
                    430:                } else {
                    431:                        /*
                    432:                         * If setting debug or promiscuous mode, do not reset
                    433:                         * the chip; for everything else, call hmeinit()
                    434:                         * which will trigger a reset.
                    435:                         */
                    436: #define RESETIGN (IFF_CANTCHANGE | IFF_DEBUG)
                    437:                        if (ifp->if_flags == sc->sc_if_flags)
                    438:                                break;
                    439:                        if ((ifp->if_flags & (~RESETIGN))
                    440:                            == (sc->sc_if_flags & (~RESETIGN)))
                    441:                                hme_mcreset(sc);
                    442:                        else
                    443:                                hmeinit(sc);
                    444: #undef RESETIGN
                    445:                }
                    446:                break;
                    447:
                    448:        case SIOCADDMULTI:
                    449:        case SIOCDELMULTI:
                    450:                error = (cmd == SIOCADDMULTI) ?
                    451:                        ether_addmulti(ifr, &sc->sc_arpcom):
                    452:                        ether_delmulti(ifr, &sc->sc_arpcom);
                    453:
                    454:                if (error == ENETRESET) {
                    455:                        /*
                    456:                         * Multicast list has changed; set the hardware filter
                    457:                         * accordingly.
                    458:                         */
                    459:                        if (ifp->if_flags & IFF_RUNNING)
                    460:                                hme_mcreset(sc);
                    461:                        error = 0;
                    462:                }
                    463:                break;
                    464:        case SIOCGIFMEDIA:
                    465:        case SIOCSIFMEDIA:
                    466:                error = ifmedia_ioctl(ifp, ifr,  &sc->sc_mii.mii_media, cmd);
                    467:                break;
                    468:        default:
                    469:                error = ENOTTY;
                    470:        }
                    471:
                    472:        sc->sc_if_flags = ifp->if_flags;
                    473:        splx(s);
                    474:        return (error);
                    475: }
                    476:
                    477: void
                    478: hme_meminit(sc)
                    479:        struct hme_softc *sc;
                    480: {
                    481:        struct hme_desc *desc;
                    482:        int i;
                    483:
                    484:        if (sc->sc_desc_dva == NULL)
                    485:                sc->sc_desc_dva = (struct hme_desc *) dvma_malloc(
                    486:                    sizeof(struct hme_desc), &sc->sc_desc, M_NOWAIT);
                    487:        if (sc->sc_bufs_dva == NULL)
                    488:                sc->sc_bufs_dva = (struct hme_bufs *) dvma_malloc(
                    489:                    sizeof(struct hme_bufs), &sc->sc_bufs, M_NOWAIT);
                    490:
                    491:        desc = sc->sc_desc;
                    492:
                    493:        /*
                    494:         * Setup TX descriptors
                    495:         */
                    496:        sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
                    497:        for (i = 0; i < HME_TX_RING_SIZE; i++) {
                    498:                desc->hme_txd[i].tx_addr =
                    499:                    (u_int32_t)sc->sc_bufs_dva->tx_buf[i];
                    500:                desc->hme_txd[i].tx_flags = 0;
                    501:        }
                    502:
                    503:        /*
                    504:         * Setup RX descriptors
                    505:         */
                    506:        sc->sc_last_rd = 0;
                    507:        for (i = 0; i < HME_RX_RING_SIZE; i++) {
                    508:                desc->hme_rxd[i].rx_addr =
                    509:                    (u_int32_t)sc->sc_bufs_dva->rx_buf[i];
                    510:                desc->hme_rxd[i].rx_flags = HME_RXD_OWN |
                    511:                    ((HME_RX_PKT_BUF_SZ - HME_RX_OFFSET) << 16);
                    512:        }
                    513: }
                    514:
                    515: void
                    516: hmeinit(sc)
                    517:        struct hme_softc *sc;
                    518: {
                    519:        u_int32_t c, n;
                    520:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    521:        struct hme_tcvr *tcvr = sc->sc_tcvr;
                    522:        struct hme_cr *cr = sc->sc_cr;
                    523:        struct hme_gr *gr = sc->sc_gr;
                    524:        struct hme_txr *txr = sc->sc_txr;
                    525:        struct hme_rxr *rxr = sc->sc_rxr;
                    526:
                    527:        hme_poll_stop(sc);
                    528:        hmestop(sc);
                    529:
                    530:        hme_meminit(sc);
                    531:
                    532:        tcvr->int_mask = 0xffff;
                    533:
                    534:        c = tcvr->cfg;
                    535:        if (sc->sc_flags & HME_FLAG_FENABLE)
                    536:                tcvr->cfg = c & ~(TCVR_CFG_BENABLE);
                    537:        else
                    538:                tcvr->cfg = c | TCVR_CFG_BENABLE;
                    539:
                    540:        hme_reset_tx(sc);
                    541:        hme_reset_rx(sc);
                    542:
                    543:        cr->rand_seed = sc->sc_arpcom.ac_enaddr[5] |
                    544:            ((sc->sc_arpcom.ac_enaddr[4] << 8) & 0x3f00);
                    545:        cr->mac_addr0 = (sc->sc_arpcom.ac_enaddr[0] << 8) |
                    546:                           sc->sc_arpcom.ac_enaddr[1];
                    547:        cr->mac_addr1 = (sc->sc_arpcom.ac_enaddr[2] << 8) |
                    548:                           sc->sc_arpcom.ac_enaddr[3];
                    549:        cr->mac_addr2 = (sc->sc_arpcom.ac_enaddr[4] << 8) |
                    550:                           sc->sc_arpcom.ac_enaddr[5];
                    551:        cr->tx_pkt_max = cr->rx_pkt_max = ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN;
                    552:
                    553:        cr->jsize = HME_DEFAULT_JSIZE;
                    554:        cr->ipkt_gap1 = HME_DEFAULT_IPKT_GAP1;
                    555:        cr->ipkt_gap2 = HME_DEFAULT_IPKT_GAP2;
                    556:
                    557:        rxr->rx_ring = (u_int32_t)sc->sc_desc_dva->hme_rxd;
                    558:        txr->tx_ring = (u_int32_t)sc->sc_desc_dva->hme_txd;
                    559:
                    560:        if (sc->sc_burst & SBUS_BURST_64)
                    561:                gr->cfg = GR_CFG_BURST64;
                    562:        else if (sc->sc_burst & SBUS_BURST_32)
                    563:                gr->cfg = GR_CFG_BURST32;
                    564:        else if (sc->sc_burst & SBUS_BURST_16)
                    565:                gr->cfg = GR_CFG_BURST16;
                    566:        else {
                    567:                printf("%s: burst size unknown\n", sc->sc_dev.dv_xname);
                    568:                gr->cfg = 0;
                    569:        }
                    570:
                    571:        gr->imask = GR_IMASK_SENTFRAME | GR_IMASK_TXPERR |
                    572:                      GR_IMASK_GOTFRAME | GR_IMASK_RCNTEXP;
                    573:
                    574:        txr->tx_rsize = (HME_TX_RING_SIZE >> TXR_RSIZE_SHIFT) - 1;
                    575:        txr->cfg |= TXR_CFG_DMAENABLE;
                    576:
                    577:        c = RXR_CFG_DMAENABLE | (HME_RX_OFFSET << 3);
                    578:        /* RX TCP/UDP cksum offset */
                    579:        n = (ETHER_HDR_LEN + sizeof(struct ip)) / 2;
                    580:        n = (n << RXR_CFG_CSUM_SHIFT) & RXR_CFG_CSUMSTART;
                    581:        c |= n;
                    582: #if HME_RX_RING_SIZE == 32
                    583:        c |= RXR_CFG_RINGSIZE32;
                    584: #elif HME_RX_RING_SIZE == 64
                    585:        c |= RXR_CFG_RINGSIZE64;
                    586: #elif HME_RX_RING_SIZE == 128
                    587:        c |= RXR_CFG_RINGSIZE128;
                    588: #elif HME_RX_RING_SIZE == 256
                    589:        c |= RXR_CFG_RINGSIZE256;
                    590: #else
                    591: #error "HME_RX_RING_SIZE must be 32, 64, 128, or 256."
                    592: #endif
                    593:        rxr->cfg = c;
                    594:        DELAY(20);
                    595:        if (c != rxr->cfg)      /* the receiver sometimes misses bits */
                    596:                printf("%s: setting rxreg->cfg failed.\n", sc->sc_dev.dv_xname);
                    597:
                    598:        cr->rx_cfg = 0;
                    599:        hme_mcreset(sc);
                    600:        DELAY(10);
                    601:
                    602:        cr->tx_cfg |= CR_TXCFG_DGIVEUP;
                    603:
                    604:        c = CR_XCFG_ODENABLE;
                    605:        if (sc->sc_flags & HME_FLAG_LANCE)
                    606:                c |= (HME_DEFAULT_IPKT_GAP0 << 5) | CR_XCFG_LANCE;
                    607:        cr->xif_cfg = c;
                    608:
                    609:        cr->tx_cfg |= CR_TXCFG_ENABLE;  /* enable tx */
                    610:        cr->rx_cfg |= CR_RXCFG_ENABLE;  /* enable rx */
                    611:
                    612:        mii_mediachg(&sc->sc_mii);
                    613:
                    614:        ifp->if_flags |= IFF_RUNNING;
                    615:        ifp->if_flags &= ~IFF_OACTIVE;
                    616:        sc->sc_if_flags = ifp->if_flags;
                    617:        ifp->if_timer = 0;
                    618: }
                    619:
                    620: void
                    621: hme_poll_stop(sc)
                    622:        struct hme_softc *sc;
                    623: {
                    624:        struct hme_tcvr *tcvr = sc->sc_tcvr;
                    625:
                    626:        /* if not polling, or polling not enabled, we're done. */
                    627:        if ((sc->sc_flags & (HME_FLAG_POLLENABLE | HME_FLAG_POLL)) !=
                    628:            (HME_FLAG_POLLENABLE | HME_FLAG_POLL))
                    629:                return;
                    630:
                    631:        /* Turn off MIF interrupts, and disable polling */
                    632:        tcvr->int_mask = 0xffff;
                    633:        tcvr->cfg &= ~(TCVR_CFG_PENABLE);
                    634:        sc->sc_flags &= ~(HME_FLAG_POLL);
                    635:        DELAY(200);
                    636: }
                    637:
                    638: #define RESET_TRIES    32
                    639:
                    640: void
                    641: hme_reset_tx(sc)
                    642:        struct hme_softc *sc;
                    643: {
                    644:        int tries = RESET_TRIES;
                    645:        struct hme_cr *cr = sc->sc_cr;
                    646:
                    647:        cr->tx_swreset = 0;
                    648:        while (--tries && (cr->tx_swreset & 1))
                    649:                DELAY(20);
                    650:
                    651:        if (!tries)
                    652:                printf("%s: reset tx failed\n", sc->sc_dev.dv_xname);
                    653: }
                    654:
                    655: void
                    656: hme_reset_rx(sc)
                    657:        struct hme_softc *sc;
                    658: {
                    659:        int tries = RESET_TRIES;
                    660:        struct hme_cr *cr = sc->sc_cr;
                    661:
                    662:        cr->rx_swreset = 0;
                    663:        while (--tries && (cr->rx_swreset & 1))
                    664:                DELAY(20);
                    665:
                    666:        if (!tries)
                    667:                printf("%s: reset rx failed\n", sc->sc_dev.dv_xname);
                    668: }
                    669:
                    670: /*
                    671:  * mif interrupt
                    672:  */
                    673: int
                    674: hme_mint(sc, why)
                    675:        struct hme_softc *sc;
                    676:        u_int32_t why;
                    677: {
                    678:        printf("%s: link status changed\n", sc->sc_dev.dv_xname);
                    679:        hme_poll_stop(sc);
                    680:        return (1);
                    681: }
                    682:
                    683: /*
                    684:  * transmit interrupt
                    685:  */
                    686: int
                    687: hme_tint(sc)
                    688:        struct hme_softc *sc;
                    689: {
                    690:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    691:        struct hme_cr *cr = sc->sc_cr;
                    692:        int bix;
                    693:        struct hme_txd txd;
                    694:
                    695:        /*
                    696:         * Get collision counters
                    697:         */
                    698:        ifp->if_collisions += cr->ex_ctr + cr->lt_ctr + cr->fc_ctr + cr->nc_ctr;
                    699:        cr->ex_ctr = 0;
                    700:        cr->lt_ctr = 0;
                    701:        cr->fc_ctr = 0;
                    702:        cr->nc_ctr = 0;
                    703:
                    704:        bix = sc->sc_first_td;
                    705:
                    706:        for (;;) {
                    707:                if (sc->sc_no_td <= 0)
                    708:                        break;
                    709:
                    710:                bcopy(&sc->sc_desc->hme_txd[bix], &txd, sizeof(txd));
                    711:
                    712:                if (txd.tx_flags & HME_TXD_OWN)
                    713:                        break;
                    714:
                    715:                ifp->if_flags &= ~IFF_OACTIVE;
                    716:                ifp->if_opackets++;
                    717:
                    718:                if (++bix == HME_TX_RING_SIZE)
                    719:                        bix = 0;
                    720:
                    721:                --sc->sc_no_td;
                    722:        }
                    723:
                    724:        sc->sc_first_td = bix;
                    725:
                    726:        hmestart(ifp);
                    727:
                    728:        if (sc->sc_no_td == 0)
                    729:                ifp->if_timer = 0;
                    730:
                    731:        return (1);
                    732: }
                    733:
                    734: /*
                    735:  * XXX layering violation
                    736:  *
                    737:  * If we can have additional csum data member in 'struct pkthdr' for
                    738:  * these incomplete checksum offload capable hardware, things would be
                    739:  * much simpler. That member variable will carry partial checksum
                    740:  * data and it may be evaluated in TCP/UDP input handler after
                    741:  * computing pseudo header checksumming.
                    742:  */
                    743: void
                    744: hme_rxcksum(struct mbuf *m, u_int32_t flags)
                    745: {
                    746:        struct ether_header *eh;
                    747:        struct ip *ip;
                    748:        struct udphdr *uh;
                    749:        int32_t hlen, len, pktlen;
                    750:        u_int16_t cksum, *opts;
                    751:        u_int32_t temp32;
                    752:        union pseudoh {
                    753:                struct hdr {
                    754:                        u_int16_t len;
                    755:                        u_int8_t ttl;
                    756:                        u_int8_t proto;
                    757:                        u_int32_t src;
                    758:                        u_int32_t dst;
                    759:                } h;
                    760:                u_int16_t w[6];
                    761:        } ph;
                    762:
                    763:        pktlen = m->m_pkthdr.len;
                    764:        if (pktlen < sizeof(struct ether_header))
                    765:                return;
                    766:        eh = mtod(m, struct ether_header *);
                    767:        if (eh->ether_type != htons(ETHERTYPE_IP))
                    768:                return;
                    769:        ip = (struct ip *)(eh + 1);
                    770:        if (ip->ip_v != IPVERSION)
                    771:                return;
                    772:
                    773:        hlen = ip->ip_hl << 2;
                    774:        pktlen -= sizeof(struct ether_header);
                    775:        if (hlen < sizeof(struct ip))
                    776:                return;
                    777:        if (ntohs(ip->ip_len) < hlen)
                    778:                return;
                    779:        if (ntohs(ip->ip_len) != pktlen)
                    780:                return;
                    781:        if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
                    782:                return; /* can't handle fragmented packet */
                    783:
                    784:        switch (ip->ip_p) {
                    785:        case IPPROTO_TCP:
                    786:                if (pktlen < (hlen + sizeof(struct tcphdr)))
                    787:                        return;
                    788:                break;
                    789:        case IPPROTO_UDP:
                    790:                if (pktlen < (hlen + sizeof(struct udphdr)))
                    791:                        return;
                    792:                uh = (struct udphdr *)((caddr_t)ip + hlen);
                    793:                if (uh->uh_sum == 0)
                    794:                        return; /* no checksum */
                    795:                break;
                    796:        default:
                    797:                return;
                    798:        }
                    799:
                    800:        cksum = htons(~(flags & HME_RXD_CSUM));
                    801:        /* cksum fixup for IP options */
                    802:        len = hlen - sizeof(struct ip);
                    803:        if (len > 0) {
                    804:                opts = (u_int16_t *)(ip + 1);
                    805:                for (; len > 0; len -= sizeof(u_int16_t), opts++) {
                    806:                        temp32 = cksum - *opts;
                    807:                        temp32 = (temp32 >> 16) + (temp32 & 65535);
                    808:                        cksum = temp32 & 65535;
                    809:                }
                    810:        }
                    811:        /* cksum fixup for pseudo-header, replace with in_cksum_phdr()? */
                    812:        ph.h.len = htons(ntohs(ip->ip_len) - hlen);
                    813:        ph.h.ttl = 0;
                    814:        ph.h.proto = ip->ip_p;
                    815:        ph.h.src = ip->ip_src.s_addr;
                    816:        ph.h.dst = ip->ip_dst.s_addr;
                    817:        temp32 = cksum;
                    818:        opts = &ph.w[0];
                    819:        temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5];
                    820:        temp32 = (temp32 >> 16) + (temp32 & 65535);
                    821:        temp32 += (temp32 >> 16);
                    822:        cksum = ~temp32;
                    823:        if (cksum == 0) {
                    824:                m->m_pkthdr.csum_flags |=
                    825:                        M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK;
                    826:        }
                    827: }
                    828:
                    829: int
                    830: hme_rint(sc)
                    831:        struct hme_softc *sc;
                    832: {
                    833:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    834:        int bix, len;
                    835:        struct hme_rxd rxd;
                    836:
                    837:        bix = sc->sc_last_rd;
                    838:
                    839:        for (;;) {
                    840:                bcopy(&sc->sc_desc->hme_rxd[bix], &rxd, sizeof(rxd));
                    841:                len = rxd.rx_flags >> 16;
                    842:
                    843:                if (rxd.rx_flags & HME_RXD_OWN)
                    844:                        break;
                    845:
                    846:                if (rxd.rx_flags & HME_RXD_OVERFLOW)
                    847:                        ifp->if_ierrors++;
                    848:                else
                    849:                        hme_read(sc, bix, len, rxd.rx_flags);
                    850:
                    851:                rxd.rx_flags = HME_RXD_OWN |
                    852:                    ((HME_RX_PKT_BUF_SZ - HME_RX_OFFSET) << 16);
                    853:                bcopy(&rxd, &sc->sc_desc->hme_rxd[bix], sizeof(rxd));
                    854:
                    855:                if (++bix == HME_RX_RING_SIZE)
                    856:                        bix = 0;
                    857:        }
                    858:
                    859:        sc->sc_last_rd = bix;
                    860:
                    861:        return (1);
                    862: }
                    863:
                    864: /*
                    865:  * error interrupt
                    866:  */
                    867: int
                    868: hme_eint(sc, why)
                    869:        struct hme_softc *sc;
                    870:        u_int32_t why;
                    871: {
                    872:        if (why & GR_STAT_NORXD) {
                    873:                sc->sc_arpcom.ac_if.if_ierrors++;
                    874:                why &= ~GR_STAT_NORXD;
                    875:        }
                    876:        if (why & GR_STAT_DTIMEXP) {
                    877:                sc->sc_arpcom.ac_if.if_oerrors++;
                    878:                why &= ~GR_STAT_DTIMEXP;
                    879:        }
                    880:
                    881:        if (why & GR_STAT_ALL_ERRORS) {
                    882:                printf("%s: stat=%b, resetting.\n", sc->sc_dev.dv_xname,
                    883:                    why, GR_STAT_BITS);
                    884:                hmereset(sc);
                    885:        }
                    886:
                    887:        return (1);
                    888: }
                    889:
                    890: /*
                    891:  * Interrupt handler
                    892:  */
                    893: int
                    894: hmeintr(v)
                    895:        void *v;
                    896: {
                    897:        struct hme_softc *sc = (struct hme_softc *)v;
                    898:        struct hme_gr *gr = sc->sc_gr;
                    899:        u_int32_t why;
                    900:        int r = 0;
                    901:
                    902:        why = gr->stat;
                    903:
                    904:        if (why & GR_STAT_ALL_ERRORS)
                    905:                r |= hme_eint(sc, why);
                    906:
                    907:        if (why & GR_STAT_MIFIRQ)
                    908:                r |= hme_mint(sc, why);
                    909:
                    910:        if (why & (GR_STAT_TXALL | GR_STAT_HOSTTOTX))
                    911:                r |= hme_tint(sc);
                    912:
                    913:        if (why & GR_STAT_RXTOHOST)
                    914:                r |= hme_rint(sc);
                    915:
                    916:        return (r);
                    917: }
                    918:
                    919: int
                    920: hme_put(sc, idx, m)
                    921:        struct hme_softc *sc;
                    922:        int idx;
                    923:        struct mbuf *m;
                    924: {
                    925:        struct mbuf *n;
                    926:        u_int8_t *buf = sc->sc_bufs->tx_buf[idx];
                    927:        int len, tlen = 0;
                    928:
                    929:        for (; m; m = n) {
                    930:                len = m->m_len;
                    931:                if (len == 0) {
                    932:                        MFREE(m, n);
                    933:                        continue;
                    934:                }
                    935:                bcopy(mtod(m, caddr_t), buf, len);
                    936:                buf += len;
                    937:                tlen += len;
                    938:                MFREE(m, n);
                    939:        }
                    940:        return (tlen);
                    941: }
                    942:
                    943: void
                    944: hme_read(sc, idx, len, flags)
                    945:        struct hme_softc *sc;
                    946:        int idx, len;
                    947:        u_int32_t flags;
                    948: {
                    949:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    950:        struct mbuf *m;
                    951:
                    952:        if (len <= sizeof(struct ether_header) ||
                    953:            len > ETHERMTU + sizeof(struct ether_header)) {
                    954:                printf("%s: invalid packet size %d; dropping\n",
                    955:                    ifp->if_xname, len);
                    956:                ifp->if_ierrors++;
                    957:                return;
                    958:        }
                    959:
                    960:        /* Pull packet off interface. */
                    961:        m = m_devget(sc->sc_bufs->rx_buf[idx], len + HME_RX_OFFSET, 0,
                    962:            &sc->sc_arpcom.ac_if, NULL);
                    963:        if (m == NULL) {
                    964:                ifp->if_ierrors++;
                    965:                return;
                    966:        }
                    967:        m_adj(m, HME_RX_OFFSET);
                    968:
                    969:        ifp->if_ipackets++;
                    970:        hme_rxcksum(m, flags);
                    971:
                    972: #if NBPFILTER > 0
                    973:        /*
                    974:         * Check if there's a BPF listener on this interface.
                    975:         * If so, hand off the raw packet to BPF.
                    976:         */
                    977:        if (ifp->if_bpf)
                    978:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    979: #endif
                    980:        /* Pass the packet up. */
                    981:        ether_input_mbuf(ifp, m);
                    982: }
                    983:
                    984: /*
                    985:  * Program the multicast receive filter.
                    986:  */
                    987: void
                    988: hme_mcreset(sc)
                    989:        struct hme_softc *sc;
                    990: {
                    991:        struct arpcom *ac = &sc->sc_arpcom;
                    992:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    993:        struct hme_cr *cr = sc->sc_cr;
                    994:        u_int32_t crc;
                    995:        u_int16_t hash[4];
                    996:        u_int8_t octet;
                    997:        int i, j;
                    998:        struct ether_multi *enm;
                    999:        struct ether_multistep step;
                   1000:
                   1001:        if (ifp->if_flags & IFF_PROMISC) {
                   1002:                cr->rx_cfg |= CR_RXCFG_PMISC;
                   1003:                return;
                   1004:        }
                   1005:        else
                   1006:                cr->rx_cfg &= ~CR_RXCFG_PMISC;
                   1007:
                   1008:        if (ifp->if_flags & IFF_ALLMULTI) {
                   1009:                cr->htable3 = 0xffff;
                   1010:                cr->htable2 = 0xffff;
                   1011:                cr->htable1 = 0xffff;
                   1012:                cr->htable0 = 0xffff;
                   1013:                cr->rx_cfg |= CR_RXCFG_HENABLE;
                   1014:                return;
                   1015:        }
                   1016:
                   1017:        hash[3] = hash[2] = hash[1] = hash[0] = 0;
                   1018:
                   1019:        ETHER_FIRST_MULTI(step, ac, enm);
                   1020:        while (enm != NULL) {
                   1021:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
                   1022:                        /*
                   1023:                         * We must listen to a range of multicast
                   1024:                         * addresses.  For now, just accept all
                   1025:                         * multicasts, rather than trying to set only
                   1026:                         * those filter bits needed to match the range.
                   1027:                         * (At this time, the only use of address
                   1028:                         * ranges is for IP multicast routing, for
                   1029:                         * which the range is big enough to require
                   1030:                         * all bits set.)
                   1031:                         */
                   1032:                        cr->htable3 = 0xffff;
                   1033:                        cr->htable2 = 0xffff;
                   1034:                        cr->htable1 = 0xffff;
                   1035:                        cr->htable0 = 0xffff;
                   1036:                        cr->rx_cfg |= CR_RXCFG_HENABLE;
                   1037:                        ifp->if_flags |= IFF_ALLMULTI;
                   1038:                        return;
                   1039:                }
                   1040:
                   1041:                crc = 0xffffffff;
                   1042:
                   1043:                for (i = 0; i < ETHER_ADDR_LEN; i++) {
                   1044:                        octet = enm->enm_addrlo[i];
                   1045:
                   1046:                        for (j = 0; j < 8; j++) {
                   1047:                                if ((crc & 1) ^ (octet & 1)) {
                   1048:                                        crc >>= 1;
                   1049:                                        crc ^= ETHER_CRC_POLY_LE;
                   1050:                                }
                   1051:                                else
                   1052:                                        crc >>= 1;
                   1053:                                octet >>= 1;
                   1054:                        }
                   1055:                }
                   1056:
                   1057:                crc >>=26;
                   1058:                hash[crc >> 4] |= 1 << (crc & 0xf);
                   1059:                ETHER_NEXT_MULTI(step, enm);
                   1060:        }
                   1061:        cr->htable3 = hash[3];
                   1062:        cr->htable2 = hash[2];
                   1063:        cr->htable1 = hash[1];
                   1064:        cr->htable0 = hash[0];
                   1065:        cr->rx_cfg |= CR_RXCFG_HENABLE;
                   1066:        ifp->if_flags &= ~IFF_ALLMULTI;
                   1067: }
                   1068:
                   1069: /*
                   1070:  * Writing to the serial BitBang, is a matter of putting the bit
                   1071:  * into the data register, then strobing the clock.
                   1072:  */
                   1073: void
                   1074: hme_tcvr_bb_writeb(sc, b)
                   1075:        struct hme_softc *sc;
                   1076:        int b;
                   1077: {
                   1078:        sc->sc_tcvr->bb_data = b & 0x1;
                   1079:        sc->sc_tcvr->bb_clock = 0;
                   1080:        sc->sc_tcvr->bb_clock = 1;
                   1081: }
                   1082:
                   1083: /*
                   1084:  * Read a bit from a PHY, if the PHY is not our internal or external
                   1085:  * phy addr, just return all zero's.
                   1086:  */
                   1087: int
                   1088: hme_tcvr_bb_readb(sc, phy)
                   1089:        struct hme_softc *sc;
                   1090:        int phy;
                   1091: {
                   1092:        int ret;
                   1093:
                   1094:        sc->sc_tcvr->bb_clock = 0;
                   1095:        DELAY(10);
                   1096:
                   1097:        if (phy == TCVR_PHYADDR_ITX)
                   1098:                ret = sc->sc_tcvr->cfg & TCVR_CFG_MDIO0;
                   1099:        else if (phy == TCVR_PHYADDR_ETX)
                   1100:                ret = sc->sc_tcvr->cfg & TCVR_CFG_MDIO1;
                   1101:        else
                   1102:                ret = 0;
                   1103:
                   1104:        sc->sc_tcvr->bb_clock = 1;
                   1105:
                   1106:        return ((ret) ? 1 : 0);
                   1107: }
                   1108:
                   1109: void
                   1110: hme_mii_write(self, phy, reg, val)
                   1111:        struct device *self;
                   1112:        int phy, reg, val;
                   1113: {
                   1114:        struct hme_softc *sc = (struct hme_softc *)self;
                   1115:        struct hme_tcvr *tcvr = sc->sc_tcvr;
                   1116:        int tries = 16, i;
                   1117:
                   1118:        if (sc->sc_flags & HME_FLAG_FENABLE) {
                   1119:                tcvr->frame = (FRAME_WRITE | phy << 23) |
                   1120:                    ((reg & 0xff) << 18) | (val & 0xffff);
                   1121:                while (!(tcvr->frame & 0x10000) && (tries != 0)) {
                   1122:                        tries--;
                   1123:                        DELAY(200);
                   1124:                }
                   1125:                if (!tries)
                   1126:                        printf("%s: mii_write failed\n", sc->sc_dev.dv_xname);
                   1127:                return;
                   1128:        }
                   1129:
                   1130:        tcvr->bb_oenab = 1;
                   1131:
                   1132:        for (i = 0; i < 32; i++)
                   1133:                hme_tcvr_bb_writeb(sc, 1);
                   1134:
                   1135:        hme_tcvr_bb_writeb(sc, (MII_COMMAND_START >> 1) & 1);
                   1136:        hme_tcvr_bb_writeb(sc, MII_COMMAND_START & 1);
                   1137:        hme_tcvr_bb_writeb(sc, (MII_COMMAND_WRITE >> 1) & 1);
                   1138:        hme_tcvr_bb_writeb(sc, MII_COMMAND_WRITE & 1);
                   1139:
                   1140:        for (i = 4; i >= 0; i--)
                   1141:                hme_tcvr_bb_writeb(sc, (phy >> i) & 1);
                   1142:
                   1143:        for (i = 4; i >= 0; i--)
                   1144:                hme_tcvr_bb_writeb(sc, (reg >> i) & 1);
                   1145:
                   1146:        for (i = 15; i >= 0; i--)
                   1147:                hme_tcvr_bb_writeb(sc, (reg >> i) & 1);
                   1148:
                   1149:        tcvr->bb_oenab = 0;
                   1150: }
                   1151:
                   1152: int
                   1153: hme_mii_read(self, phy, reg)
                   1154:        struct device *self;
                   1155:        int phy, reg;
                   1156: {
                   1157:        struct hme_softc *sc = (struct hme_softc *)self;
                   1158:        struct hme_tcvr *tcvr = sc->sc_tcvr;
                   1159:        int tries = 16, i, ret = 0;
                   1160:
                   1161:        /* Use the frame if possible */
                   1162:        if (sc->sc_flags & HME_FLAG_FENABLE) {
                   1163:                tcvr->frame = (FRAME_READ | phy << 23) |
                   1164:                    ((reg & 0xff) << 18);
                   1165:                while (!(tcvr->frame & 0x10000) && (tries != 0)) {
                   1166:                        tries--;
                   1167:                        DELAY(20);
                   1168:                }
                   1169:                if (!tries) {
                   1170:                        printf("%s: mii_read failed\n", sc->sc_dev.dv_xname);
                   1171:                        return (0);
                   1172:                }
                   1173:                return (tcvr->frame & 0xffff);
                   1174:        }
                   1175:
                   1176:        tcvr->bb_oenab = 1;
                   1177:
                   1178:        for (i = 0; i < 32; i++)                /* make bitbang idle */
                   1179:                hme_tcvr_bb_writeb(sc, 1);
                   1180:
                   1181:        hme_tcvr_bb_writeb(sc, (MII_COMMAND_START >> 1) & 1);
                   1182:        hme_tcvr_bb_writeb(sc, MII_COMMAND_START & 1);
                   1183:        hme_tcvr_bb_writeb(sc, (MII_COMMAND_READ >> 1) & 1);
                   1184:        hme_tcvr_bb_writeb(sc, MII_COMMAND_READ & 1);
                   1185:
                   1186:        for (i = 4; i >= 0; i--)
                   1187:                hme_tcvr_bb_writeb(sc, (phy >> i) & 1);
                   1188:
                   1189:        for (i = 4; i >= 0; i--)
                   1190:                hme_tcvr_bb_writeb(sc, (reg >> i) & 1);
                   1191:
                   1192:        tcvr->bb_oenab = 0;                     /* turn off bitbang intrs */
                   1193:
                   1194:        hme_tcvr_bb_readb(sc, phy);             /* ignore... */
                   1195:
                   1196:        for (i = 15; i >= 15; i--)              /* read value */
                   1197:                ret |= hme_tcvr_bb_readb(sc, phy) << i;
                   1198:
                   1199:        hme_tcvr_bb_readb(sc, phy);                     /* ignore... */
                   1200:        hme_tcvr_bb_readb(sc, phy);                     /* ignore... */
                   1201:        hme_tcvr_bb_readb(sc, phy);                     /* ignore... */
                   1202:
                   1203:        return (ret);
                   1204: }
                   1205:
                   1206: int
                   1207: hme_mediachange(ifp)
                   1208:        struct ifnet *ifp;
                   1209: {
                   1210:        if (ifp->if_flags & IFF_UP)
                   1211:                hmeinit(ifp->if_softc);
                   1212:        return (0);
                   1213: }
                   1214:
                   1215: void
                   1216: hme_mediastatus(ifp, ifmr)
                   1217:        struct ifnet *ifp;
                   1218:        struct ifmediareq *ifmr;
                   1219: {
                   1220:        struct hme_softc *sc = (struct hme_softc *)ifp->if_softc;
                   1221:
                   1222:        mii_pollstat(&sc->sc_mii);
                   1223:        ifmr->ifm_active = sc->sc_mii.mii_media_active;
                   1224:        ifmr->ifm_status = sc->sc_mii.mii_media_status;
                   1225: }
                   1226:
                   1227: void
                   1228: hme_mii_statchg(self)
                   1229:        struct device *self;
                   1230: {
                   1231:        struct hme_softc *sc = (struct hme_softc *)self;
                   1232:        struct hme_cr *cr = sc->sc_cr;
                   1233:
                   1234:        /* Apparently the hme chip is SIMPLEX if working in full duplex mode,
                   1235:           but not otherwise. */
                   1236:        if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) {
                   1237:                cr->tx_cfg |= CR_TXCFG_FULLDPLX;
                   1238:                sc->sc_arpcom.ac_if.if_flags |= IFF_SIMPLEX;
                   1239:        } else {
                   1240:                cr->tx_cfg &= ~CR_TXCFG_FULLDPLX;
                   1241:                sc->sc_arpcom.ac_if.if_flags &= ~IFF_SIMPLEX;
                   1242:        }
                   1243:        sc->sc_if_flags = sc->sc_arpcom.ac_if.if_flags;
                   1244: }

CVSweb