Calculate and use PCI BAR memory sizes in most drivers.

This commit is contained in:
Jeremy Soller
2019-09-04 20:38:08 -06:00
parent a1144552d5
commit eda6bc6f92
8 changed files with 80 additions and 27 deletions
+8 -2
View File
@@ -23,14 +23,20 @@ fn main() {
let bar_str = args.next().expect("ahcid: no address provided");
let bar = usize::from_str_radix(&bar_str, 16).expect("ahcid: failed to parse address");
let bar_size_str = args.next().expect("ahcid: no address size provided");
let bar_size = usize::from_str_radix(&bar_str, 16).expect("ahcid: failed to parse address size");
let irq_str = args.next().expect("ahcid: no irq provided");
let irq = irq_str.parse::<u8>().expect("ahcid: failed to parse irq");
print!("{}", format!(" + AHCI {} on: {:X} IRQ: {}\n", name, bar, irq));
print!("{}", format!(" + AHCI {} on: {:X} size: {} IRQ: {}\n", name, bar, bar_size, irq));
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
let address = unsafe { syscall::physmap(bar, 4096, PHYSMAP_WRITE | PHYSMAP_NO_CACHE).expect("ahcid: failed to map address") };
let address = unsafe {
syscall::physmap(bar, bar_size, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
.expect("ahcid: failed to map address")
};
{
let scheme_name = format!("disk/{}", name);
let socket_fd = syscall::open(
+1 -2
View File
@@ -2,5 +2,4 @@
name = "E1000 NIC"
class = 2
ids = { 0x8086 = [0x1004, 0x100e, 0x100f, 0x1503] }
command = ["e1000d", "$NAME", "$BAR0", "$IRQ"]
command = ["e1000d", "$NAME", "$BAR0", "$BARSIZE0", "$IRQ"]
+5 -2
View File
@@ -68,10 +68,13 @@ fn main() {
let bar_str = args.next().expect("e1000d: no address provided");
let bar = usize::from_str_radix(&bar_str, 16).expect("e1000d: failed to parse address");
let bar_size_str = args.next().expect("e1000d: no address size provided");
let bar_size = usize::from_str_radix(&bar_str, 16).expect("e1000d: failed to parse address size");
let irq_str = args.next().expect("e1000d: no irq provided");
let irq = irq_str.parse::<u8>().expect("e1000d: failed to parse irq");
println!(" + E1000 {} on: {:X} IRQ: {}", name, bar, irq);
println!(" + E1000 {} on: {:X} size: {} IRQ: {}", name, bar, bar_size, irq);
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
@@ -91,7 +94,7 @@ fn main() {
let mut irq_file = unsafe { File::from_raw_fd(irq_fd as RawFd) };
let address = unsafe {
syscall::physmap(bar, 128 * 1024, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
syscall::physmap(bar, bar_size, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
.expect("e1000d: failed to map address")
};
{
+2 -2
View File
@@ -5,7 +5,7 @@
name = "AHCI storage"
class = 1
subclass = 6
command = ["ahcid", "$NAME", "$BAR5", "$IRQ"]
command = ["ahcid", "$NAME", "$BAR5", "$BARSIZE5", "$IRQ"]
# bgad
[[drivers]]
@@ -27,7 +27,7 @@ command = ["bgad", "$NAME", "$BAR0"]
name = "NVME storage"
class = 1
subclass = 8
command = ["nvmed", "$NAME", "$BAR0", "$IRQ"]
command = ["nvmed", "$NAME", "$BAR0", "$BARSIZE0", "$IRQ"]
# vboxd
[[drivers]]
+8 -3
View File
@@ -26,15 +26,20 @@ fn main() {
let bar_str = args.next().expect("nvmed: no address provided");
let bar = usize::from_str_radix(&bar_str, 16).expect("nvmed: failed to parse address");
let bar_size_str = args.next().expect("nvmed: no address size provided");
let bar_size = usize::from_str_radix(&bar_str, 16).expect("nvmed: failed to parse address size");
let irq_str = args.next().expect("nvmed: no irq provided");
let irq = irq_str.parse::<u8>().expect("nvmed: failed to parse irq");
print!("{}", format!(" + NVME {} on: {:X} IRQ: {}\n", name, bar, irq));
print!("{}", format!(" + NVME {} on: {:X} size: {} IRQ: {}\n", name, bar, bar_size, irq));
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
//TODO: Figure out correct size of mapping, not just 256 * 1024
let address = unsafe { syscall::physmap(bar, 256 * 1024, PHYSMAP_WRITE | PHYSMAP_NO_CACHE).expect("nvmed: failed to map address") };
let address = unsafe {
syscall::physmap(bar, bar_size, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
.expect("nvmed: failed to map address")
};
{
let event_fd = syscall::open("event:", syscall::O_RDWR | syscall::O_CLOEXEC)
.expect("nvmed: failed to open event queue");
+50 -12
View File
@@ -13,7 +13,7 @@ use std::process::Command;
use syscall::iopl;
use crate::config::Config;
use crate::pci::{Pci, PciClass, PciHeader, PciHeaderError, PciHeaderType};
use crate::pci::{Pci, PciBar, PciClass, PciHeader, PciHeaderError, PciHeaderType};
mod config;
mod pci;
@@ -82,7 +82,7 @@ fn handle_parsed_header(config: &Config, pci: &Pci, bus_num: u8,
if let Some(ref ids) = driver.ids {
let mut device_found = false;
for (vendor, devices) in ids {
let vendor_without_prefix = vendor.trim_left_matches("0x");
let vendor_without_prefix = vendor.trim_start_matches("0x");
let vendor = i64::from_str_radix(vendor_without_prefix, 16).unwrap() as u16;
if vendor != header.vendor_id() { continue; }
@@ -130,6 +130,42 @@ fn handle_parsed_header(config: &Config, pci: &Pci, bus_num: u8,
pci.write(bus_num, dev_num, func_num, 0x3C, data);
}
// Find BAR sizes
let mut bars = [PciBar::None; 6];
let mut bar_sizes = [0; 6];
unsafe {
let count = match header.header_type() {
PciHeaderType::GENERAL => 6,
PciHeaderType::PCITOPCI => 2,
_ => 0,
};
for i in 0..count {
bars[i] = header.get_bar(i);
let offset = 0x10 + (i as u8) * 4;
let original = pci.read(bus_num, dev_num, func_num, offset);
pci.write(bus_num, dev_num, func_num, offset, 0xFFFFFFFF);
let new = pci.read(bus_num, dev_num, func_num, offset);
pci.write(bus_num, dev_num, func_num, offset, original);
let masked = if new & 1 == 1 {
new & 0xFFFFFFFC
} else {
new & 0xFFFFFFF0
};
let size = !masked + 1;
bar_sizes[i] = if size <= 1 {
0
} else {
size
};
}
}
// TODO: find a better way to pass the header data down to the
// device driver, making passing the capabilities list etc
// posible.
@@ -142,16 +178,18 @@ fn handle_parsed_header(config: &Config, pci: &Pci, bus_num: u8,
"$DEV" => format!("{:>02X}", dev_num),
"$FUNC" => format!("{:>02X}", func_num),
"$NAME" => format!("pci-{:>02X}.{:>02X}.{:>02X}", bus_num, dev_num, func_num),
"$BAR0" => format!("{}", header.get_bar(0)),
"$BAR1" => format!("{}", header.get_bar(1)),
"$BAR2" if header.header_type() == PciHeaderType::GENERAL =>
format!("{}", header.get_bar(2)),
"$BAR3" if header.header_type() == PciHeaderType::GENERAL =>
format!("{}", header.get_bar(3)),
"$BAR4" if header.header_type() == PciHeaderType::GENERAL =>
format!("{}", header.get_bar(4)),
"$BAR5" if header.header_type() == PciHeaderType::GENERAL =>
format!("{}", header.get_bar(5)),
"$BAR0" => format!("{}", bars[0]),
"$BAR1" => format!("{}", bars[1]),
"$BAR2" => format!("{}", bars[2]),
"$BAR3" => format!("{}", bars[3]),
"$BAR4" => format!("{}", bars[4]),
"$BAR5" => format!("{}", bars[5]),
"$BARSIZE0" => format!("{:>08X}", bar_sizes[0]),
"$BARSIZE1" => format!("{:>08X}", bar_sizes[1]),
"$BARSIZE2" => format!("{:>08X}", bar_sizes[2]),
"$BARSIZE3" => format!("{:>08X}", bar_sizes[3]),
"$BARSIZE4" => format!("{:>08X}", bar_sizes[4]),
"$BARSIZE5" => format!("{:>08X}", bar_sizes[5]),
"$IRQ" => format!("{}", irq),
"$VENID" => format!("{:>04X}", header.vendor_id()),
"$DEVID" => format!("{:>04X}", header.device_id()),
+1 -2
View File
@@ -2,5 +2,4 @@
name = "RTL8168 NIC"
class = 2
ids = { 0x10ec = [0x8168] }
command = ["rtl8168d", "$NAME", "$BAR2", "$IRQ"]
command = ["rtl8168d", "$NAME", "$BAR2", "$BARSIZE2", "$IRQ"]
+5 -2
View File
@@ -68,10 +68,13 @@ fn main() {
let bar_str = args.next().expect("rtl8168d: no address provided");
let bar = usize::from_str_radix(&bar_str, 16).expect("rtl8168d: failed to parse address");
let bar_size_str = args.next().expect("rtl8168d: no address size provided");
let bar_size = usize::from_str_radix(&bar_str, 16).expect("rtl8168d: failed to parse address size");
let irq_str = args.next().expect("rtl8168d: no irq provided");
let irq = irq_str.parse::<u8>().expect("rtl8168d: failed to parse irq");
println!(" + RTL8168 {} on: {:X}, IRQ: {}", name, bar, irq);
println!(" + RTL8168 {} on: {:X} size: {} IRQ: {}", name, bar, bar_size, irq);
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
@@ -91,7 +94,7 @@ fn main() {
let mut irq_file = unsafe { File::from_raw_fd(irq_fd as RawFd) };
let address = unsafe {
syscall::physmap(bar, 256, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
syscall::physmap(bar, bar_size, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
.expect("rtl8168d: failed to map address")
};
{