91 lines
2.6 KiB
Rust
91 lines
2.6 KiB
Rust
use core::arch::asm;
|
|
use x86::apic::{xapic::XAPIC, ioapic::IoApic, ApicControl};
|
|
use x86_64::PhysAddr;
|
|
use x86_64::structures::idt::InterruptStackFrame;
|
|
use x86_64::structures::paging::PhysFrame;
|
|
use crate::{debug, KERN_INFO, print, println};
|
|
use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32};
|
|
use crate::serial::{command, read};
|
|
|
|
// todo! maybe abstract this into different sections for different parts of cpu func?
|
|
|
|
pub struct WAPICManager {
|
|
pub xapic: XAPIC,
|
|
pub id: u32,
|
|
}
|
|
|
|
pub struct WIOAPICManager {
|
|
pub ioapic: IoApic,
|
|
}
|
|
|
|
pub fn check_apic_compat() -> bool {
|
|
unsafe {
|
|
let mut eax: u32;
|
|
let mut edx: u32;
|
|
asm!("cpuid",
|
|
in("eax") 1,
|
|
lateout("eax") eax,
|
|
lateout("edx") edx,
|
|
);
|
|
edx & (1 << 9) != 0
|
|
}
|
|
}
|
|
|
|
pub fn enable_apic() -> WAPICManager {
|
|
// we need to get the xapic region
|
|
let mut XAPIC_REGION: &'static mut [u32] = unsafe {
|
|
// region should be FFFE0000H to FFFE0FFFH
|
|
let region_start = 0xFFFE_0000u32;
|
|
let region_end = 0xFFFE_0FFFu32;
|
|
let region_size = region_end - region_start;
|
|
let region_size = region_size as usize;
|
|
let region_start = region_start as *mut u32;
|
|
// read to make sure it gets mapped
|
|
let _ = read_phys_memory32(region_start as u32);
|
|
let _ = read_phys_memory32(region_end as u32);
|
|
core::slice::from_raw_parts_mut(region_start, region_size)
|
|
};
|
|
let mut xapic = unsafe { XAPIC::new(XAPIC_REGION) };
|
|
xapic.attach();
|
|
|
|
// get xapic id to ensure it's working
|
|
let id = xapic.id();
|
|
debug!("xapic id: {}", id);
|
|
debug!("xapic version: {}", xapic.version());
|
|
|
|
WAPICManager {
|
|
xapic,
|
|
id,
|
|
}
|
|
}
|
|
|
|
// todo! in the future this will be removed, it is only for testing basic apic functionality
|
|
pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
|
|
debug!("keyboard interrupt");
|
|
unsafe { asm!("iretq"); }
|
|
let scancode = read(0x60);
|
|
|
|
print!("ksc: {},", scancode);
|
|
|
|
// reset keyboard controller
|
|
let mut a = read(0x61);
|
|
a |= 0x82;
|
|
command(0x61, a);
|
|
a &= 0x7f;
|
|
command(0x61, a);
|
|
}
|
|
|
|
// todo! we should abstract this away
|
|
pub fn setup_ioapic(ioapicaddr: u32) -> WIOAPICManager {
|
|
let mut ioapic = unsafe { IoApic::new(ioapicaddr as usize) };
|
|
let _ = read_phys_memory32(ioapicaddr);
|
|
// assert that supported interrupts is greater than 1
|
|
debug!("ioapic supported interrupts: {}", ioapic.supported_interrupts());
|
|
// setup keyboard irq (interrupt 0x40)
|
|
ioapic.enable(1, 0x40);
|
|
|
|
// return
|
|
WIOAPICManager {
|
|
ioapic,
|
|
}
|
|
} |