Implement reading pci memory address

toolchain_update
Jiajie Chen 6 years ago
parent 197bebb1d2
commit dd61ce30ba

@ -1,5 +1,6 @@
use x86_64::instructions::port::Port;
use crate::logging::*;
use core::slice;
const VENDOR: u32 = 0x00;
const DEVICE: u32 = 0x02;
@ -7,10 +8,22 @@ const STATUS: u32 = 0x06;
const SUBCLASS: u32 = 0x0a;
const CLASS: u32 = 0x0b;
const HEADER: u32 = 0x0e;
const BAR0: u32 = 0x10;
const PCI_ADDR_PORT: u16 = 0xcf8;
const PCI_DATA_PORT: u16 = 0xcfc;
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;
struct PciTag(u32);
impl PciTag {
@ -30,7 +43,7 @@ impl PciTag {
(self.0 >> 8) & 0x7
}
// biscuit/src/pci/pci.go
// 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);
@ -48,7 +61,12 @@ impl PciTag {
pci_addr.write(0);
let ret = d >> (rsh * 8);
let m = (1 << (8 * width)) - 1;
let m = if (width < 4) {
(1 << (8 * width)) - 1
} else {
0xffffffff
};
return ret & m;
}
@ -66,6 +84,39 @@ impl PciTag {
pci_addr.write(0);
}
// biscuit/src/pci/pci.go Pci_bar_mem
// linux/drivers/pci/probe.c pci_read_bases
pub unsafe fn getBarMem(&self, bar_number: u32) -> Option<&'static mut [u8]> {
assert!(bar_number <= 4);
let bar = BAR0 + 4 * bar_number;
let mut base = self.read(bar, 4);
self.write(bar, 0xffffffff);
let mut max_base = self.read(bar, 4);
self.write(bar, base);
// memory instead of io
assert!(base & PCI_BASE_ADDRESS_SPACE == PCI_BASE_ADDRESS_SPACE_MEMORY);
// only support 32bit addr for now
assert!(base & PCI_BASE_ADDRESS_MEM_TYPE_MASK == PCI_BASE_ADDRESS_MEM_TYPE_32);
base = base & PCI_BASE_ADDRESS_MEM_MASK;
max_base = max_base & PCI_BASE_ADDRESS_MEM_MASK;
if (max_base == 0) {
return None;
}
// linux/drivers/pci/probe.c pci_size
let mut size = PCI_BASE_ADDRESS_MEM_MASK & max_base;
if (size == 0) {
return None;
}
size = (size & !(size - 1)) - 1;
debug!("device memory address from {:#X} to {:#X}", base, base + size);
return Some(slice::from_raw_parts_mut(base as *mut u8, size as usize));
}
pub fn describe(&self) -> bool {
unsafe {
let v = self.read(VENDOR, 2);
@ -77,6 +128,7 @@ impl PciTag {
let cl = self.read(CLASS, 1);
let scl = self.read(SUBCLASS, 1);
info!("{}: {}: {}: {:#X} {:#X} ({} {})", self.bus(), self.dev(), self.func(), v, d, cl, scl);
self.getBarMem(0);
return mf & 0x80 != 0;
}
}

@ -165,7 +165,7 @@ impl VirtIOVirtqueue {
// write barrier
fence(Ordering::SeqCst);
self.avail_idx += 1;
self.avail_idx = self.avail_idx.wrapping_add(1);
avail.idx.write(self.avail_idx);
self.desc_state[head] = user_data;
return true;
@ -227,7 +227,7 @@ impl VirtIOVirtqueue {
}
self.free_head = index;
self.last_used_idx += 1;
self.last_used_idx = self.last_used_idx.wrapping_add(1);
Some((input, output, len as usize, user_data))
}

@ -16,5 +16,6 @@
},
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float",
"panic-strategy": "abort"
"panic-strategy": "abort",
"eliminate-frame-pointer": false
}

Loading…
Cancel
Save