blob: 657a62b83ea8b0823ea90e47b826d45019528013 [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//! Console driver for 8250 UART.
16
17use crate::uart::Uart;
18use core::fmt::{write, Arguments, Write};
19use spin::mutex::SpinMutex;
20
Pierre-Clément Tosia38bc782022-10-05 20:28:30 +010021/// Base memory-mapped address of the primary UART device.
22pub const BASE_ADDRESS: usize = 0x3f8;
Andrew Walbranf2594882022-03-15 17:32:53 +000023
24static CONSOLE: SpinMutex<Option<Uart>> = SpinMutex::new(None);
25
26/// Initialises a new instance of the UART driver and returns it.
27fn create() -> Uart {
Andrew Walbranc06e7342023-07-05 14:00:51 +000028 // SAFETY: BASE_ADDRESS is the base of the MMIO region for a UART and is mapped as device
Andrew Walbranf2594882022-03-15 17:32:53 +000029 // memory.
30 unsafe { Uart::new(BASE_ADDRESS) }
31}
32
33/// Initialises the global instance of the UART driver. This must be called before using
34/// the `print!` and `println!` macros.
35pub fn init() {
36 let uart = create();
37 CONSOLE.lock().replace(uart);
38}
39
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010040/// Writes a formatted string followed by a newline to the console.
Andrew Walbranf2594882022-03-15 17:32:53 +000041///
42/// Panics if [`init`] was not called first.
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010043pub(crate) fn writeln(format_args: Arguments) {
44 let mut guard = CONSOLE.lock();
45 let uart = guard.as_mut().unwrap();
46
47 write(uart, format_args).unwrap();
48 let _ = uart.write_str("\n");
Andrew Walbranf2594882022-03-15 17:32:53 +000049}
50
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010051/// Reinitializes the UART driver and writes a formatted string followed by a newline to it.
Andrew Walbranf2594882022-03-15 17:32:53 +000052///
53/// This is intended for use in situations where the UART may be in an unknown state or the global
54/// instance may be locked, such as in an exception handler or panic handler.
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010055pub fn ewriteln(format_args: Arguments) {
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000056 let mut uart = create();
57 let _ = write(&mut uart, format_args);
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010058 let _ = uart.write_str("\n");
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000059}
60
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000061/// Prints the given formatted string to the console, followed by a newline.
62///
Alice Wangeff58392023-07-04 13:32:09 +000063/// Panics if the console has not yet been initialized. May hang if used in an exception context;
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000064/// use `eprintln!` instead.
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000065macro_rules! println {
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010066 ($($arg:tt)*) => ($crate::console::writeln(format_args!($($arg)*)));
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000067}
68
Jakob Vukalovicef996292023-04-13 14:28:34 +000069pub(crate) use println; // Make it available in this crate.
70
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000071/// Prints the given string followed by a newline to the console in an emergency, such as an
72/// exception handler.
73///
74/// Never panics.
75#[macro_export]
76macro_rules! eprintln {
Pierre-Clément Tosibc9fb7e2024-06-19 17:28:47 +010077 ($($arg:tt)*) => ($crate::console::ewriteln(format_args!($($arg)*)));
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000078}