mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-27 19:33:23 +00:00
rtc, non-blocking console input support
This commit is contained in:
@ -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();
|
||||
}
|
||||
|
72
src/framework/jinux-frame/src/driver/rtc.rs
Normal file
72
src/framework/jinux-frame/src/driver/rtc.rs
Normal 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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
75
src/framework/jinux-frame/src/time.rs
Normal file
75
src/framework/jinux-frame/src/time.rs
Normal 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()
|
||||
}
|
||||
|
Reference in New Issue
Block a user