1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
//! Manages and handles initialization of all storage devices
//! and storage controllers in the system.
#![no_std]
extern crate alloc;
#[macro_use] extern crate log;
extern crate spin;
extern crate pci;
extern crate ata;
extern crate storage_device;
use alloc::{
vec::Vec,
sync::Arc,
};
use spin::Mutex;
use pci::PciDevice;
pub use storage_device::*;
/// A list of all of the available and initialized storage controllers that exist on this system.
static STORAGE_CONTROLLERS: Mutex<Vec<StorageControllerRef>> = Mutex::new(Vec::new());
/// Returns an iterator over all initialized storage controllers on this system.
///
/// This function requires allocation, as it currently clones the list of storage controllers,\
/// effectively a `Vec<Arc<StorageController>>`.
pub fn storage_controllers() -> impl Iterator<Item = StorageControllerRef> {
STORAGE_CONTROLLERS.lock().clone().into_iter()
}
/// Returns an iterator over all storage devices attached to the storage controllers on this system.
///
/// This function requires allocation, as it currently clones the list of storage devices (lazily)
/// within each storage controller, effectively a `Vec<Arc<Vec<Arc<StorageDevice>>>>`.
pub fn storage_devices() -> impl Iterator<Item = StorageDeviceRef> {
storage_controllers()
.flat_map(|c| c.lock()
.devices()
.collect::<Vec<StorageDeviceRef>>()
.into_iter()
)
}
/// Attempts to handle the initialization of the given `PciDevice`,
/// if it is a recognized storage device.
///
/// # Return
/// * `Ok(Some(StorageControllerRef))` if successful, containing the newly-initialized storage controller.
/// * `Ok(None)` if the given `PciDevice` isn't a supported storage device,
/// * An error if it fails to initialize a supported storage device.
pub fn init_device(pci_device: &PciDevice) -> Result<Option<StorageControllerRef>, &'static str> {
// We currently only support IDE controllers for ATA drives (aka PATA).
let storage_controller = if pci_device.class == 0x01 && pci_device.subclass == 0x01 {
info!("IDE controller PCI device found at: {:?}", pci_device.location);
let ide_controller = ata::IdeController::new(pci_device)?;
let storage_controller_ref: StorageControllerRef = Arc::new(Mutex::new(ide_controller));
STORAGE_CONTROLLERS.lock().push(Arc::clone(&storage_controller_ref));
Some(storage_controller_ref)
}
// Here: in the future, handle other supported storage devices
else {
None
};
Ok(storage_controller)
}