rtc, non-blocking console input support

This commit is contained in:
Yuke Peng
2023-01-02 18:40:01 -08:00
parent 85b8253a2c
commit 66f582e3a6
10 changed files with 223 additions and 11 deletions

View File

@ -7,6 +7,7 @@ pub mod apic;
pub mod ioapic;
pub mod pic;
pub mod timer;
pub mod rtc;
pub use apic::ack;
pub use timer::TimerCallback;
@ -27,4 +28,5 @@ pub(crate) fn init(rsdp: Option<u64>) {
}
}
pic::init();
rtc::init();
}

View File

@ -0,0 +1,72 @@
use core::sync::atomic::AtomicU8;
use core::sync::atomic::Ordering::Relaxed;
use acpi::{sdt::Signature, fadt::Fadt};
use lazy_static::lazy_static;
use spin::Mutex;
use crate::{x86_64_util::{out8, in8}, time::Time};
use super::acpi::ACPI_TABLES;
const CMOS_ADDRESS : u16 = 0x70;
const CMOS_DATA : u16 = 0x71;
pub(crate) static CENTURY_REGISTER : AtomicU8 = AtomicU8::new(0);
lazy_static!{
static ref READ_TIME : Mutex<Time> = Mutex::new(Time::default());
}
pub fn init(){
let c = ACPI_TABLES.lock();
let r_century = unsafe{
let a = c.get_sdt::<Fadt>(Signature::FADT).unwrap().expect("not found FACP in ACPI table");
a.century
};
CENTURY_REGISTER.store(r_century, Relaxed);
}
pub fn get_cmos(reg: u8) -> u8{
out8(CMOS_ADDRESS, reg as u8);
in8(CMOS_DATA)
}
pub fn is_updating() -> bool{
out8(CMOS_ADDRESS,0x0A);
in8(CMOS_DATA) & 0x80 != 0
}
pub fn read()-> Time{
update_time();
READ_TIME.lock().clone()
}
/// read year,month,day and other data
/// ref: https://wiki.osdev.org/CMOS#Reading_All_RTC_Time_and_Date_Registers
fn update_time(){
let mut last_time :Time;
let register_b : u8;
let mut lock = READ_TIME.lock();
lock.update_from_rtc();
last_time = lock.clone();
lock.update_from_rtc();
while *lock!=last_time{
last_time = lock.clone();
lock.update_from_rtc();
}
register_b = get_cmos(0x0B);
lock.convert_bcd_to_binary(register_b);
lock.convert_12_hour_to_24_hour(register_b);
lock.modify_year();
}

View File

@ -29,6 +29,7 @@ pub mod user;
mod util;
pub mod vm;
pub(crate) mod x86_64_util;
pub mod time;
use core::{mem, panic::PanicInfo};
pub use driver::ack as apic_ack;

View File

@ -0,0 +1,75 @@
use crate::driver::rtc::{get_cmos, is_updating, CENTURY_REGISTER, read};
use core::sync::atomic::Ordering::Relaxed;
#[derive(Debug,Clone, Copy,Default,PartialEq, Eq, PartialOrd, Ord)]
pub struct Time{
century: u8,
pub year: u16,
pub month: u8,
pub day: u8,
pub hour: u8,
pub minute: u8,
pub second: u8,
}
impl Time{
pub(crate) fn update_from_rtc(&mut self){
while is_updating(){}
self.second = get_cmos(0x00);
self.minute = get_cmos(0x02);
self.hour = get_cmos(0x04);
self.day = get_cmos(0x07);
self.month = get_cmos(0x08);
self.year = get_cmos(0x09) as u16;
let century_register = CENTURY_REGISTER.load(Relaxed);
if century_register !=0{
self.century = get_cmos(century_register);
}
}
/// convert BCD to binary values
/// ref:https://wiki.osdev.org/CMOS#Reading_All_RTC_Time_and_Date_Registers
pub(crate) fn convert_bcd_to_binary(&mut self,register_b: u8){
if register_b & 0x04 == 0{
let century_register = CENTURY_REGISTER.load(Relaxed);
self.second = (self.second & 0x0F) + ((self.second / 16) * 10);
self.minute = (self.minute & 0x0F) + ((self.minute / 16) * 10);
self.hour = ( (self.hour & 0x0F) + (((self.hour & 0x70) / 16) * 10) ) | (self.hour & 0x80);
self.day = (self.day & 0x0F) + ((self.day / 16) * 10);
self.month = (self.month & 0x0F) + ((self.month / 16) * 10);
self.year = (self.year & 0x0F) + ((self.year / 16) * 10);
if century_register != 0 {
self.century = (self.century & 0x0F) + ((self.century / 16) * 10);
}
}
}
/// convert 12 hour clock to 24 hour clock
pub(crate) fn convert_12_hour_to_24_hour(&mut self,register_b:u8){
// bit1 in register_b is not set if 12 hour format is enable
// if highest bit in hour is set, then it is pm
if ((register_b & 0x02)==0) && ((self.hour & 0x80) !=0){
self.hour = ((self.hour & 0x7F) + 12) % 24;
}
}
/// convert raw year (10, 20 etc.) to real year (2010, 2020 etc.)
pub(crate) fn modify_year(&mut self){
let century_register = CENTURY_REGISTER.load(Relaxed);
if century_register !=0{
self.year += self.century as u16 * 100;
}else{
panic!("century register not exists");
}
}
}
/// get real time
pub fn get_real_time() -> Time{
read()
}