Switch to pci_types for header parsing
This commit is contained in:
parent
465a46f294
commit
d18ead3093
194
Cargo.lock
generated
194
Cargo.lock
generated
@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
@ -47,9 +47,9 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@ -71,9 +71,9 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.1.3"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "derive-try-from-primitive"
|
||||
@ -88,9 +88,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
@ -106,9 +106,9 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
@ -121,9 +121,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.0"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
@ -141,9 +141,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.6.0"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
@ -151,9 +151,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.159"
|
||||
version = "0.2.170"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -171,6 +171,22 @@ version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
@ -200,7 +216,9 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"binread",
|
||||
"derive-try-from-primitive",
|
||||
"pci-ids",
|
||||
"pci_rpc",
|
||||
"pci_types",
|
||||
"serde",
|
||||
"spin",
|
||||
"syslog_rpc",
|
||||
@ -208,6 +226,19 @@ dependencies = [
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pci-ids"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d88ae3281b415d856e9c2ddbcdd5961e71c1a3e90138512c04d720241853a6af"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pci_rpc"
|
||||
version = "0.1.0"
|
||||
@ -217,10 +248,58 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.0.10"
|
||||
name = "pci_types"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e"
|
||||
checksum = "c4325c6aa3cca3373503b1527e75756f9fbfe5fd76be4b4c8a143ee47430b8e0"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
|
||||
dependencies = [
|
||||
"cobs",
|
||||
"embedded-io 0.4.0",
|
||||
@ -231,27 +310,42 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.7"
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@ -267,9 +361,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@ -279,24 +373,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.218"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.218"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -309,10 +403,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
@ -342,9 +442,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.79"
|
||||
version = "2.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
||||
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -369,9 +469,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.19"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@ -390,9 +490,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.22"
|
||||
version = "0.22.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
@ -403,9 +503,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
@ -479,18 +579,18 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.20"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
|
||||
checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x86_64"
|
||||
version = "0.15.1"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
|
||||
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
|
@ -6,7 +6,9 @@ edition = "2021"
|
||||
[dependencies]
|
||||
binread = "2.2.0"
|
||||
derive-try-from-primitive = "1.0.0"
|
||||
pci-ids = "0.2.5"
|
||||
pci_rpc = { version = "0.1.0", path = "pci_rpc" }
|
||||
pci_types = "0.10.0"
|
||||
serde = { path = "../serde/serde", features = ["derive"] }
|
||||
spin = "0.9.8"
|
||||
syslog_rpc = { version = "0.1.0", path = "../syslog/syslog_rpc" }
|
||||
|
576
src/main.rs
576
src/main.rs
@ -1,11 +1,18 @@
|
||||
#![allow(clippy::verbose_bit_mask)]
|
||||
use std::{
|
||||
collections::HashMap, fs, io::Cursor, os::mikros::{ipc, syscalls}, path::{Path, PathBuf}
|
||||
collections::HashMap,
|
||||
fs,
|
||||
os::mikros::{ipc, syscalls},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use binread::prelude::*;
|
||||
use device_types::{Class, InvalidClass};
|
||||
use device_types::Class;
|
||||
use pci_ids::Device;
|
||||
use pci_rpc::Server;
|
||||
use pci_types::{
|
||||
capability::PciCapability,
|
||||
Bar, ConfigRegionAccess, EndpointHeader, PciAddress, PciHeader, MAX_BARS,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use spin::Mutex;
|
||||
use x86_64::instructions::port::{Port, PortWriteOnly};
|
||||
@ -15,217 +22,36 @@ pub mod device_types;
|
||||
static CONFIG_PORT: Mutex<PortWriteOnly<u32>> = Mutex::new(PortWriteOnly::new(0xCF8));
|
||||
static DATA_PORT: Mutex<Port<u32>> = Mutex::new(Port::new(0xCFC));
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct ConfigAccessor(u32);
|
||||
struct PortAccessor;
|
||||
|
||||
impl ConfigAccessor {
|
||||
pub fn new(bus: u8, device: u8, function: u8) -> Self {
|
||||
assert!(device < 32);
|
||||
assert!(function < 8);
|
||||
Self(
|
||||
(u32::from(bus) << 16)
|
||||
| (u32::from(device) << 11)
|
||||
| (u32::from(function) << 8)
|
||||
| 0x8000_0000,
|
||||
)
|
||||
}
|
||||
|
||||
fn read(self, index: u8) -> u32 {
|
||||
assert!(index < 64);
|
||||
let register = index * 4;
|
||||
unsafe { CONFIG_PORT.lock().write(self.0 | u32::from(register)) }
|
||||
impl ConfigRegionAccess for PortAccessor {
|
||||
unsafe fn read(&self, address: pci_types::PciAddress, offset: u16) -> u32 {
|
||||
unsafe {
|
||||
CONFIG_PORT.lock().write(
|
||||
0x8000_0000
|
||||
| (u32::from(address.bus()) << 16)
|
||||
| (u32::from(address.device()) << 11)
|
||||
| (u32::from(address.function()) << 8)
|
||||
| u32::from(offset),
|
||||
)
|
||||
}
|
||||
|
||||
unsafe { DATA_PORT.lock().read() }
|
||||
}
|
||||
|
||||
fn write(self, index: u8, data: u32) {
|
||||
assert!(index < 64);
|
||||
let register = index * 4;
|
||||
unsafe { CONFIG_PORT.lock().write(self.0 | u32::from(register)) }
|
||||
|
||||
unsafe { DATA_PORT.lock().write(data) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct InvalidHeaderType;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConfigRaw {
|
||||
pub data: [u8; 256],
|
||||
}
|
||||
|
||||
impl ConfigRaw {
|
||||
pub fn new(bus: u8, device: u8, function: u8) -> Self {
|
||||
let accessor = ConfigAccessor::new(bus, device, function);
|
||||
let mut data = [0; 256];
|
||||
for reg_num in 0..32 {
|
||||
let reg = accessor.read(reg_num);
|
||||
for (i, &byte) in reg.to_le_bytes().iter().enumerate() {
|
||||
data[usize::from(reg_num) * 4 + i] = byte;
|
||||
}
|
||||
unsafe fn write(&self, address: pci_types::PciAddress, offset: u16, value: u32) {
|
||||
unsafe {
|
||||
CONFIG_PORT.lock().write(
|
||||
0x8000_0000
|
||||
| (u32::from(address.bus()) << 16)
|
||||
| (u32::from(address.device()) << 11)
|
||||
| (u32::from(address.function()) << 8)
|
||||
| u32::from(offset),
|
||||
)
|
||||
}
|
||||
ConfigRaw { data }
|
||||
|
||||
unsafe { DATA_PORT.lock().write(value) }
|
||||
}
|
||||
|
||||
pub fn common(&self) -> ConfigCommon {
|
||||
Cursor::new(&self.data)
|
||||
.read_le()
|
||||
.expect("Unable to parse PCI device common config")
|
||||
}
|
||||
|
||||
pub fn config(&self) -> Result<ConfigTypeSpecific, InvalidHeaderType> {
|
||||
match Cursor::new(&self.data).read_le() {
|
||||
Ok(cfg) => Ok(cfg),
|
||||
Err(binread::Error::NoVariantMatch { pos: _ }) => Err(InvalidHeaderType),
|
||||
Err(err) => panic!("Only NoVariantMatch should be possible: {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, BinRead)]
|
||||
#[repr(C)]
|
||||
pub struct ConfigCommon {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: u16,
|
||||
pub status: u16,
|
||||
pub rev_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub lat_timer: u8,
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
}
|
||||
|
||||
impl ConfigCommon {
|
||||
fn class(&self) -> Result<Class, InvalidClass> {
|
||||
Class::new(self.class_code, self.subclass, self.prog_if)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, BinRead)]
|
||||
pub enum ConfigTypeSpecific {
|
||||
Type0(ConfigType0),
|
||||
Type1(ConfigType1),
|
||||
Type2(ConfigType2),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, BinRead)]
|
||||
#[repr(C)]
|
||||
pub struct ConfigType0 {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: u16,
|
||||
pub status: u16,
|
||||
pub rev_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub lat_timer: u8,
|
||||
#[br(assert(header_type & 0x7F == 0))]
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
pub bars: [u32; 6],
|
||||
pub cardbus_cis: u32,
|
||||
pub sub_sys_vendor_id: u16,
|
||||
pub sub_sys_id: u16,
|
||||
pub exp_rom_base: u32,
|
||||
pub cap_ptr: u8,
|
||||
reserved: [u8; 7],
|
||||
pub int_line: u8,
|
||||
pub int_pin: u8,
|
||||
pub min_grant: u8,
|
||||
pub max_latency: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, BinRead)]
|
||||
#[repr(C)]
|
||||
pub struct ConfigType1 {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: u16,
|
||||
pub status: u16,
|
||||
pub rev_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub lat_timer: u8,
|
||||
#[br(assert(header_type & 0x7F == 1))]
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
pub bars: [u32; 2],
|
||||
pub prim_bus_num: u8,
|
||||
pub sec_bus_num: u8,
|
||||
pub sub_bus_num: u8,
|
||||
pub sec_latency_timer: u8,
|
||||
pub io_base: u8,
|
||||
pub io_limit: u8,
|
||||
pub sec_status: u16,
|
||||
pub mem_base: u16,
|
||||
pub mem_limit: u16,
|
||||
pub prefetch_mem_base: u16,
|
||||
pub prefetch_mem_limit: u16,
|
||||
pub prefetch_mem_base_upper32: u32,
|
||||
pub prefetch_mem_limit_upper32: u32,
|
||||
pub io_base_upper16: u16,
|
||||
pub io_limit_upper16: u16,
|
||||
pub cap_ptr: u8,
|
||||
reserved: [u8; 3],
|
||||
pub exp_rom_base: u32,
|
||||
pub int_line: u8,
|
||||
pub int_pin: u8,
|
||||
pub bridge_control: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, BinRead)]
|
||||
#[repr(C)]
|
||||
#[repr(packed)]
|
||||
pub struct ConfigType2 {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: u16,
|
||||
pub status: u16,
|
||||
pub rev_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub lat_timer: u8,
|
||||
#[br(assert(header_type & 0x7F == 2))]
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
pub cap_ptr: u8,
|
||||
reserved: u8,
|
||||
pub sec_status: u16,
|
||||
pub mem_base_0: u32,
|
||||
pub mem_limit_0: u32,
|
||||
pub mem_base_1: u32,
|
||||
pub mem_limit_1: u32,
|
||||
pub io_base_0: u32,
|
||||
pub io_limit_0: u32,
|
||||
pub io_base_1: u32,
|
||||
pub io_limit_1: u32,
|
||||
pub int_line: u8,
|
||||
pub int_pin: u8,
|
||||
pub bridge_control: u16,
|
||||
pub sub_sys_vendor_id: u16,
|
||||
pub sub_sys_id: u16,
|
||||
pub legacy_card_base: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Device {
|
||||
pub bus: u8,
|
||||
pub device: u8,
|
||||
pub function: u8,
|
||||
pub common: ConfigCommon,
|
||||
pub type_specific: ConfigTypeSpecific,
|
||||
pub class: Class,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@ -257,91 +83,73 @@ impl DriverMapping {
|
||||
}
|
||||
}
|
||||
|
||||
fn scan_bus(bus: u8, device_vec: &mut Vec<Device>) {
|
||||
fn scan_bus(bus: u8, device_vec: &mut Vec<PciAddress>) {
|
||||
for device in 0..32 {
|
||||
scan_device(bus, device, device_vec);
|
||||
}
|
||||
}
|
||||
|
||||
fn scan_device(bus: u8, device: u8, device_vec: &mut Vec<Device>) {
|
||||
let func0cfg = ConfigRaw::new(bus, device, 0);
|
||||
if func0cfg.common().vendor_id == 0xFFFF {
|
||||
fn scan_device(bus: u8, device: u8, device_vec: &mut Vec<PciAddress>) {
|
||||
//let func0cfg = ConfigRaw::new(bus, device, 0);
|
||||
let func0cfg = PciHeader::new(PciAddress::new(0, bus, device, 0));
|
||||
if func0cfg.id(PortAccessor).0 == 0xFFFF {
|
||||
return;
|
||||
}
|
||||
let header_type = func0cfg.common().header_type;
|
||||
found_function(bus, device, 0, &func0cfg, device_vec);
|
||||
if (header_type & 0x80) != 0 {
|
||||
device_vec.push(PciAddress::new(0, bus, device, 0));
|
||||
if func0cfg.has_multiple_functions(PortAccessor) {
|
||||
for func in 1..8 {
|
||||
let cfg = ConfigRaw::new(bus, device, func);
|
||||
if cfg.common().vendor_id != 0xFFFF {
|
||||
found_function(bus, device, func, &cfg, device_vec);
|
||||
let adresss = PciAddress::new(0, bus, device, func);
|
||||
let cfg = PciHeader::new(adresss);
|
||||
if cfg.id(PortAccessor).0 != 0xFFFF {
|
||||
device_vec.push(adresss)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn found_function(
|
||||
bus: u8,
|
||||
device: u8,
|
||||
function: u8,
|
||||
cfg: &ConfigRaw,
|
||||
device_vec: &mut Vec<Device>,
|
||||
) {
|
||||
let type_specific = if let Ok(type_specific) = cfg.config() {
|
||||
type_specific
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let class = if let Ok(class) = cfg.common().class() {
|
||||
class
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let device = Device {
|
||||
bus,
|
||||
device,
|
||||
function,
|
||||
common: cfg.common(),
|
||||
type_specific,
|
||||
class,
|
||||
};
|
||||
device_vec.push(device);
|
||||
}
|
||||
|
||||
struct PCIServer(Vec<Device>);
|
||||
struct PCIServer(Vec<PciAddress>);
|
||||
|
||||
impl Server for PCIServer {
|
||||
fn get_bars(&self, bus: u8, dev_no: u8, func: u8) -> Result<[(bool, u32, u32); 6], ()> {
|
||||
let device = self
|
||||
let address = *self
|
||||
.0
|
||||
.iter()
|
||||
.find(|dev| dev.bus == bus && dev.device == dev_no && dev.function == func)
|
||||
.find(|addr| addr.bus() == bus && addr.device() == dev_no && addr.function() == func)
|
||||
.ok_or(())?;
|
||||
match device.type_specific {
|
||||
ConfigTypeSpecific::Type0(hdr) => {
|
||||
let accessor = ConfigAccessor::new(bus, dev_no, func);
|
||||
let mut res: [(bool, u32, u32); 6] = [(false, 0, 0); 6];
|
||||
for (i, bar) in hdr.bars.iter().copied().enumerate() {
|
||||
let bar_idx = (i + 0x4) as u8;
|
||||
accessor.write(bar_idx, 0xFFFF_FFFF);
|
||||
let bar_tmp = accessor.read(bar_idx);
|
||||
let info_bits = if bar & 0x1 == 1 {
|
||||
bar_tmp & !0x3
|
||||
} else {
|
||||
bar_tmp & !0xF
|
||||
};
|
||||
let size = !(info_bits) + 1;
|
||||
accessor.write(bar_idx, bar);
|
||||
if bar & 0x1 == 1 {
|
||||
res[i] = (true, bar & !0x3, size);
|
||||
} else {
|
||||
res[i] = (false, bar & !0xF, size);
|
||||
};
|
||||
let common_hdr = PciHeader::new(address);
|
||||
if let Some(hdr) = EndpointHeader::from_header(common_hdr, PortAccessor) {
|
||||
let mut res: [(bool, u32, u32); 6] = [(false, 0, 0); 6];
|
||||
let mut i = 0;
|
||||
while i < MAX_BARS as u8 {
|
||||
let Some(bar) = hdr.bar(i, PortAccessor) else {
|
||||
i += 1;
|
||||
continue;
|
||||
};
|
||||
match bar {
|
||||
Bar::Memory32 {
|
||||
address,
|
||||
size,
|
||||
prefetchable: _,
|
||||
} => {
|
||||
res[i as usize] = (false, address, size);
|
||||
}
|
||||
Bar::Memory64 {
|
||||
address: _,
|
||||
size: _,
|
||||
prefetchable: _,
|
||||
} => {
|
||||
i += 1;
|
||||
// TODO
|
||||
}
|
||||
Bar::Io { port } => {
|
||||
res[i as usize] = (true, port, 0);
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
i += 1;
|
||||
}
|
||||
ConfigTypeSpecific::Type1(_) => Err(()),
|
||||
ConfigTypeSpecific::Type2(_) => Err(()),
|
||||
Ok(res)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -355,65 +163,209 @@ fn main() {
|
||||
}
|
||||
};
|
||||
let syslog_client = syslog_rpc::Client::new(syslog_pid);
|
||||
let mut device_vec = Vec::new();
|
||||
scan_bus(0, &mut device_vec);
|
||||
let srv = PCIServer(device_vec.clone());
|
||||
let mut device_addresses = Vec::new();
|
||||
scan_bus(0, &mut device_addresses);
|
||||
let srv = PCIServer(device_addresses.clone());
|
||||
pci_rpc::register_server(Box::new(srv));
|
||||
let mut driver_map: HashMap<PathBuf, Vec<(u8, u8, u8)>> = HashMap::new();
|
||||
for device in &device_vec {
|
||||
for &address in &device_addresses {
|
||||
let common_hdr = PciHeader::new(address);
|
||||
let (vid, pid) = common_hdr.id(PortAccessor);
|
||||
let device_id = Device::from_vid_pid(vid, pid);
|
||||
let (_, class, subclass, progif) = common_hdr.revision_and_class(PortAccessor);
|
||||
let Ok(class) = Class::new(class, subclass, progif) else {
|
||||
continue;
|
||||
};
|
||||
syslog_client.send_text_message(
|
||||
"pci",
|
||||
format!(
|
||||
"Bus {}, device {}, function {}: Type {:?}, Vendor ID {:#x}, Device ID {:#x}, Header type {}",
|
||||
device.bus,
|
||||
device.device,
|
||||
device.function,
|
||||
device.class,
|
||||
device.common.vendor_id,
|
||||
device.common.device_id,
|
||||
device.common.header_type,
|
||||
"Bus {}, device {}, function {}: Type {:?}, Vendor ID {:#x} ({}), Device ID {:#x} ({}), Header type {:?}",
|
||||
address.bus(),
|
||||
address.device(),
|
||||
address.function(),
|
||||
class,
|
||||
vid,
|
||||
device_id.map_or("Unknown", |x| x.vendor().name()),
|
||||
pid,
|
||||
device_id.map_or("Unknown", |x| x.name()),
|
||||
common_hdr.header_type(PortAccessor),
|
||||
)
|
||||
).unwrap();
|
||||
if let &ConfigTypeSpecific::Type0(cfg_type0) = &device.type_specific {
|
||||
let accessor = ConfigAccessor::new(device.bus, device.device, device.function);
|
||||
for (i, &bar) in cfg_type0.bars.iter().enumerate() {
|
||||
if bar == 0x0 {
|
||||
if let Some(hdr) = EndpointHeader::from_header(common_hdr, PortAccessor) {
|
||||
let mut i = 0;
|
||||
while i < MAX_BARS as u8 {
|
||||
let Some(bar) = hdr.bar(i, PortAccessor) else {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
let bar_idx = (i + 0x4) as u8;
|
||||
accessor.write(bar_idx, 0xFFFF_FFFF);
|
||||
let bar_tmp = accessor.read(bar_idx);
|
||||
let info_bits = if bar & 0x1 == 1 {
|
||||
bar_tmp & !0x3
|
||||
} else {
|
||||
bar_tmp & !0xF
|
||||
};
|
||||
let size = !(info_bits) + 1;
|
||||
accessor.write(bar_idx, bar);
|
||||
if bar & 0x1 == 1 {
|
||||
syslog_client.send_text_message("pci", format!("BAR {}: IO {:#x}, size {:#x}", i, bar & (!0x3), size)).unwrap();
|
||||
} else {
|
||||
syslog_client.send_text_message("pci", format!("BAR {}: MEM {:#x}, size {:#x}", i, bar & (!0xF), size)).unwrap();
|
||||
match bar {
|
||||
Bar::Memory32 {
|
||||
address,
|
||||
size,
|
||||
prefetchable: _,
|
||||
} => {
|
||||
syslog_client
|
||||
.send_text_message(
|
||||
"pci",
|
||||
format!("BAR {i}: MEM 32 {address:#x}, size {size:#x}"),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
Bar::Memory64 {
|
||||
address,
|
||||
size,
|
||||
prefetchable: _,
|
||||
} => {
|
||||
syslog_client
|
||||
.send_text_message(
|
||||
"pci",
|
||||
format!("BAR {i}: MEM 64 {address:#x}, size {size:#x}"),
|
||||
)
|
||||
.unwrap();
|
||||
i += 1;
|
||||
}
|
||||
Bar::Io { port } => {
|
||||
syslog_client
|
||||
.send_text_message("pci", format!("BAR {i}: IO {port:#x}"))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if hdr.status(PortAccessor).has_capability_list() {
|
||||
syslog_client
|
||||
.send_text_message("pci", "Capabilities supported")
|
||||
.unwrap();
|
||||
for capability in hdr.capabilities(PortAccessor) {
|
||||
match capability {
|
||||
PciCapability::PowerManagement(_) => syslog_client
|
||||
.send_text_message("pci", "Power management capability")
|
||||
.unwrap(),
|
||||
PciCapability::AcceleratedGraphicsPort(_) => syslog_client
|
||||
.send_text_message("pci", "AGP capability")
|
||||
.unwrap(),
|
||||
PciCapability::VitalProductData(_) => syslog_client
|
||||
.send_text_message("pci", "Vital product data capability")
|
||||
.unwrap(),
|
||||
PciCapability::SlotIdentification(_) => syslog_client
|
||||
.send_text_message("pci", "External expansion capability")
|
||||
.unwrap(),
|
||||
PciCapability::Msi(_) => syslog_client
|
||||
.send_text_message("pci", "MSI capability")
|
||||
.unwrap(),
|
||||
PciCapability::CompactPCIHotswap(_) => syslog_client
|
||||
.send_text_message("pci", "CompactPCI Hotswap capability")
|
||||
.unwrap(),
|
||||
PciCapability::PciX(_) => syslog_client
|
||||
.send_text_message("pci", "PCI-X capability")
|
||||
.unwrap(),
|
||||
PciCapability::HyperTransport(_) => syslog_client
|
||||
.send_text_message("pci", "HyperTransport capability")
|
||||
.unwrap(),
|
||||
PciCapability::Vendor(_) => syslog_client
|
||||
.send_text_message("pci", "Vendor specific capability")
|
||||
.unwrap(),
|
||||
PciCapability::DebugPort(_) => syslog_client
|
||||
.send_text_message("pci", "Debug port capability")
|
||||
.unwrap(),
|
||||
PciCapability::CompactPCICentralResourceControl(_) => syslog_client
|
||||
.send_text_message("pci", "CompactPCI central resource control capability")
|
||||
.unwrap(),
|
||||
PciCapability::PciHotPlugControl(_) => syslog_client
|
||||
.send_text_message("pci", "Hotplug capability")
|
||||
.unwrap(),
|
||||
PciCapability::BridgeSubsystemVendorId(_) => syslog_client
|
||||
.send_text_message("pci", "Bridge Subsystem Vendor ID capability")
|
||||
.unwrap(),
|
||||
PciCapability::AGP3(_) => syslog_client
|
||||
.send_text_message("pci", "AGP3 capability")
|
||||
.unwrap(),
|
||||
PciCapability::PciExpress(_) => syslog_client
|
||||
.send_text_message("pci", "PCI-Express capability")
|
||||
.unwrap(),
|
||||
PciCapability::MsiX(_) => syslog_client
|
||||
.send_text_message("pci", "MSI-X capability")
|
||||
.unwrap(),
|
||||
PciCapability::Unknown { address: _, id } => syslog_client
|
||||
.send_text_message("pci", format!("Other capability (type {id:#x})")).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//if cfg_type0.status & 0x10 > 0 {
|
||||
// syslog_client
|
||||
// .send_text_message("pci", "Capabilities supported")
|
||||
// .unwrap();
|
||||
// let mut cap_ptr = cfg_type0.cap_ptr & 0xFC;
|
||||
// while cap_ptr > 0 {
|
||||
// let cap_reg0 = accessor.read(cap_ptr / 4);
|
||||
// let typ = (cap_reg0 & 0xFF) as u8;
|
||||
// if typ == 0x9 && device.common.vendor_id == 0x1AF4 {
|
||||
// let cfg_typ = ((cap_reg0 >> 24) & 0xFF) as u8;
|
||||
// let bar = accessor.read((cap_ptr / 4) + 1) as u8;
|
||||
// let offfset = accessor.read((cap_ptr / 4) + 2);
|
||||
// let length = accessor.read((cap_ptr / 4) + 3);
|
||||
// syslog_client.send_text_message("pci", format!("Virtio capability type {}, BAR {}, offfset {:#x}, length {:#x} found", cfg_typ, bar, offfset, length)).unwrap();
|
||||
// } else if typ == 0x5 {
|
||||
// let control = ((cap_reg0 >> 16) & 0xFFFF) as u16;
|
||||
// let en = (control & 0x1) > 0;
|
||||
// let mmc = (control & 0xE) as u8;
|
||||
// let mme = ((control & 0x70) >> 4) as u8;
|
||||
// let address = if (control & 0x80) > 0 {
|
||||
// let address_low = accessor.read((cap_ptr / 4) + 1);
|
||||
// let address_high = accessor.read((cap_ptr / 4) + 2);
|
||||
// ((address_high as u64) << 32) | (address_low as u64)
|
||||
// } else {
|
||||
// let address = accessor.read((cap_ptr / 4) + 1);
|
||||
// address as u64
|
||||
// };
|
||||
// let data = if (control & 0x80) > 0 {
|
||||
// accessor.read((cap_ptr / 4) + 3) as u16
|
||||
// } else {
|
||||
// accessor.read((cap_ptr / 4) + 2) as u16
|
||||
// };
|
||||
// if (control & 0x100) > 0 {
|
||||
// let mask = accessor.read((cap_ptr / 4) + 4);
|
||||
// syslog_client.send_text_message("pci", format!("MSI capability: en = {en:?}, mmc = {mmc}, mme = {mme}, addr = {address:#x}, data = {data:#x}, mask = {mask:#x}")).unwrap();
|
||||
// } else {
|
||||
// syslog_client.send_text_message("pci", format!("MSI capability: en = {en:?}, mmc = {mmc}, mme = {mme}, addr = {address:#x}, data = {data:#x}, no masking")).unwrap();
|
||||
// }
|
||||
// } else if typ == 0x11 {
|
||||
// let control = ((cap_reg0 >> 16) & 0xFFFF) as u16;
|
||||
// let en = (control & 0x8000) > 0;
|
||||
// let mask_all = (control & 0x4000) > 0;
|
||||
// let size = (control & 0x7FF) + 1;
|
||||
// let cap_reg1 = accessor.read((cap_ptr / 4) + 1);
|
||||
// let table_bar = (cap_reg1 & 0x7) as u8;
|
||||
// let table_offset = cap_reg1 & 0xFFFF_FFF8;
|
||||
// let cap_reg2 = accessor.read((cap_ptr / 4) + 1);
|
||||
// let pending_bar = (cap_reg2 & 0x7) as u8;
|
||||
// let pending_offset = cap_reg2 & 0xFFFF_FFF8;
|
||||
// syslog_client.send_text_message("pci", format!("MSI-X capability: en = {en:?}, mask_all = {mask_all:?}, size = {size}, table_bar = {table_bar}, table_offset = {table_offset:#x}, pending_bar = {pending_bar}, pending_offset = {pending_offset:#x}")).unwrap();
|
||||
// } else {
|
||||
// syslog_client
|
||||
// .send_text_message("pci", format!("Capability {:#x} found", typ))
|
||||
// .unwrap();
|
||||
// }
|
||||
// cap_ptr = ((cap_reg0 >> 8) & 0xFF) as u8;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
let driver = config
|
||||
.mappings
|
||||
.iter()
|
||||
.find(|mapping| match mapping {
|
||||
DriverMapping::GenericClass {
|
||||
class,
|
||||
class: drv_class,
|
||||
vend_dev_exclude,
|
||||
..
|
||||
} => {
|
||||
&device.class == class
|
||||
&& !vend_dev_exclude.as_ref().map_or(false, |x| {
|
||||
x.contains(&(device.common.vendor_id, device.common.device_id))
|
||||
})
|
||||
}
|
||||
DriverMapping::VendDev { list, .. } => {
|
||||
list.contains(&(device.common.vendor_id, device.common.device_id))
|
||||
&class == drv_class
|
||||
&& !vend_dev_exclude
|
||||
.as_ref()
|
||||
.map_or(false, |x| x.contains(&(vid, pid)))
|
||||
}
|
||||
DriverMapping::VendDev { list, .. } => list.contains(&(vid, pid)),
|
||||
})
|
||||
.map(|mapping| mapping.path());
|
||||
if let Some(driver) = driver {
|
||||
@ -421,7 +373,11 @@ fn main() {
|
||||
.send_text_message("pci", format!(" Driver {}", driver.display()))
|
||||
.unwrap();
|
||||
|
||||
driver_map.entry(driver.to_owned()).or_default().push((device.bus, device.device, device.function));
|
||||
driver_map.entry(driver.to_owned()).or_default().push((
|
||||
address.bus(),
|
||||
address.device(),
|
||||
address.function(),
|
||||
));
|
||||
} else {
|
||||
syslog_client
|
||||
.send_text_message("pci", " WARN: No driver")
|
||||
|
Loading…
x
Reference in New Issue
Block a user