// Copyright 2022, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Console driver for 8250 UART.

use crate::uart::Uart;
use core::{
    cell::OnceCell,
    fmt::{write, Arguments, Write},
};
use spin::mutex::SpinMutex;

// Arbitrary limit on the number of consoles that can be registered.
//
// Matches the UART count in crosvm.
const MAX_CONSOLES: usize = 4;

static CONSOLES: [SpinMutex<Option<Uart>>; MAX_CONSOLES] =
    [SpinMutex::new(None), SpinMutex::new(None), SpinMutex::new(None), SpinMutex::new(None)];
static ADDRESSES: [SpinMutex<OnceCell<usize>>; MAX_CONSOLES] = [
    SpinMutex::new(OnceCell::new()),
    SpinMutex::new(OnceCell::new()),
    SpinMutex::new(OnceCell::new()),
    SpinMutex::new(OnceCell::new()),
];

/// Index of the console used by default for logging.
pub const DEFAULT_CONSOLE_INDEX: usize = 0;

/// Index of the console used by default for emergency logging.
pub const DEFAULT_EMERGENCY_CONSOLE_INDEX: usize = DEFAULT_CONSOLE_INDEX;

/// Initialises the global instance(s) of the UART driver.
///
/// This must be called before using the `print!` and `println!` macros.
///
/// # Safety
///
/// This must be called once with the bases of UARTs, mapped as device memory and (if necessary)
/// shared with the host as MMIO, to which no other references must be held.
pub unsafe fn init(base_addresses: &[usize]) {
    for (i, &base_address) in base_addresses.iter().enumerate() {
        // Remember the valid address, for emergency console accesses.
        ADDRESSES[i].lock().set(base_address).expect("console::init() called more than once");

        // Initialize the console driver, for normal console accesses.
        let mut console = CONSOLES[i].lock();
        assert!(console.is_none(), "console::init() called more than once");
        // SAFETY: base_address must be the base of a mapped UART.
        console.replace(unsafe { Uart::new(base_address) });
    }
}

/// Writes a formatted string followed by a newline to the n-th console.
///
/// Panics if the n-th console was not initialized by calling [`init`] first.
pub fn writeln(n: usize, format_args: Arguments) {
    let mut guard = CONSOLES[n].lock();
    let uart = guard.as_mut().unwrap();

    write(uart, format_args).unwrap();
    let _ = uart.write_str("\n");
}

/// Reinitializes the n-th UART driver and writes a formatted string followed by a newline to it.
///
/// This is intended for use in situations where the UART may be in an unknown state or the global
/// instance may be locked, such as in an exception handler or panic handler.
pub fn ewriteln(n: usize, format_args: Arguments) {
    let Some(cell) = ADDRESSES[n].try_lock() else { return };
    let Some(addr) = cell.get() else { return };

    // SAFETY: addr contains the base of a mapped UART, passed in init().
    let mut uart = unsafe { Uart::new(*addr) };

    let _ = write(&mut uart, format_args);
    let _ = uart.write_str("\n");
}

/// Prints the given formatted string to the n-th console, followed by a newline.
///
/// Panics if the console has not yet been initialized. May hang if used in an exception context;
/// use `eprintln!` instead.
#[macro_export]
macro_rules! console_writeln {
    ($n:expr, $($arg:tt)*) => ({
        $crate::console::writeln($n, format_args!($($arg)*))
    })
}

pub(crate) use console_writeln;

/// Prints the given formatted string to the console, followed by a newline.
///
/// Panics if the console has not yet been initialized. May hang if used in an exception context;
/// use `eprintln!` instead.
macro_rules! println {
    ($($arg:tt)*) => ({
        $crate::console::console_writeln!($crate::console::DEFAULT_CONSOLE_INDEX, $($arg)*)
    })
}

pub(crate) use println; // Make it available in this crate.

/// Prints the given string followed by a newline to the console in an emergency, such as an
/// exception handler.
///
/// Never panics.
#[macro_export]
macro_rules! eprintln {
    ($($arg:tt)*) => ({
        $crate::console::ewriteln($crate::console::DEFAULT_EMERGENCY_CONSOLE_INDEX, format_args!($($arg)*))
    })
}
