1use core::fmt;
2
3use alloc::{collections::BTreeMap, string::String, sync::Arc};
4use tracing::info;
5
6use crate::{
7 fs::{
8 self, DirTraverse, DirectoryNode, FileAttributes, FileNode, FileSystem, FileSystemError,
9 Node,
10 },
11 power,
12 sync::{once::OnceLock, spin::rwlock::RwLock},
13};
14
15use self::{
16 keyboard_mouse::{KeyboardDeviceCreator, MouseDeviceCreator},
17 pci::{PciDeviceConfig, PciDeviceProbeIterator},
18};
19
20pub mod clock;
21pub mod ide;
22pub mod keyboard_mouse;
23pub mod net;
24pub mod pci;
25pub mod pipe;
26
27static DEVICES: OnceLock<Devices> = OnceLock::new();
28
29pub(crate) const DEVICES_FILESYSTEM_CLUSTER_MAGIC: u64 = 0xdef1ce5;
30pub(crate) const DEVICES_FILESYSTEM_ROOT_INODE_MAGIC: u64 = 0xdef1ce55007;
31
32#[derive(Debug)]
33struct Devices {
34 devices: RwLock<BTreeMap<String, Arc<dyn Device>>>,
35}
36
37impl Devices {
38 fn register_device(&self, device: Arc<dyn Device>) {
39 let mut devices = self.devices.write();
40 assert!(
41 !devices.contains_key(device.name()),
42 "Device {} already registered",
43 device.name()
44 );
45 info!("Registered {} device", device.name());
46 devices.insert(String::from(device.name()), device);
47 }
48
49 fn unregister_all_devices(&self) {
50 let mut devices = self.devices.write();
51
52 devices.iter_mut().for_each(|(name, device)| {
53 let _ = device.close();
54 info!("Unregistering {} device", name);
55 });
56
57 devices.clear();
58 }
59}
60
61pub trait Device: Sync + Send + fmt::Debug {
62 fn name(&self) -> &str;
63 fn read(&self, _offset: u64, _buf: &mut [u8]) -> Result<u64, FileSystemError> {
64 Err(FileSystemError::ReadNotSupported)
65 }
66 fn write(&self, _offset: u64, _buf: &[u8]) -> Result<u64, FileSystemError> {
67 Err(FileSystemError::WriteNotSupported)
68 }
69 fn set_size(&self, _size: u64) -> Result<(), FileSystemError> {
70 Err(FileSystemError::WriteNotSupported)
71 }
72 fn close(&self) -> Result<(), FileSystemError> {
74 Ok(())
75 }
76 fn clone_device(&self) -> Result<(), FileSystemError> {
78 Ok(())
79 }
80 fn try_create(&self) -> Option<Result<Arc<dyn Device>, FileSystemError>> {
85 None
86 }
87}
88
89struct DevicesFilesystem;
90
91impl FileSystem for DevicesFilesystem {
92 fn open_root(&self) -> Result<DirectoryNode, FileSystemError> {
93 Ok(DirectoryNode::without_parent(
94 String::from("/"),
95 FileAttributes::DIRECTORY,
96 DEVICES_FILESYSTEM_ROOT_INODE_MAGIC,
97 ))
98 }
99
100 fn read_dir(
101 &self,
102 inode: &DirectoryNode,
103 handler: &mut dyn FnMut(Node) -> DirTraverse,
104 ) -> Result<(), FileSystemError> {
105 assert_eq!(inode.start_cluster(), DEVICES_FILESYSTEM_ROOT_INODE_MAGIC);
106
107 if inode.name().is_empty() || inode.name() == "/" {
108 for node in DEVICES.get().devices.read().iter().map(|(name, device)| {
109 FileNode::new_device(name.clone(), FileAttributes::EMPTY, device.clone()).into()
110 }) {
111 if let DirTraverse::Stop = handler(node) {
112 break;
113 }
114 }
115 Ok(())
116 } else {
117 Err(FileSystemError::FileNotFound)
118 }
119 }
120
121 fn unmount(self: Arc<Self>) {
122 DEVICES.get().unregister_all_devices();
124 }
125}
126
127pub fn init_devices_mapping() {
128 DEVICES
129 .set(Devices {
130 devices: RwLock::new(BTreeMap::new()),
131 })
132 .expect("Devices already initialized");
133
134 register_device(Arc::new(power::PowerDevice));
136
137 fs::mapping::mount("/devices", Arc::new(DevicesFilesystem)).expect("Mapping failed");
138}
139
140pub fn register_device(device: Arc<dyn Device>) {
141 DEVICES.get().register_device(device);
142}
143
144pub fn probe_pci_devices() {
145 let pci_device_iter = PciDeviceProbeIterator::new();
146 for device in pci_device_iter {
147 if probe_pci_driver(&device) {
148 info!(
149 "[{:02X}.{:02X}.{:02X}] Driver found for device: {:04X}:{:04X} - {}",
150 device.bus,
151 device.dev,
152 device.func,
153 device.vendor_id,
154 device.device_id,
155 device.device_type
156 );
157 } else {
158 info!(
159 "[{:02X}.{:02X}.{:02X}] No driver found for device: {:04X}:{:04X} - {}",
160 device.bus,
161 device.dev,
162 device.func,
163 device.vendor_id,
164 device.device_id,
165 device.device_type
166 );
167 }
168 }
169}
170
171pub fn probe_pci_driver(pci_device: &PciDeviceConfig) -> bool {
172 ide::try_register_ide_device(pci_device) || net::try_register_net_device(pci_device)
173 }
175
176pub fn init_legacy_devices() {
178 keyboard_mouse::init_device();
179 register_device(Arc::new(KeyboardDeviceCreator));
180 register_device(Arc::new(MouseDeviceCreator));
181}