root/dev/pci/if_myx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. myx_match
  2. myx_attach
  3. myx_ether_aton
  4. myx_query
  5. myx_loadfirmware
  6. myx_attachhook
  7. myx_read
  8. myx_rawread
  9. myx_write
  10. myx_rawwrite
  11. myx_dmamem_alloc
  12. myx_dmamem_free
  13. myx_cmd
  14. myx_boot
  15. myx_rdma
  16. myx_reset
  17. myx_media_change
  18. myx_media_status
  19. myx_link_state
  20. myx_watchdog
  21. myx_tick
  22. myx_ioctl
  23. myx_iff
  24. myx_init
  25. myx_start
  26. myx_stop
  27. myx_setlladdr
  28. myx_intr
  29. myx_init_rings
  30. myx_free_rings
  31. myx_getbuf

    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 }

/* [<][>][^][v][top][bottom][index][help] */