parent
							
								
									0d1afaa016
								
							
						
					
					
						commit
						b49211f24e
					
				
					 23 changed files with 459 additions and 239 deletions
				
			
		
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ version = "0.1.0" | |||
| 
 | ||||
| [dependencies] | ||||
| bitflags = "*" | ||||
| dma = { path = "../dma/" } | ||||
| io = { path = "../io/" } | ||||
| spin = "*" | ||||
| syscall = { path = "../../syscall/" } | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										6
									
								
								drivers/dma/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								drivers/dma/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| [package] | ||||
| name = "dma" | ||||
| version = "0.1.0" | ||||
| 
 | ||||
| [dependencies] | ||||
| syscall = { path = "../../syscall/" } | ||||
|  | @ -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, | ||||
							
								
								
									
										10
									
								
								drivers/e1000d/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								drivers/e1000d/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| [package] | ||||
| name = "rtl8139d" | ||||
| version = "0.1.0" | ||||
| 
 | ||||
| [dependencies] | ||||
| bitflags = "*" | ||||
| dma = { path = "../dma/" } | ||||
| io = { path = "../io/" } | ||||
| spin = "*" | ||||
| syscall = { path = "../../syscall/" } | ||||
							
								
								
									
										41
									
								
								drivers/e1000d/src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								drivers/e1000d/src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -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::<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 = [] | ||||
|  |  | |||
							
								
								
									
										3
									
								
								drivers/vesad/src/console.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								drivers/vesad/src/console.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| pub struct Text { | ||||
| 
 | ||||
| } | ||||
|  | @ -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() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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"); | ||||
|                 } | ||||
|                 */ | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										143
									
								
								drivers/vesad/src/scheme.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								drivers/vesad/src/scheme.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -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<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(); | ||||
|             } | ||||
|             Ok(0) | ||||
|         } else { | ||||
|             Err(Error::new(EBADF)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> { | ||||
|         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<usize> { | ||||
|         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<usize> { | ||||
|         Ok(0) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										1
									
								
								drivers/vesad/src/screen/graphic.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								drivers/vesad/src/screen/graphic.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| pub struct GraphicScreen; | ||||
							
								
								
									
										10
									
								
								drivers/vesad/src/screen/mod.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								drivers/vesad/src/screen/mod.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -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) | ||||
| } | ||||
							
								
								
									
										149
									
								
								drivers/vesad/src/screen/text.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								drivers/vesad/src/screen/text.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -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<usize>, | ||||
|     pub input: VecDeque<u8>, | ||||
|     pub end_of_input: bool, | ||||
|     pub cooked: VecDeque<u8>, | ||||
|     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<usize> { | ||||
|         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<usize> { | ||||
|         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<usize> { | ||||
|         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(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										6
									
								
								filesystem/etc/pcid.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								filesystem/etc/pcid.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| [[drivers]] | ||||
| name = "E1000 NIC" | ||||
| class = 2 | ||||
| vendor = 32902 | ||||
| device = 4110 | ||||
| command = ["file:bin/e1000d", "$BAR0", "$IRQ"] | ||||
|  | @ -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 | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| Subproject commit b7915192616f3ab058638c10fbfe84d9bcda2008 | ||||
| Subproject commit db8e494fda926c1bec3c283edeab90db83ca3539 | ||||
|  | @ -1 +1 @@ | |||
| Subproject commit eaf26765c12efe5519fb2af72557dc0ee8286bcd | ||||
| Subproject commit 17896532dc139fcc42237effbb7e90cf5bb95702 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller