You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
2.5 KiB
101 lines
2.5 KiB
use spin::Mutex;
|
|
use core::ptr::Unique;
|
|
use volatile::Volatile;
|
|
use x86_64::instructions::port::{outw, outb};
|
|
use consts::KERNEL_OFFSET;
|
|
|
|
pub const VGA_BUFFER: Unique<VgaBuffer> = unsafe {
|
|
Unique::new_unchecked((KERNEL_OFFSET + 0xb8000) as *mut _)
|
|
};
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
#[repr(u8)]
|
|
pub enum Color {
|
|
Black = 0,
|
|
Blue = 1,
|
|
Green = 2,
|
|
Cyan = 3,
|
|
Red = 4,
|
|
Magenta = 5,
|
|
Brown = 6,
|
|
LightGray = 7,
|
|
DarkGray = 8,
|
|
LightBlue = 9,
|
|
LightGreen = 10,
|
|
LightCyan = 11,
|
|
LightRed = 12,
|
|
Pink = 13,
|
|
Yellow = 14,
|
|
White = 15,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
struct ColorCode(u8);
|
|
|
|
impl ColorCode {
|
|
const fn new(foreground: Color, background: Color) -> ColorCode {
|
|
ColorCode((background as u8) << 4 | (foreground as u8))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[repr(C)]
|
|
pub struct ScreenChar {
|
|
ascii_char: u8,
|
|
color_code: ColorCode,
|
|
}
|
|
|
|
impl ScreenChar {
|
|
pub const fn new(ascii_char: u8, foreground_color: Color, background_color: Color) -> Self {
|
|
ScreenChar {
|
|
ascii_char,
|
|
color_code: ColorCode::new(foreground_color, background_color)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub const BUFFER_HEIGHT: usize = 25;
|
|
pub const BUFFER_WIDTH: usize = 80;
|
|
|
|
pub struct VgaBuffer {
|
|
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
|
}
|
|
|
|
impl VgaBuffer {
|
|
pub fn clear(&mut self) {
|
|
let blank = ScreenChar::new(b' ', Color::LightGray, Color::Black);
|
|
for row in 0 .. BUFFER_HEIGHT {
|
|
for col in 0..BUFFER_WIDTH {
|
|
self.chars[row][col].write(blank);
|
|
}
|
|
}
|
|
}
|
|
pub fn write(&mut self, row: usize, col: usize, screen_char: ScreenChar) {
|
|
self.chars[row][col].write(screen_char);
|
|
}
|
|
pub fn read(&self, row: usize, col: usize) -> ScreenChar {
|
|
self.chars[row][col].read()
|
|
}
|
|
pub fn set_cursor_at(&self, row: usize, col: usize) {
|
|
assert!(row < BUFFER_HEIGHT && col < BUFFER_WIDTH);
|
|
let pos = row * BUFFER_WIDTH + col;
|
|
unsafe {
|
|
// Reference: Rustboot project
|
|
outw(0x3D4, 15u16); // WARNING verify should be u16
|
|
outb(0x3D5, pos as u8);
|
|
outw(0x3D4, 14u16);
|
|
outb(0x3D5, (pos >> 8) as u8);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
#[test]
|
|
fn print_something() {
|
|
let vga = unsafe {&mut *VGA_BUFFER};
|
|
vga.clear();
|
|
vga.write(0, 0, ScreenChar::new('h', Color::LightGray, Color::Black));
|
|
}
|
|
} |