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::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 {
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user