Merge pull request #6 from CWood1/rtc-century

Implemented reading from RTC Century counter in x86_64 arch, if available
This commit is contained in:
Jeremy Soller
2017-03-19 07:29:30 -06:00
committed by GitHub
4 changed files with 68 additions and 11 deletions

View File

@@ -4,6 +4,8 @@
use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering;
use spin::Mutex;
use device::local_apic::LOCAL_APIC;
use interrupt;
use memory::{allocate_frames, Frame};
@@ -27,7 +29,13 @@ pub mod xsdt;
const TRAMPOLINE: usize = 0x7E00;
const AP_STARTUP: usize = TRAMPOLINE + 512;
pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
pub enum AcpiTable {
fadt(Fadt),
madt(Madt),
dmar(Dmar)
}
pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option<AcpiTable> {
print!(" ");
for &c in sdt.signature.iter() {
print!("{}", c as char);
@@ -35,6 +43,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
if let Some(fadt) = Fadt::new(sdt) {
println!(": {:#?}", fadt);
Some(AcpiTable::fadt(fadt))
} else if let Some(madt) = Madt::new(sdt) {
println!(": {:>08X}: {}", madt.local_address, madt.flags);
@@ -138,6 +147,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
// Unmap trampoline
let result = active_table.unmap(trampoline_page);
result.flush(active_table);
Some(AcpiTable::madt(madt))
} else if let Some(dmar) = Dmar::new(sdt) {
println!(": {}: {}", dmar.addr_width, dmar.flags);
@@ -157,16 +167,20 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
_ => ()
}
}
Some(AcpiTable::dmar(dmar))
} else {
println!(": Unknown");
None
}
}
/// Parse the ACPI tables to gather CPU, interrupt, and timer information
pub unsafe fn init(active_table: &mut ActivePageTable) -> Option<Acpi> {
pub unsafe fn init(active_table: &mut ActivePageTable) {
let start_addr = 0xE0000;
let end_addr = 0xFFFFF;
let mut theFADT: Option<Fadt> = None;
// Map all of the ACPI RSDP space
{
let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr));
@@ -212,14 +226,26 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option<Acpi> {
if let Some(rsdt) = Rsdt::new(rxsdt) {
for sdt_address in rsdt.iter() {
let (sdt, mapped) = get_sdt(sdt_address, active_table);
init_sdt(sdt, active_table);
drop_sdt(sdt, mapped, active_table);
// If we find the FADT, rather than drop it, save a copy of the pointer, as this is needed elsewhere.
// TODO: Eventually, save pointers to all tables containing pertinent information to other parts of
// the kernel
match init_sdt(sdt, active_table) {
Some(AcpiTable::fadt(fadt)) => theFADT = Some(fadt),
_ => drop_sdt(sdt, mapped, active_table)
}
}
} else if let Some(xsdt) = Xsdt::new(rxsdt) {
for sdt_address in xsdt.iter() {
let (sdt, mapped) = get_sdt(sdt_address, active_table);
init_sdt(sdt, active_table);
drop_sdt(sdt, mapped, active_table);
// If we find the FADT, rather than drop it, save a copy of the pointer, as this is needed elsewhere.
// TODO: Eventually, save pointers to all tables containing pertinent information to other parts of
// the kernel
match init_sdt(sdt, active_table) {
Some(AcpiTable::fadt(fadt)) => theFADT = Some(fadt),
_ => drop_sdt(sdt, mapped, active_table)
}
}
} else {
println!("UNKNOWN RSDT OR XSDT SIGNATURE");
@@ -241,10 +267,16 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option<Acpi> {
}
}
None
if let Some(fadt) = theFADT {
ACPI_TABLE.lock().fadt = Some(fadt);
}
}
pub struct Acpi;
pub struct Acpi {
pub fadt: Option<Fadt>
}
pub static ACPI_TABLE: Mutex<Acpi> = Mutex::new(Acpi { fadt: None });
/// RSDP
#[derive(Copy, Clone, Debug)]

View File

@@ -9,6 +9,9 @@ pub mod serial;
pub unsafe fn init(active_table: &mut ActivePageTable){
pic::init();
local_apic::init(active_table);
}
pub unsafe fn init_noncore() {
rtc::init();
serial::init();
}

View File

@@ -1,6 +1,8 @@
use syscall::io::{Io, Pio};
use time;
use acpi;
pub fn init() {
let mut rtc = Rtc::new();
time::START.lock().0 = rtc.time();
@@ -45,7 +47,15 @@ impl Rtc {
let mut day;
let mut month;
let mut year;
let mut century;
let register_b;
let century_register = if let Some(ref fadt) = acpi::ACPI_TABLE.lock().fadt {
Some(fadt.century)
} else {
None
};
unsafe {
self.wait();
second = self.read(0) as usize;
@@ -54,6 +64,11 @@ impl Rtc {
day = self.read(7) as usize;
month = self.read(8) as usize;
year = self.read(9) as usize;
century = if let Some(century_reg) = century_register {
self.read(century_reg) as usize
} else {
20 as usize
};
register_b = self.read(0xB);
}
@@ -64,14 +79,18 @@ impl Rtc {
day = cvt_bcd(day);
month = cvt_bcd(month);
year = cvt_bcd(year);
century = if let Some(century_reg) = century_register {
cvt_bcd(century)
} else {
century
};
}
if register_b & 2 != 2 || hour & 0x80 == 0x80 {
hour = ((hour & 0x7F) + 12) % 24;
}
// TODO: Century Register
year += 2000;
year += century * 100;
// Unix time from clock
let mut secs: u64 = (year as u64 - 1970) * 31536000;

View File

@@ -113,13 +113,16 @@ pub unsafe extern fn kstart() -> ! {
// Init the allocator
allocator::init(::KERNEL_HEAP_OFFSET, ::KERNEL_HEAP_SIZE);
}
// Initialize devices
device::init(&mut active_table);
// Read ACPI tables, starts APs
acpi::init(&mut active_table);
// Initialize all of the non-core devices not otherwise needed to complete initialization
device::init_noncore();
BSP_READY.store(true, Ordering::SeqCst);
}