diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 664b6bb..74b14ea 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -1,6 +1,10 @@ use core::{mem, ptr}; use super::sdt::Sdt; +use core::intrinsics::{volatile_load, volatile_store}; + +use memory::Frame; +use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; #[repr(packed)] #[derive(Clone, Copy, Debug, Default)] @@ -29,11 +33,30 @@ pub struct Hpet { } impl Hpet { - pub fn new(sdt: &'static Sdt) -> Option { + pub fn new(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option { if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::() { - Some(unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) }) + let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) }; + unsafe { s.base_address.init(active_table) }; + Some(s) } else { None } } } + +impl GenericAddressStructure { + pub unsafe fn init(&self, active_table: &mut ActivePageTable) { + let page = Page::containing_address(VirtualAddress::new(self.address as usize)); + let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize)); + let result = active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); + result.flush(active_table); + } + + pub unsafe fn read_u64(&self, offset: usize) -> u64{ + volatile_load((self.address as usize + offset) as *const u64) + } + + pub unsafe fn write_u64(&mut self, offset: usize, value: u64) { + volatile_store((self.address as usize + offset) as *mut u64, value); + } +} diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index d246609..ada10d1 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -203,7 +203,7 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { _ => () } } - } else if let Some(hpet) = Hpet::new(sdt) { + } else if let Some(hpet) = Hpet::new(sdt, active_table) { println!(": {}", hpet.hpet_number); let mut hpet_t = ACPI_TABLE.hpet.write(); diff --git a/src/device/hpet.rs b/src/device/hpet.rs index 3f88f36..9307fc5 100644 --- a/src/device/hpet.rs +++ b/src/device/hpet.rs @@ -5,15 +5,6 @@ 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; @@ -21,62 +12,24 @@ 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) } - } +static CAPABILITY_OFFSET: usize = 0x00; +static GENERAL_CONFIG_OFFSET: usize = 0x10; +static GENERAL_INTERRUPT_OFFSET: usize = 0x20; +static MAIN_COUNTER_OFFSET: usize = 0xF0; +static T0_CONFIG_CAPABILITY_OFFSET: usize = 0x100; +static T0_COMPARATOR_OFFSET: usize = 0x108; + +pub unsafe fn init(hpet: &mut Hpet) { + let counter_clk_period_fs = hpet.base_address.read_u64(CAPABILITY_OFFSET) >> 32; + 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 = hpet.base_address.read_u64(GENERAL_CONFIG_OFFSET) | LEG_RT_CNF | ENABLE_CNF; + hpet.base_address.write_u64(GENERAL_CONFIG_OFFSET, enable_word); + // Enable interrupts from the HPET + + let t0_config_word: u64 = TN_VAL_SET_CNF | TN_TYPE_CNF | TN_INT_ENB_CNF; + hpet.base_address.write_u64(T0_CONFIG_CAPABILITY_OFFSET, t0_config_word); + hpet.base_address.write_u64(T0_COMPARATOR_OFFSET, clk_periods_per_kernel_tick); } diff --git a/src/device/mod.rs b/src/device/mod.rs index 568f395..18700d0 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -15,10 +15,10 @@ pub unsafe fn init(active_table: &mut ActivePageTable){ local_apic::init(active_table); } -pub unsafe fn init_noncore(active_table: &mut ActivePageTable) { +pub unsafe fn init_noncore() { { - if let Some(ref hpet) = *ACPI_TABLE.hpet.read() { - hpet::init(hpet, active_table); + if let Some(ref mut hpet) = *ACPI_TABLE.hpet.write() { + hpet::init(hpet); } else { pit::init(); } diff --git a/src/start.rs b/src/start.rs index 8f88204..d7b3663 100644 --- a/src/start.rs +++ b/src/start.rs @@ -109,7 +109,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(&mut active_table); + device::init_noncore(); // Initialize memory functions after core has loaded memory::init_noncore();