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:
parent
960ef2e1f8
commit
a0d9a8b2de
@ -1,4 +1,5 @@
|
||||
use alloc::sync::Arc;
|
||||
use alloc::string::String;
|
||||
use core::cmp::min;
|
||||
use core::mem::{size_of};
|
||||
use core::slice;
|
||||
@ -107,6 +108,10 @@ impl Driver for VirtIOBlkDriver {
|
||||
fn device_type(&self) -> DeviceType {
|
||||
DeviceType::Block
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("virtio_block")
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockDevice for VirtIOBlkDriver {
|
||||
|
@ -3,8 +3,8 @@ use crate::drivers::{Driver, DRIVERS, NET_DRIVERS};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use spin::Mutex;
|
||||
use core::cmp::Ordering;
|
||||
use spin::Mutex;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
const PCI_VENDOR: u32 = 0x00;
|
||||
@ -44,7 +44,6 @@ const PCI_BASE_ADDRESS_MEM_MASK: u32 = 0xfffffff0;
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PciTag(u32);
|
||||
|
||||
|
||||
impl Ord for PciTag {
|
||||
fn cmp(&self, other: &PciTag) -> Ordering {
|
||||
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 {
|
||||
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
|
||||
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
|
||||
let irq = unsafe { tag.enable() };
|
||||
PCI_DRIVERS.lock()
|
||||
PCI_DRIVERS
|
||||
.lock()
|
||||
.insert(tag, ixgbe::ixgbe_init(name, irq, addr, len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detach_driver(bus: u32, dev: u32, func: u32) -> bool {
|
||||
match PCI_DRIVERS.lock().remove(&PciTag::new(bus, dev, func)) {
|
||||
pub fn detach_driver(tag: &PciTag) -> bool {
|
||||
match PCI_DRIVERS.lock().remove(tag) {
|
||||
Some(driver) => {
|
||||
DRIVERS.write().retain(|dri| !Arc::ptr_eq(&driver, dri));
|
||||
NET_DRIVERS.write().retain(|dri| !Arc::ptr_eq(&driver, dri));
|
||||
DRIVERS.write().retain(|dri| dri.get_id() != driver.get_id());
|
||||
NET_DRIVERS.write().retain(|dri| dri.get_id() != driver.get_id());
|
||||
true
|
||||
}
|
||||
None => {
|
||||
false
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,5 +359,6 @@ pub fn find_device(vendor: u32, product: u32) -> Option<PciTag> {
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use alloc::alloc::{GlobalAlloc, Layout};
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use core::slice;
|
||||
|
||||
@ -214,6 +215,10 @@ impl Driver for VirtIOGpuDriver {
|
||||
fn device_type(&self) -> DeviceType {
|
||||
DeviceType::Gpu
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("virtio_gpu")
|
||||
}
|
||||
}
|
||||
|
||||
fn request(driver: &mut VirtIOGpu) {
|
||||
|
@ -172,6 +172,10 @@ impl Driver for VirtIOInputDriver {
|
||||
fn device_type(&self) -> DeviceType {
|
||||
DeviceType::Input
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
String::from("virtio_input")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn virtio_input_init(node: &Node) {
|
||||
|
@ -6,7 +6,7 @@ use smoltcp::wire::{EthernetAddress, Ipv4Address};
|
||||
use smoltcp::socket::SocketSet;
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::sync::{Condvar, MutexGuard, SpinNoIrq};
|
||||
use crate::sync::Condvar;
|
||||
use self::block::virtio_blk::VirtIOBlkDriver;
|
||||
|
||||
mod device_tree;
|
||||
@ -39,6 +39,10 @@ pub trait Driver : Send + Sync {
|
||||
// return the correspondent device type, see 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...
|
||||
// network related drivers should implement these
|
||||
// get mac address for this device
|
||||
|
@ -16,7 +16,6 @@ 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::wire::*;
|
||||
@ -123,6 +122,10 @@ impl Driver for E1000Interface {
|
||||
DeviceType::Net
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("e1000")
|
||||
}
|
||||
|
||||
fn get_mac(&self) -> EthernetAddress {
|
||||
self.iface.lock().ethernet_addr()
|
||||
}
|
||||
|
@ -145,8 +145,9 @@ const IXGBE_EEC: usize = 0x10010 / 4;
|
||||
pub struct IXGBEInterface {
|
||||
iface: Mutex<EthernetInterface<'static, 'static, 'static, IXGBEDriver>>,
|
||||
driver: IXGBEDriver,
|
||||
name: String,
|
||||
ifname: String,
|
||||
irq: Option<u32>,
|
||||
id: String,
|
||||
}
|
||||
|
||||
impl Driver for IXGBEInterface {
|
||||
@ -180,10 +181,10 @@ impl Driver for IXGBEInterface {
|
||||
let status = ixgbe[IXGBE_LINKS].read();
|
||||
if status & (1 << 7) != 0 {
|
||||
// link up
|
||||
info!("ixgbe: interface {} link up", &self.name);
|
||||
info!("ixgbe: interface {} link up", &self.ifname);
|
||||
} else {
|
||||
// link down
|
||||
info!("ixgbe: interface {} link down", &self.name);
|
||||
info!("ixgbe: interface {} link down", &self.ifname);
|
||||
}
|
||||
}
|
||||
if icr & (1 << 0) != 0 {
|
||||
@ -217,12 +218,16 @@ impl Driver for IXGBEInterface {
|
||||
DeviceType::Net
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
self.ifname.clone()
|
||||
}
|
||||
|
||||
fn get_mac(&self) -> EthernetAddress {
|
||||
self.iface.lock().ethernet_addr()
|
||||
}
|
||||
|
||||
fn get_ifname(&self) -> String {
|
||||
self.name.clone()
|
||||
self.ifname.clone()
|
||||
}
|
||||
|
||||
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 {
|
||||
iface: Mutex::new(iface),
|
||||
driver: net_driver.clone(),
|
||||
name,
|
||||
ifname: name.clone(),
|
||||
id: name,
|
||||
irq,
|
||||
};
|
||||
|
||||
@ -801,6 +807,28 @@ pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) ->
|
||||
|
||||
impl Drop for IXGBE {
|
||||
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 {
|
||||
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());
|
||||
|
@ -65,6 +65,10 @@ impl Driver for VirtIONetDriver {
|
||||
DeviceType::Net
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("virtio_net")
|
||||
}
|
||||
|
||||
fn get_mac(&self) -> EthernetAddress {
|
||||
self.0.lock().mac
|
||||
}
|
||||
|
@ -9,11 +9,16 @@ use super::*;
|
||||
pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
|
||||
use crate::drivers::bus::pci;
|
||||
info!(
|
||||
"map_pci_device: vendor: {}, product: {}",
|
||||
"map_pci_device: vendor: {:x}, product: {:x}",
|
||||
vendor, product
|
||||
);
|
||||
|
||||
let tag = pci::find_device(vendor as u32, product as u32)
|
||||
.ok_or(SysError::ENOENT)?;
|
||||
if pci::detach_driver(&tag) {
|
||||
info!("Kernel driver detached");
|
||||
}
|
||||
|
||||
// Get BAR0 memory
|
||||
let (base, len) = unsafe { tag.get_bar_mem(0) }
|
||||
.ok_or(SysError::ENOENT)?;
|
||||
|
Loading…
Reference in New Issue
Block a user