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 keyboard;
|
||||||
pub mod pit;
|
pub mod pit;
|
||||||
pub mod ide;
|
pub mod ide;
|
||||||
|
pub mod rtc_cmos;
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
assert_has_not_been_called!();
|
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);
|
self.write(cap_ptr + PCI_MSI_DATA, 55 | 0 << 12);
|
||||||
|
|
||||||
let orig_ctrl = self.read(cap_ptr + PCI_MSI_CTRL_CAP, 4);
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
info!("cap id {} at {:#X}", self.read(cap_ptr, 1), cap_ptr);
|
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::slice;
|
||||||
use core::sync::atomic::{fence, Ordering};
|
use core::sync::atomic::{fence, Ordering};
|
||||||
|
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
use bitflags::*;
|
use bitflags::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use rcore_memory::paging::PageTable;
|
use rcore_memory::paging::PageTable;
|
||||||
use rcore_memory::PAGE_SIZE;
|
use rcore_memory::PAGE_SIZE;
|
||||||
|
use smoltcp::iface::*;
|
||||||
use smoltcp::phy::{self, DeviceCapabilities};
|
use smoltcp::phy::{self, DeviceCapabilities};
|
||||||
|
use smoltcp::socket::*;
|
||||||
use smoltcp::time::Instant;
|
use smoltcp::time::Instant;
|
||||||
use smoltcp::wire::EthernetAddress;
|
use smoltcp::wire::EthernetAddress;
|
||||||
use smoltcp::Result;
|
|
||||||
use smoltcp::wire::*;
|
use smoltcp::wire::*;
|
||||||
use smoltcp::iface::*;
|
use smoltcp::Result;
|
||||||
use smoltcp::socket::*;
|
use volatile::Volatile;
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use volatile::{Volatile};
|
|
||||||
|
|
||||||
use crate::memory::active_table;
|
use crate::memory::active_table;
|
||||||
use crate::sync::SpinNoIrqLock as Mutex;
|
use crate::sync::SpinNoIrqLock as Mutex;
|
||||||
@ -79,8 +79,9 @@ impl Driver for E1000Interface {
|
|||||||
current_addr = current_addr + PAGE_SIZE;
|
current_addr = current_addr + PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
let e1000 =
|
let e1000 = unsafe {
|
||||||
unsafe { slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4) };
|
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
|
||||||
|
};
|
||||||
|
|
||||||
let icr = e1000[E1000_ICR].read();
|
let icr = e1000[E1000_ICR].read();
|
||||||
if icr != 0 {
|
if icr != 0 {
|
||||||
@ -416,7 +417,7 @@ pub fn e1000_init(header: usize, size: usize) {
|
|||||||
|
|
||||||
// EN | PSP | CT=0x10 | COLD=0x40
|
// EN | PSP | CT=0x10 | COLD=0x40
|
||||||
e1000[E1000_TCTL].write((1 << 1) | (1 << 3) | (0x10 << 4) | (0x40 << 12)); // TCTL
|
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
|
e1000[E1000_TIPG].write(0xa | (0x8 << 10) | (0xc << 20)); // TIPG
|
||||||
|
|
||||||
let mut ral: u32 = 0;
|
let mut ral: u32 = 0;
|
||||||
@ -429,7 +430,7 @@ pub fn e1000_init(header: usize, size: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
e1000[E1000_RAL].write(ral); // RAL
|
e1000[E1000_RAL].write(ral); // RAL
|
||||||
// AV | AS=DA
|
// AV | AS=DA
|
||||||
e1000[E1000_RAH].write(rah | (1 << 31)); // RAH
|
e1000[E1000_RAH].write(rah | (1 << 31)); // RAH
|
||||||
|
|
||||||
// MTA
|
// MTA
|
||||||
@ -471,7 +472,7 @@ pub fn e1000_init(header: usize, size: usize) {
|
|||||||
let net_driver = E1000Driver(Arc::new(Mutex::new(driver)));
|
let net_driver = E1000Driver(Arc::new(Mutex::new(driver)));
|
||||||
|
|
||||||
let ethernet_addr = EthernetAddress::from_bytes(&mac);
|
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 neighbor_cache = NeighborCache::new(BTreeMap::new());
|
||||||
let iface = EthernetInterfaceBuilder::new(net_driver.clone())
|
let iface = EthernetInterfaceBuilder::new(net_driver.clone())
|
||||||
.ethernet_addr(ethernet_addr)
|
.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]),
|
083 => sys_mkdir(args[0] as *const u8, args[1]),
|
||||||
086 => sys_link(args[0] as *const u8, args[1] as *const u8),
|
086 => sys_link(args[0] as *const u8, args[1] as *const u8),
|
||||||
087 => sys_unlink(args[0] 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(),
|
// 097 => sys_getrlimit(),
|
||||||
// 098 => sys_getrusage(),
|
// 098 => sys_getrusage(),
|
||||||
110 => sys_getppid(),
|
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) {
|
match socket.connect((dest.unwrap(), port), temp_port) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
// avoid deadlock
|
||||||
drop(socket);
|
drop(socket);
|
||||||
drop(sockets);
|
drop(sockets);
|
||||||
|
|
||||||
@ -185,12 +186,12 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
|
|||||||
// still connecting
|
// still connecting
|
||||||
SOCKET_ACTIVITY._wait()
|
SOCKET_ACTIVITY._wait()
|
||||||
} else if socket.state() == TcpState::Established {
|
} else if socket.state() == TcpState::Established {
|
||||||
break Ok(0)
|
break Ok(0);
|
||||||
} else if socket.state() == TcpState::Closed {
|
} else if socket.state() == TcpState::Closed {
|
||||||
break Err(SysError::ECONNREFUSED)
|
break Err(SysError::ECONNREFUSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(_) => Err(SysError::ENOBUFS),
|
Err(_) => Err(SysError::ENOBUFS),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -210,18 +211,20 @@ pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usi
|
|||||||
if socket.can_send() {
|
if socket.can_send() {
|
||||||
match socket.send_slice(&slice) {
|
match socket.send_slice(&slice) {
|
||||||
Ok(size) => {
|
Ok(size) => {
|
||||||
|
// avoid deadlock
|
||||||
drop(socket);
|
drop(socket);
|
||||||
drop(sockets);
|
drop(sockets);
|
||||||
|
|
||||||
iface.poll();
|
iface.poll();
|
||||||
Ok(size as isize)
|
Ok(size as isize)
|
||||||
},
|
}
|
||||||
Err(err) => Err(SysError::ENOBUFS),
|
Err(err) => Err(SysError::ENOBUFS),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(SysError::ENOBUFS)
|
Err(SysError::ENOBUFS)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(SysError::ECONNREFUSED)
|
Err(SysError::ENOTCONN)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unimplemented!("socket type")
|
unimplemented!("socket type")
|
||||||
@ -291,6 +294,7 @@ pub fn sys_sendto(
|
|||||||
|
|
||||||
socket.send_slice(&buffer).unwrap();
|
socket.send_slice(&buffer).unwrap();
|
||||||
|
|
||||||
|
// avoid deadlock
|
||||||
drop(socket);
|
drop(socket);
|
||||||
drop(sockets);
|
drop(sockets);
|
||||||
iface.poll();
|
iface.poll();
|
||||||
@ -338,6 +342,7 @@ pub fn sys_recvfrom(
|
|||||||
return Ok(size as isize);
|
return Ok(size as isize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// avoid deadlock
|
||||||
drop(socket);
|
drop(socket);
|
||||||
SOCKET_ACTIVITY._wait()
|
SOCKET_ACTIVITY._wait()
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
//! Syscalls for time
|
//! Syscalls for time
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::arch::driver::rtc_cmos;
|
||||||
|
|
||||||
pub fn sys_get_time() -> SysResult {
|
pub fn sys_gettimeofday(tv: *mut u64, tz: *const u8) -> SysResult {
|
||||||
unsafe { Ok(crate::trap::TICK as isize) }
|
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 {
|
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 {
|
if time as usize != 0 {
|
||||||
let mut proc = process();
|
let mut proc = process();
|
||||||
proc.memory_set.check_mut_ptr(time)?;
|
proc.memory_set.check_mut_ptr(time)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user