blob: 44344a4993f4af5cc299f7239303f96f40db7cf1 [file] [log] [blame]
#include "config.h" // CONFIG_DEBUG_LEVEL
#include "malloc.h" // free
#include "output.h" // dprintf
#include "stacks.h" // run_thread
#include "string.h" // memset
#include "util.h" // acpi_dsdt_*
#include "virtio-pci.h"
#include "virtio-blk.h"
#include "virtio-scsi.h"
#include "virtio-ring.h"
#include "virtio-mmio.h"
void virtio_mmio_setup_acpi(void)
{
static const char *virtio_hid = "LNRO0005";
struct acpi_device *dev;
u64 mem, irq, unused;
for (dev = acpi_dsdt_find_string(NULL, virtio_hid);
dev != NULL;
dev = acpi_dsdt_find_string(dev, virtio_hid)) {
if (acpi_dsdt_find_mem(dev, &mem, &unused) < 0)
continue;
if (acpi_dsdt_find_irq(dev, &irq) < 0)
continue;
dprintf(1, "ACPI: virtio-mmio device %s at 0x%llx, irq %lld\n",
acpi_dsdt_name(dev), mem, irq);
virtio_mmio_setup_one(mem);
}
}
void virtio_mmio_setup_one(u64 addr)
{
static const char *names[] = {
[ 1 ] = "net",
[ 2 ] = "blk",
[ 3 ] = "console",
[ 4 ] = "rng",
[ 8 ] = "scsi",
[ 9 ] = "9p",
[ 16 ] = "gpu",
[ 19 ] = "vsock",
[ 18 ] = "input",
[ 26 ] = "fs",
};
const char *name;
u32 magic, version, devid;
void *mmio;
if (addr >= 0x100000000) {
dprintf(1, "virtio-mmio: %llx: above 4G\n", addr);
return;
}
mmio = (void*)(u32)(addr);
magic = readl(mmio);
if (magic != 0x74726976) {
dprintf(1, "virtio-mmio: %llx: magic mismatch\n", addr);
return;
}
version = readl(mmio+4);
if (version != 1 /* legacy */ &&
version != 2 /* 1.0 */) {
dprintf(1, "virtio-mmio: %llx: unknown version %d\n", addr, version);
return;
}
devid = readl(mmio+8);
name = (devid < ARRAY_SIZE(names) && names[devid] != NULL)
? names[devid] : "unknown";
dprintf(1, "virtio-mmio: %llx: device id %x (%s%s)\n",
addr, devid, name, version == 1 ? ", legacy" : "");
switch (devid) {
case 2: /* blk */
run_thread(init_virtio_blk_mmio, mmio);
break;
case 8: /* scsi */
run_thread(init_virtio_scsi_mmio, mmio);
break;
default:
break;
}
}
void vp_init_mmio(struct vp_device *vp, void *mmio)
{
memset(vp, 0, sizeof(*vp));
vp->use_mmio = 1;
vp->common.mode = VP_ACCESS_MMIO;
vp->common.memaddr = mmio;
vp->device.mode = VP_ACCESS_MMIO;
vp->device.memaddr = mmio + 0x100;
vp_reset(vp);
vp_set_status(vp, VIRTIO_CONFIG_S_ACKNOWLEDGE |
VIRTIO_CONFIG_S_DRIVER);
}