use crate::IntelArch;
const FAMILIES: &[(u16, u16, IntelArch)] = &[
(0x4905, 0x4909, IntelArch::XeLp),
(0x4600, 0x46FF, IntelArch::XeLp),
(0x4C80, 0x4CFF, IntelArch::XeLp),
(0x9A40, 0x9AFF, IntelArch::XeLp),
(0xA700, 0xA7FF, IntelArch::XeLp),
(0x5690, 0x56CF, IntelArch::XeHpg),
(0x0BD0, 0x0BDF, IntelArch::XeHpc),
(0x7D00, 0x7DFF, IntelArch::XeLpg),
(0x6400, 0x64FF, IntelArch::Xe2),
(0xE200, 0xE2FF, IntelArch::Xe2),
];
#[allow(dead_code)] pub(crate) fn arch_for_device_id(id: u16) -> Option<IntelArch> {
FAMILIES
.iter()
.find(|(first, last, _)| (*first..=*last).contains(&id))
.map(|&(_, _, arch)| arch)
}
#[allow(dead_code)] pub(crate) fn parse_device_id(content: &str) -> Option<u16> {
let text = content.trim();
let digits = text
.strip_prefix("0x")
.or_else(|| text.strip_prefix("0X"))?;
u16::from_str_radix(digits, 16).ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_sysfs_pci_ids() {
assert_eq!(parse_device_id("0x56a0\n"), Some(0x56A0));
assert_eq!(parse_device_id("0X9A49"), Some(0x9A49));
assert_eq!(parse_device_id(" 0xe20b "), Some(0xE20B));
}
#[test]
fn rejects_ids_without_a_hex_prefix() {
assert_eq!(parse_device_id("56a0"), None);
assert_eq!(parse_device_id("0xzzzz"), None);
assert_eq!(parse_device_id("0x1ffff"), None, "wider than u16");
assert_eq!(parse_device_id(""), None);
}
#[test]
fn maps_discrete_parts_to_their_family() {
assert_eq!(arch_for_device_id(0x56A0), Some(IntelArch::XeHpg));
assert_eq!(arch_for_device_id(0xE20B), Some(IntelArch::Xe2));
assert_eq!(arch_for_device_id(0x4905), Some(IntelArch::XeLp));
assert_eq!(arch_for_device_id(0x0BD5), Some(IntelArch::XeHpc));
}
#[test]
fn maps_integrated_parts_to_their_family() {
assert_eq!(
arch_for_device_id(0x9A49),
Some(IntelArch::XeLp),
"Tiger Lake"
);
assert_eq!(
arch_for_device_id(0x4680),
Some(IntelArch::XeLp),
"Alder Lake"
);
assert_eq!(
arch_for_device_id(0x7D55),
Some(IntelArch::XeLpg),
"Meteor Lake"
);
assert_eq!(
arch_for_device_id(0x64A0),
Some(IntelArch::Xe2),
"Lunar Lake"
);
}
#[test]
fn unknown_ids_report_nothing_rather_than_guessing() {
assert_eq!(arch_for_device_id(0x1912), None, "Skylake GT2");
assert_eq!(arch_for_device_id(0x8A52), None, "Ice Lake");
assert_eq!(arch_for_device_id(0x0000), None);
assert_eq!(arch_for_device_id(0xFFFF), None);
}
#[test]
fn ranges_do_not_overlap() {
for (i, &(first, last, _)) in FAMILIES.iter().enumerate() {
assert!(first <= last, "range {i} is inverted");
for &(other_first, other_last, _) in &FAMILIES[i + 1..] {
assert!(
last < other_first || other_last < first,
"ranges {first:#06x}..={last:#06x} and \
{other_first:#06x}..={other_last:#06x} overlap",
);
}
}
}
}