My full code: https://github.com/toku-sa-n/ramen/tree ... _from_qemu
This is the initialization of MSI-X. (kernel/src/device/pci/config/extended_capability/msi_x.rs)
Code: Select all
impl<'a> CapabilitySpec for MsiX<'a> {
fn init_for_xhci(&self, config_type_spec: &TypeSpec) {
let base_address = config_type_spec.base_address(self.bir());
let mut table = self.table(base_address);
let pending_base = config_type_spec.base_address(self.pending_bir());
self.pending_bit_table(pending_base)[0] = 1;
table[0].init_for_xhci();
self.enable_interrupt();
}
}
Code: Select all
impl<'a> MsiX<'a> {
fn enable_interrupt(&self) {
let val = self.registers.get(self.base) | 0xf000_0000;
self.registers.set(self.base, val);
}
}
// kernel/src/device/pci/config/extended_capability/msi_x.rs
bitfield! {
#[derive(Debug)]
#[repr(transparent)]
struct Element(u128);
u32, from into MessageAddress, message_address,set_message_address: 31, 0;
u32, from into MessageData, message_data, set_message_data: 95, 64;
masked, set_mask: 96;
}
impl Element {
fn init_for_xhci(&mut self) {
self.message_address().init_for_xhci();
self.message_data().init_for_xhci();
self.set_mask(false);
}
}
// kernel/src/device/pci/config/extended_capability/mod.rs
bitfield! {
#[repr(transparent)]
pub struct MessageAddress(u32);
redirection_hint, set_redirection_hint: 3;
u8, destination_id, set_destination_id: 19, 12;
fixed_value, set_fixed_value: 31, 20;
}
impl MessageAddress {
pub fn init_for_xhci(&mut self) {
info!("LOCAL APIC ID: {}", Self::get_local_apic_id());
self.set_destination_id(Self::get_local_apic_id());
self.set_redirection_hint(false);
self.set_fixed_value(0xfee);
}
fn get_local_apic_id() -> u8 {
let accessor = single_object::Accessor::<u32>::new(LOCAL_APIC_ID_REGISTER_ADDR, 0);
u8::try_from(*accessor >> 24).unwrap()
}
}
bitfield! {
#[repr(transparent)]
pub struct MessageData(u32);
vector, set_vector: 7, 0;
delivery_mode, set_delivery_mode: 10, 8;
level, set_level: 14;
trigger_mode, set_trigger_mode: 15;
}
impl MessageData {
pub fn init_for_xhci(&mut self) {
self.set_level_trigger();
self.set_vector(0x40);
self.set_delivery_mode(0);
}
fn set_level_trigger(&mut self) {
self.set_trigger_mode(true);
self.set_level(true);
}
}