diff --git a/kernel/src/arch/x86_64/driver/mod.rs b/kernel/src/arch/x86_64/driver/mod.rs index 52934cb4..f8382dab 100644 --- a/kernel/src/arch/x86_64/driver/mod.rs +++ b/kernel/src/arch/x86_64/driver/mod.rs @@ -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!(); diff --git a/kernel/src/arch/x86_64/driver/rtc_cmos.rs b/kernel/src/arch/x86_64/driver/rtc_cmos.rs new file mode 100644 index 00000000..f5d0c750 --- /dev/null +++ b/kernel/src/arch/x86_64/driver/rtc_cmos.rs @@ -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::::new(CMOS_ADDR); + let data = Port::::new(CMOS_DATA); + + addr.write(0x0A); + return (data.read() & 0x80) != 0; +} + +unsafe fn read_rtc(reg: u8) -> u8 { + let mut addr = Port::::new(CMOS_ADDR); + let data = Port::::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 + } +} diff --git a/kernel/src/drivers/bus/pci.rs b/kernel/src/drivers/bus/pci.rs index fa13db67..2097870e 100644 --- a/kernel/src/drivers/bus/pci.rs +++ b/kernel/src/drivers/bus/pci.rs @@ -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); diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index 236df302..25f9da90 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -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, driver.size / 4) }; + let e1000 = unsafe { + slice::from_raw_parts_mut(driver.header as *mut Volatile, 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) diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 80f6d409..e0a549c4 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -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(), diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 5ff813f9..586e8f2b 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -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() } diff --git a/kernel/src/syscall/time.rs b/kernel/src/syscall/time.rs index e686fe46..23005536 100644 --- a/kernel/src/syscall/time.rs +++ b/kernel/src/syscall/time.rs @@ -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)?;