1
0
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:
Jiajie Chen 2019-03-04 16:25:57 +08:00
parent 1a1e39c960
commit c6c89198cd
7 changed files with 113 additions and 21 deletions

View File

@ -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!();

View 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
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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(),

View File

@ -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()
} }

View File

@ -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)?;