blob: e35555d4c6cc93fa5cd0b02028767466391ecd94 [file] [log] [blame]
Andrew Walbranf2594882022-03-15 17:32:53 +00001// Copyright 2022, The Android Open Source Project
2//
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 at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// 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 and
13// limitations under the License.
14
15//! Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
16//! provided by crosvm, and won't work with real hardware.
17
18use core::fmt::{self, Write};
Andrew Walbranf2594882022-03-15 17:32:53 +000019
20/// Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
21/// provided by crosvm, and won't work with real hardware.
22pub struct Uart {
23 base_address: *mut u8,
24}
25
26impl Uart {
27 /// Constructs a new instance of the UART driver for a device at the given base address.
28 ///
29 /// # Safety
30 ///
31 /// The given base address must point to the 8 MMIO control registers of an appropriate UART
32 /// device, which must be mapped into the address space of the process as device memory and not
33 /// have any other aliases.
34 pub unsafe fn new(base_address: usize) -> Self {
35 Self { base_address: base_address as *mut u8 }
36 }
37
38 /// Writes a single byte to the UART.
39 pub fn write_byte(&self, byte: u8) {
Andrew Walbranc06e7342023-07-05 14:00:51 +000040 // SAFETY: We know that the base address points to the control registers of a UART device
41 // which is appropriately mapped.
Andrew Walbranf2594882022-03-15 17:32:53 +000042 unsafe {
Andrew Walbranba17f352024-06-11 17:24:53 +010043 core::arch::asm!(
44 "strb {value:w}, [{ptr}]",
45 value = in(reg) byte,
46 ptr = in(reg) self.base_address,
47 );
Andrew Walbranf2594882022-03-15 17:32:53 +000048 }
49 }
50}
51
52impl Write for Uart {
53 fn write_str(&mut self, s: &str) -> fmt::Result {
54 for c in s.as_bytes() {
55 self.write_byte(*c);
56 }
57 Ok(())
58 }
59}
60
Andrew Walbranc06e7342023-07-05 14:00:51 +000061// SAFETY: `Uart` just contains a pointer to device memory, which can be accessed from any context.
Andrew Walbranf2594882022-03-15 17:32:53 +000062unsafe impl Send for Uart {}