use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P2, P3};
use super::CapabilityDataError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Sata {
pub revision: Revision,
pub bar_offset: BarOffset,
pub bar_location: BarLocation,
}
impl TryFrom<&[u8]> for Sata {
type Error = CapabilityDataError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let Seq {
head: Le((revision, rsvd, sata_cap1)),
..
} = P3(slice).try_into().map_err(|_| CapabilityDataError {
name: "Serial ATA",
size: 6,
})?;
let _: u8 = rsvd;
let Lsb((minor, major)) = P2::<u8, 4, 4>(revision).into();
let Lsb((bar_location, bar_offset, ())) = P3::<u32, 4, 20, 8>(sata_cap1).into();
Ok(Self {
revision: Revision { minor, major },
bar_offset: BarOffset(bar_offset),
bar_location: From::<u8>::from(bar_location),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Revision {
pub minor: u8,
pub major: u8,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BarLocation {
Bar0,
Bar1,
Bar2,
Bar3,
Bar4,
Bar5,
SataCapability1,
Reserved(u8),
}
impl From<u8> for BarLocation {
fn from(byte: u8) -> Self {
match byte {
0b0100 => Self::Bar0,
0b0101 => Self::Bar1,
0b0110 => Self::Bar2,
0b0111 => Self::Bar3,
0b1000 => Self::Bar4,
0b1001 => Self::Bar5,
0b1111 => Self::SataCapability1,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BarOffset(pub u32);
impl BarOffset {
pub fn value(&self) -> u32 {
self.0 * 4
}
}