[BACK]Return to if_xe.c CVS log [TXT][DIR] Up to [local] / sys / dev / pcmcia

Annotation of sys/dev/pcmcia/if_xe.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_xe.c,v 1.33 2007/06/06 09:43:44 henning Exp $      */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1999 Niklas Hallqvist, Brandon Creighton, Job de Haas
        !             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:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Niklas Hallqvist,
        !            18:  *     C Stone and Job de Haas.
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: /*
        !            35:  * A driver for Xircom ethernet PC-cards.
        !            36:  *
        !            37:  * The driver has been inspired by the xirc2ps_cs.c driver found in Linux'
        !            38:  * PCMCIA package written by Werner Koch <werner.koch@guug.de>:
        !            39:  * [xirc2ps_cs.c wk 14.04.97] (1.31 1998/12/09 19:32:55)
        !            40:  * I will note that no code was used verbatim from that driver as it is under
        !            41:  * the much too strong GNU General Public License, it was only used as a
        !            42:  * "specification" of sorts.
        !            43:  * Other inspirations have been if_fxp.c, if_ep_pcmcia.c and elink3.c as
        !            44:  * they were found in OpenBSD 2.4.
        !            45:  */
        !            46:
        !            47: #include "bpfilter.h"
        !            48:
        !            49: #include <sys/param.h>
        !            50: #include <sys/systm.h>
        !            51: #include <sys/device.h>
        !            52: #include <sys/ioctl.h>
        !            53: #include <sys/mbuf.h>
        !            54: #include <sys/malloc.h>
        !            55: #include <sys/kernel.h>
        !            56: #include <sys/socket.h>
        !            57: #include <sys/syslog.h>
        !            58:
        !            59: #include <net/if.h>
        !            60: #include <net/if_dl.h>
        !            61: #include <net/if_media.h>
        !            62: #include <net/if_types.h>
        !            63:
        !            64: #ifdef INET
        !            65: #include <netinet/in.h>
        !            66: #include <netinet/in_systm.h>
        !            67: #include <netinet/in_var.h>
        !            68: #include <netinet/ip.h>
        !            69: #include <netinet/if_ether.h>
        !            70: #endif
        !            71:
        !            72: #if NBPFILTER > 0
        !            73: #include <net/bpf.h>
        !            74: #endif
        !            75:
        !            76: /*
        !            77:  * Maximum number of bytes to read per interrupt.  Linux recommends
        !            78:  * somewhere between 2000-22000.
        !            79:  * XXX This is currently a hard maximum.
        !            80:  */
        !            81: #define MAX_BYTES_INTR 12000
        !            82:
        !            83: #include <dev/mii/miivar.h>
        !            84:
        !            85: #include <dev/pcmcia/pcmciareg.h>
        !            86: #include <dev/pcmcia/pcmciavar.h>
        !            87: #include <dev/pcmcia/pcmciadevs.h>
        !            88: #include <dev/pcmcia/if_xereg.h>
        !            89:
        !            90: #ifdef __GNUC__
        !            91: #define INLINE __inline
        !            92: #else
        !            93: #define INLINE
        !            94: #endif /* __GNUC__ */
        !            95:
        !            96: #ifdef XEDEBUG
        !            97:
        !            98: #define XED_CONFIG     0x1
        !            99: #define XED_MII                0x2
        !           100: #define XED_INTR       0x4
        !           101: #define XED_FIFO       0x8
        !           102:
        !           103: #ifndef XEDEBUG_DEF
        !           104: #define XEDEBUG_DEF    (XED_CONFIG|XED_INTR)
        !           105: #endif /* XEDEBUG_DEF */
        !           106:
        !           107: int xedebug = XEDEBUG_DEF;
        !           108:
        !           109: #define DPRINTF(cat, x) if (xedebug & (cat)) printf x
        !           110:
        !           111: #else  /* XEDEBUG */
        !           112: #define DPRINTF(cat, x) (void)0
        !           113: #endif /* XEDEBUG */
        !           114:
        !           115: int    xe_pcmcia_match(struct device *, void *, void *);
        !           116: void   xe_pcmcia_attach(struct device *, struct device *, void *);
        !           117: int    xe_pcmcia_detach(struct device *, int);
        !           118: int    xe_pcmcia_activate(struct device *, enum devact);
        !           119:
        !           120: /*
        !           121:  * In case this chipset ever turns up out of pcmcia attachments (very
        !           122:  * unlikely) do the driver splitup.
        !           123:  */
        !           124: struct xe_softc {
        !           125:        struct  device sc_dev;                  /* Generic device info */
        !           126:        u_int32_t       sc_flags;               /* Misc. flags */
        !           127:        void    *sc_ih;                         /* Interrupt handler */
        !           128:        struct  arpcom sc_arpcom;               /* Ethernet common part */
        !           129:        struct  ifmedia sc_media;               /* Media control */
        !           130:        struct  mii_data sc_mii;                /* MII media information */
        !           131:        int     sc_all_mcasts;                  /* Receive all multicasts */
        !           132:        bus_space_tag_t sc_bst;                 /* Bus cookie */
        !           133:        bus_space_handle_t      sc_bsh;         /* Bus I/O handle */
        !           134:        bus_size_t      sc_offset;              /* Offset of registers */
        !           135:        u_int8_t        sc_rev;                 /* Chip revision */
        !           136: };
        !           137:
        !           138: #define XEF_MOHAWK     0x001
        !           139: #define XEF_DINGO      0x002
        !           140: #define XEF_MODEM      0x004
        !           141: #define XEF_UNSUPPORTED 0x008
        !           142: #define XEF_CE         0x010
        !           143: #define XEF_CE2                0x020
        !           144: #define XEF_CE3                0x040
        !           145: #define XEF_CE33       0x080
        !           146: #define XEF_CE56       0x100
        !           147:
        !           148: struct xe_pcmcia_softc {
        !           149:        struct  xe_softc sc_xe;                 /* Generic device info */
        !           150:        struct  pcmcia_mem_handle sc_pcmh;      /* PCMCIA memspace info */
        !           151:        int     sc_mem_window;                  /* mem window */
        !           152:        struct  pcmcia_io_handle sc_pcioh;      /* iospace info */
        !           153:        int     sc_io_window;                   /* io window info */
        !           154:        struct  pcmcia_function *sc_pf;         /* PCMCIA function */
        !           155: };
        !           156:
        !           157: /* Autoconfig definition of driver back-end */
        !           158: struct cfdriver xe_cd = {
        !           159:        NULL, "xe", DV_IFNET
        !           160: };
        !           161:
        !           162: struct cfattach xe_pcmcia_ca = {
        !           163:        sizeof (struct xe_pcmcia_softc), xe_pcmcia_match, xe_pcmcia_attach,
        !           164:        xe_pcmcia_detach, xe_pcmcia_activate
        !           165: };
        !           166:
        !           167: void   xe_cycle_power(struct xe_softc *);
        !           168: int    xe_ether_ioctl(struct ifnet *, u_long cmd, caddr_t);
        !           169: void   xe_full_reset(struct xe_softc *);
        !           170: void   xe_init(struct xe_softc *);
        !           171: int    xe_intr(void *);
        !           172: int    xe_ioctl(struct ifnet *, u_long, caddr_t);
        !           173: int    xe_mdi_read(struct device *, int, int);
        !           174: void   xe_mdi_write(struct device *, int, int, int);
        !           175: int    xe_mediachange(struct ifnet *);
        !           176: void   xe_mediastatus(struct ifnet *, struct ifmediareq *);
        !           177: int    xe_pcmcia_funce_enaddr(struct device *, u_int8_t *);
        !           178: u_int32_t xe_pcmcia_interpret_manfid(struct device *);
        !           179: int    xe_pcmcia_lan_nid_ciscallback(struct pcmcia_tuple *, void *);
        !           180: int    xe_pcmcia_manfid_ciscallback(struct pcmcia_tuple *, void *);
        !           181: u_int16_t xe_get(struct xe_softc *);
        !           182: void   xe_reset(struct xe_softc *);
        !           183: void   xe_set_address(struct xe_softc *);
        !           184: void   xe_start(struct ifnet *);
        !           185: void   xe_statchg(struct device *);
        !           186: void   xe_stop(struct xe_softc *);
        !           187: void   xe_watchdog(struct ifnet *);
        !           188: #ifdef XEDEBUG
        !           189: void   xe_reg_dump(struct xe_softc *);
        !           190: #endif /* XEDEBUG */
        !           191:
        !           192: int
        !           193: xe_pcmcia_match(parent, match, aux)
        !           194:        struct device *parent;
        !           195:        void *match, *aux;
        !           196: {
        !           197:        struct pcmcia_attach_args *pa = aux;
        !           198:
        !           199:        if (pa->pf->function != PCMCIA_FUNCTION_NETWORK)
        !           200:                return (0);
        !           201:
        !           202:        switch (pa->manufacturer) {
        !           203:        case PCMCIA_VENDOR_COMPAQ:
        !           204:        case PCMCIA_VENDOR_COMPAQ2:
        !           205:                return (0);
        !           206:
        !           207:        case PCMCIA_VENDOR_INTEL:
        !           208:        case PCMCIA_VENDOR_XIRCOM:
        !           209:                /* XXX Per-productid checking here. */
        !           210:                return (1);
        !           211:
        !           212:        default:
        !           213:                return (0);
        !           214:        }
        !           215: }
        !           216:
        !           217: void
        !           218: xe_pcmcia_attach(parent, self, aux)
        !           219:        struct device *parent, *self;
        !           220:        void *aux;
        !           221: {
        !           222:        struct xe_pcmcia_softc *psc = (struct xe_pcmcia_softc *)self;
        !           223:        struct xe_softc *sc = &psc->sc_xe;
        !           224:        struct pcmcia_attach_args *pa = aux;
        !           225:        struct pcmcia_function *pf = pa->pf;
        !           226:        struct pcmcia_config_entry *cfe;
        !           227:        struct ifnet *ifp;
        !           228:        u_int8_t myla[ETHER_ADDR_LEN], *enaddr = NULL;
        !           229:        int state = 0;
        !           230:        struct pcmcia_mem_handle pcmh;
        !           231:        int ccr_window;
        !           232:        bus_size_t ccr_offset;
        !           233:        const char *intrstr;
        !           234:
        !           235:        psc->sc_pf = pf;
        !           236:
        !           237: #if 0
        !           238:        /* Figure out what card we are. */
        !           239:        sc->sc_flags = xe_pcmcia_interpret_manfid(parent);
        !           240: #endif
        !           241:        if (sc->sc_flags & XEF_UNSUPPORTED) {
        !           242:                printf(": card unsupported\n");
        !           243:                goto bad;
        !           244:        }
        !           245:
        !           246:        /* Tell the pcmcia framework where the CCR is. */
        !           247:        pf->ccr_base = 0x800;
        !           248:        pf->ccr_mask = 0x67;
        !           249:
        !           250:        /* Fake a cfe. */
        !           251:        SIMPLEQ_FIRST(&pa->pf->cfe_head) = cfe = (struct pcmcia_config_entry *)
        !           252:            malloc(sizeof *cfe, M_DEVBUF, M_NOWAIT);
        !           253:        if (!cfe) {
        !           254:                printf(": function enable failed\n");
        !           255:                return;
        !           256:        }
        !           257:        bzero(cfe, sizeof *cfe);
        !           258:
        !           259:        /*
        !           260:         * XXX Use preprocessor symbols instead.
        !           261:         * Enable ethernet & its interrupts, wiring them to -INT
        !           262:         * No I/O base.
        !           263:         */
        !           264:        cfe->number = 0x5;
        !           265:        cfe->flags = 0;         /* XXX Check! */
        !           266:        cfe->iftype = PCMCIA_IFTYPE_IO;
        !           267:        cfe->num_iospace = 0;
        !           268:        cfe->num_memspace = 0;
        !           269:        cfe->irqmask = 0x8eb0;
        !           270:
        !           271:        /* Enable the card. */
        !           272:        pcmcia_function_init(pa->pf, cfe);
        !           273:        if (pcmcia_function_enable(pa->pf)) {
        !           274:                printf(": function enable failed\n");
        !           275:                goto bad;
        !           276:        }
        !           277:
        !           278:        state++;
        !           279:
        !           280:        if (pcmcia_io_alloc(pa->pf, 0, 16, 16, &psc->sc_pcioh)) {
        !           281:                printf(": io allocation failed\n");
        !           282:                goto bad;
        !           283:        }
        !           284:
        !           285:        state++;
        !           286:
        !           287:        if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO16, 0, 16, &psc->sc_pcioh,
        !           288:                &psc->sc_io_window)) {
        !           289:                printf(": can't map io space\n");
        !           290:                goto bad;
        !           291:        }
        !           292:        sc->sc_bst = psc->sc_pcioh.iot;
        !           293:        sc->sc_bsh = psc->sc_pcioh.ioh;
        !           294:        sc->sc_offset = 0;
        !           295:
        !           296:        printf(" port 0x%lx/%d", psc->sc_pcioh.addr, 16);
        !           297:
        !           298: #if 0
        !           299:        if (pcmcia_mem_alloc(pf, 16, &psc->sc_pcmh)) {
        !           300:                printf(": pcmcia memory allocation failed\n");
        !           301:                goto bad;
        !           302:        }
        !           303:        state++;
        !           304:
        !           305:        if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0x300, 16, &psc->sc_pcmh,
        !           306:            &sc->sc_offset, &psc->sc_mem_window)) {
        !           307:                printf(": pcmcia memory mapping failed\n");
        !           308:                goto bad;
        !           309:        }
        !           310:
        !           311:        sc->sc_bst = psc->sc_pcmh.memt;
        !           312:        sc->sc_bsh = psc->sc_pcmh.memh;
        !           313: #endif
        !           314:
        !           315:        /* Figure out what card we are. */
        !           316:        sc->sc_flags = xe_pcmcia_interpret_manfid(parent);
        !           317:
        !           318:        /*
        !           319:         * Configuration as advised by DINGO documentation.
        !           320:         * We only know about this flag after the manfid interpretation.
        !           321:         * Dingo has some extra configuration registers in the CCR space.
        !           322:         */
        !           323:        if (sc->sc_flags & XEF_DINGO) {
        !           324:                if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE_DINGO, &pcmh)) {
        !           325:                        DPRINTF(XED_CONFIG, ("bad mem alloc\n"));
        !           326:                        goto bad;
        !           327:                }
        !           328:
        !           329:                if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
        !           330:                    PCMCIA_CCR_SIZE_DINGO, &pcmh, &ccr_offset,
        !           331:                    &ccr_window)) {
        !           332:                        DPRINTF(XED_CONFIG, ("bad mem map\n"));
        !           333:                        pcmcia_mem_free(pf, &pcmh);
        !           334:                        goto bad;
        !           335:                }
        !           336:
        !           337:                bus_space_write_1(pcmh.memt, pcmh.memh,
        !           338:                    ccr_offset + PCMCIA_CCR_DCOR0, PCMCIA_CCR_DCOR0_SFINT);
        !           339:                bus_space_write_1(pcmh.memt, pcmh.memh,
        !           340:                    ccr_offset + PCMCIA_CCR_DCOR1,
        !           341:                    PCMCIA_CCR_DCOR1_FORCE_LEVIREQ | PCMCIA_CCR_DCOR1_D6);
        !           342:                bus_space_write_1(pcmh.memt, pcmh.memh,
        !           343:                    ccr_offset + PCMCIA_CCR_DCOR2, 0);
        !           344:                bus_space_write_1(pcmh.memt, pcmh.memh,
        !           345:                    ccr_offset + PCMCIA_CCR_DCOR3, 0);
        !           346:                bus_space_write_1(pcmh.memt, pcmh.memh,
        !           347:                    ccr_offset + PCMCIA_CCR_DCOR4, 0);
        !           348:
        !           349:                /* We don't need them anymore and can free them (I think). */
        !           350:                pcmcia_mem_unmap(pf, ccr_window);
        !           351:                pcmcia_mem_free(pf, &pcmh);
        !           352:        }
        !           353:
        !           354:        /*
        !           355:         * Try to get the ethernet address from FUNCE/LAN_NID tuple.
        !           356:         */
        !           357:        if (xe_pcmcia_funce_enaddr(parent, myla))
        !           358:                enaddr = myla;
        !           359:        ifp = &sc->sc_arpcom.ac_if;
        !           360:        if (enaddr)
        !           361:                bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           362:        else {
        !           363:                printf(", unable to get ethernet address\n");
        !           364:                goto bad;
        !           365:        }
        !           366:
        !           367:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           368:        ifp->if_softc = sc;
        !           369:        ifp->if_flags =
        !           370:            IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX | IFF_MULTICAST;
        !           371:        ifp->if_ioctl = xe_ioctl;
        !           372:        ifp->if_start = xe_start;
        !           373:        ifp->if_watchdog = xe_watchdog;
        !           374:        IFQ_SET_READY(&ifp->if_snd);
        !           375:
        !           376:        /* Establish the interrupt. */
        !           377:        sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, xe_intr, sc,
        !           378:            sc->sc_dev.dv_xname);
        !           379:        if (sc->sc_ih == NULL) {
        !           380:                printf(", couldn't establish interrupt\n");
        !           381:                goto bad;
        !           382:        }
        !           383:        intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
        !           384:        printf("%s%s: address %s\n", *intrstr ? ", " : "", intrstr,
        !           385:            ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           386:
        !           387:        /* Reset and initialize the card. */
        !           388:        xe_full_reset(sc);
        !           389:
        !           390:        /* Initialize our media structures and probe the phy. */
        !           391:        sc->sc_mii.mii_ifp = ifp;
        !           392:        sc->sc_mii.mii_readreg = xe_mdi_read;
        !           393:        sc->sc_mii.mii_writereg = xe_mdi_write;
        !           394:        sc->sc_mii.mii_statchg = xe_statchg;
        !           395:        ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, xe_mediachange,
        !           396:            xe_mediastatus);
        !           397:        DPRINTF(XED_MII | XED_CONFIG,
        !           398:            ("bmsr %x\n", xe_mdi_read(&sc->sc_dev, 0, 1)));
        !           399:        mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
        !           400:            0);
        !           401:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL)
        !           402:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO, 0,
        !           403:                    NULL);
        !           404:        ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
        !           405:
        !           406:        /*
        !           407:         * Attach the interface.
        !           408:         */
        !           409:        if_attach(ifp);
        !           410:        ether_ifattach(ifp);
        !           411:
        !           412:        /*
        !           413:         * Reset and initialize the card again for DINGO (as found in Linux
        !           414:         * driver).  Without this Dingo will get a watchdog timeout the first
        !           415:         * time.  The ugly media tickling seems to be necessary for getting
        !           416:         * autonegotiation to work too.
        !           417:         */
        !           418:        if (sc->sc_flags & XEF_DINGO) {
        !           419:                xe_full_reset(sc);
        !           420:                xe_init(sc);
        !           421:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
        !           422:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE);
        !           423:                xe_stop(sc);
        !           424:        }
        !           425:
        !           426: #ifdef notyet
        !           427:        pcmcia_function_disable(pa->pf);
        !           428: #endif /* notyet */
        !           429:
        !           430:        return;
        !           431:
        !           432: bad:
        !           433:        if (state > 2)
        !           434:                pcmcia_io_unmap(pf, psc->sc_io_window);
        !           435:        if (state > 1)
        !           436:                pcmcia_io_free(pf, &psc->sc_pcioh);
        !           437:        if (state > 0)
        !           438:                pcmcia_function_disable(pa->pf);
        !           439:        free(cfe, M_DEVBUF);
        !           440: }
        !           441:
        !           442: int
        !           443: xe_pcmcia_detach(dev, flags)
        !           444:        struct device *dev;
        !           445:        int flags;
        !           446: {
        !           447:        struct xe_pcmcia_softc *psc = (struct xe_pcmcia_softc *)dev;
        !           448:        struct xe_softc *sc = &psc->sc_xe;
        !           449:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           450:        int rv = 0;
        !           451:
        !           452:        mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
        !           453:        ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
        !           454:
        !           455:        pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
        !           456:        pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
        !           457:
        !           458:        ether_ifdetach(ifp);
        !           459:        if_detach(ifp);
        !           460:
        !           461:        return (rv);
        !           462: }
        !           463:
        !           464: int
        !           465: xe_pcmcia_activate(dev, act)
        !           466:        struct device *dev;
        !           467:        enum devact act;
        !           468: {
        !           469:        struct xe_pcmcia_softc *sc = (struct xe_pcmcia_softc *)dev;
        !           470:        struct ifnet *ifp = &sc->sc_xe.sc_arpcom.ac_if;
        !           471:        int s;
        !           472:
        !           473:        s = splnet();
        !           474:        switch (act) {
        !           475:        case DVACT_ACTIVATE:
        !           476:                pcmcia_function_enable(sc->sc_pf);
        !           477:                sc->sc_xe.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
        !           478:                    xe_intr, sc, sc->sc_xe.sc_dev.dv_xname);
        !           479:                xe_init(&sc->sc_xe);
        !           480:                break;
        !           481:
        !           482:        case DVACT_DEACTIVATE:
        !           483:                ifp->if_timer = 0;
        !           484:                if (ifp->if_flags & IFF_RUNNING)
        !           485:                        xe_stop(&sc->sc_xe);
        !           486:                pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih);
        !           487:                pcmcia_function_disable(sc->sc_pf);
        !           488:                break;
        !           489:        }
        !           490:        splx(s);
        !           491:        return (0);
        !           492: }
        !           493:
        !           494: /*
        !           495:  * XXX These two functions might be OK to factor out into pcmcia.c since
        !           496:  * if_sm_pcmcia.c uses similar ones.
        !           497:  */
        !           498: int
        !           499: xe_pcmcia_funce_enaddr(parent, myla)
        !           500:        struct device *parent;
        !           501:        u_int8_t *myla;
        !           502: {
        !           503:        /* XXX The Linux driver has more ways to do this in case of failure. */
        !           504:        return (pcmcia_scan_cis(parent, xe_pcmcia_lan_nid_ciscallback, myla));
        !           505: }
        !           506:
        !           507: int
        !           508: xe_pcmcia_lan_nid_ciscallback(tuple, arg)
        !           509:        struct pcmcia_tuple *tuple;
        !           510:        void *arg;
        !           511: {
        !           512:        u_int8_t *myla = arg;
        !           513:        int i;
        !           514:
        !           515:        if (tuple->code == PCMCIA_CISTPL_FUNCE) {
        !           516:                if (tuple->length < 2)
        !           517:                        return (0);
        !           518:
        !           519:                switch (pcmcia_tuple_read_1(tuple, 0)) {
        !           520:                case PCMCIA_TPLFE_TYPE_LAN_NID:
        !           521:                        if (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN)
        !           522:                                return (0);
        !           523:                        break;
        !           524:
        !           525:                case 0x02:
        !           526:                        /*
        !           527:                         * Not sure about this, I don't have a CE2
        !           528:                         * that puts the ethernet addr here.
        !           529:                         */
        !           530:                        if (pcmcia_tuple_read_1(tuple, 1) != 13)
        !           531:                                return (0);
        !           532:                        break;
        !           533:
        !           534:                default:
        !           535:                        return (0);
        !           536:                }
        !           537:
        !           538:                for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           539:                        myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
        !           540:                return (1);
        !           541:        }
        !           542:
        !           543:        /* Yet another spot where this might be. */
        !           544:        if (tuple->code == 0x89) {
        !           545:                pcmcia_tuple_read_1(tuple, 1);
        !           546:                for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           547:                        myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
        !           548:                return (1);
        !           549:        }
        !           550:        return (0);
        !           551: }
        !           552:
        !           553: u_int32_t
        !           554: xe_pcmcia_interpret_manfid (parent)
        !           555:        struct device *parent;
        !           556: {
        !           557:        u_int32_t flags = 0;
        !           558:        struct pcmcia_softc *psc = (struct pcmcia_softc *)parent;
        !           559:        char *tptr;
        !           560:
        !           561:        if (!pcmcia_scan_cis(parent, xe_pcmcia_manfid_ciscallback, &flags))
        !           562:                return (XEF_UNSUPPORTED);
        !           563:
        !           564:        if (flags & XEF_CE) {
        !           565:                tptr = memchr(psc->card.cis1_info[2], 'C',
        !           566:                    strlen(psc->card.cis1_info[2]));
        !           567:                /* XXX not sure if other CE2s hide "CE2" in different places */
        !           568:                if (tptr && *(tptr + 1) == 'E' && *(tptr + 2) == '2') {
        !           569:                        flags ^= (XEF_CE | XEF_UNSUPPORTED);
        !           570:                        flags |= XEF_CE2;
        !           571:                }
        !           572:        }
        !           573:        return (flags);
        !           574: }
        !           575:
        !           576: int
        !           577: xe_pcmcia_manfid_ciscallback(tuple, arg)
        !           578:        struct pcmcia_tuple *tuple;
        !           579:        void *arg;
        !           580: {
        !           581:        u_int32_t *flagsp = arg;
        !           582:        u_int8_t media, product;
        !           583:
        !           584:        if (tuple->code == PCMCIA_CISTPL_MANFID) {
        !           585:                if (tuple->length < 2)
        !           586:                        return (0);
        !           587:
        !           588:                media = pcmcia_tuple_read_1(tuple, 3);
        !           589:                product = pcmcia_tuple_read_1(tuple, 4);
        !           590:
        !           591:                if (!(product & XEPROD_CREDITCARD) ||
        !           592:                    !(media & XEMEDIA_ETHER)) {
        !           593:                        *flagsp |= XEF_UNSUPPORTED;
        !           594:                        return (1);
        !           595:                }
        !           596:
        !           597:                if (media & XEMEDIA_MODEM)
        !           598:                        *flagsp |= XEF_MODEM;
        !           599:
        !           600:                switch (product & XEPROD_IDMASK) {
        !           601:                case 1:
        !           602:                        /* XXX Can be CE2 too (we double-check later). */
        !           603:                        *flagsp |= XEF_CE | XEF_UNSUPPORTED;
        !           604:                        break;
        !           605:                case 2:
        !           606:                        *flagsp |= XEF_CE2;
        !           607:                        break;
        !           608:                case 3:
        !           609:                        if (!(*flagsp & XEF_MODEM))
        !           610:                                *flagsp |= XEF_MOHAWK;
        !           611:                        *flagsp |= XEF_CE3;
        !           612:                        break;
        !           613:                case 4:
        !           614:                        *flagsp |= XEF_CE33;
        !           615:                        break;
        !           616:                case 5:
        !           617:                        *flagsp |= XEF_CE56 | XEF_MOHAWK;
        !           618:                        break;
        !           619:                case 6:
        !           620:                case 7:
        !           621:                        *flagsp |= XEF_CE56 | XEF_MOHAWK | XEF_DINGO;
        !           622:                        break;
        !           623:                default:
        !           624:                        *flagsp |= XEF_UNSUPPORTED;
        !           625:                        break;
        !           626:                }
        !           627:
        !           628:                return (1);
        !           629:        }
        !           630:        return (0);
        !           631: }
        !           632:
        !           633: int
        !           634: xe_intr(arg)
        !           635:        void *arg;
        !           636: {
        !           637:        struct xe_softc *sc = arg;
        !           638:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           639:        u_int8_t esr, rsr, isr, rx_status, savedpage;
        !           640:        u_int16_t tx_status, recvcount = 0, tempint;
        !           641:
        !           642:        ifp->if_timer = 0;      /* turn watchdog timer off */
        !           643:
        !           644:        if (sc->sc_flags & XEF_MOHAWK) {
        !           645:                /* Disable interrupt (Linux does it). */
        !           646:                bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
        !           647:                    0);
        !           648:        }
        !           649:
        !           650:        savedpage =
        !           651:            bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + PR);
        !           652:
        !           653:        PAGE(sc, 0);
        !           654:        esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + ESR);
        !           655:        isr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + ISR0);
        !           656:        rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RSR);
        !           657:
        !           658:        /* Check to see if card has been ejected. */
        !           659:        if (isr == 0xff) {
        !           660:                printf("%s: interrupt for dead card\n", sc->sc_dev.dv_xname);
        !           661:                goto end;
        !           662:        }
        !           663:
        !           664:        PAGE(sc, 40);
        !           665:        rx_status =
        !           666:            bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RXST0);
        !           667:        tx_status =
        !           668:            bus_space_read_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + TXST0);
        !           669:
        !           670:        /*
        !           671:         * XXX Linux writes to RXST0 and TXST* here.  My CE2 works just fine
        !           672:         * without it, and I can't see an obvious reason for it.
        !           673:         */
        !           674:
        !           675:        PAGE(sc, 0);
        !           676:        while (esr & FULL_PKT_RCV) {
        !           677:                if (!(rsr & RSR_RX_OK))
        !           678:                        break;
        !           679:
        !           680:                /* Compare bytes read this interrupt to hard maximum. */
        !           681:                if (recvcount > MAX_BYTES_INTR) {
        !           682:                        DPRINTF(XED_INTR,
        !           683:                            ("%s: too many bytes this interrupt\n",
        !           684:                            sc->sc_dev.dv_xname));
        !           685:                        ifp->if_iqdrops++;
        !           686:                        /* Drop packet. */
        !           687:                        bus_space_write_2(sc->sc_bst, sc->sc_bsh,
        !           688:                            sc->sc_offset + DO0, DO_SKIP_RX_PKT);
        !           689:                }
        !           690:                tempint = xe_get(sc);
        !           691:                recvcount += tempint;
        !           692:                ifp->if_ibytes += tempint;
        !           693:                esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
        !           694:                    sc->sc_offset + ESR);
        !           695:                rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
        !           696:                    sc->sc_offset + RSR);
        !           697:        }
        !           698:
        !           699:        /* Packet too long? */
        !           700:        if (rsr & RSR_TOO_LONG) {
        !           701:                ifp->if_ierrors++;
        !           702:                DPRINTF(XED_INTR,
        !           703:                    ("%s: packet too long\n", sc->sc_dev.dv_xname));
        !           704:        }
        !           705:
        !           706:        /* CRC error? */
        !           707:        if (rsr & RSR_CRCERR) {
        !           708:                ifp->if_ierrors++;
        !           709:                DPRINTF(XED_INTR,
        !           710:                    ("%s: CRC error detected\n", sc->sc_dev.dv_xname));
        !           711:        }
        !           712:
        !           713:        /* Alignment error? */
        !           714:        if (rsr & RSR_ALIGNERR) {
        !           715:                ifp->if_ierrors++;
        !           716:                DPRINTF(XED_INTR,
        !           717:                    ("%s: alignment error detected\n", sc->sc_dev.dv_xname));
        !           718:        }
        !           719:
        !           720:        /* Check for rx overrun. */
        !           721:        if (rx_status & RX_OVERRUN) {
        !           722:                bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
        !           723:                    CLR_RX_OVERRUN);
        !           724:                DPRINTF(XED_INTR, ("overrun cleared\n"));
        !           725:        }
        !           726:
        !           727:        /* Try to start more packets transmitting. */
        !           728:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
        !           729:                xe_start(ifp);
        !           730:
        !           731:        /* Detected excessive collisions? */
        !           732:        if ((tx_status & EXCESSIVE_COLL) && ifp->if_opackets > 0) {
        !           733:                DPRINTF(XED_INTR,
        !           734:                    ("%s: excessive collisions\n", sc->sc_dev.dv_xname));
        !           735:                bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
        !           736:                    RESTART_TX);
        !           737:                ifp->if_oerrors++;
        !           738:        }
        !           739:
        !           740:        if ((tx_status & TX_ABORT) && ifp->if_opackets > 0)
        !           741:                ifp->if_oerrors++;
        !           742:
        !           743: end:
        !           744:        /* Reenable interrupts. */
        !           745:        PAGE(sc, savedpage);
        !           746:        bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
        !           747:            ENABLE_INT);
        !           748:
        !           749:        return (1);
        !           750: }
        !           751:
        !           752: u_int16_t
        !           753: xe_get(sc)
        !           754:        struct xe_softc *sc;
        !           755: {
        !           756:        u_int8_t rsr;
        !           757:        struct mbuf *top, **mp, *m;
        !           758:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           759:        u_int16_t pktlen, len, recvcount = 0;
        !           760:        u_int8_t *data;
        !           761:
        !           762:        PAGE(sc, 0);
        !           763:        rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RSR);
        !           764:
        !           765:        pktlen =
        !           766:            bus_space_read_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RBC0) &
        !           767:            RBC_COUNT_MASK;
        !           768:        if (pktlen == 0) {
        !           769:                /*
        !           770:                 * XXX At least one CE2 sets RBC0 == 0 occasionally, and only
        !           771:                 * when MPE is set.  It is not known why.
        !           772:                 */
        !           773:                return (0);
        !           774:        }
        !           775:        recvcount += pktlen;
        !           776:
        !           777:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           778:        if (m == 0)
        !           779:                return (recvcount);
        !           780:        m->m_pkthdr.rcvif = ifp;
        !           781:        m->m_pkthdr.len = pktlen;
        !           782:        len = MHLEN;
        !           783:        top = 0;
        !           784:        mp = &top;
        !           785:
        !           786:        while (pktlen > 0) {
        !           787:                if (top) {
        !           788:                        MGET(m, M_DONTWAIT, MT_DATA);
        !           789:                        if (m == 0) {
        !           790:                                m_freem(top);
        !           791:                                return (recvcount);
        !           792:                        }
        !           793:                        len = MLEN;
        !           794:                }
        !           795:                if (pktlen >= MINCLSIZE) {
        !           796:                        MCLGET(m, M_DONTWAIT);
        !           797:                        if (!(m->m_flags & M_EXT)) {
        !           798:                                m_freem(m);
        !           799:                                m_freem(top);
        !           800:                                return (recvcount);
        !           801:                        }
        !           802:                        len = MCLBYTES;
        !           803:                }
        !           804:                if (!top) {
        !           805:                        caddr_t newdata = (caddr_t)ALIGN(m->m_data +
        !           806:                            sizeof (struct ether_header)) -
        !           807:                            sizeof (struct ether_header);
        !           808:                        len -= newdata - m->m_data;
        !           809:                        m->m_data = newdata;
        !           810:                }
        !           811:                len = min(pktlen, len);
        !           812:
        !           813:                data = mtod(m, u_int8_t *);
        !           814:                if (len > 1) {
        !           815:                        len &= ~1;
        !           816:                        bus_space_read_raw_multi_2(sc->sc_bst, sc->sc_bsh,
        !           817:                            sc->sc_offset + EDP, data, len);
        !           818:                } else
        !           819:                        *data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
        !           820:                            sc->sc_offset + EDP);
        !           821:                m->m_len = len;
        !           822:                pktlen -= len;
        !           823:                *mp = m;
        !           824:                mp = &m->m_next;
        !           825:        }
        !           826:
        !           827:        /* Skip Rx packet. */
        !           828:        bus_space_write_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + DO0,
        !           829:            DO_SKIP_RX_PKT);
        !           830:
        !           831:        ifp->if_ipackets++;
        !           832:
        !           833: #if NBPFILTER > 0
        !           834:        if (ifp->if_bpf)
        !           835:                bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_IN);
        !           836: #endif
        !           837:
        !           838:        ether_input_mbuf(ifp, top);
        !           839:        return (recvcount);
        !           840: }
        !           841:
        !           842:
        !           843: /*
        !           844:  * Serial management for the MII.
        !           845:  * The DELAY's below stem from the fact that the maximum frequency
        !           846:  * acceptable on the MDC pin is 2.5 MHz and fast processors can easily
        !           847:  * go much faster than that.
        !           848:  */
        !           849:
        !           850: /* Let the MII serial management be idle for one period. */
        !           851: static INLINE void xe_mdi_idle(struct xe_softc *);
        !           852: static INLINE void
        !           853: xe_mdi_idle(sc)
        !           854:        struct xe_softc *sc;
        !           855: {
        !           856:        bus_space_tag_t bst = sc->sc_bst;
        !           857:        bus_space_handle_t bsh = sc->sc_bsh;
        !           858:        bus_size_t offset = sc->sc_offset;
        !           859:
        !           860:        /* Drive MDC low... */
        !           861:        bus_space_write_1(bst, bsh, offset + GP2, MDC_LOW);
        !           862:        DELAY(1);
        !           863:
        !           864:        /* and high again. */
        !           865:        bus_space_write_1(bst, bsh, offset + GP2, MDC_HIGH);
        !           866:        DELAY(1);
        !           867: }
        !           868:
        !           869: /* Pulse out one bit of data. */
        !           870: static INLINE void xe_mdi_pulse(struct xe_softc *, int);
        !           871: static INLINE void
        !           872: xe_mdi_pulse(sc, data)
        !           873:        struct xe_softc *sc;
        !           874:        int data;
        !           875: {
        !           876:        bus_space_tag_t bst = sc->sc_bst;
        !           877:        bus_space_handle_t bsh = sc->sc_bsh;
        !           878:        bus_size_t offset = sc->sc_offset;
        !           879:        u_int8_t bit = data ? MDIO_HIGH : MDIO_LOW;
        !           880:
        !           881:        /* First latch the data bit MDIO with clock bit MDC low...*/
        !           882:        bus_space_write_1(bst, bsh, offset + GP2, bit | MDC_LOW);
        !           883:        DELAY(1);
        !           884:
        !           885:        /* then raise the clock again, preserving the data bit. */
        !           886:        bus_space_write_1(bst, bsh, offset + GP2, bit | MDC_HIGH);
        !           887:        DELAY(1);
        !           888: }
        !           889:
        !           890: /* Probe one bit of data. */
        !           891: static INLINE int xe_mdi_probe(struct xe_softc *sc);
        !           892: static INLINE int
        !           893: xe_mdi_probe(sc)
        !           894:        struct xe_softc *sc;
        !           895: {
        !           896:        bus_space_tag_t bst = sc->sc_bst;
        !           897:        bus_space_handle_t bsh = sc->sc_bsh;
        !           898:        bus_size_t offset = sc->sc_offset;
        !           899:        u_int8_t x;
        !           900:
        !           901:        /* Pull clock bit MDCK low... */
        !           902:        bus_space_write_1(bst, bsh, offset + GP2, MDC_LOW);
        !           903:        DELAY(1);
        !           904:
        !           905:        /* Read data and drive clock high again. */
        !           906:        x = bus_space_read_1(bst, bsh, offset + GP2) & MDIO;
        !           907:        bus_space_write_1(bst, bsh, offset + GP2, MDC_HIGH);
        !           908:        DELAY(1);
        !           909:
        !           910:        return (x);
        !           911: }
        !           912:
        !           913: /* Pulse out a sequence of data bits. */
        !           914: static INLINE void xe_mdi_pulse_bits(struct xe_softc *, u_int32_t, int);
        !           915: static INLINE void
        !           916: xe_mdi_pulse_bits(sc, data, len)
        !           917:        struct xe_softc *sc;
        !           918:        u_int32_t data;
        !           919:        int len;
        !           920: {
        !           921:        u_int32_t mask;
        !           922:
        !           923:        for (mask = 1 << (len - 1); mask; mask >>= 1)
        !           924:                xe_mdi_pulse(sc, data & mask);
        !           925: }
        !           926:
        !           927: /* Read a PHY register. */
        !           928: int
        !           929: xe_mdi_read(self, phy, reg)
        !           930:        struct device *self;
        !           931:        int phy;
        !           932:        int reg;
        !           933: {
        !           934:        struct xe_softc *sc = (struct xe_softc *)self;
        !           935:        int i;
        !           936:        u_int32_t mask;
        !           937:        u_int32_t data = 0;
        !           938:
        !           939:        PAGE(sc, 2);
        !           940:        for (i = 0; i < 32; i++)        /* Synchronize. */
        !           941:                xe_mdi_pulse(sc, 1);
        !           942:        xe_mdi_pulse_bits(sc, 0x06, 4); /* Start + Read opcode */
        !           943:        xe_mdi_pulse_bits(sc, phy, 5);  /* PHY address */
        !           944:        xe_mdi_pulse_bits(sc, reg, 5);  /* PHY register */
        !           945:        xe_mdi_idle(sc);                /* Turn around. */
        !           946:        xe_mdi_probe(sc);               /* Drop initial zero bit. */
        !           947:
        !           948:        for (mask = 1 << 15; mask; mask >>= 1)
        !           949:                if (xe_mdi_probe(sc))
        !           950:                        data |= mask;
        !           951:        xe_mdi_idle(sc);
        !           952:
        !           953:        DPRINTF(XED_MII,
        !           954:            ("xe_mdi_read: phy %d reg %d -> %x\n", phy, reg, data));
        !           955:        return (data);
        !           956: }
        !           957:
        !           958: /* Write a PHY register. */
        !           959: void
        !           960: xe_mdi_write(self, phy, reg, value)
        !           961:        struct device *self;
        !           962:        int phy;
        !           963:        int reg;
        !           964:        int value;
        !           965: {
        !           966:        struct xe_softc *sc = (struct xe_softc *)self;
        !           967:        int i;
        !           968:
        !           969:        PAGE(sc, 2);
        !           970:        for (i = 0; i < 32; i++)        /* Synchronize. */
        !           971:                xe_mdi_pulse(sc, 1);
        !           972:        xe_mdi_pulse_bits(sc, 0x05, 4); /* Start + Write opcode */
        !           973:        xe_mdi_pulse_bits(sc, phy, 5);  /* PHY address */
        !           974:        xe_mdi_pulse_bits(sc, reg, 5);  /* PHY register */
        !           975:        xe_mdi_pulse_bits(sc, 0x02, 2); /* Turn around. */
        !           976:        xe_mdi_pulse_bits(sc, value, 16);       /* Write the data */
        !           977:        xe_mdi_idle(sc);                /* Idle away. */
        !           978:
        !           979:        DPRINTF(XED_MII,
        !           980:            ("xe_mdi_write: phy %d reg %d val %x\n", phy, reg, value));
        !           981: }
        !           982:
        !           983: void
        !           984: xe_statchg(self)
        !           985:        struct device *self;
        !           986: {
        !           987:        /* XXX Update ifp->if_baudrate */
        !           988: }
        !           989:
        !           990: /*
        !           991:  * Change media according to request.
        !           992:  */
        !           993: int
        !           994: xe_mediachange(ifp)
        !           995:        struct ifnet *ifp;
        !           996: {
        !           997:        if (ifp->if_flags & IFF_UP)
        !           998:                xe_init(ifp->if_softc);
        !           999:        return (0);
        !          1000: }
        !          1001:
        !          1002: /*
        !          1003:  * Notify the world which media we're using.
        !          1004:  */
        !          1005: void
        !          1006: xe_mediastatus(ifp, ifmr)
        !          1007:        struct ifnet *ifp;
        !          1008:        struct ifmediareq *ifmr;
        !          1009: {
        !          1010:        struct xe_softc *sc = ifp->if_softc;
        !          1011:
        !          1012:        mii_pollstat(&sc->sc_mii);
        !          1013:        ifmr->ifm_status = sc->sc_mii.mii_media_status;
        !          1014:        ifmr->ifm_active = sc->sc_mii.mii_media_active;
        !          1015: }
        !          1016:
        !          1017: void
        !          1018: xe_reset(sc)
        !          1019:        struct xe_softc *sc;
        !          1020: {
        !          1021:        int s;
        !          1022:
        !          1023:        s = splnet();
        !          1024:        xe_stop(sc);
        !          1025:        xe_full_reset(sc);
        !          1026:        xe_init(sc);
        !          1027:        splx(s);
        !          1028: }
        !          1029:
        !          1030: void
        !          1031: xe_watchdog(ifp)
        !          1032:        struct ifnet *ifp;
        !          1033: {
        !          1034:        struct xe_softc *sc = ifp->if_softc;
        !          1035:
        !          1036:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !          1037:        ++sc->sc_arpcom.ac_if.if_oerrors;
        !          1038:
        !          1039:        xe_reset(sc);
        !          1040: }
        !          1041:
        !          1042: void
        !          1043: xe_stop(sc)
        !          1044:        register struct xe_softc *sc;
        !          1045: {
        !          1046:        /* Disable interrupts. */
        !          1047:        PAGE(sc, 0);
        !          1048:        bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR, 0);
        !          1049:
        !          1050:        PAGE(sc, 1);
        !          1051:        bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + IMR0, 0);
        !          1052:
        !          1053:        /* Power down, wait. */
        !          1054:        PAGE(sc, 4);
        !          1055:        bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + GP1, 0);
        !          1056:        DELAY(40000);
        !          1057:
        !          1058:        /* Cancel watchdog timer. */
        !          1059:        sc->sc_arpcom.ac_if.if_timer = 0;
        !          1060: }
        !          1061:
        !          1062: void
        !          1063: xe_init(sc)
        !          1064:        struct xe_softc *sc;
        !          1065: {
        !          1066:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1067:        int s;
        !          1068:
        !          1069:        DPRINTF(XED_CONFIG, ("xe_init\n"));
        !          1070:
        !          1071:        s = splnet();
        !          1072:
        !          1073:        xe_set_address(sc);
        !          1074:
        !          1075:        /* Set current media. */
        !          1076:        mii_mediachg(&sc->sc_mii);
        !          1077:
        !          1078:        ifp->if_flags |= IFF_RUNNING;
        !          1079:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1080:        splx(s);
        !          1081: }
        !          1082:
        !          1083: /*
        !          1084:  * Start outputting on the interface.
        !          1085:  * Always called as splnet().
        !          1086:  */
        !          1087: void
        !          1088: xe_start(ifp)
        !          1089:        struct ifnet *ifp;
        !          1090: {
        !          1091:        struct xe_softc *sc = ifp->if_softc;
        !          1092:        bus_space_tag_t bst = sc->sc_bst;
        !          1093:        bus_space_handle_t bsh = sc->sc_bsh;
        !          1094:        bus_size_t offset = sc->sc_offset;
        !          1095:        unsigned int s, len, pad = 0;
        !          1096:        struct mbuf *m0, *m;
        !          1097:        u_int16_t space;
        !          1098:
        !          1099:        /* Don't transmit if interface is busy or not running. */
        !          1100:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !          1101:                return;
        !          1102:
        !          1103:        /* Peek at the next packet. */
        !          1104:        IFQ_POLL(&ifp->if_snd, m0);
        !          1105:        if (m0 == 0)
        !          1106:                return;
        !          1107:
        !          1108:        /* We need to use m->m_pkthdr.len, so require the header. */
        !          1109:        if (!(m0->m_flags & M_PKTHDR))
        !          1110:                panic("xe_start: no header mbuf");
        !          1111:
        !          1112:        len = m0->m_pkthdr.len;
        !          1113:
        !          1114:        /* Pad to ETHER_MIN_LEN - ETHER_CRC_LEN. */
        !          1115:        if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
        !          1116:                pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
        !          1117:
        !          1118:        PAGE(sc, 0);
        !          1119:        space = bus_space_read_2(bst, bsh, offset + TSO0) & 0x7fff;
        !          1120:        if (len + pad + 2 > space) {
        !          1121:                DPRINTF(XED_FIFO,
        !          1122:                    ("%s: not enough space in output FIFO (%d > %d)\n",
        !          1123:                    sc->sc_dev.dv_xname, len + pad + 2, space));
        !          1124:                return;
        !          1125:        }
        !          1126:
        !          1127:        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          1128:
        !          1129: #if NBPFILTER > 0
        !          1130:        if (ifp->if_bpf)
        !          1131:                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          1132: #endif
        !          1133:
        !          1134:        /*
        !          1135:         * Do the output at splhigh() so that an interrupt from another device
        !          1136:         * won't cause a FIFO underrun.
        !          1137:         */
        !          1138:        s = splhigh();
        !          1139:
        !          1140:        bus_space_write_2(bst, bsh, offset + TSO2, (u_int16_t)len + pad + 2);
        !          1141:        bus_space_write_2(bst, bsh, offset + EDP, (u_int16_t)len + pad);
        !          1142:        for (m = m0; m; ) {
        !          1143:                if (m->m_len > 1)
        !          1144:                        bus_space_write_raw_multi_2(bst, bsh, offset + EDP,
        !          1145:                            mtod(m, u_int8_t *), m->m_len & ~1);
        !          1146:                if (m->m_len & 1)
        !          1147:                        bus_space_write_1(bst, bsh, offset + EDP,
        !          1148:                            *(mtod(m, u_int8_t *) + m->m_len - 1));
        !          1149:                MFREE(m, m0);
        !          1150:                m = m0;
        !          1151:        }
        !          1152:        if (sc->sc_flags & XEF_MOHAWK)
        !          1153:                bus_space_write_1(bst, bsh, offset + CR, TX_PKT | ENABLE_INT);
        !          1154:        else {
        !          1155:                for (; pad > 1; pad -= 2)
        !          1156:                        bus_space_write_2(bst, bsh, offset + EDP, 0);
        !          1157:                if (pad == 1)
        !          1158:                        bus_space_write_1(bst, bsh, offset + EDP, 0);
        !          1159:        }
        !          1160:
        !          1161:        splx(s);
        !          1162:
        !          1163:        ifp->if_timer = 5;
        !          1164:        ++ifp->if_opackets;
        !          1165: }
        !          1166:
        !          1167: int
        !          1168: xe_ether_ioctl(ifp, cmd, data)
        !          1169:        struct ifnet *ifp;
        !          1170:        u_long cmd;
        !          1171:        caddr_t data;
        !          1172: {
        !          1173:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          1174:        struct xe_softc *sc = ifp->if_softc;
        !          1175:
        !          1176:        switch (cmd) {
        !          1177:        case SIOCSIFADDR:
        !          1178:                ifp->if_flags |= IFF_UP;
        !          1179:
        !          1180:                switch (ifa->ifa_addr->sa_family) {
        !          1181: #ifdef INET
        !          1182:                case AF_INET:
        !          1183:                        xe_init(sc);
        !          1184:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !          1185:                        break;
        !          1186: #endif /* INET */
        !          1187:
        !          1188:                default:
        !          1189:                        xe_init(sc);
        !          1190:                        break;
        !          1191:                }
        !          1192:                break;
        !          1193:
        !          1194:        default:
        !          1195:                return (EINVAL);
        !          1196:        }
        !          1197:
        !          1198:        return (0);
        !          1199: }
        !          1200:
        !          1201: int
        !          1202: xe_ioctl(ifp, command, data)
        !          1203:        struct ifnet *ifp;
        !          1204:        u_long command;
        !          1205:        caddr_t data;
        !          1206: {
        !          1207:        struct xe_softc *sc = ifp->if_softc;
        !          1208:        struct ifreq *ifr = (struct ifreq *)data;
        !          1209:        int s, error = 0;
        !          1210:
        !          1211:        s = splnet();
        !          1212:
        !          1213:        switch (command) {
        !          1214:        case SIOCSIFADDR:
        !          1215:                error = xe_ether_ioctl(ifp, command, data);
        !          1216:                break;
        !          1217:
        !          1218:        case SIOCSIFFLAGS:
        !          1219:                sc->sc_all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
        !          1220:
        !          1221:                PAGE(sc, 0x42);
        !          1222:                if ((ifp->if_flags & IFF_PROMISC) ||
        !          1223:                    (ifp->if_flags & IFF_ALLMULTI))
        !          1224:                        bus_space_write_1(sc->sc_bst, sc->sc_bsh,
        !          1225:                            sc->sc_offset + SWC1,
        !          1226:                            SWC1_PROMISC | SWC1_MCAST_PROM);
        !          1227:                else
        !          1228:                        bus_space_write_1(sc->sc_bst, sc->sc_bsh,
        !          1229:                            sc->sc_offset + SWC1, 0);
        !          1230:
        !          1231:                /*
        !          1232:                 * If interface is marked up and not running, then start it.
        !          1233:                 * If it is marked down and running, stop it.
        !          1234:                 * XXX If it's up then re-initialize it. This is so flags
        !          1235:                 * such as IFF_PROMISC are handled.
        !          1236:                 */
        !          1237:                if (ifp->if_flags & IFF_UP) {
        !          1238:                        xe_init(sc);
        !          1239:                } else {
        !          1240:                        if (ifp->if_flags & IFF_RUNNING)
        !          1241:                                xe_stop(sc);
        !          1242:                }
        !          1243:                break;
        !          1244:
        !          1245:        case SIOCADDMULTI:
        !          1246:        case SIOCDELMULTI:
        !          1247:                sc->sc_all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
        !          1248:                error = (command == SIOCADDMULTI) ?
        !          1249:                    ether_addmulti(ifr, &sc->sc_arpcom) :
        !          1250:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !          1251:
        !          1252:                if (error == ENETRESET) {
        !          1253:                        /*
        !          1254:                         * Multicast list has changed; set the hardware
        !          1255:                         * filter accordingly.
        !          1256:                         */
        !          1257:                        if (!sc->sc_all_mcasts &&
        !          1258:                            !(ifp->if_flags & IFF_PROMISC))
        !          1259:                                xe_set_address(sc);
        !          1260:
        !          1261:                        /*
        !          1262:                         * xe_set_address() can turn on all_mcasts if we run
        !          1263:                         * out of space, so check it again rather than else {}.
        !          1264:                         */
        !          1265:                        if (sc->sc_all_mcasts)
        !          1266:                                xe_init(sc);
        !          1267:                        error = 0;
        !          1268:                }
        !          1269:                break;
        !          1270:
        !          1271:        case SIOCSIFMEDIA:
        !          1272:        case SIOCGIFMEDIA:
        !          1273:                error =
        !          1274:                    ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
        !          1275:                break;
        !          1276:
        !          1277:        default:
        !          1278:                error = EINVAL;
        !          1279:        }
        !          1280:        splx(s);
        !          1281:        return (error);
        !          1282: }
        !          1283:
        !          1284: void
        !          1285: xe_set_address(sc)
        !          1286:        struct xe_softc *sc;
        !          1287: {
        !          1288:        bus_space_tag_t bst = sc->sc_bst;
        !          1289:        bus_space_handle_t bsh = sc->sc_bsh;
        !          1290:        bus_size_t offset = sc->sc_offset;
        !          1291:        struct arpcom *arp = &sc->sc_arpcom;
        !          1292:        struct ether_multi *enm;
        !          1293:        struct ether_multistep step;
        !          1294:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1295:        int i, page, pos, num;
        !          1296:
        !          1297:        PAGE(sc, 0x50);
        !          1298:        for (i = 0; i < 6; i++) {
        !          1299:                bus_space_write_1(bst, bsh, offset + IA + i,
        !          1300:                    sc->sc_arpcom.ac_enaddr[(sc->sc_flags & XEF_MOHAWK) ?
        !          1301:                    5 - i : i]);
        !          1302:        }
        !          1303:
        !          1304:        if (arp->ac_multicnt > 0) {
        !          1305:                if (arp->ac_multicnt > 9) {
        !          1306:                        PAGE(sc, 0x42);
        !          1307:                        bus_space_write_1(sc->sc_bst, sc->sc_bsh,
        !          1308:                            sc->sc_offset + SWC1,
        !          1309:                            SWC1_PROMISC | SWC1_MCAST_PROM);
        !          1310:                        return;
        !          1311:                }
        !          1312:
        !          1313:                ETHER_FIRST_MULTI(step, arp, enm);
        !          1314:
        !          1315:                pos = IA + 6;
        !          1316:                for (page = 0x50, num = arp->ac_multicnt; num > 0 && enm;
        !          1317:                    num--) {
        !          1318:                        if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
        !          1319:                            sizeof(enm->enm_addrlo)) != 0) {
        !          1320:                                /*
        !          1321:                                 * The multicast address is really a range;
        !          1322:                                 * it's easier just to accept all multicasts.
        !          1323:                                 * XXX should we be setting IFF_ALLMULTI here?
        !          1324:                                 */
        !          1325:                                ifp->if_flags |= IFF_ALLMULTI;
        !          1326:                                sc->sc_all_mcasts=1;
        !          1327:                                break;
        !          1328:                        }
        !          1329:
        !          1330:                        for (i = 0; i < 6; i++) {
        !          1331:                                bus_space_write_1(bst, bsh, offset + pos,
        !          1332:                                    enm->enm_addrlo[
        !          1333:                                    (sc->sc_flags & XEF_MOHAWK) ? 5 - i : i]);
        !          1334:
        !          1335:                                if (++pos > 15) {
        !          1336:                                        pos = IA;
        !          1337:                                        page++;
        !          1338:                                        PAGE(sc, page);
        !          1339:                                }
        !          1340:                        }
        !          1341:                }
        !          1342:        }
        !          1343: }
        !          1344:
        !          1345: void
        !          1346: xe_cycle_power(sc)
        !          1347:        struct xe_softc *sc;
        !          1348: {
        !          1349:        bus_space_tag_t bst = sc->sc_bst;
        !          1350:        bus_space_handle_t bsh = sc->sc_bsh;
        !          1351:        bus_size_t offset = sc->sc_offset;
        !          1352:
        !          1353:        PAGE(sc, 4);
        !          1354:        DELAY(1);
        !          1355:        bus_space_write_1(bst, bsh, offset + GP1, 0);
        !          1356:        DELAY(40000);
        !          1357:        if (sc->sc_flags & XEF_MOHAWK)
        !          1358:                bus_space_write_1(bst, bsh, offset + GP1, POWER_UP);
        !          1359:        else
        !          1360:                /* XXX What is bit 2 (aka AIC)? */
        !          1361:                bus_space_write_1(bst, bsh, offset + GP1, POWER_UP | 4);
        !          1362:        DELAY(20000);
        !          1363: }
        !          1364:
        !          1365: void
        !          1366: xe_full_reset(sc)
        !          1367:        struct xe_softc *sc;
        !          1368: {
        !          1369:        bus_space_tag_t bst = sc->sc_bst;
        !          1370:        bus_space_handle_t bsh = sc->sc_bsh;
        !          1371:        bus_size_t offset = sc->sc_offset;
        !          1372:
        !          1373:        /* Do an as extensive reset as possible on all functions. */
        !          1374:        xe_cycle_power(sc);
        !          1375:        bus_space_write_1(bst, bsh, offset + CR, SOFT_RESET);
        !          1376:        DELAY(20000);
        !          1377:        bus_space_write_1(bst, bsh, offset + CR, 0);
        !          1378:        DELAY(20000);
        !          1379:        if (sc->sc_flags & XEF_MOHAWK) {
        !          1380:                PAGE(sc, 4);
        !          1381:                /*
        !          1382:                 * Drive GP1 low to power up ML6692 and GP2 high to power up
        !          1383:                 * the 10MHz chip.  XXX What chip is that?  The phy?
        !          1384:                 */
        !          1385:                bus_space_write_1(bst, bsh, offset + GP0,
        !          1386:                    GP1_OUT | GP2_OUT | GP2_WR);
        !          1387:        }
        !          1388:        DELAY(500000);
        !          1389:
        !          1390:        /* Get revision information.  XXX Symbolic constants. */
        !          1391:        sc->sc_rev = bus_space_read_1(bst, bsh, offset + BV) &
        !          1392:            ((sc->sc_flags & XEF_MOHAWK) ? 0x70 : 0x30) >> 4;
        !          1393:
        !          1394:        /* Media selection.  XXX Maybe manual overriding too? */
        !          1395:        if (!(sc->sc_flags & XEF_MOHAWK)) {
        !          1396:                PAGE(sc, 4);
        !          1397:                /*
        !          1398:                 * XXX I have no idea what this really does, it is from the
        !          1399:                 * Linux driver.
        !          1400:                 */
        !          1401:                bus_space_write_1(bst, bsh, offset + GP0, GP1_OUT);
        !          1402:        }
        !          1403:        DELAY(40000);
        !          1404:
        !          1405:        /* Setup the ethernet interrupt mask. */
        !          1406:        PAGE(sc, 1);
        !          1407:        bus_space_write_1(bst, bsh, offset + IMR0,
        !          1408:            ISR_TX_OFLOW | ISR_PKT_TX | ISR_MAC_INT | /* ISR_RX_EARLY | */
        !          1409:            ISR_RX_FULL | ISR_RX_PKT_REJ | ISR_FORCED_INT);
        !          1410: #if 0
        !          1411:        bus_space_write_1(bst, bsh, offset + IMR0, 0xff);
        !          1412: #endif
        !          1413:        if (!(sc->sc_flags & XEF_DINGO))
        !          1414:                /* XXX What is this?  Not for Dingo at least. */
        !          1415:                bus_space_write_1(bst, bsh, offset + IMR1, 1);
        !          1416:
        !          1417:        /*
        !          1418:         * Disable source insertion.
        !          1419:         * XXX Dingo does not have this bit, but Linux does it unconditionally.
        !          1420:         */
        !          1421:        if (!(sc->sc_flags & XEF_DINGO)) {
        !          1422:                PAGE(sc, 0x42);
        !          1423:                bus_space_write_1(bst, bsh, offset + SWC0, 0x20);
        !          1424:        }
        !          1425:
        !          1426:        /* Set the local memory dividing line. */
        !          1427:        if (sc->sc_rev != 1) {
        !          1428:                PAGE(sc, 2);
        !          1429:                /* XXX Symbolic constant preferrable. */
        !          1430:                bus_space_write_2(bst, bsh, offset + RBS0, 0x2000);
        !          1431:        }
        !          1432:
        !          1433:        xe_set_address(sc);
        !          1434:
        !          1435:        /*
        !          1436:         * Apparently the receive byte pointer can be bad after a reset, so
        !          1437:         * we hardwire it correctly.
        !          1438:         */
        !          1439:        PAGE(sc, 0);
        !          1440:        bus_space_write_2(bst, bsh, offset + DO0, DO_CHG_OFFSET);
        !          1441:
        !          1442:        /* Setup ethernet MAC registers. XXX Symbolic constants. */
        !          1443:        PAGE(sc, 0x40);
        !          1444:        bus_space_write_1(bst, bsh, offset + RX0MSK,
        !          1445:            PKT_TOO_LONG | CRC_ERR | RX_OVERRUN | RX_ABORT | RX_OK);
        !          1446:        bus_space_write_1(bst, bsh, offset + TX0MSK,
        !          1447:            CARRIER_LOST | EXCESSIVE_COLL | TX_UNDERRUN | LATE_COLLISION |
        !          1448:            SQE | TX_ABORT | TX_OK);
        !          1449:        if (!(sc->sc_flags & XEF_DINGO))
        !          1450:                /* XXX From Linux, dunno what 0xb0 means. */
        !          1451:                bus_space_write_1(bst, bsh, offset + TX1MSK, 0xb0);
        !          1452:        bus_space_write_1(bst, bsh, offset + RXST0, 0);
        !          1453:        bus_space_write_1(bst, bsh, offset + TXST0, 0);
        !          1454:        bus_space_write_1(bst, bsh, offset + TXST1, 0);
        !          1455:
        !          1456:        /* Enable MII function if available. */
        !          1457:        if (LIST_FIRST(&sc->sc_mii.mii_phys)) {
        !          1458:                PAGE(sc, 2);
        !          1459:                bus_space_write_1(bst, bsh, offset + MSR,
        !          1460:                    bus_space_read_1(bst, bsh, offset + MSR) | SELECT_MII);
        !          1461:                DELAY(20000);
        !          1462:        } else {
        !          1463:                PAGE(sc, 0);
        !          1464:
        !          1465:                /* XXX Do we need to do this? */
        !          1466:                PAGE(sc, 0x42);
        !          1467:                bus_space_write_1(bst, bsh, offset + SWC1, SWC1_AUTO_MEDIA);
        !          1468:                DELAY(50000);
        !          1469:
        !          1470:                /* XXX Linux probes the media here. */
        !          1471:        }
        !          1472:
        !          1473:        /* Configure the LED registers. */
        !          1474:        PAGE(sc, 2);
        !          1475:
        !          1476:        /* XXX This is not good for 10base2. */
        !          1477:        bus_space_write_1(bst, bsh, offset + LED,
        !          1478:            LED_TX_ACT << LED1_SHIFT | LED_10MB_LINK << LED0_SHIFT);
        !          1479:        if (sc->sc_flags & XEF_DINGO)
        !          1480:                bus_space_write_1(bst, bsh, offset + LED3,
        !          1481:                    LED_100MB_LINK << LED3_SHIFT);
        !          1482:
        !          1483:        /* Enable receiver and go online. */
        !          1484:        PAGE(sc, 0x40);
        !          1485:        bus_space_write_1(bst, bsh, offset + CMD0, ENABLE_RX | ONLINE);
        !          1486:
        !          1487: #if 0
        !          1488:        /* XXX Linux does this here - is it necessary? */
        !          1489:        PAGE(sc, 1);
        !          1490:        bus_space_write_1(bst, bsh, offset + IMR0, 0xff);
        !          1491:        if (!(sc->sc_flags & XEF_DINGO))
        !          1492:                /* XXX What is this?  Not for Dingo at least. */
        !          1493:                bus_space_write_1(bst, bsh, offset + IMR1, 1);
        !          1494: #endif
        !          1495:
        !          1496:        /* Enable interrupts. */
        !          1497:        PAGE(sc, 0);
        !          1498:        bus_space_write_1(bst, bsh, offset + CR, ENABLE_INT);
        !          1499:
        !          1500:        /* XXX This is pure magic for me, found in the Linux driver. */
        !          1501:        if ((sc->sc_flags & (XEF_DINGO | XEF_MODEM)) == XEF_MODEM) {
        !          1502:                if ((bus_space_read_1(bst, bsh, offset + 0x10) & 0x01) == 0)
        !          1503:                        /* Unmask the master interrupt bit. */
        !          1504:                        bus_space_write_1(bst, bsh, offset + 0x10, 0x11);
        !          1505:        }
        !          1506:
        !          1507:        /*
        !          1508:         * The Linux driver says this:
        !          1509:         * We should switch back to page 0 to avoid a bug in revision 0
        !          1510:         * where regs with offset below 8 can't be read after an access
        !          1511:         * to the MAC registers.
        !          1512:         */
        !          1513:        PAGE(sc, 0);
        !          1514: }
        !          1515:
        !          1516: #ifdef XEDEBUG
        !          1517: void
        !          1518: xe_reg_dump(sc)
        !          1519:        struct xe_softc *sc;
        !          1520: {
        !          1521:        int page, i;
        !          1522:        bus_space_tag_t bst = sc->sc_bst;
        !          1523:        bus_space_handle_t bsh = sc->sc_bsh;
        !          1524:        bus_size_t offset = sc->sc_offset;
        !          1525:
        !          1526:        printf("%x: Common registers: ", sc->sc_dev.dv_xname);
        !          1527:        for (i = 0; i < 8; i++) {
        !          1528:                printf(" %2.2x", bus_space_read_1(bst, bsh, offset + i));
        !          1529:        }
        !          1530:        printf("\n");
        !          1531:
        !          1532:        for (page = 0; page < 8; page++) {
        !          1533:                printf("%s: Register page %2.2x: ", sc->sc_dev.dv_xname, page);
        !          1534:                PAGE(sc, page);
        !          1535:                for (i = 8; i < 16; i++) {
        !          1536:                        printf(" %2.2x",
        !          1537:                            bus_space_read_1(bst, bsh, offset + i));
        !          1538:                }
        !          1539:                printf("\n");
        !          1540:        }
        !          1541:
        !          1542:        for (page = 0x40; page < 0x5f; page++) {
        !          1543:                if (page == 0x43 || (page >= 0x46 && page <= 0x4f) ||
        !          1544:                    (page >= 0x51 && page <= 0x5e))
        !          1545:                        continue;
        !          1546:                printf("%s: Register page %2.2x: ", sc->sc_dev.dv_xname, page);
        !          1547:                PAGE(sc, page);
        !          1548:                for (i = 8; i < 16; i++) {
        !          1549:                        printf(" %2.2x",
        !          1550:                            bus_space_read_1(bst, bsh, offset + i));
        !          1551:                }
        !          1552:                printf("\n");
        !          1553:        }
        !          1554: }
        !          1555: #endif /* XEDEBUG */

CVSweb