An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
174 lines
5.4 KiB
C
174 lines
5.4 KiB
C
#pragma once
|
|
|
|
// virtio 1.0 over PCI — the transport, and virtio-gpu's 2D protocol.
|
|
//
|
|
// Written from the OASIS specification (virtio 1.1, chapters 2, 4.1 and 5.7),
|
|
// which is a public document with no licence on what you write from it. Same
|
|
// reasoning as kernel/drivers/xhci.c.
|
|
//
|
|
// Why virtio-gpu at all, when there is already a framebuffer: the VBE
|
|
// framebuffer is a flat block of memory the loader happened to be told about.
|
|
// It has no mode setting, no notion of a frame being complete, and no way to
|
|
// ask the host to present anything -- so a compositor drawing into it is
|
|
// racing the scanout with no way to synchronise. virtio-gpu has resources,
|
|
// explicit transfer and an explicit flush, which is the model every real GPU
|
|
// driver has. It is the smallest device that teaches the right shape.
|
|
|
|
// --- PCI transport ---------------------------------------------------------
|
|
|
|
#define VIRTIO_VENDOR 0x1AF4
|
|
// Modern (1.0) device IDs are 0x1040 + the virtio device type. GPU is type 16.
|
|
#define VIRTIO_DEV_GPU 0x1050
|
|
|
|
// Vendor-specific PCI capability, which is how a virtio device says where in
|
|
// its BARs each configuration structure lives.
|
|
#define PCI_CAP_ID_VNDR 0x09
|
|
|
|
#define VIRTIO_PCI_CAP_COMMON_CFG 1
|
|
#define VIRTIO_PCI_CAP_NOTIFY_CFG 2
|
|
#define VIRTIO_PCI_CAP_ISR_CFG 3
|
|
#define VIRTIO_PCI_CAP_DEVICE_CFG 4
|
|
|
|
// Offsets within the common configuration structure. Written out rather than
|
|
// declared as a struct: the fields are little-endian by specification and of
|
|
// mixed width, and a struct invites the compiler to pad or a caller to forget
|
|
// that these are MMIO and must be accessed at exactly the stated width.
|
|
#define VCOMMON_DFEAT_SEL 0x00 // le32
|
|
#define VCOMMON_DFEAT 0x04 // le32
|
|
#define VCOMMON_GFEAT_SEL 0x08 // le32
|
|
#define VCOMMON_GFEAT 0x0C // le32
|
|
#define VCOMMON_MSIX_CFG 0x10 // le16
|
|
#define VCOMMON_NUM_QUEUES 0x12 // le16
|
|
#define VCOMMON_STATUS 0x14 // u8
|
|
#define VCOMMON_CFG_GEN 0x15 // u8
|
|
#define VCOMMON_Q_SELECT 0x16 // le16
|
|
#define VCOMMON_Q_SIZE 0x18 // le16
|
|
#define VCOMMON_Q_MSIX 0x1A // le16
|
|
#define VCOMMON_Q_ENABLE 0x1C // le16
|
|
#define VCOMMON_Q_NOTIFY_OFF 0x1E // le16
|
|
#define VCOMMON_Q_DESC 0x20 // le64
|
|
#define VCOMMON_Q_DRIVER 0x28 // le64
|
|
#define VCOMMON_Q_DEVICE 0x30 // le64
|
|
|
|
// device_status bits, set in this order during bring-up.
|
|
#define VSTATUS_ACK 1
|
|
#define VSTATUS_DRIVER 2
|
|
#define VSTATUS_DRIVER_OK 4
|
|
#define VSTATUS_FEATURES_OK 8
|
|
#define VSTATUS_FAILED 0x80
|
|
|
|
#define VIRTIO_F_VERSION_1 32 // feature bit: this is a 1.0 device
|
|
|
|
// --- split virtqueue -------------------------------------------------------
|
|
|
|
#define VRING_DESC_F_NEXT 1
|
|
#define VRING_DESC_F_WRITE 2 // device writes it; i.e. this is our buffer
|
|
|
|
struct vring_desc {
|
|
uint64 addr;
|
|
uint32 len;
|
|
uint16 flags;
|
|
uint16 next;
|
|
} __attribute__((packed));
|
|
|
|
struct vring_avail {
|
|
uint16 flags;
|
|
uint16 idx;
|
|
uint16 ring[];
|
|
} __attribute__((packed));
|
|
|
|
struct vring_used_elem {
|
|
uint32 id;
|
|
uint32 len;
|
|
} __attribute__((packed));
|
|
|
|
struct vring_used {
|
|
uint16 flags;
|
|
uint16 idx;
|
|
struct vring_used_elem ring[];
|
|
} __attribute__((packed));
|
|
|
|
// --- virtio-gpu, 2D --------------------------------------------------------
|
|
|
|
#define VIRTIO_GPU_CMD_GET_DISPLAY_INFO 0x0100
|
|
#define VIRTIO_GPU_CMD_RESOURCE_CREATE_2D 0x0101
|
|
#define VIRTIO_GPU_CMD_RESOURCE_UNREF 0x0102
|
|
#define VIRTIO_GPU_CMD_SET_SCANOUT 0x0103
|
|
#define VIRTIO_GPU_CMD_RESOURCE_FLUSH 0x0104
|
|
#define VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D 0x0105
|
|
#define VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING 0x0106
|
|
|
|
#define VIRTIO_GPU_RESP_OK_NODATA 0x1100
|
|
#define VIRTIO_GPU_RESP_OK_DISPLAY_INFO 0x1101
|
|
|
|
#define VIRTIO_GPU_MAX_SCANOUTS 16
|
|
|
|
// B8G8R8X8, which is what a 32-bit little-endian 0x00RRGGBB word looks like in
|
|
// memory -- the same layout vga.c already draws into, so a framebuffer can be
|
|
// handed over without a conversion pass.
|
|
#define VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM 2
|
|
|
|
struct virtio_gpu_ctrl_hdr {
|
|
uint32 type;
|
|
uint32 flags;
|
|
uint64 fence_id;
|
|
uint32 ctx_id;
|
|
uint32 padding;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_rect {
|
|
uint32 x, y, width, height;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_display_one {
|
|
struct virtio_gpu_rect r;
|
|
uint32 enabled;
|
|
uint32 flags;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_resp_display_info {
|
|
struct virtio_gpu_ctrl_hdr hdr;
|
|
struct virtio_gpu_display_one pmodes[VIRTIO_GPU_MAX_SCANOUTS];
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_resource_create_2d {
|
|
struct virtio_gpu_ctrl_hdr hdr;
|
|
uint32 resource_id;
|
|
uint32 format;
|
|
uint32 width;
|
|
uint32 height;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_mem_entry {
|
|
uint64 addr;
|
|
uint32 length;
|
|
uint32 padding;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_resource_attach_backing {
|
|
struct virtio_gpu_ctrl_hdr hdr;
|
|
uint32 resource_id;
|
|
uint32 nr_entries;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_set_scanout {
|
|
struct virtio_gpu_ctrl_hdr hdr;
|
|
struct virtio_gpu_rect r;
|
|
uint32 scanout_id;
|
|
uint32 resource_id;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_transfer_to_host_2d {
|
|
struct virtio_gpu_ctrl_hdr hdr;
|
|
struct virtio_gpu_rect r;
|
|
uint64 offset;
|
|
uint32 resource_id;
|
|
uint32 padding;
|
|
} __attribute__((packed));
|
|
|
|
struct virtio_gpu_resource_flush {
|
|
struct virtio_gpu_ctrl_hdr hdr;
|
|
struct virtio_gpu_rect r;
|
|
uint32 resource_id;
|
|
uint32 padding;
|
|
} __attribute__((packed));
|