chipset_device/pio.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Port IO intercepts
5
6use crate::ChipsetDevice;
7use crate::io::IoResult;
8use std::ops::RangeInclusive;
9
10/// Implemented by devices which use port IO intercepts.
11pub trait PortIoIntercept: ChipsetDevice {
12 /// Dispatch an IO port read to the device with the given address.
13 fn io_read(&mut self, io_port: u16, data: &mut [u8]) -> IoResult;
14 /// Dispatch an IO port write to the device with the given address.
15 fn io_write(&mut self, io_port: u16, data: &[u8]) -> IoResult;
16
17 /// Report a set of static io port regions (region_name, port_range) that
18 /// cannot be remapped at runtime and are always registered.
19 ///
20 /// _Note:_ This is a convenience method that makes it easy for simple
21 /// devices to declare some fixed IO regions without having to do through
22 /// the rigamarole of obtaining a reference to an instance of
23 /// [`RegisterPortIoIntercept`] + manually registering fixed ranges as part
24 /// of device init.
25 fn get_static_regions(&mut self) -> &[(&str, RangeInclusive<u16>)] {
26 &[]
27 }
28}
29
30io_region!(RegisterPortIoIntercept, ControlPortIoIntercept, u16);
31
32/// A zero sized type that has a no-op `impl` of [`RegisterPortIoIntercept`].
33///
34/// As the name suggests, this type should be used when a [`ChipsetDevice`] is
35/// hosted outside of a traditional "chipset" context, where some external code
36/// is responsible for managing the device's port IO intercepts.
37///
38/// That said, if you find yourself reaching for this type (outside the context
39/// of a test), you're probably doing something wrong. Consider implementing a
40/// proper chipset to host the device on instead.
41pub struct ExternallyManagedPortIoIntercepts;
42
43impl RegisterPortIoIntercept for ExternallyManagedPortIoIntercepts {
44 fn new_io_region(&mut self, _region_name: &str, _len: u16) -> Box<dyn ControlPortIoIntercept> {
45 Box::new(())
46 }
47}
48
49impl ControlPortIoIntercept for () {
50 fn region_name(&self) -> &str {
51 "(noop)"
52 }
53 fn map(&mut self, _addr: u16) {}
54 fn unmap(&mut self) {}
55 fn addr(&self) -> Option<u16> {
56 None
57 }
58 fn len(&self) -> u16 {
59 0
60 }
61 fn offset_of(&self, _addr: u16) -> Option<u16> {
62 None
63 }
64}