working again

This commit is contained in:
husky 2025-09-11 16:28:11 -07:00
parent f13cb2eb12
commit b3af2a7967
8 changed files with 105 additions and 78 deletions

View file

@ -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));
}

View file

@ -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' {

View file

@ -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,15 +34,16 @@ 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 == ' ' {
@ -51,18 +53,17 @@ pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, mut y: usize,
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;
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],
]));
}
}
}
@ -70,26 +71,36 @@ pub fn fb_write_char_array(tc: &mut TrafficControl, mut x: usize, mut y: usize,
x += CHAR_SIZE;
}
}
if drew_anything {
linebuffer_push(tc, line as u32);
}
}
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,
);
}

View file

@ -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);
}

View file

@ -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::<CtrlHeader>(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::<GPUMemEntry>(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::<TransferToHost2D>(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);
}

View file

@ -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<T: Sized>(tc: &mut TrafficControl) -> &'static mut T {
let num_blocks = size_of::<T>().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
}
_ => {

View file

@ -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 {

View file

@ -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
}
},