You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
5.1 KiB
Rust

// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
//! Driver support.
use crate::{
println,
synchronization::{interface::Mutex, NullLock},
};
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
const NUM_DRIVERS: usize = 5;
struct DriverManagerInner {
next_index: usize,
descriptors: [Option<DeviceDriverDescriptor>; NUM_DRIVERS],
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// Driver interfaces.
pub mod interface {
/// Device Driver functions.
pub trait DeviceDriver {
/// Return a compatibility string for identifying the driver.
fn compatible(&self) -> &'static str;
/// Called by the kernel to bring up the device.
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
unsafe fn init(&self) -> Result<(), &'static str> {
Ok(())
}
}
}
/// Tpye to be used as an optional callback after a driver's init() has run.
pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'static str>;
/// A descriptor for device drivers.
#[derive(Copy, Clone)]
pub struct DeviceDriverDescriptor {
device_driver: &'static (dyn interface::DeviceDriver + Sync),
post_init_callback: Option<DeviceDriverPostInitCallback>,
}
/// Provides device driver management functions.
pub struct DriverManager {
inner: NullLock<DriverManagerInner>,
}
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
static DRIVER_MANAGER: DriverManager = DriverManager::new();
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
impl DriverManagerInner {
/// Create an instance.
pub const fn new() -> Self {
Self {
next_index: 0,
descriptors: [None; NUM_DRIVERS],
}
}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl DeviceDriverDescriptor {
/// Create an instance.
pub fn new(
device_driver: &'static (dyn interface::DeviceDriver + Sync),
post_init_callback: Option<DeviceDriverPostInitCallback>,
) -> Self {
Self {
device_driver,
post_init_callback,
}
}
}
/// Return a reference to the global DriverManager.
pub fn driver_manager() -> &'static DriverManager {
&DRIVER_MANAGER
}
impl DriverManager {
/// Create an instance.
pub const fn new() -> Self {
Self {
inner: NullLock::new(DriverManagerInner::new()),
}
}
/// Register a device driver with the kernel.
pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
self.inner.lock(|inner| {
inner.descriptors[inner.next_index] = Some(descriptor);
inner.next_index += 1;
})
}
/// Helper for iterating over registered drivers.
fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDescriptor)) {
self.inner.lock(|inner| {
inner
.descriptors
.iter()
.filter_map(|x| x.as_ref())
.for_each(f)
})
}
/// Fully initialize all drivers.
///
/// # Safety
///
/// - During init, drivers might do stuff with system-wide impact.
pub unsafe fn init_drivers(&self) {
self.for_each_descriptor(|descriptor| {
// 1. Initialize driver.
if let Err(x) = descriptor.device_driver.init() {
panic!(
"Error initializing driver: {}: {}",
descriptor.device_driver.compatible(),
x
);
}
// 2. Call corresponding post init callback.
if let Some(callback) = &descriptor.post_init_callback {
if let Err(x) = callback() {
panic!(
"Error during driver post-init callback: {}: {}",
descriptor.device_driver.compatible(),
x
);
}
}
});
}
/// Enumerate all registered device drivers.
pub fn enumerate(&self) {
let mut i: usize = 1;
self.for_each_descriptor(|descriptor| {
println!(" {}. {}", i, descriptor.device_driver.compatible());
i += 1;
});
}
}