diff --git a/Makefile b/Makefile index 2df2be4..315820d 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,11 @@ else ifneq ($(kvm),no) QEMUFLAGS+=-enable-kvm -cpu host endif + ifeq ($(net),no) + QEMUFLAGS+=-net none + else + QEMUFLAGS+=-net nic,model=e1000 -net user -net dump,file=$(KBUILD)/network.pcap + endif ifeq ($(storage),usb) QEMUFLAGS+=-device usb-ehci,id=flash_bus -drive id=flash_drive,file=$(KBUILD)/harddrive.bin,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 else @@ -226,6 +231,7 @@ filesystem/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib rm $@.d drivers: \ + filesystem/bin/e1000d \ filesystem/bin/ps2d \ filesystem/bin/vesad diff --git a/drivers/ahcid/Cargo.toml b/drivers/ahcid/Cargo.toml index 2bc8fa8..80725d7 100644 --- a/drivers/ahcid/Cargo.toml +++ b/drivers/ahcid/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" [dependencies] bitflags = "*" +dma = { path = "../dma/" } io = { path = "../io/" } spin = "*" syscall = { path = "../../syscall/" } diff --git a/drivers/ahcid/src/ahci/disk.rs b/drivers/ahcid/src/ahci/disk.rs index 5f37c01..f28d5e8 100644 --- a/drivers/ahcid/src/ahci/disk.rs +++ b/drivers/ahcid/src/ahci/disk.rs @@ -1,8 +1,8 @@ use std::ptr; +use dma::Dma; use syscall::error::Result; -use super::dma::Dma; use super::hba::{HbaPort, HbaCmdTable, HbaCmdHeader}; pub struct Disk { diff --git a/drivers/ahcid/src/ahci/hba.rs b/drivers/ahcid/src/ahci/hba.rs index 3f6748c..43d29e1 100644 --- a/drivers/ahcid/src/ahci/hba.rs +++ b/drivers/ahcid/src/ahci/hba.rs @@ -1,12 +1,11 @@ -use io::{Io, Mmio}; - use std::mem::size_of; use std::ops::DerefMut; use std::{ptr, u32}; +use dma::Dma; +use io::{Io, Mmio}; use syscall::error::{Error, Result, EIO}; -use super::dma::Dma; use super::fis::{FisType, FisRegH2D}; const ATA_CMD_READ_DMA_EXT: u8 = 0x25; diff --git a/drivers/ahcid/src/ahci/mod.rs b/drivers/ahcid/src/ahci/mod.rs index 9d594de..b4e1465 100644 --- a/drivers/ahcid/src/ahci/mod.rs +++ b/drivers/ahcid/src/ahci/mod.rs @@ -4,7 +4,6 @@ use self::disk::Disk; use self::hba::{HbaMem, HbaPortType}; pub mod disk; -pub mod dma; pub mod fis; pub mod hba; diff --git a/drivers/ahcid/src/main.rs b/drivers/ahcid/src/main.rs index 07ca38e..7f5ccda 100644 --- a/drivers/ahcid/src/main.rs +++ b/drivers/ahcid/src/main.rs @@ -3,6 +3,7 @@ #[macro_use] extern crate bitflags; +extern crate dma; extern crate io; extern crate spin; extern crate syscall; diff --git a/drivers/dma/Cargo.toml b/drivers/dma/Cargo.toml new file mode 100644 index 0000000..e05c929 --- /dev/null +++ b/drivers/dma/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dma" +version = "0.1.0" + +[dependencies] +syscall = { path = "../../syscall/" } diff --git a/drivers/ahcid/src/ahci/dma.rs b/drivers/dma/src/lib.rs similarity index 95% rename from drivers/ahcid/src/ahci/dma.rs rename to drivers/dma/src/lib.rs index 91258b8..fa8e3d1 100644 --- a/drivers/ahcid/src/ahci/dma.rs +++ b/drivers/dma/src/lib.rs @@ -1,7 +1,11 @@ +#![feature(question_mark)] + +extern crate syscall; + use std::{mem, ptr}; use std::ops::{Deref, DerefMut}; -use syscall::{self, Result}; +use syscall::Result; struct PhysBox { address: usize, diff --git a/drivers/e1000d/Cargo.toml b/drivers/e1000d/Cargo.toml new file mode 100644 index 0000000..eacd0d1 --- /dev/null +++ b/drivers/e1000d/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rtl8139d" +version = "0.1.0" + +[dependencies] +bitflags = "*" +dma = { path = "../dma/" } +io = { path = "../io/" } +spin = "*" +syscall = { path = "../../syscall/" } diff --git a/drivers/e1000d/src/main.rs b/drivers/e1000d/src/main.rs new file mode 100644 index 0000000..9ae8b04 --- /dev/null +++ b/drivers/e1000d/src/main.rs @@ -0,0 +1,41 @@ +#![feature(asm)] + +extern crate dma; +extern crate syscall; + +use std::{env, thread}; +use std::fs::File; +use std::io::{Read, Write}; + +use syscall::{iopl, physmap, physunmap, Packet, MAP_WRITE}; + +fn main() { + let mut args = env::args().skip(1); + + let bar_str = args.next().expect("e1000d: no address provided"); + let bar = usize::from_str_radix(&bar_str, 16).expect("e1000d: failed to parse address"); + + let irq_str = args.next().expect("e1000d: no irq provided"); + let irq = irq_str.parse::().expect("e1000d: failed to parse irq"); + + thread::spawn(move || { + unsafe { + iopl(3).expect("e1000d: failed to get I/O permission"); + asm!("cli" :::: "intel", "volatile"); + } + + let address = unsafe { physmap(bar, 4096, MAP_WRITE).expect("e1000d: failed to map address") }; + { + println!("e1000d {:X}", bar); + let mut socket = File::create(":network").expect("e1000d: failed to create network scheme"); + //let scheme = DiskScheme::new(ahci::disks(address, irq)); + loop { + let mut packet = Packet::default(); + socket.read(&mut packet).expect("e1000d: failed to read network scheme"); + //scheme.handle(&mut packet); + socket.write(&mut packet).expect("e1000d: failed to read network scheme"); + } + } + unsafe { let _ = physunmap(address); } + }); +} diff --git a/drivers/ps2d/src/keyboard.rs b/drivers/ps2d/src/keyboard.rs index d50557e..8eb2858 100644 --- a/drivers/ps2d/src/keyboard.rs +++ b/drivers/ps2d/src/keyboard.rs @@ -36,6 +36,15 @@ pub fn keyboard() { rshift = pressed; } else if pressed { match scancode { + f @ 0x3B ... 0x44 => { // F1 through F10 + input.write(&[(f - 0x3B) + 0xF4]).unwrap(); + }, + 0x57 => { // F11 + input.write(&[0xFE]).unwrap(); + }, + 0x58 => { // F12 + input.write(&[0xFF]).unwrap(); + }, 0x47 => { // Home input.write(b"\x1B[H").unwrap(); }, @@ -69,7 +78,7 @@ pub fn keyboard() { _ => { let c = if ctrl { match keymap::get_char(scancode, false) { - c @ 'a' ... 'z' => (c as u8 - b'a' + b'\x01') as char, + c @ 'a' ... 'z' => ((c as u8 - b'a') + b'\x01') as char, c => c } } else { diff --git a/drivers/vesad/Cargo.toml b/drivers/vesad/Cargo.toml index cf0c2fa..ebfdf0b 100644 --- a/drivers/vesad/Cargo.toml +++ b/drivers/vesad/Cargo.toml @@ -4,5 +4,8 @@ version = "0.1.0" [dependencies] ransid = { git = "https://github.com/redox-os/ransid.git", branch = "new_api" } -rusttype = { git = "https://github.com/dylanede/rusttype.git" } +rusttype = { git = "https://github.com/dylanede/rusttype.git", optional = true } syscall = { path = "../../syscall/" } + +[features] +default = [] diff --git a/drivers/vesad/src/console.rs b/drivers/vesad/src/console.rs new file mode 100644 index 0000000..ea3546d --- /dev/null +++ b/drivers/vesad/src/console.rs @@ -0,0 +1,3 @@ +pub struct Text { + +} diff --git a/drivers/vesad/src/display.rs b/drivers/vesad/src/display.rs index 064321f..a21be24 100644 --- a/drivers/vesad/src/display.rs +++ b/drivers/vesad/src/display.rs @@ -1,7 +1,8 @@ #[cfg(feature="rusttype")] extern crate rusttype; -use std::cmp; +use alloc::heap; +use std::{cmp, slice}; use primitive::{fast_set32, fast_set64, fast_copy, fast_copy64}; @@ -11,6 +12,15 @@ use self::rusttype::{Font, FontCollection, Scale, point}; #[cfg(not(feature="rusttype"))] static FONT: &'static [u8] = include_bytes!("../../../res/fonts/unifont.font"); +#[cfg(feature="rusttype")] +static FONT: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono.ttf"); +#[cfg(feature="rusttype")] +static FONT_BOLD: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono-Bold.ttf"); +#[cfg(feature="rusttype")] +static FONT_BOLD_ITALIC: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono-BoldOblique.ttf"); +#[cfg(feature="rusttype")] +static FONT_ITALIC: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono-Oblique.ttf"); + /// A display #[cfg(not(feature="rusttype"))] pub struct Display { @@ -39,26 +49,32 @@ pub struct Display { impl Display { #[cfg(not(feature="rusttype"))] - pub fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display { + pub fn new(width: usize, height: usize, onscreen: usize) -> Display { + let size = width * height; + let offscreen = unsafe { heap::allocate(size * 4, 4096) }; + unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; Display { width: width, height: height, - onscreen: onscreen, - offscreen: offscreen + onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, + offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } } } #[cfg(feature="rusttype")] - pub fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display { + pub fn new(width: usize, height: usize, onscreen: usize) -> Display { + let size = width * height; + let offscreen = unsafe { heap::allocate(size * 4, 4096) }; + unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; Display { width: width, height: height, - onscreen: onscreen, - offscreen: offscreen, - font: FontCollection::from_bytes(include_bytes!("../../../res/fonts/DejaVuSansMono.ttf")).into_font().unwrap(), - font_bold: FontCollection::from_bytes(include_bytes!("../../../res/fonts/DejaVuSansMono-Bold.ttf")).into_font().unwrap(), - font_bold_italic: FontCollection::from_bytes(include_bytes!("../../../res/fonts/DejaVuSansMono-BoldOblique.ttf")).into_font().unwrap(), - font_italic: FontCollection::from_bytes(include_bytes!("../../../res/fonts/DejaVuSansMono-Oblique.ttf")).into_font().unwrap() + onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, + offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }, + font: FontCollection::from_bytes(FONT).into_font().unwrap(), + font_bold: FontCollection::from_bytes(FONT_BOLD).into_font().unwrap(), + font_bold_italic: FontCollection::from_bytes(FONT_BOLD_ITALIC).into_font().unwrap(), + font_italic: FontCollection::from_bytes(FONT_ITALIC).into_font().unwrap() } } diff --git a/drivers/vesad/src/main.rs b/drivers/vesad/src/main.rs index c6247a2..57a13b3 100644 --- a/drivers/vesad/src/main.rs +++ b/drivers/vesad/src/main.rs @@ -4,200 +4,22 @@ #![feature(question_mark)] extern crate alloc; -extern crate ransid; extern crate syscall; -use std::cell::RefCell; -use std::collections::{BTreeSet, VecDeque}; use std::fs::File; use std::io::{Read, Write}; -use std::{slice, thread}; -use ransid::{Console, Event}; -use syscall::{physmap, physunmap, Packet, Result, Scheme, EVENT_READ, MAP_WRITE, MAP_WRITE_COMBINE}; +use std::thread; +use syscall::{physmap, physunmap, Packet, Scheme, MAP_WRITE, MAP_WRITE_COMBINE}; -use display::Display; use mode_info::VBEModeInfo; use primitive::fast_set64; +use scheme::DisplayScheme; pub mod display; pub mod mode_info; pub mod primitive; - -struct DisplayScheme { - console: RefCell, - display: RefCell, - changed: RefCell>, - input: RefCell>, - end_of_input: RefCell, - cooked: RefCell>, - requested: RefCell -} - -impl DisplayScheme { - fn event(&self, event: Event) { - let mut display = self.display.borrow_mut(); - let mut changed = self.changed.borrow_mut(); - - match event { - Event::Char { x, y, c, color, bold, .. } => { - display.char(x * 8, y * 16, c, color.data, bold, false); - changed.insert(y); - }, - Event::Rect { x, y, w, h, color } => { - display.rect(x * 8, y * 16, w * 8, h * 16, color.data); - for y2 in y..y + h { - changed.insert(y2); - } - }, - Event::Scroll { rows, color } => { - display.scroll(rows * 16, color.data); - for y in 0..display.height/16 { - changed.insert(y); - } - } - } - } - - fn sync(&self) { - let mut display = self.display.borrow_mut(); - let mut changed = self.changed.borrow_mut(); - - let width = display.width; - for change in changed.iter() { - display.sync(0, change * 16, width, 16); - } - changed.clear(); - } -} - -impl Scheme for DisplayScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - if path == b"input" { - Ok(1) - } else { - Ok(0) - } - } - - fn dup(&self, id: usize) -> Result { - Ok(id) - } - - fn fevent(&self, _id: usize, flags: usize) -> Result { - *self.requested.borrow_mut() = flags; - println!("fevent {:X}", flags); - Ok(0) - } - - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { - let path_str = if id == 1 { - format!("display:input") - } else { - let console = self.console.borrow(); - format!("display:{}/{}", console.w, console.h) - }; - - let path = path_str.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&self, id: usize) -> Result { - if id == 1 { - - } else { - self.sync(); - } - - Ok(0) - } - - fn read(&self, _id: usize, buf: &mut [u8]) -> Result { - let mut i = 0; - let mut input = self.input.borrow_mut(); - while i < buf.len() && ! input.is_empty() { - buf[i] = input.pop_front().unwrap(); - i += 1; - } - if i == 0 { - *self.end_of_input.borrow_mut() = false; - } - Ok(i) - } - - fn write(&self, id: usize, buf: &[u8]) -> Result { - if id == 1 { - if self.console.borrow().raw_mode { - for &b in buf.iter() { - self.input.borrow_mut().push_back(b); - } - } else { - for &b in buf.iter() { - match b { - b'\x03' => { - *self.end_of_input.borrow_mut() = true; - self.write(0, b"^C\n")?; - }, - b'\x08' | b'\x7F' => { - if let Some(_c) = self.cooked.borrow_mut().pop_back() { - self.write(0, b"\x08")?; - } - }, - b'\n' | b'\r' => { - self.cooked.borrow_mut().push_back(b); - while let Some(c) = self.cooked.borrow_mut().pop_front() { - self.input.borrow_mut().push_back(c); - } - self.write(0, b"\n")?; - }, - _ => { - self.cooked.borrow_mut().push_back(b); - self.write(0, &[b])?; - } - } - } - } - Ok(buf.len()) - } else { - let mut console = self.console.borrow_mut(); - if console.cursor && console.x < console.w && console.y < console.h { - self.event(Event::Rect { - x: console.x, - y: console.y, - w: 1, - h: 1, - color: console.background - }); - } - console.write(buf, |event| { - self.event(event); - }); - if console.cursor && console.x < console.w && console.y < console.h { - self.event(Event::Rect { - x: console.x, - y: console.y, - w: 1, - h: 1, - color: console.foreground - }); - } - if ! console.raw_mode { - self.sync(); - } - Ok(buf.len()) - } - } - - fn close(&self, _id: usize) -> Result { - Ok(0) - } -} +pub mod scheme; +pub mod screen; fn main() { let width; @@ -220,58 +42,42 @@ fn main() { let size = width * height; - let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") }; + let onscreen = unsafe { physmap(physbaseptr, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") }; unsafe { fast_set64(onscreen as *mut u64, 0, size/2) }; - let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) }; - unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; + let scheme = DisplayScheme::new(width, height, onscreen); - let scheme = DisplayScheme { - console: RefCell::new(Console::new(width/8, height/16)), - display: RefCell::new(Display::new(width, height, - unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, - unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } - )), - changed: RefCell::new(BTreeSet::new()), - input: RefCell::new(VecDeque::new()), - end_of_input: RefCell::new(false), - cooked: RefCell::new(VecDeque::new()), - requested: RefCell::new(0) - }; - - let mut blocked = VecDeque::new(); + let mut blocked = Vec::new(); loop { let mut packet = Packet::default(); socket.read(&mut packet).expect("vesad: failed to read display scheme"); //println!("vesad: {:?}", packet); // If it is a read packet, and there is no data, block it. Otherwise, handle packet - let mut block = false; - if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.input.borrow().is_empty() { - if ! *scheme.end_of_input.borrow() { - block = true; - } - } - - if block { - blocked.push_back(packet); + if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.will_block(packet.b) { + blocked.push(packet); } else { scheme.handle(&mut packet); socket.write(&packet).expect("vesad: failed to write display scheme"); } // If there are blocked readers, and data is available, handle them - while ! scheme.input.borrow().is_empty() || *scheme.end_of_input.borrow() { - if let Some(mut packet) = blocked.pop_front() { - scheme.handle(&mut packet); - socket.write(&packet).expect("vesad: failed to write display scheme"); - } else { - break; + { + let mut i = 0; + while i < blocked.len() { + if ! scheme.will_block(blocked[i].b) { + let mut packet = blocked.remove(i); + scheme.handle(&mut packet); + socket.write(&packet).expect("vesad: failed to write display scheme"); + } else { + i += 1; + } } } // If there are requested events, and data is available, send a notification - if (! scheme.input.borrow().is_empty() || *scheme.end_of_input.borrow()) && *scheme.requested.borrow() & EVENT_READ == EVENT_READ { + /* TODO + if (! scheme.screen.borrow().input.is_empty() || scheme.screen.borrow().end_of_input) && scheme.screen.borrow().requested & EVENT_READ == EVENT_READ { let event_packet = Packet { id: 0, pid: 0, @@ -280,10 +86,11 @@ fn main() { a: syscall::number::SYS_FEVENT, b: 0, c: EVENT_READ, - d: scheme.input.borrow().len() + d: scheme.screen.borrow().input.len() }; socket.write(&event_packet).expect("vesad: failed to write display scheme"); } + */ } }); } diff --git a/drivers/vesad/src/scheme.rs b/drivers/vesad/src/scheme.rs new file mode 100644 index 0000000..4c9155d --- /dev/null +++ b/drivers/vesad/src/scheme.rs @@ -0,0 +1,143 @@ +use std::cell::{Cell, RefCell}; +use std::collections::BTreeMap; +use std::str; + +use syscall::{Result, Error, EBADF, ENOENT, Scheme}; + +use display::Display; +use screen::TextScreen; + +pub struct DisplayScheme { + width: usize, + height: usize, + onscreen: usize, + active: Cell, + screens: RefCell> +} + +impl DisplayScheme { + pub fn new(width: usize, height: usize, onscreen: usize) -> DisplayScheme { + let mut screens = BTreeMap::new(); + for i in 1..7 { + screens.insert(i, TextScreen::new(Display::new(width, height, onscreen))); + } + + DisplayScheme { + width: width, + height: height, + onscreen: onscreen, + active: Cell::new(1), + screens: RefCell::new(screens) + } + } + + pub fn will_block(&self, id: usize) -> bool { + let screens = self.screens.borrow(); + if let Some(screen) = screens.get(&id) { + screen.will_block() + } else { + false + } + } +} + +impl Scheme for DisplayScheme { + fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { + if path == b"input" { + Ok(0) + } else { + let path_str = str::from_utf8(path).unwrap_or(""); + let id = path_str.parse::().unwrap_or(0); + if self.screens.borrow().contains_key(&id) { + Ok(id) + } else { + Err(Error::new(ENOENT)) + } + } + } + + fn dup(&self, id: usize) -> Result { + Ok(id) + } + + fn fevent(&self, id: usize, flags: usize) -> Result { + let mut screens = self.screens.borrow_mut(); + if let Some(mut screen) = screens.get_mut(&id) { + println!("fevent {:X}", flags); + screen.requested = flags; + Ok(0) + } else { + Err(Error::new(EBADF)) + } + } + + fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { + let screens = self.screens.borrow(); + let path_str = if id == 0 { + format!("display:input") + } else if let Some(screen) = screens.get(&id) { + format!("display:{}/{}/{}", id, screen.console.w, screen.console.h) + } else { + return Err(Error::new(EBADF)); + }; + + let path = path_str.as_bytes(); + + let mut i = 0; + while i < buf.len() && i < path.len() { + buf[i] = path[i]; + i += 1; + } + + Ok(i) + } + + fn fsync(&self, id: usize) -> Result { + let mut screens = self.screens.borrow_mut(); + if let Some(mut screen) = screens.get_mut(&id) { + if id == self.active.get() { + screen.sync(); + } + Ok(0) + } else { + Err(Error::new(EBADF)) + } + } + + fn read(&self, id: usize, buf: &mut [u8]) -> Result { + let mut screens = self.screens.borrow_mut(); + if let Some(mut screen) = screens.get_mut(&id) { + screen.read(buf) + } else { + Err(Error::new(EBADF)) + } + } + + fn write(&self, id: usize, buf: &[u8]) -> Result { + let mut screens = self.screens.borrow_mut(); + if id == 0 { + if buf.len() == 1 && buf[0] >= 0xF4 { + let new_active = (buf[0] - 0xF4) as usize + 1; + if let Some(mut screen) = screens.get_mut(&new_active) { + self.active.set(new_active); + screen.redraw(); + } + Ok(1) + } else { + if let Some(mut screen) = screens.get_mut(&self.active.get()) { + screen.input(buf) + } else { + Err(Error::new(EBADF)) + } + } + } else if let Some(mut screen) = screens.get_mut(&id) { + screen.write(buf, id == self.active.get()) + } else { + Err(Error::new(EBADF)) + } + } + + fn close(&self, _id: usize) -> Result { + Ok(0) + } +} diff --git a/drivers/vesad/src/screen/graphic.rs b/drivers/vesad/src/screen/graphic.rs new file mode 100644 index 0000000..9e6b71a --- /dev/null +++ b/drivers/vesad/src/screen/graphic.rs @@ -0,0 +1 @@ +pub struct GraphicScreen; diff --git a/drivers/vesad/src/screen/mod.rs b/drivers/vesad/src/screen/mod.rs new file mode 100644 index 0000000..01e1583 --- /dev/null +++ b/drivers/vesad/src/screen/mod.rs @@ -0,0 +1,10 @@ +pub use self::graphic::GraphicScreen; +pub use self::text::TextScreen; + +mod graphic; +mod text; + +pub enum Screen { + Graphic(GraphicScreen), + Text(TextScreen) +} diff --git a/drivers/vesad/src/screen/text.rs b/drivers/vesad/src/screen/text.rs new file mode 100644 index 0000000..bf187b7 --- /dev/null +++ b/drivers/vesad/src/screen/text.rs @@ -0,0 +1,149 @@ +extern crate ransid; + +use std::collections::{BTreeSet, VecDeque}; + +use self::ransid::{Console, Event}; +use syscall::Result; + +use display::Display; + +pub struct TextScreen { + pub console: Console, + pub display: Display, + pub changed: BTreeSet, + pub input: VecDeque, + pub end_of_input: bool, + pub cooked: VecDeque, + pub requested: usize +} + +impl TextScreen { + pub fn new(display: Display) -> TextScreen { + TextScreen { + console: Console::new(display.width/8, display.height/16), + display: display, + changed: BTreeSet::new(), + input: VecDeque::new(), + end_of_input: false, + cooked: VecDeque::new(), + requested: 0 + } + } + + pub fn input(&mut self, buf: &[u8]) -> Result { + if self.console.raw_mode { + for &b in buf.iter() { + self.input.push_back(b); + } + } else { + for &b in buf.iter() { + match b { + b'\x03' => { + self.end_of_input = true; + self.write(b"^C\n", true)?; + }, + b'\x08' | b'\x7F' => { + if let Some(_c) = self.cooked.pop_back() { + self.write(b"\x08", true)?; + } + }, + b'\n' | b'\r' => { + self.cooked.push_back(b); + while let Some(c) = self.cooked.pop_front() { + self.input.push_back(c); + } + self.write(b"\n", true)?; + }, + _ => { + self.cooked.push_back(b); + self.write(&[b], true)?; + } + } + } + } + Ok(buf.len()) + } + + pub fn read(&mut self, buf: &mut [u8]) -> Result { + let mut i = 0; + + while i < buf.len() && ! self.input.is_empty() { + buf[i] = self.input.pop_front().unwrap(); + i += 1; + } + + if i == 0 { + self.end_of_input = false; + } + + Ok(i) + } + + pub fn will_block(&self) -> bool { + self.input.is_empty() && ! self.end_of_input + } + + pub fn write(&mut self, buf: &[u8], sync: bool) -> Result { + if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h { + let x = self.console.x; + let y = self.console.y; + let color = self.console.background; + self.display.rect(x * 8, y * 16, 8, 16, color.data); + self.changed.insert(y); + } + + { + let display = &mut self.display; + let changed = &mut self.changed; + self.console.write(buf, |event| { + match event { + Event::Char { x, y, c, color, bold, .. } => { + display.char(x * 8, y * 16, c, color.data, bold, false); + changed.insert(y); + }, + Event::Rect { x, y, w, h, color } => { + display.rect(x * 8, y * 16, w * 8, h * 16, color.data); + for y2 in y..y + h { + changed.insert(y2); + } + }, + Event::Scroll { rows, color } => { + display.scroll(rows * 16, color.data); + for y in 0..display.height/16 { + changed.insert(y); + } + } + } + }); + } + + if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h { + let x = self.console.x; + let y = self.console.y; + let color = self.console.foreground; + self.display.rect(x * 8, y * 16, 8, 16, color.data); + self.changed.insert(y); + } + + if ! self.console.raw_mode && sync { + self.sync(); + } + + Ok(buf.len()) + } + + pub fn sync(&mut self) { + let width = self.display.width; + for change in self.changed.iter() { + self.display.sync(0, change * 16, width, 16); + } + self.changed.clear(); + } + + pub fn redraw(&mut self) { + let width = self.display.width; + let height = self.display.height; + self.display.sync(0, 0, width, height); + self.changed.clear(); + } +} diff --git a/filesystem/etc/pcid.toml b/filesystem/etc/pcid.toml new file mode 100644 index 0000000..2aee667 --- /dev/null +++ b/filesystem/etc/pcid.toml @@ -0,0 +1,6 @@ +[[drivers]] +name = "E1000 NIC" +class = 2 +vendor = 32902 +device = 4110 +command = ["file:bin/e1000d", "$BAR0", "$IRQ"] diff --git a/initfs/etc/init.rc b/initfs/etc/init.rc index 4ac3e96..d5530ee 100644 --- a/initfs/etc/init.rc +++ b/initfs/etc/init.rc @@ -1,5 +1,11 @@ initfs:bin/pcid initfs:etc/pcid.toml initfs:bin/redoxfs disk:0 +initfs:bin/pcid file:etc/pcid.toml file:bin/vesad file:bin/ps2d -file:bin/getty display: +file:bin/getty display:1 +file:bin/getty display:2 +file:bin/getty display:3 +file:bin/getty display:4 +file:bin/getty display:5 +file:bin/getty display:6 diff --git a/programs/ion b/programs/ion index b791519..db8e494 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit b7915192616f3ab058638c10fbfe84d9bcda2008 +Subproject commit db8e494fda926c1bec3c283edeab90db83ca3539 diff --git a/programs/userutils b/programs/userutils index eaf2676..1789653 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit eaf26765c12efe5519fb2af72557dc0ee8286bcd +Subproject commit 17896532dc139fcc42237effbb7e90cf5bb95702