Commit 4b3bc6ac authored by Jeremy Soller's avatar Jeremy Soller

PCI driver WIP

parents
[package]
name = "pcid"
version = "0.1.0"
[dependencies.syscall]
path = "../../syscall/"
#![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();
}
#[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)
}
}
}
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
}
}
}
#[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)
}
}
}
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
}
}
}
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)
}
}
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] }
}
}
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
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment