diff options
Diffstat (limited to 'third_party/rust/redox_syscall/src/io')
-rw-r--r-- | third_party/rust/redox_syscall/src/io/dma.rs | 76 | ||||
-rw-r--r-- | third_party/rust/redox_syscall/src/io/io.rs | 67 | ||||
-rw-r--r-- | third_party/rust/redox_syscall/src/io/mmio.rs | 31 | ||||
-rw-r--r-- | third_party/rust/redox_syscall/src/io/mod.rs | 11 | ||||
-rw-r--r-- | third_party/rust/redox_syscall/src/io/pio.rs | 89 |
5 files changed, 274 insertions, 0 deletions
diff --git a/third_party/rust/redox_syscall/src/io/dma.rs b/third_party/rust/redox_syscall/src/io/dma.rs new file mode 100644 index 0000000000..d5334b843f --- /dev/null +++ b/third_party/rust/redox_syscall/src/io/dma.rs @@ -0,0 +1,76 @@ +use core::{mem, ptr}; +use core::ops::{Deref, DerefMut}; + +use Result; + +struct PhysBox { + address: usize, + size: usize +} + +impl PhysBox { + fn new(size: usize) -> Result<PhysBox> { + let address = unsafe { ::physalloc(size)? }; + Ok(PhysBox { + address: address, + size: size + }) + } +} + +impl Drop for PhysBox { + fn drop(&mut self) { + let _ = unsafe { ::physfree(self.address, self.size) }; + } +} + +pub struct Dma<T> { + phys: PhysBox, + virt: *mut T +} + +impl<T> Dma<T> { + pub fn new(value: T) -> Result<Dma<T>> { + let phys = PhysBox::new(mem::size_of::<T>())?; + let virt = unsafe { ::physmap(phys.address, phys.size, ::PHYSMAP_WRITE)? } as *mut T; + unsafe { ptr::write(virt, value); } + Ok(Dma { + phys: phys, + virt: virt + }) + } + + pub fn zeroed() -> Result<Dma<T>> { + let phys = PhysBox::new(mem::size_of::<T>())?; + let virt = unsafe { ::physmap(phys.address, phys.size, ::PHYSMAP_WRITE)? } as *mut T; + unsafe { ptr::write_bytes(virt as *mut u8, 0, phys.size); } + Ok(Dma { + phys: phys, + virt: virt + }) + } + + pub fn physical(&self) -> usize { + self.phys.address + } +} + +impl<T> Deref for Dma<T> { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.virt } + } +} + +impl<T> DerefMut for Dma<T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.virt } + } +} + +impl<T> Drop for Dma<T> { + fn drop(&mut self) { + unsafe { drop(ptr::read(self.virt)); } + let _ = unsafe { ::physunmap(self.virt as usize) }; + } +} diff --git a/third_party/rust/redox_syscall/src/io/io.rs b/third_party/rust/redox_syscall/src/io/io.rs new file mode 100644 index 0000000000..fb866b581b --- /dev/null +++ b/third_party/rust/redox_syscall/src/io/io.rs @@ -0,0 +1,67 @@ +use core::cmp::PartialEq; +use core::ops::{BitAnd, BitOr, Not}; + +pub trait Io { + type Value: Copy + PartialEq + BitAnd<Output = Self::Value> + BitOr<Output = Self::Value> + Not<Output = Self::Value>; + + fn read(&self) -> Self::Value; + fn write(&mut self, value: Self::Value); + + #[inline(always)] + fn readf(&self, flags: Self::Value) -> bool { + (self.read() & flags) as Self::Value == flags + } + + #[inline(always)] + fn writef(&mut self, flags: Self::Value, value: bool) { + let tmp: Self::Value = match value { + true => self.read() | flags, + false => self.read() & !flags, + }; + self.write(tmp); + } +} + +pub struct ReadOnly<I: Io> { + inner: I +} + +impl<I: Io> ReadOnly<I> { + pub const fn new(inner: I) -> ReadOnly<I> { + ReadOnly { + inner: inner + } + } + + #[inline(always)] + pub fn read(&self) -> I::Value { + self.inner.read() + } + + #[inline(always)] + pub fn readf(&self, flags: I::Value) -> bool { + self.inner.readf(flags) + } +} + +pub struct WriteOnly<I: Io> { + inner: I +} + +impl<I: Io> WriteOnly<I> { + pub const fn new(inner: I) -> WriteOnly<I> { + WriteOnly { + inner: inner + } + } + + #[inline(always)] + pub fn write(&mut self, value: I::Value) { + self.inner.write(value) + } + + #[inline(always)] + pub fn writef(&mut self, flags: I::Value, value: bool) { + self.inner.writef(flags, value) + } +} diff --git a/third_party/rust/redox_syscall/src/io/mmio.rs b/third_party/rust/redox_syscall/src/io/mmio.rs new file mode 100644 index 0000000000..b8e7727d3c --- /dev/null +++ b/third_party/rust/redox_syscall/src/io/mmio.rs @@ -0,0 +1,31 @@ +use core::ptr::{read_volatile, write_volatile}; +use core::mem::uninitialized; +use core::ops::{BitAnd, BitOr, Not}; + +use super::io::Io; + +#[repr(packed)] +pub struct Mmio<T> { + value: T, +} + +impl<T> Mmio<T> { + /// Create a new Mmio without initializing + pub fn new() -> Self { + Mmio { + value: unsafe { uninitialized() } + } + } +} + +impl<T> Io for Mmio<T> where T: Copy + PartialEq + BitAnd<Output = T> + BitOr<Output = T> + Not<Output = T> { + type Value = T; + + fn read(&self) -> T { + unsafe { read_volatile(&self.value) } + } + + fn write(&mut self, value: T) { + unsafe { write_volatile(&mut self.value, value) }; + } +} diff --git a/third_party/rust/redox_syscall/src/io/mod.rs b/third_party/rust/redox_syscall/src/io/mod.rs new file mode 100644 index 0000000000..a35456e30a --- /dev/null +++ b/third_party/rust/redox_syscall/src/io/mod.rs @@ -0,0 +1,11 @@ +//! I/O functions + +pub use self::dma::*; +pub use self::io::*; +pub use self::mmio::*; +pub use self::pio::*; + +mod dma; +mod io; +mod mmio; +mod pio; diff --git a/third_party/rust/redox_syscall/src/io/pio.rs b/third_party/rust/redox_syscall/src/io/pio.rs new file mode 100644 index 0000000000..91ae310b62 --- /dev/null +++ b/third_party/rust/redox_syscall/src/io/pio.rs @@ -0,0 +1,89 @@ +use core::marker::PhantomData; + +use super::io::Io; + +/// Generic PIO +#[derive(Copy, Clone)] +pub struct Pio<T> { + port: u16, + value: PhantomData<T>, +} + +impl<T> Pio<T> { + /// Create a PIO from a given port + pub const fn new(port: u16) -> Self { + Pio::<T> { + port: port, + value: PhantomData, + } + } +} + +/// Read/Write for byte PIO +impl Io for Pio<u8> { + type Value = u8; + + /// Read + #[inline(always)] + fn read(&self) -> u8 { + let value: u8; + unsafe { + asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value + } + + /// Write + #[inline(always)] + fn write(&mut self, value: u8) { + unsafe { + asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + } +} + +/// Read/Write for word PIO +impl Io for Pio<u16> { + type Value = u16; + + /// Read + #[inline(always)] + fn read(&self) -> u16 { + let value: u16; + unsafe { + asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value + } + + /// Write + #[inline(always)] + fn write(&mut self, value: u16) { + unsafe { + asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + } +} + +/// Read/Write for doubleword PIO +impl Io for Pio<u32> { + type Value = u32; + + /// Read + #[inline(always)] + fn read(&self) -> u32 { + let value: u32; + unsafe { + asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value + } + + /// Write + #[inline(always)] + fn write(&mut self, value: u32) { + unsafe { + asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + } +} |