refactor: extract shared hw-virtio crate, eliminate VirtIO protocol duplication
Two VirtIO block and two VirtIO GPU implementations (adapter + driver)
shared 90% of their protocol logic. Extracted the common code into
hw-virtio, parameterized by MmioAccess trait.
New crate: hw-virtio (no_std, zero deps)
- mmio.rs: MmioAccess trait, DirectMmio, init_legacy_device(), scan
- queue.rs: VirtioQueue with descriptor chain submit + poll
- block.rs: block read protocol (3-descriptor chain)
- gpu.rs: GPU commands (create_2d, attach_backing, set_scanout,
transfer_to_host, resource_flush)
Adapter thin wrappers (identity-mapped, statics for DMA):
- virtio_blk.rs: 220 → 53 lines
- virtio_gpu.rs: 165 → 37 lines
Driver thin wrappers (mapped VAs, phys-info for DMA):
- drivers/block/virtio: 139 → 70 lines
- drivers/framebuffer/virtio: 146 → 95 lines
Also deleted input-server/input_device.rs (1-line re-export,
superseded by port-input-device).
This commit is contained in:
87
crates/hw-virtio/src/gpu.rs
Normal file
87
crates/hw-virtio/src/gpu.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use crate::mmio::MmioAccess;
|
||||
use crate::queue::{Descriptor, VirtioQueue};
|
||||
|
||||
pub struct GpuDmaAddrs {
|
||||
pub cmd_pa: u64,
|
||||
pub cmd_va: usize,
|
||||
pub resp_pa: u64,
|
||||
}
|
||||
|
||||
pub fn create_2d(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, width: u32, height: u32) {
|
||||
write_cmd_header(dma.cmd_va, 0x0101);
|
||||
unsafe {
|
||||
let p = dma.cmd_va as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, resource_id);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, 1); // B8G8R8A8_UNORM
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, width);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, height);
|
||||
}
|
||||
submit_cmd(mmio, queue, dma, 40);
|
||||
}
|
||||
|
||||
pub fn attach_backing(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, fb_pa: u64, fb_size: u32) {
|
||||
write_cmd_header(dma.cmd_va, 0x0104);
|
||||
unsafe {
|
||||
let p = dma.cmd_va as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, resource_id);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, 1);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u64, fb_pa);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u32, 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: u32, height: u32) {
|
||||
write_cmd_header(dma.cmd_va, 0x0103);
|
||||
unsafe {
|
||||
let p = dma.cmd_va as *mut u8;
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, width);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, height);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u32, scanout_id);
|
||||
core::ptr::write_volatile(p.add(44) as *mut u32, 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) {
|
||||
write_cmd_header(dma.cmd_va, 0x0105);
|
||||
unsafe {
|
||||
let p = dma.cmd_va as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, x);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, y);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, w);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, h);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u64, 0);
|
||||
core::ptr::write_volatile(p.add(48) as *mut u32, 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) {
|
||||
write_cmd_header(dma.cmd_va, 0x0106);
|
||||
unsafe {
|
||||
let p = dma.cmd_va as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, x);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, y);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, w);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, h);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u32, resource_id);
|
||||
}
|
||||
submit_cmd(mmio, queue, dma, 48);
|
||||
}
|
||||
|
||||
fn write_cmd_header(cmd_va: usize, cmd_type: u32) {
|
||||
unsafe {
|
||||
let p = cmd_va as *mut u8;
|
||||
core::ptr::write_bytes(p, 0, 512);
|
||||
core::ptr::write_volatile(p as *mut u32, cmd_type);
|
||||
}
|
||||
}
|
||||
|
||||
fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) {
|
||||
let descs = [
|
||||
Descriptor { addr: dma.cmd_pa, len: cmd_len, writable: false },
|
||||
Descriptor { addr: dma.resp_pa, len: 24, writable: true },
|
||||
];
|
||||
queue.submit(mmio, &descs);
|
||||
}
|
||||
Reference in New Issue
Block a user