diff --git a/Makefile b/Makefile index ac98e50..fc04650 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ clean: cargo clean --manifest-path libstd/Cargo.toml cargo clean --manifest-path init/Cargo.toml cargo clean --manifest-path ion/Cargo.toml - cargo clean --manifest-path drivers/atkbd/Cargo.toml + cargo clean --manifest-path drivers/ps2d/Cargo.toml cargo clean --manifest-path drivers/pcid/Cargo.toml rm -rf build diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs index 0886bef..52f90b1 100644 --- a/drivers/pcid/src/main.rs +++ b/drivers/pcid/src/main.rs @@ -2,8 +2,10 @@ extern crate syscall; +use std::fs::File; +use std::io::{Read, Write}; use std::thread; -use syscall::iopl; +use syscall::{iopl, Packet}; use pci::{Pci, PciBar, PciClass}; @@ -75,5 +77,17 @@ fn main() { unsafe { iopl(3).unwrap() }; enumerate_pci(); + + let mut scheme = File::create(":pci").expect("pcid: failed to create pci scheme"); + loop { + let mut packet = Packet::default(); + scheme.read(&mut packet).expect("pcid: failed to read events from pci scheme"); + + println!("{:?}", packet); + + packet.a = 0; + + scheme.write(&packet).expect("pcid: failed to write responses to pci scheme"); + } }); } diff --git a/drivers/ps2d/src/keyboard.rs b/drivers/ps2d/src/keyboard.rs index 109819a..b0090a3 100644 --- a/drivers/ps2d/src/keyboard.rs +++ b/drivers/ps2d/src/keyboard.rs @@ -5,7 +5,7 @@ use std::thread; use keymap; -pub fn keyboard() { +pub fn keyboard() { let mut file = File::open("irq:1").expect("ps2d: failed to open irq:1"); loop { diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index f4340a0..d53688b 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -19,6 +19,7 @@ use self::debug::DebugScheme; use self::env::EnvScheme; use self::initfs::InitFsScheme; use self::irq::IrqScheme; +use self::root::RootScheme; /// Debug scheme pub mod debug; @@ -32,6 +33,9 @@ pub mod initfs; /// IRQ handling pub mod irq; +/// Root scheme +pub mod root; + /// Userspace schemes pub mod user; @@ -102,10 +106,11 @@ static SCHEMES: Once> = Once::new(); /// Initialize schemes, called if needed fn init_schemes() -> RwLock { let mut list: SchemeList = SchemeList::new(); - list.insert(Box::new(*b"debug"), Arc::new(Box::new(DebugScheme))).expect("failed to insert debug: scheme"); - list.insert(Box::new(*b"env"), Arc::new(Box::new(EnvScheme::new()))).expect("failed to insert env: scheme"); - list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs: scheme"); - list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq: scheme"); + list.insert(Box::new(*b""), Arc::new(Box::new(RootScheme::new()))).expect("failed to insert root scheme"); + list.insert(Box::new(*b"debug"), Arc::new(Box::new(DebugScheme))).expect("failed to insert debug scheme"); + list.insert(Box::new(*b"env"), Arc::new(Box::new(EnvScheme::new()))).expect("failed to insert env scheme"); + list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs scheme"); + list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq scheme"); RwLock::new(list) } diff --git a/kernel/scheme/root.rs b/kernel/scheme/root.rs new file mode 100644 index 0000000..14cf55e --- /dev/null +++ b/kernel/scheme/root.rs @@ -0,0 +1,84 @@ +use alloc::arc::Arc; +use alloc::boxed::Box; +use collections::BTreeMap; +use core::sync::atomic::{AtomicUsize, Ordering}; +use core::str; +use spin::RwLock; + +use syscall::{Error, Result}; +use scheme::{self, Scheme}; +use scheme::user::{UserInner, UserScheme}; + +pub struct RootScheme { + next_id: AtomicUsize, + handles: RwLock>> +} + +impl RootScheme { + pub fn new() -> RootScheme { + RootScheme { + next_id: AtomicUsize::new(0), + handles: RwLock::new(BTreeMap::new()) + } + } +} + +impl Scheme for RootScheme { + fn open(&self, path: &[u8], flags: usize) -> Result { + let inner = { + let mut schemes = scheme::schemes_mut(); + if schemes.get_name(path).is_some() { + return Err(Error::FileExists); + } + let inner = Arc::new(UserInner::new()); + schemes.insert(path.to_vec().into_boxed_slice(), Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner))))).expect("failed to insert user scheme"); + inner + }; + + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(id, inner); + + Ok(id) + } + + fn dup(&self, file: usize) -> Result { + let inner = { + let handles = self.handles.read(); + let inner = handles.get(&file).ok_or(Error::BadFile)?; + inner.clone() + }; + + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(id, inner); + + Ok(id) + } + + fn read(&self, file: usize, buf: &mut [u8]) -> Result { + let inner = { + let handles = self.handles.read(); + let inner = handles.get(&file).ok_or(Error::BadFile)?; + inner.clone() + }; + + inner.read(buf) + } + + fn write(&self, file: usize, buf: &[u8]) -> Result { + let inner = { + let handles = self.handles.read(); + let inner = handles.get(&file).ok_or(Error::BadFile)?; + inner.clone() + }; + + inner.write(buf) + } + + fn fsync(&self, _file: usize) -> Result<()> { + Ok(()) + } + + fn close(&self, file: usize) -> Result<()> { + self.handles.write().remove(&file).ok_or(Error::BadFile).and(Ok(())) + } +} diff --git a/kernel/scheme/user.rs b/kernel/scheme/user.rs index 6ff446a..691ae02 100644 --- a/kernel/scheme/user.rs +++ b/kernel/scheme/user.rs @@ -1,7 +1,8 @@ +use alloc::arc::Weak; use collections::{BTreeMap, VecDeque}; use core::sync::atomic::{AtomicUsize, Ordering}; use core::{mem, usize}; -use spin::RwLock; +use spin::Mutex; use context; use syscall::{convert_to_result, Call, Error, Result}; @@ -18,109 +19,125 @@ pub struct Packet { pub d: usize } -/// UserScheme has to be wrapped -pub struct UserScheme { +pub struct UserInner { next_id: AtomicUsize, - todo: RwLock>, - done: RwLock> + todo: Mutex>, + done: Mutex> } -impl UserScheme { - fn call(&self, a: Call, b: usize, c: usize, d: usize) -> Result { +impl UserInner { + pub fn new() -> UserInner { + UserInner { + next_id: AtomicUsize::new(0), + todo: Mutex::new(VecDeque::new()), + done: Mutex::new(BTreeMap::new()) + } + } + + pub fn call(&self, a: Call, b: usize, c: usize, d: usize) -> Result { let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.todo.write().push_back(Packet { + let packet = Packet { id: id, a: a as usize, b: b, c: c, d: d - }); + }; + + self.todo.lock().push_back(packet); loop { - if let Some(a) = self.done.write().remove(&id) { + if let Some(a) = self.done.lock().remove(&id) { return convert_to_result(a); } unsafe { context::switch(); } } } + + pub fn read(&self, buf: &mut [u8]) -> Result { + let packet_size = mem::size_of::(); + let len = buf.len()/packet_size; + if len > 0 { + loop { + let mut i = 0; + { + let mut todo = self.todo.lock(); + while ! todo.is_empty() && i < len { + let packet = todo.pop_front().unwrap(); + unsafe { *(buf.as_mut_ptr() as *mut Packet).offset(i as isize) = packet; } + i += 1; + } + } + + if i > 0 { + return Ok(i * packet_size); + } else { + unsafe { context::switch(); } + } + } + } else { + Ok(0) + } + } + + pub fn write(&self, buf: &[u8]) -> Result { + let packet_size = mem::size_of::(); + let len = buf.len()/packet_size; + let mut i = 0; + while i < len { + let packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) }; + self.done.lock().insert(packet.id, packet.a); + + i += 1; + } + + Ok(i * packet_size) + } +} + +/// UserInner has to be wrapped +pub struct UserScheme { + inner: Weak +} + +impl UserScheme { + pub fn new(inner: Weak) -> UserScheme { + UserScheme { + inner: inner + } + } } impl Scheme for UserScheme { fn open(&self, path: &[u8], flags: usize) -> Result { - self.call(Call::Open, path.as_ptr() as usize, path.len(), flags) + let inner = self.inner.upgrade().ok_or(Error::NoDevice)?; + inner.call(Call::Open, path.as_ptr() as usize, path.len(), flags) } fn dup(&self, file: usize) -> Result { - if file == usize::MAX { - Ok(file) - } else { - self.call(Call::Dup, file, 0, 0) - } + let inner = self.inner.upgrade().ok_or(Error::NoDevice)?; + inner.call(Call::Dup, file, 0, 0) } fn read(&self, file: usize, buf: &mut [u8]) -> Result { - if file == usize::MAX { - let packet_size = mem::size_of::(); - let len = buf.len()/packet_size; - if len > 0 { - loop { - let mut i = 0; - { - let mut todo = self.todo.write(); - while ! todo.is_empty() && i < len { - unsafe { *(buf.as_mut_ptr() as *mut Packet).offset(i as isize) = todo.pop_front().unwrap(); } - i += 1; - } - } - - if i > 0 { - return Ok(i * packet_size); - } else { - unsafe { context::switch(); } - } - } - } else { - Ok(0) - } - } else { - self.call(Call::Read, file, buf.as_mut_ptr() as usize, buf.len()) - } + let inner = self.inner.upgrade().ok_or(Error::NoDevice)?; + inner.call(Call::Read, file, buf.as_mut_ptr() as usize, buf.len()) } fn write(&self, file: usize, buf: &[u8]) -> Result { - if file == usize::MAX { - let packet_size = mem::size_of::(); - let len = buf.len()/packet_size; - let mut i = 0; - while i < len { - let packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) }; - self.done.write().insert(packet.id, packet.a); - - i += 1; - } - - Ok(i * packet_size) - } else { - self.call(Call::Write, file, buf.as_ptr() as usize, buf.len()) - } + let inner = self.inner.upgrade().ok_or(Error::NoDevice)?; + inner.call(Call::Write, file, buf.as_ptr() as usize, buf.len()) } fn fsync(&self, file: usize) -> Result<()> { - if file == usize::MAX { - Ok(()) - } else { - self.call(Call::FSync, file, 0, 0).and(Ok(())) - } + let inner = self.inner.upgrade().ok_or(Error::NoDevice)?; + inner.call(Call::FSync, file, 0, 0).and(Ok(())) } fn close(&self, file: usize) -> Result<()> { - if file == usize::MAX { - println!("Close user scheme"); - Ok(()) - } else { - self.call(Call::Close, file, 0, 0).and(Ok(())) - } + let inner = self.inner.upgrade().ok_or(Error::NoDevice)?; + inner.call(Call::Close, file, 0, 0).and(Ok(())) } } diff --git a/libstd b/libstd index 0d434cc..3d771c7 160000 --- a/libstd +++ b/libstd @@ -1 +1 @@ -Subproject commit 0d434cc168b1d88211f1a3b72c8290c911432826 +Subproject commit 3d771c76c4cbd82ad699c59d3bfb645556d90f39 diff --git a/syscall/src/lib.rs b/syscall/src/lib.rs index 800a1db..51032bb 100644 --- a/syscall/src/lib.rs +++ b/syscall/src/lib.rs @@ -3,16 +3,19 @@ pub use self::arch::*; pub use self::error::*; +pub use self::scheme::*; #[cfg(target_arch = "x86")] #[path="x86.rs"] -pub mod arch; +mod arch; #[cfg(target_arch = "x86_64")] #[path="x86_64.rs"] -pub mod arch; +mod arch; -pub mod error; +mod error; + +mod scheme; pub const SYS_BRK: usize = 45; pub const SYS_CHDIR: usize = 12; diff --git a/syscall/src/scheme.rs b/syscall/src/scheme.rs new file mode 100644 index 0000000..756fc26 --- /dev/null +++ b/syscall/src/scheme.rs @@ -0,0 +1,29 @@ +use core::ops::{Deref, DerefMut}; +use core::{mem, slice}; + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct Packet { + pub id: usize, + pub a: usize, + pub b: usize, + pub c: usize, + pub d: usize +} + +impl Deref for Packet { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const Packet as *const u8, mem::size_of::()) as &[u8] + } + } +} + +impl DerefMut for Packet { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut Packet as *mut u8, mem::size_of::()) as &mut [u8] + } + } +}