use core::{
ops::Deref,
ptr::NonNull, };
use crate::{
prelude::*,
str::CString,
types::Opaque, };
pub use super::{
PhysAddr,
ResourceSize, };
pub struct Region {
resource: NonNull<bindings::resource>,
_name: CString,
}
impl Deref for Region {
type Target = Resource;
fn deref(&self) -> &Self::Target {
unsafe { Resource::from_raw(self.resource.as_ptr()) }
}
}
impl Drop for Region {
fn drop(&mut self) {
let (flags, start, size) = {
let res = &**self;
(res.flags(), res.start(), res.size())
};
let release_fn = if flags.contains(Flags::IORESOURCE_MEM) {
bindings::release_mem_region
} else {
bindings::release_region
};
unsafe { release_fn(start, size) };
}
}
unsafe impl Send for Region {}
unsafe impl Sync for Region {}
#[repr(transparent)]
pub struct Resource(Opaque<bindings::resource>);
impl Resource {
pub(crate) const unsafe fn from_raw<'a>(ptr: *mut bindings::resource) -> &'a Self {
unsafe { &*ptr.cast() }
}
pub fn request_region(
&self,
start: PhysAddr,
size: ResourceSize,
name: CString,
flags: Flags,
) -> Option<Region> {
let region = unsafe {
bindings::__request_region(
self.0.get(),
start,
size,
name.as_char_ptr(),
flags.0 as c_int,
)
};
Some(Region {
resource: NonNull::new(region)?,
_name: name,
})
}
pub fn size(&self) -> ResourceSize {
let inner = self.0.get();
unsafe { bindings::resource_size(inner) }
}
pub fn start(&self) -> PhysAddr {
let inner = self.0.get();
unsafe { (*inner).start }
}
pub fn name(&self) -> Option<&CStr> {
let inner = self.0.get();
let name = unsafe { (*inner).name };
if name.is_null() {
return None;
}
Some(unsafe { CStr::from_char_ptr(name) })
}
pub fn flags(&self) -> Flags {
let inner = self.0.get();
let flags = unsafe { (*inner).flags };
Flags(flags)
}
}
unsafe impl Send for Resource {}
unsafe impl Sync for Resource {}
#[derive(Clone, Copy, PartialEq)]
pub struct Flags(c_ulong);
impl Flags {
pub fn contains(self, flags: Flags) -> bool {
(self & flags) == flags
}
}
impl core::ops::BitOr for Flags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl core::ops::BitAnd for Flags {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}
impl core::ops::Not for Flags {
type Output = Self;
fn not(self) -> Self::Output {
Self(!self.0)
}
}
impl Flags {
pub const IORESOURCE_IO: Flags = Flags::new(bindings::IORESOURCE_IO);
pub const IORESOURCE_MUXED: Flags = Flags::new(bindings::IORESOURCE_MUXED);
pub const IORESOURCE_MEM: Flags = Flags::new(bindings::IORESOURCE_MEM);
pub const IORESOURCE_MEM_NONPOSTED: Flags = Flags::new(bindings::IORESOURCE_MEM_NONPOSTED);
#[inline(always)]
const fn new(value: u32) -> Self {
crate::build_assert!(value as u64 <= c_ulong::MAX as u64);
Flags(value as c_ulong)
}
}