Browse Source

Add VGA text-mode console driver

master
3moon 8 years ago
parent
commit
8aa1f15b4e
7 changed files with 195 additions and 1 deletions
  1. +14
    -0
      Cargo.lock
  2. +3
    -1
      Cargo.toml
  3. +1
    -0
      src/arch/mod.rs
  4. +1
    -0
      src/arch/x86_64/device/mod.rs
  5. +155
    -0
      src/arch/x86_64/device/vga_console.rs
  6. +1
    -0
      src/arch/x86_64/mod.rs
  7. +20
    -0
      src/macros.rs

+ 14
- 0
Cargo.lock View File

@ -3,6 +3,8 @@ name = "sparkle_os"
version = "0.1.0"
dependencies = [
"rlibc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"x86 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -179,6 +181,16 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "spin"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "volatile"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "x86"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -214,4 +226,6 @@ dependencies = [
"checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa"
"checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36"
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
"checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53"
"checksum volatile 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6633c5250f16598f92b48272265ce9f8179447f702f0ba0cb640c5be6537b0c0"
"checksum x86 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ada1976e1004a0b5999beb7403541af96637e8f439b97d86c8c9abef2e0e7d19"

+ 3
- 1
Cargo.toml View File

@ -8,4 +8,6 @@ crate-type = ["staticlib"]
[dependencies]
rlibc = "1.0"
x86 = "0.8"
spin = "0.4.5"
volatile = "0.2"
x86 = "0.8"

+ 1
- 0
src/arch/mod.rs View File

@ -0,0 +1 @@
pub mod x86_64;

+ 1
- 0
src/arch/x86_64/device/mod.rs View File

@ -0,0 +1 @@
pub mod vga_console;

+ 155
- 0
src/arch/x86_64/device/vga_console.rs View File

@ -0,0 +1,155 @@
use core::fmt;
use core::ptr::Unique;
use spin::Mutex;
use volatile::Volatile;
pub static WRITER: Mutex<Writer> = Mutex::new(Writer {
column_pos: 0, row_pos: 0,
style: CharStyle::new(Color::Cyan, Color::DarkGray),
buffer: unsafe {Unique::new(0xb8000 as *mut _)},
});
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
#[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(Clone, Copy, Debug)]
pub struct CharStyle(u8);
impl CharStyle {
const fn new(foreground: Color, background: Color) -> CharStyle {
CharStyle((background as u8) << 4 | (foreground as u8))
}
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
struct VgaChar {
ascii_char: u8,
style: CharStyle,
}
const BUFFER_HEIGHT: usize = 25;
const BUFFER_WIDTH: usize = 80;
/// Shadows the actual VGA text-mode buffer at 0xb8000.
struct Buffer {
chars: [[Volatile<VgaChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
/// Abstraction layer used to write into the VGA text buffer
pub struct Writer {
/// Current position of the 'write cursor'
row_pos: usize, column_pos: usize,
/// Current style we're writing with
style: CharStyle,
/// This is set up on initialization to shadow `0xb8000`, the VGA text-mode buffer.
buffer: Unique<Buffer>,
}
#[allow(dead_code)]
impl Writer {
pub fn write_byte(&mut self, byte: u8) {
match byte {
b'\n' => self.new_line(),
byte => {
if self.column_pos >= BUFFER_WIDTH {self.new_line();}
let row = self.row_pos;
let col = self.column_pos;
let style = self.style;
self.buffer().chars[row][col].write(VgaChar {
ascii_char: byte,
style: style,
});
self.column_pos += 1;
}
}
}
pub fn write_byte_at(&mut self, byte: u8, row: usize, col: usize) {
self.row_pos = row; self.column_pos = col;
let style = self.style;
self.buffer().chars[row][col].write(VgaChar {ascii_char: byte, style: style});
}
pub fn clear_screen(&mut self) {
let clear_style = VgaChar {ascii_char: b' ', style: self.style};
for row in 0..BUFFER_HEIGHT {
for col in 0..BUFFER_WIDTH {
self.buffer().chars[row][col].write(clear_style);
}
}
}
pub fn set_style(&mut self, style: CharStyle) {
self.style = style;
}
pub fn get_style(&self) -> CharStyle {
self.style
}
fn new_line(&mut self) {
self.column_pos = 0;
self.row_pos += 1;
if self.row_pos >= BUFFER_HEIGHT {
self.scroll();
}
}
fn clear_row(&mut self, row: usize) {
let clear_style = VgaChar {ascii_char: b' ', style: self.style};
for col in 0..BUFFER_WIDTH {
self.buffer().chars[row][col].write(clear_style);
}
}
fn scroll(&mut self){
for row in 0..(BUFFER_HEIGHT - 1) {
for col in 0..BUFFER_WIDTH {
let c = self.buffer().chars[row + 1][col].read();
self.buffer().chars[row][col].write(c);
}
}
self.clear_row(BUFFER_HEIGHT - 1);
self.column_pos = 0;
self.row_pos = BUFFER_HEIGHT - 1;
}
fn buffer(&mut self) -> &mut Buffer {
unsafe { self.buffer.as_mut() }
}
}
impl fmt::Write for Writer {
fn write_str(&mut self, s: &str) -> fmt::Result {
for byte in s.bytes() {
self.write_byte(byte);
}
Ok(())
}
}

+ 1
- 0
src/arch/x86_64/mod.rs View File

@ -0,0 +1 @@
pub mod device;

+ 20
- 0
src/macros.rs View File

@ -0,0 +1,20 @@
use core::fmt;
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ({
$crate::macros::print(format_args!($($arg)*));
});
}
pub fn print(args: fmt::Arguments) {
use core::fmt::Write;
let _ = ::arch::x86_64::device::vga_console::WRITER.lock().write_fmt(args);
}
#[macro_export]
macro_rules! println {
() => (print!("\n"));
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

Loading…
Cancel
Save