diff --git a/pcid/src/main.rs b/pcid/src/main.rs index 5789d21263..2858433a43 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -6,7 +6,7 @@ use std::thread; use std::sync::{Arc, Mutex}; use pci_types::device_type::DeviceType; -use pci_types::{ConfigRegionAccess, PciAddress}; +use pci_types::{CommandRegister, ConfigRegionAccess, PciAddress}; use structopt::StructOpt; use log::{debug, error, info, warn, trace}; use redox_log::{OutputBuilder, RedoxLogger}; @@ -16,7 +16,7 @@ use crate::config::Config; use crate::pci::{PciBar, PciFunc}; use crate::pci::cap::Capability as PciCapability; use crate::pci::func::{ConfigReader, ConfigWriter}; -use crate::pci_header::{PciHeader, PciHeaderError}; +use crate::pci_header::{PciEndpointHeader, PciHeader, PciHeaderError}; mod cfg_access; mod config; @@ -206,10 +206,9 @@ pub struct State { pcie: Pcie, } -fn handle_parsed_header(state: Arc, config: &Config, addr: PciAddress, header: PciHeader) { - let raw_class: u8 = header.class().into(); +fn print_pci_function(addr: PciAddress, header: &PciHeader) { let mut string = format!("PCI {} {:>04X}:{:>04X} {:>02X}.{:>02X}.{:>02X}.{:>02X} {:?}", - addr, header.vendor_id(), header.device_id(), raw_class, + addr, header.vendor_id(), header.device_id(), header.class(), header.subclass(), header.interface(), header.revision(), header.class()); let device_type = DeviceType::from((header.class(), header.subclass())); match device_type { @@ -229,19 +228,10 @@ fn handle_parsed_header(state: Arc, config: &Config, addr: PciAddress, he }, _ => (), } - - let bars = header.bars(&state.pcie); - for (i, bar) in bars.iter().enumerate() { - match bar { - PciBar::None => {}, - PciBar::Memory32{addr,..} => string.push_str(&format!(" {i}={addr:08X}")), - PciBar::Memory64{addr,..} => string.push_str(&format!(" {i}={addr:016X}")), - PciBar::Port(port) => string.push_str(&format!(" {i}=P{port:04X}")), - } - } - info!("{}", string); +} +fn handle_parsed_header(state: Arc, config: &Config, addr: PciAddress, header: PciEndpointHeader) { for driver in config.drivers.iter() { if !driver.match_function(header.full_device_id()) { continue; @@ -251,13 +241,30 @@ fn handle_parsed_header(state: Arc, config: &Config, addr: PciAddress, he continue; }; - // Enable bus mastering, memory space, and I/O space - unsafe { - let mut data = state.pcie.read(addr, 0x04); - data |= 7; - state.pcie.write(addr, 0x04, data); + let mut string = String::new(); + let bars = header.bars(&state.pcie); + for (i, bar) in bars.iter().enumerate() { + match bar { + PciBar::None => {}, + PciBar::Memory32 { addr, .. } => string.push_str(&format!(" {i}={addr:08X}")), + PciBar::Memory64 { addr, .. } => string.push_str(&format!(" {i}={addr:016X}")), + PciBar::Port(port) => string.push_str(&format!(" {i}=P{port:04X}")), + } } + if !string.is_empty() { + info!(" BAR{}", string); + } + + let endpoint_header = header.endpoint_header(&state.pcie); + + // Enable bus mastering, memory space, and I/O space + endpoint_header.update_command(&state.pcie, |cmd| { + cmd | CommandRegister::BUS_MASTER_ENABLE + | CommandRegister::MEMORY_ENABLE + | CommandRegister::IO_ENABLE + }); + // Set IRQ line to 9 if not set let mut irq; let interrupt_pin; @@ -273,7 +280,7 @@ fn handle_parsed_header(state: Arc, config: &Config, addr: PciAddress, he state.pcie.write(addr, 0x3C, data); }; - let capabilities = if header.status() & (1 << 4) != 0 { + let capabilities = if endpoint_header.status(&state.pcie).has_capability_list() { let func = PciFunc { pci: &state.pcie, addr @@ -467,9 +474,21 @@ fn main(args: Args) { let func_addr = PciAddress::new(0, bus_num, dev_num, func_num); match PciHeader::from_reader(&state.pcie, func_addr) { Ok(header) => { - handle_parsed_header(Arc::clone(&state), &config, func_addr, header); - if let PciHeader::PciToPci { secondary_bus_num, .. } = header { - bus_nums.push(secondary_bus_num); + print_pci_function(func_addr, &header); + match header { + PciHeader::General(endpoint_header) => { + handle_parsed_header( + Arc::clone(&state), + &config, + func_addr, + endpoint_header, + ); + } + PciHeader::PciToPci { + secondary_bus_num, .. + } => { + bus_nums.push(secondary_bus_num); + } } } Err(PciHeaderError::NoDevice) => { diff --git a/pcid/src/pci_header.rs b/pcid/src/pci_header.rs index 9905af380e..2b3a64e4c5 100644 --- a/pcid/src/pci_header.rs +++ b/pcid/src/pci_header.rs @@ -16,19 +16,20 @@ pub enum PciHeaderError { #[derive(Clone, Copy, Debug, PartialEq)] pub struct SharedPciHeader { full_device_id: FullDeviceId, - command: u16, - status: u16, addr: PciAddress, } +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct PciEndpointHeader { + shared: SharedPciHeader, + subsystem_vendor_id: u16, + subsystem_id: u16, + cap_pointer: u8, +} + #[derive(Clone, Copy, Debug, PartialEq)] pub enum PciHeader { - General { - shared: SharedPciHeader, - subsystem_vendor_id: u16, - subsystem_id: u16, - cap_pointer: u8, - }, + General(PciEndpointHeader), PciToPci { shared: SharedPciHeader, secondary_bus_num: u8, @@ -49,9 +50,6 @@ impl PciHeader { let header = TyPciHeader::new(addr); let (vendor_id, device_id) = header.id(access); - let command_and_status = unsafe { access.read(addr, 4) }; - let command = (command_and_status & 0xffff) as u16; - let status = (command_and_status >> 16) as u16; let (revision, class, subclass, interface) = header.revision_and_class(access); let header_type = header.header_type(access); let shared = SharedPciHeader { @@ -63,8 +61,6 @@ impl PciHeader { interface, revision, }, - command, - status, addr, }; @@ -73,12 +69,12 @@ impl PciHeader { let endpoint_header = EndpointHeader::from_header(header, access).unwrap(); let (subsystem_id, subsystem_vendor_id) = endpoint_header.subsystem(access); let cap_pointer = (unsafe { access.read(addr, 0x34) } & 0xff) as u8; - Ok(PciHeader::General { + Ok(PciHeader::General(PciEndpointHeader { shared, subsystem_vendor_id, subsystem_id, cap_pointer, - }) + })) } HeaderType::PciPciBridge => { let bridge_header = PciPciBridgeHeader::from_header(header, access).unwrap(); @@ -97,14 +93,14 @@ impl PciHeader { /// Return all identifying information of the PCI function. pub fn full_device_id(&self) -> &FullDeviceId { match self { - PciHeader::General { + PciHeader::General(PciEndpointHeader { shared: SharedPciHeader { full_device_id: device_id, .. }, .. - } + }) | PciHeader::PciToPci { shared: SharedPciHeader { @@ -145,17 +141,21 @@ impl PciHeader { pub fn class(&self) -> u8 { self.full_device_id().class } +} + +impl PciEndpointHeader { + pub fn endpoint_header(&self, access: &impl ConfigRegionAccess) -> EndpointHeader { + EndpointHeader::from_header(TyPciHeader::new(self.shared.addr), access).unwrap() + } + + pub fn full_device_id(&self) -> &FullDeviceId { + &self.shared.full_device_id + } /// Return the Headers BARs. // FIXME use pci_types::Bar instead pub fn bars(&self, access: &impl ConfigRegionAccess) -> [PciBar; 6] { - let endpoint_header = match *self { - PciHeader::General { - shared: SharedPciHeader { addr, .. }, - .. - } => EndpointHeader::from_header(TyPciHeader::new(addr), access).unwrap(), - PciHeader::PciToPci { .. } => unreachable!(), - }; + let endpoint_header = self.endpoint_header(access); let mut bars = [PciBar::None; 6]; let mut skip = false; @@ -195,25 +195,8 @@ impl PciHeader { bars } - pub fn status(&self) -> u16 { - match self { - &PciHeader::General { - shared: SharedPciHeader { status, .. }, - .. - } - | &PciHeader::PciToPci { - shared: SharedPciHeader { status, .. }, - .. - } => status, - } - } - pub fn cap_pointer(&self) -> u8 { - match self { - &PciHeader::General { cap_pointer, .. } | &PciHeader::PciToPci { cap_pointer, .. } => { - cap_pointer - } - } + self.cap_pointer } }