[BACK]Return to if_xi.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pcmcia

Annotation of src/sys/dev/pcmcia/if_xi.c, Revision 1.2

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

CVSweb <webmaster@jp.NetBSD.org>