Merge branch 'pci_use_pci_types2' into 'master'

Use the pci_types crate for writing the command register and reading the status register

See merge request redox-os/drivers!136
This commit is contained in:
Jeremy Soller
2024-01-24 13:19:46 +00:00
2 changed files with 69 additions and 67 deletions
+44 -25
View File
@@ -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<State>, 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<State>, 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<State>, 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<State>, 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<State>, 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) => {
+25 -42
View File
@@ -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
}
}