Merge branch 'rtcd' into 'master'
Add a userspace RTC driver for x86 PCs See merge request redox-os/drivers!76
This commit is contained in:
Generated
+26
-9
@@ -14,7 +14,7 @@ dependencies = [
|
||||
"redox-daemon",
|
||||
"redox_event",
|
||||
"redox_syscall",
|
||||
"spin",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -705,7 +705,7 @@ dependencies = [
|
||||
"redox-daemon",
|
||||
"redox_event",
|
||||
"redox_syscall",
|
||||
"spin",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -809,9 +809,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.26"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "maybe-uninit"
|
||||
@@ -873,9 +873,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.1"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "orbclient"
|
||||
@@ -1226,6 +1226,14 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtcd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtl8139d"
|
||||
version = "0.1.0"
|
||||
@@ -1285,7 +1293,7 @@ dependencies = [
|
||||
"redox-daemon",
|
||||
"redox_event",
|
||||
"redox_syscall",
|
||||
"spin",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1420,6 +1428,15 @@ dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.2.5"
|
||||
@@ -1688,7 +1705,7 @@ dependencies = [
|
||||
"redox-daemon",
|
||||
"redox_event",
|
||||
"redox_syscall",
|
||||
"spin",
|
||||
"spin 0.10.0",
|
||||
"static_assertions",
|
||||
"thiserror",
|
||||
"virtio-core",
|
||||
@@ -1728,7 +1745,7 @@ dependencies = [
|
||||
"redox-daemon",
|
||||
"redox_event",
|
||||
"redox_syscall",
|
||||
"spin",
|
||||
"spin 0.9.8",
|
||||
"static_assertions",
|
||||
"virtio-core",
|
||||
]
|
||||
|
||||
@@ -7,6 +7,7 @@ members = [
|
||||
"hwd",
|
||||
"pcid",
|
||||
"pcid-spawner",
|
||||
"rtcd",
|
||||
"vboxd",
|
||||
"xhcid",
|
||||
"usbctl",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "rtcd"
|
||||
version = "0.1.0"
|
||||
authors = ["4lDO2 <4lDO2@protonmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
|
||||
common = { path = "../common" }
|
||||
@@ -0,0 +1,26 @@
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
// TODO: Do not use target architecture to distinguish these.
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod x86;
|
||||
|
||||
/// The rtc driver runs only once, being perhaps the first of all processes that init starts (since
|
||||
/// early logging benefits from knowing the time, even though this can be adjusted later once the
|
||||
/// time is known). The sole job of `rtcd` is to read from the hardware real-time clock, and then
|
||||
/// write the offset to the kernel.
|
||||
|
||||
fn main() -> Result<()> {
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
{
|
||||
common::acquire_port_io_rights().context("failed to set iopl")?;
|
||||
|
||||
let time_s = self::x86::get_time();
|
||||
let time_ns = u128::from(time_s) * 1_000_000_000;
|
||||
|
||||
std::fs::write("/scheme/sys/update_time_offset", &time_ns.to_ne_bytes())
|
||||
.context("failed to write to time offset")?;
|
||||
}
|
||||
// TODO: aarch64 is currently handled in the kernel
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
// TODO: Get RTC information from acpid.
|
||||
use common::io::{Io, Pio};
|
||||
|
||||
pub fn get_time() -> u64 {
|
||||
Rtc::new().time()
|
||||
}
|
||||
|
||||
fn cvt_bcd(value: usize) -> usize {
|
||||
(value & 0xF) + ((value / 16) * 10)
|
||||
}
|
||||
|
||||
/// RTC
|
||||
pub struct Rtc {
|
||||
addr: Pio<u8>,
|
||||
data: Pio<u8>,
|
||||
nmi: bool,
|
||||
}
|
||||
|
||||
impl Rtc {
|
||||
/// Create new empty RTC
|
||||
pub fn new() -> Self {
|
||||
Rtc {
|
||||
addr: Pio::<u8>::new(0x70),
|
||||
data: Pio::<u8>::new(0x71),
|
||||
nmi: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read
|
||||
unsafe fn read(&mut self, reg: u8) -> u8 {
|
||||
if self.nmi {
|
||||
self.addr.write(reg & 0x7F);
|
||||
} else {
|
||||
self.addr.write(reg | 0x80);
|
||||
}
|
||||
self.data.read()
|
||||
}
|
||||
|
||||
/// Write
|
||||
#[allow(dead_code)]
|
||||
unsafe fn write(&mut self, reg: u8, value: u8) {
|
||||
if self.nmi {
|
||||
self.addr.write(reg & 0x7F);
|
||||
} else {
|
||||
self.addr.write(reg | 0x80);
|
||||
}
|
||||
self.data.write(value);
|
||||
}
|
||||
|
||||
/// Wait for an update, can take one second if full is specified!
|
||||
unsafe fn wait(&mut self, full: bool) {
|
||||
if full {
|
||||
while self.read(0xA) & 0x80 != 0x80 {}
|
||||
}
|
||||
while self.read(0xA) & 0x80 == 0x80 {}
|
||||
}
|
||||
|
||||
/// Get time without waiting
|
||||
pub unsafe fn time_no_wait(&mut self) -> u64 {
|
||||
/*let century_register = if let Some(ref fadt) = acpi::ACPI_TABLE.lock().fadt {
|
||||
Some(fadt.century)
|
||||
} else {
|
||||
None
|
||||
};*/
|
||||
|
||||
let mut second = self.read(0) as usize;
|
||||
let mut minute = self.read(2) as usize;
|
||||
let mut hour = self.read(4) as usize;
|
||||
let mut day = self.read(7) as usize;
|
||||
let mut month = self.read(8) as usize;
|
||||
let mut year = self.read(9) as usize;
|
||||
let mut century = /* TODO: Fix invalid value from VirtualBox
|
||||
if let Some(century_reg) = century_register {
|
||||
self.read(century_reg) as usize
|
||||
} else */ {
|
||||
20
|
||||
};
|
||||
let register_b = self.read(0xB);
|
||||
|
||||
if register_b & 4 != 4 {
|
||||
second = cvt_bcd(second);
|
||||
minute = cvt_bcd(minute);
|
||||
hour = cvt_bcd(hour & 0x7F) | (hour & 0x80);
|
||||
day = cvt_bcd(day);
|
||||
month = cvt_bcd(month);
|
||||
year = cvt_bcd(year);
|
||||
century = /* TODO: Fix invalid value from VirtualBox
|
||||
if century_register.is_some() {
|
||||
cvt_bcd(century)
|
||||
} else */ {
|
||||
century
|
||||
};
|
||||
}
|
||||
|
||||
if register_b & 2 != 2 || hour & 0x80 == 0x80 {
|
||||
hour = ((hour & 0x7F) + 12) % 24;
|
||||
}
|
||||
|
||||
year += century * 100;
|
||||
|
||||
// Unix time from clock
|
||||
let mut secs: u64 = (year as u64 - 1970) * 31_536_000;
|
||||
|
||||
let mut leap_days = (year as u64 - 1972) / 4 + 1;
|
||||
if year % 4 == 0 && month <= 2 {
|
||||
leap_days -= 1;
|
||||
}
|
||||
secs += leap_days * 86_400;
|
||||
|
||||
match month {
|
||||
2 => secs += 2_678_400,
|
||||
3 => secs += 5_097_600,
|
||||
4 => secs += 7_776_000,
|
||||
5 => secs += 10_368_000,
|
||||
6 => secs += 13_046_400,
|
||||
7 => secs += 15_638_400,
|
||||
8 => secs += 18_316_800,
|
||||
9 => secs += 20_995_200,
|
||||
10 => secs += 23_587_200,
|
||||
11 => secs += 26_265_600,
|
||||
12 => secs += 28_857_600,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
secs += (day as u64 - 1) * 86_400;
|
||||
secs += hour as u64 * 3600;
|
||||
secs += minute as u64 * 60;
|
||||
secs += second as u64;
|
||||
|
||||
secs
|
||||
}
|
||||
|
||||
/// Get time
|
||||
pub fn time(&mut self) -> u64 {
|
||||
loop {
|
||||
unsafe {
|
||||
self.wait(false);
|
||||
let time = self.time_no_wait();
|
||||
self.wait(false);
|
||||
let next_time = self.time_no_wait();
|
||||
if time == next_time {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user