From 67278f9442b8a2a3fc6409145b3f2c254e558e72 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 27 Sep 2016 20:52:26 -0600 Subject: [PATCH] Add disk scheme (mostly finished) --- drivers/ahcid/src/main.rs | 31 ++++++-------- drivers/ahcid/src/scheme.rs | 85 +++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 19 deletions(-) create mode 100644 drivers/ahcid/src/scheme.rs diff --git a/drivers/ahcid/src/main.rs b/drivers/ahcid/src/main.rs index 4eff7cd..07ca38e 100644 --- a/drivers/ahcid/src/main.rs +++ b/drivers/ahcid/src/main.rs @@ -4,13 +4,18 @@ #[macro_use] extern crate bitflags; extern crate io; +extern crate spin; extern crate syscall; +use std::fs::File; +use std::io::{Read, Write}; use std::{env, thread, usize}; +use syscall::{iopl, physmap, physunmap, MAP_WRITE, Packet, Scheme}; -use syscall::{iopl, physmap, physunmap, MAP_WRITE}; +use scheme::DiskScheme; pub mod ahci; +pub mod scheme; fn main() { let mut args = env::args().skip(1); @@ -29,25 +34,13 @@ fn main() { let address = unsafe { physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") }; { - let mut disks = ahci::disks(address, irq); - for mut disk in disks.iter_mut() { - let mut sector = [0; 512]; - println!("Read disk {} size {} MB", disk.id(), disk.size()/1024/1024); - match disk.read(0, &mut sector) { - Ok(count) => { - println!("{}", count); - for i in 0..512 { - print!("{:X} ", sector[i]); - } - println!(""); - }, - Err(err) => { - println!("{}", err); - } - } - } + let mut socket = File::create(":disk").expect("ahcid: failed to create disk scheme"); + let scheme = DiskScheme::new(ahci::disks(address, irq)); loop { - let _ = syscall::sched_yield(); + let mut packet = Packet::default(); + socket.read(&mut packet).expect("ahcid: failed to read disk scheme"); + scheme.handle(&mut packet); + socket.write(&mut packet).expect("ahcid: failed to read disk scheme"); } } unsafe { let _ = physunmap(address); } diff --git a/drivers/ahcid/src/scheme.rs b/drivers/ahcid/src/scheme.rs new file mode 100644 index 0000000..76b8b8a --- /dev/null +++ b/drivers/ahcid/src/scheme.rs @@ -0,0 +1,85 @@ +use std::collections::BTreeMap; +use std::{cmp, str}; +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; +use spin::Mutex; +use syscall::{Error, EBADF, EINVAL, ENOENT, Result, Scheme, SEEK_CUR, SEEK_END, SEEK_SET}; + +use ahci::disk::Disk; + +pub struct DiskScheme { + disks: Box<[Arc>]>, + handles: Mutex>, usize)>>, + next_id: AtomicUsize +} + +impl DiskScheme { + pub fn new(disks: Vec) -> DiskScheme { + let mut disk_arcs = vec![]; + for disk in disks { + disk_arcs.push(Arc::new(Mutex::new(disk))); + } + + DiskScheme { + disks: disk_arcs.into_boxed_slice(), + handles: Mutex::new(BTreeMap::new()), + next_id: AtomicUsize::new(0) + } + } +} + +impl Scheme for DiskScheme { + fn open(&self, path: &[u8], _flags: usize) -> Result { + let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; + + let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; + + if let Some(disk) = self.disks.get(i) { + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.lock().insert(id, (disk.clone(), 0)); + Ok(id) + } else { + Err(Error::new(ENOENT)) + } + } + + fn read(&self, id: usize, buf: &mut [u8]) -> Result { + let mut handles = self.handles.lock(); + let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + + let mut disk = handle.0.lock(); + let count = disk.read((handle.1 as u64)/512, buf)?; + handle.1 += count; + Ok(count) + } + + fn write(&self, id: usize, buf: &[u8]) -> Result { + let mut handles = self.handles.lock(); + let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + + let mut disk = handle.0.lock(); + let count = disk.write((handle.1 as u64)/512, buf)?; + handle.1 += count; + Ok(count) + } + + fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { + let mut handles = self.handles.lock(); + let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + + let len = handle.0.lock().size() as usize; + handle.1 = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; + + Ok(handle.1) + } + + fn close(&self, id: usize) -> Result { + let mut handles = self.handles.lock(); + handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + } +}