Commit 2cadfb86 authored by Jeremy Soller's avatar Jeremy Soller Committed by GitHub

Graphics (#13)

Virtual Terminals
parent da74f55e
......@@ -4,6 +4,7 @@ version = "0.1.0"
[dependencies]
bitflags = "*"
dma = { path = "../dma/" }
io = { path = "../io/" }
spin = "*"
syscall = { path = "../../syscall/" }
use std::ptr;
use dma::Dma;
use syscall::error::Result;
use super::dma::Dma;
use super::hba::{HbaPort, HbaCmdTable, HbaCmdHeader};
pub struct Disk {
......
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;
......
......@@ -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;
......
......@@ -3,6 +3,7 @@
#[macro_use]
extern crate bitflags;
extern crate dma;
extern crate io;
extern crate spin;
extern crate syscall;
......
[package]
name = "dma"
version = "0.1.0"
[dependencies]
syscall = { path = "../../syscall/" }
#![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,
......
[package]
name = "rtl8139d"
version = "0.1.0"
[dependencies]
bitflags = "*"
dma = { path = "../dma/" }
io = { path = "../io/" }
spin = "*"
syscall = { path = "../../syscall/" }
#![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::<u8>().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); }
});
}
......@@ -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 {
......
......@@ -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 = []
pub struct Text {
}
#[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()
}
}
......
......@@ -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<Console>,
display: RefCell<Display>,
changed: RefCell<BTreeSet<usize>>,
input: RefCell<VecDeque<u8>>,
end_of_input: RefCell<bool>,
cooked: RefCell<VecDeque<u8>>,
requested: RefCell<usize>
}
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<usize> {
if path == b"input" {
Ok(1)
} else {
Ok(0)
}
}
fn dup(&self, id: usize) -> Result<usize> {
Ok(id)
}
fn fevent(&self, _id: usize, flags: usize) -> Result<usize> {
*self.requested.borrow_mut() = flags;
println!("fevent {:X}", flags);
Ok(0)
}
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
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<usize> {
if id == 1 {
} else {
self.sync();
}
Ok(0)
}
fn read(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
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<usize> {
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<usize> {
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");
}
*/
}
});
}
......
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<usize>,
screens: RefCell<BTreeMap<usize, TextScreen>>
}
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<usize> {
if path == b"input" {
Ok(0)
} else {
let path_str = str::from_utf8(path).unwrap_or("");
let id = path_str.parse::<usize>().unwrap_or(0);
if self.screens.borrow().contains_key(&id) {
Ok(id)
} else {
Err(Error::new(ENOENT))
}
}
}
fn dup(&self, id: usize) -> Result<usize> {
Ok(id)
}
fn fevent(&self, id: usize, flags: usize) -> Result<usize> {
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<usize> {
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<usize> {
let mut screens = self.screens.borrow_mut();
if let Some(mut screen) = screens.get_mut(&id) {
if id == self.active.get() {
screen.sync();
}