feat: devices via caps (BootInfo, init assigns devices, drivers map MMIO/DMA themselves, IRQ-driven input); drop boot device wiring and info pages; headless display fallback
This commit is contained in:
@@ -15,5 +15,4 @@ libkos = { workspace = true }
|
||||
server-framework = { workspace = true }
|
||||
display-server = { workspace = true }
|
||||
driver-framebuffer-virtio = { workspace = true }
|
||||
driver-framebuffer-mock = { workspace = true }
|
||||
port-framebuffer = { workspace = true }
|
||||
|
||||
@@ -8,12 +8,13 @@ use types::bounded::CapSlot;
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main() {
|
||||
let ep = CapSlot::const_new(0);
|
||||
|
||||
if let Some(fb) = driver_framebuffer_virtio::VirtioFramebuffer::try_new() {
|
||||
// Init hands over the GPU, or nothing if the machine has none.
|
||||
let dev = libkos::device::receive_device(ep);
|
||||
if let Some(fb) = dev.mmio.and_then(driver_framebuffer_virtio::VirtioFramebuffer::try_new) {
|
||||
run_virtio(fb, ep);
|
||||
} else {
|
||||
run_mock(ep);
|
||||
}
|
||||
libkos::println!("display: no GPU, running headless");
|
||||
run_headless(ep);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
@@ -25,12 +26,33 @@ fn run_virtio(mut fb: driver_framebuffer_virtio::VirtioFramebuffer, ep: CapSlot)
|
||||
server_framework::serve(&mut srv, ep)
|
||||
}
|
||||
|
||||
/// No GPU: clients still get answers (and the dimensions they draw for);
|
||||
/// pixels go nowhere.
|
||||
struct Headless;
|
||||
|
||||
impl port_framebuffer::Framebuffer for Headless {
|
||||
fn width(&self) -> types::display::Dimension {
|
||||
types::display::Dimension::new(640)
|
||||
}
|
||||
fn height(&self) -> types::display::Dimension {
|
||||
types::display::Dimension::new(480)
|
||||
}
|
||||
fn write_pixel(&mut self, _: types::display::ScreenCoord, _: types::display::ScreenCoord, _: types::display::Color) {}
|
||||
fn fill_rect(
|
||||
&mut self,
|
||||
_: types::display::ScreenCoord,
|
||||
_: types::display::ScreenCoord,
|
||||
_: types::display::Dimension,
|
||||
_: types::display::Dimension,
|
||||
_: types::display::Color,
|
||||
) {
|
||||
}
|
||||
fn clear(&mut self, _: types::display::Color) {}
|
||||
fn flush(&mut self) {}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn run_mock(ep: CapSlot) -> ! {
|
||||
let fb = driver_framebuffer_mock::MockFramebuffer::new(
|
||||
types::display::Dimension::new(640),
|
||||
types::display::Dimension::new(480),
|
||||
);
|
||||
let mut srv = display_server::server::DisplayServer::new(fb);
|
||||
fn run_headless(ep: CapSlot) -> ! {
|
||||
let mut srv = display_server::server::DisplayServer::new(Headless);
|
||||
server_framework::serve(&mut srv, ep)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ test = false
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
port-input-device = { workspace = true }
|
||||
types = { workspace = true }
|
||||
libkos = { workspace = true }
|
||||
|
||||
|
||||
@@ -3,28 +3,38 @@
|
||||
|
||||
extern crate libkos;
|
||||
|
||||
use libkos::device::{self, KIND_UART_16550, KIND_VIRTIO};
|
||||
use port_input_device::InputDevice;
|
||||
use types::bounded::CapSlot;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn main() {
|
||||
let ep = CapSlot::new(0).unwrap();
|
||||
|
||||
if let Some(dev) = driver_input_virtio::VirtioInputDevice::try_new() {
|
||||
run_input(dev, ep);
|
||||
} else {
|
||||
run_uart(ep);
|
||||
// Init hands over the keyboard (virtio) or, failing that, the UART.
|
||||
let dev = device::receive_device(ep);
|
||||
match (dev.kind, dev.mmio) {
|
||||
(KIND_VIRTIO, Some(mmio)) => {
|
||||
if let Some(d) = driver_input_virtio::VirtioInputDevice::try_new(mmio) {
|
||||
run(d, dev.irq, ep);
|
||||
}
|
||||
}
|
||||
(KIND_UART_16550, Some(mmio)) => {
|
||||
if let Some(d) = driver_input_uart::UartInputDevice::new(mmio) {
|
||||
run(d, dev.irq, ep);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
libkos::println!("input: no usable input device, exiting");
|
||||
libkos::syscall::exit();
|
||||
}
|
||||
|
||||
/// Serves `device`, woken by its interrupt when it has one.
|
||||
#[inline(never)]
|
||||
fn run_input(device: driver_input_virtio::VirtioInputDevice, ep: CapSlot) -> ! {
|
||||
let mut srv = input_server::server::InputServer::new(device);
|
||||
server_framework::serve(&mut srv, ep)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn run_uart(ep: CapSlot) -> ! {
|
||||
let device = driver_input_uart::UartInputDevice::new();
|
||||
let mut srv = input_server::server::InputServer::new(device);
|
||||
fn run<D: InputDevice>(device: D, irq: Option<CapSlot>, ep: CapSlot) -> ! {
|
||||
let mut srv = match irq.filter(|irq| device::bind_irq(*irq).is_ok()) {
|
||||
Some(irq) => input_server::server::InputServer::with_irq(device, irq),
|
||||
None => input_server::server::InputServer::new(device),
|
||||
};
|
||||
server_framework::serve(&mut srv, ep)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user