kernel/devices/
mod.rs

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    /// Informs the device that it is closed.
73    fn close(&self) -> Result<(), FileSystemError> {
74        Ok(())
75    }
76    /// Informs the device that it is cloned.
77    fn clone_device(&self) -> Result<(), FileSystemError> {
78        Ok(())
79    }
80    /// Open the device.
81    /// This tells the device manager that when opening a file with this device name, it should
82    /// instead use the device returned by this function.
83    /// if `None`, it will just use the device directly.
84    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        // clean the devices
123        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    // initialize builtin devices
135    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    // add more devices here
174}
175
176/// Devices such as PS/2 keyboard, mouse, serial ports, etc.
177pub fn init_legacy_devices() {
178    keyboard_mouse::init_device();
179    register_device(Arc::new(KeyboardDeviceCreator));
180    register_device(Arc::new(MouseDeviceCreator));
181}