GenericAddressStructure now handles reads and writes itself

This commit is contained in:
Connor Wood
2017-07-21 12:42:11 +01:00
parent 2256e0288b
commit 5c05b48921
5 changed files with 50 additions and 74 deletions

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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();