GenericAddressStructure now handles reads and writes itself
This commit is contained in:
@@ -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<Hpet> {
|
||||
pub fn new(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option<Hpet> {
|
||||
if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::<Hpet>() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user