dev: pass DeviceInitContext into Device::init()

This commit is contained in:
Mark Poliakov 2025-02-06 12:24:03 +02:00
parent 7348232aa9
commit 8cbde8389f
24 changed files with 122 additions and 75 deletions

View File

@ -8,7 +8,7 @@ use alloc::{format, sync::Arc, vec::Vec};
use bytemuck::Zeroable;
use data::ReceivedFis;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{InterruptAffinity, InterruptHandler, IrqVector},
};
use error::AhciError;
@ -181,7 +181,9 @@ impl InterruptHandler for AhciController {
}
impl Device for AhciController {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
// Do the init in background
runtime::spawn(self.late_init())?;
Ok(())

View File

@ -15,7 +15,7 @@ use core::{
use alloc::{collections::BTreeMap, format, sync::Arc, vec::Vec};
use command::{IdentifyActiveNamespaceIdListRequest, IdentifyControllerRequest};
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{InterruptAffinity, InterruptHandler, IrqVector},
};
use drive::NvmeNamespace;
@ -345,7 +345,10 @@ impl InterruptHandler for NvmeController {
}
impl Device for NvmeController {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
let regs = self.regs.lock();
let timeout = Duration::from_millis(regs.CAP.read(CAP::TO) * 500);

View File

@ -13,8 +13,12 @@ use alloc::{format, sync::Arc, vec::Vec};
use bitflags::bitflags;
use device::{PciBusDevice, PciDeviceInfo};
use device_api::device::DeviceInitContext;
use interrupt::{PciInterruptMap, PciMsiMap};
use libk::fs::sysfs::{self, object::KObject};
use libk::{
dma::DummyDmaAllocator,
fs::sysfs::{self, object::KObject},
};
use libk_mm::address::PhysicalAddress;
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
use space::legacy;
@ -614,8 +618,11 @@ fn setup_bus_device(device: &mut PciBusDevice) -> Result<(), Error> {
if let Some(driver) = driver::lookup_driver(&device.info) {
log::info!("{} -> {}", device.info.address, driver.driver_name());
let instance = driver.probe(&device.info)?;
let cx = DeviceInitContext {
dma_allocator: Arc::new(DummyDmaAllocator),
};
unsafe { instance.clone().init() }?;
unsafe { instance.clone().init(cx) }?;
device.device.replace(instance);
device.driver_name.replace(driver.driver_name());

View File

@ -2,7 +2,7 @@ use core::mem::MaybeUninit;
use alloc::sync::Arc;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqVector},
};
use libk::error::Error;
@ -342,7 +342,10 @@ impl InterruptHandler for Rtl8139 {
}
impl Device for Rtl8139 {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
log::info!("Initialize rtl8139 driver");
log::info!("MAC: {}", self.mac);

View File

@ -5,7 +5,7 @@ use core::{
use alloc::{sync::Arc, vec::Vec};
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqVector},
};
use libk::error::Error;
@ -592,7 +592,9 @@ impl InterruptHandler for Rtl8168 {
}
impl Device for Rtl8168 {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
log::info!("Initialize rtl8168");
log::info!("MAC: {}", self.mac);

View File

@ -3,7 +3,7 @@ use core::sync::atomic::{AtomicU8, Ordering};
use alloc::{boxed::Box, collections::btree_map::BTreeMap, sync::Arc, vec::Vec};
use async_trait::async_trait;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{InterruptHandler, IrqVector},
};
use libk::{error::Error, task::runtime};
@ -443,7 +443,10 @@ impl CommandExecutor for Xhci {
}
impl Device for Xhci {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
self.regs.hc_reset(10000000)?;
log::info!("xHC reset complete");

View File

@ -6,7 +6,7 @@ use core::mem::MaybeUninit;
use alloc::{sync::Arc, vec::Vec};
use command::{ControlLock, ScanoutInfo};
use device_api::device::Device;
use device_api::device::{Device, DeviceInitContext};
use libk::device::{
display::{
DisplayDevice, DisplayMode, DisplayOwner, DriverFlags, FramebufferInfo, PixelFormat,
@ -253,7 +253,9 @@ impl<T: Transport + 'static> VirtioGpu<T> {
}
impl<T: Transport + 'static> Device for VirtioGpu<T> {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
let status = self.begin_init()?;
self.setup_queues()?;
self.finish_init(status);

View File

@ -8,7 +8,7 @@ use core::mem::size_of;
use alloc::{collections::BTreeMap, sync::Arc};
use bytemuck::{Pod, Zeroable};
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{InterruptAffinity, InterruptHandler, IrqVector},
};
use libk_mm::PageBox;
@ -253,7 +253,9 @@ impl<T: Transport + 'static> Device for VirtioNet<T> {
"VirtIO Network Device"
}
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
// TODO use DmaAllocator instead of PageBox
let _ = cx;
let status = self.begin_init()?;
// TODO multiqueue

View File

@ -1,7 +1,11 @@
use alloc::sync::Arc;
use yggdrasil_abi::error::Error;
use crate::{bus::Bus, clock::ClockController};
use crate::{bus::Bus, clock::ClockController, dma::DmaAllocator};
pub struct DeviceInitContext {
pub dma_allocator: Arc<dyn DmaAllocator>,
}
pub trait Device: Sync + Send {
fn display_name(&self) -> &str;
@ -13,7 +17,8 @@ pub trait Device: Sync + Send {
/// # Safety
///
/// The caller must make sure the function is only called once.
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, cx: DeviceInitContext) -> Result<(), Error> {
let _ = cx;
Ok(())
}

View File

@ -0,0 +1 @@
pub trait DmaAllocator {}

View File

@ -11,6 +11,8 @@ pub mod interrupt;
pub mod serial;
pub mod timer;
pub mod dma;
use device::Device;
use yggdrasil_abi::error::Error;

View File

@ -8,10 +8,11 @@ use alloc::{
use device_api::{
bus::Bus,
clock::ClockController,
device::Device,
device::{Device, DeviceInitContext},
interrupt::{ExternalInterruptController, FullIrq, MessageInterruptController},
};
use fdt_rs::spec::Phandle;
use libk::dma::DummyDmaAllocator;
use libk_mm::address::PhysicalAddress;
use libk_util::OneTimeInit;
use yggdrasil_abi::error::Error;
@ -188,7 +189,8 @@ impl Node {
pub fn lazy_init(self: Arc<Self>) -> Option<Result<(), Error>> {
let device = self.clone().probe()?;
let result = self.init_token.or_try_init_with(|| {
unsafe { device.init() }?;
let cx = self.make_init_context();
unsafe { device.init(cx) }?;
Ok(())
});
match result {
@ -233,12 +235,21 @@ impl Node {
.inspect_err(|_| log::error!("Does not exist: probe({:?})", self.name))?;
self.init_token.try_init_with_opt(|| {
unsafe { device.init() }?;
let cx = self.make_init_context();
unsafe { device.init(cx) }?;
Ok(())
})?;
Ok(())
}
fn make_init_context(&self) -> DeviceInitContext {
let cx = DeviceInitContext {
dma_allocator: Arc::new(DummyDmaAllocator),
};
cx
}
/// Returns an iterator over the node's children
pub fn children(&self) -> impl Iterator<Item = &Arc<Node>> {
self.children.get().iter()

View File

@ -49,18 +49,6 @@ impl PageProvider for Partition {
}
impl Device for Partition {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
todo!()
}
unsafe fn deinit(&self) -> Result<(), Error> {
todo!()
}
unsafe fn init_irq(self: Arc<Self>) -> Result<(), Error> {
todo!()
}
fn display_name(&self) -> &str {
"Partition"
}

View File

@ -162,36 +162,36 @@ impl DeviceRegistry {
});
}
pub fn run_initialization(&self) {
let mut devices = self.pending_initialization.write();
// pub fn run_initialization(&self) {
// let mut devices = self.pending_initialization.write();
for pending in devices.iter_mut() {
if pending.irq_only {
continue;
}
// for pending in devices.iter_mut() {
// if pending.irq_only {
// continue;
// }
log::debug!("Init device: {:?}", pending.device.display_name());
if let Err(error) = unsafe { pending.device.clone().init() } {
log::error!("{:?} init error: {error:?}", pending.device.display_name());
pending.failed = true;
continue;
}
}
// log::debug!("Init device: {:?}", pending.device.display_name());
// if let Err(error) = unsafe { pending.device.clone().init() } {
// log::error!("{:?} init error: {error:?}", pending.device.display_name());
// pending.failed = true;
// continue;
// }
// }
for pending in devices.drain(..) {
if pending.failed {
continue;
}
// for pending in devices.drain(..) {
// if pending.failed {
// continue;
// }
log::debug!("Init IRQ: {:?}", pending.device.display_name());
if let Err(error) = unsafe { pending.device.clone().init_irq() } {
log::error!(
"{:?} IRQ init error: {error:?}",
pending.device.display_name()
);
}
}
}
// log::debug!("Init IRQ: {:?}", pending.device.display_name());
// if let Err(error) = unsafe { pending.device.clone().init_irq() } {
// log::error!(
// "{:?} IRQ init error: {error:?}",
// pending.device.display_name()
// );
// }
// }
// }
}
async fn probe_partition_table(

5
kernel/libk/src/dma.rs Normal file
View File

@ -0,0 +1,5 @@
use device_api::dma::DmaAllocator;
pub struct DummyDmaAllocator;
impl DmaAllocator for DummyDmaAllocator {}

View File

@ -44,6 +44,8 @@ pub mod random;
pub mod time;
pub mod vfs;
pub mod dma;
#[cfg(any(target_os = "none", rust_analyzer))]
pub mod panic;

View File

@ -4,7 +4,7 @@ use core::{mem::offset_of, ops::Range};
use abi::error::Error;
use alloc::{sync::Arc, vec::Vec};
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{
ExternalInterruptController, InterruptAffinity, InterruptHandler, Irq, IrqLevel,
IrqOptions, IrqTrigger, IrqVector, MessageInterruptController, MsiInfo,
@ -83,7 +83,7 @@ pub struct Gicv2m {
}
impl Device for Gicv2m {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
let regs = self.regs.lock();
log::info!("gicv2m: init @ {:#x}", self.base);

View File

@ -6,7 +6,7 @@ use aarch64_cpu::asm::barrier;
use abi::error::Error;
use alloc::sync::Arc;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{
ExternalInterruptController, FixedInterruptTable, FullIrq, InterruptHandler,
InterruptTable, IpiDeliveryTarget, IpiMessage, Irq, IrqLevel, IrqOptions, IrqTrigger,
@ -58,7 +58,7 @@ impl Device for Gic {
"ARM Generic Interrupt Controller v2"
}
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
log::debug!(
"Init GIC: gicd={:#x}, gicc={:#x}",
self.gicd_base,

View File

@ -6,7 +6,7 @@ use aarch64_cpu::registers::{CNTFRQ_EL0, CNTPCT_EL0, CNTP_CTL_EL0, CNTP_TVAL_EL0
use abi::{error::Error, time::NANOSECONDS_IN_SECOND};
use alloc::sync::Arc;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
@ -55,7 +55,7 @@ impl Device for ArmTimer {
"ARM Generic Timer"
}
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
Ok(())
}

View File

@ -7,7 +7,10 @@ use core::ops::Range;
use abi::error::Error;
use alloc::{sync::Arc, vec::Vec};
use device_api::{bus::Bus, device::Device};
use device_api::{
bus::Bus,
device::{Device, DeviceInitContext},
};
use device_tree::{
driver::{device_tree_driver, Node, ProbeContext},
DeviceTreePropertyRead,
@ -18,7 +21,7 @@ struct SimpleBus {
}
impl Device for SimpleBus {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
Ok(())
}

View File

@ -2,7 +2,10 @@
use aarch64_cpu::registers::ReadWriteable;
use abi::error::Error;
use alloc::sync::Arc;
use device_api::{clock::ClockController, device::Device};
use device_api::{
clock::ClockController,
device::{Device, DeviceInitContext},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo};
use libk_util::{sync::IrqSafeSpinlock, OneTimeInit};
@ -52,7 +55,7 @@ impl ClockController for Bcm2835Aux {
}
impl Device for Bcm2835Aux {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
let regs = DeviceMemoryIo::map(self.base, Default::default())?;
self.regs.init(IrqSafeSpinlock::new(regs));
Ok(())

View File

@ -2,7 +2,10 @@
use abi::error::Error;
use alloc::sync::Arc;
use device_api::{device::Device, CpuBringupDevice, ResetDevice};
use device_api::{
device::{Device, DeviceInitContext},
CpuBringupDevice, ResetDevice,
};
use device_tree::{
driver::{device_tree_driver, Node, ProbeContext},
DeviceTreePropertyRead,
@ -31,7 +34,7 @@ impl Device for Psci {
"ARM PSCI"
}
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
PLATFORM.psci.init(self.clone());
Ok(())
}

View File

@ -8,7 +8,7 @@ use abi::{
};
use alloc::sync::Arc;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::{
@ -148,7 +148,7 @@ impl InterruptHandler for Bcm2835AuxUart {
}
impl Device for Bcm2835AuxUart {
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
// TODO initialize pinctrl
// NOTE: might as well make it an error if clock cannot be initialized

View File

@ -2,7 +2,7 @@
use abi::{error::Error, io::TerminalOptions};
use alloc::sync::Arc;
use device_api::{
device::Device,
device::{Device, DeviceInitContext},
interrupt::{FullIrq, InterruptHandler, IrqVector},
};
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
@ -139,7 +139,7 @@ impl Device for Pl011 {
"Primecell PL011 UART"
}
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
let mut io = Io {
regs: DeviceMemoryIo::map(self.base, Default::default())?,
};