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

Annotation of sys/dev/pci/if_myx.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_myx.c,v 1.5 2007/06/01 18:07:08 reyk Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * Driver for the Myricom Myri-10G Lanai-Z8E Ethernet chipsets.
        !            21:  */
        !            22:
        !            23: #include "bpfilter.h"
        !            24:
        !            25: #include <sys/param.h>
        !            26: #include <sys/systm.h>
        !            27: #include <sys/sockio.h>
        !            28: #include <sys/mbuf.h>
        !            29: #include <sys/kernel.h>
        !            30: #include <sys/socket.h>
        !            31: #include <sys/malloc.h>
        !            32: #include <sys/timeout.h>
        !            33: #include <sys/proc.h>
        !            34: #include <sys/device.h>
        !            35: #include <sys/sensors.h>
        !            36:
        !            37: #include <machine/bus.h>
        !            38: #include <machine/intr.h>
        !            39:
        !            40: #include <net/if.h>
        !            41: #include <net/if_dl.h>
        !            42: #include <net/if_media.h>
        !            43: #include <net/if_types.h>
        !            44:
        !            45: #if NBPFILTER > 0
        !            46: #include <net/bpf.h>
        !            47: #endif
        !            48:
        !            49: #ifdef INET
        !            50: #include <netinet/in.h>
        !            51: #include <netinet/if_ether.h>
        !            52: #endif
        !            53:
        !            54: #include <dev/pci/pcireg.h>
        !            55: #include <dev/pci/pcivar.h>
        !            56: #include <dev/pci/pcidevs.h>
        !            57:
        !            58: #include <dev/pci/if_myxreg.h>
        !            59:
        !            60: #define MYX_DEBUG
        !            61: #ifdef MYX_DEBUG
        !            62: #define MYXDBG_INIT    (1<<0)  /* chipset initialization */
        !            63: #define MYXDBG_CMD     (2<<0)  /* commands */
        !            64: #define MYXDBG_INTR    (3<<0)  /* interrupts */
        !            65: #define MYXDBG_ALL     0xffff  /* enable all debugging messages */
        !            66: int myx_debug = MYXDBG_ALL;
        !            67: #define DPRINTF(_lvl, _arg...) do {                                    \
        !            68:        if (myx_debug & (_lvl))                                         \
        !            69:                printf(_arg);                                           \
        !            70: } while (0)
        !            71: #else
        !            72: #define DPRINTF(_lvl, arg...)
        !            73: #endif
        !            74:
        !            75: #define DEVNAME(_s)    ((_s)->_s##_dev.dv_xname)
        !            76:
        !            77: struct myx_dmamem {
        !            78:        bus_dmamap_t             mxm_map;
        !            79:        bus_dma_segment_t        mxm_seg;
        !            80:        int                      mxm_nsegs;
        !            81:        size_t                   mxm_size;
        !            82:        caddr_t                  mxm_kva;
        !            83:        const char              *mxm_name;
        !            84: };
        !            85:
        !            86: struct myx_buf {
        !            87:        bus_dmamap_t             mb_dmamap;
        !            88:        struct mbuf             *mb_m;
        !            89: };
        !            90:
        !            91: struct myx_softc {
        !            92:        struct device            sc_dev;
        !            93:        struct arpcom            sc_ac;
        !            94:
        !            95:        pci_chipset_tag_t        sc_pc;
        !            96:        pcitag_t                 sc_tag;
        !            97:        u_int                    sc_function;
        !            98:
        !            99:        bus_dma_tag_t            sc_dmat;
        !           100:        bus_space_tag_t          sc_memt;
        !           101:        bus_space_handle_t       sc_memh;
        !           102:        bus_size_t               sc_mems;
        !           103:
        !           104:        struct myx_dmamem        sc_cmddma;
        !           105:        struct myx_dmamem        sc_paddma;
        !           106:
        !           107:        struct myx_dmamem        sc_stsdma;
        !           108:        struct myx_status       *sc_sts;
        !           109:
        !           110:        struct myx_dmamem        sc_rxdma;
        !           111:        struct myx_rxdesc       *sc_rxdesc;
        !           112:        struct myx_rxbufdesc    *sc_rxbufdesc[2];
        !           113:        struct myx_buf          *sc_rxbuf[2];
        !           114: #define  MYX_RXSMALL            0
        !           115: #define  MYX_RXBIG              1
        !           116:        int                      sc_rxactive;
        !           117:        int                      sc_rxidx;
        !           118:
        !           119:        void                    *sc_irqh;
        !           120:        u_int32_t                sc_irqcoaloff;
        !           121:        u_int32_t                sc_irqclaimoff;
        !           122:        u_int32_t                sc_irqdeassertoff;
        !           123:
        !           124:        u_int8_t                 sc_lladdr[ETHER_ADDR_LEN];
        !           125:        struct ifmedia           sc_media;
        !           126:
        !           127:        u_int32_t                sc_rxringsize;
        !           128:        u_int32_t                sc_rxsmallringoff;
        !           129:        u_int32_t                sc_rxbigringoff;
        !           130:        int                      sc_rxndesc;
        !           131:        size_t                   sc_rxdescsize;
        !           132:        size_t                   sc_rxbufsize;
        !           133:        size_t                   sc_rxbufdescsize;
        !           134:        u_int32_t                sc_txringsize;
        !           135:        u_int32_t                sc_txringoff;
        !           136:        int                      sc_txndesc;
        !           137:
        !           138:        u_int                    sc_phy;        /* PHY type (CX4/SR/LR) */
        !           139:        u_int                    sc_hwflags;
        !           140: #define  MYXFLAG_FLOW_CONTROL   (1<<0)         /* Rx/Tx pause is enabled */
        !           141: #define  MYXFLAG_PROMISC        (1<<1)         /* promisc mode is enabled */
        !           142: #define  MYXFLAG_ALLMULTI       (1<<2)         /* allmulti is set */
        !           143:        u_int8_t                 sc_active;
        !           144:
        !           145:        struct timeout           sc_tick;
        !           146: };
        !           147:
        !           148: int     myx_match(struct device *, void *, void *);
        !           149: void    myx_attach(struct device *, struct device *, void *);
        !           150: int     myx_query(struct myx_softc *sc);
        !           151: u_int   myx_ether_aton(char *, u_int8_t *, u_int);
        !           152: int     myx_loadfirmware(struct myx_softc *, u_int8_t *, size_t,
        !           153:            u_int32_t, int);
        !           154: void    myx_attachhook(void *);
        !           155: void    myx_read(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
        !           156: void    myx_rawread(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
        !           157: void    myx_write(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
        !           158: void    myx_rawwrite(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
        !           159: int     myx_cmd(struct myx_softc *, u_int32_t, struct myx_cmd *, u_int32_t *);
        !           160: int     myx_boot(struct myx_softc *, u_int32_t, struct myx_bootcmd *);
        !           161: int     myx_rdma(struct myx_softc *, u_int);
        !           162: int     myx_reset(struct myx_softc *);
        !           163: int     myx_dmamem_alloc(struct myx_softc *, struct myx_dmamem *,
        !           164:            bus_size_t, u_int align, const char *);
        !           165: void    myx_dmamem_free(struct myx_softc *, struct myx_dmamem *);
        !           166: int     myx_media_change(struct ifnet *);
        !           167: void    myx_media_status(struct ifnet *, struct ifmediareq *);
        !           168: void    myx_link_state(struct myx_softc *);
        !           169: void    myx_watchdog(struct ifnet *);
        !           170: void    myx_tick(void *);
        !           171: int     myx_ioctl(struct ifnet *, u_long, caddr_t);
        !           172: void    myx_iff(struct myx_softc *);
        !           173: void    myx_init(struct ifnet *);
        !           174: void    myx_start(struct ifnet *);
        !           175: void    myx_stop(struct ifnet *);
        !           176: int     myx_setlladdr(struct myx_softc *, u_int8_t *);
        !           177: int     myx_intr(void *);
        !           178: int     myx_init_rings(struct myx_softc *);
        !           179: void    myx_free_rings(struct myx_softc *);
        !           180: struct mbuf *myx_getbuf(struct myx_softc *, bus_dmamap_t, int);
        !           181:
        !           182: struct cfdriver myx_cd = {
        !           183:        0, "myx", DV_IFNET
        !           184: };
        !           185: struct cfattach myx_ca = {
        !           186:        sizeof(struct myx_softc), myx_match, myx_attach
        !           187: };
        !           188:
        !           189: const struct pci_matchid myx_devices[] = {
        !           190:        { PCI_VENDOR_MYRICOM, PCI_PRODUCT_MYRICOM_Z8E }
        !           191: };
        !           192:
        !           193: int
        !           194: myx_match(struct device *parent, void *match, void *aux)
        !           195: {
        !           196:        return (pci_matchbyid((struct pci_attach_args *)aux,
        !           197:            myx_devices, sizeof(myx_devices) / sizeof(myx_devices[0])));
        !           198: }
        !           199:
        !           200: void
        !           201: myx_attach(struct device *parent, struct device *self, void *aux)
        !           202: {
        !           203:        struct myx_softc        *sc = (struct myx_softc *)self;
        !           204:        struct pci_attach_args  *pa = aux;
        !           205:        pci_intr_handle_t        ih;
        !           206:        pcireg_t                 memtype;
        !           207:        const char              *intrstr;
        !           208:        struct ifnet            *ifp;
        !           209:
        !           210:        sc->sc_pc = pa->pa_pc;
        !           211:        sc->sc_tag = pa->pa_tag;
        !           212:        sc->sc_dmat = pa->pa_dmat;
        !           213:        sc->sc_function = pa->pa_function;
        !           214:
        !           215:        memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MYXBAR0);
        !           216:        switch (memtype) {
        !           217:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !           218:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !           219:                break;
        !           220:        default:
        !           221:                printf(": invalid memory type: 0x%x\n", memtype);
        !           222:                return;
        !           223:        }
        !           224:
        !           225:        /* Map the PCI memory space */
        !           226:        if (pci_mapreg_map(pa, MYXBAR0, memtype, 0, &sc->sc_memt,
        !           227:            &sc->sc_memh, NULL, &sc->sc_mems, 0) != 0) {
        !           228:                printf(": unable to map register memory\n");
        !           229:                return;
        !           230:        }
        !           231:
        !           232:        /* Get the board information and initialize the h/w */
        !           233:        if (myx_query(sc) != 0)
        !           234:                goto unmap;
        !           235:
        !           236:        /*
        !           237:         * Allocate command DMA memory
        !           238:         */
        !           239:        if (myx_dmamem_alloc(sc, &sc->sc_cmddma, MYXALIGN_CMD,
        !           240:            MYXALIGN_CMD, "cmd") != 0) {
        !           241:                printf(": failed to allocate command DMA memory\n");
        !           242:                goto unmap;
        !           243:        }
        !           244:
        !           245:        if (myx_dmamem_alloc(sc, &sc->sc_paddma,
        !           246:            MYXALIGN_CMD, MYXALIGN_CMD, "pad") != 0) {
        !           247:                printf(": failed to allocate pad DMA memory\n");
        !           248:                goto err2;
        !           249:        }
        !           250:
        !           251:        if (myx_dmamem_alloc(sc, &sc->sc_stsdma,
        !           252:            sizeof(struct myx_status), MYXALIGN_DATA /* XXX */, "status") != 0) {
        !           253:                printf(": failed to allocate status DMA memory\n");
        !           254:                goto err1;
        !           255:        }
        !           256:        sc->sc_sts = (struct myx_status *)sc->sc_stsdma.mxm_kva;
        !           257:
        !           258:        /*
        !           259:         * Map and establish the interrupt
        !           260:         */
        !           261:        if (pci_intr_map(pa, &ih) != 0) {
        !           262:                printf(": unable to map interrupt\n");
        !           263:                goto err;
        !           264:        }
        !           265:        intrstr = pci_intr_string(pa->pa_pc, ih);
        !           266:        sc->sc_irqh = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
        !           267:            myx_intr, sc, DEVNAME(sc));
        !           268:        if (sc->sc_irqh == NULL) {
        !           269:                printf(": unable to establish interrupt %s\n", intrstr);
        !           270:                goto err;
        !           271:        }
        !           272:        printf(": %s, address %s\n", intrstr,
        !           273:            ether_sprintf(sc->sc_ac.ac_enaddr));
        !           274:
        !           275:        ifp = &sc->sc_ac.ac_if;
        !           276:        ifp->if_softc = sc;
        !           277:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           278:        ifp->if_ioctl = myx_ioctl;
        !           279:        ifp->if_start = myx_start;
        !           280:        ifp->if_watchdog = myx_watchdog;
        !           281:        strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
        !           282:        IFQ_SET_MAXLEN(&ifp->if_snd, MYX_NTXDESC_MIN - 1);
        !           283:        IFQ_SET_READY(&ifp->if_snd);
        !           284:
        !           285:        ifp->if_capabilities = IFCAP_VLAN_MTU;
        !           286: #if 0
        !           287:        ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
        !           288:        ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
        !           289:                    IFCAP_CSUM_UDPv4;
        !           290: #endif
        !           291:        ifp->if_baudrate = ULONG_MAX;   /* XXX fix if_baudrate */
        !           292:
        !           293:        ifmedia_init(&sc->sc_media, 0,
        !           294:            myx_media_change, myx_media_status);
        !           295:        ifmedia_add(&sc->sc_media, IFM_ETHER|sc->sc_phy, 0, NULL);
        !           296:        ifmedia_set(&sc->sc_media, IFM_ETHER|sc->sc_phy);
        !           297:
        !           298:        if_attach(ifp);
        !           299:        ether_ifattach(ifp);
        !           300:
        !           301:        timeout_set(&sc->sc_tick, myx_tick, sc);
        !           302:        timeout_add(&sc->sc_tick, hz);
        !           303:
        !           304:        mountroothook_establish(myx_attachhook, sc);
        !           305:
        !           306:        return;
        !           307:
        !           308:  err:
        !           309:        myx_dmamem_free(sc, &sc->sc_stsdma);
        !           310:  err1:
        !           311:        myx_dmamem_free(sc, &sc->sc_paddma);
        !           312:  err2:
        !           313:        myx_dmamem_free(sc, &sc->sc_cmddma);
        !           314:  unmap:
        !           315:        bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
        !           316:        sc->sc_mems = 0;
        !           317: }
        !           318:
        !           319: u_int
        !           320: myx_ether_aton(char *mac, u_int8_t *lladdr, u_int maxlen)
        !           321: {
        !           322:        u_int           i, j;
        !           323:        u_int8_t        digit;
        !           324:
        !           325:        bzero(lladdr, ETHER_ADDR_LEN);
        !           326:        for (i = j = 0; mac[i] != '\0' && i < maxlen; i++) {
        !           327:                if (mac[i] >= '0' && mac[i] <= '9')
        !           328:                        digit = mac[i] - '0';
        !           329:                else if (mac[i] >= 'A' && mac[i] <= 'F')
        !           330:                        digit = mac[i] - 'A' + 10;
        !           331:                else if (mac[i] >= 'a' && mac[i] <= 'f')
        !           332:                        digit = mac[i] - 'a' + 10;
        !           333:                else
        !           334:                        continue;
        !           335:                if ((j & 1) == 0)
        !           336:                        digit <<= 4;
        !           337:                lladdr[j++/2] |= digit;
        !           338:        }
        !           339:
        !           340:        return (i);
        !           341: }
        !           342:
        !           343: int
        !           344: myx_query(struct myx_softc *sc)
        !           345: {
        !           346:        u_int8_t        eeprom[MYX_EEPROM_SIZE];
        !           347:        u_int           i, maxlen;
        !           348:
        !           349:        myx_read(sc, MYX_EEPROM, eeprom, MYX_EEPROM_SIZE);
        !           350:
        !           351:        for (i = 0; i < MYX_EEPROM_SIZE; i++) {
        !           352:                maxlen = MYX_EEPROM_SIZE - i;
        !           353:                if (eeprom[i] == '\0')
        !           354:                        break;
        !           355:                if (maxlen > 4 && bcmp("MAC=", &eeprom[i], 4) == 0) {
        !           356:                        i += 4;
        !           357:                        i += myx_ether_aton(&eeprom[i],
        !           358:                            sc->sc_ac.ac_enaddr, maxlen);
        !           359:                }
        !           360:                for (; i < MYX_EEPROM_SIZE; i++)
        !           361:                        if (eeprom[i] == '\0')
        !           362:                                break;
        !           363:        }
        !           364:
        !           365:        return (0);
        !           366: }
        !           367:
        !           368: int
        !           369: myx_loadfirmware(struct myx_softc *sc, u_int8_t *fw, size_t fwlen,
        !           370:     u_int32_t fwhdroff, int reload)
        !           371: {
        !           372:        struct myx_firmware_hdr *fwhdr;
        !           373:        u_int                    i, len, ret = 0;
        !           374:
        !           375:        fwhdr = (struct myx_firmware_hdr *)(fw + fwhdroff);
        !           376:        DPRINTF(MYXDBG_INIT, "%s(%s): "
        !           377:            "fw hdr off %d, length %d, type 0x%x, version %s\n",
        !           378:            DEVNAME(sc), __func__,
        !           379:            fwhdroff, betoh32(fwhdr->fw_hdrlength),
        !           380:            betoh32(fwhdr->fw_type),
        !           381:            fwhdr->fw_version);
        !           382:
        !           383:        if (betoh32(fwhdr->fw_type) != MYXFW_TYPE_ETH ||
        !           384:            bcmp(MYXFW_VER, fwhdr->fw_version, strlen(MYXFW_VER)) != 0) {
        !           385:                if (reload)
        !           386:                        printf("%s: invalid firmware type 0x%x version %s\n",
        !           387:                            DEVNAME(sc), betoh32(fwhdr->fw_type),
        !           388:                            fwhdr->fw_version);
        !           389:                ret = 1;
        !           390:                goto done;
        !           391:        }
        !           392:
        !           393:        if (!reload)
        !           394:                goto done;
        !           395:
        !           396:        /* Write the firmware to the card's SRAM */
        !           397:        for (i = 0; i < fwlen; i += 256) {
        !           398:                len = min(256, fwlen - i);
        !           399:                myx_rawwrite(sc, i + MYX_FW, fw + i, min(256, fwlen - i));
        !           400:        }
        !           401:
        !           402:  done:
        !           403:        free(fw, M_DEVBUF);
        !           404:        return (ret);
        !           405: }
        !           406:
        !           407: void
        !           408: myx_attachhook(void *arg)
        !           409: {
        !           410:        struct myx_softc        *sc = (struct myx_softc *)arg;
        !           411:        size_t                   fwlen;
        !           412:        u_int8_t                *fw = NULL;
        !           413:        u_int32_t                fwhdroff;
        !           414:        struct myx_bootcmd       bc;
        !           415:
        !           416:        /*
        !           417:         * First try the firmware found in the SRAM
        !           418:         */
        !           419:        myx_read(sc, MYX_HEADER_POS, (u_int8_t *)&fwhdroff, sizeof(fwhdroff));
        !           420:        fwhdroff = betoh32(fwhdroff);
        !           421:        fwlen = sizeof(struct myx_firmware_hdr);
        !           422:        if ((fwhdroff + fwlen) > MYX_SRAM_SIZE)
        !           423:                goto load;
        !           424:
        !           425:        fw = malloc(fwlen, M_DEVBUF, M_WAIT);
        !           426:        myx_rawread(sc, MYX_HEADER_POS, fw, fwlen);
        !           427:
        !           428:        if (myx_loadfirmware(sc, fw, fwlen, fwhdroff, 0) == 0)
        !           429:                goto boot;
        !           430:
        !           431:  load:
        !           432:        /*
        !           433:         * Now try the firmware stored on disk
        !           434:         */
        !           435:        if (loadfirmware(MYXFW_ALIGNED /* XXX */, &fw, &fwlen) != 0) {
        !           436:                printf("%s: could not load firmware\n", DEVNAME(sc));
        !           437:                return;
        !           438:        }
        !           439:        if (fwlen > MYX_SRAM_SIZE || fwlen < MYXFW_MIN_LEN) {
        !           440:                printf("%s: invalid firmware image size\n", DEVNAME(sc));
        !           441:                goto err;
        !           442:        }
        !           443:
        !           444:        bcopy(fw + MYX_HEADER_POS, &fwhdroff, sizeof(fwhdroff));
        !           445:        fwhdroff = betoh32(fwhdroff);
        !           446:        if ((fwhdroff + sizeof(struct myx_firmware_hdr)) > fwlen) {
        !           447:                printf("%s: invalid firmware image\n", DEVNAME(sc));
        !           448:                goto err;
        !           449:        }
        !           450:
        !           451:        if (myx_loadfirmware(sc, fw, fwlen, fwhdroff, 1) != 0) {
        !           452:                fw = NULL;
        !           453:                goto err;
        !           454:        }
        !           455:        fw = NULL;
        !           456:
        !           457:  boot:
        !           458:        bzero(&bc, sizeof(bc));
        !           459:        if (myx_boot(sc, fwlen, &bc) != 0) {
        !           460:                printf("%s: failed to bootstrap the device\n", DEVNAME(sc));
        !           461:                goto err;
        !           462:        }
        !           463:        if (myx_reset(sc) != 0)
        !           464:                goto err;
        !           465:
        !           466:        sc->sc_active = 1;
        !           467:        return;
        !           468:
        !           469:  err:
        !           470:        if (fw != NULL)
        !           471:                free(fw, M_DEVBUF);
        !           472: }
        !           473:
        !           474: void
        !           475: myx_read(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr, bus_size_t len)
        !           476: {
        !           477:        bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
        !           478:            BUS_SPACE_BARRIER_READ);
        !           479:        bus_space_read_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len / 4);
        !           480: }
        !           481:
        !           482: void
        !           483: myx_rawread(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr,
        !           484:     bus_size_t len)
        !           485: {
        !           486:        bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
        !           487:            BUS_SPACE_BARRIER_READ);
        !           488:        bus_space_read_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len);
        !           489: }
        !           490:
        !           491: void
        !           492: myx_write(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr, bus_size_t len)
        !           493: {
        !           494:        bus_space_write_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len / 4);
        !           495:        bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
        !           496:            BUS_SPACE_BARRIER_WRITE);
        !           497: }
        !           498:
        !           499: void
        !           500: myx_rawwrite(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr,
        !           501:     bus_size_t len)
        !           502: {
        !           503:        bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len);
        !           504:        bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
        !           505:            BUS_SPACE_BARRIER_WRITE);
        !           506: }
        !           507:
        !           508: int
        !           509: myx_dmamem_alloc(struct myx_softc *sc, struct myx_dmamem *mxm,
        !           510:     bus_size_t size, u_int align, const char *mname)
        !           511: {
        !           512:        mxm->mxm_size = size;
        !           513:
        !           514:        if (bus_dmamap_create(sc->sc_dmat, mxm->mxm_size, 1,
        !           515:            mxm->mxm_size, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
        !           516:            &mxm->mxm_map) != 0)
        !           517:                return (1);
        !           518:        if (bus_dmamem_alloc(sc->sc_dmat, mxm->mxm_size,
        !           519:            align, 0, &mxm->mxm_seg, 1, &mxm->mxm_nsegs,
        !           520:            BUS_DMA_WAITOK) != 0)
        !           521:                goto destroy;
        !           522:        if (bus_dmamem_map(sc->sc_dmat, &mxm->mxm_seg, mxm->mxm_nsegs,
        !           523:            mxm->mxm_size, &mxm->mxm_kva, BUS_DMA_WAITOK) != 0)
        !           524:                goto free;
        !           525:        if (bus_dmamap_load(sc->sc_dmat, mxm->mxm_map, mxm->mxm_kva,
        !           526:            mxm->mxm_size, NULL, BUS_DMA_WAITOK) != 0)
        !           527:                goto unmap;
        !           528:
        !           529:        bzero(mxm->mxm_kva, mxm->mxm_size);
        !           530:        mxm->mxm_name = mname;
        !           531:
        !           532:        return (0);
        !           533:  unmap:
        !           534:        bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
        !           535:  free:
        !           536:        bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
        !           537:  destroy:
        !           538:        bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
        !           539:        return (1);
        !           540: }
        !           541:
        !           542: void
        !           543: myx_dmamem_free(struct myx_softc *sc, struct myx_dmamem *mxm)
        !           544: {
        !           545:        bus_dmamap_unload(sc->sc_dmat, mxm->mxm_map);
        !           546:        bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
        !           547:        bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
        !           548:        bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
        !           549: }
        !           550:
        !           551: int
        !           552: myx_cmd(struct myx_softc *sc, u_int32_t cmd, struct myx_cmd *mc, u_int32_t *r)
        !           553: {
        !           554:        bus_dmamap_t             map = sc->sc_cmddma.mxm_map;
        !           555:        struct myx_response     *mr;
        !           556:        u_int                    i;
        !           557:        u_int32_t                result, data;
        !           558: #ifdef MYX_DEBUG
        !           559:        static const char *cmds[MYXCMD_MAX] = {
        !           560:                "CMD_NONE",
        !           561:                "CMD_RESET",
        !           562:                "CMD_GET_VERSION",
        !           563:                "CMD_SET_INTRQDMA",
        !           564:                "CMD_SET_BIGBUFSZ",
        !           565:                "CMD_SET_SMALLBUFSZ",
        !           566:                "CMD_GET_TXRINGOFF",
        !           567:                "CMD_GET_RXSMALLRINGOFF",
        !           568:                "CMD_GET_RXBIGRINGOFF",
        !           569:                "CMD_GET_INTRACKOFF",
        !           570:                "CMD_GET_INTRDEASSERTOFF",
        !           571:                "CMD_GET_TXRINGSZ",
        !           572:                "CMD_GET_RXRINGSZ",
        !           573:                "CMD_SET_INTRQSZ",
        !           574:                "CMD_SET_IFUP",
        !           575:                "CMD_SET_IFDOWN",
        !           576:                "CMD_SET_MTU",
        !           577:                "CMD_GET_INTRCOALDELAYOFF",
        !           578:                "CMD_SET_STATSINTVL",
        !           579:                "CMD_SET_STATSDMA_OLD",
        !           580:                "CMD_SET_PROMISC",
        !           581:                "CMD_UNSET_PROMISC",
        !           582:                "CMD_SET_LLADDR",
        !           583:                "CMD_SET_FC",
        !           584:                "CMD_UNSET_FC",
        !           585:                "CMD_DMA_TEST",
        !           586:                "CMD_SET_ALLMULTI",
        !           587:                "CMD_UNSET_ALLMULTI",
        !           588:                "CMD_SET_MCASTGROUP",
        !           589:                "CMD_UNSET_MCASTGROUP",
        !           590:                "CMD_UNSET_MCAST",
        !           591:                "CMD_SET_STATSDMA",
        !           592:                "CMD_UNALIGNED_DMA_TEST",
        !           593:                "CMD_GET_UNALIGNED_STATUS"
        !           594:        };
        !           595: #endif
        !           596:
        !           597:        mc->mc_cmd = htobe32(cmd);
        !           598:        mc->mc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !           599:        mc->mc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
        !           600:
        !           601:        mr = (struct myx_response *)sc->sc_cmddma.mxm_kva;
        !           602:        mr->mr_result = 0xffffffff;
        !           603:
        !           604:        /* Send command */
        !           605:        myx_write(sc, MYX_CMD, (u_int8_t *)mc, sizeof(struct myx_cmd));
        !           606:
        !           607:        for (i = 0; i < 20; i++) {
        !           608:                bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !           609:                    BUS_DMASYNC_POSTREAD);
        !           610:                result = betoh32(mr->mr_result);
        !           611:                data = betoh32(mr->mr_data);
        !           612:
        !           613:                if (result != 0xffffffff)
        !           614:                        break;
        !           615:                delay(1000);
        !           616:        }
        !           617:
        !           618:        DPRINTF(MYXDBG_CMD, "%s(%s): %s completed, i %d, "
        !           619:            "result 0x%x, data 0x%x (%u)\n", DEVNAME(sc), __func__,
        !           620:            cmds[cmd], i, result, data, data);
        !           621:
        !           622:        if (result != 0)
        !           623:                return (-1);
        !           624:
        !           625:        if (r != NULL)
        !           626:                *r = data;
        !           627:        return (0);
        !           628: }
        !           629:
        !           630: int
        !           631: myx_boot(struct myx_softc *sc, u_int32_t length, struct myx_bootcmd *bc)
        !           632: {
        !           633:        bus_dmamap_t             map = sc->sc_cmddma.mxm_map;
        !           634:        u_int32_t               *status;
        !           635:        u_int                    i;
        !           636:
        !           637:        bc->bc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !           638:        bc->bc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
        !           639:        bc->bc_result = 0xffffffff;
        !           640:        bc->bc_offset = htobe32(MYX_FW_BOOT);
        !           641:        bc->bc_length = htobe32(length);
        !           642:        bc->bc_copyto = htobe32(8);
        !           643:        bc->bc_jumpto = htobe32(0);
        !           644:
        !           645:        status = (u_int32_t *)sc->sc_cmddma.mxm_kva;
        !           646:        *status = 0;
        !           647:
        !           648:        /* Send command */
        !           649:        myx_write(sc, MYX_BOOT, (u_int8_t *)bc, sizeof(struct myx_bootcmd));
        !           650:
        !           651:        for (i = 0; i < 200; i++) {
        !           652:                bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !           653:                    BUS_DMASYNC_POSTREAD);
        !           654:                if (*status == 0xffffffff)
        !           655:                        break;
        !           656:                delay(1000);
        !           657:        }
        !           658:
        !           659:        DPRINTF(MYXDBG_CMD, "%s(%s): boot completed, i %d, result 0x%x\n",
        !           660:            DEVNAME(sc), __func__, i, betoh32(*status));
        !           661:
        !           662:        if (*status != 0xffffffff)
        !           663:                return (-1);
        !           664:
        !           665:        return (0);
        !           666: }
        !           667:
        !           668: int
        !           669: myx_rdma(struct myx_softc *sc, u_int do_enable)
        !           670: {
        !           671:        struct myx_rdmacmd       rc;
        !           672:        bus_dmamap_t             map = sc->sc_cmddma.mxm_map;
        !           673:        bus_dmamap_t             pad = sc->sc_paddma.mxm_map;
        !           674:        u_int32_t               *status;
        !           675:        u_int                    i;
        !           676:
        !           677:        /*
        !           678:         * It is required to setup a _dummy_ RDMA address. It also makes
        !           679:         * some PCI-E chipsets resend dropped messages.
        !           680:         */
        !           681:        rc.rc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !           682:        rc.rc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
        !           683:        rc.rc_result = 0xffffffff;
        !           684:        rc.rc_rdma_high = htobe32(MYX_ADDRHIGH(pad->dm_segs[0].ds_addr));
        !           685:        rc.rc_rdma_low = htobe32(MYX_ADDRLOW(pad->dm_segs[0].ds_addr));
        !           686:        rc.rc_enable = htobe32(do_enable);
        !           687:
        !           688:        status = (u_int32_t *)sc->sc_cmddma.mxm_kva;
        !           689:        *status = 0;
        !           690:
        !           691:        /* Send command */
        !           692:        myx_write(sc, MYX_RDMA, (u_int8_t *)&rc, sizeof(struct myx_rdmacmd));
        !           693:
        !           694:        for (i = 0; i < 20; i++) {
        !           695:                bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !           696:                    BUS_DMASYNC_POSTREAD);
        !           697:                if (*status == 0xffffffff)
        !           698:                        break;
        !           699:                delay(1000);
        !           700:        }
        !           701:
        !           702:        DPRINTF(MYXDBG_CMD, "%s(%s): dummy RDMA %s, i %d, result 0x%x\n",
        !           703:            DEVNAME(sc), __func__,
        !           704:            do_enable ? "enabled" : "disabled", i, betoh32(*status));
        !           705:
        !           706:        if (*status != 0xffffffff)
        !           707:                return (-1);
        !           708:
        !           709:        return (0);
        !           710: }
        !           711:
        !           712: int
        !           713: myx_reset(struct myx_softc *sc)
        !           714: {
        !           715:        struct myx_cmd           mc;
        !           716:        u_int32_t                data;
        !           717:        struct ifnet            *ifp = &sc->sc_ac.ac_if;
        !           718:
        !           719:        bzero(&mc, sizeof(mc));
        !           720:        if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) {
        !           721:                printf("%s: failed to reset the device\n", DEVNAME(sc));
        !           722:                return (-1);
        !           723:        }
        !           724:
        !           725:        if (myx_rdma(sc, MYXRDMA_ON) != 0) {
        !           726:                printf("%s: failed to enable dummy RDMA\n", DEVNAME(sc));
        !           727:                return (-1);
        !           728:        }
        !           729:
        !           730:        if (myx_cmd(sc, MYXCMD_GET_INTRCOALDELAYOFF, &mc,
        !           731:            &sc->sc_irqcoaloff) != 0) {
        !           732:                printf("%s: failed to get IRQ coal offset\n", DEVNAME(sc));
        !           733:                return (-1);
        !           734:        }
        !           735:        data = htobe32(MYX_IRQCOALDELAY);
        !           736:        myx_write(sc, sc->sc_irqcoaloff, (u_int8_t *)&data, sizeof(data));
        !           737:
        !           738:        if (myx_cmd(sc, MYXCMD_GET_INTRACKOFF, &mc,
        !           739:            &sc->sc_irqclaimoff) != 0) {
        !           740:                printf("%s: failed to get IRQ ack offset\n", DEVNAME(sc));
        !           741:                return (-1);
        !           742:        }
        !           743:
        !           744:        if (myx_cmd(sc, MYXCMD_GET_INTRDEASSERTOFF, &mc,
        !           745:            &sc->sc_irqdeassertoff) != 0) {
        !           746:                printf("%s: failed to get IRQ deassert offset\n", DEVNAME(sc));
        !           747:                return (-1);
        !           748:        }
        !           749:
        !           750:        if (myx_cmd(sc, MYXCMD_UNSET_PROMISC, &mc, NULL) != 0) {
        !           751:                printf("%s: failed to disable promisc mode\n", DEVNAME(sc));
        !           752:                return (-1);
        !           753:        }
        !           754:
        !           755:        if (myx_cmd(sc, MYXCMD_FC_DEFAULT, &mc, NULL) != 0) {
        !           756:                printf("%s: failed to configure flow control\n", DEVNAME(sc));
        !           757:                return (-1);
        !           758:        }
        !           759:
        !           760:        if (myx_setlladdr(sc, LLADDR(ifp->if_sadl)) != 0)
        !           761:                return (-1);
        !           762:
        !           763:        return (0);
        !           764: }
        !           765:
        !           766:
        !           767: int
        !           768: myx_media_change(struct ifnet *ifp)
        !           769: {
        !           770:        return (EINVAL);
        !           771: }
        !           772:
        !           773: void
        !           774: myx_media_status(struct ifnet *ifp, struct ifmediareq *imr)
        !           775: {
        !           776:        struct myx_softc        *sc = (struct myx_softc *)ifp->if_softc;
        !           777:
        !           778:        imr->ifm_active = IFM_ETHER|sc->sc_phy;
        !           779:        imr->ifm_status = IFM_AVALID;
        !           780:        myx_link_state(sc);
        !           781:        if (!LINK_STATE_IS_UP(ifp->if_link_state))
        !           782:                return;
        !           783:        imr->ifm_active |= IFM_FDX;
        !           784:        imr->ifm_status |= IFM_ACTIVE;
        !           785:
        !           786:        /* Flow control */
        !           787:        if (sc->sc_hwflags & MYXFLAG_FLOW_CONTROL)
        !           788:                imr->ifm_active |= IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE;
        !           789: }
        !           790:
        !           791: void
        !           792: myx_link_state(struct myx_softc *sc)
        !           793: {
        !           794:        struct ifnet            *ifp = &sc->sc_ac.ac_if;
        !           795:        int                      link_state = LINK_STATE_DOWN;
        !           796:
        !           797:        if (sc->sc_sts == NULL)
        !           798:                return;
        !           799:        if (sc->sc_sts->ms_linkstate == MYXSTS_LINKUP)
        !           800:                link_state = LINK_STATE_FULL_DUPLEX;
        !           801:        if (ifp->if_link_state != link_state) {
        !           802:                ifp->if_link_state = link_state;
        !           803:                if_link_state_change(ifp);
        !           804:        }
        !           805: }
        !           806:
        !           807: void
        !           808: myx_watchdog(struct ifnet *ifp)
        !           809: {
        !           810:        return;
        !           811: }
        !           812:
        !           813: void
        !           814: myx_tick(void *arg)
        !           815: {
        !           816:        struct myx_softc        *sc = (struct myx_softc *)arg;
        !           817:
        !           818:        if (!sc->sc_active)
        !           819:                return;
        !           820:
        !           821:        myx_link_state(sc);
        !           822:        timeout_add(&sc->sc_tick, hz);
        !           823: }
        !           824:
        !           825: int
        !           826: myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        !           827: {
        !           828:        struct myx_softc        *sc = (struct myx_softc *)ifp->if_softc;
        !           829:        struct ifaddr           *ifa = (struct ifaddr *)data;
        !           830:        struct ifreq            *ifr = (struct ifreq *)data;
        !           831:        int                      s, error = 0;
        !           832:
        !           833:        s = splnet();
        !           834:        if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
        !           835:                splx(s);
        !           836:                return (error);
        !           837:        }
        !           838:
        !           839:        switch (cmd) {
        !           840:        case SIOCSIFADDR:
        !           841:                ifp->if_flags |= IFF_UP;
        !           842: #ifdef INET
        !           843:                if (ifa->ifa_addr->sa_family == AF_INET)
        !           844:                        arp_ifinit(&sc->sc_ac, ifa);
        !           845: #endif
        !           846:                /* FALLTHROUGH */
        !           847:        case SIOCSIFFLAGS:
        !           848:                if (ifp->if_flags & IFF_UP) {
        !           849:                        if (ifp->if_flags & IFF_RUNNING)
        !           850:                                myx_iff(sc);
        !           851:                        else
        !           852:                                myx_init(ifp);
        !           853:                } else {
        !           854:                        if (ifp->if_flags & IFF_RUNNING)
        !           855:                                myx_stop(ifp);
        !           856:                }
        !           857:                break;
        !           858:
        !           859:        case SIOCSIFMTU:
        !           860:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
        !           861:                        error = EINVAL;
        !           862:                else if (ifp->if_mtu != ifr->ifr_mtu)
        !           863:                        ifp->if_mtu = ifr->ifr_mtu;
        !           864:                break;
        !           865:
        !           866:        case SIOCADDMULTI:
        !           867:                error = ether_addmulti(ifr, &sc->sc_ac);
        !           868:                break;
        !           869:
        !           870:        case SIOCDELMULTI:
        !           871:                error = ether_delmulti(ifr, &sc->sc_ac);
        !           872:                break;
        !           873:
        !           874:        case SIOCGIFMEDIA:
        !           875:        case SIOCSIFMEDIA:
        !           876:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
        !           877:                break;
        !           878:
        !           879:        default:
        !           880:                error = ENOTTY;
        !           881:        }
        !           882:
        !           883:        if (error == ENETRESET) {
        !           884:                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
        !           885:                    (IFF_UP | IFF_RUNNING))
        !           886:                        myx_iff(sc);
        !           887:                error = 0;
        !           888:        }
        !           889:
        !           890:        splx(s);
        !           891:
        !           892:        return (error);
        !           893: }
        !           894:
        !           895: void
        !           896: myx_iff(struct myx_softc *sc)
        !           897: {
        !           898:        /* XXX set multicast filters etc. */
        !           899:        return;
        !           900: }
        !           901:
        !           902: void
        !           903: myx_init(struct ifnet *ifp)
        !           904: {
        !           905:        struct myx_softc        *sc = (struct myx_softc *)ifp->if_softc;
        !           906:        struct myx_cmd           mc;
        !           907:
        !           908:        if (myx_reset(sc) != 0)
        !           909:                return;
        !           910:
        !           911:        if (myx_init_rings(sc) != 0)
        !           912:                return;
        !           913:
        !           914:        if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) {
        !           915:                printf("%s: failed to start the device\n", DEVNAME(sc));
        !           916:                myx_free_rings(sc);
        !           917:                return;
        !           918:        }
        !           919:
        !           920:        ifp->if_flags |= IFF_RUNNING;
        !           921:        ifp->if_flags &= ~IFF_OACTIVE;
        !           922: }
        !           923:
        !           924: void
        !           925: myx_start(struct ifnet *ifp)
        !           926: {
        !           927: }
        !           928:
        !           929: void
        !           930: myx_stop(struct ifnet *ifp)
        !           931: {
        !           932:        struct myx_softc        *sc = (struct myx_softc *)ifp->if_softc;
        !           933:        struct myx_cmd           mc;
        !           934:
        !           935:        bzero(&mc, sizeof(mc));
        !           936:        (void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL);
        !           937:        myx_free_rings(sc);
        !           938:
        !           939:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !           940: }
        !           941:
        !           942: int
        !           943: myx_setlladdr(struct myx_softc *sc, u_int8_t *addr)
        !           944: {
        !           945:        struct myx_cmd           mc;
        !           946:
        !           947:        bzero(&mc, sizeof(mc));
        !           948:        mc.mc_data0 = addr[3] | addr[2] << 8 | addr[1] << 16 | addr[0] << 24;
        !           949:        mc.mc_data1 = addr[5] | addr[4] << 8;
        !           950:        if (myx_cmd(sc, MYXCMD_SET_LLADDR, &mc, NULL) != 0) {
        !           951:                printf("%s: failed to set the lladdr\n", DEVNAME(sc));
        !           952:                return (-1);
        !           953:        }
        !           954:        return (0);
        !           955: }
        !           956:
        !           957: int
        !           958: myx_intr(void *arg)
        !           959: {
        !           960:        struct myx_softc        *sc = (struct myx_softc *)arg;
        !           961:        u_int32_t                data, valid;
        !           962:        struct myx_status       *sts = sc->sc_sts;
        !           963:        bus_dmamap_t             map = sc->sc_stsdma.mxm_map;
        !           964:
        !           965:        if (!sc->sc_active)
        !           966:                return (0);
        !           967:
        !           968:        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !           969:            BUS_DMASYNC_POSTWRITE);
        !           970:
        !           971:        /*
        !           972:         * XXX The 'valid' flags should be set by the NIC, but it doesn't
        !           973:         * XXX work yet.
        !           974:         */
        !           975:        valid = sts->ms_isvalid;
        !           976:        if (!valid)
        !           977:                return (0);
        !           978:
        !           979:        data = 0;
        !           980:        myx_write(sc, sc->sc_irqdeassertoff, (u_int8_t *)&data, sizeof(data));
        !           981:
        !           982:        DPRINTF(MYXDBG_INTR, "%s(%s): interrupt, valid 0x%x\n",
        !           983:            DEVNAME(sc), __func__, valid);
        !           984:
        !           985: #ifdef MYX_DEBUG
        !           986: #define DPRINT_STATUS(_n)                                              \
        !           987:        DPRINTF(MYXDBG_INTR, "%s(%s): %s: %u, 0x%x\n", DEVNAME(sc), __func__,\
        !           988:            #_n, sts->_n, sts->_n)
        !           989:
        !           990:        DPRINT_STATUS(ms_reserved);
        !           991:        DPRINT_STATUS(ms_dropped_pause);
        !           992:        DPRINT_STATUS(ms_dropped_unicast);
        !           993:        DPRINT_STATUS(ms_dropped_crc32err);
        !           994:        DPRINT_STATUS(ms_dropped_phyerr);
        !           995:        DPRINT_STATUS(ms_dropped_mcast);
        !           996:        DPRINT_STATUS(ms_txdonecnt);
        !           997:        DPRINT_STATUS(ms_linkstate);
        !           998:        DPRINT_STATUS(ms_dropped_linkoverflow);
        !           999:        DPRINT_STATUS(ms_dropped_linkerror);
        !          1000:        DPRINT_STATUS(ms_dropped_runt);
        !          1001:        DPRINT_STATUS(ms_dropped_overrun);
        !          1002:        DPRINT_STATUS(ms_dropped_smallbufunderrun);
        !          1003:        DPRINT_STATUS(ms_dropped_bigbufunderrun);
        !          1004:        DPRINT_STATUS(ms_rdmatags_available);
        !          1005:        DPRINT_STATUS(ms_txstopped);
        !          1006:        DPRINT_STATUS(ms_linkdowncnt);
        !          1007:        DPRINT_STATUS(ms_statusupdated);
        !          1008:        DPRINT_STATUS(ms_isvalid);
        !          1009: #endif
        !          1010:
        !          1011:        data = htobe32(3);
        !          1012:        if (sts->ms_isvalid)
        !          1013:                myx_write(sc, sc->sc_irqclaimoff, (u_int8_t *)&data,
        !          1014:                    sizeof(data));
        !          1015:        myx_write(sc, sc->sc_irqclaimoff + sizeof(u_int32_t),
        !          1016:            (u_int8_t *)&data, sizeof(data));
        !          1017:
        !          1018:        return (1);
        !          1019: }
        !          1020:
        !          1021: int
        !          1022: myx_init_rings(struct myx_softc *sc)
        !          1023: {
        !          1024:        struct myx_cmd           mc;
        !          1025:        struct ifnet            *ifp = &sc->sc_ac.ac_if;
        !          1026:        bus_dmamap_t             map;
        !          1027:        int                      i;
        !          1028:        struct myx_buf          *mb;
        !          1029:        struct myx_rxbufdesc    *rxb;
        !          1030:        u_int32_t                data;
        !          1031:
        !          1032:        bzero(&mc, sizeof(mc));
        !          1033:        if (!(myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc,
        !          1034:            &sc->sc_rxringsize) == 0 && sc->sc_rxringsize &&
        !          1035:            myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc,
        !          1036:            &sc->sc_rxsmallringoff) == 0 && sc->sc_rxsmallringoff &&
        !          1037:            myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc,
        !          1038:            &sc->sc_rxbigringoff) == 0 && sc->sc_rxbigringoff &&
        !          1039:            myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc,
        !          1040:            &sc->sc_txringsize) == 0 && sc->sc_txringsize &&
        !          1041:            myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc,
        !          1042:            &sc->sc_txringoff) == 0 && sc->sc_txringoff)) {
        !          1043:                printf("%s: failed to get ring sizes and offsets\n",
        !          1044:                    DEVNAME(sc));
        !          1045:                return (-1);
        !          1046:        }
        !          1047:        sc->sc_rxndesc = sc->sc_rxringsize / sizeof(struct myx_rxbufdesc);
        !          1048:        sc->sc_txndesc = sc->sc_txringsize / sizeof(struct myx_txdesc);
        !          1049:        sc->sc_rxdescsize = sc->sc_rxndesc * 2 * sizeof(struct myx_rxdesc);
        !          1050:        sc->sc_rxbufsize = sc->sc_rxndesc * sizeof(struct myx_buf);
        !          1051:        sc->sc_rxbufdescsize = sc->sc_rxndesc * sizeof(struct myx_rxbufdesc);
        !          1052:        IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_txndesc - 1);
        !          1053:        IFQ_SET_READY(&ifp->if_snd);
        !          1054:
        !          1055:        DPRINTF(MYXDBG_INIT, "%s(%s): Rx ring ndesc %u size %u bufsize %u, "
        !          1056:            "Tx ring ndesc %u size %u offset 0x%x\n", DEVNAME(sc), __func__,
        !          1057:            sc->sc_rxndesc, sc->sc_rxdescsize, sc->sc_rxringsize,
        !          1058:            sc->sc_txndesc, sc->sc_txringsize, sc->sc_txringoff);
        !          1059:
        !          1060:        /*
        !          1061:         * Setup Rx DMA descriptors
        !          1062:         */
        !          1063:        if (myx_dmamem_alloc(sc, &sc->sc_rxdma,
        !          1064:            sc->sc_rxdescsize, MYXALIGN_DATA, "rxring") != 0) {
        !          1065:                printf(": failed to allocate Rx DMA memory\n");
        !          1066:                return (-1);
        !          1067:        }
        !          1068:        sc->sc_rxdesc = (struct myx_rxdesc *)sc->sc_rxdma.mxm_kva;
        !          1069:
        !          1070:        bzero(&mc, sizeof(mc));
        !          1071:        mc.mc_data0 = htobe32(sc->sc_rxdescsize);
        !          1072:        if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) {
        !          1073:                printf("%s: failed to set Rx DMA size\n", DEVNAME(sc));
        !          1074:                goto err;
        !          1075:        }
        !          1076:
        !          1077:        map = sc->sc_rxdma.mxm_map;
        !          1078:        mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
        !          1079:        mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
        !          1080:        if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) {
        !          1081:                printf("%s: failed to set Rx DMA address\n", DEVNAME(sc));
        !          1082:                goto err;
        !          1083:        }
        !          1084:
        !          1085: #ifdef notyet
        !          1086:        /*
        !          1087:         * XXX It fails to set the MTU and it always returns
        !          1088:         * XXX MYXCMD_ERR_RANGE.
        !          1089:         */
        !          1090:        bzero(&mc, sizeof(mc));
        !          1091:        mc.mc_data0 = ifp->if_mtu + ETHER_HDR_LEN + 4;
        !          1092:        if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) {
        !          1093:                printf("%s: failed to set MTU size %d\n",
        !          1094:                    DEVNAME(sc), ifp->if_mtu + ETHER_HDR_LEN + 4);
        !          1095:                goto err;
        !          1096:        }
        !          1097: #endif
        !          1098:
        !          1099:        /*
        !          1100:         * Setup Rx buffer descriptors
        !          1101:         */
        !          1102:        sc->sc_rxbuf[MYX_RXSMALL] = (struct myx_buf *)
        !          1103:            malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
        !          1104:        sc->sc_rxbufdesc[MYX_RXSMALL] = (struct myx_rxbufdesc *)
        !          1105:            malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
        !          1106:        sc->sc_rxbuf[MYX_RXBIG] = (struct myx_buf *)
        !          1107:            malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
        !          1108:        sc->sc_rxbufdesc[MYX_RXBIG] = (struct myx_rxbufdesc *)
        !          1109:            malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
        !          1110:        if (sc->sc_rxbuf[MYX_RXSMALL] == NULL ||
        !          1111:            sc->sc_rxbufdesc[MYX_RXSMALL] == NULL ||
        !          1112:            sc->sc_rxbuf[MYX_RXBIG] == NULL ||
        !          1113:            sc->sc_rxbufdesc[MYX_RXBIG] == NULL) {
        !          1114:                printf("%s: failed to allocate rx buffers\n", DEVNAME(sc));
        !          1115:                goto err;
        !          1116:        }
        !          1117:
        !          1118:        for (i = 0; i < sc->sc_rxndesc; i++) {
        !          1119:                /*
        !          1120:                 * Small Rx buffers and descriptors
        !          1121:                 */
        !          1122:                mb = sc->sc_rxbuf[MYX_RXSMALL] + i;
        !          1123:                rxb = sc->sc_rxbufdesc[MYX_RXSMALL] + i;
        !          1124:
        !          1125:                if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
        !          1126:                    MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
        !          1127:                        printf("%s: unable to create dmamap for small rx %d\n",
        !          1128:                            DEVNAME(sc), i);
        !          1129:                        goto err;
        !          1130:                }
        !          1131:
        !          1132:                map = mb->mb_dmamap;
        !          1133:                mb->mb_m = myx_getbuf(sc, map, 1);
        !          1134:                if (mb->mb_m == NULL) {
        !          1135:                        bus_dmamap_destroy(sc->sc_dmat, map);
        !          1136:                        goto err;
        !          1137:                }
        !          1138:
        !          1139:                bus_dmamap_sync(sc->sc_dmat, map, 0,
        !          1140:                    mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
        !          1141:
        !          1142:                rxb->rb_addr_high =
        !          1143:                    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !          1144:                rxb->rb_addr_low =
        !          1145:                    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !          1146:
        !          1147:                data = sc->sc_rxsmallringoff + i * sizeof(*rxb);
        !          1148:                myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
        !          1149:
        !          1150:                /*
        !          1151:                 * Big Rx buffers and descriptors
        !          1152:                 */
        !          1153:                mb = sc->sc_rxbuf[MYX_RXBIG] + i;
        !          1154:                rxb = sc->sc_rxbufdesc[MYX_RXBIG] + i;
        !          1155:
        !          1156:                if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
        !          1157:                    MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
        !          1158:                        printf("%s: unable to create dmamap for big rx %d\n",
        !          1159:                            DEVNAME(sc), i);
        !          1160:                        goto err;
        !          1161:                }
        !          1162:
        !          1163:                map = mb->mb_dmamap;
        !          1164:                mb->mb_m = myx_getbuf(sc, map, 1);
        !          1165:                if (mb->mb_m == NULL) {
        !          1166:                        bus_dmamap_destroy(sc->sc_dmat, map);
        !          1167:                        goto err;
        !          1168:                }
        !          1169:
        !          1170:                bus_dmamap_sync(sc->sc_dmat, map, 0,
        !          1171:                    mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
        !          1172:
        !          1173:                rxb->rb_addr_high =
        !          1174:                    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !          1175:                rxb->rb_addr_low =
        !          1176:                    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
        !          1177:
        !          1178:                data = sc->sc_rxbigringoff + i * sizeof(*rxb);
        !          1179:                myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
        !          1180:        }
        !          1181:
        !          1182:        bzero(&mc, sizeof(mc));
        !          1183:        mc.mc_data0 = MYX_MAX_MTU_SMALL;
        !          1184:        if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) {
        !          1185:                printf("%s: failed to set small buf size\n", DEVNAME(sc));
        !          1186:                goto err;
        !          1187:        }
        !          1188:
        !          1189:        bzero(&mc, sizeof(mc));
        !          1190:        mc.mc_data0 = MCLBYTES;
        !          1191:        if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) {
        !          1192:                printf("%s: failed to set big buf size\n", DEVNAME(sc));
        !          1193:                goto err;
        !          1194:        }
        !          1195:
        !          1196:        /*
        !          1197:         * Setup status DMA
        !          1198:         */
        !          1199:        map = sc->sc_stsdma.mxm_map;
        !          1200:
        !          1201:        bzero(&mc, sizeof(mc));
        !          1202:        mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
        !          1203:        mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
        !          1204:        mc.mc_data2 = sizeof(struct myx_status);
        !          1205:        if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) {
        !          1206:                printf("%s: failed to set status DMA offset\n", DEVNAME(sc));
        !          1207:                goto err;
        !          1208:        }
        !          1209:
        !          1210:        bus_dmamap_sync(sc->sc_dmat, map, 0,
        !          1211:            map->dm_mapsize, BUS_DMASYNC_PREWRITE);
        !          1212:
        !          1213:        return (0);
        !          1214:  err:
        !          1215:        myx_free_rings(sc);
        !          1216:        return (-1);
        !          1217: }
        !          1218:
        !          1219: void
        !          1220: myx_free_rings(struct myx_softc *sc)
        !          1221: {
        !          1222:        if (sc->sc_rxbuf[MYX_RXSMALL] != NULL) {
        !          1223:                free(sc->sc_rxbuf[MYX_RXSMALL], M_DEVBUF);
        !          1224:                sc->sc_rxbuf[MYX_RXSMALL] = NULL;
        !          1225:        }
        !          1226:        if (sc->sc_rxbufdesc[MYX_RXSMALL] != NULL) {
        !          1227:                free(sc->sc_rxbufdesc[MYX_RXSMALL], M_DEVBUF);
        !          1228:                sc->sc_rxbufdesc[MYX_RXSMALL] = NULL;
        !          1229:        }
        !          1230:        if (sc->sc_rxbuf[MYX_RXBIG] != NULL) {
        !          1231:                free(sc->sc_rxbuf[MYX_RXBIG], M_DEVBUF);
        !          1232:                sc->sc_rxbuf[MYX_RXBIG] = NULL;
        !          1233:        }
        !          1234:        if (sc->sc_rxbufdesc[MYX_RXBIG] != NULL) {
        !          1235:                free(sc->sc_rxbufdesc[MYX_RXBIG], M_DEVBUF);
        !          1236:                sc->sc_rxbufdesc[MYX_RXBIG] = NULL;
        !          1237:        }
        !          1238:        if (sc->sc_rxdesc != NULL) {
        !          1239:                myx_dmamem_free(sc, &sc->sc_rxdma);
        !          1240:                sc->sc_rxdesc = NULL;
        !          1241:        }
        !          1242:        if (sc->sc_sts != NULL) {
        !          1243:                myx_dmamem_free(sc, &sc->sc_stsdma);
        !          1244:                sc->sc_sts = NULL;
        !          1245:        }
        !          1246:        return;
        !          1247: }
        !          1248:
        !          1249: struct mbuf *
        !          1250: myx_getbuf(struct myx_softc *sc, bus_dmamap_t map, int wait)
        !          1251: {
        !          1252:        struct mbuf             *m = NULL;
        !          1253:
        !          1254:        MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA);
        !          1255:        if (m == NULL)
        !          1256:                goto merr;
        !          1257:
        !          1258:        MCLGET(m, wait ? M_WAIT : M_DONTWAIT);
        !          1259:        if ((m->m_flags & M_EXT) == 0)
        !          1260:                goto merr;
        !          1261:        m->m_len = m->m_pkthdr.len = MCLBYTES;
        !          1262:
        !          1263:        if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
        !          1264:            wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) {
        !          1265:                printf("%s: could not load mbuf dma map\n", DEVNAME(sc));
        !          1266:                goto err;
        !          1267:        }
        !          1268:
        !          1269:        return (m);
        !          1270:  merr:
        !          1271:        printf("%s: unable to allocate mbuf\n", DEVNAME(sc));
        !          1272:  err:
        !          1273:        if (m != NULL)
        !          1274:                m_freem(m);
        !          1275:        return (NULL);
        !          1276: }

CVSweb