serial_16550_resources/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Resource definitions for the 16550A UART.
5
6#![forbid(unsafe_code)]
7
8use mesh::MeshPayload;
9use vm_resource::Resource;
10use vm_resource::ResourceId;
11use vm_resource::kind::ChipsetDeviceHandleKind;
12use vm_resource::kind::SerialBackendHandle;
13
14/// A handle to a 16550A serial device.
15#[derive(MeshPayload)]
16pub struct Serial16550DeviceHandle {
17    /// The base address for the device registers.
18    pub base: MmioOrIoPort,
19    /// The width of the device registers, in bytes.
20    pub register_width: u8,
21    /// The IRQ line for interrupts.
22    pub irq: u32,
23    /// The IO backend.
24    pub io: Resource<SerialBackendHandle>,
25    /// If true, wait for the guest to set DTR+RTS modem bits before
26    /// transmitting data to it. Otherwise, relay data from `io` even if
27    /// the guest does not appear to be ready.
28    pub wait_for_rts: bool,
29}
30
31impl ResourceId<ChipsetDeviceHandleKind> for Serial16550DeviceHandle {
32    const ID: &'static str = "serial_16550";
33}
34
35/// A PC standard COM port.
36#[derive(Copy, Clone, PartialEq, Eq, Debug)]
37pub enum ComPort {
38    /// COM1, at 0x3f8/IRQ4.
39    Com1,
40    /// COM2, at 0x2f8/IRQ3.
41    Com2,
42    /// COM3, at 0x3e8/IRQ4.
43    Com3,
44    /// COM4, at 0x2e8/IRQ3.
45    Com4,
46}
47
48impl ComPort {
49    /// The IO port for the COM port.
50    pub const fn io_port(&self) -> u16 {
51        match *self {
52            ComPort::Com1 => 0x3f8,
53            ComPort::Com2 => 0x2f8,
54            ComPort::Com3 => 0x3e8,
55            ComPort::Com4 => 0x2e8,
56        }
57    }
58
59    /// The IRQ line for the COM port.
60    pub const fn irq(&self) -> u8 {
61        match *self {
62            ComPort::Com1 => 4,
63            ComPort::Com2 => 3,
64            ComPort::Com3 => 4,
65            ComPort::Com4 => 3,
66        }
67    }
68}
69
70impl Serial16550DeviceHandle {
71    /// Helper function to construct a standard PC COM port.
72    pub fn com_port(com_port: ComPort, io: Resource<SerialBackendHandle>) -> Self {
73        Self {
74            base: MmioOrIoPort::IoPort(com_port.io_port()),
75            register_width: 1,
76            irq: com_port.irq().into(),
77            io,
78            wait_for_rts: false,
79        }
80    }
81
82    /// Helper function to construct the four standard PC COM ports.
83    pub fn com_ports(io: [Resource<SerialBackendHandle>; 4]) -> [Self; 4] {
84        let [com1, com2, com3, com4] = io;
85        [
86            Self::com_port(ComPort::Com1, com1),
87            Self::com_port(ComPort::Com2, com2),
88            Self::com_port(ComPort::Com3, com3),
89            Self::com_port(ComPort::Com4, com4),
90        ]
91    }
92}
93
94/// The base address for the serial controller, either an MMIO address or an IO
95/// port.
96#[derive(MeshPayload)]
97pub enum MmioOrIoPort {
98    /// The physical MMIO address.
99    Mmio(u64),
100    /// The IO port.
101    IoPort(u16),
102}