Implement PCI driver detach and merge NetDriver trait into Driver

master
Jiajie Chen 6 years ago
parent cf3b183311
commit 960ef2e1f8

@ -6,9 +6,9 @@ Rust version of THU [uCore OS Plus](https://github.com/chyyuu/ucore_os_plus).
Going to be the next generation teaching operating system.
Supported architectures: x86_64, RISCV32/64, AArch64
Supported architectures: x86_64, RISCV32/64, AArch64, MIPS (planned)
Tested boards: QEMU, PC, Raspberry Pi 3B+
Tested boards: QEMU, HiFive Unleashed, x86_64 PC (i5/i7), Raspberry Pi 3B+
[Dev docs](https://rucore.gitbook.io/rust-os-docs/) (in Chinese)
@ -24,20 +24,22 @@ Tested boards: QEMU, PC, Raspberry Pi 3B+
* [bootimage](https://github.com/rust-osdev/bootimage) (for x86_64)
* [RISCV64 GNU toolchain](https://www.sifive.com/boards) (for riscv32/64)
* [AArch64 GNU toolchain](https://cs140e.sergio.bz/assignments/0-blinky/) (for aarch64)
* [musl-cross-make](https://github.com/richfelker/musl-cross-make) (for userland musl)
See [Travis script](./.travis.yml) for details.
### How to run
```bash
rustup component add rust-src
cargo install cargo-xbuild bootimage
$ rustup component add rust-src
$ cargo install cargo-xbuild bootimage
```
```bash
git clone https://github.com/rcore-os/rCore.git --recursive
cd rCore/kernel
make run arch={riscv32,riscv64,x86_64,aarch64}
$ git clone https://github.com/rcore-os/rCore.git --recursive
$ cd rCore/kernel
$ make sfsimg arch={riscv32,riscv64,x86_64,aarch64} # requires musl-cross-make
$ make run arch={riscv32,riscv64,x86_64,aarch64}
```
## History

@ -1,3 +1,3 @@
pub mod virtio_mmio;
#[cfg(target_arch = "x86_64")]
pub mod pci;
pub mod virtio_mmio;

@ -1,6 +1,11 @@
use crate::drivers::net::*;
use x86_64::instructions::port::Port;
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 x86_64::instructions::port::Port;
const PCI_VENDOR: u32 = 0x00;
const PCI_DEVICE: u32 = 0x02;
@ -39,6 +44,28 @@ 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)
}
}
impl PartialOrd for PciTag {
fn partial_cmp(&self, other: &PciTag) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Eq for PciTag {
}
impl PartialEq for PciTag {
fn eq(&self, other: &PciTag) -> bool {
self.0 == other.0
}
}
impl PciTag {
pub fn new(bus: u32, dev: u32, func: u32) -> PciTag {
assert!(bus < 256);
@ -135,10 +162,9 @@ impl PciTag {
max_base |= (max_base_hi as usize) << 32;
address_mark = !0;
}
_ => unimplemented!("pci bar mem type")
_ => unimplemented!("pci bar mem type"),
}
if max_base == 0 {
return None;
}
@ -191,7 +217,6 @@ impl PciTag {
}
}
/// Enable the pci tag and its interrupt
/// Return assigned MSI interrupt number when applicable
pub unsafe fn enable(&self) -> Option<u32> {
@ -221,11 +246,18 @@ impl PciTag {
// enable MSI interrupt, assuming 64bit for now
let orig_ctrl = self.read(cap_ptr + PCI_MSI_CTRL_CAP, 4);
self.write(cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
debug!("MSI control {:#b}, enabling MSI interrupts", orig_ctrl >> 16);
debug!(
"MSI control {:#b}, enabling MSI interrupts",
orig_ctrl >> 16
);
msi_found = true;
break;
}
debug!("PCI device has cap id {} at {:#X}", self.read(cap_ptr, 1), cap_ptr);
debug!(
"PCI device has cap id {} at {:#X}",
self.read(cap_ptr, 1),
cap_ptr
);
cap_ptr = self.read(cap_ptr + 1, 1);
}
@ -235,7 +267,10 @@ impl PciTag {
self.write(PCI_COMMAND, orig | 0xf);
let line = self.read(PCI_INTERRUPT_LINE, 1);
let pin = self.read(PCI_INTERRUPT_PIN, 1);
debug!("MSI not found, using PCI interrupt line {} pin {}", line, pin);
debug!(
"MSI not found, using PCI interrupt line {} pin {}",
line, pin
);
}
assigned_irq
@ -260,15 +295,27 @@ pub fn init_driver(name: String, vid: u32, did: u32, tag: PciTag) {
} else if did == 0x10fb {
// 82599ES 10-Gigabit SFI/SFP+ Network Connection
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
let irq = unsafe {
tag.enable()
};
ixgbe::ixgbe_init(name, irq, addr, len);
let irq = unsafe { tag.enable() };
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)) {
Some(driver) => {
DRIVERS.write().retain(|dri| !Arc::ptr_eq(&driver, dri));
NET_DRIVERS.write().retain(|dri| !Arc::ptr_eq(&driver, dri));
true
}
None => {
false
}
}
}
pub fn init() {
for bus in 0..256 {
for dev in 0..32 {
@ -313,3 +360,7 @@ pub fn find_device(vendor: u32, product: u32) -> Option<PciTag> {
}
None
}
lazy_static! {
pub static ref PCI_DRIVERS: Arc<Mutex<BTreeMap<PciTag, Arc<Driver>>>> = Arc::new(Mutex::new(BTreeMap::new()));
}

@ -1,20 +1,20 @@
use alloc::{vec, vec::Vec};
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::{vec, vec::Vec};
use core::mem::size_of;
use core::slice;
use core::sync::atomic::{fence, Ordering};
use bitflags::*;
use device_tree::Node;
use device_tree::util::SliceRead;
use device_tree::Node;
use log::*;
use rcore_memory::PAGE_SIZE;
use rcore_memory::paging::PageTable;
use rcore_memory::PAGE_SIZE;
use volatile::{ReadOnly, Volatile, WriteOnly};
use crate::HEAP_ALLOCATOR;
use crate::memory::active_table;
use crate::arch::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
use crate::memory::active_table;
use crate::HEAP_ALLOCATOR;
use super::super::block::virtio_blk;
use super::super::gpu::virtio_gpu;
@ -59,7 +59,7 @@ pub struct VirtIOHeader {
queue_used_low: WriteOnly<u32>,
queue_used_high: WriteOnly<u32>,
__r9: [ReadOnly<u32>; 21],
config_generation: ReadOnly<u32>
config_generation: ReadOnly<u32>,
}
#[repr(C)]
@ -90,16 +90,19 @@ impl VirtIOVirtqueue {
let size = virtqueue_size(queue_num, align);
assert!(size % align == 0);
// alloc continuous pages
let address = unsafe {
HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(size, align).unwrap())
} as usize;
let address =
unsafe { HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(size, align).unwrap()) }
as usize;
header.queue_num.write(queue_num as u32);
header.queue_align.write(align as u32);
header.queue_pfn.write(((address - KERNEL_OFFSET + MEMORY_OFFSET) as u32) >> 12);
header
.queue_pfn
.write(((address - KERNEL_OFFSET + MEMORY_OFFSET) as u32) >> 12);
// link desc together
let desc = unsafe { slice::from_raw_parts_mut(address as *mut VirtIOVirtqueueDesc, queue_num) };
let desc =
unsafe { slice::from_raw_parts_mut(address as *mut VirtIOVirtqueueDesc, queue_num) };
for i in 0..(queue_num - 1) {
desc[i].next.write((i + 1) as u16);
}
@ -133,25 +136,35 @@ impl VirtIOVirtqueue {
return false;
}
let desc = unsafe { slice::from_raw_parts_mut(self.desc as *mut VirtIOVirtqueueDesc, self.queue_num) };
let desc = unsafe {
slice::from_raw_parts_mut(self.desc as *mut VirtIOVirtqueueDesc, self.queue_num)
};
let head = self.free_head;
let mut prev = 0;
let mut cur = self.free_head;
for i in 0..output.len() {
desc[cur].flags.write(VirtIOVirtqueueFlag::NEXT.bits());
desc[cur].addr.write(output[i].as_ptr() as u64 - KERNEL_OFFSET as u64 + MEMORY_OFFSET as u64);
desc[cur]
.addr
.write(output[i].as_ptr() as u64 - KERNEL_OFFSET as u64 + MEMORY_OFFSET as u64);
desc[cur].len.write(output[i].len() as u32);
prev = cur;
cur = desc[cur].next.read() as usize;
}
for i in 0..input.len() {
desc[cur].flags.write((VirtIOVirtqueueFlag::NEXT | VirtIOVirtqueueFlag::WRITE).bits());
desc[cur].addr.write(input[i].as_ptr() as u64 - KERNEL_OFFSET as u64 + MEMORY_OFFSET as u64);
desc[cur]
.flags
.write((VirtIOVirtqueueFlag::NEXT | VirtIOVirtqueueFlag::WRITE).bits());
desc[cur]
.addr
.write(input[i].as_ptr() as u64 - KERNEL_OFFSET as u64 + MEMORY_OFFSET as u64);
desc[cur].len.write(input[i].len() as u32);
prev = cur;
cur = desc[cur].next.read() as usize;
}
desc[prev].flags.write(desc[prev].flags.read() & !(VirtIOVirtqueueFlag::NEXT.bits()));
desc[prev]
.flags
.write(desc[prev].flags.read() & !(VirtIOVirtqueueFlag::NEXT.bits()));
self.num_used += input.len() + output.len();
self.free_head = cur;
@ -189,7 +202,7 @@ impl VirtIOVirtqueue {
pub fn get(&mut self) -> Option<(Vec<&'static [u8]>, Vec<&'static [u8]>, usize, usize)> {
let used = unsafe { &mut *(self.used as *mut VirtIOVirtqueueUsedRing) };
if self.last_used_idx == used.idx.read() {
return None
return None;
}
// read barrier
fence(Ordering::SeqCst);
@ -202,13 +215,16 @@ impl VirtIOVirtqueue {
self.desc_state[last_used_slot] = 0;
let mut cur = index;
let desc = unsafe { slice::from_raw_parts_mut(self.desc as *mut VirtIOVirtqueueDesc, self.queue_num) };
let desc = unsafe {
slice::from_raw_parts_mut(self.desc as *mut VirtIOVirtqueueDesc, self.queue_num)
};
let mut input = Vec::new();
let mut output = Vec::new();
loop {
let flags = VirtIOVirtqueueFlag::from_bits_truncate(desc[cur].flags.read());
let addr = desc[cur].addr.read() as u64 - MEMORY_OFFSET as u64 + KERNEL_OFFSET as u64;
let buffer = unsafe { slice::from_raw_parts(addr as *const u8, desc[cur].len.read() as usize) };
let buffer =
unsafe { slice::from_raw_parts(addr as *const u8, desc[cur].len.read() as usize) };
if flags.contains(VirtIOVirtqueueFlag::WRITE) {
input.push(buffer);
} else {
@ -221,7 +237,7 @@ impl VirtIOVirtqueue {
} else {
desc[cur].next.write(self.free_head as u16);
self.num_used -= 1;
break
break;
}
}
@ -263,9 +279,11 @@ impl VirtIOHeader {
pub fn write_driver_features(&mut self, driver_features: u64) {
self.driver_features_sel.write(0); // driver features [0, 32)
self.driver_features.write((driver_features & 0xFFFFFFFF) as u32);
self.driver_features
.write((driver_features & 0xFFFFFFFF) as u32);
self.driver_features_sel.write(1); // driver features [32, 64)
self.driver_features.write(((driver_features & 0xFFFFFFFF00000000) >> 32) as u32);
self.driver_features
.write(((driver_features & 0xFFFFFFFF00000000) >> 32) as u32);
}
}
@ -286,7 +304,7 @@ pub struct VirtIOVirtqueueDesc {
pub addr: Volatile<u64>,
pub len: Volatile<u32>,
pub flags: Volatile<u16>,
pub next: Volatile<u16>
pub next: Volatile<u16>,
}
bitflags! {
@ -303,14 +321,14 @@ pub struct VirtIOVirtqueueAvailableRing {
pub flags: Volatile<u16>,
pub idx: Volatile<u16>,
pub ring: [Volatile<u16>; 32], // actual size: queue_size
used_event: Volatile<u16> // unused
used_event: Volatile<u16>, // unused
}
#[repr(C)]
#[derive(Debug)]
pub struct VirtIOVirtqueueUsedElem {
id: Volatile<u32>,
len: Volatile<u32>
len: Volatile<u32>,
}
#[repr(C)]
@ -319,17 +337,19 @@ pub struct VirtIOVirtqueueUsedRing {
pub flags: Volatile<u16>,
pub idx: Volatile<u16>,
pub ring: [VirtIOVirtqueueUsedElem; 32], // actual size: queue_size
avail_event: Volatile<u16> // unused
avail_event: Volatile<u16>, // unused
}
// virtio 2.4.2 Legacy Interfaces: A Note on Virtqueue Layout
pub fn virtqueue_size(num: usize, align: usize) -> usize {
(((size_of::<VirtIOVirtqueueDesc>() * num + size_of::<u16>() * (3 + num)) + align) & !(align-1)) +
(((size_of::<u16>() * 3 + size_of::<VirtIOVirtqueueUsedElem>() * num) + align) & !(align-1))
(((size_of::<VirtIOVirtqueueDesc>() * num + size_of::<u16>() * (3 + num)) + align)
& !(align - 1))
+ (((size_of::<u16>() * 3 + size_of::<VirtIOVirtqueueUsedElem>() * num) + align)
& !(align - 1))
}
pub fn virtqueue_used_elem_offset(num: usize, align: usize) -> usize {
((size_of::<VirtIOVirtqueueDesc>() * num + size_of::<u16>() * (3 + num)) + align) & !(align-1)
((size_of::<VirtIOVirtqueueDesc>() * num + size_of::<u16>() * (3 + num)) + align) & !(align - 1)
}
pub fn virtio_probe(node: &Node) {
@ -344,19 +364,27 @@ pub fn virtio_probe(node: &Node) {
let version = header.version.read();
let device_id = header.device_id.read();
// only support legacy device
if magic == 0x74726976 && version == 1 && device_id != 0 { // "virt" magic
info!("Detected virtio device with vendor id {:#X}", header.vendor_id.read());
if magic == 0x74726976 && version == 1 && device_id != 0 {
// "virt" magic
info!(
"Detected virtio device with vendor id {:#X}",
header.vendor_id.read()
);
info!("Device tree node {:?}", node);
// virtio 3.1.1 Device Initialization
header.status.write(0);
header.status.write(VirtIODeviceStatus::ACKNOWLEDGE.bits());
if device_id == 1 { // net device
if device_id == 1 {
// net device
virtio_net::virtio_net_init(node);
} else if device_id == 2 { // blk device
} else if device_id == 2 {
// blk device
virtio_blk::virtio_blk_init(node);
} else if device_id == 16 { // gpu device
} else if device_id == 16 {
// gpu device
virtio_gpu::virtio_gpu_init(node);
} else if device_id == 18 { // input device
} else if device_id == 18 {
// input device
virtio_input::virtio_input_init(node);
} else {
println!("Unrecognized virtio device {}", device_id);

@ -38,27 +38,35 @@ pub trait Driver : Send + Sync {
// return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType;
}
pub trait NetDriver : Driver {
// Rust trait is still too restricted...
// network related drivers should implement these
// get mac address for this device
fn get_mac(&self) -> EthernetAddress;
fn get_mac(&self) -> EthernetAddress {
unimplemented!("not a net driver")
}
// get interface name for this device
fn get_ifname(&self) -> String;
fn get_ifname(&self) -> String {
unimplemented!("not a net driver")
}
// get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address>;
fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!("not a net driver")
}
// manually trigger a poll, use it after sending packets
fn poll(&self);
fn poll(&self) {
unimplemented!("not a net driver")
}
}
lazy_static! {
// NOTE: RwLock only write when initializing drivers
pub static ref DRIVERS: RwLock<Vec<Arc<Driver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<NetDriver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<Driver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<VirtIOBlkDriver>>> = RwLock::new(Vec::new());
}

@ -1,4 +1,5 @@
//! Intel PRO/1000 Network Adapter i.e. e1000 network driver
//! Datasheet: https://www.intel.ca/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::format;
@ -28,7 +29,7 @@ use crate::sync::SpinNoIrqLock as Mutex;
use crate::sync::{MutexGuard, SpinNoIrq};
use crate::HEAP_ALLOCATOR;
use super::super::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
// At the beginning, all transmit descriptors have there status non-zero,
// so we need to track whether we are using the descriptor for the first time.
@ -121,9 +122,7 @@ impl Driver for E1000Interface {
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
}
impl NetDriver for E1000Interface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}

@ -1,4 +1,5 @@
//! Intel 10Gb Network Adapter 82599 i.e. ixgbe network driver
//! Datasheet: https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::prelude::*;
@ -27,7 +28,7 @@ use crate::sync::SpinNoIrqLock as Mutex;
use crate::sync::{MutexGuard, SpinNoIrq};
use crate::HEAP_ALLOCATOR;
use super::super::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
// At the beginning, all transmit descriptors have there status non-zero,
// so we need to track whether we are using the descriptor for the first time.
@ -215,9 +216,7 @@ impl Driver for IXGBEInterface {
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
}
impl NetDriver for IXGBEInterface {
fn get_mac(&self) -> EthernetAddress {
self.iface.lock().ethernet_addr()
}
@ -360,7 +359,7 @@ impl<'a> phy::Device<'a> for IXGBEDriver {
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.max_transmission_unit = IXGBE_MTU; // max MTU
caps.max_burst_size = Some(64);
caps.max_burst_size = Some(256);
// IP Rx checksum is offloaded with RXCSUM
caps.checksum.ipv4 = Checksum::Tx;
caps
@ -442,7 +441,7 @@ bitflags! {
}
}
pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) {
pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) -> Arc<IXGBEInterface> {
assert_eq!(size_of::<IXGBESendDesc>(), 16);
assert_eq!(size_of::<IXGBERecvDesc>(), 16);
@ -796,5 +795,21 @@ pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) {
let driver = Arc::new(ixgbe_iface);
DRIVERS.write().push(driver.clone());
NET_DRIVERS.write().push(driver);
NET_DRIVERS.write().push(driver.clone());
driver
}
impl Drop for IXGBE {
fn drop(&mut self) {
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());
for send_buffer in self.send_buffers.iter() {
HEAP_ALLOCATOR.dealloc(*send_buffer as *mut u8, Layout::from_size_align(IXGBE_BUFFER_SIZE, PAGE_SIZE).unwrap());
}
for recv_buffer in self.recv_buffers.iter() {
HEAP_ALLOCATOR.dealloc(*recv_buffer as *mut u8, Layout::from_size_align(IXGBE_BUFFER_SIZE, PAGE_SIZE).unwrap());
}
}
}
}

@ -24,7 +24,7 @@ use crate::sync::{MutexGuard, SpinNoIrq};
use crate::HEAP_ALLOCATOR;
use super::super::bus::virtio_mmio::*;
use super::super::{DeviceType, Driver, NetDriver, DRIVERS, NET_DRIVERS};
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS};
pub struct VirtIONet {
interrupt_parent: u32,
@ -64,19 +64,7 @@ impl Driver for VirtIONetDriver {
fn device_type(&self) -> DeviceType {
DeviceType::Net
}
}
impl VirtIONet {
fn transmit_available(&self) -> bool {
self.queues[VIRTIO_QUEUE_TRANSMIT].can_add(1, 0)
}
fn receive_available(&self) -> bool {
self.queues[VIRTIO_QUEUE_RECEIVE].can_get()
}
}
impl NetDriver for VirtIONetDriver {
fn get_mac(&self) -> EthernetAddress {
self.0.lock().mac
}
@ -94,6 +82,16 @@ impl NetDriver for VirtIONetDriver {
}
}
impl VirtIONet {
fn transmit_available(&self) -> bool {
self.queues[VIRTIO_QUEUE_TRANSMIT].can_add(1, 0)
}
fn receive_available(&self) -> bool {
self.queues[VIRTIO_QUEUE_RECEIVE].can_get()
}
}
pub struct VirtIONetRxToken(VirtIONetDriver);
pub struct VirtIONetTxToken(VirtIONetDriver);

@ -1,4 +1,4 @@
use crate::drivers::NetDriver;
use crate::drivers::Driver;
use crate::drivers::NET_DRIVERS;
use crate::net::SOCKETS;
use crate::thread;

@ -11,7 +11,6 @@ use crate::arch::interrupt::{Context, TrapFrame};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use crate::fs::{FileHandle, OpenOptions};
use crate::sync::Condvar;
use crate::drivers::NET_DRIVERS;
use crate::net::{SocketWrapper, SOCKETS};
use super::abi::{self, ProcInitInfo};

@ -3,6 +3,8 @@ use rcore_memory::memory_set::handler::Linear;
use rcore_memory::memory_set::MemoryAttr;
use super::*;
/// Allocate this PCI device to user space
/// The kernel driver using the PCI device will be unloaded
#[cfg(target_arch = "x86_64")]
pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
use crate::drivers::bus::pci;

@ -1,7 +1,7 @@
//! Syscalls for networking
use super::*;
use crate::drivers::{NET_DRIVERS, SOCKET_ACTIVITY};
use crate::drivers::SOCKET_ACTIVITY;
use crate::net::{
get_ephemeral_port, poll_ifaces, SocketType, SocketWrapper, TcpSocketState, UdpSocketState,
SOCKETS,

Loading…
Cancel
Save