Merge remote-tracking branch 'origin/master' into mipsel

toolchain_update
Harry Chen 6 years ago
commit f8a62b5549

14
kernel/Cargo.lock generated

@ -125,12 +125,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "deque"
version = "0.3.2"
source = "git+https://github.com/rcore-os/deque.git?branch=no_std#907d03935b9badde1902d9c84d138872f34c6763"
source = "git+https://github.com/rcore-os/deque.git?branch=no_std#b13a836dd69ae82cc0b8d711c2990b9baf5170d1"
[[package]]
name = "device_tree"
version = "1.0.3"
source = "git+https://github.com/rcore-os/device_tree-rs#0e887395ab92e99f68117b17d85b0b417bfd1b45"
source = "git+https://github.com/rcore-os/device_tree-rs#7945459093f49a39996291283b8894753c8a638d"
[[package]]
name = "fixedvec"
@ -252,6 +252,14 @@ name = "pc-keyboard"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pci"
version = "0.0.1"
source = "git+https://github.com/rcore-os/pci-rs#30f2e83aa51dd313957f3fd6c3b233d3c905a4d0"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pulldown-cmark"
version = "0.0.3"
@ -317,6 +325,7 @@ dependencies = [
"mips 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)",
"raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rcore-fs 0.1.0 (git+https://github.com/rcore-os/rcore-fs)",
"rcore-fs-sfs 0.1.0 (git+https://github.com/rcore-os/rcore-fs)",
@ -618,6 +627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "931fb7a4cf34610cf6cbe58d52a8ca5ef4c726d4e2e178abd0dc13a6551c6d73"
"checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a"
"checksum pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48392db76c4e9a69e0b3be356c5f97ebb7b14413c5e4fd0af4755dbf86e2fce"
"checksum pci 0.0.1 (git+https://github.com/rcore-os/pci-rs)" = "<none>"
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"

@ -50,6 +50,7 @@ volatile = "0.2"
heapless = "0.4"
console-traits = "0.3"
buddy_system_allocator = "0.1"
pci = { git = "https://github.com/rcore-os/pci-rs" }
device_tree = { git = "https://github.com/rcore-os/device_tree-rs" }
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers" }
lazy_static = { version = "1.3", features = ["spin_no_std"] }

@ -27,6 +27,7 @@
# | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+
# pci_passthru = 0000:00:00.1 Only available on x86_64, passthrough the specified PCI device
# init = /bin/ls Only available on riscv64, run specified program instead of user shell
# extra_nic = on | off Only available on x86_64, add an additional e1000 nic
arch ?= riscv64
board ?= none
@ -36,6 +37,7 @@ graphic ?= off
smp ?= 4
pci_passthru ?=
init ?=
extra_nic ?= off
target := $(arch)
build_path := target/$(target)/$(mode)
@ -76,7 +78,9 @@ qemu_net_opts := \
ifeq ($(arch), x86_64)
qemu_opts += \
-drive format=raw,file=$(bootimage) \
-drive format=qcow2,file=$(SFSIMG),media=disk,cache=writeback \
-drive format=qcow2,file=$(SFSIMG),media=disk,cache=writeback,id=sfsimg,if=none \
-device ahci,id=ahci0 \
-device ide-drive,drive=sfsimg,bus=ahci0.0 \
-serial mon:stdio \
-m 4G \
-device isa-debug-exit
@ -85,10 +89,15 @@ qemu_net_opts += \
-device e1000e,netdev=net0
else
qemu_opts += \
-machine ubuntu,accel=kvm
-machine accel=kvm
qemu_net_opts += \
-device vfio-pci,host=$(pci_passthru)
endif
ifeq ($(extra_nic), on)
qemu_net_opts += \
-netdev type=tap,id=net1,script=no,downscript=no \
-device e1000e,netdev=net1
endif
else ifeq ($(arch), riscv32)
qemu_opts += \

@ -2,13 +2,13 @@ use crate::consts::KERNEL_OFFSET;
use bit_allocator::BitAlloc;
// Depends on kernel
use super::{BootInfo, MemoryRegionType};
use crate::memory::{active_table, init_heap, FRAME_ALLOCATOR, alloc_frame};
use crate::memory::{active_table, alloc_frame, init_heap, FRAME_ALLOCATOR};
use crate::HEAP_ALLOCATOR;
use rcore_memory::PAGE_SIZE;
use alloc::vec::Vec;
use log::*;
use once::*;
use rcore_memory::paging::*;
use rcore_memory::PAGE_SIZE;
pub fn init(boot_info: &BootInfo) {
assert_has_not_been_called!("memory::init must be called only once");
@ -60,14 +60,12 @@ fn enlarge_heap() {
addrs.push((va, PAGE_SIZE));
}
for (addr, len) in addrs.into_iter() {
for va in (addr..(addr+len)).step_by(PAGE_SIZE) {
for va in (addr..(addr + len)).step_by(PAGE_SIZE) {
page_table.map(va, va - va_offset).update();
}
info!("Adding {:#X} {:#X} to heap", addr, len);
unsafe {
HEAP_ALLOCATOR
.lock()
.init(addr, len);
HEAP_ALLOCATOR.lock().init(addr, len);
}
}
}

@ -0,0 +1,497 @@
//! Driver for AHCI
//!
//! Spec: https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1-3-1.pdf
use alloc::alloc::{alloc_zeroed, Layout};
use alloc::boxed::Box;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::mem::size_of;
use core::slice;
use core::sync::atomic::spin_loop_hint;
use bit_field::*;
use bitflags::*;
use log::*;
use rcore_fs::dev::BlockDevice;
use volatile::Volatile;
use rcore_memory::paging::PageTable;
use rcore_memory::{PhysAddr, VirtAddr, PAGE_SIZE};
use crate::drivers::BlockDriver;
use crate::memory::active_table;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS};
pub struct AHCI {
header: usize,
size: usize,
received_fis: &'static mut AHCIReceivedFIS,
cmd_list: &'static mut [AHCICommandHeader],
cmd_table: &'static mut AHCICommandTable,
data: &'static mut [u8],
port: &'static mut AHCIPort,
}
pub struct AHCIDriver(Mutex<AHCI>);
/// AHCI Generic Host Control (3.1)
#[repr(C)]
pub struct AHCIGHC {
/// Host capability
capability: Volatile<AHCICap>,
/// Global host control
global_host_control: Volatile<u32>,
/// Interrupt status
interrupt_status: Volatile<u32>,
/// Port implemented
port_implemented: Volatile<u32>,
/// Version
version: Volatile<u32>,
/// Command completion coalescing control
ccc_control: Volatile<u32>,
/// Command completion coalescing ports
ccc_ports: Volatile<u32>,
/// Enclosure management location
em_location: Volatile<u32>,
/// Enclosure management control
em_control: Volatile<u32>,
/// Host capabilities extended
capabilities2: Volatile<u32>,
/// BIOS/OS handoff control and status
bios_os_handoff_control: Volatile<u32>,
}
bitflags! {
struct AHCICap : u32 {
const S64A = 1 << 31;
const SNCQ = 1 << 30;
const SSNTF = 1 << 29;
const SMPS = 1 << 28;
const SSS = 1 << 27;
const SALP = 1 << 26;
const SAL = 1 << 25;
const SCLO = 1 << 24;
const ISS_GEN_1 = 1 << 20;
const ISS_GEN_2 = 2 << 20;
const ISS_GEN_3 = 3 << 20;
const SAM = 1 << 18;
const SPM = 1 << 17;
const FBSS = 1 << 16;
const PMD = 1 << 15;
const SSC = 1 << 14;
const PSC = 1 << 13;
const CCCS = 1 << 7;
const EMS = 1 << 6;
const SXS = 1 << 5;
// number of ports - 1
const NUM_MASK = 0b11111;
}
}
impl AHCIGHC {
fn enable(&mut self) {
self.global_host_control.update(|v| {
v.set_bit(13, true);
});
}
fn num_ports(&self) -> usize {
(self.capability.read() & AHCICap::NUM_MASK).bits() as usize + 1
}
fn has_port(&self, port_num: usize) -> bool {
self.port_implemented.read().get_bit(port_num)
}
}
/// AHCI Port Registers (3.3) (one set per port)
#[repr(C)]
pub struct AHCIPort {
command_list_base_address: Volatile<u64>,
fis_base_address: Volatile<u64>,
interrupt_status: Volatile<u32>,
interrupt_enable: Volatile<u32>,
command: Volatile<u32>,
reserved: Volatile<u32>,
task_file_data: Volatile<u32>,
signature: Volatile<u32>,
sata_status: Volatile<u32>,
sata_control: Volatile<u32>,
sata_error: Volatile<u32>,
sata_active: Volatile<u32>,
command_issue: Volatile<u32>,
sata_notification: Volatile<u32>,
fis_based_switch_control: Volatile<u32>,
}
impl AHCIPort {
fn spin_on_slot(&mut self, slot: usize) {
loop {
let ci = self.command_issue.read();
if !ci.get_bit(slot) {
break;
}
spin_loop_hint();
}
}
fn issue_command(&mut self, slot: usize) {
assert!(slot < 32);
self.command_issue.write(1 << (slot as u32));
}
}
/// AHCI Received FIS Structure (4.2.1)
#[repr(C)]
pub struct AHCIReceivedFIS {
dma: [u8; 0x20],
pio: [u8; 0x20],
d2h: [u8; 0x18],
sdbfis: [u8; 0x8],
ufis: [u8; 0x40],
reserved: [u8; 0x60],
}
/// # AHCI Command List Structure (4.2.2)
///
/// Host sends commands to the device through Command List.
///
/// Command List consists of 1 to 32 command headers, each one is called a slot.
///
/// Each command header describes an ATA or ATAPI command, including a
/// Command FIS, an ATAPI command buffer and a bunch of Physical Region
/// Descriptor Tables specifying the data payload address and size.
///
/// https://wiki.osdev.org/images/e/e8/Command_list.jpg
#[repr(C)]
pub struct AHCICommandHeader {
///
flags: CommandHeaderFlags,
/// Physical region descriptor table length in entries
prdt_length: u16,
/// Physical region descriptor byte count transferred
prd_byte_count: u32,
/// Command table descriptor base address
command_table_base_address: u64,
/// Reserved
reserved: [u32; 4],
}
bitflags! {
pub struct CommandHeaderFlags: u16 {
/// Command FIS length in DWORDS, 2 ~ 16
const CFL_MASK = 0b11111;
/// ATAPI
const ATAPI = 1 << 5;
/// Write, 1: H2D, 0: D2H
const WRITE = 1 << 6;
/// Prefetchable
const PREFETCHABLE = 1 << 7;
/// Reset
const RESET = 1 << 8;
/// BIST
const BIST = 1 << 9;
/// Clear busy upon R_OK
const CLEAR = 1 << 10;
/// Port multiplier port
const PORT_MULTIPLIER_PORT_MASK = 0b1111 << 12;
}
}
/// AHCI Command Table (4.2.3)
#[repr(C)]
pub struct AHCICommandTable {
/// Command FIS
cfis: SATAFISRegH2D,
/// ATAPI command, 12 or 16 bytes
acmd: [u8; 16],
/// Reserved
reserved: [u8; 48],
/// Physical region descriptor table entries, 0 ~ 65535
prdt: [AHCIPrdtEntry; 1],
}
/// Physical region descriptor table entry
#[repr(C)]
pub struct AHCIPrdtEntry {
/// Data base address
data_base_address: u64,
/// Reserved
reserved: u32,
/// Bit 21-0: Byte count, 4M max
/// Bit 31: Interrupt on completion
dbc_i: u32,
}
const FIS_REG_H2D: u8 = 0x27;
const CMD_READ_DMA_EXT: u8 = 0x25;
const CMD_WRITE_DMA_EXT: u8 = 0x35;
const CMD_IDENTIFY_DEVICE: u8 = 0xec;
/// SATA Register FIS - Host to Device
///
/// https://wiki.osdev.org/AHCI Figure 5-2
#[repr(C)]
pub struct SATAFISRegH2D {
fis_type: u8,
cflags: u8,
command: u8,
feature_lo: u8,
lba_0: u8, // LBA 7:0
lba_1: u8, // LBA 15:8
lba_2: u8, // LBA 23:16
dev_head: u8,
lba_3: u8, // LBA 31:24
lba_4: u8, // LBA 39:32
lba_5: u8, // LBA 47:40
feature_hi: u8,
sector_count: u16,
reserved: u8,
control: u8,
_padding: [u8; 48],
}
impl SATAFISRegH2D {
fn set_lba(&mut self, lba: u64) {
self.lba_0 = (lba >> 0) as u8;
self.lba_1 = (lba >> 8) as u8;
self.lba_2 = (lba >> 16) as u8;
self.lba_3 = (lba >> 24) as u8;
self.lba_4 = (lba >> 32) as u8;
self.lba_5 = (lba >> 40) as u8;
}
}
/// IDENTIFY DEVICE data
///
/// ATA8-ACS Table 29
#[repr(C)]
pub struct ATAIdentifyPacket {
_1: [u16; 10],
serial: [u8; 20], // words 10-19
_2: [u16; 3],
firmware: [u8; 8], // words 23-26
model: [u8; 40], // words 27-46
_3: [u16; 13],
lba_sectors: u32, // words 60-61
_4: [u16; 38],
lba48_sectors: u64, // words 100-103
}
impl AHCI {
fn read_block(&mut self, block_id: usize, buf: &mut [u8]) -> usize {
self.cmd_list[0].flags = CommandHeaderFlags::empty();
let fis = &mut self.cmd_table.cfis;
// Register FIS from HBA to device
fis.fis_type = FIS_REG_H2D;
fis.cflags = 1 << 7;
// 7.25 READ DMA EXT - 25h, DMA
fis.command = CMD_READ_DMA_EXT;
fis.sector_count = 1;
fis.dev_head = 0x40; // LBA
fis.control = 0x80; // LBA48
fis.set_lba(block_id as u64);
self.port.issue_command(0);
self.port.spin_on_slot(0);
let len = buf.len().min(BLOCK_SIZE);
buf[..len].clone_from_slice(&self.data[0..len]);
len
}
fn write_block(&mut self, block_id: usize, buf: &[u8]) -> usize {
self.cmd_list[0].flags = CommandHeaderFlags::WRITE; // device write
let len = buf.len().min(BLOCK_SIZE);
self.data[0..len].clone_from_slice(&buf[..len]);
let fis = &mut self.cmd_table.cfis;
// Register FIS from HBA to device
fis.fis_type = FIS_REG_H2D;
fis.cflags = 1 << 7;
// ATA8-ACS
// 7.63 WRITE DMA EXT - 35h, DMA
fis.command = CMD_WRITE_DMA_EXT;
fis.sector_count = 1;
fis.dev_head = 0x40; // LBA
fis.control = 0x80; // LBA48
fis.set_lba(block_id as u64);
self.port.issue_command(0);
self.port.spin_on_slot(0);
len
}
}
impl Driver for AHCIDriver {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
false
}
fn device_type(&self) -> DeviceType {
DeviceType::Block
}
fn get_id(&self) -> String {
format!("ahci")
}
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool {
let mut driver = self.0.lock();
driver.read_block(block_id, buf);
true
}
fn write_block(&self, block_id: usize, buf: &[u8]) -> bool {
if buf.len() < BLOCK_SIZE {
return false;
}
let mut driver = self.0.lock();
driver.write_block(block_id, buf);
true
}
}
const BLOCK_SIZE: usize = 512;
fn from_ata_string(data: &[u8]) -> String {
let mut swapped_data = Vec::new();
assert_eq!(data.len() % 2, 0);
for i in (0..data.len()).step_by(2) {
swapped_data.push(data[i + 1]);
swapped_data.push(data[i]);
}
return String::from_utf8(swapped_data).unwrap();
}
/// Allocate consequent physical frames for DMA
fn alloc_dma(page_num: usize) -> (VirtAddr, PhysAddr) {
let layout = Layout::from_size_align(PAGE_SIZE * page_num, PAGE_SIZE).unwrap();
let vaddr = unsafe { alloc_zeroed(layout) } as usize;
let paddr = active_table().get_entry(vaddr).unwrap().target();
(vaddr, paddr)
}
pub fn ahci_init(irq: Option<u32>, header: usize, size: usize) -> Arc<AHCIDriver> {
let ghc = unsafe { &mut *(header as *mut AHCIGHC) };
ghc.enable();
for port_num in 0..ghc.num_ports() {
if ghc.has_port(port_num) {
let addr = header + 0x100 + 0x80 * port_num;
let port = unsafe { &mut *(addr as *mut AHCIPort) };
// SSTS IPM Active
if port.sata_status.read().get_bits(8..12) != 1 {
continue;
}
// SSTS DET Present
if port.sata_status.read().get_bits(0..4) != 3 {
continue;
}
debug!("probing port {}", port_num);
// Disable Port First
port.command.update(|c| {
c.set_bit(4, false);
c.set_bit(0, false);
});
let (rfis_va, rfis_pa) = alloc_dma(1);
let (cmd_list_va, cmd_list_pa) = alloc_dma(1);
let (cmd_table_va, cmd_table_pa) = alloc_dma(1);
let (data_va, data_pa) = alloc_dma(1);
let received_fis = unsafe { &mut *(rfis_va as *mut AHCIReceivedFIS) };
let cmd_list = unsafe {
slice::from_raw_parts_mut(
cmd_list_va as *mut AHCICommandHeader,
PAGE_SIZE / size_of::<AHCICommandHeader>(),
)
};
let cmd_table = unsafe { &mut *(cmd_table_va as *mut AHCICommandTable) };
let identify_data = unsafe { &*(data_va as *mut ATAIdentifyPacket) };
cmd_table.prdt[0].data_base_address = data_pa as u64;
cmd_table.prdt[0].dbc_i = (BLOCK_SIZE - 1) as u32;
cmd_list[0].command_table_base_address = cmd_table_pa as u64;
cmd_list[0].prdt_length = 1;
cmd_list[0].prd_byte_count = 0;
port.command_list_base_address.write(cmd_list_pa as u64);
port.fis_base_address.write(rfis_pa as u64);
// clear status and errors
port.command_issue.write(0);
port.sata_active.write(0);
port.sata_error.write(0);
// enable port
port.command.update(|c| {
*c |= 1 << 0 | 1 << 1 | 1 << 2 | 1 << 4 | 1 << 28;
});
let stat = port.sata_status.read();
if stat == 0 {
warn!("port is not connected to external drive?");
}
let fis = &mut cmd_table.cfis;
// Register FIS from HBA to device
fis.fis_type = FIS_REG_H2D;
fis.cflags = 1 << 7;
// 7.15 IDENTIFY DEVICE - ECh, PIO Data-In
fis.command = CMD_IDENTIFY_DEVICE;
fis.sector_count = 1;
port.issue_command(0);
port.spin_on_slot(0);
unsafe {
debug!(
"Found ATA Device serial {} firmware {} model {} sectors 24bit={} 48bit={}",
from_ata_string(&identify_data.serial).trim_end(),
from_ata_string(&identify_data.firmware).trim_end(),
from_ata_string(&identify_data.model).trim_end(),
identify_data.lba_sectors,
identify_data.lba48_sectors,
);
}
let data = unsafe { slice::from_raw_parts_mut(data_va as *mut u8, BLOCK_SIZE) };
let driver = AHCIDriver(Mutex::new(AHCI {
header,
size,
received_fis,
cmd_list,
cmd_table,
data,
port,
}));
let driver = Arc::new(driver);
DRIVERS.write().push(driver.clone());
BLK_DRIVERS
.write()
.push(Arc::new(BlockDriver(driver.clone())));
return driver;
}
}
unimplemented!();
}

@ -1 +1,2 @@
pub mod ahci;
pub mod virtio_blk;

@ -1,3 +1,4 @@
use alloc::boxed::Box;
use alloc::string::String;
use alloc::sync::Arc;
use core::cmp::min;
@ -14,6 +15,7 @@ use volatile::Volatile;
use rcore_fs::dev::BlockDevice;
use crate::drivers::BlockDriver;
use crate::memory::active_table;
use crate::sync::SpinNoIrqLock as Mutex;
@ -125,11 +127,8 @@ impl Driver for VirtIOBlkDriver {
fn get_id(&self) -> String {
format!("virtio_block")
}
}
impl BlockDevice for VirtIOBlkDriver {
const BLOCK_SIZE_LOG2: u8 = 9; // 512
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> bool {
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool {
let mut driver = self.0.lock();
// ensure header page is mapped
active_table().map_if_not_exists(driver.header as usize, driver.header as usize);
@ -157,7 +156,7 @@ impl BlockDevice for VirtIOBlkDriver {
}
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> bool {
fn write_block(&self, block_id: usize, buf: &[u8]) -> bool {
let mut driver = self.0.lock();
// ensure header page is mapped
active_table().map_if_not_exists(driver.header as usize, driver.header as usize);
@ -226,5 +225,5 @@ pub fn virtio_blk_init(node: &Node) {
let driver = Arc::new(driver);
DRIVERS.write().push(driver.clone());
BLK_DRIVERS.write().push(driver);
BLK_DRIVERS.write().push(Arc::new(BlockDriver(driver)));
}

@ -1,309 +1,159 @@
use crate::consts::KERNEL_OFFSET;
use crate::drivers::block::*;
use crate::drivers::net::*;
use crate::drivers::{Driver, DRIVERS, NET_DRIVERS};
use crate::memory::active_table;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::sync::Arc;
use core::cmp::Ordering;
use pci::*;
use rcore_memory::{paging::PageTable, PAGE_SIZE};
use spin::Mutex;
use x86_64::instructions::port::Port;
const PCI_VENDOR: u32 = 0x00;
const PCI_DEVICE: u32 = 0x02;
const PCI_COMMAND: u32 = 0x04;
const PCI_STATUS: u32 = 0x06;
const PCI_SUBCLASS: u32 = 0x0a;
const PCI_CLASS: u32 = 0x0b;
const PCI_HEADER: u32 = 0x0e;
const PCI_BAR0: u32 = 0x10; // first
const PCI_BAR5: u32 = 0x24; // last
const PCI_CAP_PTR: u32 = 0x34;
const PCI_INTERRUPT_LINE: u32 = 0x3c;
const PCI_INTERRUPT_PIN: u32 = 0x3d;
const PCI_COMMAND: u16 = 0x04;
const PCI_CAP_PTR: u16 = 0x34;
const PCI_INTERRUPT_LINE: u16 = 0x3c;
const PCI_INTERRUPT_PIN: u16 = 0x3d;
const PCI_MSI_CTRL_CAP: u32 = 0x00;
const PCI_MSI_ADDR: u32 = 0x04;
const PCI_MSI_UPPER_ADDR: u32 = 0x08;
const PCI_MSI_DATA: u32 = 0x0C;
const PCI_MSI_CTRL_CAP: u16 = 0x00;
const PCI_MSI_ADDR: u16 = 0x04;
const PCI_MSI_UPPER_ADDR: u16 = 0x08;
const PCI_MSI_DATA: u16 = 0x0C;
const PCI_CAP_ID_MSI: u32 = 0x05;
const PCI_CAP_ID_MSI: u8 = 0x05;
const PCI_ADDR_PORT: u16 = 0xcf8;
const PCI_DATA_PORT: u16 = 0xcfc;
struct PortOpsImpl;
const PCI_BASE_ADDRESS_SPACE: u32 = 0x01;
const PCI_BASE_ADDRESS_SPACE_IO: u32 = 0x01;
const PCI_BASE_ADDRESS_SPACE_MEMORY: u32 = 0x00;
const PCI_BASE_ADDRESS_MEM_TYPE_MASK: u32 = 0x06;
const PCI_BASE_ADDRESS_MEM_TYPE_32: u32 = 0x00;
const PCI_BASE_ADDRESS_MEM_TYPE_1M: u32 = 0x02;
const PCI_BASE_ADDRESS_MEM_TYPE_64: u32 = 0x04;
const PCI_BASE_ADDRESS_MEM_PREFETCH: u32 = 0x08;
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 PortOps for PortOpsImpl {
unsafe fn read8(&self, port: u16) -> u8 {
Port::new(port).read()
}
}
impl PartialOrd for PciTag {
fn partial_cmp(&self, other: &PciTag) -> Option<Ordering> {
Some(self.cmp(other))
unsafe fn read16(&self, port: u16) -> u16 {
Port::new(port).read()
}
}
impl Eq for PciTag {}
impl PartialEq for PciTag {
fn eq(&self, other: &PciTag) -> bool {
self.0 == other.0
unsafe fn read32(&self, port: u16) -> u32 {
Port::new(port).read()
}
}
impl PciTag {
pub fn new(bus: u32, dev: u32, func: u32) -> PciTag {
assert!(bus < 256);
assert!(dev < 32);
assert!(func < 8);
PciTag(bus << 16 | dev << 11 | func << 8)
unsafe fn write8(&self, port: u16, val: u8) {
Port::new(port).write(val);
}
pub fn bus(&self) -> u32 {
(self.0 >> 16) & 0xFF
unsafe fn write16(&self, port: u16, val: u16) {
Port::new(port).write(val);
}
pub fn dev(&self) -> u32 {
(self.0 >> 11) & 0x1F
unsafe fn write32(&self, port: u16, val: u32) {
Port::new(port).write(val);
}
}
pub fn func(&self) -> u32 {
(self.0 >> 8) & 0x7
}
// biscuit/src/pci/pci.go Pci_read
pub unsafe fn read(&self, reg: u32, width: u32) -> u32 {
// spans in one reg
assert_eq!(reg / 4, (reg + width - 1) / 4);
let enable = 1 << 31;
let rsh = reg % 4;
let r = reg - rsh;
let t = enable | self.0 | r;
let mut pci_addr: Port<u32> = Port::new(PCI_ADDR_PORT);
let mut pci_data: Port<u32> = Port::new(PCI_DATA_PORT);
pci_addr.write(t);
let d = pci_data.read();
pci_addr.write(0);
let ret = d >> (rsh * 8);
let m = if width < 4 {
(1 << (8 * width)) - 1
} else {
0xffffffff
};
return ret & m;
}
pub unsafe fn write(&self, reg: u32, val: u32) {
assert_eq!(reg & 3, 0);
let enable = 1 << 31;
let t = enable | self.0 | reg;
let mut pci_addr: Port<u32> = Port::new(PCI_ADDR_PORT);
let mut pci_data: Port<u32> = Port::new(PCI_DATA_PORT);
pci_addr.write(t);
pci_data.write(val);
pci_addr.write(0);
}
// biscuit/src/pci/pci.go Pci_bar_mem
// linux/drivers/pci/probe.c pci_read_bases
// return (addr, len)
pub unsafe fn get_bar_mem(&self, bar_number: u32) -> Option<(usize, usize)> {
assert!(bar_number <= 4);
let bar = PCI_BAR0 + 4 * bar_number;
let mut base_lo = self.read(bar, 4);
self.write(bar, 0xffffffff);
let mut max_base_lo = self.read(bar, 4);
self.write(bar, base_lo);
let mut base;
let mut max_base;
let mut address_mark;
// memory instead of io
assert!(base_lo & PCI_BASE_ADDRESS_SPACE == PCI_BASE_ADDRESS_SPACE_MEMORY);
match base_lo & PCI_BASE_ADDRESS_MEM_TYPE_MASK {
PCI_BASE_ADDRESS_MEM_TYPE_32 => {
base = (base_lo & PCI_BASE_ADDRESS_MEM_MASK) as usize;
max_base = (max_base_lo & PCI_BASE_ADDRESS_MEM_MASK) as usize;
address_mark = PCI_BASE_ADDRESS_MEM_MASK as usize;
}
PCI_BASE_ADDRESS_MEM_TYPE_64 => {
base = (base_lo & PCI_BASE_ADDRESS_MEM_MASK) as usize;
max_base = (max_base_lo & PCI_BASE_ADDRESS_MEM_MASK) as usize;
let base_hi = self.read(bar + 4, 4);
self.write(bar + 4, 0xffffffff);
let max_base_hi = self.read(bar + 4, 4);
self.write(bar + 4, base_hi);
base |= (base_hi as usize) << 32;
max_base |= (max_base_hi as usize) << 32;
address_mark = !0;
}
_ => unimplemented!("pci bar mem type"),
}
if max_base == 0 {
return None;
}
// linux/drivers/pci/probe.c pci_size
let mut size = max_base & address_mark;
if size == 0 {
return None;
}
size = (size & !(size - 1)) - 1;
debug!(
"device memory address from {:#X} to {:#X}",
base,
base + size
);
return Some((base as usize, size as usize));
}
// returns a tuple of (vid, did, next)
pub fn probe(&self) -> Option<(u32, u32, bool)> {
unsafe {
// To lookup vendor and device, please see https://pci-ids.ucw.cz/read/PC/
let v = self.read(PCI_VENDOR, 2);
if v == 0xffff {
return None;
}
let d = self.read(PCI_DEVICE, 2);
let mf = self.read(PCI_HEADER, 1);
// To lookup class and subclass, please see https://pci-ids.ucw.cz/read/PD/
let cl = self.read(PCI_CLASS, 1);
let scl = self.read(PCI_SUBCLASS, 1);
let line = self.read(PCI_INTERRUPT_LINE, 1);
let pin = self.read(PCI_INTERRUPT_PIN, 1);
info!(
"{:02x}:{:02x}.{}: {:#x} {:#x} ({} {}) irq {}:{}",
self.bus(),
self.dev(),
self.func(),
v,
d,
cl,
scl,
line,
pin
);
return Some((v, d, mf & 0x80 != 0));
}
}
/// Enable the pci tag and its interrupt
/// Return assigned MSI interrupt number when applicable
pub unsafe fn enable(&self) -> Option<u32> {
// 23 and lower are used
static mut MSI_IRQ: u32 = 23;
let orig = self.read(PCI_COMMAND, 2);
// IO Space | MEM Space | Bus Mastering | Special Cycles | PCI Interrupt Disable
self.write(PCI_COMMAND, orig | 0x40f);
// find MSI cap
let mut msi_found = false;
let mut cap_ptr = self.read(PCI_CAP_PTR, 1);
let mut assigned_irq = None;
while cap_ptr > 0 {
let cap_id = self.read(cap_ptr, 1);
if cap_id == PCI_CAP_ID_MSI {
// The manual Volume 3 Chapter 10.11 Message Signalled Interrupts
// 0 is (usually) the apic id of the bsp.
self.write(cap_ptr + PCI_MSI_ADDR, 0xfee00000 | (0 << 12));
MSI_IRQ += 1;
let irq = MSI_IRQ;
assigned_irq = Some(irq);
// we offset all our irq numbers by 32
self.write(cap_ptr + PCI_MSI_DATA, irq + 32);
// 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
);
msi_found = true;
break;
}
debug!(
"PCI device has cap id {} at {:#X}",
self.read(cap_ptr, 1),
cap_ptr
);
cap_ptr = self.read(cap_ptr + 1, 1);
}
if !msi_found {
// Use PCI legacy interrupt instead
// IO Space | MEM Space | Bus Mastering | Special Cycles
self.write(PCI_COMMAND, orig | 0xf);
let line = self.read(PCI_INTERRUPT_LINE, 1);
let pin = self.read(PCI_INTERRUPT_PIN, 1);
/// Enable the pci device and its interrupt
/// Return assigned MSI interrupt number when applicable
unsafe fn enable(loc: Location) -> Option<u32> {
let ops = &PortOpsImpl;
let am = CSpaceAccessMethod::IO;
// 23 and lower are used
static mut MSI_IRQ: u32 = 23;
let orig = am.read16(ops, loc, PCI_COMMAND);
// IO Space | MEM Space | Bus Mastering | Special Cycles | PCI Interrupt Disable
am.write32(ops, loc, PCI_COMMAND, (orig | 0x40f) as u32);
// find MSI cap
let mut msi_found = false;
let mut cap_ptr = am.read8(ops, loc, PCI_CAP_PTR) as u16;
let mut assigned_irq = None;
while cap_ptr > 0 {
let cap_id = am.read8(ops, loc, cap_ptr);
if cap_id == PCI_CAP_ID_MSI {
// The manual Volume 3 Chapter 10.11 Message Signalled Interrupts
// 0 is (usually) the apic id of the bsp.
am.write32(ops, loc, cap_ptr + PCI_MSI_ADDR, 0xfee00000 | (0 << 12));
MSI_IRQ += 1;
let irq = MSI_IRQ;
assigned_irq = Some(irq);
// we offset all our irq numbers by 32
am.write32(ops, loc, cap_ptr + PCI_MSI_DATA, irq + 32);
// enable MSI interrupt, assuming 64bit for now
let orig_ctrl = am.read32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP);
am.write32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
debug!(
"MSI not found, using PCI interrupt line {} pin {}",
line, pin
"MSI control {:#b}, enabling MSI interrupts",
orig_ctrl >> 16
);
msi_found = true;
break;
}
debug!("PCI device has cap id {} at {:#X}", cap_id, cap_ptr);
cap_ptr = am.read8(ops, loc, cap_ptr + 1) as u16;
}
assigned_irq
if !msi_found {
// Use PCI legacy interrupt instead
// IO Space | MEM Space | Bus Mastering | Special Cycles
am.write32(ops, loc, PCI_COMMAND, (orig | 0xf) as u32);
debug!("MSI not found, using PCI interrupt");
}
assigned_irq
}
pub fn init_driver(name: String, vid: u32, did: u32, tag: PciTag) {
if vid == 0x8086 {
if did == 0x100e || did == 0x100f || did == 0x10d3 {
pub fn init_driver(dev: &PCIDevice) {
let name = format!("enp{}s{}f{}", dev.loc.bus, dev.loc.device, dev.loc.function);
match (dev.id.vendor_id, dev.id.device_id) {
(0x8086, 0x100e) | (0x8086, 0x100f) | (0x8086, 0x10d3) => {
// 0x100e
// 82540EM Gigabit Ethernet Controller
// 0x100f
// 82545EM Gigabit Ethernet Controller (Copper)
// 0x10d3
// 82574L Gigabit Network Connection
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
unsafe {
tag.enable();
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
let irq = unsafe { enable(dev.loc) };
let vaddr = KERNEL_OFFSET + addr as usize;
let mut current_addr = addr as usize;
while current_addr < addr as usize + len as usize {
active_table().map_if_not_exists(KERNEL_OFFSET + current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
e1000::e1000_init(addr, len);
e1000::e1000_init(name, irq, vaddr, len as usize);
}
} else if did == 0x10fb {
}
(0x8086, 0x10fb) => {
// 82599ES 10-Gigabit SFI/SFP+ Network Connection
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
let irq = unsafe { tag.enable() };
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[0] {
let irq = unsafe { enable(dev.loc) };
let vaddr = KERNEL_OFFSET + addr as usize;
let mut current_addr = addr as usize;
while current_addr < addr as usize + len as usize {
active_table().map_if_not_exists(KERNEL_OFFSET + current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
PCI_DRIVERS
.lock()
.insert(dev.loc, ixgbe::ixgbe_init(name, irq, vaddr, len as usize));
}
}
(0x8086, 0x2922) => {
// 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[5] {
let irq = unsafe { enable(dev.loc) };
assert!(len as usize <= PAGE_SIZE);
let vaddr = KERNEL_OFFSET + addr as usize;
active_table().map(vaddr, addr as usize);
PCI_DRIVERS
.lock()
.insert(tag, ixgbe::ixgbe_init(name, irq, addr, len));
.insert(dev.loc, ahci::ahci_init(irq, vaddr, len as usize));
}
}
_ => {}
}
}
pub fn detach_driver(tag: &PciTag) -> bool {
match PCI_DRIVERS.lock().remove(tag) {
pub fn detach_driver(loc: &Location) -> bool {
match PCI_DRIVERS.lock().remove(loc) {
Some(driver) => {
DRIVERS
.write()
@ -318,51 +168,44 @@ pub fn detach_driver(tag: &PciTag) -> bool {
}
pub fn init() {
for bus in 0..256 {
for dev in 0..32 {
let tag = PciTag::new(bus, dev, 0);
if let Some((vid, did, next)) = tag.probe() {
let name = format!("enp{}s{}f0", bus, dev);
init_driver(name, vid, did, tag);
if next {
for func in 1..8 {
let tag = PciTag::new(bus, dev, func);
if let Some((vid, did, _)) = tag.probe() {
let name = format!("enp{}s{}f{}", bus, dev, func);
init_driver(name, vid, did, tag);
}
}
}
}
}
let mut pci_iter = unsafe { scan_bus(&PortOpsImpl, CSpaceAccessMethod::IO) };
for dev in pci_iter {
info!(
"pci: {:02x}:{:02x}.{} {:#x} {:#x} ({} {}) irq: {}:{:?}",
dev.loc.bus,
dev.loc.device,
dev.loc.function,
dev.id.vendor_id,
dev.id.device_id,
dev.id.class,
dev.id.subclass,
dev.pic_interrupt_line,
dev.interrupt_pin,
);
init_driver(&dev);
}
}
pub fn find_device(vendor: u32, product: u32) -> Option<PciTag> {
for bus in 0..256 {
for dev in 0..32 {
let tag = PciTag::new(bus, dev, 0);
if let Some((vid, did, next)) = tag.probe() {
if vid == vendor && did == product {
return Some(tag);
}
if next {
for func in 1..8 {
let tag = PciTag::new(bus, dev, func);
if let Some((vid, did, _)) = tag.probe() {
if vid == vendor && did == product {
return Some(tag);
}
}
}
}
}
pub fn find_device(vendor: u16, product: u16) -> Option<Location> {
let mut pci_iter = unsafe { scan_bus(&PortOpsImpl, CSpaceAccessMethod::IO) };
for dev in pci_iter {
if dev.id.vendor_id == vendor && dev.id.device_id == product {
return Some(dev.loc);
}
}
None
}
pub fn get_bar0_mem(loc: Location) -> Option<(usize, usize)> {
unsafe { probe_function(&PortOpsImpl, loc, CSpaceAccessMethod::IO) }
.and_then(|dev| dev.bars[0])
.map(|bar| match bar {
BAR::Memory(addr, len, _, _) => (addr as usize, len as usize),
_ => unimplemented!(),
})
}
lazy_static! {
pub static ref PCI_DRIVERS: Arc<Mutex<BTreeMap<PciTag, Arc<Driver>>>> =
Arc::new(Mutex::new(BTreeMap::new()));
pub static ref PCI_DRIVERS: Mutex<BTreeMap<Location, Arc<Driver>>> =
Mutex::new(BTreeMap::new());
}

@ -1,6 +1,8 @@
use alloc::prelude::*;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec;
use alloc::vec::Vec;
use core::fmt;
use core::mem::size_of;
use core::mem::transmute_copy;

@ -1,12 +1,13 @@
use alloc::prelude::*;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use lazy_static::lazy_static;
use smoltcp::wire::{EthernetAddress, Ipv4Address};
use spin::RwLock;
use self::block::virtio_blk::VirtIOBlkDriver;
use crate::sync::Condvar;
use rcore_fs::dev::BlockDevice;
#[allow(dead_code)]
pub mod block;
@ -64,13 +65,35 @@ pub trait Driver: Send + Sync {
fn poll(&self) {
unimplemented!("not a net driver")
}
// block related drivers should implement these
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool {
unimplemented!("not a block driver")
}
fn write_block(&self, block_id: usize, buf: &[u8]) -> bool {
unimplemented!("not a block 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<Driver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<VirtIOBlkDriver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<BlockDriver>>> = RwLock::new(Vec::new());
}
pub struct BlockDriver(Arc<Driver>);
impl BlockDevice for BlockDriver {
const BLOCK_SIZE_LOG2: u8 = 9; // 512
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> bool {
self.0.read_block(block_id, buf)
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> bool {
self.0.write_block(block_id, buf)
}
}
lazy_static! {

@ -3,8 +3,9 @@
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::format;
use alloc::prelude::*;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::mem::size_of;
use core::slice;
use core::sync::atomic::{fence, Ordering};
@ -72,20 +73,19 @@ const E1000_RAH: usize = 0x5404 / 4;
pub struct E1000Interface {
iface: Mutex<EthernetInterface<'static, 'static, 'static, E1000Driver>>,
driver: E1000Driver,
name: String,
irq: Option<u32>,
}
impl Driver for E1000Interface {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let irq = {
let driver = self.driver.0.lock();
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool {
if irq.is_some() && self.irq.is_some() && irq != self.irq {
// not ours, skip it
return false;
}
if let None = active_table().get_entry(driver.header) {
let mut current_addr = driver.header;
while current_addr < driver.header + driver.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let data = {
let driver = self.driver.0.lock();
let e1000 = unsafe {
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
@ -101,7 +101,7 @@ impl Driver for E1000Interface {
}
};
if irq {
if data {
let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64);
let mut sockets = SOCKETS.lock();
match self.iface.lock().poll(&mut sockets, timestamp) {
@ -114,7 +114,7 @@ impl Driver for E1000Interface {
}
}
return irq;
return data;
}
fn device_type(&self) -> DeviceType {
@ -130,7 +130,7 @@ impl Driver for E1000Interface {
}
fn get_ifname(&self) -> String {
format!("e1000")
self.name.clone()
}
fn ipv4_address(&self) -> Option<Ipv4Address> {
@ -184,14 +184,6 @@ impl<'a> phy::Device<'a> for E1000Driver {
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
let driver = self.0.lock();
if let None = active_table().get_entry(driver.header) {
let mut current_addr = driver.header;
while current_addr < driver.header + driver.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let e1000 = unsafe {
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
};
@ -237,14 +229,6 @@ impl<'a> phy::Device<'a> for E1000Driver {
fn transmit(&'a mut self) -> Option<Self::TxToken> {
let driver = self.0.lock();
if let None = active_table().get_entry(driver.header) {
let mut current_addr = driver.header;
while current_addr < driver.header + driver.size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let e1000 = unsafe {
slice::from_raw_parts_mut(driver.header as *mut Volatile<u32>, driver.size / 4)
};
@ -353,8 +337,8 @@ bitflags! {
}
// JudgeDuck-OS/kern/e1000.c
pub fn e1000_init(header: usize, size: usize) {
info!("Probing e1000");
pub fn e1000_init(name: String, irq: Option<u32>, header: usize, size: usize) {
info!("Probing e1000 {}", name);
assert_eq!(size_of::<E1000SendDesc>(), 16);
assert_eq!(size_of::<E1000RecvDesc>(), 16);
@ -386,12 +370,6 @@ pub fn e1000_init(header: usize, size: usize) {
first_trans: true,
};
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
let e1000 = unsafe { slice::from_raw_parts_mut(header as *mut Volatile<u32>, size / 4) };
debug!(
"status before setup: {:#?}",
@ -501,6 +479,8 @@ pub fn e1000_init(header: usize, size: usize) {
let e1000_iface = E1000Interface {
iface: Mutex::new(iface),
driver: net_driver.clone(),
name,
irq,
};
let driver = Arc::new(e1000_iface);

@ -1,8 +1,9 @@
//! 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::prelude::*;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use alloc::collections::BTreeMap;
use isomorphic_drivers::net::ethernet::intel::ixgbe;
@ -20,7 +21,6 @@ use crate::memory::active_table;
use crate::net::SOCKETS;
use crate::sync::FlagsGuard;
use crate::sync::SpinNoIrqLock as Mutex;
use crate::sync::{MutexGuard, SpinNoIrq};
use super::super::{provider::Provider, DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
@ -32,21 +32,6 @@ struct IXGBEDriver {
mtu: usize,
}
impl Drop for IXGBEDriver {
fn drop(&mut self) {
let _ = FlagsGuard::no_irq_region();
let header = self.header;
let size = self.size;
if let None = active_table().get_entry(header) {
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
}
}
pub struct IXGBEInterface {
iface: Mutex<EthernetInterface<'static, 'static, 'static, IXGBEDriver>>,
driver: IXGBEDriver,
@ -64,16 +49,6 @@ impl Driver for IXGBEInterface {
let handled = {
let _ = FlagsGuard::no_irq_region();
let header = self.driver.header;
let size = self.driver.size;
if let None = active_table().get_entry(header) {
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
self.driver.inner.try_handle_interrupt()
};
@ -135,15 +110,6 @@ impl<'a> phy::Device<'a> for IXGBEDriver {
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
let _ = FlagsGuard::no_irq_region();
let header = self.header;
let size = self.size;
if let None = active_table().get_entry(header) {
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
if self.inner.can_send() {
if let Some(data) = self.inner.recv() {
Some((IXGBERxToken(data), IXGBETxToken(self.clone())))
@ -157,15 +123,6 @@ impl<'a> phy::Device<'a> for IXGBEDriver {
fn transmit(&'a mut self) -> Option<Self::TxToken> {
let _ = FlagsGuard::no_irq_region();
let header = self.header;
let size = self.size;
if let None = active_table().get_entry(header) {
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
if self.inner.can_send() {
Some(IXGBETxToken(self.clone()))
} else {
@ -200,15 +157,6 @@ impl phy::TxToken for IXGBETxToken {
F: FnOnce(&mut [u8]) -> Result<R>,
{
let _ = FlagsGuard::no_irq_region();
let header = self.0.header;
let size = self.0.size;
if let None = active_table().get_entry(header) {
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let mut buffer = [0u8; ixgbe::IXGBEDriver::get_mtu()];
let result = f(&mut buffer[..len]);
if result.is_ok() {
@ -225,13 +173,6 @@ pub fn ixgbe_init(
size: usize,
) -> Arc<IXGBEInterface> {
let _ = FlagsGuard::no_irq_region();
if let None = active_table().get_entry(header) {
let mut current_addr = header;
while current_addr < header + size {
active_table().map_if_not_exists(current_addr, current_addr);
current_addr = current_addr + PAGE_SIZE;
}
}
let ixgbe = ixgbe::IXGBEDriver::init(Provider::new(), header, size);
ixgbe.enable_irq();

@ -1,7 +1,8 @@
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::format;
use alloc::prelude::*;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::mem::size_of;
use core::slice;

@ -37,15 +37,15 @@ lazy_static! {
pub static ref ROOT_INODE: Arc<INode> = {
#[cfg(not(feature = "link_user"))]
let device = {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "x86_64"))]
{
crate::drivers::BLK_DRIVERS.read().iter()
.next().expect("VirtIOBlk not found")
.next().expect("Block device not found")
.clone()
}
#[cfg(target_arch = "x86_64")]
#[cfg(target_arch = "aarch64")]
{
Arc::new(ide::IDE::new(1))
unimplemented!()
}
};
#[cfg(feature = "link_user")]

@ -13,13 +13,13 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
vendor, product
);
let tag = pci::find_device(vendor as u32, product as u32).ok_or(SysError::ENOENT)?;
let tag = pci::find_device(vendor as u16, product as u16).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)?;
let (base, len) = pci::get_bar0_mem(tag).ok_or(SysError::ENOENT)?;
let mut proc = process();
let virt_addr = proc.vm.find_free_area(0, len);

@ -1,8 +1,8 @@
use super::*;
use crate::arch::cpu;
use crate::consts::USER_STACK_SIZE;
use core::mem::size_of;
use core::sync::atomic::{AtomicI32, Ordering};
use crate::consts::USER_STACK_SIZE;
pub fn sys_arch_prctl(code: i32, addr: usize, tf: &mut TrapFrame) -> SysResult {
const ARCH_SET_FS: i32 = 0x1002;
@ -177,7 +177,7 @@ pub fn sys_prlimit64(
}
}
Ok(0)
},
}
RLIMIT_RSS | RLIMIT_AS => {
if !old_limit.is_null() {
proc.vm.check_write_ptr(old_limit)?;

@ -1 +1 @@
Subproject commit 69febc9fcc64df60329687b4f24b9b5309c99adf
Subproject commit b1e7a2d07e81ce5035a1cc25b0ade9367aee1a94
Loading…
Cancel
Save