Andrew Walbran | f259488 | 2022-03-15 17:32:53 +0000 | [diff] [blame] | 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 | |
Pierre-Clément Tosi | a38bc78 | 2022-10-05 20:28:30 +0100 | [diff] [blame] | 21 | /// Base memory-mapped address of the primary UART device. |
| 22 | pub const BASE_ADDRESS: usize = 0x3f8; |
Andrew Walbran | f259488 | 2022-03-15 17:32:53 +0000 | [diff] [blame] | 23 | |
| 24 | static CONSOLE: SpinMutex<Option<Uart>> = SpinMutex::new(None); |
| 25 | |
| 26 | /// Initialises a new instance of the UART driver and returns it. |
| 27 | fn 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. |
| 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. |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 43 | pub(crate) fn write_str(s: &str) { |
Andrew Walbran | f259488 | 2022-03-15 17:32:53 +0000 | [diff] [blame] | 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. |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 50 | pub(crate) fn write_args(format_args: Arguments) { |
Andrew Walbran | f259488 | 2022-03-15 17:32:53 +0000 | [diff] [blame] | 51 | write(CONSOLE.lock().as_mut().unwrap(), format_args).unwrap(); |
| 52 | } |
| 53 | |
Alice Wang | eff5839 | 2023-07-04 13:32:09 +0000 | [diff] [blame^] | 54 | /// Reinitializes the UART driver and writes a string to it. |
Andrew Walbran | f259488 | 2022-03-15 17:32:53 +0000 | [diff] [blame] | 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. |
| 58 | pub fn emergency_write_str(s: &str) { |
| 59 | let mut uart = create(); |
| 60 | let _ = uart.write_str(s); |
| 61 | } |
Andrew Walbran | c1bcb3c | 2022-03-31 13:13:57 +0000 | [diff] [blame] | 62 | |
Alice Wang | eff5839 | 2023-07-04 13:32:09 +0000 | [diff] [blame^] | 63 | /// Reinitializes the UART driver and writes a formatted string to it. |
Andrew Walbran | c1bcb3c | 2022-03-31 13:13:57 +0000 | [diff] [blame] | 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. |
| 67 | pub fn emergency_write_args(format_args: Arguments) { |
| 68 | let mut uart = create(); |
| 69 | let _ = write(&mut uart, format_args); |
| 70 | } |
| 71 | |
Andrew Walbran | c1bcb3c | 2022-03-31 13:13:57 +0000 | [diff] [blame] | 72 | /// Prints the given formatted string to the console, followed by a newline. |
| 73 | /// |
Alice Wang | eff5839 | 2023-07-04 13:32:09 +0000 | [diff] [blame^] | 74 | /// Panics if the console has not yet been initialized. May hang if used in an exception context; |
Andrew Walbran | c1bcb3c | 2022-03-31 13:13:57 +0000 | [diff] [blame] | 75 | /// use `eprintln!` instead. |
Andrew Walbran | c1bcb3c | 2022-03-31 13:13:57 +0000 | [diff] [blame] | 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 | |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 84 | pub(crate) use println; // Make it available in this crate. |
| 85 | |
Andrew Walbran | c1bcb3c | 2022-03-31 13:13:57 +0000 | [diff] [blame] | 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 | } |