context::Context handles multiple Writers, Writer handles cursor
This commit is contained in:
parent
66d75c0895
commit
67dbf5d9b3
7 changed files with 119 additions and 123 deletions
44
kernel-rs/src/context.rs
Normal file
44
kernel-rs/src/context.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<Buffer>,
|
||||
pub struct Writer<T: AsMut<[u8]>> {
|
||||
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<T: AsMut<[u8]>> Writer<T> {
|
||||
pub fn new(slice: T) -> Writer<T> {
|
||||
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<T: AsMut<[u8]>> fmt::Write for Writer<T> {
|
||||
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<ScreenChar>; 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<BufferAction>;
|
||||
// fn load();
|
||||
// fn unload() -> ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<vga::BufferAction> {
|
||||
Some(vga::BufferAction::WRITE_BYTE(ascii))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue