static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset) { SyborgVirtIOProxy *s = opaque; VirtIODevice *vdev = s->vdev; DPRINTF("readb 0x%x\n", (int)offset); if (offset >= SYBORG_VIRTIO_CONFIG) { return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG); } BADF("Bad byte read offset 0x%x\n", (int)offset); return -1; }
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size) { VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset); if (!vdev) { /* If no backend is present, we treat most registers as * read-as-zero, except for the magic number, version and * vendor ID. This is not strictly sanctioned by the virtio * spec, but it allows us to provide transports with no backend * plugged in which don't confuse Linux's virtio code: the * probe won't complain about the bad magic number, but the * device ID of zero means no backend will claim it. */ switch (offset) { case VIRTIO_MMIO_MAGIC: return VIRT_MAGIC; case VIRTIO_MMIO_VERSION: return VIRT_VERSION; case VIRTIO_MMIO_VENDORID: return VIRT_VENDOR; default: return 0; } } if (offset >= VIRTIO_MMIO_CONFIG) { offset -= VIRTIO_MMIO_CONFIG; switch (size) { case 1: return virtio_config_readb(vdev, offset); case 2: return virtio_config_readw(vdev, offset); case 4: return virtio_config_readl(vdev, offset); default: abort(); } } if (size != 4) { DPRINTF("wrong size access to register!\n"); return 0; } switch (offset) { case VIRTIO_MMIO_MAGIC: return VIRT_MAGIC; case VIRTIO_MMIO_VERSION: return VIRT_VERSION; case VIRTIO_MMIO_DEVICEID: return vdev->device_id; case VIRTIO_MMIO_VENDORID: return VIRT_VENDOR; case VIRTIO_MMIO_HOSTFEATURES: if (proxy->host_features_sel) { return 0; } return vdev->host_features; case VIRTIO_MMIO_QUEUENUMMAX: if (!virtio_queue_get_num(vdev, vdev->queue_sel)) { return 0; } return VIRTQUEUE_MAX_SIZE; case VIRTIO_MMIO_QUEUEPFN: return virtio_queue_get_addr(vdev, vdev->queue_sel) >> proxy->guest_page_shift; case VIRTIO_MMIO_INTERRUPTSTATUS: return atomic_read(&vdev->isr); case VIRTIO_MMIO_STATUS: return vdev->status; case VIRTIO_MMIO_HOSTFEATURESSEL: case VIRTIO_MMIO_GUESTFEATURES: case VIRTIO_MMIO_GUESTFEATURESSEL: case VIRTIO_MMIO_GUESTPAGESIZE: case VIRTIO_MMIO_QUEUESEL: case VIRTIO_MMIO_QUEUENUM: case VIRTIO_MMIO_QUEUEALIGN: case VIRTIO_MMIO_QUEUENOTIFY: case VIRTIO_MMIO_INTERRUPTACK: DPRINTF("read of write-only register\n"); return 0; default: DPRINTF("bad register offset\n"); return 0; } return 0; }