forked from rcore-os/zCore
drivers: add mock drivers for libos
And use a unified serial driver in kernel-hal
This commit is contained in:
parent
8b6be6a876
commit
994f8b80f2
|
@ -8,9 +8,12 @@ description = "Device drivers of zCore"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
mock = []
|
||||
virtio = ["virtio-drivers"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
spin = "0.9"
|
||||
cfg-if = "1.0"
|
||||
bitflags = "1.3"
|
||||
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2b3c6cf", optional = true }
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#[cfg(feature = "virtio")]
|
||||
mod virtio_blk;
|
||||
#[cfg(feature = "virtio")]
|
||||
pub use virtio_blk::VirtIoBlk;
|
|
@ -9,6 +9,9 @@ pub struct Mmio<T> {
|
|||
}
|
||||
|
||||
impl<T> Mmio<T> {
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because `base_addr` may be an arbitrary address.
|
||||
pub unsafe fn from_base<'a, R>(base_addr: usize) -> &'a mut R {
|
||||
&mut *(base_addr as *mut R)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ pub struct ReadOnly<I> {
|
|||
|
||||
impl<I> ReadOnly<I> {
|
||||
pub const fn new(inner: I) -> ReadOnly<I> {
|
||||
ReadOnly { inner: inner }
|
||||
ReadOnly { inner }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ pub struct WriteOnly<I> {
|
|||
|
||||
impl<I> WriteOnly<I> {
|
||||
pub const fn new(inner: I) -> WriteOnly<I> {
|
||||
WriteOnly { inner: inner }
|
||||
WriteOnly { inner }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ impl<T> Pio<T> {
|
|||
/// Create a PIO from a given port
|
||||
pub const fn new(port: u16) -> Self {
|
||||
Pio::<T> {
|
||||
port: port,
|
||||
port,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#![no_std]
|
||||
#![cfg_attr(not(feature = "mock"), no_std)]
|
||||
#![feature(asm)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "virtio")]
|
||||
mod virtio;
|
||||
#[cfg(feature = "mock")]
|
||||
pub mod mock;
|
||||
|
||||
#[cfg(feature = "virtio")]
|
||||
pub mod virtio;
|
||||
|
||||
pub mod block;
|
||||
pub mod io;
|
||||
pub mod scheme;
|
||||
pub mod uart;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
mod uart;
|
||||
|
||||
pub use uart::MockUart;
|
|
@ -0,0 +1,75 @@
|
|||
use std::io::{self, Read};
|
||||
use std::sync::mpsc::{self, Receiver};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::scheme::{Scheme, UartScheme};
|
||||
use crate::DeviceResult;
|
||||
|
||||
pub struct MockUart {
|
||||
stdin_channel: Mutex<Receiver<u8>>,
|
||||
}
|
||||
|
||||
impl MockUart {
|
||||
pub fn new() -> Self {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
std::thread::spawn(move || loop {
|
||||
let mut buf = [0];
|
||||
io::stdin().read_exact(&mut buf).unwrap();
|
||||
if tx.send(buf[0]).is_err() {
|
||||
break;
|
||||
}
|
||||
core::hint::spin_loop();
|
||||
});
|
||||
Self {
|
||||
stdin_channel: Mutex::new(rx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MockUart {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Scheme for MockUart {}
|
||||
|
||||
impl UartScheme for MockUart {
|
||||
fn try_recv(&self) -> DeviceResult<Option<u8>> {
|
||||
match self.stdin_channel.lock().unwrap().try_recv() {
|
||||
Ok(ch) => Ok(Some(ch)),
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn send(&self, ch: u8) -> DeviceResult {
|
||||
eprint!("{}", ch as char);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_str(&self, s: &str) -> DeviceResult {
|
||||
eprint!("{}", s);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_mock_uart() {
|
||||
let uart = MockUart::new();
|
||||
uart.write_str("Hello, World!\n").unwrap();
|
||||
uart.write_str(format!("{} + {} = {}\n", 1, 2, 1 + 2).as_str())
|
||||
.unwrap();
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
if let Some(ch) = uart.try_recv().unwrap() {
|
||||
uart.write_str(format!("received data: {:?}({:#x})\n", ch as char, ch).as_str())
|
||||
.unwrap();
|
||||
} else {
|
||||
uart.write_str("no data to receive\n").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ use super::Scheme;
|
|||
use crate::DeviceResult;
|
||||
|
||||
pub trait BlockScheme: Scheme {
|
||||
fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> DeviceResult;
|
||||
fn write_block(&mut self, block_id: usize, buf: &[u8]) -> DeviceResult;
|
||||
fn flush(&mut self) -> DeviceResult;
|
||||
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> DeviceResult;
|
||||
fn write_block(&self, block_id: usize, buf: &[u8]) -> DeviceResult;
|
||||
fn flush(&self) -> DeviceResult;
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ pub use input::InputScheme;
|
|||
pub use net::NetScheme;
|
||||
pub use uart::UartScheme;
|
||||
|
||||
pub trait Scheme {
|
||||
fn init(&mut self) -> crate::DeviceResult {
|
||||
Ok(())
|
||||
}
|
||||
pub trait Scheme: Send + Sync {
|
||||
fn handle_irq(&self, _irq_num: u32) {}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@ use super::Scheme;
|
|||
use crate::DeviceResult;
|
||||
|
||||
pub trait NetScheme: Scheme {
|
||||
fn recv(&mut self, buf: &mut [u8]) -> DeviceResult<usize>;
|
||||
fn send(&mut self, buf: &[u8]) -> DeviceResult<usize>;
|
||||
fn recv(&self, buf: &mut [u8]) -> DeviceResult<usize>;
|
||||
fn send(&self, buf: &[u8]) -> DeviceResult<usize>;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,12 @@ use super::Scheme;
|
|||
use crate::DeviceResult;
|
||||
|
||||
pub trait UartScheme: Scheme {
|
||||
fn try_recv(&mut self) -> DeviceResult<Option<u8>>;
|
||||
fn send(&mut self, ch: u8) -> DeviceResult;
|
||||
fn try_recv(&self) -> DeviceResult<Option<u8>>;
|
||||
fn send(&self, ch: u8) -> DeviceResult;
|
||||
fn write_str(&self, s: &str) -> DeviceResult {
|
||||
for c in s.bytes() {
|
||||
self.send(c)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
mod uart_16550;
|
||||
pub use uart_16550::Uart16550;
|
||||
pub use uart_16550::Uart16550Mmio;
|
||||
|
||||
#[cfg(feature = "virtio")]
|
||||
mod virtio_console;
|
||||
#[cfg(feature = "virtio")]
|
||||
pub use virtio_console::VirtIoConsole;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use uart_16550::Uart16550Pio;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use core::{convert::TryInto, fmt};
|
||||
use core::convert::TryInto;
|
||||
use core::ops::{BitAnd, BitOr, Not};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use spin::Mutex;
|
||||
|
||||
use crate::io::{Io, Mmio, ReadOnly};
|
||||
use crate::scheme::{Scheme, UartScheme};
|
||||
|
@ -28,7 +30,7 @@ bitflags! {
|
|||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Uart16550<T: Io> {
|
||||
struct Uart16550Inner<T: Io> {
|
||||
/// Data register, read to receive, write to send
|
||||
data: T,
|
||||
/// Interrupt enable
|
||||
|
@ -45,50 +47,11 @@ pub struct Uart16550<T: Io> {
|
|||
modem_sts: ReadOnly<T>,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl Uart16550<crate::io::Pio<u8>> {
|
||||
pub const fn new(base: u16) -> Self {
|
||||
use crate::io::Pio;
|
||||
Self {
|
||||
data: Pio::new(base),
|
||||
int_en: Pio::new(base + 1),
|
||||
fifo_ctrl: Pio::new(base + 2),
|
||||
line_ctrl: Pio::new(base + 3),
|
||||
modem_ctrl: Pio::new(base + 4),
|
||||
line_sts: ReadOnly::new(Pio::new(base + 5)),
|
||||
modem_sts: ReadOnly::new(Pio::new(base + 6)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Uart16550<Mmio<u8>> {
|
||||
pub unsafe fn new(base: usize) -> &'static mut Self {
|
||||
Mmio::<u8>::from_base(base)
|
||||
}
|
||||
}
|
||||
|
||||
impl Uart16550<Mmio<u32>> {
|
||||
pub unsafe fn new(base: usize) -> &'static mut Self {
|
||||
Mmio::<u32>::from_base(base)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Io> Uart16550<T>
|
||||
impl<T: Io> Uart16550Inner<T>
|
||||
where
|
||||
T::Value: From<u8> + TryInto<u8>,
|
||||
{
|
||||
fn line_sts(&self) -> LineStsFlags {
|
||||
LineStsFlags::from_bits_truncate(
|
||||
(self.line_sts.read() & 0xFF.into()).try_into().unwrap_or(0),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Io> Scheme for Uart16550<T>
|
||||
where
|
||||
T::Value: From<u8> + TryInto<u8>,
|
||||
{
|
||||
fn init(&mut self) -> DeviceResult {
|
||||
fn init(&mut self) {
|
||||
// Disable interrupts
|
||||
self.int_en.write(0x00.into());
|
||||
|
||||
|
@ -112,15 +75,14 @@ where
|
|||
|
||||
// Enable interrupts
|
||||
self.int_en.write(0x01.into());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Io> UartScheme for Uart16550<T>
|
||||
where
|
||||
T::Value: From<u8> + TryInto<u8>,
|
||||
{
|
||||
fn line_sts(&self) -> LineStsFlags {
|
||||
LineStsFlags::from_bits_truncate(
|
||||
(self.line_sts.read() & 0xFF.into()).try_into().unwrap_or(0),
|
||||
)
|
||||
}
|
||||
|
||||
fn try_recv(&mut self) -> DeviceResult<Option<u8>> {
|
||||
if self.line_sts().contains(LineStsFlags::INPUT_FULL) {
|
||||
Ok(Some(
|
||||
|
@ -136,29 +98,132 @@ where
|
|||
self.data.write(ch.into());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Io> fmt::Write for Uart16550<T>
|
||||
where
|
||||
T::Value: From<u8> + TryInto<u8>,
|
||||
{
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
fn write_str(&mut self, s: &str) -> DeviceResult {
|
||||
for b in s.bytes() {
|
||||
match b {
|
||||
8 | 0x7F => {
|
||||
self.send(8).unwrap();
|
||||
self.send(b' ').unwrap();
|
||||
self.send(8).unwrap();
|
||||
self.send(8)?;
|
||||
self.send(b' ')?;
|
||||
self.send(8)?;
|
||||
}
|
||||
b'\n' => {
|
||||
self.send(b'\r').unwrap();
|
||||
self.send(b'\n').unwrap();
|
||||
self.send(b'\r')?;
|
||||
self.send(b'\n')?;
|
||||
}
|
||||
_ => {
|
||||
self.send(b).unwrap();
|
||||
self.send(b)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Uart16550Mmio<V: 'static>
|
||||
where
|
||||
V: Copy + BitAnd<Output = V> + BitOr<Output = V> + Not<Output = V>,
|
||||
{
|
||||
inner: Mutex<&'static mut Uart16550Inner<Mmio<V>>>,
|
||||
}
|
||||
|
||||
impl<V> Scheme for Uart16550Mmio<V> where
|
||||
V: Copy + BitAnd<Output = V> + BitOr<Output = V> + Not<Output = V> + Send
|
||||
{
|
||||
}
|
||||
|
||||
impl<V> UartScheme for Uart16550Mmio<V>
|
||||
where
|
||||
V: Copy
|
||||
+ BitAnd<Output = V>
|
||||
+ BitOr<Output = V>
|
||||
+ Not<Output = V>
|
||||
+ From<u8>
|
||||
+ TryInto<u8>
|
||||
+ Send,
|
||||
{
|
||||
fn try_recv(&self) -> DeviceResult<Option<u8>> {
|
||||
self.inner.lock().try_recv()
|
||||
}
|
||||
|
||||
fn send(&self, ch: u8) -> DeviceResult {
|
||||
self.inner.lock().send(ch)
|
||||
}
|
||||
|
||||
fn write_str(&self, s: &str) -> DeviceResult {
|
||||
self.inner.lock().write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Uart16550Mmio<u8> {
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because `base_addr` may be an arbitrary address.
|
||||
pub unsafe fn new(base: usize) -> Self {
|
||||
let uart: &mut Uart16550Inner<Mmio<u8>> = Mmio::<u8>::from_base(base);
|
||||
uart.init();
|
||||
Self {
|
||||
inner: Mutex::new(uart),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Uart16550Mmio<u32> {
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because `base_addr` may be an arbitrary address.
|
||||
pub unsafe fn new(base: usize) -> Self {
|
||||
let uart: &mut Uart16550Inner<Mmio<u32>> = Mmio::<u32>::from_base(base);
|
||||
uart.init();
|
||||
Self {
|
||||
inner: Mutex::new(uart),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod pio {
|
||||
use super::*;
|
||||
use crate::io::Pio;
|
||||
|
||||
pub struct Uart16550Pio {
|
||||
inner: Mutex<Uart16550Inner<Pio<u8>>>,
|
||||
}
|
||||
|
||||
impl Scheme for Uart16550Pio {}
|
||||
|
||||
impl UartScheme for Uart16550Pio {
|
||||
fn try_recv(&self) -> DeviceResult<Option<u8>> {
|
||||
self.inner.lock().try_recv()
|
||||
}
|
||||
|
||||
fn send(&self, ch: u8) -> DeviceResult {
|
||||
self.inner.lock().send(ch)
|
||||
}
|
||||
|
||||
fn write_str(&self, s: &str) -> DeviceResult {
|
||||
self.inner.lock().write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Uart16550Pio {
|
||||
pub fn new(base: u16) -> Self {
|
||||
let mut uart = Uart16550Inner::<Pio<u8>> {
|
||||
data: Pio::new(base),
|
||||
int_en: Pio::new(base + 1),
|
||||
fifo_ctrl: Pio::new(base + 2),
|
||||
line_ctrl: Pio::new(base + 3),
|
||||
modem_ctrl: Pio::new(base + 4),
|
||||
line_sts: ReadOnly::new(Pio::new(base + 5)),
|
||||
modem_sts: ReadOnly::new(Pio::new(base + 6)),
|
||||
};
|
||||
uart.init();
|
||||
Self {
|
||||
inner: Mutex::new(uart),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use pio::Uart16550Pio;
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
use crate::scheme::{Scheme, UartScheme};
|
||||
use crate::DeviceResult;
|
||||
|
||||
use virtio_drivers::{VirtIOConsole as InnerDriver, VirtIOHeader};
|
||||
|
||||
pub struct VirtIoConsole<'a> {
|
||||
inner: InnerDriver<'a>,
|
||||
}
|
||||
|
||||
impl<'a> VirtIoConsole<'a> {
|
||||
pub fn new(header: &'static mut VirtIOHeader) -> DeviceResult<Self> {
|
||||
Ok(Self {
|
||||
inner: InnerDriver::new(header)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Scheme for VirtIoConsole<'a> {}
|
||||
|
||||
impl<'a> UartScheme for VirtIoConsole<'a> {
|
||||
fn try_recv(&mut self) -> DeviceResult<Option<u8>> {
|
||||
Ok(self.inner.recv(true)?)
|
||||
}
|
||||
|
||||
fn send(&mut self, ch: u8) -> DeviceResult {
|
||||
self.inner.send(ch)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
use spin::Mutex;
|
||||
use virtio_drivers::{VirtIOBlk as InnerDriver, VirtIOHeader};
|
||||
|
||||
use crate::scheme::{BlockScheme, Scheme};
|
||||
use crate::DeviceResult;
|
||||
|
||||
use virtio_drivers::{VirtIOBlk as InnerDriver, VirtIOHeader};
|
||||
|
||||
pub struct VirtIoBlk<'a> {
|
||||
inner: InnerDriver<'a>,
|
||||
inner: Mutex<InnerDriver<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> VirtIoBlk<'a> {
|
||||
pub fn new(header: &'static mut VirtIOHeader) -> DeviceResult<Self> {
|
||||
Ok(Self {
|
||||
inner: InnerDriver::new(header)?,
|
||||
inner: Mutex::new(InnerDriver::new(header)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +19,17 @@ impl<'a> VirtIoBlk<'a> {
|
|||
impl<'a> Scheme for VirtIoBlk<'a> {}
|
||||
|
||||
impl<'a> BlockScheme for VirtIoBlk<'a> {
|
||||
fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> DeviceResult {
|
||||
self.inner.read_block(block_id, buf)?;
|
||||
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> DeviceResult {
|
||||
self.inner.lock().read_block(block_id, buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_block(&mut self, block_id: usize, buf: &[u8]) -> DeviceResult {
|
||||
self.inner.write_block(block_id, buf)?;
|
||||
fn write_block(&self, block_id: usize, buf: &[u8]) -> DeviceResult {
|
||||
self.inner.lock().write_block(block_id, buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> DeviceResult {
|
||||
fn flush(&self) -> DeviceResult {
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
use core::fmt::{Result, Write};
|
||||
|
||||
use spin::Mutex;
|
||||
use virtio_drivers::{VirtIOConsole as InnerDriver, VirtIOHeader};
|
||||
|
||||
use crate::scheme::{Scheme, UartScheme};
|
||||
use crate::DeviceResult;
|
||||
|
||||
pub struct VirtIoConsole<'a> {
|
||||
inner: Mutex<InnerDriver<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> VirtIoConsole<'a> {
|
||||
pub fn new(header: &'static mut VirtIOHeader) -> DeviceResult<Self> {
|
||||
Ok(Self {
|
||||
inner: Mutex::new(InnerDriver::new(header)?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Scheme for VirtIoConsole<'a> {}
|
||||
|
||||
impl<'a> UartScheme for VirtIoConsole<'a> {
|
||||
fn try_recv(&self) -> DeviceResult<Option<u8>> {
|
||||
Ok(self.inner.lock().recv(true)?)
|
||||
}
|
||||
|
||||
fn send(&self, ch: u8) -> DeviceResult {
|
||||
self.inner.lock().send(ch)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for VirtIoConsole<'a> {
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
for b in s.bytes() {
|
||||
self.send(b).unwrap()
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,3 +1,9 @@
|
|||
mod blk;
|
||||
mod console;
|
||||
|
||||
pub use blk::VirtIoBlk;
|
||||
pub use console::VirtIoConsole;
|
||||
|
||||
use crate::DeviceError;
|
||||
use core::convert::From;
|
||||
use virtio_drivers::Error;
|
|
@ -8,7 +8,7 @@ description = "Kernel HAL interface definations."
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
libos = ["async-std"]
|
||||
libos = ["async-std", "zcore-drivers/mock"]
|
||||
board_qemu = []
|
||||
board_d1 = []
|
||||
|
||||
|
@ -17,10 +17,11 @@ log = "0.4"
|
|||
bitflags = "1.3"
|
||||
trapframe = "0.8.0"
|
||||
numeric-enum-macro = "0.2"
|
||||
spin = "0.7"
|
||||
spin = "0.9"
|
||||
git-version = "0.3"
|
||||
cfg-if = "1.0"
|
||||
acpi = "1.1"
|
||||
zcore-drivers = { path = "../drivers" }
|
||||
|
||||
# LibOS mode
|
||||
[target.'cfg(not(target_os = "none"))'.dependencies]
|
||||
|
@ -31,7 +32,6 @@ async-std = { version = "1.9", optional = true }
|
|||
|
||||
# Bare-metal mode
|
||||
[target.'cfg(target_os = "none")'.dependencies]
|
||||
zcore-drivers = { path = "../drivers" }
|
||||
executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" }
|
||||
naive-timer = "0.2.0"
|
||||
lazy_static = { version = "1.4", features = ["spin_no_std"] }
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
use alloc::boxed::Box;
|
||||
|
||||
use zcore_drivers::uart::Uart16550Mmio;
|
||||
|
||||
use crate::{drivers::UART, mem::phys_to_virt};
|
||||
|
||||
pub(super) fn init() {
|
||||
UART.init_by(Box::new(unsafe {
|
||||
Uart16550Mmio::<u8>::new(phys_to_virt(super::consts::UART_BASE))
|
||||
}));
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
mod consts;
|
||||
mod drivers;
|
||||
mod plic;
|
||||
mod sbi;
|
||||
mod trap;
|
||||
|
@ -10,7 +11,6 @@ pub mod context;
|
|||
pub mod cpu;
|
||||
pub mod interrupt;
|
||||
pub mod mem;
|
||||
pub mod serial;
|
||||
pub mod special;
|
||||
pub mod timer;
|
||||
pub mod vm;
|
||||
|
@ -19,7 +19,7 @@ pub fn init() {
|
|||
vm::remap_the_kernel().unwrap();
|
||||
interrupt::init();
|
||||
timer::init();
|
||||
serial::init();
|
||||
drivers::init();
|
||||
|
||||
#[cfg(feature = "board_qemu")]
|
||||
{
|
||||
|
|
|
@ -88,7 +88,7 @@ pub(super) fn handle_interrupt() {
|
|||
}
|
||||
UART0_INT_NUM => {
|
||||
//UART中断ID是10
|
||||
super::serial::handle_irq();
|
||||
crate::serial::handle_irq();
|
||||
|
||||
//换用sbi的方式获取字符
|
||||
//interrupt::try_process_serial();
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
use core::fmt::{Arguments, Result, Write};
|
||||
|
||||
use spin::Mutex;
|
||||
use zcore_drivers::scheme::{Scheme, UartScheme};
|
||||
use zcore_drivers::{io::Mmio, uart::Uart16550};
|
||||
|
||||
use crate::{mem::phys_to_virt, utils::init_once::InitOnce};
|
||||
|
||||
pub(super) static UART: InitOnce<Mutex<&'static mut Uart16550<Mmio<u8>>>> = InitOnce::new();
|
||||
|
||||
pub(super) fn init() {
|
||||
UART.init(|| {
|
||||
let uart = unsafe { Uart16550::<Mmio<u8>>::new(phys_to_virt(super::consts::UART_BASE)) };
|
||||
uart.init().unwrap();
|
||||
Mutex::new(uart)
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn handle_irq() {
|
||||
if let Some(uart) = UART.try_get() {
|
||||
if let Some(c) = uart.lock().try_recv().unwrap() {
|
||||
crate::serial::serial_put(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SbiWriter;
|
||||
|
||||
impl Write for SbiWriter {
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
for ch in s.chars() {
|
||||
super::sbi::console_putchar(ch as usize);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
hal_fn_impl! {
|
||||
impl mod crate::hal_fn::serial {
|
||||
fn serial_write_fmt(fmt: Arguments) {
|
||||
if let Some(uart) = UART.try_get() {
|
||||
uart.lock().write_fmt(fmt).unwrap();
|
||||
} else {
|
||||
SbiWriter.write_fmt(fmt).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
use alloc::boxed::Box;
|
||||
|
||||
use zcore_drivers::uart::Uart16550Pio;
|
||||
|
||||
use crate::drivers::UART;
|
||||
|
||||
pub(super) fn init() {
|
||||
UART.init_by(Box::new(Uart16550Pio::new(0x3F8)));
|
||||
}
|
|
@ -240,7 +240,7 @@ fn timer() {
|
|||
}
|
||||
|
||||
fn com1() {
|
||||
super::serial::handle_irq();
|
||||
crate::serial::handle_irq();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod acpi_table;
|
||||
mod apic;
|
||||
mod drivers;
|
||||
mod trap;
|
||||
|
||||
pub mod config;
|
||||
|
@ -7,7 +8,6 @@ pub mod context;
|
|||
pub mod cpu;
|
||||
pub mod interrupt;
|
||||
pub mod mem;
|
||||
pub mod serial;
|
||||
pub mod special;
|
||||
pub mod timer;
|
||||
pub mod vm;
|
||||
|
@ -16,8 +16,8 @@ use x86_64::registers::control::{Cr4, Cr4Flags};
|
|||
|
||||
pub fn init() {
|
||||
apic::init();
|
||||
drivers::init();
|
||||
interrupt::init();
|
||||
serial::init();
|
||||
|
||||
fn ap_main() {
|
||||
info!("processor {} started", cpu::cpu_id());
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
use core::fmt::{Arguments, Write};
|
||||
|
||||
use spin::Mutex;
|
||||
use zcore_drivers::scheme::{Scheme, UartScheme};
|
||||
use zcore_drivers::{io::Pio, uart::Uart16550};
|
||||
|
||||
pub(super) static COM1: Mutex<Uart16550<Pio<u8>>> = Mutex::new(Uart16550::<Pio<u8>>::new(0x3F8));
|
||||
|
||||
pub(super) fn init() {
|
||||
COM1.lock().init().unwrap();
|
||||
}
|
||||
|
||||
pub(super) fn handle_irq() {
|
||||
if let Some(c) = COM1.lock().try_recv().unwrap() {
|
||||
crate::serial::serial_put(c);
|
||||
}
|
||||
}
|
||||
|
||||
hal_fn_impl! {
|
||||
impl mod crate::hal_fn::serial {
|
||||
fn serial_write_fmt(fmt: Arguments) {
|
||||
COM1.lock().write_fmt(fmt).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ pub mod mem;
|
|||
pub mod thread;
|
||||
pub mod timer;
|
||||
|
||||
pub use self::arch::{config, context, cpu, interrupt, serial, vm};
|
||||
pub use self::arch::{config, context, cpu, interrupt, vm};
|
||||
pub use super::hal_fn::{dev, rand, vdso};
|
||||
|
||||
hal_fn_impl_default!(rand, vdso, dev::fb, dev::input);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
use alloc::boxed::Box;
|
||||
|
||||
use zcore_drivers::scheme::UartScheme;
|
||||
|
||||
use crate::utils::init_once::InitOnce;
|
||||
|
||||
pub static UART: InitOnce<Box<dyn UartScheme>> = InitOnce::new();
|
|
@ -3,6 +3,7 @@ pub(super) mod fb;
|
|||
|
||||
pub mod addr;
|
||||
pub mod context;
|
||||
pub mod drivers;
|
||||
pub mod future;
|
||||
pub mod mem;
|
||||
pub mod serial;
|
||||
|
|
|
@ -1,18 +1,35 @@
|
|||
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
|
||||
use core::fmt::{Arguments, Result, Write};
|
||||
|
||||
use spin::Mutex;
|
||||
|
||||
use crate::drivers::UART;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
|
||||
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> bool + Send + Sync>>> =
|
||||
Mutex::new(Vec::new());
|
||||
}
|
||||
|
||||
/// Put a char to serial buffer.
|
||||
pub fn serial_put(x: u8) {
|
||||
let x = if x == b'\r' { b'\n' } else { x };
|
||||
STDIN.lock().push_back(x);
|
||||
STDIN_CALLBACK.lock().retain(|f| !f());
|
||||
struct SerialWriter;
|
||||
|
||||
impl Write for SerialWriter {
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
if let Some(uart) = UART.try_get() {
|
||||
uart.write_str(s).unwrap();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_irq() {
|
||||
if let Some(uart) = UART.try_get() {
|
||||
if let Some(c) = uart.try_recv().unwrap() {
|
||||
let c = if c == b'\r' { b'\n' } else { c };
|
||||
STDIN.lock().push_back(c);
|
||||
STDIN_CALLBACK.lock().retain(|f| !f());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a callback of serial readable event.
|
||||
|
@ -30,7 +47,12 @@ pub fn serial_read(buf: &mut [u8]) -> usize {
|
|||
len
|
||||
}
|
||||
|
||||
/// Print format string and its arguments to serial.
|
||||
pub fn serial_write_fmt(fmt: Arguments) {
|
||||
SerialWriter.write_fmt(fmt).unwrap();
|
||||
}
|
||||
|
||||
/// Print a string to serial.
|
||||
pub fn serial_write(s: &str) {
|
||||
crate::serial::serial_write_fmt(format_args!("{}", s));
|
||||
serial_write_fmt(format_args!("{}", s));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use alloc::boxed::Box;
|
||||
use core::{fmt::Arguments, future::Future, ops::Range, pin::Pin, time::Duration};
|
||||
use core::{future::Future, ops::Range, pin::Pin, time::Duration};
|
||||
|
||||
use crate::{common, HalResult, MMUFlags, PhysAddr, VirtAddr};
|
||||
|
||||
|
@ -125,11 +125,6 @@ hal_fn_def! {
|
|||
pub(crate) fn timer_tick();
|
||||
}
|
||||
|
||||
pub mod serial: common::serial {
|
||||
/// Print format string and its arguments to serial.
|
||||
pub fn serial_write_fmt(fmt: Arguments);
|
||||
}
|
||||
|
||||
pub mod rand {
|
||||
/// Fill random bytes to the buffer
|
||||
#[allow(unused_variables)]
|
||||
|
|
|
@ -31,7 +31,7 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
pub use common::{addr, defs::*, future, user};
|
||||
pub use common::{addr, defs::*, drivers, future, serial, user};
|
||||
pub use config::*;
|
||||
pub use imp::*;
|
||||
pub use kernel_handler::*;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
use alloc::boxed::Box;
|
||||
|
||||
use zcore_drivers::mock::MockUart;
|
||||
|
||||
use crate::drivers::UART;
|
||||
|
||||
pub(super) fn init() {
|
||||
UART.init_by(Box::new(MockUart::new()));
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
mod drivers;
|
||||
mod mem_common;
|
||||
|
||||
pub(super) mod dummy;
|
||||
|
||||
pub mod config;
|
||||
pub mod mem;
|
||||
pub mod serial;
|
||||
pub mod thread;
|
||||
pub mod timer;
|
||||
pub mod vdso;
|
||||
|
@ -32,16 +32,16 @@ include!("macos.rs");
|
|||
pub fn init() {
|
||||
crate::KHANDLER.init_by(&crate::DummyKernelHandler);
|
||||
|
||||
drivers::init();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
unsafe {
|
||||
register_sigsegv_handler();
|
||||
}
|
||||
// spawn a thread to read stdin
|
||||
// TODO: raw mode
|
||||
use std::io::Read;
|
||||
std::thread::spawn(|| {
|
||||
for i in std::io::stdin().bytes() {
|
||||
serial::serial_put(i.unwrap());
|
||||
}
|
||||
std::thread::spawn(|| loop {
|
||||
crate::serial::handle_irq();
|
||||
core::hint::spin_loop();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
hal_fn_impl! {
|
||||
impl mod crate::hal_fn::serial {
|
||||
fn serial_write_fmt(fmt: core::fmt::Arguments) {
|
||||
eprint!("{}", fmt);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@ hal_fn_impl! {
|
|||
pub struct PageTable;
|
||||
|
||||
impl PageTable {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
@ -30,6 +29,12 @@ impl PageTable {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for PageTable {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericPageTable for PageTable {
|
||||
fn table_phys(&self) -> PhysAddr {
|
||||
0
|
||||
|
|
|
@ -176,7 +176,6 @@ impl<L: PageTableLevel, PTE: GenericPTE> PageTableImpl<L, PTE> {
|
|||
|
||||
/// Public implementation.
|
||||
impl<L: PageTableLevel, PTE: GenericPTE> PageTableImpl<L, PTE> {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Self {
|
||||
let root = PhysFrame::new_zero().expect("failed to alloc frame");
|
||||
Self {
|
||||
|
@ -198,6 +197,12 @@ impl<L: PageTableLevel, PTE: GenericPTE> PageTableImpl<L, PTE> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<L: PageTableLevel, PTE: GenericPTE> Default for PageTableImpl<L, PTE> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: PageTableLevel, PTE: GenericPTE> GenericPageTable for PageTableImpl<L, PTE> {
|
||||
fn table_phys(&self) -> PhysAddr {
|
||||
self.root.paddr()
|
||||
|
|
|
@ -13,7 +13,7 @@ graphic = []
|
|||
[dependencies]
|
||||
async-trait = "0.1"
|
||||
log = "0.4"
|
||||
spin = "0.7"
|
||||
spin = "0.9"
|
||||
xmas-elf = "0.7"
|
||||
bitflags = "1.3"
|
||||
hashbrown = "0.9"
|
||||
|
|
|
@ -9,7 +9,7 @@ description = "Linux syscalls implementation"
|
|||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
spin = "0.7"
|
||||
spin = "0.9"
|
||||
bitflags = "1.3"
|
||||
numeric-enum-macro = "0.2"
|
||||
zircon-object = { path = "../zircon-object" }
|
||||
|
|
|
@ -20,7 +20,7 @@ lto = true
|
|||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
spin = "0.7"
|
||||
spin = "0.9"
|
||||
cfg-if = "1.0"
|
||||
buddy_system_allocator = "0.7"
|
||||
kernel-hal = { path = "../kernel-hal" }
|
||||
|
|
|
@ -14,7 +14,7 @@ elf = ["xmas-elf"]
|
|||
|
||||
[dependencies]
|
||||
bitflags = "1.3"
|
||||
spin = "0.7"
|
||||
spin = "0.9"
|
||||
log = "0.4"
|
||||
hashbrown = "0.9"
|
||||
downcast-rs = { version = "1.2", default-features = false }
|
||||
|
|
|
@ -16,7 +16,7 @@ std = ["deny-page-fault"]
|
|||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
spin = "0.7"
|
||||
spin = "0.9"
|
||||
bitflags = "1.3"
|
||||
numeric-enum-macro = "0.2"
|
||||
zircon-object = { path = "../zircon-object" }
|
||||
|
|
Loading…
Reference in New Issue