rustubs/
io.rs

1//! I/O with keyboard, cga screen and serial
2
3use crate::arch::x86_64::arch_regs::get_sp;
4use crate::machine::cgascr::CGAScreen;
5use crate::machine::key::Key;
6use crate::machine::keyctrl::KEY_BUFFER;
7use crate::machine::serial::SerialWritter;
8use core::cell::SyncUnsafeCell;
9use core::fmt::{Arguments, Write};
10use core::panic::PanicInfo;
11use lazy_static::lazy_static;
12use spin::Mutex;
13lazy_static! {
14	pub static ref CGASCREEN_GLOBAL: Mutex<CGAScreen> =
15		Mutex::new(CGAScreen::new());
16}
17
18#[panic_handler]
19fn panic(info: &PanicInfo) -> ! {
20	println!("[{:X}] {}", get_sp(), info);
21	loop {}
22}
23
24/// the global serial writer, this is not synchronized. Used for debugging
25/// where locking is not available
26pub static SERIAL_GLOBAL: SyncUnsafeCell<SerialWritter> =
27	SyncUnsafeCell::new(SerialWritter::new(0x3f8));
28
29/// CGA screen print, synchronized. NEVER use in prologue
30#[macro_export]
31macro_rules! print {
32    ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
33}
34pub(crate) use print;
35
36/// CGA screen println, synchronized. NEVER use in prologue
37#[macro_export]
38macro_rules! println {
39    () => ($crate::print!("\n"));
40    ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*)));
41}
42pub(crate) use println;
43
44/// serial (0x3f8 for qemu) print, not synchronized. can use in prologue
45#[macro_export]
46macro_rules! sprint {
47    ($($arg:tt)*) => ($crate::io::_serial_print(format_args!($($arg)*)));
48}
49pub(crate) use sprint;
50
51#[macro_export]
52/// serial (0x3f8 for qemu) println, not synchronized. can use in prologue
53macro_rules! sprintln{
54    () => ($crate::sprint!("\n"));
55    ($($arg:tt)*) => (sprint!("{}\n", format_args!($($arg)*)));
56}
57pub(crate) use sprintln;
58
59pub fn read_key() -> Key {
60	use crate::proc::sync::semaphore::Semaphore;
61	KEY_BUFFER.p().unwrap()
62}
63
64pub fn _print(args: Arguments) {
65	CGASCREEN_GLOBAL.lock().write_fmt(args).unwrap();
66}
67
68pub fn _serial_print(args: Arguments) {
69	unsafe {
70		(*SERIAL_GLOBAL.get()).write_fmt(args).unwrap();
71	}
72}
73
74/// [clear_screen] removes the content but doesn't reset the cursor
75pub fn clear_screen() { CGASCREEN_GLOBAL.lock().clear(); }
76
77/// [reset_screen] also resets the cursor
78pub fn reset_screen() { CGASCREEN_GLOBAL.lock().reset(); }
79
80pub fn back_space() { CGASCREEN_GLOBAL.lock().backspace(); }
81
82pub fn print_help(s: &str, attr: u8) {
83	CGASCREEN_GLOBAL.lock().print_at_bottom(s, attr);
84}
85
86pub fn set_attr(attr: u8) { CGASCREEN_GLOBAL.lock().setattr(attr); }
87
88pub fn print_welcome() {
89	println!("--RuStuBs--");
90	println!("    _._     _,-'\"\"`-._     ~Meow");
91	println!("   (,-.`._,'(       |\\`-/|");
92	println!("       `-.-' \\ )-`( , o o)");
93	println!("             `-    \\`_`\"'-");
94}