[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

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