Implemented HPET driver

This commit is contained in:
Connor Wood
2017-07-14 13:58:06 +01:00
parent 0cbdb2d0c0
commit 0bd6f11a4f
5 changed files with 104 additions and 4 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ pub struct GenericAddressStructure {
bit_width: u8,
bit_offset: u8,
access_size: u8,
address: u64,
pub address: u64,
}
#[repr(packed)]
+1 -1
View File
@@ -22,7 +22,7 @@ use self::hpet::Hpet;
use self::aml::{is_aml_table, parse_aml_table, AmlNamespace, AmlError};
mod hpet;
pub mod hpet;
mod dmar;
mod fadt;
mod madt;
+82
View File
@@ -0,0 +1,82 @@
use core::intrinsics::{volatile_load, volatile_store};
use memory::Frame;
use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress};
use acpi::hpet::Hpet;
pub static mut HPET: HpetDevice = HpetDevice {
capability_addr: 0,
general_config_addr: 0,
general_interrupt_addr: 0,
main_counter_addr: 0,
t0_config_capability_addr: 0,
t0_comparator_addr: 0
};
static LEG_RT_CNF: u64 = 2;
static ENABLE_CNF: u64 = 1;
static TN_VAL_SET_CNF: u64 = 0x40;
static TN_TYPE_CNF: u64 = 0x08;
static TN_INT_ENB_CNF: u64 = 0x04;
pub struct HpetDevice {
capability_addr: usize,
general_config_addr: usize,
general_interrupt_addr: usize,
main_counter_addr: usize,
t0_config_capability_addr: usize,
t0_comparator_addr: usize
}
pub unsafe fn init(hpet: &Hpet, active_table: &mut ActivePageTable) {
HPET.init(hpet, active_table);
}
impl HpetDevice {
unsafe fn init(&mut self, hpet: &Hpet, active_table: &mut ActivePageTable) {
let base_address = hpet.base_address.address as usize;
self.capability_addr = base_address;
self.general_config_addr = base_address + 0x10;
self.general_interrupt_addr = base_address + 0x20;
self.main_counter_addr = base_address + 0xF0;
self.t0_config_capability_addr = base_address + 0x100;
self.t0_comparator_addr = base_address + 0x108;
{
let page = Page::containing_address(VirtualAddress::new(base_address));
let frame = Frame::containing_address(PhysicalAddress::new(base_address));
let result = active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
result.flush(active_table);
}
println!("HPET mapped");
let counter_clk_period_fs = self.get_counter_clock_period();
let desired_fs_period: u64 = 2250286 * 1000000;
let clk_periods_per_kernel_tick: u64 = desired_fs_period / counter_clk_period_fs;
let enable_word: u64 = volatile_load(self.general_config_addr as *const u64)
| LEG_RT_CNF | ENABLE_CNF;
volatile_store(self.general_config_addr as *mut u64, enable_word);
// Enable interrupts from the HPET
let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF;
volatile_store(self.t0_config_capability_addr as *mut u64, t0_config_word);
volatile_store(self.t0_comparator_addr as *mut u64, clk_periods_per_kernel_tick);
}
pub fn get_counter_clock_period(&self) -> u64 {
unsafe { volatile_load(self.capability_addr as *const u64) >> 32 }
}
pub fn get_main_counter(&self) -> u64 {
unsafe { volatile_load(self.main_counter_addr as *const u64) }
}
}
+19 -1
View File
@@ -1,17 +1,35 @@
use paging::ActivePageTable;
use acpi::ACPI_TABLE;
use syscall::io::{Pio, Io};
pub mod cpu;
pub mod local_apic;
pub mod pic;
pub mod rtc;
pub mod serial;
pub mod hpet;
pub unsafe fn init(active_table: &mut ActivePageTable){
pic::init();
local_apic::init(active_table);
}
pub unsafe fn init_noncore() {
pub unsafe fn init_noncore(active_table: &mut ActivePageTable) {
{
if let Some(ref hpet) = ACPI_TABLE.lock().hpet {
// Disable the PIT
// TODO: Move PIT driver to kernel, and just don't enable it in the first place if we have an HPET
let mut pit_cmd = Pio::<u8>::new(0x43);
let mut pit_c0 = Pio::<u8>::new(0x40);
pit_cmd.write(0x30);
pit_c0.write(0);
pit_c0.write(0);
hpet::init(hpet, active_table);
}
}
rtc::init();
serial::init();
}
+1 -1
View File
@@ -107,7 +107,7 @@ pub unsafe extern fn kstart(kernel_base: usize, kernel_size: usize, stack_base:
acpi::init(&mut active_table);
// Initialize all of the non-core devices not otherwise needed to complete initialization
device::init_noncore();
device::init_noncore(&mut active_table);
// Initialize memory functions after core has loaded
memory::init_noncore();