mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 08:06:17 +04:00
Implement PCI driver detach and merge NetDriver trait into Driver
This commit is contained in:
parent
cf3b183311
commit
960ef2e1f8
16
README.md
16
README.md
@ -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 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 {
|
||||
@ -312,4 +359,8 @@ 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;
|
||||
@ -25,28 +25,28 @@ use super::super::net::virtio_net;
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct VirtIOHeader {
|
||||
magic: ReadOnly<u32>, // 0x000
|
||||
version: ReadOnly<u32>, // 0x004
|
||||
device_id: ReadOnly<u32>, // 0x008
|
||||
vendor_id: ReadOnly<u32>, // 0x00c
|
||||
pub device_features: ReadOnly<u32>, // 0x010
|
||||
magic: ReadOnly<u32>, // 0x000
|
||||
version: ReadOnly<u32>, // 0x004
|
||||
device_id: ReadOnly<u32>, // 0x008
|
||||
vendor_id: ReadOnly<u32>, // 0x00c
|
||||
pub device_features: ReadOnly<u32>, // 0x010
|
||||
pub device_features_sel: WriteOnly<u32>, // 0x014
|
||||
__r1: [ReadOnly<u32>; 2],
|
||||
pub driver_features: WriteOnly<u32>, // 0x020
|
||||
__r1: [ReadOnly<u32>; 2],
|
||||
pub driver_features: WriteOnly<u32>, // 0x020
|
||||
pub driver_features_sel: WriteOnly<u32>, // 0x024
|
||||
pub guest_page_size: WriteOnly<u32>, // 0x028
|
||||
pub guest_page_size: WriteOnly<u32>, // 0x028
|
||||
__r2: ReadOnly<u32>,
|
||||
pub queue_sel: WriteOnly<u32>, // 0x030
|
||||
pub queue_sel: WriteOnly<u32>, // 0x030
|
||||
pub queue_num_max: ReadOnly<u32>, // 0x034
|
||||
pub queue_num: WriteOnly<u32>, // 0x038
|
||||
pub queue_align: WriteOnly<u32>, // 0x03c
|
||||
pub queue_pfn: Volatile<u32>, // 0x040
|
||||
queue_ready: Volatile<u32>, // new interface only
|
||||
pub queue_num: WriteOnly<u32>, // 0x038
|
||||
pub queue_align: WriteOnly<u32>, // 0x03c
|
||||
pub queue_pfn: Volatile<u32>, // 0x040
|
||||
queue_ready: Volatile<u32>, // new interface only
|
||||
__r3: [ReadOnly<u32>; 2],
|
||||
pub queue_notify: WriteOnly<u32>, // 0x050
|
||||
__r4: [ReadOnly<u32>; 3],
|
||||
pub interrupt_status: ReadOnly<u32>, // 0x060
|
||||
pub interrupt_ack: WriteOnly<u32>, // 0x064
|
||||
pub interrupt_ack: WriteOnly<u32>, // 0x064
|
||||
__r5: [ReadOnly<u32>; 2],
|
||||
pub status: Volatile<u32>, // 0x070
|
||||
__r6: [ReadOnly<u32>; 3],
|
||||
@ -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)]
|
||||
@ -68,9 +68,9 @@ pub struct VirtIOVirtqueue {
|
||||
queue_address: usize,
|
||||
queue_num: usize,
|
||||
queue: usize,
|
||||
desc: usize, // *mut VirtIOVirtqueueDesc,
|
||||
desc: usize, // *mut VirtIOVirtqueueDesc,
|
||||
avail: usize, // *mut VirtIOVirtqueueAvailableRing,
|
||||
used: usize, // *mut VirtIOVirtqueueUsedRing,
|
||||
used: usize, // *mut VirtIOVirtqueueUsedRing,
|
||||
desc_state: Vec<usize>,
|
||||
num_used: usize,
|
||||
free_head: usize,
|
||||
@ -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);
|
||||
@ -365,4 +393,4 @@ pub fn virtio_probe(node: &Node) {
|
||||
active_table().unmap(from as usize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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…
Reference in New Issue
Block a user