summaryrefslogtreecommitdiff
path: root/src/vga
diff options
context:
space:
mode:
authorChristian Cunningham <c@localhost>2022-08-22 20:54:54 -0700
committerChristian Cunningham <c@localhost>2022-08-22 20:54:54 -0700
commit188a08c3a340005d59d497e836993cb9349c9cbe (patch)
treea69cc6cc1ced12043b706dc62f5a1645d9061adb /src/vga
Initial state
Diffstat (limited to 'src/vga')
-rw-r--r--src/vga/.buffer.rs.swpbin0 -> 20480 bytes
-rw-r--r--src/vga/.mod.rs.swpbin0 -> 12288 bytes
-rw-r--r--src/vga/buffer.rs157
-rw-r--r--src/vga/mod.rs33
4 files changed, 190 insertions, 0 deletions
diff --git a/src/vga/.buffer.rs.swp b/src/vga/.buffer.rs.swp
new file mode 100644
index 0000000..0ce0feb
--- /dev/null
+++ b/src/vga/.buffer.rs.swp
Binary files differ
diff --git a/src/vga/.mod.rs.swp b/src/vga/.mod.rs.swp
new file mode 100644
index 0000000..6071785
--- /dev/null
+++ b/src/vga/.mod.rs.swp
Binary files differ
diff --git a/src/vga/buffer.rs b/src/vga/buffer.rs
new file mode 100644
index 0000000..34c665d
--- /dev/null
+++ b/src/vga/buffer.rs
@@ -0,0 +1,157 @@
+use super::*;
+use core::fmt;
+use volatile::Volatile;
+use crate::sync::NullLock;
+use crate::sync::interface::Mutex;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(C)]
+struct ScreenChar {
+ ascii_character: u8,
+ color_code: ColorCode,
+}
+
+const BUFFER_HEIGHT: usize = 25;
+const BUFFER_WIDTH: usize = 80;
+
+#[repr(transparent)]
+struct Buffer {
+ chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
+}
+
+pub struct VgaWriter {
+ column_position: usize,
+ color_code: ColorCode,
+ buffer: Option<&'static mut Buffer>,
+}
+
+impl VgaWriter {
+ pub fn write_byte(&mut self, byte: u8) {
+ match byte {
+ b'\n' => self.new_line(),
+ byte => {
+ if self.column_position >= BUFFER_WIDTH {
+ self.new_line();
+ }
+
+ let row = BUFFER_HEIGHT - 1;
+ let col = self.column_position;
+
+ let color_code = self.color_code;
+ if let Some(buffer) = &mut self.buffer {
+ buffer.chars[row][col].write(ScreenChar {
+ascii_character: byte,
+color_code,
+});
+ }
+ self.column_position += 1;
+ }
+ }
+ }
+
+ fn new_line(&mut self) {
+ for row in 1..BUFFER_HEIGHT {
+ for col in 0..BUFFER_WIDTH {
+ if let Some(buffer) = &mut self.buffer {
+ let character = buffer.chars[row][col].read();
+ buffer.chars[row - 1][col].write(character);
+ }
+ }
+ }
+ self.clear_row(BUFFER_HEIGHT - 1);
+ self.column_position = 0;
+ }
+
+ fn clear_row(&mut self, row: usize) {
+ let blank = ScreenChar {
+ ascii_character: b' ',
+ color_code: self.color_code,
+ };
+ for col in 0..BUFFER_WIDTH {
+ if let Some(buffer) = &mut self.buffer {
+ buffer.chars[row][col].write(blank);
+ }
+ }
+ }
+
+ pub fn write_string(&mut self, s: &str) {
+ for byte in s.bytes() {
+ match byte {
+ // printable ASCII byte or newline
+ 0x20..=0x7e | b'\n' => self.write_byte(byte),
+ // not part of printable ASCII range
+ _ => self.write_byte(0xfe),
+ }
+
+ }
+ }
+}
+
+impl NullLock<VgaWriter> {
+ #[allow(dead_code)]
+ pub fn write_byte(&self, byte: u8) {
+ self.lock(|writer| {
+ writer.write_byte(byte);
+ });
+ }
+
+ #[allow(dead_code)]
+ fn new_line(&self) {
+ self.lock(|writer| {
+ writer.new_line();
+ });
+ }
+
+ #[allow(dead_code)]
+ fn clear_row(&self, row: usize) {
+ self.lock(|writer| {
+ writer.clear_row(row);
+ });
+ }
+
+ pub fn write_string(&self, s: &str) {
+ self.lock(|writer| {
+ writer.write_string(s);
+ });
+ }
+}
+
+impl fmt::Write for VgaWriter {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.write_string(s);
+ Ok(())
+ }
+}
+
+impl NullLock<VgaWriter> {
+ pub fn init(&self) {
+ self.lock(|writer| {
+ writer.buffer = Some(unsafe { &mut *(0xb8000 as *mut Buffer) });
+ })
+ }
+}
+
+#[doc(hidden)]
+pub fn _print(args: fmt::Arguments) {
+ use core::fmt::Write;
+ WRITER.lock(|writer| {
+ writer.write_fmt(args).unwrap();
+ });
+}
+
+#[macro_export]
+macro_rules! print {
+ ($($arg:tt)*) => ($crate::vga::_print(format_args!($($arg)*)));
+}
+
+#[macro_export]
+macro_rules! println {
+ () => (print!("\n"));
+ ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*)));
+}
+
+pub static WRITER: NullLock<VgaWriter> = NullLock::new(VgaWriter {
+ column_position: 0,
+ color_code: ColorCode::new(Color::Yellow, Color::Black),
+ buffer: None,
+});
diff --git a/src/vga/mod.rs b/src/vga/mod.rs
new file mode 100644
index 0000000..13dffe0
--- /dev/null
+++ b/src/vga/mod.rs
@@ -0,0 +1,33 @@
+mod buffer;
+pub use buffer::*;
+
+#[allow(dead_code)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[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, PartialEq, Eq)]
+#[repr(transparent)]
+struct ColorCode(u8);
+
+impl ColorCode {
+ const fn new(foreground: Color, background: Color) -> ColorCode {
+ ColorCode((background as u8) << 4 | (foreground as u8))
+ }
+}