Skip to main content

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    /// If true, insert a debugger-mode relay between the emulator and the
30    /// backend that keeps the backend drained, dropping bytes instead of
31    /// applying backpressure. Intended for WinDbg / KD-over-serial.
32    pub debugger_mode: bool,
33}
34
35impl ResourceId<ChipsetDeviceHandleKind> for Serial16550DeviceHandle {
36    const ID: &'static str = "serial_16550";
37}
38
39/// A PC standard COM port.
40#[derive(Copy, Clone, PartialEq, Eq, Debug)]
41pub enum ComPort {
42    /// COM1, at 0x3f8/IRQ4.
43    Com1,
44    /// COM2, at 0x2f8/IRQ3.
45    Com2,
46    /// COM3, at 0x3e8/IRQ4.
47    Com3,
48    /// COM4, at 0x2e8/IRQ3.
49    Com4,
50}
51
52impl ComPort {
53    /// The IO port for the COM port.
54    pub const fn io_port(&self) -> u16 {
55        match *self {
56            ComPort::Com1 => 0x3f8,
57            ComPort::Com2 => 0x2f8,
58            ComPort::Com3 => 0x3e8,
59            ComPort::Com4 => 0x2e8,
60        }
61    }
62
63    /// The IRQ line for the COM port.
64    pub const fn irq(&self) -> u8 {
65        match *self {
66            ComPort::Com1 => 4,
67            ComPort::Com2 => 3,
68            ComPort::Com3 => 4,
69            ComPort::Com4 => 3,
70        }
71    }
72}
73
74impl Serial16550DeviceHandle {
75    /// Helper function to construct a standard PC COM port.
76    pub fn com_port(com_port: ComPort, io: Resource<SerialBackendHandle>) -> Self {
77        Self {
78            base: MmioOrIoPort::IoPort(com_port.io_port()),
79            register_width: 1,
80            irq: com_port.irq().into(),
81            io,
82            wait_for_rts: false,
83            debugger_mode: false,
84        }
85    }
86
87    /// Helper function to construct the four standard PC COM ports.
88    pub fn com_ports(io: [Resource<SerialBackendHandle>; 4]) -> [Self; 4] {
89        let [com1, com2, com3, com4] = io;
90        [
91            Self::com_port(ComPort::Com1, com1),
92            Self::com_port(ComPort::Com2, com2),
93            Self::com_port(ComPort::Com3, com3),
94            Self::com_port(ComPort::Com4, com4),
95        ]
96    }
97}
98
99/// The base address for the serial controller, either an MMIO address or an IO
100/// port.
101#[derive(MeshPayload)]
102pub enum MmioOrIoPort {
103    /// The physical MMIO address.
104    Mmio(u64),
105    /// The IO port.
106    IoPort(u16),
107}