use crate::{ok, sys, AsHandleRef, Handle, HandleBased, HandleRef, Resource, Status};
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Iommu(Handle);
impl_handle_based!(Iommu);
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct IommuDescDummy {
reserved: u8,
}
impl Default for IommuDescDummy {
fn default() -> IommuDescDummy {
Self::from(sys::zx_iommu_desc_dummy_t::default())
}
}
impl From<sys::zx_iommu_desc_dummy_t> for IommuDescDummy {
fn from(desc: sys::zx_iommu_desc_dummy_t) -> IommuDescDummy {
IommuDescDummy { reserved: desc.reserved }
}
}
impl From<IommuDescDummy> for sys::zx_iommu_desc_dummy_t {
fn from(desc: IommuDescDummy) -> sys::zx_iommu_desc_dummy_t {
sys::zx_iommu_desc_dummy_t { reserved: desc.reserved }
}
}
impl Iommu {
pub fn create_dummy(resource: &Resource, desc: IommuDescDummy) -> Result<Iommu, Status> {
let mut iommu_handle = sys::zx_handle_t::default();
let desc_dummy = sys::zx_iommu_desc_dummy_t::from(desc);
let status = unsafe {
sys::zx_iommu_create(
resource.raw_handle(),
sys::ZX_IOMMU_TYPE_DUMMY,
std::ptr::from_ref(&desc_dummy).cast::<u8>(),
std::mem::size_of_val(&desc_dummy),
&mut iommu_handle,
)
};
ok(status)?;
unsafe {
Ok(Iommu::from(Handle::from_raw(iommu_handle)))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ObjectType;
use fidl_fuchsia_kernel as fkernel;
use fuchsia_component::client::connect_channel_to_protocol;
#[test]
fn iommu_create_invalid_resource() {
let status =
Iommu::create_dummy(&Resource::from(Handle::invalid()), IommuDescDummy::default());
assert_eq!(status, Err(Status::BAD_HANDLE));
}
#[test]
fn iommu_create_valid() {
use zx::{Channel, HandleBased, MonotonicInstant};
let (client_end, server_end) = Channel::create();
connect_channel_to_protocol::<fkernel::IommuResourceMarker>(server_end).unwrap();
let service = fkernel::IommuResourceSynchronousProxy::new(client_end);
let resource =
service.get(MonotonicInstant::INFINITE).expect("couldn't get iommu resource");
let resource = unsafe { Resource::from(Handle::from_raw(resource.into_raw())) };
let iommu = Iommu::create_dummy(&resource, IommuDescDummy::default()).unwrap();
assert!(!iommu.as_handle_ref().is_invalid());
let info = iommu.as_handle_ref().basic_info().unwrap();
assert_eq!(info.object_type, ObjectType::IOMMU);
}
}