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
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Memory mapped IO (MMIO) and port IO support.
pub mod deferred;
/// An error related to the suitability of the IO request for the device. A
/// device should handle device-specific errors internally, and should return
/// `IoResult::Ok` in these conditions.
#[derive(Debug)]
pub enum IoError {
/// The requested device register is not present.
InvalidRegister,
/// The access length is invalid for the specified address.
InvalidAccessSize,
/// The caller attempted to perform an unaligned access to the device
/// registers.
UnalignedAccess,
}
/// The result returned by a device IO (memory-mapped IO, port IO, or PCI Config
/// Space) operation, as in methods of [`MmioIntercept`](crate::mmio::MmioIntercept),
/// [`PortIoIntercept`](crate::pio::PortIoIntercept), or
/// [`PciConfigSpace`](crate::pci::PciConfigSpace).
#[derive(Debug)]
#[must_use]
pub enum IoResult {
/// The IO operation succeeded.
Ok,
/// The IO operation failed due to an access error.
///
/// The caller should log the failure, then ignore writes, and fill the
/// buffer with an appropriate bus-specific error value on reads. e.g. For
/// port IO or memory-mapped IO this value is typically `!0`, while for PCI
/// config space the value is typically `0`.
Err(IoError),
/// Defer this request until [`deferred::DeferredRead::complete`] or
/// [`deferred::DeferredWrite::complete`] is called.
Defer(deferred::DeferredToken),
}
impl IoResult {
/// Asserts if `self` is not `IoResult::Ok`.
#[track_caller]
pub fn unwrap(self) {
match self {
IoResult::Ok => {}
IoResult::Err(_) | IoResult::Defer(_) => panic!("unexpected IO result {:?}", self),
}
}
/// Converts `self` to a `Result<(), IoError>`, panicking if `self` is
/// `IoResult::Defer`.
#[track_caller]
pub fn now_or_never(self) -> Result<(), IoError> {
match self {
IoResult::Ok => Ok(()),
IoResult::Err(e) => Err(e),
IoResult::Defer(_) => panic!("unexpected IO result {:?}", self),
}
}
}