use crate::lib_bitfield;
use crate::result::Result;
use super::{ExtCsd, ExtCsdIndex};
lib_bitfield! {
pub ExceptionEventsStatus(u16): u8 {
pub extended_security_failure: 4;
pub packed_failure: 3;
pub syspool_exhausted: 2;
pub dyncap_needed: 1;
pub urgent_bkops: 0;
}
}
impl ExceptionEventsStatus {
pub const MASK: u16 = 0x1f;
pub const DEFAULT: u16 = 0;
pub const fn new() -> Self {
Self(Self::DEFAULT)
}
pub const fn from_bits(val: u16) -> Self {
Self(val & Self::MASK)
}
pub const fn try_from_inner(val: u16) -> Result<Self> {
Ok(Self::from_bits(val))
}
pub const fn into_inner(self) -> u16 {
self.bits()
}
}
impl Default for ExceptionEventsStatus {
fn default() -> Self {
Self::new()
}
}
impl ExtCsd {
pub const fn exception_events_status(&self) -> Result<ExceptionEventsStatus> {
let start = self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_START];
let end = self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_END];
ExceptionEventsStatus::try_from_inner(u16::from_be_bytes([start, end]))
}
pub(crate) fn set_exception_events_status(&mut self, val: ExceptionEventsStatus) {
let [start, end] = val.into_inner().to_be_bytes();
self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_START] = start;
self.0[ExtCsdIndex::EXCEPTION_EVENTS_STATUS_END] = end;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_exception_events_status() {
let mut ext_csd = ExtCsd::new();
(1..=u8::BITS).map(|r| (1u16 << r) - 1).for_each(|raw| {
let status = ExceptionEventsStatus::from_bits(raw);
assert_eq!(status.bits(), raw & ExceptionEventsStatus::MASK);
ext_csd.set_exception_events_status(status);
assert_eq!(ext_csd.exception_events_status(), Ok(status));
});
}
}