blob: b52d92452bfb969fd3165576baefe03d0101d085 [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
21const BASE_ADDRESS: usize = 0x3f8;
22
23static CONSOLE: SpinMutex<Option<Uart>> = SpinMutex::new(None);
24
25/// Initialises a new instance of the UART driver and returns it.
26fn create() -> Uart {
27 // Safe because BASE_ADDRESS is the base of the MMIO region for a UART and is mapped as device
28 // memory.
29 unsafe { Uart::new(BASE_ADDRESS) }
30}
31
32/// Initialises the global instance of the UART driver. This must be called before using
33/// the `print!` and `println!` macros.
34pub fn init() {
35 let uart = create();
36 CONSOLE.lock().replace(uart);
37}
38
39/// Writes a string to the console.
40///
41/// Panics if [`init`] was not called first.
42pub fn write_str(s: &str) {
43 CONSOLE.lock().as_mut().unwrap().write_str(s).unwrap();
44}
45
46/// Writes a formatted string to the console.
47///
48/// Panics if [`init`] was not called first.
Andrew Walbranf2594882022-03-15 17:32:53 +000049pub fn write_args(format_args: Arguments) {
50 write(CONSOLE.lock().as_mut().unwrap(), format_args).unwrap();
51}
52
53/// Reinitialises the UART driver and writes a string to it.
54///
55/// This is intended for use in situations where the UART may be in an unknown state or the global
56/// instance may be locked, such as in an exception handler or panic handler.
57pub fn emergency_write_str(s: &str) {
58 let mut uart = create();
59 let _ = uart.write_str(s);
60}
Andrew Walbranc1bcb3c2022-03-31 13:13:57 +000061
62/// Reinitialises the UART driver and writes a formatted string to it.
63///
64/// This is intended for use in situations where the UART may be in an unknown state or the global
65/// instance may be locked, such as in an exception handler or panic handler.
66pub fn emergency_write_args(format_args: Arguments) {
67 let mut uart = create();
68 let _ = write(&mut uart, format_args);
69}
70
71/// Prints the given string to the console.
72///
73/// Panics if the console has not yet been initialised. May hang if used in an exception context;
74/// use `eprint!` instead.
75#[macro_export]
76macro_rules! print {
77 ($($arg:tt)*) => ($crate::console::write_args(format_args!($($arg)*)));
78}
79
80/// Prints the given formatted string to the console, followed by a newline.
81///
82/// Panics if the console has not yet been initialised. May hang if used in an exception context;
83/// use `eprintln!` instead.
84#[macro_export]
85macro_rules! println {
86 () => ($crate::console::write_str("\n"));
87 ($($arg:tt)*) => ({
88 $crate::console::write_args(format_args!($($arg)*))};
89 $crate::console::write_str("\n");
90 );
91}
92
93/// Prints the given string to the console in an emergency, such as an exception handler.
94///
95/// Never panics.
96#[macro_export]
97macro_rules! eprint {
98 ($($arg:tt)*) => ($crate::console::emergency_write_args(format_args!($($arg)*)));
99}
100
101/// Prints the given string followed by a newline to the console in an emergency, such as an
102/// exception handler.
103///
104/// Never panics.
105#[macro_export]
106macro_rules! eprintln {
107 () => ($crate::console::emergency_write_str("\n"));
108 ($($arg:tt)*) => ({
109 $crate::console::emergency_write_args(format_args!($($arg)*))};
110 $crate::console::emergency_write_str("\n");
111 );
112}