79 lines
2.1 KiB
Rust
79 lines
2.1 KiB
Rust
use std::ptr::NonNull;
|
|
|
|
use anyhow::{bail, Result};
|
|
|
|
pub const SUPPORTED_PCI_IDS: &[(u16, u16)] = &[
|
|
(0x8086, 0x7eb8),
|
|
(0x8086, 0x7eb9),
|
|
(0x8086, 0x7ebd),
|
|
(0x8086, 0x7ebe),
|
|
(0x8086, 0xa8b8),
|
|
(0x8086, 0xa8b9),
|
|
];
|
|
|
|
pub const REG_CONTROL: usize = 0x0000;
|
|
pub const REG_STATUS: usize = 0x0004;
|
|
pub const REG_MODE: usize = 0x0010;
|
|
pub const REG_SUBIP_OPCODE: usize = 0x0800;
|
|
pub const REG_SUBIP_ADDRESS: usize = 0x0804;
|
|
pub const REG_SUBIP_LENGTH: usize = 0x0808;
|
|
pub const REG_SUBIP_DOORBELL: usize = 0x080C;
|
|
pub const REG_SUBIP_DATA: usize = 0x0810;
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct ThcController {
|
|
base: NonNull<u8>,
|
|
len: usize,
|
|
}
|
|
|
|
impl ThcController {
|
|
pub fn new(base: *mut u8, len: usize) -> Result<Self> {
|
|
let Some(base) = NonNull::new(base) else {
|
|
bail!("THC BAR mapping returned null base pointer");
|
|
};
|
|
Ok(Self { base, len })
|
|
}
|
|
|
|
pub fn initialize_quicki2c_mode(&self) {
|
|
self.write32(REG_MODE, 0x1);
|
|
self.write32(REG_CONTROL, 0x1);
|
|
}
|
|
|
|
pub fn status(&self) -> u32 {
|
|
self.read32(REG_STATUS)
|
|
}
|
|
|
|
pub fn program_subip_transaction(&self, opcode: u32, address: u16, len: usize) {
|
|
self.write32(REG_SUBIP_OPCODE, opcode);
|
|
self.write32(REG_SUBIP_ADDRESS, u32::from(address));
|
|
self.write32(REG_SUBIP_LENGTH, len as u32);
|
|
self.write32(REG_SUBIP_DOORBELL, 1);
|
|
}
|
|
|
|
pub fn write_subip_data(&self, offset: usize, value: u32) {
|
|
self.write32(REG_SUBIP_DATA + offset, value);
|
|
}
|
|
|
|
pub fn read_subip_data(&self, offset: usize) -> u32 {
|
|
self.read32(REG_SUBIP_DATA + offset)
|
|
}
|
|
|
|
fn read32(&self, offset: usize) -> u32 {
|
|
if offset + 4 > self.len {
|
|
return 0;
|
|
}
|
|
|
|
let ptr = unsafe { self.base.as_ptr().add(offset).cast::<u32>() };
|
|
unsafe { ptr.read_volatile() }
|
|
}
|
|
|
|
fn write32(&self, offset: usize, value: u32) {
|
|
if offset + 4 > self.len {
|
|
return;
|
|
}
|
|
|
|
let ptr = unsafe { self.base.as_ptr().add(offset).cast::<u32>() };
|
|
unsafe { ptr.write_volatile(value) };
|
|
}
|
|
}
|