diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs new file mode 100644 index 00000000..cb61b08f --- /dev/null +++ b/kernel-rs/src/context.rs @@ -0,0 +1,44 @@ +extern crate core; + +use vga; + + +pub struct Context { + pub current_term: u8, + pub vga1: vga::Writer<&'static mut [u8]>, + pub vga2: vga::Writer<&'static mut [u8]>, +} + +impl Context { + pub fn new() -> Context { + let slice1 = unsafe { + core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) + }; + + let slice2 = unsafe { + core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) + }; + + Context { + current_term: 0, + vga1: vga::Writer::new(slice1), + vga2: vga::Writer::new(slice2), + } + } + + pub fn switch_term(&mut self) { + self.current_term = { + if self.current_term == 0 { 1 } + else { 0 } + }; + } + + pub fn current_term(&mut self) -> &mut vga::Writer<&'static mut [u8]>{ + if self.current_term == 0 { + &mut self.vga1 + } else { + &mut self.vga2 + } + } +} + diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 09b4f3be..7653340c 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,32 +1,30 @@ +extern crate core; + +use cpuio; +use context; +// use vga::color::{Color, ColorCode}; + pub static SCANCODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; -use vga; -use cpuio; -use vga::buffer::{Writer, Screen}; - -pub fn kbd_loop(writer: &mut Writer) { - let terminal_one: vga::terminal::Terminal = vga::Screen::new(); +pub fn kbd_callback(context: &mut context::Context) { // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); - let control = unsafe { cpuio::inb(0x64) }; if (control & 1) == 1 { let scancode = unsafe { cpuio::inb(0x60) }; - - //TODO current_screen() with mutex lock? - let current_screen = terminal_one; - //TODO implement logic to translate scancode->ascii match self::SCANCODE_TO_ASCII.get(scancode as usize) { + Some(&b'1') => { + context.switch_term(); + context.current_term().flush(); + } Some(ascii) => { - //TODO screen switching logic - // if let Some(action) = Screen::keypress(current_screen, *ascii as char) { - if let Some(action) = current_screen.keypress(*ascii as char) { - writer.action(action); - } + let mut terminal = context.current_term(); + terminal.keypress(*ascii); }, None =>{}, // None => println!("nokey ctrl {:x}", control), } + // current_screen.flush(); } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 636dbbfb..51bb83a1 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -14,6 +14,7 @@ mod vga; #[allow(dead_code)] mod cpuio; mod keyboard; +mod context; #[no_mangle] pub extern fn kmain() -> ! { @@ -40,7 +41,11 @@ pub extern fn kmain() -> ! { // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); // println!(">> Kernel startup..."); - unsafe { loop { keyboard::kbd_loop(&mut vga::buffer::WRITER); } }; + let mut context = context::Context::new(); + + loop { + keyboard::kbd_callback(&mut context); + } } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index 34617c44..7461d9ca 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use volatile::Volatile; - use super::{Color, ColorCode}; -use core::ptr::Unique; -use core::fmt; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -20,93 +16,83 @@ struct ScreenChar { color_code: ColorCode, } -const BUFFER_HEIGHT: usize = 25; -const BUFFER_WIDTH: usize = 80; +const BUFFER_ROWS: usize = 25; +const BUFFER_COLS: usize = 80 * 2; -pub struct Writer { - pub column_position: usize, - pub color_code: ColorCode, - vgabuffer: Unique, +pub struct Writer> { + pub position: usize, + color_code: ColorCode, + slice: T, + buffer: [u8; BUFFER_ROWS * BUFFER_COLS], } -// Writer is the default object to use to print to screen -pub static mut WRITER: Writer = Writer { - column_position: 0, - color_code: ColorCode::new(Color::White, Color::Black), - vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, -}; - -// blank is black for everyone, could make screens choose this -static BLANK: ScreenChar = ScreenChar { - ascii_character: b' ', - color_code: ColorCode::new(Color::White, Color::Black), -}; - -impl Writer { - pub fn action(&mut self, action: BufferAction) { - match action { - BufferAction::WRITE_BYTE(ascii) => self.write_byte(ascii as u8), - BufferAction::CLEAR_SCREEN => self.reset_screen(), +impl> Writer { + pub fn new(slice: T) -> Writer { + Writer { + slice, + position: 0, + color_code: ColorCode::new(Color::White, Color::Black), + buffer: [0; BUFFER_ROWS * BUFFER_COLS], } } - pub fn reset_screen(&mut self) - { - let color_code = self.color_code; - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: b' ', - color_code, - }); - } - } - self.column_position = 0; + pub fn keypress(&mut self, ascii: u8) { + self.write_byte(ascii); } pub fn write_byte(&mut self, byte: u8) { + let i = self.position; + match byte { - b'\n' => { self.new_line(); } + + b'\n' => { + //reset cursor + self.buffer[self.position + 1] = ColorCode::new(Color::White, Color::Black).0; + let current_line = self.position / (BUFFER_COLS); + self.position = (current_line + 1) * BUFFER_COLS; + } 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; - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: byte, - color_code: color_code, - }); - self.column_position += 1; + self.buffer[i] = byte; + self.buffer[i + 1] = self.color_code.0; + self.position += 2; } } + + if self.position >= self.buffer.len() { + self.scroll(); + } + + // cursor + self.buffer[self.position] = b' '; + self.buffer[self.position + 1] = ColorCode::new(Color::LightGray, Color::LightGray).0; + + self.flush(); } - fn buffer(&mut self) -> &mut Buffer { - unsafe { self.vgabuffer.as_mut() } + pub fn flush(&mut self) { + self.slice.as_mut().clone_from_slice(&self.buffer); } - fn new_line(&mut self) { - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - let buffer = self.buffer(); - let character = buffer.chars[row][col].read(); - buffer.chars[row - 1][col].write(character); + fn scroll(&mut self) { + + for row in 1..BUFFER_ROWS { + for col in 0..BUFFER_COLS { + let prev_position = ((row - 1) * BUFFER_COLS) + col; + let current_position = (row * BUFFER_COLS) + col; + self.buffer[prev_position] = self.buffer[current_position]; } } - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - fn clear_row(&mut self, row: usize) { - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(BLANK); + for col in 0..BUFFER_COLS/2 { + self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; } + + self.position = (BUFFER_ROWS - 1) * BUFFER_COLS; } } -impl fmt::Write for Writer { +use core::fmt; +impl> fmt::Write for Writer { fn write_str(&mut self, s: &str) -> ::core::fmt::Result { for byte in s.bytes() { self.write_byte(byte) @@ -114,20 +100,3 @@ impl fmt::Write for Writer { Ok(()) } } - -struct Buffer { - chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], -} - -pub enum BufferAction { - WRITE_BYTE(char), - CLEAR_SCREEN, -} - -/// Implementors of this trait can use the vga screen for any purpose -pub trait Screen { - fn new() -> Self; // - fn keypress(self, keycode: char) -> Option; - // fn load(); - // fn unload() -> ; -} diff --git a/kernel-rs/src/vga/color.rs b/kernel-rs/src/vga/color.rs index dc24b1ef..91bf39c4 100644 --- a/kernel-rs/src/vga/color.rs +++ b/kernel-rs/src/vga/color.rs @@ -21,7 +21,7 @@ pub enum Color { } #[derive(Debug, Clone, Copy)] -pub struct ColorCode(u8); +pub struct ColorCode(pub u8); impl ColorCode { pub const fn new(foreground: Color, background: Color) -> ColorCode { diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 2a7984e3..6d491ba0 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,10 +1,9 @@ #[macro_use] pub mod buffer; pub mod color; -pub mod terminal; pub use self::color::{Color, ColorCode}; -pub use self::buffer::{WRITER, Screen, BufferAction}; +pub use self::buffer::{Writer}; // use self::buffer::Writer; // use core::fmt; diff --git a/kernel-rs/src/vga/terminal.rs b/kernel-rs/src/vga/terminal.rs deleted file mode 100644 index 0f1fcb9a..00000000 --- a/kernel-rs/src/vga/terminal.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! terminal.rs implements a basic cursor terminal using the vga::buffer module - -use super::{Color, ColorCode}; -use vga; - -// cursor is lightgray for everyone -static CURSOR: ColorCode = ColorCode::new(Color::LightGray, Color::White); - -pub struct Terminal { } - -impl vga::Screen for Terminal { - fn new() -> Terminal { - Terminal { } - } - - fn keypress(self, ascii: char) -> Option { - Some(vga::BufferAction::WRITE_BYTE(ascii)) - } -}