serial.rs0.00%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::collections::VecDeque;16
use std::io;17
use std::sync::Arc;18
19
use bitfield::bitfield;20
use parking_lot::Mutex;21
22
use crate::device::console::{Console, UartRecv};23
use crate::device::ioapic::IoApic;24
use crate::device::{self, MmioDev, Pause};25
use crate::hv::MsiSender;26
use crate::mem::emulated::{Action, Mmio};27
use crate::{bitflags, mem};28
29
const TX_HOLDING_REGISTER: u16 = 0x0;30
const RX_BUFFER_REGISTER: u16 = 0x0;31
const DIVISOR_LATCH_LSB: u16 = 0x0;32
const DIVISOR_LATCH_MSB: u16 = 0x1;33
const INTERRUPT_ENABLE_REGISTER: u16 = 0x1;34
const FIFO_CONTROL_REGISTER: u16 = 0x2;35
const INTERRUPT_IDENTIFICATION_REGISTER: u16 = 0x2;36
const LINE_CONTROL_REGISTER: u16 = 0x3;37
const MODEM_CONTROL_REGISTER: u16 = 0x4;38
const LINE_STATUS_REGISTER: u16 = 0x5;39
const MODEM_STATUS_REGISTER: u16 = 0x6;40
const SCRATCH_REGISTER: u16 = 0x7;41
42
// offset 0x1, Interrupt Enable Register (IER)43
bitflags! {44
#[derive(Default)]45
pub struct InterruptEnable(u8) {46
MODEM_STATUS = 1 << 3;47
RECEIVER_LINE_STATUS = 1 << 2;48
TX_HOLDING_REGISTER_EMPTY = 1 << 1;49
RECEIVED_DATA_AVAILABLE = 1 << 0;50
}51
}52
53
// offset 0x2, write, FIFO Control Register (FCR)54
bitfield! {55
#[derive(Copy, Clone, Default)]56
pub struct FifoControl(u8);57
impl Debug;58
rx_trigger_size_bits, _: 7, 6;59
dma_mode, _: 3;60
tx_reset, _: 2;61
rx_reset, _: 1;62
fifo_enabled, _: 0;63
}64
65
impl FifoControl {66
pub fn rx_trigger_size(&self) -> usize {67
match self.rx_trigger_size_bits() {68
0b00 => 1,69
0b01 => 4,70
0b10 => 8,71
0b11 => 14,72
_ => unreachable!(),73
}74
}75
}76
77
// offset 0x2, read, Interrupt Identification Register78
bitfield! {79
#[derive(Copy, Clone)]80
pub struct InterruptIdentification(u8);81
impl Debug;82
fifo_enabled, _: 7, 6;83
interrupt_id, set_interrupt_id: 3,1;84
no_pending, set_no_pending: 0; // Interrupt Pending Bit85
}86
87
impl InterruptIdentification {88
pub fn set_fifo_enabled(&mut self) {89
self.0 |= 0b11 << 6;90
}91
92
pub fn clear_fifi_enabled(&mut self) {93
self.0 &= !(0b11 << 6);94
}95
96
pub fn set_rx_data_available(&mut self) {97
self.0 = (self.0 & !0b1111) | 0b0100;98
}99
100
pub fn set_tx_room_empty(&mut self) {101
self.0 = (self.0 & !0b1111) | 0b0010;102
}103
104
pub fn clear_interrupt(&mut self) {105
self.0 = (self.0 & !0b1111) | 1;106
}107
}108
109
impl Default for InterruptIdentification {110
fn default() -> Self {111
let mut val = InterruptIdentification(0);112
val.clear_interrupt();113
val114
}115
}116
117
// offset 0x3, Line Control Register (LCR)118
bitfield! {119
#[derive(Copy, Clone)]120
pub struct LineControl(u8);121
impl Debug;122
divisor_latch_access, _: 7;123
break_, _: 6;124
stick_parity, _: 5;125
even_parity, _: 4;126
parity_enabled, _: 3;127
step_bits, _: 2;128
word_length, _: 1, 0;129
}130
131
impl Default for LineControl {132
fn default() -> Self {133
LineControl(0b00000011) // 8 data bits as default134
}135
}136
137
// offset 0x4, Modem Control Register138
bitfield! {139
#[derive(Copy, Clone, Default)]140
pub struct ModemControl(u8);141
impl Debug;142
loop_back, _: 4;143
out_2, _: 3;144
out_1, _: 2;145
request_to_send, _: 1;146
data_terminal_ready, _: 0; // Data Terminal Ready147
}148
149
// offset 0x5, Line Status Register (LSR)150
bitflags! {151
pub struct LineStatus(u8) {152
ERROR_IN_RX_FIFO = 1 << 7;153
TX_EMPTY = 1 << 6;154
TX_HOLDING_REGISTER_EMPTY = 1 << 5;155
BREAK_INTERRUPT = 1 << 4;156
FRAMING_ERROR = 1 << 3;157
PARITY_ERROR = 1 << 2;158
OVERRUN_ERROR = 1 << 1;159
DATA_READY = 1 << 0;160
}161
}162
163
impl Default for LineStatus {164
fn default() -> Self {165
LineStatus::TX_EMPTY | LineStatus::TX_HOLDING_REGISTER_EMPTY166
}167
}168
169
#[derive(Default, Debug)]170
struct SerialReg {171
interrupt_enable: InterruptEnable, // 0x1, Interrupt Enable Register (IER)172
#[allow(dead_code)]173
fifo_control: FifoControl, // 0x2, write, FIFO Control Register (FCR)174
interrupt_identification: InterruptIdentification, // 0x2, read, Interrupt Identification Register175
line_control: LineControl, // 0x3, Line Control Register (LCR)176
modem_control: ModemControl, // 0x4, Modem Control Register (MCR)177
line_status: LineStatus,178
modem_status: u8, // 0x6, Modem Status Register (MSR)179
scratch: u8, // 0x7, Scratch Register (SCR)180
divisor: u16,181
data: VecDeque<u8>,182
}183
184
#[derive(Debug)]185
pub struct Serial<M: MsiSender> {186
name: Arc<str>,187
io_apci: Arc<IoApic<M>>,188
pin: u8,189
reg: Arc<Mutex<SerialReg>>,190
console: Console,191
}192
193
impl<M> Mmio for Serial<M>194
where195
M: MsiSender,196
{197
fn size(&self) -> u64 {198
8199
}200
201
fn read(&self, offset: u64, _size: u8) -> Result<u64, mem::Error> {202
let mut reg = self.reg.lock();203
let ret = match offset as u16 {204
DIVISOR_LATCH_LSB if reg.line_control.divisor_latch_access() => reg.divisor as u8,205
DIVISOR_LATCH_MSB if reg.line_control.divisor_latch_access() => {206
(reg.divisor >> 8) as u8207
}208
RX_BUFFER_REGISTER => {209
if reg.data.len() <= 1 {210
reg.line_status &= !LineStatus::DATA_READY;211
}212
reg.data.pop_front().unwrap_or(0xff)213
}214
INTERRUPT_ENABLE_REGISTER => reg.interrupt_enable.bits(),215
INTERRUPT_IDENTIFICATION_REGISTER => {216
let ret = reg.interrupt_identification.0;217
reg.interrupt_identification.clear_interrupt();218
ret219
}220
LINE_CONTROL_REGISTER => reg.line_control.0,221
MODEM_CONTROL_REGISTER => reg.modem_control.0,222
LINE_STATUS_REGISTER => reg.line_status.bits(),223
MODEM_STATUS_REGISTER => reg.modem_status,224
SCRATCH_REGISTER => reg.scratch,225
_ => {226
log::error!("{}: read unreachable offset {offset:#x}", self.name,);227
0x0228
}229
};230
Ok(ret as u64)231
}232
233
fn write(&self, offset: u64, _size: u8, val: u64) -> mem::Result<Action> {234
let byte = val as u8;235
let mut reg = self.reg.lock();236
match offset as u16 {237
DIVISOR_LATCH_LSB if reg.line_control.divisor_latch_access() => {238
reg.divisor = (reg.divisor & 0xff00) | byte as u16;239
}240
DIVISOR_LATCH_MSB if reg.line_control.divisor_latch_access() => {241
reg.divisor = (reg.divisor & 0x00ff) | ((byte as u16) << 8);242
}243
TX_HOLDING_REGISTER => {244
if reg.modem_control.loop_back() {245
reg.data.push_back(byte);246
if reg247
.interrupt_enable248
.contains(InterruptEnable::RECEIVED_DATA_AVAILABLE)249
{250
reg.interrupt_identification.set_rx_data_available();251
self.send_irq();252
}253
reg.line_status |= LineStatus::DATA_READY;254
} else {255
self.console.transmit(&[byte]);256
if reg257
.interrupt_enable258
.contains(InterruptEnable::TX_HOLDING_REGISTER_EMPTY)259
{260
reg.interrupt_identification.set_tx_room_empty();261
self.send_irq()262
}263
}264
}265
INTERRUPT_ENABLE_REGISTER => {266
reg.interrupt_enable = InterruptEnable::from_bits_truncate(byte);267
}268
FIFO_CONTROL_REGISTER => {}269
LINE_CONTROL_REGISTER => {270
reg.line_control = LineControl(byte);271
}272
MODEM_CONTROL_REGISTER => {273
reg.modem_control = ModemControl(byte);274
}275
LINE_STATUS_REGISTER => {}276
MODEM_STATUS_REGISTER => {}277
SCRATCH_REGISTER => {278
reg.scratch = byte;279
}280
_ => log::error!("{}: write unreachable offset {:#x}", self.name, offset),281
}282
Ok(Action::None)283
}284
}285
286
impl<M> Pause for Serial<M>287
where288
M: MsiSender,289
{290
fn pause(&self) -> device::Result<()> {291
Ok(())292
}293
294
fn resume(&self) -> device::Result<()> {295
Ok(())296
}297
}298
299
impl<M> MmioDev for Serial<M> where M: MsiSender {}300
301
struct SerialRecv<M: MsiSender> {302
pub name: Arc<str>,303
pub io_apci: Arc<IoApic<M>>,304
pub pin: u8,305
pub reg: Arc<Mutex<SerialReg>>,306
}307
308
impl<M: MsiSender> UartRecv for SerialRecv<M> {309
fn receive(&self, bytes: &[u8]) {310
let mut reg = self.reg.lock();311
reg.data.extend(bytes);312
if reg313
.interrupt_enable314
.contains(InterruptEnable::RECEIVED_DATA_AVAILABLE)315
{316
reg.interrupt_identification.set_rx_data_available();317
if let Err(e) = self.io_apci.service_pin(self.pin) {318
log::error!("{}: sending interrupt: {e:?}", self.name);319
}320
}321
reg.line_status |= LineStatus::DATA_READY;322
}323
}324
325
impl<M> Serial<M>326
where327
M: MsiSender,328
{329
pub fn new(base_port: u16, io_apci: Arc<IoApic<M>>, pin: u8) -> io::Result<Self> {330
let reg = Arc::new(Mutex::new(SerialReg::default()));331
let name: Arc<str> = Arc::from(format!("serial_{base_port:#x}"));332
let uart_recv = SerialRecv {333
io_apci: io_apci.clone(),334
pin,335
name: name.clone(),336
reg: reg.clone(),337
};338
let console = Console::new(name.clone(), uart_recv)?;339
let serial = Serial {340
name,341
reg,342
pin,343
io_apci,344
console,345
};346
Ok(serial)347
}348
349
fn send_irq(&self) {350
if let Err(e) = self.io_apci.service_pin(self.pin) {351
log::error!("{}: sending interrupt: {e:?}", self.name);352
}353
}354
}355