Merge pull request #36 from CWood1/hpet

HPET Driver
This commit is contained in:
Jeremy Soller
2017-07-14 08:32:52 -06:00
committed by GitHub
6 changed files with 162 additions and 3 deletions

39
src/acpi/hpet.rs Normal file
View File

@@ -0,0 +1,39 @@
use core::{mem, ptr};
use super::sdt::Sdt;
#[repr(packed)]
#[derive(Clone, Copy, Debug, Default)]
pub struct GenericAddressStructure {
address_space: u8,
bit_width: u8,
bit_offset: u8,
access_size: u8,
pub address: u64,
}
#[repr(packed)]
#[derive(Debug)]
pub struct Hpet {
pub header: Sdt,
pub hw_rev_id: u8,
pub comparator_descriptor: u8,
pub pci_vendor_id: u16,
pub base_address: GenericAddressStructure,
pub hpet_number: u8,
pub min_periodic_clk_tick: u16,
pub oem_attribute: u8
}
impl Hpet {
pub fn new(sdt: &'static Sdt) -> 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) })
} else {
None
}
}
}

View File

@@ -18,9 +18,11 @@ use self::madt::{Madt, MadtEntry};
use self::rsdt::Rsdt;
use self::sdt::Sdt;
use self::xsdt::Xsdt;
use self::hpet::Hpet;
use self::aml::{is_aml_table, parse_aml_table, AmlNamespace, AmlError};
pub mod hpet;
mod dmar;
mod fadt;
mod madt;
@@ -195,6 +197,9 @@ fn parse_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
_ => ()
}
}
} else if let Some(hpet) = Hpet::new(sdt) {
println!(": {}", hpet.hpet_number);
ACPI_TABLE.lock().hpet = Some(hpet);
} else if is_aml_table(sdt) {
ACPI_TABLE.lock().namespace = match parse_aml_table(sdt) {
Ok(res) => {
@@ -269,9 +274,10 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
pub struct Acpi {
pub fadt: Option<Fadt>,
pub namespace: Option<AmlNamespace>,
pub hpet: Option<Hpet>
}
pub static ACPI_TABLE: Mutex<Acpi> = Mutex::new(Acpi { fadt: None, namespace: None });
pub static ACPI_TABLE: Mutex<Acpi> = Mutex::new(Acpi { fadt: None, namespace: None, hpet: None });
/// RSDP
#[derive(Copy, Clone, Debug)]

82
src/device/hpet.rs Normal file
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) }
}
}

View File

@@ -1,17 +1,29 @@
use paging::ActivePageTable;
use acpi::ACPI_TABLE;
use syscall::io::{Pio, Io};
pub mod cpu;
pub mod local_apic;
pub mod pic;
pub mod pit;
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 {
hpet::init(hpet, active_table);
} else {
pit::init();
}
}
rtc::init();
serial::init();
}

20
src/device/pit.rs Normal file
View File

@@ -0,0 +1,20 @@
use syscall::io::{Io, Pio};
pub static mut CHAN0: Pio<u8> = Pio::new(0x40);
pub static mut CHAN1: Pio<u8> = Pio::new(0x41);
pub static mut CHAN2: Pio<u8> = Pio::new(0x42);
pub static mut COMMAND: Pio<u8> = Pio::new(0x43);
static SELECT_CHAN0: u8 = 0;
static LOHI: u8 = 0x30;
static MODE3: u8 = 3;
static CHAN0_DIVISOR: u16 = 2685;
pub unsafe fn init() {
COMMAND.write(SELECT_CHAN0 | LOHI | MODE3);
CHAN0.write((CHAN0_DIVISOR & 0xFF) as u8);
CHAN0.write((CHAN0_DIVISOR >> 8) as u8);
println!("Using PIT");
}

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