morpheus_network/driver/block_traits.rs
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
//! Block device trait definitions.
//!
//! Defines the interface for block storage devices (VirtIO-blk, etc.).
/// Block I/O error types.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BlockError {
/// Request queue is full.
QueueFull,
/// Device not ready.
DeviceNotReady,
/// I/O error from device.
IoError,
/// Invalid sector number.
InvalidSector,
/// Request too large.
RequestTooLarge,
/// Device is read-only.
ReadOnly,
/// Unsupported operation.
Unsupported,
/// Operation timed out.
Timeout,
/// Device reported an error.
DeviceError,
}
/// Result of a completed block I/O operation.
#[derive(Debug, Clone, Copy)]
pub struct BlockCompletion {
/// Request ID (for matching with submit)
pub request_id: u32,
/// Status: 0 = success, non-zero = error
pub status: u8,
/// Bytes transferred
pub bytes_transferred: u32,
}
/// Block device information.
#[derive(Debug, Clone, Copy)]
pub struct BlockDeviceInfo {
/// Total capacity in sectors
pub total_sectors: u64,
/// Logical block (sector) size in bytes
pub sector_size: u32,
/// Maximum sectors per request
pub max_sectors_per_request: u32,
/// Whether device is read-only
pub read_only: bool,
}
/// Core block device interface.
///
/// All block drivers must implement this trait.
/// Operations are non-blocking with fire-and-forget semantics.
pub trait BlockDriver {
/// Get device information.
fn info(&self) -> BlockDeviceInfo;
/// Check if device can accept a new request.
fn can_submit(&self) -> bool;
/// Submit a read request.
///
/// # Arguments
/// - `sector`: Starting sector number
/// - `buffer_phys`: Physical address of destination buffer
/// - `num_sectors`: Number of sectors to read
/// - `request_id`: Caller-provided ID for tracking
///
/// # Returns
/// - `Ok(())`: Request submitted
/// - `Err(BlockError)`: Submit failed
///
/// # Contract
/// - MUST return immediately (fire-and-forget)
/// - Buffer must remain valid until completion
fn submit_read(
&mut self,
sector: u64,
buffer_phys: u64,
num_sectors: u32,
request_id: u32,
) -> Result<(), BlockError>;
/// Submit a write request.
///
/// # Arguments
/// - `sector`: Starting sector number
/// - `buffer_phys`: Physical address of source buffer
/// - `num_sectors`: Number of sectors to write
/// - `request_id`: Caller-provided ID for tracking
///
/// # Returns
/// - `Ok(())`: Request submitted
/// - `Err(BlockError)`: Submit failed
fn submit_write(
&mut self,
sector: u64,
buffer_phys: u64,
num_sectors: u32,
request_id: u32,
) -> Result<(), BlockError>;
/// Poll for completed requests.
///
/// # Returns
/// - `Some(completion)`: A request completed
/// - `None`: No completions available
fn poll_completion(&mut self) -> Option<BlockCompletion>;
/// Notify device that requests are pending.
///
/// Called after one or more submit calls.
fn notify(&mut self);
/// Flush any pending writes (if supported).
fn flush(&mut self) -> Result<(), BlockError> {
// Default: no-op for devices without flush support
Ok(())
}
}
/// Block driver initialization trait.
pub trait BlockDriverInit: Sized {
/// Error type for initialization failures.
type Error: core::fmt::Debug;
/// Configuration type.
type Config;
/// PCI vendor IDs this driver supports.
fn supported_vendors() -> &'static [u16];
/// PCI device IDs this driver supports.
fn supported_devices() -> &'static [u16];
/// Check if driver supports a PCI device.
fn supports_device(vendor: u16, device: u16) -> bool {
Self::supported_vendors().contains(&vendor) && Self::supported_devices().contains(&device)
}
/// Create driver from MMIO base and configuration.
///
/// # Safety
/// - `mmio_base` must be valid device MMIO address
/// - Configuration must be valid
unsafe fn create(mmio_base: u64, config: Self::Config) -> Result<Self, Self::Error>;
}