diff --git a/arch/x86_64/src/acpi/mod.rs b/arch/x86_64/src/acpi/mod.rs index 092f609..b6c05ff 100644 --- a/arch/x86_64/src/acpi/mod.rs +++ b/arch/x86_64/src/acpi/mod.rs @@ -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 { 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 { +pub unsafe fn init(active_table: &mut ActivePageTable) { let start_addr = 0xE0000; let end_addr = 0xFFFFF; + let mut theFADT: Option = 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 { 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 { } } - None + if let Some(fadt) = theFADT { + ACPI_TABLE.lock().fadt = Some(fadt); + } } -pub struct Acpi; +pub struct Acpi { + pub fadt: Option +} + +pub static ACPI_TABLE: Mutex = Mutex::new(Acpi { fadt: None }); /// RSDP #[derive(Copy, Clone, Debug)] diff --git a/arch/x86_64/src/device/mod.rs b/arch/x86_64/src/device/mod.rs index 522b2b4..ef27ccb 100644 --- a/arch/x86_64/src/device/mod.rs +++ b/arch/x86_64/src/device/mod.rs @@ -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(); } diff --git a/arch/x86_64/src/device/rtc.rs b/arch/x86_64/src/device/rtc.rs index bfef1fc..bed9d75 100644 --- a/arch/x86_64/src/device/rtc.rs +++ b/arch/x86_64/src/device/rtc.rs @@ -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; diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index 4488009..ceab042 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -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); }