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}