Skip to main content

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/// default print and println send output to both CGA and serial, CGA screen
30/// synchronized and should NEVER be used in prologue.
31/// use `sprint!` and `sprintln!` instead.
32#[macro_export]
33macro_rules! print {
34    ($($arg:tt)*) => {{
35		$crate::io::_cga_print(format_args!($($arg)*));
36		$crate::io::_serial_print(format_args!($($arg)*));
37	}};
38}
39pub(crate) use print;
40
41/// CGA screen println, synchronized. NEVER use in prologue
42#[macro_export]
43macro_rules! println {
44    () => ($crate::print!("\n"));
45    ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*)));
46}
47pub(crate) use println;
48
49/// serial (0x3f8 for qemu) print, not synchronized. can use in prologue
50#[macro_export]
51macro_rules! sprint {
52    ($($arg:tt)*) => ($crate::io::_serial_print(format_args!($($arg)*)));
53}
54pub(crate) use sprint;
55
56#[macro_export]
57/// serial (0x3f8 for qemu) println, not synchronized. can use in prologue
58macro_rules! sprintln{
59    () => ($crate::sprint!("\n"));
60    ($($arg:tt)*) => (sprint!("{}\n", format_args!($($arg)*)));
61}
62pub(crate) use sprintln;
63
64pub fn read_key() -> Key {
65	use crate::proc::sync::semaphore::Semaphore;
66	KEY_BUFFER.p().unwrap()
67}
68
69/// CGA screen print backend, synchronized. NEVER use in prologue
70pub fn _cga_print(args: Arguments) {
71	CGASCREEN_GLOBAL.lock().write_fmt(args).unwrap();
72}
73
74/// serial print backend, not synchronized. Expect artifects when multithreaded.
75pub fn _serial_print(args: Arguments) {
76	unsafe {
77		(*SERIAL_GLOBAL.get()).write_fmt(args).unwrap();
78	}
79}
80
81/// [clear_screen] removes the content but doesn't reset the cursor
82pub fn clear_screen() { CGASCREEN_GLOBAL.lock().clear(); }
83
84/// [reset_screen] also resets the cursor
85pub fn reset_screen() { CGASCREEN_GLOBAL.lock().reset(); }
86
87pub fn back_space() { CGASCREEN_GLOBAL.lock().backspace(); }
88
89pub fn print_help(s: &str, attr: u8) {
90	CGASCREEN_GLOBAL.lock().print_at_bottom(s, attr);
91}
92
93pub fn set_attr(attr: u8) { CGASCREEN_GLOBAL.lock().setattr(attr); }
94
95pub fn print_welcome() {
96	println!("--RuStuBs--");
97	println!("    _._     _,-'\"\"`-._     ~Meow");
98	println!("   (,-.`._,'(       |\\`-/|");
99	println!("       `-.-' \\ )-`( , o o)");
100	println!("             `-    \\`_`\"'-");
101}