The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/virtio/pci/virtio_pci_modern.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2017, Bryan Venteicher <bryanv@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 /* Driver for the modern VirtIO PCI interface. */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/lock.h>
   38 #include <sys/kernel.h>
   39 #include <sys/module.h>
   40 
   41 #include <machine/bus.h>
   42 #include <machine/cpu.h>
   43 #include <machine/resource.h>
   44 #include <sys/bus.h>
   45 #include <sys/rman.h>
   46 
   47 #include <dev/pci/pcivar.h>
   48 #include <dev/pci/pcireg.h>
   49 
   50 #include <dev/virtio/virtio.h>
   51 #include <dev/virtio/virtqueue.h>
   52 #include <dev/virtio/pci/virtio_pci.h>
   53 #include <dev/virtio/pci/virtio_pci_modern_var.h>
   54 
   55 #include "virtio_bus_if.h"
   56 #include "virtio_pci_if.h"
   57 #include "virtio_if.h"
   58 
   59 struct vtpci_modern_resource_map {
   60         struct resource_map     vtrm_map;
   61         int                     vtrm_cap_offset;
   62         int                     vtrm_bar;
   63         int                     vtrm_offset;
   64         int                     vtrm_length;
   65         int                     vtrm_type;      /* SYS_RES_{MEMORY, IOPORT} */
   66 };
   67 
   68 struct vtpci_modern_bar_resource {
   69         struct resource         *vtbr_res;
   70         int                      vtbr_type;
   71 };
   72 
   73 struct vtpci_modern_softc {
   74         device_t                         vtpci_dev;
   75         struct vtpci_common              vtpci_common;
   76         uint32_t                         vtpci_notify_offset_multiplier;
   77         uint16_t                         vtpci_devid;
   78         int                              vtpci_msix_bar;
   79         struct resource                 *vtpci_msix_res;
   80 
   81         struct vtpci_modern_resource_map vtpci_common_res_map;
   82         struct vtpci_modern_resource_map vtpci_notify_res_map;
   83         struct vtpci_modern_resource_map vtpci_isr_res_map;
   84         struct vtpci_modern_resource_map vtpci_device_res_map;
   85 
   86 #define VTPCI_MODERN_MAX_BARS           6
   87         struct vtpci_modern_bar_resource vtpci_bar_res[VTPCI_MODERN_MAX_BARS];
   88 };
   89 
   90 static int      vtpci_modern_probe(device_t);
   91 static int      vtpci_modern_attach(device_t);
   92 static int      vtpci_modern_detach(device_t);
   93 static int      vtpci_modern_suspend(device_t);
   94 static int      vtpci_modern_resume(device_t);
   95 static int      vtpci_modern_shutdown(device_t);
   96 
   97 static void     vtpci_modern_driver_added(device_t, driver_t *);
   98 static void     vtpci_modern_child_detached(device_t, device_t);
   99 static int      vtpci_modern_read_ivar(device_t, device_t, int, uintptr_t *);
  100 static int      vtpci_modern_write_ivar(device_t, device_t, int, uintptr_t);
  101 
  102 static uint8_t  vtpci_modern_read_isr(device_t);
  103 static uint16_t vtpci_modern_get_vq_size(device_t, int);
  104 static bus_size_t vtpci_modern_get_vq_notify_off(device_t, int);
  105 static void     vtpci_modern_set_vq(device_t, struct virtqueue *);
  106 static void     vtpci_modern_disable_vq(device_t, int);
  107 static int      vtpci_modern_register_msix(struct vtpci_modern_softc *, int,
  108                     struct vtpci_interrupt *);
  109 static int      vtpci_modern_register_cfg_msix(device_t,
  110                     struct vtpci_interrupt *);
  111 static int      vtpci_modern_register_vq_msix(device_t, int idx,
  112                     struct vtpci_interrupt *);
  113 
  114 static uint64_t vtpci_modern_negotiate_features(device_t, uint64_t);
  115 static int      vtpci_modern_finalize_features(device_t);
  116 static int      vtpci_modern_with_feature(device_t, uint64_t);
  117 static int      vtpci_modern_alloc_virtqueues(device_t, int, int,
  118                     struct vq_alloc_info *);
  119 static int      vtpci_modern_setup_interrupts(device_t, enum intr_type);
  120 static void     vtpci_modern_stop(device_t);
  121 static int      vtpci_modern_reinit(device_t, uint64_t);
  122 static void     vtpci_modern_reinit_complete(device_t);
  123 static void     vtpci_modern_notify_vq(device_t, uint16_t, bus_size_t);
  124 static int      vtpci_modern_config_generation(device_t);
  125 static void     vtpci_modern_read_dev_config(device_t, bus_size_t, void *, int);
  126 static void     vtpci_modern_write_dev_config(device_t, bus_size_t, const void *, int);
  127 
  128 static int      vtpci_modern_probe_configs(device_t);
  129 static int      vtpci_modern_find_cap(device_t, uint8_t, int *);
  130 static int      vtpci_modern_map_configs(struct vtpci_modern_softc *);
  131 static void     vtpci_modern_unmap_configs(struct vtpci_modern_softc *);
  132 static int      vtpci_modern_find_cap_resource(struct vtpci_modern_softc *,
  133                      uint8_t, int, int, struct vtpci_modern_resource_map *);
  134 static int      vtpci_modern_bar_type(struct vtpci_modern_softc *, int);
  135 static struct resource *vtpci_modern_get_bar_resource(
  136                     struct vtpci_modern_softc *, int, int);
  137 static struct resource *vtpci_modern_alloc_bar_resource(
  138                     struct vtpci_modern_softc *, int, int);
  139 static void     vtpci_modern_free_bar_resources(struct vtpci_modern_softc *);
  140 static int      vtpci_modern_alloc_resource_map(struct vtpci_modern_softc *,
  141                     struct vtpci_modern_resource_map *);
  142 static void     vtpci_modern_free_resource_map(struct vtpci_modern_softc *,
  143                     struct vtpci_modern_resource_map *);
  144 static void     vtpci_modern_alloc_msix_resource(struct vtpci_modern_softc *);
  145 static void     vtpci_modern_free_msix_resource(struct vtpci_modern_softc *);
  146 
  147 static void     vtpci_modern_probe_and_attach_child(struct vtpci_modern_softc *);
  148 
  149 static uint64_t vtpci_modern_read_features(struct vtpci_modern_softc *);
  150 static void     vtpci_modern_write_features(struct vtpci_modern_softc *,
  151                     uint64_t);
  152 static void     vtpci_modern_select_virtqueue(struct vtpci_modern_softc *, int);
  153 static uint8_t  vtpci_modern_get_status(struct vtpci_modern_softc *);
  154 static void     vtpci_modern_set_status(struct vtpci_modern_softc *, uint8_t);
  155 static void     vtpci_modern_reset(struct vtpci_modern_softc *);
  156 static void     vtpci_modern_enable_virtqueues(struct vtpci_modern_softc *);
  157 
  158 static uint8_t  vtpci_modern_read_common_1(struct vtpci_modern_softc *,
  159                     bus_size_t);
  160 static uint16_t vtpci_modern_read_common_2(struct vtpci_modern_softc *,
  161                     bus_size_t);
  162 static uint32_t vtpci_modern_read_common_4(struct vtpci_modern_softc *,
  163                     bus_size_t);
  164 static void     vtpci_modern_write_common_1(struct vtpci_modern_softc *,
  165                      bus_size_t, uint8_t);
  166 static void     vtpci_modern_write_common_2(struct vtpci_modern_softc *,
  167                      bus_size_t, uint16_t);
  168 static void     vtpci_modern_write_common_4(struct vtpci_modern_softc *,
  169                     bus_size_t, uint32_t);
  170 static void     vtpci_modern_write_common_8(struct vtpci_modern_softc *,
  171                     bus_size_t, uint64_t);
  172 static void     vtpci_modern_write_notify_2(struct vtpci_modern_softc *,
  173                     bus_size_t, uint16_t);
  174 static uint8_t  vtpci_modern_read_isr_1(struct vtpci_modern_softc *,
  175                     bus_size_t);
  176 static uint8_t  vtpci_modern_read_device_1(struct vtpci_modern_softc *,
  177                     bus_size_t);
  178 static uint16_t vtpci_modern_read_device_2(struct vtpci_modern_softc *,
  179                     bus_size_t);
  180 static uint32_t vtpci_modern_read_device_4(struct vtpci_modern_softc *,
  181                     bus_size_t);
  182 static uint64_t vtpci_modern_read_device_8(struct vtpci_modern_softc *,
  183                     bus_size_t);
  184 static void     vtpci_modern_write_device_1(struct vtpci_modern_softc *,
  185                     bus_size_t, uint8_t);
  186 static void     vtpci_modern_write_device_2(struct vtpci_modern_softc *,
  187                     bus_size_t, uint16_t);
  188 static void     vtpci_modern_write_device_4(struct vtpci_modern_softc *,
  189                     bus_size_t, uint32_t);
  190 static void     vtpci_modern_write_device_8(struct vtpci_modern_softc *,
  191                     bus_size_t, uint64_t);
  192 
  193 /* Tunables. */
  194 static int vtpci_modern_transitional = 0;
  195 TUNABLE_INT("hw.virtio.pci.transitional", &vtpci_modern_transitional);
  196 
  197 static device_method_t vtpci_modern_methods[] = {
  198         /* Device interface. */
  199         DEVMETHOD(device_probe,                 vtpci_modern_probe),
  200         DEVMETHOD(device_attach,                vtpci_modern_attach),
  201         DEVMETHOD(device_detach,                vtpci_modern_detach),
  202         DEVMETHOD(device_suspend,               vtpci_modern_suspend),
  203         DEVMETHOD(device_resume,                vtpci_modern_resume),
  204         DEVMETHOD(device_shutdown,              vtpci_modern_shutdown),
  205 
  206         /* Bus interface. */
  207         DEVMETHOD(bus_driver_added,             vtpci_modern_driver_added),
  208         DEVMETHOD(bus_child_detached,           vtpci_modern_child_detached),
  209         DEVMETHOD(bus_child_pnpinfo,            virtio_child_pnpinfo),
  210         DEVMETHOD(bus_read_ivar,                vtpci_modern_read_ivar),
  211         DEVMETHOD(bus_write_ivar,               vtpci_modern_write_ivar),
  212 
  213         /* VirtIO PCI interface. */
  214         DEVMETHOD(virtio_pci_read_isr,           vtpci_modern_read_isr),
  215         DEVMETHOD(virtio_pci_get_vq_size,        vtpci_modern_get_vq_size),
  216         DEVMETHOD(virtio_pci_get_vq_notify_off,  vtpci_modern_get_vq_notify_off),
  217         DEVMETHOD(virtio_pci_set_vq,             vtpci_modern_set_vq),
  218         DEVMETHOD(virtio_pci_disable_vq,         vtpci_modern_disable_vq),
  219         DEVMETHOD(virtio_pci_register_cfg_msix,  vtpci_modern_register_cfg_msix),
  220         DEVMETHOD(virtio_pci_register_vq_msix,   vtpci_modern_register_vq_msix),
  221 
  222         /* VirtIO bus interface. */
  223         DEVMETHOD(virtio_bus_negotiate_features,  vtpci_modern_negotiate_features),
  224         DEVMETHOD(virtio_bus_finalize_features,   vtpci_modern_finalize_features),
  225         DEVMETHOD(virtio_bus_with_feature,        vtpci_modern_with_feature),
  226         DEVMETHOD(virtio_bus_alloc_virtqueues,    vtpci_modern_alloc_virtqueues),
  227         DEVMETHOD(virtio_bus_setup_intr,          vtpci_modern_setup_interrupts),
  228         DEVMETHOD(virtio_bus_stop,                vtpci_modern_stop),
  229         DEVMETHOD(virtio_bus_reinit,              vtpci_modern_reinit),
  230         DEVMETHOD(virtio_bus_reinit_complete,     vtpci_modern_reinit_complete),
  231         DEVMETHOD(virtio_bus_notify_vq,           vtpci_modern_notify_vq),
  232         DEVMETHOD(virtio_bus_config_generation,   vtpci_modern_config_generation),
  233         DEVMETHOD(virtio_bus_read_device_config,  vtpci_modern_read_dev_config),
  234         DEVMETHOD(virtio_bus_write_device_config, vtpci_modern_write_dev_config),
  235 
  236         DEVMETHOD_END
  237 };
  238 
  239 static driver_t vtpci_modern_driver = {
  240         .name = "virtio_pci",
  241         .methods = vtpci_modern_methods,
  242         .size = sizeof(struct vtpci_modern_softc)
  243 };
  244 
  245 DRIVER_MODULE(virtio_pci_modern, pci, vtpci_modern_driver, 0, 0);
  246 
  247 static int
  248 vtpci_modern_probe(device_t dev)
  249 {
  250         char desc[64];
  251         const char *name;
  252         uint16_t devid;
  253 
  254         if (pci_get_vendor(dev) != VIRTIO_PCI_VENDORID)
  255                 return (ENXIO);
  256 
  257         if (pci_get_device(dev) < VIRTIO_PCI_DEVICEID_MIN ||
  258             pci_get_device(dev) > VIRTIO_PCI_DEVICEID_MODERN_MAX)
  259                 return (ENXIO);
  260 
  261         if (pci_get_device(dev) < VIRTIO_PCI_DEVICEID_MODERN_MIN) {
  262                 if (!vtpci_modern_transitional)
  263                         return (ENXIO);
  264                 devid = pci_get_subdevice(dev);
  265         } else
  266                 devid = pci_get_device(dev) - VIRTIO_PCI_DEVICEID_MODERN_MIN;
  267 
  268         if (vtpci_modern_probe_configs(dev) != 0)
  269                 return (ENXIO);
  270 
  271         name = virtio_device_name(devid);
  272         if (name == NULL)
  273                 name = "Unknown";
  274 
  275         snprintf(desc, sizeof(desc), "VirtIO PCI (modern) %s adapter", name);
  276         device_set_desc_copy(dev, desc);
  277 
  278         return (BUS_PROBE_DEFAULT);
  279 }
  280 
  281 static int
  282 vtpci_modern_attach(device_t dev)
  283 {
  284         struct vtpci_modern_softc *sc;
  285         int error;
  286 
  287         sc = device_get_softc(dev);
  288         sc->vtpci_dev = dev;
  289         vtpci_init(&sc->vtpci_common, dev, true);
  290 
  291         if (pci_get_device(dev) < VIRTIO_PCI_DEVICEID_MODERN_MIN)
  292                 sc->vtpci_devid = pci_get_subdevice(dev);
  293         else
  294                 sc->vtpci_devid = pci_get_device(dev) -
  295                     VIRTIO_PCI_DEVICEID_MODERN_MIN;
  296 
  297         error = vtpci_modern_map_configs(sc);
  298         if (error) {
  299                 device_printf(dev, "cannot map configs\n");
  300                 vtpci_modern_unmap_configs(sc);
  301                 return (error);
  302         }
  303 
  304         vtpci_modern_reset(sc);
  305 
  306         /* Tell the host we've noticed this device. */
  307         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_ACK);
  308 
  309         error = vtpci_add_child(&sc->vtpci_common);
  310         if (error)
  311                 goto fail;
  312 
  313         vtpci_modern_probe_and_attach_child(sc);
  314 
  315         return (0);
  316 
  317 fail:
  318         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_FAILED);
  319         vtpci_modern_detach(dev);
  320 
  321         return (error);
  322 }
  323 
  324 static int
  325 vtpci_modern_detach(device_t dev)
  326 {
  327         struct vtpci_modern_softc *sc;
  328         int error;
  329 
  330         sc = device_get_softc(dev);
  331 
  332         error = vtpci_delete_child(&sc->vtpci_common);
  333         if (error)
  334                 return (error);
  335 
  336         vtpci_modern_reset(sc);
  337         vtpci_modern_unmap_configs(sc);
  338 
  339         return (0);
  340 }
  341 
  342 static int
  343 vtpci_modern_suspend(device_t dev)
  344 {
  345         return (bus_generic_suspend(dev));
  346 }
  347 
  348 static int
  349 vtpci_modern_resume(device_t dev)
  350 {
  351         return (bus_generic_resume(dev));
  352 }
  353 
  354 static int
  355 vtpci_modern_shutdown(device_t dev)
  356 {
  357         (void) bus_generic_shutdown(dev);
  358         /* Forcibly stop the host device. */
  359         vtpci_modern_stop(dev);
  360 
  361         return (0);
  362 }
  363 
  364 static void
  365 vtpci_modern_driver_added(device_t dev, driver_t *driver)
  366 {
  367         vtpci_modern_probe_and_attach_child(device_get_softc(dev));
  368 }
  369 
  370 static void
  371 vtpci_modern_child_detached(device_t dev, device_t child)
  372 {
  373         struct vtpci_modern_softc *sc;
  374 
  375         sc = device_get_softc(dev);
  376 
  377         vtpci_modern_reset(sc);
  378         vtpci_child_detached(&sc->vtpci_common);
  379 
  380         /* After the reset, retell the host we've noticed this device. */
  381         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_ACK);
  382 }
  383 
  384 static int
  385 vtpci_modern_read_ivar(device_t dev, device_t child, int index,
  386     uintptr_t *result)
  387 {
  388         struct vtpci_modern_softc *sc;
  389         struct vtpci_common *cn;
  390 
  391         sc = device_get_softc(dev);
  392         cn = &sc->vtpci_common;
  393 
  394         if (vtpci_child_device(cn) != child)
  395                 return (ENOENT);
  396 
  397         switch (index) {
  398         case VIRTIO_IVAR_DEVTYPE:
  399                 *result = sc->vtpci_devid;
  400                 break;
  401         default:
  402                 return (vtpci_read_ivar(cn, index, result));
  403         }
  404 
  405         return (0);
  406 }
  407 
  408 static int
  409 vtpci_modern_write_ivar(device_t dev, device_t child, int index,
  410     uintptr_t value)
  411 {
  412         struct vtpci_modern_softc *sc;
  413         struct vtpci_common *cn;
  414 
  415         sc = device_get_softc(dev);
  416         cn = &sc->vtpci_common;
  417 
  418         if (vtpci_child_device(cn) != child)
  419                 return (ENOENT);
  420 
  421         switch (index) {
  422         default:
  423                 return (vtpci_write_ivar(cn, index, value));
  424         }
  425 
  426         return (0);
  427 }
  428 
  429 static uint64_t
  430 vtpci_modern_negotiate_features(device_t dev, uint64_t child_features)
  431 {
  432         struct vtpci_modern_softc *sc;
  433         uint64_t host_features, features;
  434 
  435         sc = device_get_softc(dev);
  436         host_features = vtpci_modern_read_features(sc);
  437 
  438         /*
  439          * Since the driver was added as a child of the modern PCI bus,
  440          * always add the V1 flag.
  441          */
  442         child_features |= VIRTIO_F_VERSION_1;
  443 
  444         features = vtpci_negotiate_features(&sc->vtpci_common,
  445             child_features, host_features);
  446         vtpci_modern_write_features(sc, features);
  447 
  448         return (features);
  449 }
  450 
  451 static int
  452 vtpci_modern_finalize_features(device_t dev)
  453 {
  454         struct vtpci_modern_softc *sc;
  455         uint8_t status;
  456 
  457         sc = device_get_softc(dev);
  458 
  459         /*
  460          * Must re-read the status after setting it to verify the negotiated
  461          * features were accepted by the device.
  462          */
  463         vtpci_modern_set_status(sc, VIRTIO_CONFIG_S_FEATURES_OK);
  464 
  465         status = vtpci_modern_get_status(sc);
  466         if ((status & VIRTIO_CONFIG_S_FEATURES_OK) == 0) {
  467                 device_printf(dev, "desired features were not accepted\n");
  468                 return (ENOTSUP);
  469         }
  470 
  471         return (0);
  472 }
  473 
  474 static int
  475 vtpci_modern_with_feature(device_t dev, uint64_t feature)
  476 {
  477         struct vtpci_modern_softc *sc;
  478 
  479         sc = device_get_softc(dev);
  480 
  481         return (vtpci_with_feature(&sc->vtpci_common, feature));
  482 }
  483 
  484 static uint64_t
  485 vtpci_modern_read_features(struct vtpci_modern_softc *sc)
  486 {
  487         uint32_t features0, features1;
  488 
  489         vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_DFSELECT, 0);
  490         features0 = vtpci_modern_read_common_4(sc, VIRTIO_PCI_COMMON_DF);
  491         vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_DFSELECT, 1);
  492         features1 = vtpci_modern_read_common_4(sc, VIRTIO_PCI_COMMON_DF);
  493 
  494         return (((uint64_t) features1 << 32) | features0);
  495 }
  496 
  497 static void
  498 vtpci_modern_write_features(struct vtpci_modern_softc *sc, uint64_t features)
  499 {
  500         uint32_t features0, features1;
  501 
  502         features0 = features;
  503         features1 = features >> 32;
  504 
  505         vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GFSELECT, 0);
  506         vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GF, features0);
  507         vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GFSELECT, 1);
  508         vtpci_modern_write_common_4(sc, VIRTIO_PCI_COMMON_GF, features1);
  509 }
  510 
  511 static int
  512 vtpci_modern_alloc_virtqueues(device_t dev, int flags, int nvqs,
  513     struct vq_alloc_info *vq_info)
  514 {
  515         struct vtpci_modern_softc *sc;
  516         struct vtpci_common *cn;
  517         uint16_t max_nvqs;
  518 
  519         sc = device_get_softc(dev);
  520         cn = &sc->vtpci_common;
  521 
  522         max_nvqs = vtpci_modern_read_common_2(sc, VIRTIO_PCI_COMMON_NUMQ);
  523         if (nvqs > max_nvqs) {
  524                 device_printf(sc->vtpci_dev, "requested virtqueue count %d "
  525                     "exceeds max %d\n", nvqs, max_nvqs);
  526                 return (E2BIG);
  527         }
  528 
  529         return (vtpci_alloc_virtqueues(cn, flags, nvqs, vq_info));
  530 }
  531 
  532 static int
  533 vtpci_modern_setup_interrupts(device_t dev, enum intr_type type)
  534 {
  535         struct vtpci_modern_softc *sc;
  536         int error;
  537 
  538         sc = device_get_softc(dev);
  539 
  540         error = vtpci_setup_interrupts(&sc->vtpci_common, type);
  541         if (error == 0)
  542                 vtpci_modern_enable_virtqueues(sc);
  543 
  544         return (error);
  545 }
  546 
  547 static void
  548 vtpci_modern_stop(device_t dev)
  549 {
  550         vtpci_modern_reset(device_get_softc(dev));
  551 }
  552 
  553 static int
  554 vtpci_modern_reinit(device_t dev, uint64_t features)
  555 {
  556         struct vtpci_modern_softc *sc;
  557         struct vtpci_common *cn;
  558         int error;
  559 
  560         sc = device_get_softc(dev);
  561         cn = &sc->vtpci_common;
  562 
  563         /*
  564          * Redrive the device initialization. This is a bit of an abuse of
  565          * the specification, but VirtualBox, QEMU/KVM, and BHyVe seem to
  566          * play nice.
  567          *
  568          * We do not allow the host device to change from what was originally
  569          * negotiated beyond what the guest driver changed. MSIX state should
  570          * not change, number of virtqueues and their size remain the same, etc.
  571          * This will need to be rethought when we want to support migration.
  572          */
  573 
  574         if (vtpci_modern_get_status(sc) != VIRTIO_CONFIG_STATUS_RESET)
  575                 vtpci_modern_stop(dev);
  576 
  577         /*
  578          * Quickly drive the status through ACK and DRIVER. The device does
  579          * not become usable again until DRIVER_OK in reinit complete.
  580          */
  581         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_ACK);
  582         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER);
  583 
  584         /*
  585          * TODO: Check that features are not added as to what was
  586          * originally negotiated.
  587          */
  588         vtpci_modern_negotiate_features(dev, features);
  589         error = vtpci_modern_finalize_features(dev);
  590         if (error) {
  591                 device_printf(dev, "cannot finalize features during reinit\n");
  592                 return (error);
  593         }
  594 
  595         error = vtpci_reinit(cn);
  596         if (error)
  597                 return (error);
  598 
  599         return (0);
  600 }
  601 
  602 static void
  603 vtpci_modern_reinit_complete(device_t dev)
  604 {
  605         struct vtpci_modern_softc *sc;
  606 
  607         sc = device_get_softc(dev);
  608 
  609         vtpci_modern_enable_virtqueues(sc);
  610         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER_OK);
  611 }
  612 
  613 static void
  614 vtpci_modern_notify_vq(device_t dev, uint16_t queue, bus_size_t offset)
  615 {
  616         struct vtpci_modern_softc *sc;
  617 
  618         sc = device_get_softc(dev);
  619 
  620         vtpci_modern_write_notify_2(sc, offset, queue);
  621 }
  622 
  623 static uint8_t
  624 vtpci_modern_get_status(struct vtpci_modern_softc *sc)
  625 {
  626         return (vtpci_modern_read_common_1(sc, VIRTIO_PCI_COMMON_STATUS));
  627 }
  628 
  629 static void
  630 vtpci_modern_set_status(struct vtpci_modern_softc *sc, uint8_t status)
  631 {
  632         if (status != VIRTIO_CONFIG_STATUS_RESET)
  633                 status |= vtpci_modern_get_status(sc);
  634 
  635         vtpci_modern_write_common_1(sc, VIRTIO_PCI_COMMON_STATUS, status);
  636 }
  637 
  638 static int
  639 vtpci_modern_config_generation(device_t dev)
  640 {
  641         struct vtpci_modern_softc *sc;
  642         uint8_t gen;
  643 
  644         sc = device_get_softc(dev);
  645         gen = vtpci_modern_read_common_1(sc, VIRTIO_PCI_COMMON_CFGGENERATION);
  646 
  647         return (gen);
  648 }
  649 
  650 static void
  651 vtpci_modern_read_dev_config(device_t dev, bus_size_t offset, void *dst,
  652     int length)
  653 {
  654         struct vtpci_modern_softc *sc;
  655 
  656         sc = device_get_softc(dev);
  657 
  658         if (sc->vtpci_device_res_map.vtrm_map.r_size == 0) {
  659                 panic("%s: attempt to read dev config but not present",
  660                     __func__);
  661         }
  662 
  663         switch (length) {
  664         case 1:
  665                 *(uint8_t *) dst = vtpci_modern_read_device_1(sc, offset);
  666                 break;
  667         case 2:
  668                 *(uint16_t *) dst = virtio_htog16(true,
  669                     vtpci_modern_read_device_2(sc, offset));
  670                 break;
  671         case 4:
  672                 *(uint32_t *) dst = virtio_htog32(true,
  673                     vtpci_modern_read_device_4(sc, offset));
  674                 break;
  675         case 8:
  676                 *(uint64_t *) dst = virtio_htog64(true,
  677                     vtpci_modern_read_device_8(sc, offset));
  678                 break;
  679         default:
  680                 panic("%s: device %s invalid device read length %d offset %d",
  681                     __func__, device_get_nameunit(dev), length, (int) offset);
  682         }
  683 }
  684 
  685 static void
  686 vtpci_modern_write_dev_config(device_t dev, bus_size_t offset, const void *src,
  687     int length)
  688 {
  689         struct vtpci_modern_softc *sc;
  690 
  691         sc = device_get_softc(dev);
  692 
  693         if (sc->vtpci_device_res_map.vtrm_map.r_size == 0) {
  694                 panic("%s: attempt to write dev config but not present",
  695                     __func__);
  696         }
  697 
  698         switch (length) {
  699         case 1:
  700                 vtpci_modern_write_device_1(sc, offset, *(const uint8_t *) src);
  701                 break;
  702         case 2: {
  703                 uint16_t val = virtio_gtoh16(true, *(const uint16_t *) src);
  704                 vtpci_modern_write_device_2(sc, offset, val);
  705                 break;
  706         }
  707         case 4: {
  708                 uint32_t val = virtio_gtoh32(true, *(const uint32_t *) src);
  709                 vtpci_modern_write_device_4(sc, offset, val);
  710                 break;
  711         }
  712         case 8: {
  713                 uint64_t val = virtio_gtoh64(true, *(const uint64_t *) src);
  714                 vtpci_modern_write_device_8(sc, offset, val);
  715                 break;
  716         }
  717         default:
  718                 panic("%s: device %s invalid device write length %d offset %d",
  719                     __func__, device_get_nameunit(dev), length, (int) offset);
  720         }
  721 }
  722 
  723 static int
  724 vtpci_modern_probe_configs(device_t dev)
  725 {
  726         int error;
  727 
  728         /*
  729          * These config capabilities must be present. The DEVICE_CFG
  730          * capability is only present if the device requires it.
  731          */
  732 
  733         error = vtpci_modern_find_cap(dev, VIRTIO_PCI_CAP_COMMON_CFG, NULL);
  734         if (error) {
  735                 device_printf(dev, "cannot find COMMON_CFG capability\n");
  736                 return (error);
  737         }
  738 
  739         error = vtpci_modern_find_cap(dev, VIRTIO_PCI_CAP_NOTIFY_CFG, NULL);
  740         if (error) {
  741                 device_printf(dev, "cannot find NOTIFY_CFG capability\n");
  742                 return (error);
  743         }
  744 
  745         error = vtpci_modern_find_cap(dev, VIRTIO_PCI_CAP_ISR_CFG, NULL);
  746         if (error) {
  747                 device_printf(dev, "cannot find ISR_CFG capability\n");
  748                 return (error);
  749         }
  750 
  751         return (0);
  752 }
  753 
  754 static int
  755 vtpci_modern_find_cap(device_t dev, uint8_t cfg_type, int *cap_offset)
  756 {
  757         uint32_t type, bar;
  758         int capreg, error;
  759 
  760         for (error = pci_find_cap(dev, PCIY_VENDOR, &capreg);
  761              error == 0;
  762              error = pci_find_next_cap(dev, PCIY_VENDOR, capreg, &capreg)) {
  763 
  764                 type = pci_read_config(dev, capreg +
  765                     offsetof(struct virtio_pci_cap, cfg_type), 1);
  766                 bar = pci_read_config(dev, capreg +
  767                     offsetof(struct virtio_pci_cap, bar), 1);
  768 
  769                 /* Must ignore reserved BARs. */
  770                 if (bar >= VTPCI_MODERN_MAX_BARS)
  771                         continue;
  772 
  773                 if (type == cfg_type) {
  774                         if (cap_offset != NULL)
  775                                 *cap_offset = capreg;
  776                         break;
  777                 }
  778         }
  779 
  780         return (error);
  781 }
  782 
  783 static int
  784 vtpci_modern_map_common_config(struct vtpci_modern_softc *sc)
  785 {
  786         device_t dev;
  787         int error;
  788 
  789         dev = sc->vtpci_dev;
  790 
  791         error = vtpci_modern_find_cap_resource(sc, VIRTIO_PCI_CAP_COMMON_CFG,
  792             sizeof(struct virtio_pci_common_cfg), 4, &sc->vtpci_common_res_map);
  793         if (error) {
  794                 device_printf(dev, "cannot find cap COMMON_CFG resource\n");
  795                 return (error);
  796         }
  797 
  798         error = vtpci_modern_alloc_resource_map(sc, &sc->vtpci_common_res_map);
  799         if (error) {
  800                 device_printf(dev, "cannot alloc resource for COMMON_CFG\n");
  801                 return (error);
  802         }
  803 
  804         return (0);
  805 }
  806 
  807 static int
  808 vtpci_modern_map_notify_config(struct vtpci_modern_softc *sc)
  809 {
  810         device_t dev;
  811         int cap_offset, error;
  812 
  813         dev = sc->vtpci_dev;
  814 
  815         error = vtpci_modern_find_cap_resource(sc, VIRTIO_PCI_CAP_NOTIFY_CFG,
  816             -1, 2, &sc->vtpci_notify_res_map);
  817         if (error) {
  818                 device_printf(dev, "cannot find cap NOTIFY_CFG resource\n");
  819                 return (error);
  820         }
  821 
  822         cap_offset = sc->vtpci_notify_res_map.vtrm_cap_offset;
  823 
  824         sc->vtpci_notify_offset_multiplier = pci_read_config(dev, cap_offset +
  825             offsetof(struct virtio_pci_notify_cap, notify_off_multiplier), 4);
  826 
  827         error = vtpci_modern_alloc_resource_map(sc, &sc->vtpci_notify_res_map);
  828         if (error) {
  829                 device_printf(dev, "cannot alloc resource for NOTIFY_CFG\n");
  830                 return (error);
  831         }
  832 
  833         return (0);
  834 }
  835 
  836 static int
  837 vtpci_modern_map_isr_config(struct vtpci_modern_softc *sc)
  838 {
  839         device_t dev;
  840         int error;
  841 
  842         dev = sc->vtpci_dev;
  843 
  844         error = vtpci_modern_find_cap_resource(sc, VIRTIO_PCI_CAP_ISR_CFG,
  845             sizeof(uint8_t), 1, &sc->vtpci_isr_res_map);
  846         if (error) {
  847                 device_printf(dev, "cannot find cap ISR_CFG resource\n");
  848                 return (error);
  849         }
  850 
  851         error = vtpci_modern_alloc_resource_map(sc, &sc->vtpci_isr_res_map);
  852         if (error) {
  853                 device_printf(dev, "cannot alloc resource for ISR_CFG\n");
  854                 return (error);
  855         }
  856 
  857         return (0);
  858 }
  859 
  860 static int
  861 vtpci_modern_map_device_config(struct vtpci_modern_softc *sc)
  862 {
  863         device_t dev;
  864         int error;
  865 
  866         dev = sc->vtpci_dev;
  867 
  868         error = vtpci_modern_find_cap_resource(sc, VIRTIO_PCI_CAP_DEVICE_CFG,
  869             -1, 4, &sc->vtpci_device_res_map);
  870         if (error == ENOENT) {
  871                 /* Device configuration is optional depending on device. */
  872                 return (0);
  873         } else if (error) {
  874                 device_printf(dev, "cannot find cap DEVICE_CFG resource\n");
  875                 return (error);
  876         }
  877 
  878         error = vtpci_modern_alloc_resource_map(sc, &sc->vtpci_device_res_map);
  879         if (error) {
  880                 device_printf(dev, "cannot alloc resource for DEVICE_CFG\n");
  881                 return (error);
  882         }
  883 
  884         return (0);
  885 }
  886 
  887 static int
  888 vtpci_modern_map_configs(struct vtpci_modern_softc *sc)
  889 {
  890         int error;
  891 
  892         error = vtpci_modern_map_common_config(sc);
  893         if (error)
  894                 return (error);
  895 
  896         error = vtpci_modern_map_notify_config(sc);
  897         if (error)
  898                 return (error);
  899 
  900         error = vtpci_modern_map_isr_config(sc);
  901         if (error)
  902                 return (error);
  903 
  904         error = vtpci_modern_map_device_config(sc);
  905         if (error)
  906                 return (error);
  907 
  908         vtpci_modern_alloc_msix_resource(sc);
  909 
  910         return (0);
  911 }
  912 
  913 static void
  914 vtpci_modern_unmap_configs(struct vtpci_modern_softc *sc)
  915 {
  916 
  917         vtpci_modern_free_resource_map(sc, &sc->vtpci_common_res_map);
  918         vtpci_modern_free_resource_map(sc, &sc->vtpci_notify_res_map);
  919         vtpci_modern_free_resource_map(sc, &sc->vtpci_isr_res_map);
  920         vtpci_modern_free_resource_map(sc, &sc->vtpci_device_res_map);
  921 
  922         vtpci_modern_free_bar_resources(sc);
  923         vtpci_modern_free_msix_resource(sc);
  924 
  925         sc->vtpci_notify_offset_multiplier = 0;
  926 }
  927 
  928 static int
  929 vtpci_modern_find_cap_resource(struct vtpci_modern_softc *sc, uint8_t cfg_type,
  930     int min_size, int alignment, struct vtpci_modern_resource_map *res)
  931 {
  932         device_t dev;
  933         int cap_offset, offset, length, error;
  934         uint8_t bar, cap_length;
  935 
  936         dev = sc->vtpci_dev;
  937 
  938         error = vtpci_modern_find_cap(dev, cfg_type, &cap_offset);
  939         if (error)
  940                 return (error);
  941 
  942         cap_length = pci_read_config(dev,
  943             cap_offset + offsetof(struct virtio_pci_cap, cap_len), 1);
  944 
  945         if (cap_length < sizeof(struct virtio_pci_cap)) {
  946                 device_printf(dev, "cap %u length %d less than expected\n",
  947                     cfg_type, cap_length);
  948                 return (ENXIO);
  949         }
  950 
  951         bar = pci_read_config(dev,
  952             cap_offset + offsetof(struct virtio_pci_cap, bar), 1);
  953         offset = pci_read_config(dev,
  954             cap_offset + offsetof(struct virtio_pci_cap, offset), 4);
  955         length = pci_read_config(dev,
  956             cap_offset + offsetof(struct virtio_pci_cap, length), 4);
  957 
  958         if (min_size != -1 && length < min_size) {
  959                 device_printf(dev, "cap %u struct length %d less than min %d\n",
  960                     cfg_type, length, min_size);
  961                 return (ENXIO);
  962         }
  963 
  964         if (offset % alignment) {
  965                 device_printf(dev, "cap %u struct offset %d not aligned to %d\n",
  966                     cfg_type, offset, alignment);
  967                 return (ENXIO);
  968         }
  969 
  970         /* BMV: TODO Can we determine the size of the BAR here? */
  971 
  972         res->vtrm_cap_offset = cap_offset;
  973         res->vtrm_bar = bar;
  974         res->vtrm_offset = offset;
  975         res->vtrm_length = length;
  976         res->vtrm_type = vtpci_modern_bar_type(sc, bar);
  977 
  978         return (0);
  979 }
  980 
  981 static int
  982 vtpci_modern_bar_type(struct vtpci_modern_softc *sc, int bar)
  983 {
  984         uint32_t val;
  985 
  986         /*
  987          * The BAR described by a config capability may be either an IOPORT or
  988          * MEM, but we must know the type when calling bus_alloc_resource().
  989          */
  990         val = pci_read_config(sc->vtpci_dev, PCIR_BAR(bar), 4);
  991         if (PCI_BAR_IO(val))
  992                 return (SYS_RES_IOPORT);
  993         else
  994                 return (SYS_RES_MEMORY);
  995 }
  996 
  997 static struct resource *
  998 vtpci_modern_get_bar_resource(struct vtpci_modern_softc *sc, int bar, int type)
  999 {
 1000         struct resource *res;
 1001 
 1002         MPASS(bar >= 0 && bar < VTPCI_MODERN_MAX_BARS);
 1003         res = sc->vtpci_bar_res[bar].vtbr_res;
 1004         MPASS(res == NULL || sc->vtpci_bar_res[bar].vtbr_type == type);
 1005 
 1006         return (res);
 1007 }
 1008 
 1009 static struct resource *
 1010 vtpci_modern_alloc_bar_resource(struct vtpci_modern_softc *sc, int bar,
 1011     int type)
 1012 {
 1013         struct resource *res;
 1014         int rid;
 1015 
 1016         MPASS(bar >= 0 && bar < VTPCI_MODERN_MAX_BARS);
 1017         MPASS(type == SYS_RES_MEMORY || type == SYS_RES_IOPORT);
 1018 
 1019         res = sc->vtpci_bar_res[bar].vtbr_res;
 1020         if (res != NULL) {
 1021                 MPASS(sc->vtpci_bar_res[bar].vtbr_type == type);
 1022                 return (res);
 1023         }
 1024 
 1025         rid = PCIR_BAR(bar);
 1026         res = bus_alloc_resource_any(sc->vtpci_dev, type, &rid,
 1027             RF_ACTIVE | RF_UNMAPPED);
 1028         if (res != NULL) {
 1029                 sc->vtpci_bar_res[bar].vtbr_res = res;
 1030                 sc->vtpci_bar_res[bar].vtbr_type = type;
 1031         }
 1032 
 1033         return (res);
 1034 }
 1035 
 1036 static void
 1037 vtpci_modern_free_bar_resources(struct vtpci_modern_softc *sc)
 1038 {
 1039         device_t dev;
 1040         struct resource *res;
 1041         int bar, rid, type;
 1042 
 1043         dev = sc->vtpci_dev;
 1044 
 1045         for (bar = 0; bar < VTPCI_MODERN_MAX_BARS; bar++) {
 1046                 res = sc->vtpci_bar_res[bar].vtbr_res;
 1047                 type = sc->vtpci_bar_res[bar].vtbr_type;
 1048 
 1049                 if (res != NULL) {
 1050                         rid = PCIR_BAR(bar);
 1051                         bus_release_resource(dev, type, rid, res);
 1052                         sc->vtpci_bar_res[bar].vtbr_res = NULL;
 1053                         sc->vtpci_bar_res[bar].vtbr_type = 0;
 1054                 }
 1055         }
 1056 }
 1057 
 1058 static int
 1059 vtpci_modern_alloc_resource_map(struct vtpci_modern_softc *sc,
 1060     struct vtpci_modern_resource_map *map)
 1061 {
 1062         struct resource_map_request req;
 1063         struct resource *res;
 1064         int type;
 1065 
 1066         type = map->vtrm_type;
 1067 
 1068         res = vtpci_modern_alloc_bar_resource(sc, map->vtrm_bar, type);
 1069         if (res == NULL)
 1070                 return (ENXIO);
 1071 
 1072         resource_init_map_request(&req);
 1073         req.offset = map->vtrm_offset;
 1074         req.length = map->vtrm_length;
 1075 
 1076         return (bus_map_resource(sc->vtpci_dev, type, res, &req,
 1077             &map->vtrm_map));
 1078 }
 1079 
 1080 static void
 1081 vtpci_modern_free_resource_map(struct vtpci_modern_softc *sc,
 1082     struct vtpci_modern_resource_map *map)
 1083 {
 1084         struct resource *res;
 1085         int type;
 1086 
 1087         type = map->vtrm_type;
 1088         res = vtpci_modern_get_bar_resource(sc, map->vtrm_bar, type);
 1089 
 1090         if (res != NULL && map->vtrm_map.r_size != 0) {
 1091                 bus_unmap_resource(sc->vtpci_dev, type, res, &map->vtrm_map);
 1092                 bzero(map, sizeof(struct vtpci_modern_resource_map));
 1093         }
 1094 }
 1095 
 1096 static void
 1097 vtpci_modern_alloc_msix_resource(struct vtpci_modern_softc *sc)
 1098 {
 1099         device_t dev;
 1100         int bar;
 1101 
 1102         dev = sc->vtpci_dev;
 1103 
 1104         if (!vtpci_is_msix_available(&sc->vtpci_common) ||
 1105             (bar = pci_msix_table_bar(dev)) == -1)
 1106                 return;
 1107 
 1108         /* TODO: Can this BAR be in the 0-5 range? */
 1109         sc->vtpci_msix_bar = bar;
 1110         if ((sc->vtpci_msix_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 1111             &bar, RF_ACTIVE)) == NULL)
 1112                 device_printf(dev, "Unable to map MSIX table\n");
 1113 }
 1114 
 1115 static void
 1116 vtpci_modern_free_msix_resource(struct vtpci_modern_softc *sc)
 1117 {
 1118         device_t dev;
 1119 
 1120         dev = sc->vtpci_dev;
 1121 
 1122         if (sc->vtpci_msix_res != NULL) {
 1123                 bus_release_resource(dev, SYS_RES_MEMORY, sc->vtpci_msix_bar,
 1124                     sc->vtpci_msix_res);
 1125                 sc->vtpci_msix_bar = 0;
 1126                 sc->vtpci_msix_res = NULL;
 1127         }
 1128 }
 1129 
 1130 static void
 1131 vtpci_modern_probe_and_attach_child(struct vtpci_modern_softc *sc)
 1132 {
 1133         device_t dev, child;
 1134 
 1135         dev = sc->vtpci_dev;
 1136         child = vtpci_child_device(&sc->vtpci_common);
 1137 
 1138         if (child == NULL || device_get_state(child) != DS_NOTPRESENT)
 1139                 return;
 1140 
 1141         if (device_probe(child) != 0)
 1142                 return;
 1143 
 1144         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER);
 1145 
 1146         if (device_attach(child) != 0) {
 1147                 vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_FAILED);
 1148                 /* Reset state for later attempt. */
 1149                 vtpci_modern_child_detached(dev, child);
 1150         } else {
 1151                 vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER_OK);
 1152                 VIRTIO_ATTACH_COMPLETED(child);
 1153         }
 1154 }
 1155 
 1156 static int
 1157 vtpci_modern_register_msix(struct vtpci_modern_softc *sc, int offset,
 1158     struct vtpci_interrupt *intr)
 1159 {
 1160         uint16_t vector;
 1161 
 1162         if (intr != NULL) {
 1163                 /* Map from guest rid to host vector. */
 1164                 vector = intr->vti_rid - 1;
 1165         } else
 1166                 vector = VIRTIO_MSI_NO_VECTOR;
 1167 
 1168         vtpci_modern_write_common_2(sc, offset, vector);
 1169         return (vtpci_modern_read_common_2(sc, offset) == vector ? 0 : ENODEV);
 1170 }
 1171 
 1172 static int
 1173 vtpci_modern_register_cfg_msix(device_t dev, struct vtpci_interrupt *intr)
 1174 {
 1175         struct vtpci_modern_softc *sc;
 1176         int error;
 1177 
 1178         sc = device_get_softc(dev);
 1179 
 1180         error = vtpci_modern_register_msix(sc, VIRTIO_PCI_COMMON_MSIX, intr);
 1181         if (error) {
 1182                 device_printf(dev,
 1183                     "unable to register config MSIX interrupt\n");
 1184                 return (error);
 1185         }
 1186 
 1187         return (0);
 1188 }
 1189 
 1190 static int
 1191 vtpci_modern_register_vq_msix(device_t dev, int idx,
 1192     struct vtpci_interrupt *intr)
 1193 {
 1194         struct vtpci_modern_softc *sc;
 1195         int error;
 1196 
 1197         sc = device_get_softc(dev);
 1198 
 1199         vtpci_modern_select_virtqueue(sc, idx);
 1200         error = vtpci_modern_register_msix(sc, VIRTIO_PCI_COMMON_Q_MSIX, intr);
 1201         if (error) {
 1202                 device_printf(dev,
 1203                     "unable to register virtqueue MSIX interrupt\n");
 1204                 return (error);
 1205         }
 1206 
 1207         return (0);
 1208 }
 1209 
 1210 static void
 1211 vtpci_modern_reset(struct vtpci_modern_softc *sc)
 1212 {
 1213         /*
 1214          * Setting the status to RESET sets the host device to the
 1215          * original, uninitialized state. Must poll the status until
 1216          * the reset is complete.
 1217          */
 1218         vtpci_modern_set_status(sc, VIRTIO_CONFIG_STATUS_RESET);
 1219 
 1220         while (vtpci_modern_get_status(sc) != VIRTIO_CONFIG_STATUS_RESET)
 1221                 cpu_spinwait();
 1222 }
 1223 
 1224 static void
 1225 vtpci_modern_select_virtqueue(struct vtpci_modern_softc *sc, int idx)
 1226 {
 1227         vtpci_modern_write_common_2(sc, VIRTIO_PCI_COMMON_Q_SELECT, idx);
 1228 }
 1229 
 1230 static uint8_t
 1231 vtpci_modern_read_isr(device_t dev)
 1232 {
 1233         return (vtpci_modern_read_isr_1(device_get_softc(dev), 0));
 1234 }
 1235 
 1236 static uint16_t
 1237 vtpci_modern_get_vq_size(device_t dev, int idx)
 1238 {
 1239         struct vtpci_modern_softc *sc;
 1240 
 1241         sc = device_get_softc(dev);
 1242 
 1243         vtpci_modern_select_virtqueue(sc, idx);
 1244         return (vtpci_modern_read_common_2(sc, VIRTIO_PCI_COMMON_Q_SIZE));
 1245 }
 1246 
 1247 static bus_size_t
 1248 vtpci_modern_get_vq_notify_off(device_t dev, int idx)
 1249 {
 1250         struct vtpci_modern_softc *sc;
 1251         uint16_t q_notify_off;
 1252 
 1253         sc = device_get_softc(dev);
 1254 
 1255         vtpci_modern_select_virtqueue(sc, idx);
 1256         q_notify_off = vtpci_modern_read_common_2(sc, VIRTIO_PCI_COMMON_Q_NOFF);
 1257 
 1258         return (q_notify_off * sc->vtpci_notify_offset_multiplier);
 1259 }
 1260 
 1261 static void
 1262 vtpci_modern_set_vq(device_t dev, struct virtqueue *vq)
 1263 {
 1264         struct vtpci_modern_softc *sc;
 1265 
 1266         sc = device_get_softc(dev);
 1267 
 1268         vtpci_modern_select_virtqueue(sc, virtqueue_index(vq));
 1269 
 1270         /* BMV: Currently we never adjust the device's proposed VQ size. */
 1271         vtpci_modern_write_common_2(sc,
 1272             VIRTIO_PCI_COMMON_Q_SIZE, virtqueue_size(vq));
 1273 
 1274         vtpci_modern_write_common_8(sc,
 1275             VIRTIO_PCI_COMMON_Q_DESCLO, virtqueue_desc_paddr(vq));
 1276         vtpci_modern_write_common_8(sc,
 1277             VIRTIO_PCI_COMMON_Q_AVAILLO, virtqueue_avail_paddr(vq));
 1278         vtpci_modern_write_common_8(sc,
 1279             VIRTIO_PCI_COMMON_Q_USEDLO, virtqueue_used_paddr(vq));
 1280 }
 1281 
 1282 static void
 1283 vtpci_modern_disable_vq(device_t dev, int idx)
 1284 {
 1285         struct vtpci_modern_softc *sc;
 1286 
 1287         sc = device_get_softc(dev);
 1288 
 1289         vtpci_modern_select_virtqueue(sc, idx);
 1290         vtpci_modern_write_common_8(sc, VIRTIO_PCI_COMMON_Q_DESCLO, 0ULL);
 1291         vtpci_modern_write_common_8(sc, VIRTIO_PCI_COMMON_Q_AVAILLO, 0ULL);
 1292         vtpci_modern_write_common_8(sc, VIRTIO_PCI_COMMON_Q_USEDLO, 0ULL);
 1293 }
 1294 
 1295 static void
 1296 vtpci_modern_enable_virtqueues(struct vtpci_modern_softc *sc)
 1297 {
 1298         int idx;
 1299 
 1300         for (idx = 0; idx < sc->vtpci_common.vtpci_nvqs; idx++) {
 1301                 vtpci_modern_select_virtqueue(sc, idx);
 1302                 vtpci_modern_write_common_2(sc, VIRTIO_PCI_COMMON_Q_ENABLE, 1);
 1303         }
 1304 }
 1305 
 1306 static uint8_t
 1307 vtpci_modern_read_common_1(struct vtpci_modern_softc *sc, bus_size_t off)
 1308 {
 1309         return (bus_read_1(&sc->vtpci_common_res_map.vtrm_map, off));
 1310 }
 1311 
 1312 static uint16_t
 1313 vtpci_modern_read_common_2(struct vtpci_modern_softc *sc, bus_size_t off)
 1314 {
 1315         return virtio_htog16(true,
 1316                         bus_read_2(&sc->vtpci_common_res_map.vtrm_map, off));
 1317 }
 1318 
 1319 static uint32_t
 1320 vtpci_modern_read_common_4(struct vtpci_modern_softc *sc, bus_size_t off)
 1321 {
 1322         return virtio_htog32(true,
 1323                         bus_read_4(&sc->vtpci_common_res_map.vtrm_map, off));
 1324 }
 1325 
 1326 static void
 1327 vtpci_modern_write_common_1(struct vtpci_modern_softc *sc, bus_size_t off,
 1328     uint8_t val)
 1329 {
 1330         bus_write_1(&sc->vtpci_common_res_map.vtrm_map, off, val);
 1331 }
 1332 
 1333 static void
 1334 vtpci_modern_write_common_2(struct vtpci_modern_softc *sc, bus_size_t off,
 1335     uint16_t val)
 1336 {
 1337         bus_write_2(&sc->vtpci_common_res_map.vtrm_map,
 1338                         off, virtio_gtoh16(true, val));
 1339 }
 1340 
 1341 static void
 1342 vtpci_modern_write_common_4(struct vtpci_modern_softc *sc, bus_size_t off,
 1343     uint32_t val)
 1344 {
 1345         bus_write_4(&sc->vtpci_common_res_map.vtrm_map,
 1346                         off, virtio_gtoh32(true, val));
 1347 }
 1348 
 1349 static void
 1350 vtpci_modern_write_common_8(struct vtpci_modern_softc *sc, bus_size_t off,
 1351     uint64_t val)
 1352 {
 1353         uint32_t val0, val1;
 1354 
 1355         val0 = (uint32_t) val;
 1356         val1 = val >> 32;
 1357 
 1358         vtpci_modern_write_common_4(sc, off, val0);
 1359         vtpci_modern_write_common_4(sc, off + 4, val1);
 1360 }
 1361 
 1362 static void
 1363 vtpci_modern_write_notify_2(struct vtpci_modern_softc *sc, bus_size_t off,
 1364     uint16_t val)
 1365 {
 1366         bus_write_2(&sc->vtpci_notify_res_map.vtrm_map, off, val);
 1367 }
 1368 
 1369 static uint8_t
 1370 vtpci_modern_read_isr_1(struct vtpci_modern_softc *sc, bus_size_t off)
 1371 {
 1372         return (bus_read_1(&sc->vtpci_isr_res_map.vtrm_map, off));
 1373 }
 1374 
 1375 static uint8_t
 1376 vtpci_modern_read_device_1(struct vtpci_modern_softc *sc, bus_size_t off)
 1377 {
 1378         return (bus_read_1(&sc->vtpci_device_res_map.vtrm_map, off));
 1379 }
 1380 
 1381 static uint16_t
 1382 vtpci_modern_read_device_2(struct vtpci_modern_softc *sc, bus_size_t off)
 1383 {
 1384         return (bus_read_2(&sc->vtpci_device_res_map.vtrm_map, off));
 1385 }
 1386 
 1387 static uint32_t
 1388 vtpci_modern_read_device_4(struct vtpci_modern_softc *sc, bus_size_t off)
 1389 {
 1390         return (bus_read_4(&sc->vtpci_device_res_map.vtrm_map, off));
 1391 }
 1392 
 1393 static uint64_t
 1394 vtpci_modern_read_device_8(struct vtpci_modern_softc *sc, bus_size_t off)
 1395 {
 1396         device_t dev;
 1397         int gen;
 1398         uint32_t val0, val1;
 1399 
 1400         dev = sc->vtpci_dev;
 1401 
 1402         /*
 1403          * Treat the 64-bit field as two 32-bit fields. Use the generation
 1404          * to ensure a consistent read.
 1405          */
 1406         do {
 1407                 gen = vtpci_modern_config_generation(dev);
 1408                 val0 = vtpci_modern_read_device_4(sc, off);
 1409                 val1 = vtpci_modern_read_device_4(sc, off + 4);
 1410         } while (gen != vtpci_modern_config_generation(dev));
 1411 
 1412         return (((uint64_t) val1 << 32) | val0);
 1413 }
 1414 
 1415 static void
 1416 vtpci_modern_write_device_1(struct vtpci_modern_softc *sc, bus_size_t off,
 1417     uint8_t val)
 1418 {
 1419         bus_write_1(&sc->vtpci_device_res_map.vtrm_map, off, val);
 1420 }
 1421 
 1422 static void
 1423 vtpci_modern_write_device_2(struct vtpci_modern_softc *sc, bus_size_t off,
 1424     uint16_t val)
 1425 {
 1426         bus_write_2(&sc->vtpci_device_res_map.vtrm_map, off, val);
 1427 }
 1428 
 1429 static void
 1430 vtpci_modern_write_device_4(struct vtpci_modern_softc *sc, bus_size_t off,
 1431     uint32_t val)
 1432 {
 1433         bus_write_4(&sc->vtpci_device_res_map.vtrm_map, off, val);
 1434 }
 1435 
 1436 static void
 1437 vtpci_modern_write_device_8(struct vtpci_modern_softc *sc, bus_size_t off,
 1438     uint64_t val)
 1439 {
 1440         uint32_t val0, val1;
 1441 
 1442         val0 = (uint32_t) val;
 1443         val1 = val >> 32;
 1444 
 1445         vtpci_modern_write_device_4(sc, off, val0);
 1446         vtpci_modern_write_device_4(sc, off + 4, val1);
 1447 }

Cache object: fc29363f69cf440cf78bc673833a69cd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.