Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -3429,8 +3429,10 @@ dev/virtio/virtio_bus_if.m optional virtio dev/virtio/virtio_if.m optional virtio dev/virtio/pci/virtio_pci.c optional virtio_pci -dev/virtio/mmio/virtio_mmio.c optional virtio_mmio fdt -dev/virtio/mmio/virtio_mmio_if.m optional virtio_mmio fdt +dev/virtio/mmio/virtio_mmio.c optional virtio_mmio +dev/virtio/mmio/virtio_mmio_acpi.c optional virtio_mmio acpi +dev/virtio/mmio/virtio_mmio_fdt.c optional virtio_mmio fdt +dev/virtio/mmio/virtio_mmio_if.m optional virtio_mmio dev/virtio/network/if_vtnet.c optional vtnet dev/virtio/block/virtio_blk.c optional virtio_blk dev/virtio/balloon/virtio_balloon.c optional virtio_balloon Index: sys/dev/virtio/mmio/virtio_mmio.h =================================================================== --- sys/dev/virtio/mmio/virtio_mmio.h +++ sys/dev/virtio/mmio/virtio_mmio.h @@ -33,6 +33,29 @@ #ifndef _VIRTIO_MMIO_H #define _VIRTIO_MMIO_H +DECLARE_CLASS(vtmmio_driver); + +struct vtmmio_virtqueue; + +struct vtmmio_softc { + device_t dev; + device_t platform; + struct resource *res[2]; + + uint64_t vtmmio_features; + uint32_t vtmmio_flags; + + /* This "bus" will only ever have one child. */ + device_t vtmmio_child_dev; + struct virtio_feature_desc *vtmmio_child_feat_desc; + + int vtmmio_nvqs; + struct vtmmio_virtqueue *vtmmio_vqs; + void *ih; +}; + +int vtmmio_attach(device_t); + #define VIRTIO_MMIO_MAGIC_VALUE 0x000 #define VIRTIO_MMIO_VERSION 0x004 #define VIRTIO_MMIO_DEVICE_ID 0x008 Index: sys/dev/virtio/mmio/virtio_mmio.c =================================================================== --- sys/dev/virtio/mmio/virtio_mmio.c +++ sys/dev/virtio/mmio/virtio_mmio.c @@ -37,16 +37,6 @@ * This driver is heavily based on VirtIO PCI interface driver. */ -/* - * FDT example: - * virtio_block@1000 { - * compatible = "virtio,mmio"; - * reg = <0x1000 0x100>; - * interrupts = <63>; - * interrupt-parent = <&GIC>; - * }; - */ - #include __FBSDID("$FreeBSD$"); @@ -61,11 +51,6 @@ #include #include -#include -#include -#include -#include - #include #include #include @@ -81,25 +66,6 @@ int vtv_no_intr; }; -struct vtmmio_softc { - device_t dev; - device_t platform; - struct resource *res[2]; - - uint64_t vtmmio_features; - uint32_t vtmmio_flags; - - /* This "bus" will only ever have one child. */ - device_t vtmmio_child_dev; - struct virtio_feature_desc *vtmmio_child_feat_desc; - - int vtmmio_nvqs; - struct vtmmio_virtqueue *vtmmio_vqs; - void *ih; -}; - -static int vtmmio_probe(device_t); -static int vtmmio_attach(device_t); static int vtmmio_detach(device_t); static int vtmmio_suspend(device_t); static int vtmmio_resume(device_t); @@ -170,7 +136,6 @@ static device_method_t vtmmio_methods[] = { /* Device interface. */ - DEVMETHOD(device_probe, vtmmio_probe), DEVMETHOD(device_attach, vtmmio_attach), DEVMETHOD(device_detach, vtmmio_detach), DEVMETHOD(device_suspend, vtmmio_suspend), @@ -199,19 +164,10 @@ DEVMETHOD_END }; -static driver_t vtmmio_driver = { - "virtio_mmio", - vtmmio_methods, - sizeof(struct vtmmio_softc) -}; - -devclass_t vtmmio_devclass; +DEFINE_CLASS_0(virtio_mmio, vtmmio_driver, vtmmio_methods, + sizeof(struct vtmmio_softc)); -DRIVER_MODULE(virtio_mmio, simplebus, vtmmio_driver, vtmmio_devclass, 0, 0); -DRIVER_MODULE(virtio_mmio, ofwbus, vtmmio_driver, vtmmio_devclass, 0, 0); MODULE_VERSION(virtio_mmio, 1); -MODULE_DEPEND(virtio_mmio, simplebus, 1, 1, 1); -MODULE_DEPEND(virtio_mmio, virtio, 1, 1, 1); static int vtmmio_setup_intr(device_t dev, enum intr_type type) @@ -248,55 +204,7 @@ return (0); } -static int -vtmmio_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "virtio,mmio")) - return (ENXIO); - - device_set_desc(dev, "VirtIO MMIO adapter"); - return (BUS_PROBE_DEFAULT); -} - -static int -vtmmio_setup_platform(struct vtmmio_softc *sc) -{ - phandle_t platform_node; - struct fdt_ic *ic; - phandle_t xref; - phandle_t node; - - sc->platform = NULL; - - if ((node = ofw_bus_get_node(sc->dev)) == -1) - return (ENXIO); - - if (OF_searchencprop(node, "platform", &xref, - sizeof(xref)) == -1) { - return (ENXIO); - } - - platform_node = OF_node_from_xref(xref); - - SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) { - if (ic->iph == platform_node) { - sc->platform = ic->dev; - break; - } - } - - if (sc->platform == NULL) { - /* No platform-specific device. Ignore it. */ - } - - return (0); -} - -static int +int vtmmio_attach(device_t dev) { struct vtmmio_softc *sc; @@ -306,8 +214,6 @@ sc = device_get_softc(dev); sc->dev = dev; - vtmmio_setup_platform(sc); - rid = 0; sc->res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); Index: sys/dev/virtio/mmio/virtio_mmio_acpi.c =================================================================== --- sys/dev/virtio/mmio/virtio_mmio_acpi.c +++ sys/dev/virtio/mmio/virtio_mmio_acpi.c @@ -1,11 +1,15 @@ /*- * Copyright (c) 2014 Ruslan Bukin + * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * + * Portions of this software were developed by Andrew Turner + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -26,34 +30,57 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _VIRTIO_MMIO_H -#define _VIRTIO_MMIO_H - -#define VIRTIO_MMIO_MAGIC_VALUE 0x000 -#define VIRTIO_MMIO_VERSION 0x004 -#define VIRTIO_MMIO_DEVICE_ID 0x008 -#define VIRTIO_MMIO_VENDOR_ID 0x00c -#define VIRTIO_MMIO_HOST_FEATURES 0x010 -#define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014 -#define VIRTIO_MMIO_GUEST_FEATURES 0x020 -#define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 -#define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 -#define VIRTIO_MMIO_QUEUE_SEL 0x030 -#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 -#define VIRTIO_MMIO_QUEUE_NUM 0x038 -#define VIRTIO_MMIO_QUEUE_ALIGN 0x03c -#define VIRTIO_MMIO_QUEUE_PFN 0x040 -#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 -#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 -#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 -#define VIRTIO_MMIO_STATUS 0x070 -#define VIRTIO_MMIO_CONFIG 0x100 -#define VIRTIO_MMIO_INT_VRING (1 << 0) -#define VIRTIO_MMIO_INT_CONFIG (1 << 1) -#define VIRTIO_MMIO_VRING_ALIGN 4096 - -#endif /* _VIRTIO_MMIO_H */ +/* + * VirtIO MMIO interface. + * This driver is heavily based on VirtIO PCI interface driver. + */ + +#include "opt_acpi.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include + +static int vtmmio_acpi_probe(device_t); + +static device_method_t vtmmio_acpi_methods[] = { + /* Device interface. */ + DEVMETHOD(device_probe, vtmmio_acpi_probe), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(virtio_mmio, vtmmio_acpi_driver, vtmmio_acpi_methods, + sizeof(struct vtmmio_softc), vtmmio_driver); + +static devclass_t vtmmio_acpi_devclass; + +DRIVER_MODULE(virtio_mmio, acpi, vtmmio_acpi_driver, vtmmio_acpi_devclass, 0,0); +MODULE_DEPEND(virtio_mmio, acpi, 1, 1, 1); + +static int +vtmmio_acpi_probe(device_t dev) +{ + ACPI_HANDLE h; + + if ((h = acpi_get_handle(dev)) == NULL) + return (ENXIO); + + if (!acpi_MatchHid(h, "LNRO0005")) + return (ENXIO); + + device_set_desc(dev, "VirtIO MMIO adapter"); + return (BUS_PROBE_DEFAULT); +} Index: sys/dev/virtio/mmio/virtio_mmio_fdt.c =================================================================== --- /dev/null +++ sys/dev/virtio/mmio/virtio_mmio_fdt.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2014 Ruslan Bukin + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by Andrew Turner + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * VirtIO MMIO interface. + * This driver is heavily based on VirtIO PCI interface driver. + */ + +/* + * FDT example: + * virtio_block@1000 { + * compatible = "virtio,mmio"; + * reg = <0x1000 0x100>; + * interrupts = <63>; + * interrupt-parent = <&GIC>; + * }; + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static int vtmmio_fdt_probe(device_t); +static int vtmmio_fdt_attach(device_t); + +static device_method_t vtmmio_fdt_methods[] = { + /* Device interface. */ + DEVMETHOD(device_probe, vtmmio_fdt_probe), + DEVMETHOD(device_attach, vtmmio_fdt_attach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(virtio_mmio, vtmmio_fdt_driver, vtmmio_fdt_methods, + sizeof(struct vtmmio_softc), vtmmio_driver); + +static devclass_t vtmmio_fdt_devclass; + +DRIVER_MODULE(virtio_mmio, simplebus, vtmmio_fdt_driver, vtmmio_fdt_devclass, + 0, 0); +DRIVER_MODULE(virtio_mmio, ofwbus, vtmmio_fdt_driver, vtmmio_fdt_devclass, 0,0); +MODULE_DEPEND(virtio_mmio, simplebus, 1, 1, 1); +MODULE_DEPEND(virtio_mmio, virtio, 1, 1, 1); + +static int +vtmmio_fdt_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "virtio,mmio")) + return (ENXIO); + + device_set_desc(dev, "VirtIO MMIO adapter"); + return (BUS_PROBE_DEFAULT); +} + +static int +vtmmio_setup_platform(device_t dev, struct vtmmio_softc *sc) +{ + phandle_t platform_node; + struct fdt_ic *ic; + phandle_t xref; + phandle_t node; + + sc->platform = NULL; + + if ((node = ofw_bus_get_node(dev)) == -1) + return (ENXIO); + + if (OF_searchencprop(node, "platform", &xref, + sizeof(xref)) == -1) { + return (ENXIO); + } + + platform_node = OF_node_from_xref(xref); + + SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) { + if (ic->iph == platform_node) { + sc->platform = ic->dev; + break; + } + } + + if (sc->platform == NULL) { + /* No platform-specific device. Ignore it. */ + } + + return (0); +} + +static int +vtmmio_fdt_attach(device_t dev) +{ + struct vtmmio_softc *sc; + + sc = device_get_softc(dev); + vtmmio_setup_platform(dev, sc); + + return (vtmmio_attach(dev)); +}