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}