refactor: ByteOffset newtype for window/register/ring offsets; named virtio-gpu cmd fields

This commit is contained in:
2026-10-27 21:52:33 +01:00
parent 842d14987c
commit 7b8258b231
13 changed files with 145 additions and 93 deletions

View File

@@ -1,7 +1,7 @@
use crate::mmio::MmioAccess;
use crate::queue::{Descriptor, VirtioQueue};
use libkos::Window;
use types::address::PhysicalAddress;
use types::address::{ByteOffset, PhysicalAddress};
use types::display::Dimension;
/// The command page: commands go out from its start, responses come back
@@ -12,59 +12,76 @@ pub struct GpuDmaAddrs {
pub resp_pa: PhysicalAddress,
}
pub const RESPONSE: usize = 512;
pub const RESPONSE: ByteOffset = ByteOffset::new(512);
/// Command fields (virtio spec 5.7.6.7): a 24-byte header, then the body.
const TYPE: ByteOffset = ByteOffset::new(0);
const BODY: ByteOffset = ByteOffset::new(24);
/// Most bodies start with a rectangle: x, y, width, height.
const RECT_X: ByteOffset = ByteOffset::new(24);
const RECT_Y: ByteOffset = ByteOffset::new(28);
const RECT_W: ByteOffset = ByteOffset::new(32);
const RECT_H: ByteOffset = ByteOffset::new(36);
/// The 24 bytes of header and 16 of rectangle in a display-info response.
const DISPLAY_W: ByteOffset = ByteOffset::new(24 + 8);
const DISPLAY_H: ByteOffset = ByteOffset::new(24 + 12);
pub fn create_2d(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, width: Dimension, height: Dimension) -> bool {
write_cmd_header(&dma.cmd, 0x0101);
dma.cmd.write(24, resource_id);
dma.cmd.write(28, 1u32);
dma.cmd.write(32, width.raw() as u32);
dma.cmd.write(36, height.raw() as u32);
// Resource id, format (1: B8G8R8A8), width, height.
dma.cmd.write(BODY, resource_id);
dma.cmd.write(BODY + 4, 1u32);
dma.cmd.write(BODY + 8, width.raw() as u32);
dma.cmd.write(BODY + 12, height.raw() as u32);
submit_cmd(mmio, queue, dma, 40)
}
pub fn attach_backing(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, fb_pa: PhysicalAddress, fb_size: u32) -> bool {
write_cmd_header(&dma.cmd, 0x0106);
dma.cmd.write(24, resource_id);
dma.cmd.write(28, 1u32);
dma.cmd.write(32, fb_pa.raw() as u64 as u64);
dma.cmd.write(40, fb_size);
// Resource id, one memory entry: its address and length.
dma.cmd.write(BODY, resource_id);
dma.cmd.write(BODY + 4, 1u32);
dma.cmd.write(BODY + 8, fb_pa.raw() as u64);
dma.cmd.write(BODY + 16, fb_size);
submit_cmd(mmio, queue, dma, 48)
}
pub fn set_scanout(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, scanout_id: u32, resource_id: u32, width: Dimension, height: Dimension) -> bool {
write_cmd_header(&dma.cmd, 0x0103);
dma.cmd.write(32, width.raw() as u32);
dma.cmd.write(36, height.raw() as u32);
dma.cmd.write(40, scanout_id);
dma.cmd.write(44, resource_id);
// The rectangle (from 0, 0), then scanout and resource ids.
dma.cmd.write(RECT_W, width.raw() as u32);
dma.cmd.write(RECT_H, height.raw() as u32);
dma.cmd.write(BODY + 16, scanout_id);
dma.cmd.write(BODY + 20, resource_id);
submit_cmd(mmio, queue, dma, 48)
}
pub fn transfer_to_host(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, x: u32, y: u32, w: u32, h: u32) -> bool {
write_cmd_header(&dma.cmd, 0x0105);
dma.cmd.write(24, x);
dma.cmd.write(28, y);
dma.cmd.write(32, w);
dma.cmd.write(36, h);
dma.cmd.write(40, 0u64);
dma.cmd.write(48, resource_id);
put_rect(&dma.cmd, x, y, w, h);
// Offset into the resource's memory, then the resource id.
dma.cmd.write(BODY + 16, 0u64);
dma.cmd.write(BODY + 24, resource_id);
submit_cmd(mmio, queue, dma, 56)
}
pub fn resource_flush(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, x: u32, y: u32, w: u32, h: u32) -> bool {
write_cmd_header(&dma.cmd, 0x0104);
dma.cmd.write(24, x);
dma.cmd.write(28, y);
dma.cmd.write(32, w);
dma.cmd.write(36, h);
dma.cmd.write(40, resource_id);
put_rect(&dma.cmd, x, y, w, h);
dma.cmd.write(BODY + 16, resource_id);
submit_cmd(mmio, queue, dma, 48)
}
fn write_cmd_header(cmd: &Window, cmd_type: u32) {
cmd.fill_u32(0, 128, 0);
cmd.write(0, cmd_type);
cmd.fill_u32(ByteOffset::ZERO, 128, 0);
cmd.write(TYPE, cmd_type);
}
fn put_rect(cmd: &Window, x: u32, y: u32, w: u32, h: u32) {
cmd.write(RECT_X, x);
cmd.write(RECT_Y, y);
cmd.write(RECT_W, w);
cmd.write(RECT_H, h);
}
pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs) -> Option<(u32, u32)> {
@@ -75,8 +92,8 @@ pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDm
];
if !queue.submit(mmio, &descs) { return None; }
if dma.cmd.read::<u32>(RESPONSE) != 0x1101 { return None; }
let w: u32 = dma.cmd.read(RESPONSE + 24 + 8);
let h: u32 = dma.cmd.read(RESPONSE + 24 + 12);
let w: u32 = dma.cmd.read(RESPONSE + DISPLAY_W.raw());
let h: u32 = dma.cmd.read(RESPONSE + DISPLAY_H.raw());
if w > 0 && h > 0 { Some((w, h)) } else { None }
}