c5fc57dbf69fc9832722b277cb601ebc471bbfb7 viocon(4) console support for early kernel messages diff --git a/share/man/man4/viocon.4 b/share/man/man4/viocon.4 index 26f2bd6c26d..f6ce5da46ad 100644 --- a/share/man/man4/viocon.4 +++ b/share/man/man4/viocon.4 @@ -58,9 +58,11 @@ by .An Stefan Fritsch Aq Mt sf@sfritsch.de . It was ported to .Nx 10.0 . -.Sh BUGS -Use as a kernel console for -.Nx -is not yet supported. .Pp +Kernel support was implemented by +.An Taylor R. Campbell Aq Mt riastradh@NetBSD.org . +.Pp +Early console support was implemented by +.An Emile So iMil Sc Heitor Aq Mt imil@NetBSD.org . +.Sh BUGS The multiport feature is not yet supported. diff --git a/sys/arch/x86/conf/MICROVM.common b/sys/arch/x86/conf/MICROVM.common index 2969150a6fa..70701f66a4d 100644 --- a/sys/arch/x86/conf/MICROVM.common +++ b/sys/arch/x86/conf/MICROVM.common @@ -118,3 +118,5 @@ pseudo-device drvctl file-system PUFFS pseudo-device putter + +options VIOCON_CONSOLE diff --git a/sys/arch/x86/x86/consinit.c b/sys/arch/x86/x86/consinit.c index 9ef384c2c07..78f60c4e82b 100644 --- a/sys/arch/x86/x86/consinit.c +++ b/sys/arch/x86/x86/consinit.c @@ -32,6 +32,7 @@ __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.41 2025/04/30 05:15:08 imil Exp $"); #include "opt_kgdb.h" #include "opt_puc.h" #include "opt_xen.h" +#include "opt_viocon.h" #include #include @@ -104,6 +105,13 @@ __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.41 2025/04/30 05:15:08 imil Exp $"); #include #endif +#ifdef VIOCON_CONSOLE +#include +#include +#include +#include /* for kernel_map */ +#endif + #ifndef CONSDEVNAME #define CONSDEVNAME "pc" #endif @@ -263,6 +271,22 @@ dokbd: error); return; } +#ifdef VIOCON_CONSOLE + if (!strcmp(console_devname, "viocon")) { + /* We need uvm to be ready before we can map the MMIO region */ + if (!kernel_map) { + initted = 0; + return; + } + /* + * In x86 microvm, mmio device enumeration is done by parsing + * the kernel command line + */ + enumerate_mmio_devices = mmio_args_parse; + if (!viocon_earlyinit()) + return; + } +#endif #if (NCOM > 0) if (!strcmp(console_devname, "com")) { int addr = consinfo->addr; diff --git a/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c b/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c index 18a0ce9f8bc..b55c5a03ae4 100644 --- a/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c +++ b/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c @@ -63,21 +63,17 @@ #define VIRTIO_PRIVATE #include +#include #include #include +#include +#include #include #include "ioapic.h" #define VMMIOSTR "virtio_mmio.device=" -struct mmio_args { - uint64_t sz; - uint64_t baseaddr; - uint64_t irq; - uint64_t id; -}; - struct virtio_mmio_cmdline_softc { struct virtio_mmio_softc sc_msc; struct mmio_args margs; @@ -112,6 +108,8 @@ parsearg(struct mmio_args *margs, const char *arg) { char *p; + /* Bus space type */ + margs->bst = x86_bus_space_mem; /* */ margs->sz = strtoull(arg, (char **)&p, 0); if ((margs->sz == 0) || (margs->sz == UINT64_MAX)) @@ -186,50 +184,75 @@ bad: aprint_error("Error parsing virtio_mmio parameter: %s\n", arg); } +int +mmio_args_parse(struct mmio_args *margs) +{ + int keylen = strlen(VMMIOSTR); + char *next; + static char cmdline[LINE_MAX], *parg; + + /* first pass, or emptied parg from last pass */ + if (parg == NULL) { + strlcpy(cmdline, xen_start_info.cmd_line, sizeof(cmdline)); + parg = strstr(cmdline, VMMIOSTR); + } + + /* no args were found */ + if (parg == NULL) { + return MMIO_NO_ARG; + } + + /* useless, no parameters */ + if (strlen(parg) <= keylen) { + parg = NULL; + return MMIO_NO_ARG; + } + + parg += keylen; + + next = parg; + while (*next && *next != ' ') /* find end of argument */ + next++; + if (*next) { /* space */ + *next++ = '\0'; /* end the argument string */ + next = strstr(next,VMMIOSTR); + } + parsearg(margs, parg); + + if (next != NULL) + parg = next; + + if (!*parg) { + parg = NULL; + return MMIO_LAST_ARG; + } + + return MMIO_NEXT_ARG; +} + static void virtio_mmio_cmdline_attach(device_t parent, device_t self, void *aux) { struct virtio_mmio_cmdline_softc *sc = device_private(self); struct pv_attach_args *pvaa = aux; struct mmio_args *margs = &sc->margs; - int keylen = strlen(VMMIOSTR); - char *next; - static char cmdline[LINE_MAX], *parg = NULL; + int mmioarg; aprint_normal("\n"); aprint_naive("\n"); - if (parg == NULL) { /* first pass */ - strlcpy(cmdline, xen_start_info.cmd_line, sizeof(cmdline)); - aprint_verbose_dev(self, "kernel parameters: %s\n", - cmdline); - parg = strstr(cmdline, VMMIOSTR); - } + mmioarg = mmio_args_parse(margs); - if (parg != NULL) { - parg += keylen; - if (!*parg) - return; - - next = parg; - while (*next && *next != ' ') /* find end of argument */ - next++; - if (*next) { /* space */ - *next++ = '\0'; /* end the argument string */ - next = strstr(next, VMMIOSTR); - } - - aprint_normal_dev(self, "viommio: %s\n", parg); - parsearg(margs, parg); - - if (virtio_mmio_cmdline_do_attach(self, pvaa, margs)) - return; - - if (next) { - parg = next; - config_found(parent, pvaa, NULL, CFARGS_NONE); - } - } + if (mmioarg == MMIO_NO_ARG) + return; + + aprint_normal_dev(self, "viommio: @%#" PRIxPADDR "\n", margs->baseaddr); + + if (virtio_mmio_cmdline_do_attach(self, pvaa, margs)) + return; + + if (mmioarg == MMIO_NEXT_ARG) + config_found(parent, pvaa, NULL, CFARGS_NONE); } static int @@ -250,11 +273,10 @@ virtio_mmio_cmdline_do_attach(device_t self, error = bus_space_map(msc->sc_iot, margs->baseaddr, margs->sz, 0, &msc->sc_ioh); if (error) { - aprint_error_dev(self, "couldn't map %#" PRIx64 ": %d", + aprint_error_dev(self, "couldn't map %#" PRIxPADDR ": %d", margs->baseaddr, error); return error; } - msc->sc_alloc_interrupts = virtio_mmio_cmdline_alloc_interrupts; msc->sc_free_interrupts = virtio_mmio_cmdline_free_interrupts; diff --git a/sys/dev/virtio/arch/x86/virtio_mmio_parse.h b/sys/dev/virtio/arch/x86/virtio_mmio_parse.h new file mode 100644 index 00000000000..e78ac50b6d3 --- /dev/null +++ b/sys/dev/virtio/arch/x86/virtio_mmio_parse.h @@ -0,0 +1,41 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2025 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emile 'iMil' Heitor. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _VIRTIO_MMIO_PARSE_H_ +#define _VIRTIO_MMIO_PARSE_H_ + +#define MMIO_NEXT_ARG 2 +#define MMIO_LAST_ARG 1 +#define MMIO_NO_ARG 0 + +int mmio_args_parse(struct mmio_args *); + +#endif /* _VIRTIO_MMIO_PARSE_H_ */ diff --git a/sys/dev/virtio/files.virtio b/sys/dev/virtio/files.virtio index 4e399624ab0..4724a4c3347 100644 --- a/sys/dev/virtio/files.virtio +++ b/sys/dev/virtio/files.virtio @@ -5,6 +5,7 @@ include "dev/pci/files.virtio" file dev/virtio/virtio_mmio.c virtio_mmio +defflag opt_viocon.h VIOCON_CONSOLE device viocon attach viocon at virtio file dev/virtio/viocon.c viocon diff --git a/sys/dev/virtio/viocon.c b/sys/dev/virtio/viocon.c index 73c938936be..cce0b55c639 100644 --- a/sys/dev/virtio/viocon.c +++ b/sys/dev/virtio/viocon.c @@ -33,8 +33,16 @@ __KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.10 2024/08/05 19:13:34 riastradh Exp $" #include #include +#include "opt_viocon.h" + +#ifdef VIOCON_CONSOLE +#include +#include +#include +#endif + #include -#include +#include #include "ioconf.h" @@ -117,6 +125,13 @@ struct viocon_port { uint16_t vp_cols; u_char *vp_rx_buf; u_char *vp_tx_buf; + +#ifdef VIOCON_CONSOLE + struct consdev vp_cntab; + unsigned int vp_pollpos; + unsigned int vp_polllen; + bool vp_polling; +#endif }; struct viocon_softc { @@ -153,6 +168,26 @@ void vioconstop(struct tty *, int); int vioconioctl(dev_t, u_long, void *, int, struct lwp *); struct tty *viocontty(dev_t dev); +#ifdef VIOCON_CONSOLE +static void viocon_cnpollc(dev_t, int); +static int viocon_cngetc(dev_t); +static void viocon_cnputc(dev_t, int); +static void viocon_early_putc(dev_t, int); + +static uint32_t *early_console; +static vaddr_t viocon_mmio_vaddr = 0; + +int (*enumerate_mmio_devices)(struct mmio_args *) = NULL; + +static struct consdev viocon_early_consdev = { + .cn_putc = viocon_early_putc, + .cn_getc = NULL, + .cn_pollc = NULL, + .cn_dev = NODEV, + .cn_pri = CN_NORMAL +}; +#endif + CFATTACH_DECL_NEW(viocon, sizeof(struct viocon_softc), viocon_match, viocon_attach, /*detach*/NULL, /*activate*/NULL); @@ -183,7 +218,88 @@ dev2port(dev_t dev) return dev2sc(dev)->sc_ports[VIOCONPORT(dev)]; } -int viocon_match(struct device *parent, struct cfdata *match, void *aux) +#ifdef VIOCON_CONSOLE +static void +viocon_early_putc(dev_t dev, int c) +{ + *early_console = c; +} + +static void +free_viocon_mmio_vaddr(void) +{ + if (!viocon_mmio_vaddr) + return; + + pmap_kremove(viocon_mmio_vaddr, PAGE_SIZE); + pmap_update(pmap_kernel()); + uvm_km_free(kernel_map, viocon_mmio_vaddr, PAGE_SIZE, UVM_KMF_VAONLY); + viocon_mmio_vaddr = 0; +} + +int +viocon_earlyinit(void) +{ + struct mmio_args margs; + paddr_t mmio_baseaddr = 0; + struct virtio_mmio_softc sc; + + if (enumerate_mmio_devices == NULL) + return -1; + + while ((*enumerate_mmio_devices)(&margs)) { + if (!mmio_baseaddr) { + /* Fetch a page for early MMIO mapping */ + viocon_mmio_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, + UVM_KMF_VAONLY | UVM_KMF_NOWAIT); + if (!viocon_mmio_vaddr) + return -1; + /* map a page for early virtio console */ + mmio_baseaddr = margs.baseaddr & ~(PAGE_SIZE - 1); + pmap_kenter_pa(viocon_mmio_vaddr, mmio_baseaddr, + VM_PROT_READ|VM_PROT_WRITE, PMAP_NOCACHE); + pmap_update(pmap_kernel()); + } + + sc.sc_iot = margs.bst; + /* + * viocon_mmio_vaddr = reserved page + * margs.baseaddr = pa + * mmio_baseaddr = MMIO base address + */ + sc.sc_ioh = viocon_mmio_vaddr + (margs.baseaddr - mmio_baseaddr); + sc.sc_iosize = margs.sz; + sc.sc_le_regs = (BYTE_ORDER == LITTLE_ENDIAN); + + aprint_verbose("mmio addr:%#" PRIxPADDR "\n", margs.baseaddr); + + if (bus_space_read_4(sc.sc_iot, sc.sc_ioh, + VIRTIO_MMIO_MAGIC_VALUE) != VIRTIO_MMIO_MAGIC) + continue; + if (virtio_mmio_reg_read(&sc, VIRTIO_MMIO_DEVICE_ID) != + VIRTIO_DEVICE_ID_CONSOLE) + continue; + if (!(virtio_mmio_reg_read(&sc, VIRTIO_MMIO_DEVICE_FEATURES) & + VIRTIO_CONSOLE_F_EMERG_WRITE)) + continue; + + early_console = + (uint32_t *)(sc.sc_ioh + + VIRTIO_MMIO_CONFIG + VIRTIO_CONSOLE_EMERG_WR); + + cn_tab = &viocon_early_consdev; + + return 0; + } + + free_viocon_mmio_vaddr(); + + return -1; +} +#endif + +int +viocon_match(struct device *parent, struct cfdata *match, void *aux) { struct virtio_attach_args *va = aux; if (va->sc_childdevid == VIRTIO_DEVICE_ID_CONSOLE) @@ -229,6 +345,22 @@ viocon_attach(struct device *parent, struct device *self, void *aux) viocon_rx_fill(sc->sc_ports[0]); +#ifdef VIOCON_CONSOLE + if (cn_tab == NULL || cn_tab->cn_dev == NODEV) { + sc->sc_ports[0]->vp_cntab = (struct consdev) { + .cn_pollc = viocon_cnpollc, + .cn_getc = viocon_cngetc, + .cn_putc = viocon_cnputc, + .cn_dev = VIOCONDEV(device_unit(self), 0), + .cn_pri = CN_REMOTE, + }; + aprint_normal_dev(sc->sc_dev, "console\n"); + cn_tab = &sc->sc_ports[0]->vp_cntab; + /* if a page was mapped for early console, free it */ + free_viocon_mmio_vaddr(); + } +#endif + return; err: kmem_free(sc->sc_vqs, nvqs * sizeof(sc->sc_vqs[0])); @@ -634,3 +766,75 @@ vioconioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) return error2; return ENOTTY; } + +#ifdef VIOCON_CONSOLE +static void +viocon_cnpollc(dev_t dev, int on) +{ + struct viocon_port *vp = dev2port(dev); + int s; + + KASSERT((bool)on != vp->vp_polling); + + s = spltty(); + vp->vp_polling = on; + vioconhwiflow(vp->vp_tty, on); + splx(s); +} + +static int +viocon_cngetc(dev_t dev) +{ + struct viocon_softc *sc = dev2sc(dev); + struct viocon_port *vp = dev2port(dev); + struct virtqueue *vq = vp->vp_rx; + struct virtio_softc *vsc = sc->sc_virtio; + int slot, len; + + KASSERT(vp->vp_polling); + while (vp->vp_polllen == 0) { + if (virtio_dequeue(vsc, vq, &slot, &len) == 0) { + KASSERTMSG(slot >= 0, "slot=%d", slot); + KASSERTMSG(slot < vq->vq_num, "slot=%d", slot); + KASSERTMSG(len > 0, "len=%d", len); + KASSERTMSG(len <= BUFSIZE, "len=%d", len); + bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap, + slot * BUFSIZE, BUFSIZE, BUS_DMASYNC_POSTREAD); + vp->vp_polllen = len; + vp->vp_pollpos = slot * BUFSIZE; + } + } + KASSERT(vp->vp_pollpos <= vq->vq_num * BUFSIZE); + vp->vp_polllen--; + return vp->vp_rx_buf[vp->vp_pollpos++]; +} + +static void +viocon_cnputc(dev_t dev, int c) +{ + struct viocon_softc *sc = dev2sc(dev); + struct viocon_port *vp = dev2port(dev); + struct virtqueue *vq = vp->vp_tx; + struct virtio_softc *vsc = sc->sc_virtio; + int slot; + int s, error; + + s = spltty(); + KERNEL_LOCK(1, NULL); + (void)viocon_tx_drain(vp, vq); + error = virtio_enqueue_prep(vsc, vq, &slot); + if (error == 0) { + error = virtio_enqueue_reserve(vsc, vq, slot, 1); + KASSERTMSG(error == 0, "error=%d", error); + vp->vp_tx_buf[slot * BUFSIZE] = c; + bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap, + vp->vp_tx_buf - vp->vp_rx_buf + slot * BUFSIZE, 1, + BUS_DMASYNC_PREWRITE); + virtio_enqueue_p(vsc, vq, slot, vp->vp_dmamap, + vp->vp_tx_buf - vp->vp_rx_buf + slot * BUFSIZE, 1, 1); + virtio_enqueue_commit(vsc, vq, slot, 1); + } + KERNEL_UNLOCK_ONE(NULL); + splx(s); +} +#endif diff --git a/sys/dev/virtio/virtio_mmio.c b/sys/dev/virtio/virtio_mmio.c index eb827f528f7..5c3f085577b 100644 --- a/sys/dev/virtio/virtio_mmio.c +++ b/sys/dev/virtio/virtio_mmio.c @@ -66,39 +66,8 @@ __KERNEL_RCSID(0, "$NetBSD: virtio_mmio.c,v 1.14 2024/03/09 11:55:59 isaki Exp $ #include #include -#define VIRTIO_PRIVATE #include -#define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) - -#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_DEVICE_FEATURES 0x010 /* "HostFeatures" in v1 */ -#define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014 /* "HostFeaturesSel" in v1 */ -#define VIRTIO_MMIO_DRIVER_FEATURES 0x020 /* "GuestFeatures" in v1 */ -#define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024 /* "GuestFeaturesSel" in v1 */ -#define VIRTIO_MMIO_V1_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_V1_QUEUE_ALIGN 0x03c -#define VIRTIO_MMIO_V1_QUEUE_PFN 0x040 -#define VIRTIO_MMIO_QUEUE_READY 0x044 -#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_V2_QUEUE_DESC_LOW 0x080 -#define VIRTIO_MMIO_V2_QUEUE_DESC_HIGH 0x084 -#define VIRTIO_MMIO_V2_QUEUE_AVAIL_LOW 0x090 -#define VIRTIO_MMIO_V2_QUEUE_AVAIL_HIGH 0x094 -#define VIRTIO_MMIO_V2_QUEUE_USED_LOW 0x0a0 -#define VIRTIO_MMIO_V2_QUEUE_USED_HIGH 0x0a4 -#define VIRTIO_MMIO_V2_CONFIG_GEN 0x0fc -#define VIRTIO_MMIO_CONFIG 0x100 - /* * MMIO configuration space for virtio-mmio v1 is in guest byte order. * @@ -128,7 +97,7 @@ static int virtio_mmio_alloc_interrupts(struct virtio_softc *); static void virtio_mmio_free_interrupts(struct virtio_softc *); static int virtio_mmio_setup_interrupts(struct virtio_softc *, int); -static uint32_t +uint32_t virtio_mmio_reg_read(struct virtio_mmio_softc *sc, bus_addr_t reg) { uint32_t val; diff --git a/sys/dev/virtio/virtio_mmiovar.h b/sys/dev/virtio/virtio_mmiovar.h index c95ec285287..bcd4066b756 100644 --- a/sys/dev/virtio/virtio_mmiovar.h +++ b/sys/dev/virtio/virtio_mmiovar.h @@ -28,8 +28,40 @@ #ifndef _VIRTIO_MMIOVAR_H_ #define _VIRTIO_MMIOVAR_H_ +#define VIRTIO_PRIVATE + #include /* XXX: move to non-pci */ +#define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) + +#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_DEVICE_FEATURES 0x010 /* "HostFeatures" in v1 */ +#define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014 /* "HostFeaturesSel" in v1 */ +#define VIRTIO_MMIO_DRIVER_FEATURES 0x020 /* "GuestFeatures" in v1 */ +#define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024 /* "GuestFeaturesSel" in v1 */ +#define VIRTIO_MMIO_V1_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_V1_QUEUE_ALIGN 0x03c +#define VIRTIO_MMIO_V1_QUEUE_PFN 0x040 +#define VIRTIO_MMIO_QUEUE_READY 0x044 +#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_V2_QUEUE_DESC_LOW 0x080 +#define VIRTIO_MMIO_V2_QUEUE_DESC_HIGH 0x084 +#define VIRTIO_MMIO_V2_QUEUE_AVAIL_LOW 0x090 +#define VIRTIO_MMIO_V2_QUEUE_AVAIL_HIGH 0x094 +#define VIRTIO_MMIO_V2_QUEUE_USED_LOW 0x0a0 +#define VIRTIO_MMIO_V2_QUEUE_USED_HIGH 0x0a4 +#define VIRTIO_MMIO_V2_CONFIG_GEN 0x0fc +#define VIRTIO_MMIO_CONFIG 0x100 + struct virtio_mmio_softc { struct virtio_softc sc_sc; @@ -46,9 +78,20 @@ struct virtio_mmio_softc { }; +struct mmio_args { + bus_space_tag_t bst; + uint64_t sz; + paddr_t baseaddr; + uint64_t irq; + uint64_t id; +}; + +uint32_t virtio_mmio_reg_read(struct virtio_mmio_softc *, bus_addr_t); bool virtio_mmio_common_probe_present(struct virtio_mmio_softc *); void virtio_mmio_common_attach(struct virtio_mmio_softc *); int virtio_mmio_common_detach(struct virtio_mmio_softc *, int); int virtio_mmio_intr(void *); +extern int (*enumerate_mmio_devices)(struct mmio_args *); + #endif /* _VIRTIO_MMIOVAR_H_ */