1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-26 09:53:28 +04:00

Detach driver from the device in sys_map_pci_driver

This commit is contained in:
Jiajie Chen 2019-03-20 13:00:19 +08:00
parent 960ef2e1f8
commit a0d9a8b2de
9 changed files with 77 additions and 21 deletions

View File

@ -1,4 +1,5 @@
use alloc::sync::Arc; use alloc::sync::Arc;
use alloc::string::String;
use core::cmp::min; use core::cmp::min;
use core::mem::{size_of}; use core::mem::{size_of};
use core::slice; use core::slice;
@ -107,6 +108,10 @@ impl Driver for VirtIOBlkDriver {
fn device_type(&self) -> DeviceType { fn device_type(&self) -> DeviceType {
DeviceType::Block DeviceType::Block
} }
fn get_id(&self) -> String {
format!("virtio_block")
}
} }
impl BlockDevice for VirtIOBlkDriver { impl BlockDevice for VirtIOBlkDriver {

View File

@ -3,8 +3,8 @@ use crate::drivers::{Driver, DRIVERS, NET_DRIVERS};
use alloc::collections::BTreeMap; use alloc::collections::BTreeMap;
use alloc::string::String; use alloc::string::String;
use alloc::sync::Arc; use alloc::sync::Arc;
use spin::Mutex;
use core::cmp::Ordering; use core::cmp::Ordering;
use spin::Mutex;
use x86_64::instructions::port::Port; use x86_64::instructions::port::Port;
const PCI_VENDOR: u32 = 0x00; const PCI_VENDOR: u32 = 0x00;
@ -44,7 +44,6 @@ const PCI_BASE_ADDRESS_MEM_MASK: u32 = 0xfffffff0;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct PciTag(u32); pub struct PciTag(u32);
impl Ord for PciTag { impl Ord for PciTag {
fn cmp(&self, other: &PciTag) -> Ordering { fn cmp(&self, other: &PciTag) -> Ordering {
self.0.cmp(&other.0) self.0.cmp(&other.0)
@ -57,8 +56,7 @@ impl PartialOrd for PciTag {
} }
} }
impl Eq for PciTag { impl Eq for PciTag {}
}
impl PartialEq for PciTag { impl PartialEq for PciTag {
fn eq(&self, other: &PciTag) -> bool { fn eq(&self, other: &PciTag) -> bool {
@ -296,23 +294,22 @@ pub fn init_driver(name: String, vid: u32, did: u32, tag: PciTag) {
// 82599ES 10-Gigabit SFI/SFP+ Network Connection // 82599ES 10-Gigabit SFI/SFP+ Network Connection
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } { if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
let irq = unsafe { tag.enable() }; let irq = unsafe { tag.enable() };
PCI_DRIVERS.lock() PCI_DRIVERS
.lock()
.insert(tag, ixgbe::ixgbe_init(name, irq, addr, len)); .insert(tag, ixgbe::ixgbe_init(name, irq, addr, len));
} }
} }
} }
} }
pub fn detach_driver(bus: u32, dev: u32, func: u32) -> bool { pub fn detach_driver(tag: &PciTag) -> bool {
match PCI_DRIVERS.lock().remove(&PciTag::new(bus, dev, func)) { match PCI_DRIVERS.lock().remove(tag) {
Some(driver) => { Some(driver) => {
DRIVERS.write().retain(|dri| !Arc::ptr_eq(&driver, dri)); DRIVERS.write().retain(|dri| dri.get_id() != driver.get_id());
NET_DRIVERS.write().retain(|dri| !Arc::ptr_eq(&driver, dri)); NET_DRIVERS.write().retain(|dri| dri.get_id() != driver.get_id());
true true
} }
None => { None => false,
false
}
} }
} }
@ -362,5 +359,6 @@ pub fn find_device(vendor: u32, product: u32) -> Option<PciTag> {
} }
lazy_static! { lazy_static! {
pub static ref PCI_DRIVERS: Arc<Mutex<BTreeMap<PciTag, Arc<Driver>>>> = Arc::new(Mutex::new(BTreeMap::new())); pub static ref PCI_DRIVERS: Arc<Mutex<BTreeMap<PciTag, Arc<Driver>>>> =
Arc::new(Mutex::new(BTreeMap::new()));
} }

View File

@ -1,4 +1,5 @@
use alloc::alloc::{GlobalAlloc, Layout}; use alloc::alloc::{GlobalAlloc, Layout};
use alloc::string::String;
use alloc::sync::Arc; use alloc::sync::Arc;
use core::slice; use core::slice;
@ -214,6 +215,10 @@ impl Driver for VirtIOGpuDriver {
fn device_type(&self) -> DeviceType { fn device_type(&self) -> DeviceType {
DeviceType::Gpu DeviceType::Gpu
} }
fn get_id(&self) -> String {
format!("virtio_gpu")
}
} }
fn request(driver: &mut VirtIOGpu) { fn request(driver: &mut VirtIOGpu) {

View File

@ -172,6 +172,10 @@ impl Driver for VirtIOInputDriver {
fn device_type(&self) -> DeviceType { fn device_type(&self) -> DeviceType {
DeviceType::Input DeviceType::Input
} }
fn get_id(&self) -> String {
String::from("virtio_input")
}
} }
pub fn virtio_input_init(node: &Node) { pub fn virtio_input_init(node: &Node) {

View File

@ -6,7 +6,7 @@ use smoltcp::wire::{EthernetAddress, Ipv4Address};
use smoltcp::socket::SocketSet; use smoltcp::socket::SocketSet;
use spin::RwLock; use spin::RwLock;
use crate::sync::{Condvar, MutexGuard, SpinNoIrq}; use crate::sync::Condvar;
use self::block::virtio_blk::VirtIOBlkDriver; use self::block::virtio_blk::VirtIOBlkDriver;
mod device_tree; mod device_tree;
@ -39,6 +39,10 @@ pub trait Driver : Send + Sync {
// return the correspondent device type, see DeviceType // return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType; fn device_type(&self) -> DeviceType;
// get unique identifier for this device
// should be different for each instance
fn get_id(&self) -> String;
// Rust trait is still too restricted... // Rust trait is still too restricted...
// network related drivers should implement these // network related drivers should implement these
// get mac address for this device // get mac address for this device

View File

@ -16,7 +16,6 @@ use rcore_memory::paging::PageTable;
use rcore_memory::PAGE_SIZE; use rcore_memory::PAGE_SIZE;
use smoltcp::iface::*; 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::wire::*; use smoltcp::wire::*;
@ -123,6 +122,10 @@ impl Driver for E1000Interface {
DeviceType::Net DeviceType::Net
} }
fn get_id(&self) -> String {
format!("e1000")
}
fn get_mac(&self) -> EthernetAddress { fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr() self.iface.lock().ethernet_addr()
} }

View File

@ -145,8 +145,9 @@ const IXGBE_EEC: usize = 0x10010 / 4;
pub struct IXGBEInterface { pub struct IXGBEInterface {
iface: Mutex<EthernetInterface<'static, 'static, 'static, IXGBEDriver>>, iface: Mutex<EthernetInterface<'static, 'static, 'static, IXGBEDriver>>,
driver: IXGBEDriver, driver: IXGBEDriver,
name: String, ifname: String,
irq: Option<u32>, irq: Option<u32>,
id: String,
} }
impl Driver for IXGBEInterface { impl Driver for IXGBEInterface {
@ -180,10 +181,10 @@ impl Driver for IXGBEInterface {
let status = ixgbe[IXGBE_LINKS].read(); let status = ixgbe[IXGBE_LINKS].read();
if status & (1 << 7) != 0 { if status & (1 << 7) != 0 {
// link up // link up
info!("ixgbe: interface {} link up", &self.name); info!("ixgbe: interface {} link up", &self.ifname);
} else { } else {
// link down // link down
info!("ixgbe: interface {} link down", &self.name); info!("ixgbe: interface {} link down", &self.ifname);
} }
} }
if icr & (1 << 0) != 0 { if icr & (1 << 0) != 0 {
@ -217,12 +218,16 @@ impl Driver for IXGBEInterface {
DeviceType::Net DeviceType::Net
} }
fn get_id(&self) -> String {
self.ifname.clone()
}
fn get_mac(&self) -> EthernetAddress { fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr() self.iface.lock().ethernet_addr()
} }
fn get_ifname(&self) -> String { fn get_ifname(&self) -> String {
self.name.clone() self.ifname.clone()
} }
fn ipv4_address(&self) -> Option<Ipv4Address> { fn ipv4_address(&self) -> Option<Ipv4Address> {
@ -789,7 +794,8 @@ pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) ->
let ixgbe_iface = IXGBEInterface { let ixgbe_iface = IXGBEInterface {
iface: Mutex::new(iface), iface: Mutex::new(iface),
driver: net_driver.clone(), driver: net_driver.clone(),
name, ifname: name.clone(),
id: name,
irq, irq,
}; };
@ -801,6 +807,28 @@ pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) ->
impl Drop for IXGBE { impl Drop for IXGBE {
fn drop(&mut self) { fn drop(&mut self) {
debug!("ixgbe: interface detaching");
if let None = active_table().get_entry(self.header) {
let mut current_addr = self.header;
while current_addr < self.header + self.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let ixgbe = unsafe {
slice::from_raw_parts_mut(self.header as *mut Volatile<u32>, self.size / 4)
};
// 1. Disable interrupts.
ixgbe[IXGBE_EIMC].write(!0);
ixgbe[IXGBE_EIMC1].write(!0);
ixgbe[IXGBE_EIMC2].write(!0);
// 2. Issue a global reset.
// reset: LRST | RST
ixgbe[IXGBE_CTRL].write(1 << 3 | 1 << 26);
while ixgbe[IXGBE_CTRL].read() & (1 << 3 | 1 << 26) != 0 {}
unsafe { unsafe {
HEAP_ALLOCATOR.dealloc(self.send_page as *mut u8, Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()); HEAP_ALLOCATOR.dealloc(self.send_page as *mut u8, Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap());
HEAP_ALLOCATOR.dealloc(self.recv_page as *mut u8, Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()); HEAP_ALLOCATOR.dealloc(self.recv_page as *mut u8, Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap());

View File

@ -65,6 +65,10 @@ impl Driver for VirtIONetDriver {
DeviceType::Net DeviceType::Net
} }
fn get_id(&self) -> String {
format!("virtio_net")
}
fn get_mac(&self) -> EthernetAddress { fn get_mac(&self) -> EthernetAddress {
self.0.lock().mac self.0.lock().mac
} }

View File

@ -9,11 +9,16 @@ use super::*;
pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult { pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
use crate::drivers::bus::pci; use crate::drivers::bus::pci;
info!( info!(
"map_pci_device: vendor: {}, product: {}", "map_pci_device: vendor: {:x}, product: {:x}",
vendor, product vendor, product
); );
let tag = pci::find_device(vendor as u32, product as u32) let tag = pci::find_device(vendor as u32, product as u32)
.ok_or(SysError::ENOENT)?; .ok_or(SysError::ENOENT)?;
if pci::detach_driver(&tag) {
info!("Kernel driver detached");
}
// Get BAR0 memory // Get BAR0 memory
let (base, len) = unsafe { tag.get_bar_mem(0) } let (base, len) = unsafe { tag.get_bar_mem(0) }
.ok_or(SysError::ENOENT)?; .ok_or(SysError::ENOENT)?;