use bitflags::bitflags;
use bytemuck::{Pod, Zeroable};
use super::MemOps;
bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct EventFlags: u16 {
const ENABLE = 0x0;
const DISABLE = 0x1;
const DESC = 0x2;
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable, PartialEq, Eq, Hash)]
pub struct EventSuppression {
off_wrap: u16,
flags: u16,
}
const _: () = assert!(core::mem::size_of::<EventSuppression>() == 4);
const _: () = assert!(EventSuppression::WRAP_OFFSET == 0);
const _: () = assert!(EventSuppression::FLAGS_OFFSET == 2);
impl EventSuppression {
const FLAGS_MASK: u16 = 0x3;
const DESC_EVENT_OFF_MASK: u16 = 0x7FFF;
const DESC_EVENT_WRAP: u16 = 0x8000;
pub const SIZE: usize = core::mem::size_of::<Self>();
pub const ALIGN: usize = core::mem::align_of::<Self>();
pub const WRAP_OFFSET: usize = core::mem::offset_of!(Self, off_wrap);
pub const FLAGS_OFFSET: usize = core::mem::offset_of!(Self, flags);
pub fn new(off_wrap: u16, flags: EventFlags) -> Self {
Self {
off_wrap,
flags: flags.bits(),
}
}
pub fn flags(&self) -> EventFlags {
EventFlags::from_bits_truncate(self.flags & Self::FLAGS_MASK)
}
pub fn set_flags(&mut self, flags: EventFlags) {
self.flags = (self.flags & !Self::FLAGS_MASK) | (flags.bits() & Self::FLAGS_MASK);
}
pub fn desc_event_off(&self) -> u16 {
self.off_wrap & Self::DESC_EVENT_OFF_MASK
}
pub fn desc_event_wrap(&self) -> bool {
(self.off_wrap & Self::DESC_EVENT_WRAP) != 0
}
pub fn set_desc_event(&mut self, off: u16, wrap: bool) {
self.off_wrap =
(off & Self::DESC_EVENT_OFF_MASK) | if wrap { Self::DESC_EVENT_WRAP } else { 0 };
}
pub fn read_flags_acquire<M: MemOps>(mem: &M, addr: u64) -> Result<EventFlags, M::Error> {
let flags = mem.load_acquire(addr + Self::FLAGS_OFFSET as u64)?;
Ok(EventFlags::from_bits_truncate(flags))
}
pub fn read_body<M: MemOps>(mem: &M, addr: u64, flags: EventFlags) -> Result<Self, M::Error> {
let off_wrap: u16 = mem.read_val(addr + Self::WRAP_OFFSET as u64)?;
Ok(Self {
off_wrap,
flags: flags.bits(),
})
}
pub fn write_release<M: MemOps>(&self, mem: &M, addr: u64) -> Result<(), M::Error> {
mem.write_val(addr + Self::WRAP_OFFSET as u64, self.off_wrap)?;
mem.store_release(addr + Self::FLAGS_OFFSET as u64, self.flags)?;
Ok(())
}
}