blob: e9298cc766d61e5c5c9d137af93f885ee8a1d850 [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 {
28 // Safe because BASE_ADDRESS is the base of the MMIO region for a UART and is mapped as device
29 // 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
40/// Writes a string to the console.
41///
42/// Panics if [`init`] was not called first.
Jakob Vukalovicef996292023-04-13 14:28:34 +000043pub(crate) fn write_str(s: &str) {
Andrew Walbranf2594882022-03-15 17:32:53 +000044 CONSOLE.lock().as_mut().unwrap().write_str(s).unwrap();
45}
46
47/// Writes a formatted string to the console.
48///
49/// Panics if [`init`] was not called first.
Jakob Vukalovicef996292023-04-13 14:28:34 +000050pub(crate) fn write_args(format_args: Arguments) {
Andrew Walbranf2594882022-03-15 17:32:53 +000051 write(CONSOLE.lock().as_mut().unwrap(), format_args).unwrap();
52}
53
Alice Wangeff58392023-07-04 13:32:09 +000054/// Reinitializes the UART driver and writes a string to it.
Andrew Walbranf2594882022-03-15 17:32:53 +000055///
56/// This is intended for use in situations where the UART may be in an unknown state or the global
57/// instance may be locked, such as in an exception handler or panic handler.
58pub fn emergency_write_str(s: &str) {
59 let mut uart = create();
60 let _ = uart.write_str(s);
61}
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000062
Alice Wangeff58392023-07-04 13:32:09 +000063/// Reinitializes the UART driver and writes a formatted string to it.
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000064///
65/// This is intended for use in situations where the UART may be in an unknown state or the global
66/// instance may be locked, such as in an exception handler or panic handler.
67pub fn emergency_write_args(format_args: Arguments) {
68 let mut uart = create();
69 let _ = write(&mut uart, format_args);
70}
71
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000072/// Prints the given formatted string to the console, followed by a newline.
73///
Alice Wangeff58392023-07-04 13:32:09 +000074/// Panics if the console has not yet been initialized. May hang if used in an exception context;
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000075/// use `eprintln!` instead.
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000076macro_rules! println {
77 () => ($crate::console::write_str("\n"));
78 ($($arg:tt)*) => ({
79 $crate::console::write_args(format_args!($($arg)*))};
80 $crate::console::write_str("\n");
81 );
82}
83
Jakob Vukalovicef996292023-04-13 14:28:34 +000084pub(crate) use println; // Make it available in this crate.
85
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000086/// Prints the given string to the console in an emergency, such as an exception handler.
87///
88/// Never panics.
89#[macro_export]
90macro_rules! eprint {
91 ($($arg:tt)*) => ($crate::console::emergency_write_args(format_args!($($arg)*)));
92}
93
94/// Prints the given string followed by a newline to the console in an emergency, such as an
95/// exception handler.
96///
97/// Never panics.
98#[macro_export]
99macro_rules! eprintln {
100 () => ($crate::console::emergency_write_str("\n"));
101 ($($arg:tt)*) => ({
102 $crate::console::emergency_write_args(format_args!($($arg)*))};
103 $crate::console::emergency_write_str("\n");
104 );
105}