Add cmos rtc driver for x86

master
Jiajie Chen 6 years ago
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!();

@ -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…
Cancel
Save