1
0
mirror of https://github.com/rcore-os/rCore.git synced 2025-01-19 01:07:05 +04:00

Split Driver trait

This commit is contained in:
Jiajie Chen 2020-06-20 14:35:59 +08:00
parent d9234ccb4a
commit c8573436e9
15 changed files with 202 additions and 94 deletions

2
kernel/Cargo.lock generated
View File

@ -721,7 +721,7 @@ checksum = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
[[package]]
name = "trapframe"
version = "0.3.0"
source = "git+https://github.com/rcore-os/trapframe-rs?rev=12a73f6#12a73f6974859d9b7d93332771d28adc178f28db"
source = "git+https://github.com/rcore-os/trapframe-rs?rev=cd828e1#cd828e1457e57eeb6bddf65325cb9b72448d9b5e"
dependencies = [
"log",
"raw-cpuid",

View File

@ -74,7 +74,7 @@ rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "517af47"
rlibc = "1.0"
smoltcp = { git = "https://github.com/rcore-os/smoltcp", rev = "5bd87c7c", default-features = false, features = ["alloc", "log", "ethernet", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
spin = "0.5"
trapframe = { git = "https://github.com/rcore-os/trapframe-rs", rev = "12a73f6" }
trapframe = { git = "https://github.com/rcore-os/trapframe-rs", rev = "cd828e1" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "dfa70e14" }
volatile = "0.2"
woke = "0.0.2"

View File

@ -7,10 +7,13 @@ use alloc::sync::Arc;
use isomorphic_drivers::block::ahci::{AHCI, BLOCK_SIZE};
use crate::drivers::provider::Provider;
use crate::drivers::{provider::Provider, NetDriver};
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS};
use super::{
super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS},
BlockDriver,
};
pub struct AHCIDriver(Mutex<AHCI<Provider>>);
@ -27,6 +30,15 @@ impl Driver for AHCIDriver {
format!("ahci")
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
Some(self)
}
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
}
impl BlockDriver for AHCIDriver {
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool {
let mut driver = self.0.lock();
driver.read_block(block_id, buf);

View File

@ -1,2 +1,14 @@
use super::Driver;
pub mod ahci;
pub mod virtio_blk;
pub trait BlockDriver: Driver {
fn read_block(&self, _block_id: usize, _buf: &mut [u8]) -> bool {
unimplemented!("not a block driver")
}
fn write_block(&self, _block_id: usize, _buf: &[u8]) -> bool {
unimplemented!("not a block driver")
}
}

View File

@ -3,8 +3,11 @@ use alloc::sync::Arc;
use virtio_drivers::{VirtIOBlk, VirtIOHeader};
use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS, IRQ_MANAGER};
use crate::sync::SpinNoIrqLock as Mutex;
use super::{
super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS, IRQ_MANAGER},
BlockDriver,
};
use crate::{drivers::NetDriver, sync::SpinNoIrqLock as Mutex};
struct VirtIOBlkDriver(Mutex<VirtIOBlk<'static>>);
@ -21,6 +24,16 @@ impl Driver for VirtIOBlkDriver {
format!("virtio_block")
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
}
impl BlockDriver for VirtIOBlkDriver {
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool {
self.0.lock().read_block(block_id, buf).is_ok()
}

View File

@ -5,7 +5,10 @@ use virtio_drivers::{VirtIOGpu, VirtIOHeader};
use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER};
use crate::memory::virt_to_phys;
use crate::sync::SpinNoIrqLock as Mutex;
use crate::{
drivers::{BlockDriver, NetDriver},
sync::SpinNoIrqLock as Mutex,
};
struct VirtIOGpuDriver(Mutex<VirtIOGpu<'static>>);
@ -21,6 +24,14 @@ impl Driver for VirtIOGpuDriver {
fn get_id(&self) -> String {
format!("virtio_gpu")
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
}
pub fn init(header: &'static mut VirtIOHeader) {

View File

@ -6,7 +6,10 @@ use log::*;
use virtio_drivers::{VirtIOHeader, VirtIOInput};
use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER};
use crate::sync::SpinNoIrqLock as Mutex;
use crate::{
drivers::{BlockDriver, NetDriver},
sync::SpinNoIrqLock as Mutex,
};
struct VirtIOInputDriver(Mutex<VirtIOInput<'static>>);
@ -27,6 +30,14 @@ impl Driver for VirtIOInputDriver {
fn get_id(&self) -> String {
String::from("virtio_input")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
None
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
pub fn init(header: &'static mut VirtIOHeader) {

View File

@ -1,29 +1,24 @@
use crate::sync::Condvar;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use rcore_fs::dev::{self, BlockDevice, DevError};
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use spin::RwLock;
use crate::sync::Condvar;
use rcore_fs::dev::{self, BlockDevice, DevError};
pub use block::BlockDriver;
pub use net::NetDriver;
#[allow(dead_code)]
pub mod block;
#[allow(dead_code)]
pub mod bus;
pub mod console;
#[allow(dead_code)]
mod device_tree;
#[allow(dead_code)]
pub mod device_tree;
pub mod gpu;
#[allow(dead_code)]
mod input;
pub mod input;
pub mod irq;
#[allow(dead_code)]
pub mod net;
mod provider;
pub mod provider;
#[derive(Debug, Eq, PartialEq)]
pub enum DeviceType {
@ -47,64 +42,22 @@ pub trait Driver: Send + Sync {
// should be different for each instance
fn get_id(&self) -> String;
// Rust trait is still too restricted...
// network related drivers should implement these
// get mac address for this device
fn get_mac(&self) -> EthernetAddress {
unimplemented!("not a net driver")
}
// get interface name for this device
fn get_ifname(&self) -> String {
unimplemented!("not a net driver")
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
unimplemented!("not a net driver")
}
// get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!("not a net driver")
}
// manually trigger a poll, use it after sending packets
fn poll(&self) {
unimplemented!("not a net driver")
}
// send an ethernet frame, only use it when necessary
fn send(&self, _data: &[u8]) -> Option<usize> {
unimplemented!("not a net driver")
}
// get mac address from ip address in arp table
fn get_arp(&self, _ip: IpAddress) -> Option<EthernetAddress> {
unimplemented!("not a net driver")
}
// block related drivers should implement these
fn read_block(&self, _block_id: usize, _buf: &mut [u8]) -> bool {
unimplemented!("not a block driver")
}
fn write_block(&self, _block_id: usize, _buf: &[u8]) -> bool {
unimplemented!("not a block driver")
}
// trait casting
fn as_net(&self) -> Option<&dyn NetDriver>;
fn as_block(&self) -> Option<&dyn BlockDriver>;
}
lazy_static! {
// NOTE: RwLock only write when initializing drivers
pub static ref DRIVERS: RwLock<Vec<Arc<dyn Driver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<dyn Driver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<dyn Driver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<dyn NetDriver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<dyn BlockDriver>>> = RwLock::new(Vec::new());
pub static ref IRQ_MANAGER: RwLock<irq::IrqManager> = RwLock::new(irq::IrqManager::new());
}
pub struct BlockDriver(pub Arc<dyn Driver>);
pub struct BlockDriverWrapper(pub Arc<dyn BlockDriver>);
impl BlockDevice for BlockDriver {
impl BlockDevice for BlockDriverWrapper {
const BLOCK_SIZE_LOG2: u8 = 9; // 512
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> dev::Result<()> {
match self.0.read_block(block_id, buf) {

View File

@ -16,11 +16,14 @@ use isomorphic_drivers::net::ethernet::intel::e1000::E1000;
use isomorphic_drivers::net::ethernet::structs::EthernetAddress as DriverEthernetAddress;
use rcore_memory::PAGE_SIZE;
use crate::drivers::provider::Provider;
use crate::drivers::{provider::Provider, BlockDriver};
use crate::net::SOCKETS;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY};
use super::{
super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY},
NetDriver,
};
#[derive(Clone)]
pub struct E1000Driver(Arc<Mutex<E1000<Provider>>>);
@ -65,6 +68,16 @@ impl Driver for E1000Interface {
String::from("e1000")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl NetDriver for E1000Interface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}

View File

@ -17,10 +17,13 @@ use smoltcp::Result;
use crate::net::SOCKETS;
use crate::sync::FlagsGuard;
use crate::sync::SpinNoIrqLock as Mutex;
use crate::{drivers::BlockDriver, sync::SpinNoIrqLock as Mutex};
use super::super::{
provider::Provider, DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY,
use super::{
super::{
provider::Provider, DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY,
},
NetDriver,
};
#[derive(Clone)]
@ -75,6 +78,16 @@ impl Driver for IXGBEInterface {
self.ifname.clone()
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl NetDriver for IXGBEInterface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}

View File

@ -1,4 +1,46 @@
use super::Driver;
use alloc::string::String;
use alloc::vec::Vec;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
pub mod e1000;
pub mod ixgbe;
pub mod router;
pub mod virtio_net;
pub trait NetDriver: Driver {
// get mac address for this device
fn get_mac(&self) -> EthernetAddress {
unimplemented!("not a net driver")
}
// get interface name for this device
fn get_ifname(&self) -> String {
unimplemented!("not a net driver")
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
unimplemented!("not a net driver")
}
// get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!("not a net driver")
}
// manually trigger a poll, use it after sending packets
fn poll(&self) {
unimplemented!("not a net driver")
}
// send an ethernet frame, only use it when necessary
fn send(&self, _data: &[u8]) -> Option<usize> {
unimplemented!("not a net driver")
}
// get mac address from ip address in arp table
fn get_arp(&self, _ip: IpAddress) -> Option<EthernetAddress> {
unimplemented!("not a net driver")
}
}

View File

@ -15,8 +15,11 @@ use smoltcp::Result;
use crate::net::SOCKETS;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY};
use crate::memory::phys_to_virt;
use super::{
super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY},
NetDriver,
};
use crate::{drivers::BlockDriver, memory::phys_to_virt};
const AXI_STREAM_FIFO_ISR: *mut u32 = phys_to_virt(0x64A0_0000) as *mut u32;
const AXI_STREAM_FIFO_IER: *mut u32 = phys_to_virt(0x64A0_0004) as *mut u32;
@ -199,6 +202,16 @@ impl Driver for RouterInterface {
format!("router")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl NetDriver for RouterInterface {
fn get_mac(&self) -> EthernetAddress {
unimplemented!()
}

View File

@ -8,25 +8,16 @@ use smoltcp::wire::{EthernetAddress, Ipv4Address};
use smoltcp::Result;
use virtio_drivers::{VirtIOHeader, VirtIONet};
use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS};
use crate::sync::SpinNoIrqLock as Mutex;
use super::{
super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS},
NetDriver,
};
use crate::{drivers::BlockDriver, sync::SpinNoIrqLock as Mutex};
#[derive(Clone)]
pub struct VirtIONetDriver(Arc<Mutex<VirtIONet<'static>>>);
impl Driver for VirtIONetDriver {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
self.0.lock().ack_interrupt()
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
format!("virtio_net")
}
impl NetDriver for VirtIONetDriver {
fn get_mac(&self) -> EthernetAddress {
EthernetAddress(self.0.lock().mac())
}
@ -44,6 +35,28 @@ impl Driver for VirtIONetDriver {
}
}
impl Driver for VirtIONetDriver {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
self.0.lock().ack_interrupt()
}
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
fn get_id(&self) -> String {
format!("virtio_net")
}
fn as_net(&self) -> Option<&dyn NetDriver> {
Some(self)
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
None
}
}
impl phy::Device<'_> for VirtIONetDriver {
type RxToken = VirtIONetDriver;
type TxToken = VirtIONetDriver;

View File

@ -16,6 +16,7 @@ pub use self::file::*;
pub use self::file_like::*;
pub use self::pipe::Pipe;
pub use self::pseudo::*;
use crate::drivers::BlockDriverWrapper;
mod devfs;
mod device;
@ -51,7 +52,7 @@ lazy_static! {
{
use crate::drivers::BlockDriver;
use rcore_fs::dev::block_cache::BlockCache;
let driver = BlockDriver(
let driver = BlockDriverWrapper(
crate::drivers::BLK_DRIVERS
.read().iter()
.next().expect("Block device not found")

View File

@ -278,7 +278,8 @@ impl Thread {
let mut context = UserContext::default();
context.set_ip(entry_addr);
context.set_sp(ustack_top);
if cfg!(target_arch = "x86_64") {
#[cfg(target_arch = "x86_64")]
if true {
context.general.rflags = 0x3202;
}
@ -429,7 +430,7 @@ pub fn spawn(thread: Arc<Thread>) {
trace!("go to user: {:#x?}", cx);
cx.run();
trace!("back from user: {:#x?}", cx);
let mut trap_num = 0;
let mut trap_num: usize = 0;
if cfg!(target_arch = "x86_64") {
trap_num = cx.trap_num;
}