1 // 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
17 use crate::uart::Uart;
18 use core::fmt::{write, Arguments, Write};
19 use spin::mutex::SpinMutex;
20
21 /// Base memory-mapped address of the primary UART device.
22 pub const BASE_ADDRESS: usize = 0x3f8;
23
24 static CONSOLE: SpinMutex<Option<Uart>> = SpinMutex::new(None);
25
26 /// Initialises a new instance of the UART driver and returns it.
create() -> Uart27 fn create() -> Uart {
28 // SAFETY: 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.
init()35 pub 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.
write_str(s: &str)43 pub(crate) fn write_str(s: &str) {
44 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.
write_args(format_args: Arguments)50 pub(crate) fn write_args(format_args: Arguments) {
51 write(CONSOLE.lock().as_mut().unwrap(), format_args).unwrap();
52 }
53
54 /// Reinitializes the UART driver and writes a string to it.
55 ///
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.
emergency_write_str(s: &str)58 pub fn emergency_write_str(s: &str) {
59 let mut uart = create();
60 let _ = uart.write_str(s);
61 }
62
63 /// Reinitializes the UART driver and writes a formatted string to it.
64 ///
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.
emergency_write_args(format_args: Arguments)67 pub fn emergency_write_args(format_args: Arguments) {
68 let mut uart = create();
69 let _ = write(&mut uart, format_args);
70 }
71
72 /// Prints the given formatted string to the console, followed by a newline.
73 ///
74 /// Panics if the console has not yet been initialized. May hang if used in an exception context;
75 /// use `eprintln!` instead.
76 macro_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
84 pub(crate) use println; // Make it available in this crate.
85
86 /// Prints the given string to the console in an emergency, such as an exception handler.
87 ///
88 /// Never panics.
89 #[macro_export]
90 macro_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]
99 macro_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 }
106