use crate::ok;
use crate::{AsHandleRef, Handle, HandleBased, HandleRef, Resource, Status};
use fuchsia_zircon_sys as sys;
#[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 mut 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,
&mut desc_dummy as *mut sys::zx_iommu_desc_dummy_t as *const 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 fuchsia_zircon::{Channel, HandleBased, Time};
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(Time::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);
}
}