Created
August 22, 2019 14:34
-
-
Save ross-newman/1e02d36b0a1b8d927632e57581262626 to your computer and use it in GitHub Desktop.
IDT PCIe Switch probing with busybox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## Determine architecture | |
arch=$(arch) | |
if [ "$arch" == "ppc" ]; then | |
echo "PowerPC Host detected" | |
## When one card installed | |
dev0mem0=0xf80300000 | |
## When no card installed | |
# dev0mem0=0xf80100000 | |
else | |
# Assume Intel x86 host | |
echo "Intel Host detected not supported" | |
exit -1 | |
fi | |
size=$1 | |
value=0xdeadbeef | |
function bswap32() { | |
value=$(printf "0x%08x" $(($bar + $1)) ) | |
# Check if PPC host and endian swap | |
if [ "$arch" == "ppc" ]; then | |
value=$(echo 0x${value:8:2}${value:6:2}${value:4:2}${value:2:2}) | |
fi | |
} | |
function bswap16() { | |
value=$(printf "0x%04x" $(($bar + $1)) ) | |
# Check if PPC host and endian swap | |
if [ "$arch" == "ppc" ]; then | |
value=$(echo 0x${value:4:2}${value:2:2}) | |
fi | |
} | |
function globalAddressSpaceRead() { | |
register=$(printf "0x%04x" $1 ) | |
comment="$2" | |
registers=$4 | |
portmode="" | |
GASAADDR=$(($dev0mem0 + 0xFF8)) | |
GASADATA=$(($dev0mem0 + 0xFFC)) | |
## Manage endianness | |
bswap32 $register | |
$(busybox devmem $GASAADDR 32 $value) | |
data=$(busybox devmem $GASADATA 32) | |
bswap32 $data | |
printf "0x%04x 0x%08x %s\n" $1 $value "$comment" | |
## Print extra stuff depending on register range | |
if [ "$registers" == "1" ]; then | |
## Print some extra info | |
case "$3" in | |
1) printf "\t\e[1;31mPciStatus : 0x%04x\e[m\n" $((($value >> 16) & 0xff)) ;; ## Red | |
16) if [ $(( $value >> 20 & 0xf )) == 5 ]; then | |
dir="Upstream" | |
else | |
dir="Downstream" | |
fi | |
printf "\tLinkCap %s port \n" $dir | |
;; | |
18) printf "\t\e[1;31mPciDevStatus : 0x%04x\e[m\n" $((($value >> 16) & 0xff)) ;; | |
19) printf "\tLinkCap Width x%d Gen%d Port %d\n" $((($value >> 4) & 0xf)) $(($value & 0xf)) $((($value >> 24) & 0xff)) ;; | |
20) printf "\t\e[1;32mLinkSta Width x%d Gen%d\e[m\n" $((($value >> 20) & 0xf)) $(($value >> 16 & 0xf)) ;; | |
esac | |
fi | |
if [ "$registers" == "6" ]; then | |
## Print some extra info | |
case "$3" in | |
0) | |
case $(($value & 0xf)) in | |
0) portmode="Disabled" ;; | |
1) portmode="Downstream switch port" ;; | |
2) portmode="Upstream switch port" ;; | |
3) portmode="NT function" ;; | |
4) portmode="Upstream switch port with NT function" ;; | |
5) portmode="Unattached" ;; | |
6) portmode="Upstream switch port with DMA function" ;; | |
7) portmode="Upstream switch port with NT and DMA functions" ;; | |
8) portmode="NT with DMA function" ;; | |
esac | |
printf "\tPortMode : %s\n" "$portmode" | |
printf "\tDeviceNumber : 0x%x\n" $((($value >> 10) & 0x1f)) | |
;; | |
1) | |
up=$((($value >> 4) & 0x1)) | |
if [ $up == "1" ]; then | |
printf "\e[1;32m" | |
else | |
printf "\e[1;31m" | |
fi | |
if [ $((($value >> 5) & 0x1)) == "0" ]; then | |
linkmode="Upstream" | |
else | |
linkmode="Downstream" | |
fi | |
case $((($value >> 6) & 0xf)) in | |
0) portmode="Disabled" ;; | |
1) portmode="Downstream switch port" ;; | |
2) portmode="Upstream switch port" ;; | |
3) portmode="NT function" ;; | |
4) portmode="Upstream switch port with NT function" ;; | |
5) portmode="Unattached" ;; | |
6) portmode="Upstream switch port with DMA function" ;; | |
7) portmode="Upstream switch port with NT and DMA functions" ;; | |
8) portmode="NT with DMA function" ;; | |
esac | |
printf "\tLinkUp : 0x%s\n" $up | |
printf "\tLinkMode : %s\n" "$linkmode" | |
printf "\tPortMode : %s (0x%x)\n" "$portmode" $((($value >> 6) & 0xf)) | |
printf "\tDeviceNumber : 0x%x\n" $((($value >> 16) & 0x1f)) | |
printf "\e[m" | |
;; | |
esac | |
fi | |
if [ "$registers" == "7" ]; then | |
## Print some extra info | |
case "$3" in | |
1) | |
printf "\tTempreture : %f Degrees C\n" $((($value & 0xff) >> 1)) | |
;; | |
esac | |
fi | |
} | |
## Dump Global Address Space Registers | |
function globalAddressSpaceDump() { | |
field=$1 | |
length=$(($2-1)) | |
registers=$3 | |
for i in $( eval echo {0..$length}) | |
do | |
comment="" | |
if [ $registers == "1" ]; then | |
case "$i" in | |
0) comment="DID - Device Identification Register (0x0000) / VID - Vendor Identification Register (0x111D)" ;; | |
1) comment="PCISTS - PCI Status Register (0x0000) / PCICMD - PCI Command Register (0x0000)" ;; | |
2) comment="CCODE - Class Code Register (0x00) / RID - Revision Identification Register (0x00)" ;; | |
3) comment="PLTIMER - Primary Latency Timer (0x00) / CLS - Cache Line Size Register (0x00) / HDR - Header Type Register (0x00) / BIST - Built-in Self Test Register" ;; | |
4) comment="BAR0 - Base Address Register 0" ;; | |
5) comment="BAR0 - Base Address Register 1" ;; | |
6) comment="PBUSN - Primary Bus Number Register / SBUSN - Secondary Bus Number Register" ;; | |
16) comment="PCIECAP - PCI Express Capability" ;; | |
17) comment="PCIEDCAP - PCI Express Device Capabilities" ;; | |
18) comment="PCIEDSTS - PCI Express Device Status / PCIEDCTL - PCI Express Device Control" ;; | |
19) comment="PCIELCAP - PCI Express Link Capabilities" ;; | |
20) comment="PCIELSTS - PCI Express Link Status / PCIELCTL - PCI Express Link Control" ;; | |
esac | |
fi | |
if [ $registers == "2" ]; then | |
case "$i" in | |
0) comment="SWCTL - Switch Control" ;; | |
1) comment="BCVSTS - Boot Configuration Vector Status" ;; | |
2) comment="PCLKMODE - Port Clocking Mode" ;; | |
3) comment="(undefined)" ;; | |
4) comment="STK0CFG - Stack Configuration" ;; | |
5) comment="STK1CFG - Stack Configuration" ;; | |
6) comment="STK2CFG - Stack Configuration" ;; | |
7) comment="STK3CFG - Stack Configuration" ;; | |
esac | |
fi | |
if [ $registers == "3" ]; then | |
case "$i" in | |
0) comment="RDRAINDELAY - Reset Drain Delay" ;; | |
1) comment="POMCDELAY - Port Operating Mode Change Drain Delay" ;; | |
2) comment="(undefined)" ;; | |
3) comment="SEDELAY - Side Effect Delay" ;; | |
esac | |
fi | |
if [ $registers == "6" ]; then | |
case "$i" in | |
0) comment="SWPORT[23:0]CTL - Switch Port x Control" ;; | |
1) comment="SWPORT[23:0]STS - Switch Port x Status" ;; | |
esac | |
fi | |
if [ $registers == "7" ]; then | |
case "$i" in | |
0) comment="TMPCTL - Temperature Sensor Control" ;; | |
1) comment="TMPSTS - Temperature Sensor Status" ;; | |
esac | |
fi | |
reg=$(($field+($i*4))) | |
globalAddressSpaceRead $reg "$comment" $i $registers | |
if [ $i == "0" ]; then | |
if [ $registers == "1" ]; then | |
if [ $value == "0x00000000" ]; then | |
# First register should not be zero | |
return 0 | |
fi | |
fi | |
fi | |
done | |
} | |
## Dump the PCI Configuration Space | |
function dump() { | |
mem=$1 | |
width=16 | |
stride=2 | |
adjustment=0 | |
for i in {0..64} | |
do | |
comment="" | |
case "$i" in | |
0) comment='VID Vendor Identification Register (0x111D)';; | |
1) comment="DID - Device Identification Register (-)" ;; | |
2) comment="PCICMD - PCI Command Register (0x0000)" ;; | |
3) comment="PCISTS - PCI Status Register (0x00)" ;; | |
4) comment="RID - Revision Identification Register (-) / CCODE - Class Code Register (-)" ;; | |
5) comment="(undefined)" ;; | |
6) comment="CLS - Cache Line Size Register (0x00) / PLTIMER - Primary Latency Timer (0x00)" ;; | |
7) comment="HDR - Header Type Register (0x00) / BIST - Built-in Self Test Register (0x00)" ;; | |
8) comment="BAR0 - Base Address Register 0 (0x0000)" ;; | |
9) comment="BAR0 - Base Address Register 0 (0x0000)" ;; | |
10) comment="BAR1 - Base Address Register 1 (0x0000)" ;; | |
11) comment="BAR1 - Base Address Register 1 (0x0000)" ;; | |
12) comment="PBUSN - Primary Bus Number Register (0x00) / SBUSN - Secondary Bus Number Register (0x0000)" ;; | |
13) comment="SUBUSN - Subordinate Bus Number Register (0x00) / SLTIMER - Secondary Latency Timer Register (0x0000)" ;; | |
14) comment="IOBASE - I/O Base Register (0x00) / IOLIMIT - I/O Limit Registerr (0x0000)" ;; | |
15) comment="SECSTS - Secondary Status Register (0x0000)" ;; | |
16) comment="MBASE - Memory Base Register (0xFFF0)" ;; | |
32) comment="PCIECAP - PCI Express Capability" ;; | |
33) comment="PCIEDCAP - PCI Express Device Capabilities" ;; | |
34) comment="PCIEDCTL - PCI Express Device Control" ;; | |
35) comment="PCIECAP - PCI Express Capability" ;; | |
esac | |
if [ "$i" == "0" ]; then | |
printf "\nPCI Configuration Space\n" | |
printf "=======================\n" | |
fi | |
if [ "$i" == "32" ]; then | |
printf "\nPCI Express Capabilities Header\n" | |
printf "===============================\n" | |
width=32 | |
stride=4 | |
adjustment=0x40 | |
fi | |
currentAddr=$(($mem+i*$stride-$adjustment)) | |
value=$(busybox devmem $currentAddr $width) | |
if [ "$stride" == "2" ]; then | |
bswap16 $value | |
else | |
bswap32 $value | |
fi | |
if [ $stride == "4" ]; then | |
printf "0x%03x 0x%08x 0x%08x %s\n" $(($i*2)) $currentAddr $value "$comment" | |
else | |
printf "0x%03x 0x%08x 0x%04x %s\n" $(($i*2)) $currentAddr $value "$comment" | |
fi | |
done | |
} | |
## Dump Proprietary Port Specific Registers | |
function dumpPortSpecific() { | |
port=$1 | |
mem=$(($2 + $3)) | |
offset=$3 | |
stride=4 | |
for i in {0..64} | |
do | |
comment="" | |
case "$i" in | |
0) comment="PORTCTL - Port Control (0x0000) / P2PINTSTS - PCI-to-PCI Bridge Interrupt Status (0x0000)";; | |
1) comment="P2PINTSTS - PCI-to-PCI Bridge Interrupt Status (0x00000000)";; | |
2) comment="P2PINTMSK - PCI-to-PCI Bridge Interrupt Mask (0x00000000)";; | |
3) comment="(undefined)";; | |
4) comment="P2PSDATA - PCI-to-PCI Bridge Signal Data (0x00000000)";; | |
5) comment="P2PGSIGNAL - PCI-to-PCI Bridge Global Signal (0x00000000)";; | |
6) comment="(undefined)";; | |
7) comment="(undefined)";; | |
8) comment="(undefined)";; | |
9) comment="PAERMSK - Port AER Mask";; | |
10) comment="(undefined)";; | |
11) comment="(undefined)";; | |
12) comment="PCIESCTLIV - PCI Express Slot Control Initial Value";; | |
esac | |
if [ "$i" == "0" ]; then | |
printf "\nProprietary Port Specific Registers\n" | |
printf "===================================\n" | |
fi | |
currentAddr=$(($mem+i*$stride)) | |
value=$(busybox devmem $currentAddr $width) | |
bswap32 $value | |
printf "0x%03x 0x%08x 0x%08x %s\n" $(($offset+$i*$stride)) $currentAddr $value "$comment" | |
done | |
} | |
#lspci -d 111d:808e -nn -v -xxx | |
lspci -s 01:00.1 -nn -v -xxx | |
portSpecificRegisterOffset=0x400 | |
## Dump PCI configuration | |
dump $dev0mem0 | |
## Dump Proprietary Port Specific Registers | |
dumpPortSpecific 0 $dev0mem0 $portSpecificRegisterOffset | |
## Dump Global Address Space | |
globalAddressSpaceRead 0x1000 | |
## Dump all 24 Ports | |
for i in {0..23} | |
do | |
printf "\nGlobal Address Space - Port %d PCI-to-PCI Bridge Registers\n" $i | |
printf "===========================================================\n" | |
globalAddressSpaceDump $(($i*0x4000)) 32 1 | |
done | |
printf "\nGlobal Address Space - Configuration Status Registers\n" $i | |
printf "=======================================================\n" | |
globalAddressSpaceDump 0x3e000 8 2 | |
printf "\nGlobal Address Space - \n" $i | |
printf "========================\n" | |
globalAddressSpaceDump 0x3e080 8 3 | |
printf "\nGlobal Address Space - Switch Partition\n" $i | |
printf "=========================================\n" | |
globalAddressSpaceDump 0x3e100 4 4 | |
## Dump all 24 Ports | |
for i in {0..23} | |
do | |
printf "\nGlobal Address Space - Port %d Status and Control\n" $i | |
printf "==================================================\n" | |
globalAddressSpaceDump $(($i*0x0020+0x3e200)) 3 6 | |
done | |
printf "\nGlobal Address Space - Tempreture\n" $i | |
printf "====================================================\n" | |
globalAddressSpaceDump 0x3f1d4 2 7 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Specifically for the IDT® 89HPES24NT24G2 PCI Express® Switch
Registers as per User Manual IDT_89H24NT24G2_MAN_20140822.pdf August 2014