From b3af2a79672ec3050d350226d56147aa71c80b0e Mon Sep 17 00:00:00 2001 From: husky Date: Thu, 11 Sep 2025 16:28:11 -0700 Subject: [PATCH] working again --- src/arch/virt/asm/linker.ld | 4 ++ src/dev/framebuffer/console.rs | 1 - src/dev/framebuffer/mod.rs | 81 +++++++++++++++++++--------------- src/dev/mod.rs | 20 ++++----- src/dev/virtio/gpu.rs | 43 +++++++++++------- src/dev/virtio/mod.rs | 16 ++++--- src/memory.rs | 2 +- src/trafficcontrol.rs | 16 +++---- 8 files changed, 105 insertions(+), 78 deletions(-) diff --git a/src/arch/virt/asm/linker.ld b/src/arch/virt/asm/linker.ld index 5ac0cc5..31029b4 100644 --- a/src/arch/virt/asm/linker.ld +++ b/src/arch/virt/asm/linker.ld @@ -9,6 +9,8 @@ MEMORY ram (wxa) : ORIGIN = 0x80010000, LENGTH = 0x10000 virtqueues (wxa) : ORIGIN = 0x80020000, LENGTH = 0x20000 + + framebuffer (wxa) : ORIGIN = 0x80040000, LENGTH = 320 * 240 * 4 } PHDRS @@ -61,4 +63,6 @@ SECTIONS { PROVIDE(_virtio_queue_1_end = _virtio_queue_1_start + 0x10000); PROVIDE(_virtio_queue_2_start = _virtio_queue_1_end); PROVIDE(_virtio_queue_2_end = _virtio_queue_2_start + 0x10000); + + PROVIDE(_framebuffer_start = ORIGIN(framebuffer)); } \ No newline at end of file diff --git a/src/dev/framebuffer/console.rs b/src/dev/framebuffer/console.rs index bd98b90..d9d0120 100644 --- a/src/dev/framebuffer/console.rs +++ b/src/dev/framebuffer/console.rs @@ -37,7 +37,6 @@ impl FramebufferConsole { // DOES send a framebuffer update! pub fn printstr(&mut self, tc: &mut TrafficControl, str: &str) { - return; for c in str.chars() { let mut was_special_char = false; if c == '\n' || c == '\r' { diff --git a/src/dev/framebuffer/mod.rs b/src/dev/framebuffer/mod.rs index 2e99749..d651117 100644 --- a/src/dev/framebuffer/mod.rs +++ b/src/dev/framebuffer/mod.rs @@ -1,4 +1,5 @@ -use crate::dev::{linebuffer_push, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_WIDTH, LINEBUFFER_ADDR, LINEBUFFER_BPP}; +use crate::dev::virtio::framebuffer_update; +use crate::dev::{FRAMEBUFFER_ADDR, FRAMEBUFFER_BPP, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_WIDTH}; use crate::trafficcontrol::TrafficControl; use core::sync::atomic::Ordering; @@ -33,63 +34,73 @@ impl FBColor { } } -pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, mut y: usize, chars: &[char]) { +pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, y: usize, chars: &[char]) { + let ogx = x; + let ogy = y; const BYTES: [u8; 3] = FB_FG_COLOR.to_bytes(); - let fbaddr = LINEBUFFER_ADDR.load(Ordering::Relaxed); + let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed); if fbaddr == 0 { return; } + let fbstride = FRAMEBUFFER_BPP.load(Ordering::Relaxed) * FRAMEBUFFER_WIDTH; const CHAR_SIZE: usize = 16; - let mut drew_anything = false; - for line in 0..FRAMEBUFFER_HEIGHT { - for c in chars { - let c = *c; - if c == ' ' { - x += CHAR_SIZE; - } else if c as u8 > 32 { - let c = c as u8 - 32; - let cx = (c % 16) as usize * CHAR_SIZE; - let cy = (c / 16) as usize * CHAR_SIZE; - for row in 0..CHAR_SIZE { - if (y+row) != line { - continue; - } - for col in 0..CHAR_SIZE { - let coff = (VAPFONT_W * (cy + row)) + (cx + col); - let draw = VAPFONT[coff / 8] & (0x80 >> (coff % 8)); - if draw != 0 { - unsafe { - //let fb = (fbaddr as *mut u8).add(((y + row) * fbstride) + ((x + col) * 4)) as *mut u32; - let fb = (fbaddr as *mut u8).add((x + col) * 4) as *mut u32; - fb.write_volatile(u32::from_ne_bytes([0, BYTES[0], BYTES[1], BYTES[2]])); - drew_anything = true; - } + for c in chars { + let c = *c; + if c == ' ' { + x += CHAR_SIZE; + } else if c as u8 > 32 { + let c = c as u8 - 32; + let cx = (c % 16) as usize * CHAR_SIZE; + let cy = (c / 16) as usize * CHAR_SIZE; + for row in 0..CHAR_SIZE { + for col in 0..CHAR_SIZE { + let coff = (VAPFONT_W * (cy + row)) + (cx + col); + let draw = VAPFONT[coff / 8] & (0x80 >> (coff % 8)); + if draw != 0 { + unsafe { + let fb = (fbaddr as *mut u8) + .add(((y + row) * fbstride) + ((x + col) * 4)) + as *mut u32; + fb.write_volatile(u32::from_ne_bytes([ + 0, BYTES[0], BYTES[1], BYTES[2], + ])); } } } - x += CHAR_SIZE; } - } - if drew_anything { - linebuffer_push(tc, line as u32); + x += CHAR_SIZE; } } + + framebuffer_update( + tc, + 0, + 0, + FRAMEBUFFER_WIDTH as u32, + FRAMEBUFFER_HEIGHT as u32, + ); } pub fn fb_clearscreen(tc: &mut TrafficControl) { const BYTES: [u8; 3] = FB_BG_COLOR.to_bytes(); - let fbaddr = LINEBUFFER_ADDR.load(Ordering::Relaxed); + let fbaddr = FRAMEBUFFER_ADDR.load(Ordering::Relaxed); if fbaddr == 0 { return; } + let fbstride = FRAMEBUFFER_BPP.load(Ordering::Relaxed) * FRAMEBUFFER_WIDTH; for y in 0..FRAMEBUFFER_HEIGHT { for x in 0..FRAMEBUFFER_WIDTH { unsafe { - //let fb = (fbaddr as *mut u8).add(((y)*fbstride) + ((x)*4)) as *mut u32; - let fb = (fbaddr as *mut u8).add(x*4) as *mut u32; + let fb = (fbaddr as *mut u8).add(((y) * fbstride) + ((x) * 4)) as *mut u32; fb.write_volatile(u32::from_ne_bytes([0, BYTES[0], BYTES[1], BYTES[2]])); } } - linebuffer_push(tc, y as u32); } + framebuffer_update( + tc, + 0, + 0, + FRAMEBUFFER_WIDTH as u32, + FRAMEBUFFER_HEIGHT as u32, + ); } diff --git a/src/dev/mod.rs b/src/dev/mod.rs index 2e1bd7a..1f84f0d 100644 --- a/src/dev/mod.rs +++ b/src/dev/mod.rs @@ -8,10 +8,10 @@ pub const LINEBUFFER_BLOCKS: usize = 3; pub const LINEBUFFER_HEIGHT: usize = 1; // NOTE: -// LINEBUFFER_ADDR should always be 0 if no framebuffer exists -// if LINEBUFFER_ADDR is NOT 0, then LINEBUFFER_BPP should also be NOT 0 -pub static LINEBUFFER_ADDR: AtomicUsize = AtomicUsize::new(0); -pub static LINEBUFFER_BPP: AtomicUsize = AtomicUsize::new(0); +// FRAMEBUFFER_ADDR should always be 0 if no framebuffer exists +// if FRAMEBUFFER_ADDR is NOT 0, then FRAMEBUFFER_BPP should also be NOT 0 +pub static FRAMEBUFFER_ADDR: AtomicUsize = AtomicUsize::new(0); +pub static FRAMEBUFFER_BPP: AtomicUsize = AtomicUsize::new(0); #[cfg(feature = "dev_virtio")] pub mod virtio; @@ -29,16 +29,16 @@ pub fn read_sector(tc: &mut TrafficControl, buffer: usize, size: u32, sector: u6 false } -pub fn linebuffer_address() -> usize { - LINEBUFFER_ADDR.load(Ordering::Relaxed) +pub fn framebuffer_address() -> usize { + FRAMEBUFFER_ADDR.load(Ordering::Relaxed) } -pub fn linebuffer_bpp() -> usize { - LINEBUFFER_BPP.load(Ordering::Relaxed) +pub fn framebuffer_bpp() -> usize { + FRAMEBUFFER_BPP.load(Ordering::Relaxed) } -pub fn linebuffer_push(tc: &mut TrafficControl, line: u32) { +pub fn framebuffer_push(tc: &mut TrafficControl, x: u32, y: u32, w: u32, h: u32) { #[cfg(feature = "dev_virtio")] - virtio::framebuffer_update(tc, line); + virtio::framebuffer_update(tc, x, y, w, h); } \ No newline at end of file diff --git a/src/dev/virtio/gpu.rs b/src/dev/virtio/gpu.rs index ec68811..80f41cc 100644 --- a/src/dev/virtio/gpu.rs +++ b/src/dev/virtio/gpu.rs @@ -6,6 +6,7 @@ use crate::trafficcontrol::TrafficControl; unsafe extern "C" { fn _virtio_queue_2_start(); + fn _framebuffer_start(); } pub const VIRTIO_GPU_CMD_GET_DISPLAY_INFO: u32 = 0x0100; @@ -180,8 +181,8 @@ impl VirtIoGpuDevice { } - // allocate memory for linebuffer - let linebuffer_ptr = unsafe { tc.memory_manager.as_mut().unwrap_unchecked().alloc_n_blocks(LINEBUFFER_BLOCKS) }; + // allocate memory for framebuffer + let framebuffer_ptr = _framebuffer_start as usize; let latest_response = heap_allocate_type::(tc) as *const _ as usize; @@ -191,7 +192,7 @@ impl VirtIoGpuDevice { queue: queue_ptr, idx: 0, ack_used_idx: 0, - framebuffer: linebuffer_ptr as usize, + framebuffer: framebuffer_ptr, width: FRAMEBUFFER_WIDTH, height: FRAMEBUFFER_HEIGHT, }; @@ -252,7 +253,7 @@ impl VirtIoGpuDevice { free_me[1] = unsafe { &(*cmd) as *const _ as usize }; let mem_entry = heap_allocate_type::(tc); mem_entry.addr = gpu.framebuffer as u64; - mem_entry.length = (gpu.width * 4) as u32; + mem_entry.length = (gpu.height * gpu.width * 4) as u32; mem_entry.padding = 0; free_me[2] = unsafe { &(*mem_entry) as *const _ as usize }; @@ -319,7 +320,7 @@ impl VirtIoGpuDevice { } { } - //gpu.pending(tc); + gpu.pending(tc); for free in free_me { unsafe { @@ -408,8 +409,8 @@ impl VirtIoGpuDevice { } } - pub fn transfer(&mut self, tc: &mut TrafficControl, y: u32) { - let mut free_me = [0; 4]; + pub fn transfer(&mut self, tc: &mut TrafficControl, x: u32, y: u32, w: u32, h: u32) { + let mut free_me = [0; 2]; let cmd = heap_allocate_type::(tc); cmd.header.ctrl_type = VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D; @@ -418,14 +419,14 @@ impl VirtIoGpuDevice { cmd.header.ctx_id = 0; cmd.header.ring_idx = 0; cmd.header.padding = [0; 3]; - cmd.rect.x = 0; + cmd.rect.x = x; cmd.rect.y = y; - cmd.rect.width = self.width as u32; - cmd.rect.height = 1; + cmd.rect.width = w; + cmd.rect.height = h; cmd.offset = 0; cmd.resource_id = 1; cmd.padding = 0; - free_me[1] = unsafe { &(*cmd) as *const _ as usize }; + free_me[0] = unsafe { &(*cmd) as *const _ as usize }; let desc_rq = Descriptor { addr: unsafe { &(*cmd) as *const _ as u64 }, @@ -451,13 +452,13 @@ impl VirtIoGpuDevice { cmd.header.ctx_id = 0; cmd.header.ring_idx = 0; cmd.header.padding = [0; 3]; - cmd.rect.x = 0; + cmd.rect.x = x; cmd.rect.y = y; - cmd.rect.width = self.width as u32; - cmd.rect.height = 1; + cmd.rect.width = w; + cmd.rect.height = h; cmd.resource_id = 1; cmd.padding = 0; - free_me[2] = unsafe { &(*cmd) as *const _ as usize }; + free_me[1] = unsafe { &(*cmd) as *const _ as usize }; let desc_rq = Descriptor { addr: unsafe { &(*cmd) as *const _ as u64 }, @@ -473,7 +474,17 @@ impl VirtIoGpuDevice { }; self.send_rq_rsp(desc_rq, desc_resp); - for free in free_me.into_iter().skip(1) { + + // hack to make sure the queue doesn't get overloaded + while { + let queue = unsafe { (self.queue as *mut VirtQueue).read_volatile() }; + self.ack_used_idx == queue.used.idx + } { + + } + self.pending(tc); + + for free in free_me.into_iter() { unsafe { tc.memory_manager.as_mut().unwrap_unchecked().free_n_blocks(free, 1); } diff --git a/src/dev/virtio/mod.rs b/src/dev/virtio/mod.rs index ed95305..a838e87 100644 --- a/src/dev/virtio/mod.rs +++ b/src/dev/virtio/mod.rs @@ -2,9 +2,10 @@ //! WARNING: virtio is currently completely broken! don't use it! use core::sync::atomic::Ordering; -use crate::dev::{LINEBUFFER_ADDR, LINEBUFFER_BPP}; +use crate::dev::{FRAMEBUFFER_ADDR, FRAMEBUFFER_BPP}; use crate::dev::virtio::block::{VirtIoBlockDevice, VirtIoBlockDeviceError}; use crate::dev::virtio::gpu::{VirtIoGpuDevice, VirtIoGpuDeviceError}; +use crate::rough_panic; use crate::spinlock::Spinlock; use crate::strprint::twodigit; use crate::trafficcontrol::{TrafficControl}; @@ -83,6 +84,9 @@ pub struct VirtQueue { pub fn heap_allocate_type(tc: &mut TrafficControl) -> &'static mut T { let num_blocks = size_of::().div_ceil(512); + if num_blocks != 1 { + rough_panic(['f', 'm', 'l']); + } let addr = unsafe { tc.memory_manager.as_mut().unwrap_unchecked().alloc_n_blocks(num_blocks) }; unsafe { &mut (*(addr as *mut T)) } } @@ -130,12 +134,11 @@ pub fn probe_virtio_devices(tc: &mut TrafficControl) { } } 16 => { - continue; // gpu device let gpu_device = VirtIoGpuDevice::new_and_init(tc, addr); if let Ok(gpu_device) = gpu_device { - LINEBUFFER_ADDR.store(gpu_device.framebuffer, Ordering::Relaxed); - LINEBUFFER_BPP.store(4, Ordering::Relaxed); // virtio always uses 4 byte stride + FRAMEBUFFER_ADDR.store(gpu_device.framebuffer, Ordering::Relaxed); + FRAMEBUFFER_BPP.store(4, Ordering::Relaxed); // virtio always uses 4 byte stride devices[i] = Some(VirtIoDevice::GPUDevice(gpu_device)); *VIRTIO_GPU_DEVICE.lock() = Some(i as u8); if let Some(serial_port) = &serial_port { @@ -231,8 +234,7 @@ pub fn read_sector(tc: &mut TrafficControl, buffer: usize, size: u32, sector: u6 false } -pub fn framebuffer_update(tc: &mut TrafficControl, y: u32) -> bool { - return true; +pub fn framebuffer_update(tc: &mut TrafficControl, x: u32, y: u32, w: u32, h: u32) -> bool { let idx = { let lock = VIRTIO_GPU_DEVICE.lock(); *lock @@ -242,7 +244,7 @@ pub fn framebuffer_update(tc: &mut TrafficControl, y: u32) -> bool { if let Some(device) = devices[idx as usize].as_mut() { return match device { VirtIoDevice::GPUDevice(device) => { - device.transfer(tc, y); + device.transfer(tc, x, y, w, h); true } _ => { diff --git a/src/memory.rs b/src/memory.rs index 4c6a1e3..8a29588 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -121,7 +121,7 @@ impl MemoryManager { } pub fn free_n_blocks(&mut self, addr: usize, n: usize) { - if n == 0 || addr >= self.heap_start + self.heap_size || addr + n * BLOCK_SIZE > self.heap_start + self.heap_size { + if n == 0 || addr < self.heap_start || addr >= self.heap_start + self.heap_size || addr + n * BLOCK_SIZE > self.heap_start + self.heap_size { rough_panic(['b', 'm', 'f']) } for i in 0..n { diff --git a/src/trafficcontrol.rs b/src/trafficcontrol.rs index 0a3a8a7..c38c386 100644 --- a/src/trafficcontrol.rs +++ b/src/trafficcontrol.rs @@ -243,7 +243,7 @@ pub fn handle_syscall( } } crate::dev::probe_devices(&mut tc); - if crate::dev::LINEBUFFER_ADDR.load(Ordering::Relaxed) != 0 { + if crate::dev::FRAMEBUFFER_ADDR.load(Ordering::Relaxed) != 0 { tc.use_fb_console = true; { let uart = serial_port(); @@ -351,7 +351,7 @@ pub fn handle_syscall( 0 } SysCall::EnableFramebufferConsole => { - if crate::dev::LINEBUFFER_ADDR.load(Ordering::Relaxed) != 0 { + if crate::dev::FRAMEBUFFER_ADDR.load(Ordering::Relaxed) != 0 { tc.use_fb_console = true; // clear the screen let mut fbcons = crate::dev::framebuffer::console::FBCONSOLE.lock(); @@ -361,14 +361,14 @@ pub fn handle_syscall( 0 } SysCall::FramebufferPointer => { - crate::dev::LINEBUFFER_ADDR.load(Ordering::Relaxed) + crate::dev::FRAMEBUFFER_ADDR.load(Ordering::Relaxed) } SysCall::FlushFramebufferRect => { - let x = a1; - let y = a2; - let w = a3; - let h = a4; - crate::dev::linebuffer_push(&mut tc, y as u32); + let x = a1 as u32; + let y = a2 as u32; + let w = a3 as u32; + let h = a4 as u32; + crate::dev::framebuffer_push(&mut tc, x, y, w, h); 0 } },