chipset_device/
io.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Memory mapped IO (MMIO) and port IO support.
5
6pub mod deferred;
7
8/// An error related to the suitability of the IO request for the device. A
9/// device should handle device-specific errors internally, and should return
10/// `IoResult::Ok` in these conditions.
11#[derive(Debug)]
12pub enum IoError {
13    /// The requested device register is not present.
14    InvalidRegister,
15    /// The access length is invalid for the specified address.
16    InvalidAccessSize,
17    /// The caller attempted to perform an unaligned access to the device
18    /// registers.
19    UnalignedAccess,
20}
21
22/// The result returned by a device IO (memory-mapped IO, port IO, or PCI Config
23/// Space) operation, as in methods of [`MmioIntercept`](crate::mmio::MmioIntercept),
24/// [`PortIoIntercept`](crate::pio::PortIoIntercept), or
25/// [`PciConfigSpace`](crate::pci::PciConfigSpace).
26#[derive(Debug)]
27#[must_use]
28pub enum IoResult {
29    /// The IO operation succeeded.
30    Ok,
31    /// The IO operation failed due to an access error.
32    ///
33    /// The caller should log the failure, then ignore writes, and fill the
34    /// buffer with an appropriate bus-specific error value on reads. e.g. For
35    /// port IO or memory-mapped IO this value is typically `!0`, while for PCI
36    /// config space the value is typically `0`.
37    Err(IoError),
38    /// Defer this request until [`deferred::DeferredRead::complete`] or
39    /// [`deferred::DeferredWrite::complete`] is called.
40    Defer(deferred::DeferredToken),
41}
42
43impl IoResult {
44    /// Asserts if `self` is not `IoResult::Ok`.
45    #[track_caller]
46    pub fn unwrap(self) {
47        match self {
48            IoResult::Ok => {}
49            IoResult::Err(_) | IoResult::Defer(_) => panic!("unexpected IO result {:?}", self),
50        }
51    }
52
53    /// Converts `self` to a `Result<(), IoError>`, panicking if `self` is
54    /// `IoResult::Defer`.
55    #[track_caller]
56    pub fn now_or_never(self) -> Result<(), IoError> {
57        match self {
58            IoResult::Ok => Ok(()),
59            IoResult::Err(e) => Err(e),
60            IoResult::Defer(_) => panic!("unexpected IO result {:?}", self),
61        }
62    }
63}