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(Copy, Clone, Debug, mesh::MeshPayload)]
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    /// The device never responded to the IO request.
21    NoResponse,
22}
23
24/// The result returned by a device IO (memory-mapped IO, port IO, or PCI Config
25/// Space) operation, as in methods of [`MmioIntercept`](crate::mmio::MmioIntercept),
26/// [`PortIoIntercept`](crate::pio::PortIoIntercept), or
27/// [`PciConfigSpace`](crate::pci::PciConfigSpace).
28#[derive(Debug)]
29#[must_use]
30pub enum IoResult {
31    /// The IO operation succeeded.
32    Ok,
33    /// The IO operation failed due to an access error.
34    ///
35    /// The caller should log the failure, then ignore writes, and fill the
36    /// buffer with an appropriate bus-specific error value on reads. e.g. For
37    /// port IO or memory-mapped IO this value is typically `!0`, while for PCI
38    /// config space the value is typically `0`.
39    Err(IoError),
40    /// Defer this request until [`deferred::DeferredRead::complete`] or
41    /// [`deferred::DeferredWrite::complete`] is called.
42    Defer(deferred::DeferredToken),
43}
44
45impl IoResult {
46    /// Asserts if `self` is not `IoResult::Ok`.
47    #[track_caller]
48    pub fn unwrap(self) {
49        match self {
50            IoResult::Ok => {}
51            IoResult::Err(_) | IoResult::Defer(_) => panic!("unexpected IO result {:?}", self),
52        }
53    }
54
55    /// Converts `self` to a `Result<(), IoError>`, panicking if `self` is
56    /// `IoResult::Defer`.
57    #[track_caller]
58    pub fn now_or_never(self) -> Result<(), IoError> {
59        match self {
60            IoResult::Ok => Ok(()),
61            IoResult::Err(e) => Err(e),
62            IoResult::Defer(_) => panic!("unexpected IO result {:?}", self),
63        }
64    }
65}