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