Files
RedBear-OS/drivers/input/intel-thc-hidd/src/thc.rs
T

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) };
}
}