PCI driver WIP
This commit is contained in:
parent
f05cc96db1
commit
c9a4b3882c
16 changed files with 400 additions and 7 deletions
6
drivers/pcid/Cargo.toml
Normal file
6
drivers/pcid/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "pcid"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies.syscall]
|
||||
path = "../../syscall/"
|
73
drivers/pcid/src/main.rs
Normal file
73
drivers/pcid/src/main.rs
Normal file
|
@ -0,0 +1,73 @@
|
|||
#![feature(asm)]
|
||||
|
||||
extern crate syscall;
|
||||
|
||||
use syscall::iopl;
|
||||
|
||||
use pci::{Pci, PciBar, PciClass};
|
||||
|
||||
mod pci;
|
||||
|
||||
fn enumerate_pci() {
|
||||
println!("PCI BS/DV/FN VEND:DEVI CL.SC.IN.RV");
|
||||
|
||||
let pci = Pci::new();
|
||||
for bus in pci.buses() {
|
||||
for dev in bus.devs() {
|
||||
for func in dev.funcs() {
|
||||
if let Some(header) = func.header() {
|
||||
println!("PCI {:>02X}/{:>02X}/{:>02X} {:>04X}:{:>04X} {:>02X}.{:>02X}.{:>02X}.{:>02X} {:?}",
|
||||
bus.num, dev.num, func.num,
|
||||
header.vendor_id, header.device_id,
|
||||
header.class, header.subclass, header.interface, header.revision,
|
||||
PciClass::from(header.class));
|
||||
|
||||
for i in 0..header.bars.len() {
|
||||
match PciBar::from(header.bars[i]) {
|
||||
PciBar::None => (),
|
||||
PciBar::Memory(address) => println!(" BAR {} {:>08X}", i, address),
|
||||
PciBar::Port(address) => println!(" BAR {} {:>04X}", i, address)
|
||||
}
|
||||
}
|
||||
|
||||
match PciClass::from(header.class) {
|
||||
PciClass::Storage => match header.subclass {
|
||||
0x01 => {
|
||||
println!(" + IDE");
|
||||
},
|
||||
0x06 => {
|
||||
println!(" + SATA");
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
PciClass::SerialBus => match header.subclass {
|
||||
0x03 => match header.interface {
|
||||
0x00 => {
|
||||
println!(" + UHCI");
|
||||
},
|
||||
0x10 => {
|
||||
println!(" + OHCI");
|
||||
},
|
||||
0x20 => {
|
||||
println!(" + EHCI");
|
||||
},
|
||||
0x30 => {
|
||||
println!(" + XHCI");
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe { iopl(3).unwrap() };
|
||||
|
||||
enumerate_pci();
|
||||
}
|
18
drivers/pcid/src/pci/bar.rs
Normal file
18
drivers/pcid/src/pci/bar.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
#[derive(Debug)]
|
||||
pub enum PciBar {
|
||||
None,
|
||||
Memory(u32),
|
||||
Port(u16)
|
||||
}
|
||||
|
||||
impl From<u32> for PciBar {
|
||||
fn from(bar: u32) -> Self {
|
||||
if bar & 0xFFFFFFFC == 0 {
|
||||
PciBar::None
|
||||
} else if bar & 1 == 0 {
|
||||
PciBar::Memory(bar & 0xFFFFFFF0)
|
||||
} else {
|
||||
PciBar::Port((bar & 0xFFFC) as u16)
|
||||
}
|
||||
}
|
||||
}
|
46
drivers/pcid/src/pci/bus.rs
Normal file
46
drivers/pcid/src/pci/bus.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use super::{Pci, PciDev};
|
||||
|
||||
pub struct PciBus<'pci> {
|
||||
pub pci: &'pci Pci,
|
||||
pub num: u8
|
||||
}
|
||||
|
||||
impl<'pci> PciBus<'pci> {
|
||||
pub fn devs(&'pci self) -> PciBusIter<'pci> {
|
||||
PciBusIter::new(self)
|
||||
}
|
||||
|
||||
pub unsafe fn read(&self, dev: u8, func: u8, offset: u8) -> u32 {
|
||||
self.pci.read(self.num, dev, func, offset)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PciBusIter<'pci> {
|
||||
bus: &'pci PciBus<'pci>,
|
||||
num: u32
|
||||
}
|
||||
|
||||
impl<'pci> PciBusIter<'pci> {
|
||||
pub fn new(bus: &'pci PciBus<'pci>) -> Self {
|
||||
PciBusIter {
|
||||
bus: bus,
|
||||
num: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'pci> Iterator for PciBusIter<'pci> {
|
||||
type Item = PciDev<'pci>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.num < 32 {
|
||||
let dev = PciDev {
|
||||
bus: self.bus,
|
||||
num: self.num as u8
|
||||
};
|
||||
self.num += 1;
|
||||
Some(dev)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
50
drivers/pcid/src/pci/class.rs
Normal file
50
drivers/pcid/src/pci/class.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
#[derive(Debug)]
|
||||
pub enum PciClass {
|
||||
Legacy,
|
||||
Storage,
|
||||
Network,
|
||||
Display,
|
||||
Multimedia,
|
||||
Memory,
|
||||
Bridge,
|
||||
SimpleComms,
|
||||
Peripheral,
|
||||
Input,
|
||||
Docking,
|
||||
Processor,
|
||||
SerialBus,
|
||||
Wireless,
|
||||
IntelligentIo,
|
||||
SatelliteComms,
|
||||
Cryptography,
|
||||
SignalProc,
|
||||
Reserved(u8),
|
||||
Unknown
|
||||
}
|
||||
|
||||
impl From<u8> for PciClass {
|
||||
fn from(class: u8) -> PciClass {
|
||||
match class {
|
||||
0x00 => PciClass::Legacy,
|
||||
0x01 => PciClass::Storage,
|
||||
0x02 => PciClass::Network,
|
||||
0x03 => PciClass::Display,
|
||||
0x04 => PciClass::Multimedia,
|
||||
0x05 => PciClass::Memory,
|
||||
0x06 => PciClass::Bridge,
|
||||
0x07 => PciClass::SimpleComms,
|
||||
0x08 => PciClass::Peripheral,
|
||||
0x09 => PciClass::Input,
|
||||
0x0A => PciClass::Docking,
|
||||
0x0B => PciClass::Processor,
|
||||
0x0C => PciClass::SerialBus,
|
||||
0x0D => PciClass::Wireless,
|
||||
0x0E => PciClass::IntelligentIo,
|
||||
0x0F => PciClass::SatelliteComms,
|
||||
0x10 => PciClass::Cryptography,
|
||||
0x11 => PciClass::SignalProc,
|
||||
0xFF => PciClass::Unknown,
|
||||
reserved => PciClass::Reserved(reserved)
|
||||
}
|
||||
}
|
||||
}
|
46
drivers/pcid/src/pci/dev.rs
Normal file
46
drivers/pcid/src/pci/dev.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use super::{PciBus, PciFunc};
|
||||
|
||||
pub struct PciDev<'pci> {
|
||||
pub bus: &'pci PciBus<'pci>,
|
||||
pub num: u8
|
||||
}
|
||||
|
||||
impl<'pci> PciDev<'pci> {
|
||||
pub fn funcs(&'pci self) -> PciDevIter<'pci> {
|
||||
PciDevIter::new(self)
|
||||
}
|
||||
|
||||
pub unsafe fn read(&self, func: u8, offset: u8) -> u32 {
|
||||
self.bus.read(self.num, func, offset)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PciDevIter<'pci> {
|
||||
dev: &'pci PciDev<'pci>,
|
||||
num: u32
|
||||
}
|
||||
|
||||
impl<'pci> PciDevIter<'pci> {
|
||||
pub fn new(dev: &'pci PciDev<'pci>) -> Self {
|
||||
PciDevIter {
|
||||
dev: dev,
|
||||
num: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'pci> Iterator for PciDevIter<'pci> {
|
||||
type Item = PciFunc<'pci>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.num < 8 {
|
||||
let func = PciFunc {
|
||||
dev: self.dev,
|
||||
num: self.num as u8
|
||||
};
|
||||
self.num += 1;
|
||||
Some(func)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
30
drivers/pcid/src/pci/func.rs
Normal file
30
drivers/pcid/src/pci/func.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use std::ops::DerefMut;
|
||||
|
||||
use super::{PciDev, PciHeader};
|
||||
|
||||
pub struct PciFunc<'pci> {
|
||||
pub dev: &'pci PciDev<'pci>,
|
||||
pub num: u8
|
||||
}
|
||||
|
||||
impl<'pci> PciFunc<'pci> {
|
||||
pub fn header(&self) -> Option<PciHeader> {
|
||||
if unsafe { self.read(0) } != 0xFFFFFFFF {
|
||||
let mut header = PciHeader::default();
|
||||
{
|
||||
let dwords = header.deref_mut();
|
||||
dwords.iter_mut().fold(0usize, |offset, dword| {
|
||||
*dword = unsafe { self.read(offset as u8) };
|
||||
offset + 4
|
||||
});
|
||||
}
|
||||
Some(header)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn read(&self, offset: u8) -> u32 {
|
||||
self.dev.read(self.num, offset)
|
||||
}
|
||||
}
|
43
drivers/pcid/src/pci/header.rs
Normal file
43
drivers/pcid/src/pci/header.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::{slice, mem};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[repr(packed)]
|
||||
pub struct PciHeader {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: u16,
|
||||
pub status: u16,
|
||||
pub revision: u8,
|
||||
pub interface: u8,
|
||||
pub subclass: u8,
|
||||
pub class: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub latency_timer: u8,
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
pub bars: [u32; 6],
|
||||
pub cardbus_cis_ptr: u32,
|
||||
pub subsystem_vendor_id: u16,
|
||||
pub subsystem_id: u16,
|
||||
pub expansion_rom_bar: u32,
|
||||
pub capabilities: u8,
|
||||
pub reserved: [u8; 7],
|
||||
pub interrupt_line: u8,
|
||||
pub interrupt_pin: u8,
|
||||
pub min_grant: u8,
|
||||
pub max_latency: u8
|
||||
}
|
||||
|
||||
impl Deref for PciHeader {
|
||||
type Target = [u32];
|
||||
fn deref(&self) -> &[u32] {
|
||||
unsafe { slice::from_raw_parts(self as *const PciHeader as *const u32, mem::size_of::<PciHeader>()/4) as &[u32] }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PciHeader {
|
||||
fn deref_mut(&mut self) -> &mut [u32] {
|
||||
unsafe { slice::from_raw_parts_mut(self as *mut PciHeader as *mut u32, mem::size_of::<PciHeader>()/4) as &mut [u32] }
|
||||
}
|
||||
}
|
67
drivers/pcid/src/pci/mod.rs
Normal file
67
drivers/pcid/src/pci/mod.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
pub use self::bar::PciBar;
|
||||
pub use self::bus::{PciBus, PciBusIter};
|
||||
pub use self::class::PciClass;
|
||||
pub use self::dev::{PciDev, PciDevIter};
|
||||
pub use self::func::PciFunc;
|
||||
pub use self::header::PciHeader;
|
||||
|
||||
mod bar;
|
||||
mod bus;
|
||||
mod class;
|
||||
mod dev;
|
||||
mod func;
|
||||
mod header;
|
||||
|
||||
pub struct Pci;
|
||||
|
||||
impl Pci {
|
||||
pub fn new() -> Self {
|
||||
Pci
|
||||
}
|
||||
|
||||
pub fn buses<'pci>(&'pci self) -> PciIter<'pci> {
|
||||
PciIter::new(self)
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub unsafe fn read(&self, bus: u8, dev: u8, func: u8, offset: u8) -> u32 {
|
||||
let address = 0x80000000 | ((bus as u32) << 16) | ((dev as u32) << 11) | ((func as u32) << 8) | ((offset as u32) & 0xFC);
|
||||
let value: u32;
|
||||
asm!("mov dx, 0xCF8
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
in eax, dx"
|
||||
: "={eax}"(value) : "{eax}"(address) : "dx" : "intel", "volatile");
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PciIter<'pci> {
|
||||
pci: &'pci Pci,
|
||||
num: u32
|
||||
}
|
||||
|
||||
impl<'pci> PciIter<'pci> {
|
||||
pub fn new(pci: &'pci Pci) -> Self {
|
||||
PciIter {
|
||||
pci: pci,
|
||||
num: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'pci> Iterator for PciIter<'pci> {
|
||||
type Item = PciBus<'pci>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.num < 256 {
|
||||
let bus = PciBus {
|
||||
pci: self.pci,
|
||||
num: self.num as u8
|
||||
};
|
||||
self.num += 1;
|
||||
Some(bus)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue