Skip to content

Instantly share code, notes, and snippets.

@joevt
Last active February 8, 2024 00:44
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joevt/e3cd4ff08aae06279134969c98ca3ab7 to your computer and use it in GitHub Desktop.
Save joevt/e3cd4ff08aae06279134969c98ca3ab7 to your computer and use it in GitHub Desktop.
A bash script to produce more informative output than lspci -nntv
#!/bin/bash
# by joevt Feb 6, 2024
# Jan 22, 2023 - Updated to work in Mac OS X 10.4.
# Jan 30, 2023 - Fixed the method options.
# Apr 7, 2023 - Fixed parse of unknown prog-if and move temp files to separate tmp directory.
# Feb 6, 2024 - Fix column alignment.
#===================
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root like this:"
echo "sudo $0"
exit 1
fi
#===================
style="wide"
style="narrow"
#encoding="ascii"
encoding="utf8"
method="" # default method which for macOS on Intel is -Adarwin
#method="-Adarwin" # uses AppleACPIPlatformExpert user client
#method="-Adarwin2" # uses IOPCIBridge user client
#method="-Adarwin3" # uses IOPCIBridge through DirectHW user client
#method="-Aintel-conf1" # uses I/O to CF8h/CFCh (requires Intel DirectHW.kext on macOS)
#method="-H1" # same as -Aintel-conf1
#===================
if [ $encoding == "ascii" ]; then
box0='\'
box1='-'
box2='\'
box3='+'
box4='|'
box5='.'
else
box0='┐'
box1='─'
box2='└'
box3='├'
box4='│'
box5='┬'
fi
if [ $style == "wide" ]; then
if [ $encoding == "ascii" ]; then
# since we're using \, we want to indent one extra space
rootindent=' '
subindent=' '
else
rootindent=' '
subindent=' '
fi
domainprefix="\\${box1}\\["
domainsuffix="\\]\\${box1}\\${box0}"
bridgeprefix="\\${box3}\\${box1}"
bridgesuffixlong="\\${box1}\\${box1}\\${box1}\\${box1}\\${box0}"
bridgesuffix="\\${box1}\\${box0}"
deviceprefix="\\${box3}\\${box1}"
devicesuffix=""
else
rootindent=''
subindent=' '
domainprefix="\\${box5}\\["
domainsuffix="\\]"
bridgeprefix="\\${box3}\\${box5}"
bridgesuffixlong=""
bridgesuffix=""
deviceprefix="\\${box3}\\${box1}"
devicesuffix=""
fulladdress=1
fi
#===================
#tmp=/tmp/pcitree
tmp="$(mktemp -d "/tmp/pcitree.XXXX")"
mkdir -p "$tmp"
chmod 777 "$tmp"
# Get header type and bus information for all pci devices - reverse sort so last bus is first (required for device path substitution step below).
# Format is "domain:bus%device.function domain:primary domain:secondary domain:subordinate".
# Keep the domain number for device path substitution step below.
# -0777 allows perl to process all lines at once - here we process two lines at a time.
setpci $method -v -s '*:*:*' HEADER_TYPE.b 0x18.l 2> /dev/null | perl -0777 -pe '
s/((.{4}):(..):(..\..)) \@0e = ([08][12])\n\1 \@18 = ..(.{2})(.{2})(.{2})\n/$2:$3%$4 $2:$8 $2:$7 $2:$6\n/g; # bridge(01) or card bus(02) header type, multifunction(80) or not (00).
s/((.{4}):(..):(..\..)) \@0e = (..)\n\1 \@18 = ..(.{2})(.{2})(.{2})\n/$2:$3%$4\n/g # endpoint (or anything else) header type
' \
| sort -r > "$tmp"/pcilist.txt
# If primary = secondary = subordinate then that is a problem - change them to XX.
sed '/^\(....:..%..\..\) \(\(.\{4\}:\)..\) \2 \2$/s//\1 \3XX \3XX \3XX/' "$tmp"/pcilist.txt > "$tmp"/pcilist2.txt
echo '/ ....:/s// /g' > "$tmp"/pcipaths.txt # Add a command that will remove domain from primary, secondary, and subordinate bus numbers.
# Create device path substitution commands that will add parent bus to each secondary bus.
# When applied to the list of pci devices, the commands will create a full device path for
# each pci device. Multiple commands will be applied to each device to build the device
# path from right to left: end point (greatest bus number) to domain (lowest bus number).
# The commands are sorted from highest bus number to lowest bus number to make that possible.
sed -nE '/^(....:..%..\..) .{4}:.. (.{4}:..) .*/s//\/(\2)\/s\/\/\1%\\1\/g/p' "$tmp"/pcilist2.txt >> "$tmp"/pcipaths.txt
sed -E -f "$tmp"/pcipaths.txt "$tmp"/pcilist2.txt > "$tmp"/pcitree1.txt # Apply the device path substitution commands.
sed -E '/^(....:..).*/s//\1/g' "$tmp"/pcitree1.txt | sort -u > "$tmp"/pcitree2.txt # Get all root complexes (usually just 0000:00).
cat "$tmp"/pcitree1.txt "$tmp"/pcitree2.txt | LC_ALL=C sort > "$tmp"/pcitree3.txt # Concatenate the devices and root complexes and sort.
# Use perl to do some formatting.
perl -CSDA -Mutf8 -pe '
s/^(.*(\w\w\w\w:\w\w%\w\w\.\w).*)/\1 # \2/; # save domain/bus/device/function after a " # " - this will be used to append name and ids
s/^\w\w\w\w:\w\w%/'"$rootindent"'/; # remove domain/bus number from left side and indent
s/\w\w\.\w%\w\w\w\w:\w\w%/'"$subindent"'/g; # use the paths to do more indenting
s/(\w\w\.\w) \w\w (\w\w) \2/'"${bridgeprefix}"'\1-[\2]'"${bridgesuffixlong}"'/; # format the secondary and subordinate bus numbers for single bus bridge
s/(\w\w\.\w) \w\w (\w\w) (\w\w)/'"${bridgeprefix}"'\1-[\2-\3]'"${bridgesuffix}"'/; # format the secondary and subordinate bus numbers for multiple bus bridge
s/%/:/; # replace % bus/device delimiter with standard ":"
s/(\w\w\.\w )/'"${deviceprefix}"'\1'"${devicesuffix}"'/; # add the "+-" formating for devices
s/^(\w\w\w\w:\w\w)$/'"${domainprefix}"'\1'"${domainsuffix}"'/ # add the -[ ]\" for domain/bus
' \
"$tmp"/pcitree3.txt > "$tmp"/pcitree4.txt
# https://perldoc.perl.org/perlrun.html
# The -C flag controls some of the Perl Unicode features.
# S: STDIN, STDOUT and STDERR are assumed to be in UTF-8.
# D: UTF-8 is the default PerlIO layer for both input and output streams.
# A: @ARGV elements are expected to be strings encoded in UTF-8.
# -0[octal/hexadecimal] specifies the input record separator ($/ ) as an octal or hexadecimal number.
# Any value 0400 or above will cause Perl to slurp files whole, but by convention the value 0777 is the one normally used for this purpose.
# -Mmodule executes use module ; before executing your program. This loads the module and calls its import method, causing the module to have its default effect, typically importing subroutines or giving effect to a pragma.
# -p causes Perl to assume a loop around your program, which makes it iterate over filename arguments somewhat like sed.
# -e commandline May be used to enter one line of program.
perl -CSDA -Mutf8 -0777 -pe '
# add | between devices of the same bus
do {
$good=0;
while (
/ # begin regular expression
( # begin g1
\n # \n
([\ '"\\${box4}"']*) # [ |]* -> g2
['"\\${box3}\\${box4}"'] # [+|]
[^\n]* # rest of the line up to \n, (change + to *+ to give nothing back)
(?{$X=pos()}) # mark position
\n # \n
) # end g1
(?= # begin lookahead
( # begin group
\2\ [^\n]* # following line(s) start with g2 also (change + to *+ to give nothing back)
\n #
)+ # end group, match one or more, (change + to ++ to give nothing back)
\2 # the line after those start with g2
'"\\${box3}"' # and "+" meaning that another device follows g1 on the same bus
) # end lookahead
(
\2 #
(?{$C=pos()}) # $C is the position where we want to insert the |
\ # the character at position $C to be modified is a space character
) #
/gx # end regular expression (g=global; x=ignore white space in RE)
) {
$good = 1;
substr($_,$C,1) = "'"\\${box4}"'"; # replace the space character at position $C with a |
pos() = $X; # start next search at $X which is the end of the previous line
}
} until ($good == 0);
# replace + with \ for last device of a bus
s/(\n[\ '"\\${box4}"']*)'"\\${box3}"'(?![^\n]*\1['"\\${box3}\\${box4}"'])/\1'"\\${box2}"'/g;
' "$tmp"/pcitree4.txt > "$tmp"/pcitree5.txt
# Create the substitutions for the detail column
lspci $method -nnv -D 2> /dev/null > "$tmp"/pcidevices0_lspci.txt
perl -pe '
s/^\n//g;
s/^[ \t].*\n//g;
s|/|\\/|g;
s|^(....:..:..\..) ([^[]*) (\[....\])(.*) (\[....:....\])( \(rev ..\))?(?: \(prog-if ..(( \[.*?\])?)\))?|/# (\1)\$/s//'" "'# \\1 \5 \3:\6 : \2\7 \4/|;
s/\]:([^:]{9}.*?) *:([^:]{37}.*?) *:/]\1\2 :/ # rev column is 9 characters and type column is 36 characters
' \
"$tmp"/pcidevices0_lspci.txt > "$tmp"/pcidevices1_lspci_sed.txt
# Get link width and speed max/current.
pat="(....:..:..\..) @09 = (..)"
IFS=$'\n'
echo "" > "$tmp"/pcidevices2_link_sed.txt
echo "" > "$tmp"/pcidevices1_progintf_sed.txt
for thedevice in $(sudo setpci $method -v -s '*:*:*' CLASS_PROG.b 2> /dev/null); do
pcidevice="${thedevice% @*}"
proginterface="${thedevice#* = }"
# We have to do this in a loop because setpci stops if express capability doesn't exist
LinkRegisters=$(sudo setpci $method -s $pcidevice CAP_EXP+12.w CAP_EXP+c.l 2> /dev/null)
if [[ -n $LinkRegisters ]]; then
LinkStatusRegister=${LinkRegisters:0:4}
LinkWidth=$((0x$LinkStatusRegister >> 4 & 31))
if [[ $LinkWidth -ge 0 ]]; then
LinkSpeed=$((0x$LinkStatusRegister & 15))
LinkCapabilitiesRegister=${LinkRegisters:5:8}
MaxLinkWidth=$((0x$LinkCapabilitiesRegister >> 4 & 31))
MaxLinkSpeed=$((0x$LinkCapabilitiesRegister & 15))
echo "/# ($pcidevice .*$)/s//# g${MaxLinkSpeed}x${MaxLinkWidth} > g${LinkSpeed}x${LinkWidth} \1/" >> "$tmp"/pcidevices2_link_sed.txt
fi
fi
echo "/(# +$pcidevice \[....:....\] \[....)/s//\1${proginterface}/" >> "$tmp"/pcidevices1_progintf_sed.txt
done
perl -CSDA -Mutf8 -pe '
s/# (g.x..?) > \1 /# \1 /; # if the links are the same then output it only once
s|(/s//#.{16}) *|\1|; # make the link column 16 characters wide
' "$tmp"/pcidevices2_link_sed.txt > "$tmp"/pcidevices3_link_sed.txt
# If there's only one domain/segment then remove them from the output.
if [[ $(sed -E '/(....).*/s//\1/' "$tmp"/pcitree2.txt | sort -u | wc -l) -eq 1 ]]; then
echo "/(#.{16}).{4}:/s//\\1/" >> "$tmp"/pcidevices3_link_sed.txt
fi
if [[ $fulladdress -eq 1 ]]; then
echo "/..\..([^#]*#.{16})([0-9a-f.:]+) /s//\\2\\1/" >> "$tmp"/pcidevices3_link_sed.txt
fi
# Apply the substitutions
sed -E -f "$tmp"/pcidevices1_lspci_sed.txt -f "$tmp"/pcidevices1_progintf_sed.txt -f "$tmp"/pcidevices3_link_sed.txt "$tmp"/pcitree5.txt > "$tmp"/pcitree6.txt
# Set width of the first column to the minimum required
spaces=$(perl -CSDA -Mutf8 -e '$spaces=0; while (<>) { if (/^([^#]*?) *#/) { $s = length($1); if ($s > $spaces) { $spaces = $s }}} print $spaces' "$tmp"/pcitree6.txt)
perl -CSDA -Mutf8 -pe 's/^(.{'"$((spaces+2))"'}) */$1/' "$tmp"/pcitree6.txt > "$tmp"/pcitree7.txt
echo '#========================================================================================='
cat "$tmp"/pcitree7.txt # final output
@joevt
Copy link
Author

joevt commented May 9, 2020

Tested in Ubuntu and macOS. Use it like this:
sudo pcitree.sh
Output should look like this:

#=========================================================================================
┬[0000:00]
├─00:00.0             # g1x4           [8086:4003] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset Memory Controller Hub
├┬00:01.0-[01-10]     # g2x16 > g1x16  [8086:4021] [060400] (rev 20) PCI bridge [Normal decode]           : Intel Corporation 5400 Chipset PCI Express Port 1
│└┬01:00.0-[02-10]    # g3x16 > g1x16  [10b5:8747] [060400] (rev ca) PCI bridge [Normal decode]           : PLX Technology, Inc. PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch
│ ├┬02:08.0-[03-08]   # g3x8 > g3x4    [10b5:8747] [060400] (rev ca) PCI bridge [Normal decode]           : PLX Technology, Inc. PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch
│ │└┬03:00.0-[04-08]  # g3x4           [8086:15ea] [060400] (rev 06) PCI bridge [Normal decode]           : Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018]
│ │ ├┬04:00.0-[05]    # g1x4           [8086:15ea] [060400] (rev 06) PCI bridge [Normal decode]           : Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018]
│ │ │└─05:00.0        # g1x4           [8086:15eb] [088000] (rev 06) System peripheral                    : Intel Corporation JHL7540 Thunderbolt 3 NHI [Titan Ridge 4C 2018]
│ │ ├┬04:01.0-[06]    # g1x4           [8086:15ea] [060400] (rev 06) PCI bridge [Normal decode]           : Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018]
│ │ ├┬04:02.0-[07]    # g1x4           [8086:15ea] [060400] (rev 06) PCI bridge [Normal decode]           : Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018]
│ │ │└─07:00.0        # g1x4           [8086:15ec] [0c0330] (rev 06) USB controller [XHCI]                : Intel Corporation JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018]
│ │ └┬04:04.0-[08]    # g1x4           [8086:15ea] [060400] (rev 06) PCI bridge [Normal decode]           : Intel Corporation JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018]
│ ├┬02:09.0-[09-0e]   # g3x8 > g3x4    [10b5:8747] [060400] (rev ca) PCI bridge [Normal decode]           : PLX Technology, Inc. PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch
│ │└┬09:00.0-[0a-0e]  # g3x4           [8086:1136] [060400] (rev 02) PCI bridge [Normal decode]           : Intel Corporation Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
│ │ ├┬0a:00.0-[0b]    # g1x4           [8086:1136] [060400] (rev 02) PCI bridge [Normal decode]           : Intel Corporation Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
│ │ │└─0b:00.0        # g1x4           [8086:1137] [0c0340]          USB controller [USB4 Host Interface] : Intel Corporation Thunderbolt 4 NHI [Maple Ridge 4C 2020]
│ │ ├┬0a:01.0-[0c]    # g1x4           [8086:1136] [060400] (rev 02) PCI bridge [Normal decode]           : Intel Corporation Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
│ │ ├┬0a:02.0-[0d]    # g1x4 > g0x4    [8086:1136] [060400] (rev 02) PCI bridge [Normal decode]           : Intel Corporation Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
│ │ │└─0d:00.0        # g1x4           [8086:1138] [0c0330]          USB controller [XHCI]                : Intel Corporation Thunderbolt 4 USB Controller [Maple Ridge 4C 2020]
│ │ └┬0a:03.0-[0e]    # g1x4           [8086:1136] [060400] (rev 02) PCI bridge [Normal decode]           : Intel Corporation Thunderbolt 4 Bridge [Maple Ridge 4C 2020]
│ ├┬02:10.0-[0f]      # g3x8 > g1x0    [10b5:8747] [060400] (rev ca) PCI bridge [Normal decode]           : PLX Technology, Inc. PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch
│ └┬02:11.0-[10]      # g3x8 > g3x4    [10b5:8747] [060400] (rev ca) PCI bridge [Normal decode]           : PLX Technology, Inc. PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch
│  └┬10:00.0-[XX]     # g3x4           [ffff:ffff] [060400]          PCI bridge [Normal decode]           : Illegal Vendor ID Device
├┬00:05.0-[11]        # g2x16 > g1x16  [8086:4025] [060400] (rev 20) PCI bridge [Normal decode]           : Intel Corporation 5400 Chipset PCI Express Port 5
│├─11:00.0            # g2x16 > g1x16  [10de:1180] [030000] (rev a1) VGA compatible controller [VGA controller] : NVIDIA Corporation GK104 [GeForce GTX 680]
│└─11:00.1            # g2x16 > g1x16  [10de:0e0a] [040300] (rev a1) Audio device                         : NVIDIA Corporation GK104 HDMI Audio Controller
├┬00:09.0-[12-1a]     # g2x4 > g1x4    [8086:4029] [060400] (rev 20) PCI bridge [Normal decode]           : Intel Corporation 5400 Chipset PCI Express Port 9
│├┬12:00.0-[13-19]    # g1x8 > g1x4    [8086:3500] [060400] (rev 01) PCI bridge [Normal decode]           : Intel Corporation 6311ESB/6321ESB PCI Express Upstream Port
││├┬13:00.0-[14-17]   # g1x4           [8086:3510] [060400] (rev 01) PCI bridge [Normal decode]           : Intel Corporation 6311ESB/6321ESB PCI Express Downstream Port E1
│││└┬14:00.0-[15-17]  # g2x4 > g1x4    [12d8:2308] [060400]          PCI bridge [Normal decode]           : Pericom Semiconductor PI7C9X2G308GP 8-lane PCI Express 2.0 Switch with 3 PCI Express ports
│││ ├┬15:01.0-[16]    # g2x2           [12d8:2308] [060400]          PCI bridge [Normal decode]           : Pericom Semiconductor PI7C9X2G308GP 8-lane PCI Express 2.0 Switch with 3 PCI Express ports
│││ │└─16:00.0        # g2x2           [1b21:1242] [0c0330]          USB controller [XHCI]                : ASMedia Technology Inc. ASM1142 USB 3.1 Host Controller
│││ └┬15:02.0-[17]    # g2x2           [12d8:2308] [060400]          PCI bridge [Normal decode]           : Pericom Semiconductor PI7C9X2G308GP 8-lane PCI Express 2.0 Switch with 3 PCI Express ports
│││  └─17:00.0        # g2x2           [1b21:0625] [010601] (rev 01) SATA controller [AHCI 1.0]           : ASMedia Technology Inc. 106x SATA/RAID Controller
││├┬13:01.0-[18]      # g1x4 > g1x0    [8086:3514] [060400] (rev 01) PCI bridge [Normal decode]           : Intel Corporation 6311ESB/6321ESB PCI Express Downstream Port E2
││└┬13:02.0-[19]      # g1x4           [8086:3518] [060400] (rev 01) PCI bridge [Normal decode]           : Intel Corporation 6311ESB/6321ESB PCI Express Downstream Port E3
││ ├─19:00.0          # g1x4           [8086:1096] [020000] (rev 01) Ethernet controller                  : Intel Corporation 80003ES2LAN Gigabit Ethernet Controller (Copper)
││ └─19:00.1          # g1x4           [8086:1096] [020000] (rev 01) Ethernet controller                  : Intel Corporation 80003ES2LAN Gigabit Ethernet Controller (Copper)
│└┬12:00.3-[1a]       # g1x8 > g1x4    [8086:350c] [060400] (rev 01) PCI bridge [Normal decode]           : Intel Corporation 6311ESB/6321ESB PCI Express to PCI-X Bridge
├─00:0f.0             # g0x0           [8086:402f] [088000] (rev 20) System peripheral                    : Intel Corporation 5400 Chipset QuickData Technology Device
├─00:10.0             #                [8086:4030] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FSB Registers
├─00:10.1             #                [8086:4030] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FSB Registers
├─00:10.2             #                [8086:4030] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FSB Registers
├─00:10.3             #                [8086:4030] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FSB Registers
├─00:10.4             #                [8086:4030] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FSB Registers
├─00:11.0             #                [8086:4031] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset CE/SF Registers
├─00:15.0             #                [8086:4035] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FBD Registers
├─00:15.1             #                [8086:4035] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FBD Registers
├─00:16.0             #                [8086:4036] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FBD Registers
├─00:16.1             #                [8086:4036] [060000] (rev 20) Host bridge                          : Intel Corporation 5400 Chipset FBD Registers
├─00:1b.0             # g0x0           [8086:269a] [040300] (rev 09) Audio device                         : Intel Corporation 631xESB/632xESB High Definition Audio Controller
├┬00:1c.0-[1b]        # g1x1 > g1x0    [8086:2690] [060400] (rev 09) PCI bridge [Normal decode]           : Intel Corporation 631xESB/632xESB/3100 Chipset PCI Express Root Port 1
├┬00:1c.1-[1c]        # g1x1 > g1x0    [8086:2692] [060400] (rev 09) PCI bridge [Normal decode]           : Intel Corporation 631xESB/632xESB/3100 Chipset PCI Express Root Port 2
├┬00:1c.2-[1d-1e]     # g1x1           [8086:2694] [060400] (rev 09) PCI bridge [Normal decode]           : Intel Corporation 631xESB/632xESB/3100 Chipset PCI Express Root Port 3
│└┬1d:00.0-[1e]       # g1x1           [104c:823e] [060400]          PCI bridge [Normal decode]           : Texas Instruments XIO2213A/B/XIO2221 PCI Express to PCI Bridge [Cheetah Express]
│ └─1e:00.0           #                [104c:823f] [0c0010]          FireWire (IEEE 1394) [OHCI]          : Texas Instruments XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express]
├┬00:1c.3-[1f]        # g1x1           [8086:2696] [060400] (rev 09) PCI bridge [Normal decode]           : Intel Corporation 631xESB/632xESB/3100 Chipset PCI Express Root Port 4
│└─1f:00.0            # g1x1           [14e4:4328] [028000] (rev 03) Network controller                   : Broadcom Inc. and subsidiaries BCM4321 802.11a/b/g/n
├─00:1d.0             #                [8086:2688] [0c0300] (rev 09) USB controller [UHCI]                : Intel Corporation 631xESB/632xESB/3100 Chipset UHCI USB Controller #1
├─00:1d.1             #                [8086:2689] [0c0300] (rev 09) USB controller [UHCI]                : Intel Corporation 631xESB/632xESB/3100 Chipset UHCI USB Controller #2
├─00:1d.2             #                [8086:268a] [0c0300] (rev 09) USB controller [UHCI]                : Intel Corporation 631xESB/632xESB/3100 Chipset UHCI USB Controller #3
├─00:1d.3             #                [8086:268b] [0c0300] (rev 09) USB controller [UHCI]                : Intel Corporation 631xESB/632xESB/3100 Chipset UHCI USB Controller #4
├─00:1d.7             #                [8086:268c] [0c0320] (rev 09) USB controller [EHCI]                : Intel Corporation 631xESB/632xESB/3100 Chipset EHCI USB2 Controller
├┬00:1e.0-[20]        #                [8086:244e] [060401] (rev d9) PCI bridge [Subtractive decode]      : Intel Corporation 82801 PCI Bridge
├─00:1f.0             #                [8086:2670] [060100] (rev 09) ISA bridge                           : Intel Corporation 631xESB/632xESB/3100 Chipset LPC Interface Controller
├─00:1f.1             #                [8086:269e] [01018f] (rev 09) IDE interface [PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering] : Intel Corporation 631xESB/632xESB IDE Controller
├─00:1f.2             #                [8086:2681] [010601] (rev 09) SATA controller [AHCI 1.0]           : Intel Corporation 631xESB/632xESB SATA AHCI Controller
└─00:1f.3             #                [8086:269b] [0c0500] (rev 09) SMBus                                : Intel Corporation 631xESB/632xESB/3100 Chipset SMBus Controller

@joevt
Copy link
Author

joevt commented Jul 24, 2020

Setup

The script should work unmodified for Linux.

DirectHW.kext is required for PowerPC Macs running Mac OS X 10.4 or 10.5 (or any Mac OS X version).
DirectHW.kext may be required for Intel Macs running macOS 10.11 El Capitan or 10.12 Sierra.
Sierra might panic if you try the darwin2 access method.
It might work for Apple Silicon Macs without DirectHW.kext using the darwin2 access method but this is untested. DirectHW.kext on Apple Silicon Macs is also untested.

The darwin and darwin2 access methods of pciutils require nvram boot-args to include debug=0x144. If it does not, then add it:
sudo nvram boot-args="debug=0x144"
This may require SIP to be disabled, otherwise execute the command without sudo in Recovery's Terminal.app.
Don't forget to include the existing contents of boot-args inside the quotes.
The value used for debug= might not matter.

Download the script

cd ~
git clone https://gist.github.com/e3cd4ff08aae06279134969c98ca3ab7.git pcitree
cd pcitree
chmod +x pcitree.sh

(Optional) Install pciutils (this example uses my fork)

If the lspci command doesn't exist already (likely for macOS but not Linux), then you need to install pciutils.

cd ~
git clone https://github.com/joevt/pciutils.git
cd pciutils
make
sudo make install
grep -q /usr/local/sbin /etc/paths || sudo sed -e $'1i\\\n/usr/local/sbin\\\n' -i "" /etc/paths
cd ~

Create a new Terminal window to start using the new commands.

Occasionally, update the pciids database:

sudo update-pciids

Test the pciutils commands (-A detect is new option in my fork):

sudo lspci -A detect
sudo lspci

Finally, try the pcitree script:

cd ~/pcitree
sudo ./pcitree.sh

@joevt
Copy link
Author

joevt commented Jul 18, 2021

I created a EFI driver called FixPCIeLinkRate.efi which also produces similar output to pcitree.sh. https://forums.macrumors.com/threads/opencore-and-the-2008-mac-pro-3-1.2287044/post-30087837
https://github.com/joevt/joevtApps

@joevt
Copy link
Author

joevt commented Dec 14, 2022

Updates

Feb 6, 2024

  • Fix column alignment.

Apr 7, 2023

  • Fixed parse of unknown prog-if
  • Moved temporary files to separate tmp directory.

Jan 30, 2023

  • Fixed list of alternate access methods.

Jan 22, 2023

  • Updated to work in Mac OS X 10.4. Now it can be used for PowerPC Macs.

Jan 3, 2023

  • Remove domain numbers if they're all the same.

Dec 14, 2022

  • Updated for latest pciutils.
  • Includes program interface in the class code columns (the numeric column and the text column).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment