mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-25 17:33:28 +04:00
Add cmos rtc driver for x86
This commit is contained in:
parent
1a1e39c960
commit
c6c89198cd
@ -6,6 +6,7 @@ pub mod pic;
|
||||
pub mod keyboard;
|
||||
pub mod pit;
|
||||
pub mod ide;
|
||||
pub mod rtc_cmos;
|
||||
|
||||
pub fn init() {
|
||||
assert_has_not_been_called!();
|
||||
|
78
kernel/src/arch/x86_64/driver/rtc_cmos.rs
Normal file
78
kernel/src/arch/x86_64/driver/rtc_cmos.rs
Normal file
@ -0,0 +1,78 @@
|
||||
//! Driver for x86 CMOS RTC clock
|
||||
use crate::arch::interrupt;
|
||||
use log::*;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
const CMOS_ADDR: u16 = 0x70;
|
||||
const CMOS_DATA: u16 = 0x71;
|
||||
|
||||
unsafe fn check_updating() -> bool {
|
||||
let mut addr = Port::<u8>::new(CMOS_ADDR);
|
||||
let data = Port::<u8>::new(CMOS_DATA);
|
||||
|
||||
addr.write(0x0A);
|
||||
return (data.read() & 0x80) != 0;
|
||||
}
|
||||
|
||||
unsafe fn read_rtc(reg: u8) -> u8 {
|
||||
let mut addr = Port::<u8>::new(CMOS_ADDR);
|
||||
let data = Port::<u8>::new(CMOS_DATA);
|
||||
|
||||
addr.write(reg);
|
||||
return data.read();
|
||||
}
|
||||
|
||||
fn bcd2bin(num: u64) -> u64 {
|
||||
(num & 0x0f) + (num >> 4) * 10
|
||||
}
|
||||
|
||||
// read seconds since 1970-01-01
|
||||
pub fn read_epoch() -> u64 {
|
||||
unsafe {
|
||||
let flags = interrupt::disable_and_store();
|
||||
|
||||
while check_updating() {}
|
||||
|
||||
let mut second = read_rtc(0x00) as u64;
|
||||
let mut minute = read_rtc(0x02) as u64;
|
||||
let mut hour = read_rtc(0x04) as u64;
|
||||
let mut day = read_rtc(0x07) as u64;
|
||||
let mut month = read_rtc(0x08) as u64;
|
||||
let mut year = read_rtc(0x09) as u64;
|
||||
|
||||
let control = read_rtc(0x0B);
|
||||
if (control & 0x04) == 0 {
|
||||
// BCD
|
||||
second = bcd2bin(second);
|
||||
minute = bcd2bin(minute);
|
||||
hour = bcd2bin(hour);
|
||||
day = bcd2bin(day);
|
||||
month = bcd2bin(month);
|
||||
year = bcd2bin(year);
|
||||
}
|
||||
|
||||
// TODO: parse ACPI and find century register
|
||||
year += 2000;
|
||||
|
||||
// mktime64
|
||||
if month <= 2 {
|
||||
month = month + 10;
|
||||
year = year - 1;
|
||||
} else {
|
||||
month = month - 2;
|
||||
}
|
||||
|
||||
let result = ((((year / 4 - year / 100 + year / 400 + 367 * month / 12 + day) + year * 365
|
||||
- 719499)
|
||||
* 24
|
||||
+ hour)
|
||||
* 60
|
||||
+ minute)
|
||||
* 60
|
||||
+ second;
|
||||
|
||||
interrupt::restore(flags);
|
||||
|
||||
result
|
||||
}
|
||||
}
|
@ -178,9 +178,7 @@ impl PciTag {
|
||||
self.write(cap_ptr + PCI_MSI_DATA, 55 | 0 << 12);
|
||||
|
||||
let orig_ctrl = self.read(cap_ptr + PCI_MSI_CTRL_CAP, 4);
|
||||
debug!("orig ctrl {:b}", orig_ctrl);
|
||||
self.write(cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
|
||||
debug!("new ctrl {:b}", self.read(cap_ptr + PCI_MSI_CTRL_CAP, 2));
|
||||
break;
|
||||
}
|
||||
info!("cap id {} at {:#X}", self.read(cap_ptr, 1), cap_ptr);
|
||||
|
@ -6,19 +6,19 @@ use core::mem::{size_of, transmute};
|
||||
use core::slice;
|
||||
use core::sync::atomic::{fence, Ordering};
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use bitflags::*;
|
||||
use log::*;
|
||||
use rcore_memory::paging::PageTable;
|
||||
use rcore_memory::PAGE_SIZE;
|
||||
use smoltcp::iface::*;
|
||||
use smoltcp::phy::{self, DeviceCapabilities};
|
||||
use smoltcp::socket::*;
|
||||
use smoltcp::time::Instant;
|
||||
use smoltcp::wire::EthernetAddress;
|
||||
use smoltcp::Result;
|
||||
use smoltcp::wire::*;
|
||||
use smoltcp::iface::*;
|
||||
use smoltcp::socket::*;
|
||||
use alloc::collections::BTreeMap;
|
||||
use volatile::{Volatile};
|
||||
use smoltcp::Result;
|
||||
use volatile::Volatile;
|
||||
|
||||
use crate::memory::active_table;
|
||||
use crate::sync::SpinNoIrqLock as Mutex;
|
||||
@ -79,8 +79,9 @@ impl Driver for E1000Interface {
|
||||
current_addr = current_addr + PAGE_SIZE;
|
||||
}
|
||||
|
||||
let e1000 =
|
||||
unsafe { slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4) };
|
||||
let e1000 = unsafe {
|
||||
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
|
||||
};
|
||||
|
||||
let icr = e1000[E1000_ICR].read();
|
||||
if icr != 0 {
|
||||
@ -416,7 +417,7 @@ pub fn e1000_init(header: usize, size: usize) {
|
||||
|
||||
// EN | PSP | CT=0x10 | COLD=0x40
|
||||
e1000[E1000_TCTL].write((1 << 1) | (1 << 3) | (0x10 << 4) | (0x40 << 12)); // TCTL
|
||||
// IPGT=0xa | IPGR1=0x8 | IPGR2=0xc
|
||||
// IPGT=0xa | IPGR1=0x8 | IPGR2=0xc
|
||||
e1000[E1000_TIPG].write(0xa | (0x8 << 10) | (0xc << 20)); // TIPG
|
||||
|
||||
let mut ral: u32 = 0;
|
||||
@ -429,7 +430,7 @@ pub fn e1000_init(header: usize, size: usize) {
|
||||
}
|
||||
|
||||
e1000[E1000_RAL].write(ral); // RAL
|
||||
// AV | AS=DA
|
||||
// AV | AS=DA
|
||||
e1000[E1000_RAH].write(rah | (1 << 31)); // RAH
|
||||
|
||||
// MTA
|
||||
@ -471,7 +472,7 @@ pub fn e1000_init(header: usize, size: usize) {
|
||||
let net_driver = E1000Driver(Arc::new(Mutex::new(driver)));
|
||||
|
||||
let ethernet_addr = EthernetAddress::from_bytes(&mac);
|
||||
let ip_addrs = [IpCidr::new(IpAddress::v4(10,0,0,2), 24)];
|
||||
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 0, 2), 24)];
|
||||
let neighbor_cache = NeighborCache::new(BTreeMap::new());
|
||||
let iface = EthernetInterfaceBuilder::new(net_driver.clone())
|
||||
.ethernet_addr(ethernet_addr)
|
||||
|
@ -80,7 +80,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
||||
083 => sys_mkdir(args[0] as *const u8, args[1]),
|
||||
086 => sys_link(args[0] as *const u8, args[1] as *const u8),
|
||||
087 => sys_unlink(args[0] as *const u8),
|
||||
096 => sys_get_time(), // TODO: sys_gettimeofday
|
||||
096 => sys_gettimeofday(args[0] as *mut u64, args[1] as *const u8),
|
||||
// 097 => sys_getrlimit(),
|
||||
// 098 => sys_getrusage(),
|
||||
110 => sys_getppid(),
|
||||
|
@ -172,6 +172,7 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
|
||||
|
||||
match socket.connect((dest.unwrap(), port), temp_port) {
|
||||
Ok(()) => {
|
||||
// avoid deadlock
|
||||
drop(socket);
|
||||
drop(sockets);
|
||||
|
||||
@ -185,12 +186,12 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
|
||||
// still connecting
|
||||
SOCKET_ACTIVITY._wait()
|
||||
} else if socket.state() == TcpState::Established {
|
||||
break Ok(0)
|
||||
break Ok(0);
|
||||
} else if socket.state() == TcpState::Closed {
|
||||
break Err(SysError::ECONNREFUSED)
|
||||
break Err(SysError::ECONNREFUSED);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(_) => Err(SysError::ENOBUFS),
|
||||
}
|
||||
} else {
|
||||
@ -210,18 +211,20 @@ pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usi
|
||||
if socket.can_send() {
|
||||
match socket.send_slice(&slice) {
|
||||
Ok(size) => {
|
||||
// avoid deadlock
|
||||
drop(socket);
|
||||
drop(sockets);
|
||||
|
||||
iface.poll();
|
||||
Ok(size as isize)
|
||||
},
|
||||
}
|
||||
Err(err) => Err(SysError::ENOBUFS),
|
||||
}
|
||||
} else {
|
||||
Err(SysError::ENOBUFS)
|
||||
}
|
||||
} else {
|
||||
Err(SysError::ECONNREFUSED)
|
||||
Err(SysError::ENOTCONN)
|
||||
}
|
||||
} else {
|
||||
unimplemented!("socket type")
|
||||
@ -291,6 +294,7 @@ pub fn sys_sendto(
|
||||
|
||||
socket.send_slice(&buffer).unwrap();
|
||||
|
||||
// avoid deadlock
|
||||
drop(socket);
|
||||
drop(sockets);
|
||||
iface.poll();
|
||||
@ -338,6 +342,7 @@ pub fn sys_recvfrom(
|
||||
return Ok(size as isize);
|
||||
}
|
||||
|
||||
// avoid deadlock
|
||||
drop(socket);
|
||||
SOCKET_ACTIVITY._wait()
|
||||
}
|
||||
|
@ -1,13 +1,22 @@
|
||||
//! Syscalls for time
|
||||
|
||||
use super::*;
|
||||
use crate::arch::driver::rtc_cmos;
|
||||
|
||||
pub fn sys_get_time() -> SysResult {
|
||||
unsafe { Ok(crate::trap::TICK as isize) }
|
||||
pub fn sys_gettimeofday(tv: *mut u64, tz: *const u8) -> SysResult {
|
||||
if tz as usize != 0 {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
|
||||
let mut proc = process();
|
||||
proc.memory_set.check_mut_ptr(tv)?;
|
||||
|
||||
unsafe { *tv = rtc_cmos::read_epoch() };
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_time(time: *mut u64) -> SysResult {
|
||||
let t = unsafe { crate::trap::TICK };
|
||||
let t = rtc_cmos::read_epoch();
|
||||
if time as usize != 0 {
|
||||
let mut proc = process();
|
||||
proc.memory_set.check_mut_ptr(time)?;
|
||||
|
Loading…
Reference in New Issue
Block a user