diff --git a/crates/adapter-riscv/src/devices/gpu_setup.rs b/crates/adapter-riscv/src/devices/gpu_setup.rs index 63758db..2deb015 100644 --- a/crates/adapter-riscv/src/devices/gpu_setup.rs +++ b/crates/adapter-riscv/src/devices/gpu_setup.rs @@ -13,10 +13,8 @@ const VQUEUE_VA: usize = 0x21000; const CMDBUF_VA: usize = 0x23000; const PHYSINFO_VA: usize = 0x24000; const FB_VA: usize = 0x100000; -const FB_WIDTH: Dimension = Dimension::new(640); -const FB_HEIGHT: Dimension = Dimension::new(480); -const FB_BPP: usize = 4; -const FB_PAGES: usize = (FB_WIDTH.raw() as usize * FB_HEIGHT.raw() as usize * FB_BPP + 4095) / 4096; +const DEFAULT_WIDTH: Dimension = Dimension::new(640); +const DEFAULT_HEIGHT: Dimension = Dimension::new(480); pub fn configure(uart: &Uart, display_pid: ProcessId) { let gpu = match VirtioGpu::probe() { @@ -38,8 +36,36 @@ pub fn configure(uart: &Uart, display_pid: ProcessId) { let cmd_phys = mmu::allocator::alloc_zeroed_page(); map_page(pt, CMDBUF_VA, cmd_phys); - let fb_phys = alloc_contiguous(FB_PAGES); - map_range(pt, FB_VA, fb_phys, FB_PAGES); + gpu.init_device(vq_phys); + + let queue = hw_virtio::queue::VirtioQueue::new( + hw_virtio::queue::QueueAddrs::from_base(vq_phys), + ); + let dma = hw_virtio::gpu::GpuDmaAddrs { + cmd_pa: types::address::PhysicalAddress::from_raw(cmd_phys), + cmd_va: types::address::VirtualAddress::from_raw(cmd_phys), + resp_pa: types::address::PhysicalAddress::from_raw(cmd_phys + 512), + }; + use hw_virtio::mmio::MmioAccess; + + let (width, height) = match hw_virtio::gpu::get_display_info(gpu.mmio(), &queue, &dma) { + Some((w, h)) => { + uart.write_str("k-os: GPU display: "); + uart.write_dec(w as usize); + uart.put_char(b'x'); + uart.write_dec(h as usize); + uart.put_char(b'\n'); + (Dimension::new(w as u16), Dimension::new(h as u16)) + } + None => { + uart.write_str("k-os: GPU display: using default 640x480\n"); + (DEFAULT_WIDTH, DEFAULT_HEIGHT) + } + }; + + let fb_pages = (width.raw() as usize * height.raw() as usize * 4 + 4095) / 4096; + let fb_phys = alloc_contiguous(fb_pages); + map_range(pt, FB_VA, fb_phys, fb_pages); let info_phys = mmu::allocator::alloc_zeroed_page(); map_page(pt, PHYSINFO_VA, info_phys); @@ -48,12 +74,11 @@ pub fn configure(uart: &Uart, display_pid: ProcessId) { core::ptr::write_volatile(info, cmd_phys as u64); core::ptr::write_volatile(info.add(1), (cmd_phys + 512) as u64); core::ptr::write_volatile(info.add(2), fb_phys as u64); - core::ptr::write_volatile(info.add(3), FB_WIDTH.raw() as u64); - core::ptr::write_volatile(info.add(4), FB_HEIGHT.raw() as u64); + core::ptr::write_volatile(info.add(3), width.raw() as u64); + core::ptr::write_volatile(info.add(4), height.raw() as u64); } - gpu.init_device(vq_phys); - if gpu.setup_framebuffer(cmd_phys, vq_phys, fb_phys, FB_WIDTH, FB_HEIGHT) { + if gpu.setup_framebuffer(cmd_phys, vq_phys, fb_phys, width, height) { uart.write_str("k-os: VirtIO GPU configured\n"); } else { uart.write_str("k-os: VirtIO GPU setup failed (display will be headless)\n"); diff --git a/crates/apps/snake/src/main.rs b/crates/apps/snake/src/main.rs index 3f25c3c..b3c2e0f 100644 --- a/crates/apps/snake/src/main.rs +++ b/crates/apps/snake/src/main.rs @@ -14,7 +14,7 @@ use display_server::protocol::DisplayRequest; const INPUT_EP: CapSlot = CapSlot::const_new(0); const DISPLAY_EP: CapSlot = CapSlot::const_new(1); -const TICK_DELAY: u64 = 2_000_000; +const TICK_DELAY: u64 = 5_000_000; const MAX_RENDER_CMDS: usize = 140; fn display_send(req: &DisplayRequest) { @@ -50,20 +50,17 @@ extern "C" fn main() { } flush(); - wait_tick(); - handle_input(&mut snake); - snake.tick(); - if snake.state() == GameState::GameOver { let gw = renderer::grid_pixel_width(); let gh = renderer::grid_pixel_height(); - draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFF800000); + draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFFCC0000); flush(); - - let end = Ticks::from_raw(syscall::get_time().raw() + 50_000_000); - while syscall::get_time().raw() < end.raw() { syscall::yield_now(); } - return; + loop { syscall::yield_now(); } } + + wait_tick(); + handle_input(&mut snake); + snake.tick(); } } diff --git a/crates/hw-virtio/src/gpu.rs b/crates/hw-virtio/src/gpu.rs index 00601c9..1352948 100644 --- a/crates/hw-virtio/src/gpu.rs +++ b/crates/hw-virtio/src/gpu.rs @@ -83,6 +83,24 @@ fn write_cmd_header(cmd_va: VirtualAddress, cmd_type: u32) { } } +pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs) -> Option<(u32, u32)> { + write_cmd_header(dma.cmd_va, 0x0100); + let descs = [ + Descriptor { addr: dma.cmd_pa.raw() as u64, len: 24, writable: false }, + Descriptor { addr: dma.resp_pa.raw() as u64, len: 408, writable: true }, + ]; + if !queue.submit(mmio, &descs) { return None; } + unsafe { + let resp = dma.resp_pa.raw() as usize; + let resp_va = dma.cmd_va.raw() + 512; + let resp_type = core::ptr::read_volatile(resp_va as *const u32); + if resp_type != 0x1101 { return None; } + let w = core::ptr::read_volatile((resp_va + 24 + 8) as *const u32); + let h = core::ptr::read_volatile((resp_va + 24 + 12) as *const u32); + if w > 0 && h > 0 { Some((w, h)) } else { None } + } +} + fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) -> bool { let descs = [ Descriptor { addr: dma.cmd_pa.raw() as u64, len: cmd_len, writable: false },