PCI driver WIP
This commit is contained in:
parent
f05cc96db1
commit
c9a4b3882c
16 changed files with 400 additions and 7 deletions
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