root/dev/pci/if_vic.c

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

DEFINITIONS

This source file includes following definitions.
  1. vic_match
  2. vic_attach
  3. vic_map_pci
  4. vic_query
  5. vic_alloc_data
  6. vic_init_data
  7. vic_uninit_data
  8. vic_link_state
  9. vic_shutdown
  10. vic_intr
  11. vic_rx_proc
  12. vic_tx_proc
  13. vic_iff
  14. vic_getlladdr
  15. vic_setlladdr
  16. vic_media_change
  17. vic_media_status
  18. vic_start
  19. vic_load_txb
  20. vic_watchdog
  21. vic_ioctl
  22. vic_init
  23. vic_stop
  24. vic_alloc_mbuf
  25. vic_tick
  26. vic_read
  27. vic_write
  28. vic_read_cmd
  29. vic_alloc_dmamem
  30. vic_free_dmamem

    1 /*      $OpenBSD: if_vic.c,v 1.49 2007/06/15 02:29:50 dlg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org>
    5  * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 /*
   21  * Driver for the VMware Virtual NIC ("vmxnet")
   22  */
   23 
   24 #include "bpfilter.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/systm.h>
   28 #include <sys/sockio.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/kernel.h>
   31 #include <sys/socket.h>
   32 #include <sys/malloc.h>
   33 #include <sys/timeout.h>
   34 #include <sys/device.h>
   35 
   36 #include <machine/bus.h>
   37 #include <machine/intr.h>
   38 
   39 #include <net/if.h>
   40 #include <net/if_dl.h>
   41 #include <net/if_media.h>
   42 #include <net/if_types.h>
   43 
   44 #if NBPFILTER > 0
   45 #include <net/bpf.h>
   46 #endif
   47 
   48 #ifdef INET
   49 #include <netinet/in.h>
   50 #include <netinet/if_ether.h>
   51 #endif
   52 
   53 #include <dev/pci/pcireg.h>
   54 #include <dev/pci/pcivar.h>
   55 #include <dev/pci/pcidevs.h>
   56 
   57 #define VIC_PCI_BAR             PCI_MAPREG_START /* Base Address Register */
   58 
   59 #define VIC_MAGIC               0xbabe864f
   60 
   61 /* Register address offsets */
   62 #define VIC_DATA_ADDR           0x0000          /* Shared data address */
   63 #define VIC_DATA_LENGTH         0x0004          /* Shared data length */
   64 #define VIC_Tx_ADDR             0x0008          /* Tx pointer address */
   65 
   66 /* Command register */
   67 #define VIC_CMD                 0x000c          /* Command register */
   68 #define  VIC_CMD_INTR_ACK       0x0001  /* Acknowledge interrupt */
   69 #define  VIC_CMD_MCASTFIL       0x0002  /* Multicast address filter */
   70 #define   VIC_CMD_MCASTFIL_LENGTH       2
   71 #define  VIC_CMD_IFF            0x0004  /* Interface flags */
   72 #define   VIC_CMD_IFF_PROMISC   0x0001          /* Promiscous enabled */
   73 #define   VIC_CMD_IFF_BROADCAST 0x0002          /* Broadcast enabled */
   74 #define   VIC_CMD_IFF_MULTICAST 0x0004          /* Multicast enabled */
   75 #define  VIC_CMD_INTR_DISABLE   0x0020  /* Enable interrupts */
   76 #define  VIC_CMD_INTR_ENABLE    0x0040  /* Disable interrupts */
   77 #define  VIC_CMD_Tx_DONE        0x0100  /* Tx done register */
   78 #define  VIC_CMD_NUM_Rx_BUF     0x0200  /* Number of Rx buffers */
   79 #define  VIC_CMD_NUM_Tx_BUF     0x0400  /* Number of Tx buffers */
   80 #define  VIC_CMD_NUM_PINNED_BUF 0x0800  /* Number of pinned buffers */
   81 #define  VIC_CMD_HWCAP          0x1000  /* Capability register */
   82 #define   VIC_CMD_HWCAP_SG              (1<<0) /* Scatter-gather transmits */
   83 #define   VIC_CMD_HWCAP_CSUM_IPv4       (1<<1) /* TCP/UDP cksum */
   84 #define   VIC_CMD_HWCAP_CSUM_ALL        (1<<3) /* Hardware cksum */
   85 #define   VIC_CMD_HWCAP_CSUM \
   86         (VIC_CMD_HWCAP_CSUM_IPv4 | VIC_CMD_HWCAP_CSUM_ALL)
   87 #define   VIC_CMD_HWCAP_DMA_HIGH                (1<<4) /* High DMA mapping */
   88 #define   VIC_CMD_HWCAP_TOE             (1<<5) /* TCP offload engine */
   89 #define   VIC_CMD_HWCAP_TSO             (1<<6) /* TCP segmentation offload */
   90 #define   VIC_CMD_HWCAP_TSO_SW          (1<<7) /* Software TCP segmentation */
   91 #define   VIC_CMD_HWCAP_VPROM           (1<<8) /* Virtual PROM available */
   92 #define   VIC_CMD_HWCAP_VLAN_Tx         (1<<9) /* Hardware VLAN MTU Rx */
   93 #define   VIC_CMD_HWCAP_VLAN_Rx         (1<<10) /* Hardware VLAN MTU Tx */
   94 #define   VIC_CMD_HWCAP_VLAN_SW         (1<<11) /* Software VLAN MTU */
   95 #define   VIC_CMD_HWCAP_VLAN \
   96         (VIC_CMD_HWCAP_VLAN_Tx | VIC_CMD_HWCAP_VLAN_Rx | \
   97         VIC_CMD_HWCAP_VLAN_SW)
   98 #define  VIC_CMD_HWCAP_BITS \
   99         "\20\01SG\02CSUM4\03CSUM\04HDMA\05TOE\06TSO" \
  100         "\07TSOSW\10VPROM\13VLANTx\14VLANRx\15VLANSW"
  101 #define  VIC_CMD_FEATURE        0x2000  /* Additional feature register */
  102 #define   VIC_CMD_FEATURE_0_Tx          (1<<0)
  103 #define   VIC_CMD_FEATURE_TSO           (1<<1)
  104 
  105 #define VIC_LLADDR              0x0010          /* MAC address register */
  106 #define VIC_VERSION_MINOR       0x0018          /* Minor version register */
  107 #define VIC_VERSION_MAJOR       0x001c          /* Major version register */
  108 #define VIC_VERSION_MAJOR_M     0xffff0000
  109 
  110 /* Status register */
  111 #define VIC_STATUS              0x0020
  112 #define  VIC_STATUS_CONNECTED           (1<<0)
  113 #define  VIC_STATUS_ENABLED             (1<<1)
  114 
  115 #define VIC_TOE_ADDR            0x0024          /* TCP offload address */
  116 
  117 /* Virtual PROM address */
  118 #define VIC_VPROM               0x0028
  119 #define VIC_VPROM_LENGTH        6
  120 
  121 /* Shared DMA data structures */
  122 
  123 struct vic_sg {
  124         u_int32_t       sg_addr_low;
  125         u_int16_t       sg_addr_high;
  126         u_int16_t       sg_length;
  127 } __packed;
  128 
  129 #define VIC_SG_MAX              6
  130 #define VIC_SG_ADDR_MACH        0
  131 #define VIC_SG_ADDR_PHYS        1
  132 #define VIC_SG_ADDR_VIRT        3
  133 
  134 struct vic_sgarray {
  135         u_int16_t       sa_addr_type;
  136         u_int16_t       sa_length;
  137         struct vic_sg   sa_sg[VIC_SG_MAX];
  138 } __packed;
  139 
  140 struct vic_rxdesc {
  141         u_int64_t       rx_physaddr;
  142         u_int32_t       rx_buflength;
  143         u_int32_t       rx_length;
  144         u_int16_t       rx_owner;
  145         u_int16_t       rx_flags;
  146         u_int32_t       rx_priv;
  147 } __packed;
  148 
  149 #define VIC_RX_FLAGS_CSUMHW_OK  0x0001
  150 
  151 struct vic_txdesc {
  152         u_int16_t               tx_flags;
  153         u_int16_t               tx_owner;
  154         u_int32_t               tx_priv;
  155         u_int32_t               tx_tsomss;
  156         struct vic_sgarray      tx_sa;
  157 } __packed;
  158 
  159 #define VIC_TX_FLAGS_KEEP       0x0001
  160 #define VIC_TX_FLAGS_TXURN      0x0002
  161 #define VIC_TX_FLAGS_CSUMHW     0x0004
  162 #define VIC_TX_FLAGS_TSO        0x0008
  163 #define VIC_TX_FLAGS_PINNED     0x0010
  164 #define VIC_TX_FLAGS_QRETRY     0x1000
  165 
  166 struct vic_stats {
  167         u_int32_t               vs_tx_count;
  168         u_int32_t               vs_tx_packets;
  169         u_int32_t               vs_tx_0copy;
  170         u_int32_t               vs_tx_copy;
  171         u_int32_t               vs_tx_maxpending;
  172         u_int32_t               vs_tx_stopped;
  173         u_int32_t               vs_tx_overrun;
  174         u_int32_t               vs_intr;
  175         u_int32_t               vs_rx_packets;
  176         u_int32_t               vs_rx_underrun;
  177 } __packed;
  178 
  179 struct vic_data {
  180         u_int32_t               vd_magic;
  181 
  182         u_int32_t               vd_rx_length;
  183         u_int32_t               vd_rx_nextidx;
  184         u_int32_t               vd_rx_length2;
  185         u_int32_t               vd_rx_nextidx2;
  186 
  187         u_int32_t               vd_irq;
  188         u_int32_t               vd_iff;
  189 
  190         u_int32_t               vd_mcastfil[VIC_CMD_MCASTFIL_LENGTH];
  191 
  192         u_int32_t               vd_reserved1[1];
  193 
  194         u_int32_t               vd_tx_length;
  195         u_int32_t               vd_tx_curidx;
  196         u_int32_t               vd_tx_nextidx;
  197         u_int32_t               vd_tx_stopped;
  198         u_int32_t               vd_tx_triggerlvl;
  199         u_int32_t               vd_tx_queued;
  200         u_int32_t               vd_tx_minlength;
  201 
  202         u_int32_t               vd_reserved2[6];
  203 
  204         u_int32_t               vd_rx_saved_nextidx;
  205         u_int32_t               vd_rx_saved_nextidx2;
  206         u_int32_t               vd_tx_saved_nextidx;
  207 
  208         u_int32_t               vd_length;
  209         u_int32_t               vd_rx_offset;
  210         u_int32_t               vd_rx_offset2;
  211         u_int32_t               vd_tx_offset;
  212         u_int32_t               vd_debug;
  213         u_int32_t               vd_tx_physaddr;
  214         u_int32_t               vd_tx_physaddr_length;
  215         u_int32_t               vd_tx_maxlength;
  216 
  217         struct vic_stats        vd_stats;
  218 } __packed;
  219 
  220 #define VIC_OWNER_DRIVER        0
  221 #define VIC_OWNER_DRIVER_PEND   1
  222 #define VIC_OWNER_NIC           2
  223 #define VIC_OWNER_NIC_PEND      3
  224 
  225 #define VIC_JUMBO_FRAMELEN      9018
  226 #define VIC_JUMBO_MTU           (VIC_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
  227 
  228 #define VIC_NBUF                100
  229 #define VIC_NBUF_MAX            128
  230 #define VIC_MAX_SCATTER         1       /* 8? */
  231 #define VIC_QUEUE_SIZE          VIC_NBUF_MAX
  232 #define VIC_QUEUE2_SIZE         1
  233 #define VIC_INC(_x, _y)         (_x) = ((_x) + 1) % (_y)
  234 #define VIC_TX_TIMEOUT          5
  235 
  236 #define VIC_MIN_FRAMELEN        (ETHER_MIN_LEN - ETHER_CRC_LEN)
  237 
  238 #define VIC_TXURN_WARN(_sc)     ((_sc)->sc_txpending >= ((_sc)->sc_ntxbuf - 5))
  239 #define VIC_TXURN(_sc)          ((_sc)->sc_txpending >= (_sc)->sc_ntxbuf)
  240 
  241 struct vic_rxbuf {
  242         bus_dmamap_t            rxb_dmamap;
  243         struct mbuf             *rxb_m;
  244 };
  245 
  246 struct vic_txbuf {
  247         bus_dmamap_t            txb_dmamap;
  248         struct mbuf             *txb_m;
  249 };
  250 
  251 struct vic_softc {
  252         struct device           sc_dev;
  253 
  254         pci_chipset_tag_t       sc_pc;
  255         pcitag_t                sc_tag;
  256 
  257         bus_space_tag_t         sc_iot;
  258         bus_space_handle_t      sc_ioh;
  259         bus_size_t              sc_ios;
  260         bus_dma_tag_t           sc_dmat;
  261 
  262         void                    *sc_ih;
  263 
  264         struct timeout          sc_tick;
  265 
  266         struct arpcom           sc_ac;
  267         struct ifmedia          sc_media;
  268 
  269         u_int32_t               sc_nrxbuf;
  270         u_int32_t               sc_ntxbuf;
  271         u_int32_t               sc_cap;
  272         u_int32_t               sc_feature;
  273         u_int8_t                sc_lladdr[ETHER_ADDR_LEN];
  274 
  275         bus_dmamap_t            sc_dma_map;
  276         bus_dma_segment_t       sc_dma_seg;
  277         size_t                  sc_dma_size;
  278         caddr_t                 sc_dma_kva;
  279 #define VIC_DMA_DVA(_sc)        ((_sc)->sc_dma_map->dm_segs[0].ds_addr)
  280 #define VIC_DMA_KVA(_sc)        ((void *)(_sc)->sc_dma_kva)
  281 
  282         struct vic_data         *sc_data;
  283 
  284         struct vic_rxbuf        *sc_rxbuf;
  285         struct vic_rxdesc       *sc_rxq;
  286         struct vic_rxdesc       *sc_rxq2;
  287 
  288         struct vic_txbuf        *sc_txbuf;
  289         struct vic_txdesc       *sc_txq;
  290         volatile u_int          sc_txpending;
  291 };
  292 
  293 struct cfdriver vic_cd = {
  294         0, "vic", DV_IFNET
  295 };
  296 
  297 int             vic_match(struct device *, void *, void *);
  298 void            vic_attach(struct device *, struct device *, void *);
  299 
  300 struct cfattach vic_ca = {
  301         sizeof(struct vic_softc), vic_match, vic_attach
  302 };
  303 
  304 int             vic_intr(void *);
  305 void            vic_shutdown(void *);
  306 
  307 int             vic_map_pci(struct vic_softc *, struct pci_attach_args *);
  308 int             vic_query(struct vic_softc *);
  309 int             vic_alloc_data(struct vic_softc *);
  310 int             vic_init_data(struct vic_softc *sc);
  311 int             vic_uninit_data(struct vic_softc *sc);
  312 
  313 u_int32_t       vic_read(struct vic_softc *, bus_size_t);
  314 void            vic_write(struct vic_softc *, bus_size_t, u_int32_t);
  315 
  316 u_int32_t       vic_read_cmd(struct vic_softc *, u_int32_t);
  317 
  318 int             vic_alloc_dmamem(struct vic_softc *);
  319 void            vic_free_dmamem(struct vic_softc *);
  320 
  321 void            vic_link_state(struct vic_softc *);
  322 void            vic_rx_proc(struct vic_softc *);
  323 void            vic_tx_proc(struct vic_softc *);
  324 void            vic_iff(struct vic_softc *);
  325 void            vic_getlladdr(struct vic_softc *);
  326 void            vic_setlladdr(struct vic_softc *);
  327 int             vic_media_change(struct ifnet *);
  328 void            vic_media_status(struct ifnet *, struct ifmediareq *);
  329 void            vic_start(struct ifnet *);
  330 int             vic_load_txb(struct vic_softc *, struct vic_txbuf *,
  331                     struct mbuf *);
  332 void            vic_watchdog(struct ifnet *);
  333 int             vic_ioctl(struct ifnet *, u_long, caddr_t);
  334 void            vic_init(struct ifnet *);
  335 void            vic_stop(struct ifnet *);
  336 void            vic_tick(void *);
  337 
  338 #define DEVNAME(_s)     ((_s)->sc_dev.dv_xname)
  339 
  340 struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t);
  341 
  342 const struct pci_matchid vic_devices[] = {
  343         { PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET }
  344 };
  345 
  346 int
  347 vic_match(struct device *parent, void *match, void *aux)
  348 {
  349         return (pci_matchbyid((struct pci_attach_args *)aux,
  350             vic_devices, sizeof(vic_devices)/sizeof(vic_devices[0])));
  351 }
  352 
  353 void
  354 vic_attach(struct device *parent, struct device *self, void *aux)
  355 {
  356         struct vic_softc                *sc = (struct vic_softc *)self;
  357         struct pci_attach_args          *pa = aux;
  358         struct ifnet                    *ifp;
  359 
  360         if (vic_map_pci(sc, pa) != 0) {
  361                 /* error printed by vic_map_pci */
  362                 return;
  363         }
  364 
  365         if (vic_query(sc) != 0) {
  366                 /* error printed by vic_query */
  367                 return;
  368         }
  369 
  370         if (vic_alloc_data(sc) != 0) {
  371                 /* error printed by vic_alloc */
  372                 return;
  373         }
  374 
  375         timeout_set(&sc->sc_tick, vic_tick, sc);
  376 
  377         bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
  378 
  379         ifp = &sc->sc_ac.ac_if;
  380         ifp->if_softc = sc;
  381         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  382         ifp->if_ioctl = vic_ioctl;
  383         ifp->if_start = vic_start;
  384         ifp->if_watchdog = vic_watchdog;
  385         ifp->if_hardmtu = VIC_JUMBO_MTU;
  386         strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
  387         IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_ntxbuf - 1);
  388         IFQ_SET_READY(&ifp->if_snd);
  389 
  390         ifp->if_capabilities = IFCAP_VLAN_MTU;
  391 
  392 #if 0
  393         /* XXX interface capabilities */
  394         if (sc->sc_cap & VIC_CMD_HWCAP_VLAN)
  395                 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
  396         if (sc->sc_cap & VIC_CMD_HWCAP_CSUM)
  397                 ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
  398                     IFCAP_CSUM_UDPv4;
  399 #endif
  400 
  401         ifmedia_init(&sc->sc_media, 0, vic_media_change, vic_media_status);
  402         ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
  403         ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
  404 
  405         if_attach(ifp);
  406         ether_ifattach(ifp);
  407 
  408         return;
  409 }
  410 
  411 int
  412 vic_map_pci(struct vic_softc *sc, struct pci_attach_args *pa)
  413 {
  414         pcireg_t                        memtype;
  415         pci_intr_handle_t               ih;
  416         const char                      *intrstr;
  417 
  418         sc->sc_pc = pa->pa_pc;
  419         sc->sc_tag = pa->pa_tag;
  420         sc->sc_dmat = pa->pa_dmat;
  421 
  422         memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, VIC_PCI_BAR);
  423         if (pci_mapreg_map(pa, VIC_PCI_BAR, memtype, 0, &sc->sc_iot,
  424             &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
  425                 printf(": unable to map system interface register\n");
  426                 return (1);
  427         }
  428 
  429         if (pci_intr_map(pa, &ih) != 0) {
  430                 printf(": unable to map interrupt\n");
  431                 goto unmap;
  432         }
  433 
  434         intrstr = pci_intr_string(pa->pa_pc, ih);
  435         sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
  436             vic_intr, sc, DEVNAME(sc));
  437         if (sc->sc_ih == NULL) {
  438                 printf(": unable to map interrupt%s%s\n",
  439                     intrstr == NULL ? "" : " at ",
  440                     intrstr == NULL ? "" : intrstr);
  441                 goto unmap;
  442         }
  443         printf(": %s\n", intrstr);
  444 
  445         return (0);
  446 
  447 unmap:
  448         bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
  449         sc->sc_ios = 0;
  450         return (1);
  451 }
  452 
  453 int
  454 vic_query(struct vic_softc *sc)
  455 {
  456         u_int32_t                       major, minor;
  457 
  458         major = vic_read(sc, VIC_VERSION_MAJOR);
  459         minor = vic_read(sc, VIC_VERSION_MINOR);
  460 
  461         /* Check for a supported version */
  462         if ((major & VIC_VERSION_MAJOR_M) !=
  463             (VIC_MAGIC & VIC_VERSION_MAJOR_M)) {
  464                 printf("%s: magic mismatch\n", DEVNAME(sc));
  465                 return (1);
  466         }
  467 
  468         if (VIC_MAGIC > major || VIC_MAGIC < minor) {
  469                 printf("%s: unsupported version (%X)\n", DEVNAME(sc),
  470                     major & ~VIC_VERSION_MAJOR_M);
  471                 return (1);
  472         }
  473 
  474         sc->sc_nrxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Rx_BUF);
  475         sc->sc_ntxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Tx_BUF);
  476         sc->sc_feature = vic_read_cmd(sc, VIC_CMD_FEATURE);
  477         sc->sc_cap = vic_read_cmd(sc, VIC_CMD_HWCAP);
  478 
  479         vic_getlladdr(sc);
  480 
  481         printf("%s: VMXnet %04X, address %s\n", DEVNAME(sc),
  482             major & ~VIC_VERSION_MAJOR_M, ether_sprintf(sc->sc_lladdr));
  483 
  484 #ifdef VIC_DEBUG
  485         printf("%s: feature 0x%8x, cap 0x%8x, rx/txbuf %d/%d\n", DEVNAME(sc),
  486             sc->sc_feature, sc->sc_cap, sc->sc_nrxbuf, sc->sc_ntxbuf);
  487 #endif
  488 
  489         if (sc->sc_nrxbuf > VIC_NBUF_MAX || sc->sc_nrxbuf == 0)
  490                 sc->sc_nrxbuf = VIC_NBUF;
  491         if (sc->sc_ntxbuf > VIC_NBUF_MAX || sc->sc_ntxbuf == 0)
  492                 sc->sc_ntxbuf = VIC_NBUF;
  493 
  494         return (0);
  495 }
  496 
  497 int
  498 vic_alloc_data(struct vic_softc *sc)
  499 {
  500         u_int8_t                        *kva;
  501         u_int                           offset;
  502         struct vic_rxdesc               *rxd;
  503         int                             i;
  504 
  505         sc->sc_rxbuf = malloc(sizeof(struct vic_rxbuf) * sc->sc_nrxbuf,
  506             M_NOWAIT, M_DEVBUF);
  507         if (sc->sc_rxbuf == NULL) {
  508                 printf("%s: unable to allocate rxbuf\n", DEVNAME(sc));
  509                 goto err;
  510         }
  511 
  512         sc->sc_txbuf = malloc(sizeof(struct vic_txbuf) * sc->sc_ntxbuf,
  513             M_NOWAIT, M_DEVBUF);
  514         if (sc->sc_txbuf == NULL) {
  515                 printf("%s: unable to allocate txbuf\n", DEVNAME(sc));
  516                 goto freerx;
  517         }
  518 
  519         sc->sc_dma_size = sizeof(struct vic_data) +
  520             (sc->sc_nrxbuf + VIC_QUEUE2_SIZE) * sizeof(struct vic_rxdesc) +
  521             sc->sc_ntxbuf * sizeof(struct vic_txdesc);
  522 
  523         if (vic_alloc_dmamem(sc) != 0) {
  524                 printf("%s: unable to allocate dma region\n", DEVNAME(sc));
  525                 goto freetx;
  526         }
  527         kva = VIC_DMA_KVA(sc);
  528 
  529         /* set up basic vic data */
  530         sc->sc_data = VIC_DMA_KVA(sc);
  531 
  532         sc->sc_data->vd_magic = VIC_MAGIC;
  533         sc->sc_data->vd_length = sc->sc_dma_size;
  534 
  535         offset = sizeof(struct vic_data);
  536 
  537         /* set up the rx ring */
  538         sc->sc_rxq = (struct vic_rxdesc *)&kva[offset];
  539 
  540         sc->sc_data->vd_rx_offset = offset;
  541         sc->sc_data->vd_rx_length = sc->sc_nrxbuf;
  542 
  543         offset += sizeof(struct vic_rxdesc) * sc->sc_nrxbuf;
  544 
  545         /* set up the dummy rx ring 2 with an unusable entry */
  546         sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset];
  547 
  548         sc->sc_data->vd_rx_offset2 = offset;
  549         sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE;
  550 
  551         for (i = 0; i < VIC_QUEUE2_SIZE; i++) {
  552                 rxd = &sc->sc_rxq2[i];
  553 
  554                 rxd->rx_physaddr = 0;
  555                 rxd->rx_buflength = 0;
  556                 rxd->rx_length = 0;
  557                 rxd->rx_owner = VIC_OWNER_DRIVER;
  558 
  559                 offset += sizeof(struct vic_rxdesc);
  560         }
  561 
  562         /* set up the tx ring */
  563         sc->sc_txq = (struct vic_txdesc *)&kva[offset];
  564 
  565         sc->sc_data->vd_tx_offset = offset;
  566         sc->sc_data->vd_tx_length = sc->sc_ntxbuf;
  567 
  568         return (0);
  569 freetx:
  570         free(sc->sc_txbuf, M_DEVBUF);
  571 freerx:
  572         free(sc->sc_rxbuf, M_DEVBUF);
  573 err:
  574         return (1);
  575 }
  576 
  577 int
  578 vic_init_data(struct vic_softc *sc)
  579 {
  580         struct vic_rxbuf                *rxb;
  581         struct vic_rxdesc               *rxd;
  582         struct vic_txbuf                *txb;
  583 
  584         int                             i;
  585 
  586         for (i = 0; i < sc->sc_nrxbuf; i++) {
  587                 rxb = &sc->sc_rxbuf[i];
  588                 rxd = &sc->sc_rxq[i];
  589 
  590                 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
  591                     MCLBYTES, 0, BUS_DMA_NOWAIT, &rxb->rxb_dmamap) != 0) {
  592                         printf("%s: unable to create dmamap for rxb %d\n",
  593                             DEVNAME(sc), i);
  594                         goto freerxbs;
  595                 }
  596 
  597                 rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap);
  598                 if (rxb->rxb_m == NULL) {
  599                         /* error already printed */
  600                         bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
  601                         goto freerxbs;
  602                 }
  603 
  604                 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
  605                     rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
  606 
  607                 rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr;
  608                 rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len; /* XXX? */
  609                 rxd->rx_length = 0;
  610                 rxd->rx_owner = VIC_OWNER_NIC;
  611         }
  612 
  613         for (i = 0; i < sc->sc_ntxbuf; i++) {
  614                 txb = &sc->sc_txbuf[i];
  615                 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
  616                     (sc->sc_cap & VIC_CMD_HWCAP_SG) ? VIC_SG_MAX : 1,
  617                     MCLBYTES, 0, BUS_DMA_NOWAIT, &txb->txb_dmamap) != 0) {
  618                         printf("%s: unable to create dmamap for tx %d\n",
  619                             DEVNAME(sc), i);
  620                         goto freetxbs;
  621                 }
  622                 txb->txb_m = NULL;
  623         }
  624 
  625         return (0);
  626 
  627 freetxbs:
  628         while (i--) {
  629                 txb = &sc->sc_txbuf[i];
  630                 bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
  631         }
  632 
  633         i = sc->sc_nrxbuf;
  634 freerxbs:
  635         while (i--) {
  636                 rxb = &sc->sc_rxbuf[i];
  637                 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
  638                     rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
  639                 bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
  640                 bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
  641         }
  642 
  643         return (1);
  644 }
  645 
  646 int
  647 vic_uninit_data(struct vic_softc *sc)
  648 {
  649         struct vic_rxbuf                *rxb;
  650         struct vic_rxdesc               *rxd;
  651         struct vic_txbuf                *txb;
  652 
  653         int                             i;
  654 
  655         for (i = 0; i < sc->sc_nrxbuf; i++) {
  656                 rxb = &sc->sc_rxbuf[i];
  657                 rxd = &sc->sc_rxq[i];
  658 
  659                 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
  660                     rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
  661                 bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
  662                 bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
  663 
  664                 m_freem(rxb->rxb_m);
  665                 rxb->rxb_m = NULL;
  666         }
  667 
  668         for (i = 0; i < sc->sc_ntxbuf; i++) {
  669                 txb = &sc->sc_txbuf[i];
  670                 bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
  671         }
  672 
  673         return (0);
  674 }
  675 
  676 void
  677 vic_link_state(struct vic_softc *sc)
  678 {
  679         struct ifnet *ifp = &sc->sc_ac.ac_if;
  680         u_int32_t status;
  681         int link_state = LINK_STATE_DOWN;
  682 
  683         status = vic_read(sc, VIC_STATUS);
  684         if (status & VIC_STATUS_CONNECTED)
  685                 link_state = LINK_STATE_FULL_DUPLEX;
  686         if (ifp->if_link_state != link_state) {
  687                 ifp->if_link_state = link_state;
  688                 if_link_state_change(ifp);
  689         }
  690 }
  691 
  692 void
  693 vic_shutdown(void *self)
  694 {
  695         struct vic_softc *sc = (struct vic_softc *)self;
  696 
  697         vic_stop(&sc->sc_ac.ac_if);
  698 }
  699 
  700 int
  701 vic_intr(void *arg)
  702 {
  703         struct vic_softc *sc = (struct vic_softc *)arg;
  704 
  705         vic_rx_proc(sc);
  706         vic_tx_proc(sc);
  707 
  708         vic_write(sc, VIC_CMD, VIC_CMD_INTR_ACK);
  709 
  710         return (1);
  711 }
  712 
  713 void
  714 vic_rx_proc(struct vic_softc *sc)
  715 {
  716         struct ifnet                    *ifp = &sc->sc_ac.ac_if;
  717         struct vic_rxdesc               *rxd;
  718         struct vic_rxbuf                *rxb;
  719         struct mbuf                     *m;
  720         int                             len, idx;
  721 
  722         if ((ifp->if_flags & IFF_RUNNING) == 0)
  723                 return;
  724 
  725         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
  726             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  727 
  728         for (;;) {
  729                 idx = sc->sc_data->vd_rx_nextidx;
  730                 if (idx >= sc->sc_data->vd_rx_length) {
  731                         ifp->if_ierrors++;
  732                         if (ifp->if_flags & IFF_DEBUG)
  733                                 printf("%s: receive index error\n",
  734                                     sc->sc_dev.dv_xname);
  735                         break;
  736                 }
  737 
  738                 rxd = &sc->sc_rxq[idx];
  739                 if (rxd->rx_owner != VIC_OWNER_DRIVER)
  740                         break;
  741 
  742                 rxb = &sc->sc_rxbuf[idx];
  743 
  744                 len = rxd->rx_length;
  745                 if (len < VIC_MIN_FRAMELEN) {
  746                         ifp->if_iqdrops++;
  747                         goto nextp;
  748                 }
  749 
  750                 if (rxb->rxb_m == NULL) {
  751                         ifp->if_ierrors++;
  752                         printf("%s: rxb %d has no mbuf\n", DEVNAME(sc), idx);
  753                         break;
  754                 }
  755 
  756                 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
  757                     rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
  758                 bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
  759 
  760                 m = rxb->rxb_m;
  761                 rxb->rxb_m = NULL;
  762                 m->m_pkthdr.rcvif = ifp;
  763                 m->m_pkthdr.len = m->m_len = len;
  764 
  765                 /* Get new mbuf for the Rx queue */
  766                 rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap);
  767                 if (rxb->rxb_m == NULL) {
  768                         ifp->if_ierrors++;
  769                         printf("%s: mbuf alloc failed\n", DEVNAME(sc));
  770                         break;
  771                 }
  772                 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
  773                     rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
  774 
  775                 rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr;
  776                 rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len;
  777                 rxd->rx_length = 0;
  778                 rxd->rx_owner = VIC_OWNER_DRIVER;
  779 
  780                 ifp->if_ipackets++;
  781 
  782 #if NBPFILTER > 0
  783                 if (ifp->if_bpf)
  784                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
  785 #endif
  786 
  787                 ether_input_mbuf(ifp, m);
  788 
  789 nextp:
  790                 rxd->rx_owner = VIC_OWNER_NIC;
  791                 VIC_INC(sc->sc_data->vd_rx_nextidx, sc->sc_data->vd_rx_length);
  792         }
  793 
  794         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
  795             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  796 }
  797 
  798 void
  799 vic_tx_proc(struct vic_softc *sc)
  800 {
  801         struct ifnet                    *ifp = &sc->sc_ac.ac_if;
  802         struct vic_txdesc               *txd;
  803         struct vic_txbuf                *txb;
  804         int                             idx;
  805 
  806         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
  807             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  808 
  809         while (sc->sc_txpending > 0) {
  810                 idx = sc->sc_data->vd_tx_curidx;
  811                 if (idx >= sc->sc_data->vd_tx_length) {
  812                         ifp->if_oerrors++;
  813                         break;
  814                 }
  815 
  816                 txd = &sc->sc_txq[idx];
  817                 if (txd->tx_owner != VIC_OWNER_DRIVER)
  818                         break;
  819 
  820                 txb = &sc->sc_txbuf[idx];
  821                 if (txb->txb_m == NULL) {
  822                         printf("%s: tx ring is corrupt\n", DEVNAME(sc));
  823                         ifp->if_oerrors++;
  824                         break;
  825                 }
  826 
  827                 bus_dmamap_sync(sc->sc_dmat, txb->txb_dmamap, 0,
  828                     txb->txb_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
  829                 bus_dmamap_unload(sc->sc_dmat, txb->txb_dmamap);
  830 
  831                 m_freem(txb->txb_m);
  832                 txb->txb_m = NULL;
  833                 ifp->if_flags &= ~IFF_OACTIVE;
  834 
  835                 sc->sc_txpending--;
  836                 sc->sc_data->vd_tx_stopped = 0;
  837 
  838                 VIC_INC(sc->sc_data->vd_tx_curidx, sc->sc_data->vd_tx_length);
  839         }
  840 
  841         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
  842             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  843 
  844         vic_start(ifp);
  845 }
  846 
  847 void
  848 vic_iff(struct vic_softc *sc)
  849 {
  850         struct arpcom *ac = &sc->sc_ac;
  851         struct ifnet *ifp = &sc->sc_ac.ac_if;
  852         struct ether_multi *enm;
  853         struct ether_multistep step;
  854         u_int32_t crc;
  855         u_int16_t *mcastfil = (u_int16_t *)sc->sc_data->vd_mcastfil;
  856         u_int flags = 0;
  857 
  858         bzero(&sc->sc_data->vd_mcastfil, sizeof(sc->sc_data->vd_mcastfil));
  859         ifp->if_flags &= ~IFF_ALLMULTI;
  860 
  861         if ((ifp->if_flags & IFF_RUNNING) == 0)
  862                 goto domulti;
  863         if (ifp->if_flags & IFF_PROMISC)
  864                 goto allmulti;
  865 
  866         ETHER_FIRST_MULTI(step, ac, enm);
  867         while (enm != NULL) {
  868                 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN))
  869                         goto allmulti;
  870 
  871                 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
  872                 crc >>= 26;
  873                 mcastfil[crc >> 4] |= htole16(1 << (crc & 0xf));
  874 
  875                 ETHER_NEXT_MULTI(step, enm);
  876         }
  877 
  878         goto domulti;
  879 
  880  allmulti:
  881         ifp->if_flags |= IFF_ALLMULTI;
  882         memset(&sc->sc_data->vd_mcastfil, 0xff,
  883             sizeof(sc->sc_data->vd_mcastfil));
  884 
  885  domulti:
  886         vic_write(sc, VIC_CMD, VIC_CMD_MCASTFIL);
  887 
  888         if (ifp->if_flags & IFF_RUNNING) {
  889                 flags = (ifp->if_flags & IFF_PROMISC) ?
  890                     VIC_CMD_IFF_PROMISC :
  891                     (VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST);
  892         }
  893         sc->sc_data->vd_iff = flags;
  894         vic_write(sc, VIC_CMD, VIC_CMD_IFF);
  895 }
  896 
  897 void
  898 vic_getlladdr(struct vic_softc *sc)
  899 {
  900         u_int32_t reg;
  901 
  902         /* Get MAC address */
  903         reg = (sc->sc_cap & VIC_CMD_HWCAP_VPROM) ? VIC_VPROM : VIC_LLADDR;
  904 
  905         bus_space_barrier(sc->sc_iot, sc->sc_ioh, reg, ETHER_ADDR_LEN,
  906             BUS_SPACE_BARRIER_READ);
  907         bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, reg, sc->sc_lladdr,
  908             ETHER_ADDR_LEN);
  909 
  910         /* Update the MAC address register */
  911         if (reg == VIC_VPROM)
  912                 vic_setlladdr(sc);
  913 }
  914 
  915 void
  916 vic_setlladdr(struct vic_softc *sc)
  917 {
  918         bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, VIC_LLADDR,
  919             sc->sc_lladdr, ETHER_ADDR_LEN);
  920         bus_space_barrier(sc->sc_iot, sc->sc_ioh, VIC_LLADDR, ETHER_ADDR_LEN,
  921             BUS_SPACE_BARRIER_WRITE);
  922 }
  923 
  924 int
  925 vic_media_change(struct ifnet *ifp)
  926 {
  927         /* Ignore */
  928         return (0);
  929 }
  930 
  931 void
  932 vic_media_status(struct ifnet *ifp, struct ifmediareq *imr)
  933 {
  934         struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
  935 
  936         imr->ifm_active = IFM_ETHER | IFM_AUTO;
  937         imr->ifm_status = IFM_AVALID;
  938 
  939         vic_link_state(sc);
  940 
  941         if (LINK_STATE_IS_UP(ifp->if_link_state) &&
  942             ifp->if_flags & IFF_UP)
  943                 imr->ifm_status |= IFM_ACTIVE;
  944 }
  945 
  946 void
  947 vic_start(struct ifnet *ifp)
  948 {
  949         struct vic_softc                *sc;
  950         struct mbuf                     *m;
  951         struct vic_txbuf                *txb;
  952         struct vic_txdesc               *txd;
  953         struct vic_sg                   *sge;
  954         bus_dmamap_t                    dmap;
  955         int                             i, idx;
  956         int                             tx = 0;
  957 
  958         if (!(ifp->if_flags & IFF_RUNNING))
  959                 return;
  960 
  961         if (ifp->if_flags & IFF_OACTIVE)
  962                 return;
  963 
  964         if (IFQ_IS_EMPTY(&ifp->if_snd))
  965                 return;
  966 
  967         sc = (struct vic_softc *)ifp->if_softc;
  968 
  969         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
  970             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  971 
  972         for (;;) {
  973                 if (VIC_TXURN(sc)) {
  974                         ifp->if_flags |= IFF_OACTIVE;
  975                         break;
  976                 }
  977 
  978                 IFQ_POLL(&ifp->if_snd, m);
  979                 if (m == NULL)
  980                         break;
  981 
  982                 idx = sc->sc_data->vd_tx_nextidx;
  983                 if (idx >= sc->sc_data->vd_tx_length) {
  984                         printf("%s: tx idx is corrupt\n", DEVNAME(sc));
  985                         ifp->if_oerrors++;
  986                         break;
  987                 }
  988 
  989                 txd = &sc->sc_txq[idx];
  990                 txb = &sc->sc_txbuf[idx];
  991 
  992                 if (txb->txb_m != NULL) {
  993                         printf("%s: tx ring is corrupt\n", DEVNAME(sc));
  994                         sc->sc_data->vd_tx_stopped = 1;
  995                         ifp->if_oerrors++;
  996                         break;
  997                 }
  998 
  999                 /*
 1000                  * we're committed to sending it now. if we cant map it into
 1001                  * dma memory then we drop it.
 1002                  */
 1003                 IFQ_DEQUEUE(&ifp->if_snd, m);
 1004                 if (vic_load_txb(sc, txb, m) != 0) {
 1005                         m_freem(m);
 1006                         ifp->if_oerrors++;
 1007                         /* continue? */
 1008                         break;
 1009                 }
 1010 
 1011 #if NBPFILTER > 0
 1012                 if (ifp->if_bpf)
 1013                         bpf_mtap(ifp->if_bpf, txb->txb_m, BPF_DIRECTION_OUT);
 1014 #endif
 1015 
 1016                 dmap = txb->txb_dmamap;
 1017                 txd->tx_flags = VIC_TX_FLAGS_KEEP;
 1018                 txd->tx_owner = VIC_OWNER_NIC;
 1019                 txd->tx_sa.sa_addr_type = VIC_SG_ADDR_PHYS;
 1020                 txd->tx_sa.sa_length = dmap->dm_nsegs;
 1021                 for (i = 0; i < dmap->dm_nsegs; i++) {
 1022                         sge = &txd->tx_sa.sa_sg[i];
 1023                         sge->sg_length = dmap->dm_segs[i].ds_len;
 1024                         sge->sg_addr_low = dmap->dm_segs[i].ds_addr;
 1025                 }
 1026 
 1027                 if (VIC_TXURN_WARN(sc)) {
 1028                         txd->tx_flags |= VIC_TX_FLAGS_TXURN;
 1029                 }
 1030 
 1031                 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
 1032                     BUS_DMASYNC_PREWRITE);
 1033 
 1034                 ifp->if_opackets++;
 1035                 sc->sc_txpending++;
 1036 
 1037                 VIC_INC(sc->sc_data->vd_tx_nextidx, sc->sc_data->vd_tx_length);
 1038 
 1039                 tx = 1;
 1040         }
 1041 
 1042         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
 1043             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1044 
 1045         if (tx)
 1046                 vic_read(sc, VIC_Tx_ADDR);
 1047 }
 1048 
 1049 int
 1050 vic_load_txb(struct vic_softc *sc, struct vic_txbuf *txb, struct mbuf *m)
 1051 {
 1052         bus_dmamap_t                    dmap = txb->txb_dmamap;
 1053         struct mbuf                     *m0 = NULL;
 1054         int                             error;
 1055 
 1056         error = bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m, BUS_DMA_NOWAIT);
 1057         switch (error) {
 1058         case 0:
 1059                 txb->txb_m = m;
 1060                 break;
 1061 
 1062         case EFBIG: /* mbuf chain is too fragmented */
 1063                 MGETHDR(m0, M_DONTWAIT, MT_DATA);
 1064                 if (m0 == NULL)
 1065                         return (ENOBUFS);
 1066                 if (m->m_pkthdr.len > MHLEN) {
 1067                         MCLGET(m0, M_DONTWAIT);
 1068                         if (!(m0->m_flags & M_EXT)) {
 1069                                 m_freem(m0);
 1070                                 return (ENOBUFS);
 1071                         }
 1072                 }
 1073                 m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
 1074                 m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
 1075                 error = bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m0,
 1076                     BUS_DMA_NOWAIT);
 1077                 if (error != 0) {
 1078                         m_freem(m0);
 1079                         printf("%s: tx dmamap load error %d\n", DEVNAME(sc),
 1080                             error);
 1081                         return (ENOBUFS);
 1082                 }
 1083                 m_freem(m);
 1084                 txb->txb_m = m0;
 1085                 break;
 1086 
 1087         default:
 1088                 printf("%s: tx dmamap load error %d\n", DEVNAME(sc), error);
 1089                 return (ENOBUFS);
 1090         }
 1091 
 1092         return (0);
 1093 }
 1094 
 1095 void
 1096 vic_watchdog(struct ifnet *ifp)
 1097 {
 1098 #if 0
 1099         struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
 1100 
 1101         if (sc->sc_txpending && sc->sc_txtimeout > 0) {
 1102                 if (--sc->sc_txtimeout == 0) {
 1103                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
 1104                         ifp->if_flags &= ~IFF_RUNNING;
 1105                         vic_init(ifp);
 1106                         ifp->if_oerrors++;
 1107                         return;
 1108                 }
 1109         }
 1110 
 1111         if (!IFQ_IS_EMPTY(&ifp->if_snd))
 1112                 vic_start(ifp);
 1113 #endif
 1114 }
 1115 
 1116 int
 1117 vic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 1118 {
 1119         struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
 1120         struct ifreq *ifr = (struct ifreq *)data;
 1121         struct ifaddr *ifa;
 1122         int s, error = 0;
 1123 
 1124         s = splnet();
 1125 
 1126         if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
 1127                 splx(s);
 1128                 return (error);
 1129         }
 1130 
 1131         switch (cmd) {
 1132         case SIOCSIFADDR:
 1133                 ifa = (struct ifaddr *)data;
 1134                 ifp->if_flags |= IFF_UP;
 1135 #ifdef INET
 1136                 if (ifa->ifa_addr->sa_family == AF_INET)
 1137                         arp_ifinit(&sc->sc_ac, ifa);
 1138 #endif
 1139                 /* FALLTHROUGH */
 1140         case SIOCSIFFLAGS:
 1141                 if (ifp->if_flags & IFF_UP) {
 1142                         if (ifp->if_flags & IFF_RUNNING)
 1143                                 vic_iff(sc);
 1144                         else
 1145                                 vic_init(ifp);
 1146                 } else {
 1147                         if (ifp->if_flags & IFF_RUNNING)
 1148                                 vic_stop(ifp);
 1149                 }
 1150                 break;
 1151 
 1152         case SIOCSIFMTU:
 1153                 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
 1154                         error = EINVAL;
 1155                 else if (ifp->if_mtu != ifr->ifr_mtu)
 1156                         ifp->if_mtu = ifr->ifr_mtu;
 1157                 break;
 1158 
 1159         case SIOCADDMULTI:
 1160         case SIOCDELMULTI:
 1161                 ifr = (struct ifreq *)data;
 1162                 error = (cmd == SIOCADDMULTI) ?
 1163                     ether_addmulti(ifr, &sc->sc_ac) :
 1164                     ether_delmulti(ifr, &sc->sc_ac);
 1165 
 1166                 if (error == ENETRESET) {
 1167                         if (ifp->if_flags & IFF_RUNNING)
 1168                                 vic_iff(sc);
 1169                         error = 0;
 1170                 }
 1171                 break;
 1172 
 1173         case SIOCGIFMEDIA:
 1174         case SIOCSIFMEDIA:
 1175                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
 1176                 break;
 1177 
 1178         default:
 1179                 error = ENOTTY;
 1180                 break;
 1181         }
 1182 
 1183         if (error == ENETRESET) {
 1184                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
 1185                     (IFF_UP | IFF_RUNNING))
 1186                         vic_iff(ifp->if_softc);
 1187                 error = 0;
 1188         }
 1189 
 1190         splx(s);
 1191 
 1192         return (error);
 1193 }
 1194 
 1195 void
 1196 vic_init(struct ifnet *ifp)
 1197 {
 1198         struct vic_softc        *sc = (struct vic_softc *)ifp->if_softc;
 1199         int                     s;
 1200 
 1201         if (vic_init_data(sc) != 0)
 1202                 return;
 1203 
 1204         sc->sc_data->vd_tx_curidx = 0;
 1205         sc->sc_data->vd_tx_nextidx = 0;
 1206         sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0;
 1207 
 1208         sc->sc_data->vd_rx_nextidx = 0;
 1209         sc->sc_data->vd_rx_nextidx2 = 0;
 1210 
 1211         sc->sc_data->vd_rx_saved_nextidx = 0;
 1212         sc->sc_data->vd_rx_saved_nextidx2 = 0;
 1213         sc->sc_data->vd_tx_saved_nextidx = 0;
 1214 
 1215         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
 1216             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1217 
 1218         s = splnet();
 1219 
 1220         vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc));
 1221         vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size);
 1222 
 1223         ifp->if_flags |= IFF_RUNNING;
 1224         ifp->if_flags &= ~IFF_OACTIVE;
 1225 
 1226         vic_iff(sc);
 1227         vic_write(sc, VIC_CMD, VIC_CMD_INTR_ENABLE);
 1228 
 1229         splx(s);
 1230 
 1231         timeout_add(&sc->sc_tick, hz);
 1232 }
 1233 
 1234 void
 1235 vic_stop(struct ifnet *ifp)
 1236 {
 1237         struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
 1238         int s;
 1239 
 1240         s = splnet();
 1241 
 1242         timeout_del(&sc->sc_tick);
 1243 
 1244         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 1245 
 1246         bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
 1247             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1248 
 1249         /* XXX wait for tx to complete */
 1250         while (sc->sc_txpending > 0) {
 1251                 splx(s);
 1252                 delay(1000);
 1253                 s = splnet();
 1254         }
 1255 
 1256         sc->sc_data->vd_tx_stopped = 1;
 1257 
 1258         vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE);
 1259 
 1260         vic_iff(sc);
 1261         vic_write(sc, VIC_DATA_ADDR, 0);
 1262 
 1263         vic_uninit_data(sc);
 1264 
 1265         splx(s);
 1266 }
 1267 
 1268 struct mbuf *
 1269 vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map)
 1270 {
 1271         struct mbuf *m = NULL;
 1272 
 1273         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1274         if (m == NULL)
 1275                 return (NULL);
 1276 
 1277         MCLGET(m, M_DONTWAIT);
 1278         if ((m->m_flags & M_EXT) == 0) {
 1279                 m_freem(m);
 1280                 return (NULL);
 1281         }
 1282         m->m_len = m->m_pkthdr.len = MCLBYTES;
 1283 
 1284         if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) {
 1285                 printf("%s: could not load mbuf DMA map", DEVNAME(sc));
 1286                 m_freem(m);
 1287                 return (NULL);
 1288         }
 1289 
 1290         return (m);
 1291 }
 1292 
 1293 void
 1294 vic_tick(void *arg)
 1295 {
 1296         struct vic_softc                *sc = (struct vic_softc *)arg;
 1297 
 1298         vic_link_state(sc);
 1299 
 1300         timeout_add(&sc->sc_tick, hz);
 1301 }
 1302 
 1303 u_int32_t
 1304 vic_read(struct vic_softc *sc, bus_size_t r)
 1305 {
 1306         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
 1307             BUS_SPACE_BARRIER_READ);
 1308         return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
 1309 }
 1310 
 1311 void
 1312 vic_write(struct vic_softc *sc, bus_size_t r, u_int32_t v)
 1313 {
 1314         bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
 1315         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
 1316             BUS_SPACE_BARRIER_WRITE);
 1317 }
 1318 
 1319 u_int32_t
 1320 vic_read_cmd(struct vic_softc *sc, u_int32_t cmd)
 1321 {
 1322         vic_write(sc, VIC_CMD, cmd);
 1323         return (vic_read(sc, VIC_CMD));
 1324 }
 1325 
 1326 int
 1327 vic_alloc_dmamem(struct vic_softc *sc)
 1328 {
 1329         int nsegs;
 1330 
 1331         if (bus_dmamap_create(sc->sc_dmat, sc->sc_dma_size, 1,
 1332             sc->sc_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
 1333             &sc->sc_dma_map) != 0)
 1334                 goto err;
 1335 
 1336         if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_dma_size, 16, 0,
 1337             &sc->sc_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT) != 0)
 1338                 goto destroy;
 1339 
 1340         if (bus_dmamem_map(sc->sc_dmat, &sc->sc_dma_seg, nsegs,
 1341             sc->sc_dma_size, &sc->sc_dma_kva, BUS_DMA_NOWAIT) != 0)
 1342                 goto free;
 1343 
 1344         if (bus_dmamap_load(sc->sc_dmat, sc->sc_dma_map, sc->sc_dma_kva,
 1345             sc->sc_dma_size, NULL, BUS_DMA_NOWAIT) != 0)
 1346                 goto unmap;
 1347 
 1348         bzero(sc->sc_dma_kva, sc->sc_dma_size);
 1349 
 1350         return (0);
 1351 
 1352 unmap:
 1353         bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size);
 1354 free:
 1355         bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1);
 1356 destroy:
 1357         bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map);
 1358 err:
 1359         return (1);
 1360 }
 1361 
 1362 void
 1363 vic_free_dmamem(struct vic_softc *sc)
 1364 {
 1365         bus_dmamap_unload(sc->sc_dmat, sc->sc_dma_map);
 1366         bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size);
 1367         bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1);
 1368         bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map);
 1369 }

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