yggdrasil/kernel/src/device/bus/simple_bus.rs

88 lines
2.4 KiB
Rust

//! Simple "passthrough" bus device
// use device_tree::{device_tree_driver, dt::DevTreeIndexNodeExt};
// use libk::device::manager::DEVICE_REGISTRY;
use core::ops::Range;
use abi::error::Error;
use alloc::{sync::Arc, vec::Vec};
use device_api::{
bus::Bus,
device::{Device, DeviceInitContext},
};
use device_tree::{
driver::{device_tree_driver, Node, ProbeContext},
DeviceTreePropertyRead,
};
struct SimpleBus {
ranges: Vec<(Range<u64>, u64)>,
}
impl Device for SimpleBus {
unsafe fn init(self: Arc<Self>, _cx: DeviceInitContext) -> Result<(), Error> {
Ok(())
}
fn as_bus(self: Arc<Self>) -> Option<Arc<dyn Bus>> {
Some(self)
}
fn display_name(&self) -> &str {
"simple-bus"
}
}
impl Bus for SimpleBus {
fn map_range(&self, bus_range: Range<u64>) -> Option<Range<u64>> {
if self.ranges.is_empty() {
return Some(bus_range);
}
let start = bus_range.start;
let end = bus_range.end;
for (range, offset) in self.ranges.iter() {
if range.contains(&start) && range.contains(&end) {
let start = start - range.start + *offset;
let end = end - range.start + *offset;
return Some(start..end);
}
}
None
}
}
device_tree_driver! {
compatible: ["simple-bus"],
driver: {
fn probe(&self, node: &Arc<Node>, _context: &ProbeContext) -> Option<Arc<dyn Device>> {
// Format per DT spec: (child-bus-address, parent-bus-address, length)
// Where:
// child-bus-address: #address-cells of this node
// parent-bus-address: #address-cells of parent bus
// length: #size-cells of this node
let ranges = node.property("ranges")?;
let parent_address_cells = node.bus_address_cells();
let child_address_cells = node.self_address_cells()?;
let child_size_cells = node.self_size_cells()?;
let cell_sizes = (child_address_cells, parent_address_cells, child_size_cells);
let mut items = Vec::new();
for (child_address, parent_address, length) in ranges.iter_cells(cell_sizes) {
let child_range = child_address..child_address + length;
items.push((child_range, parent_address));
}
Some(Arc::new(SimpleBus {
ranges: items,
}))
}
}
}