18 July 2009

pcidump.c

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>

#include <linux/pci.h>
#include <asm/page.h>

/* A structure to declare how data is decoded */
struct pcidump_info {
int offset; /* the data item to retrieve */
unsigned long bitmask;
int bool; /* true or false */
char *string;
};

#define ONEBYTE 0xFF
#define TWOBYTES 0xFFFF
#define FOURBYTES 0xFFFFFFFF

struct pcidump_info dumpinfo[] = {
{0, 0, 0, "\tCompulsory registers:\n"},
{PCI_VENDOR_ID, TWOBYTES, 0, "Vendor id: 0x%04x\n"},
{PCI_DEVICE_ID, TWOBYTES, 0, "Device id: 0x%04x\n"},
{PCI_COMMAND, TWOBYTES, 0, "Command Register: 0x%04x\n"},
{PCI_STATUS, TWOBYTES, 0, "Status Register: 0x%04x\n"},
{PCI_REVISION_ID, ONEBYTE, 0, "Revision id (decimal): %i\n"},
{PCI_CLASS_PROG, ONEBYTE, 0, "Programmer Interface: 0x%02x\n"},
{PCI_CLASS_DEVICE, TWOBYTES, 0, "Class of device: 0x%04x\n"},
{PCI_HEADER_TYPE, 0x7f, 0, "Header type: 0x%02x\n"},
{PCI_HEADER_TYPE, 0x80, 1, "Multi function device: %c\n"},
{0, 0, 0, "\tOptional registers:\n"},
{PCI_CACHE_LINE_SIZE, ONEBYTE, 0, "Cache line size (decimal): %i\n"},
{PCI_LATENCY_TIMER, ONEBYTE, 0, "Latency timer (decimal): %i\n"},
{PCI_BIST, ONEBYTE, 0, "Is Built-In-Self-Test available: %c\n"},
{PCI_BASE_ADDRESS_0, FOURBYTES, 0, "Base Address 0 (B0): 0x%08x\n"},
{PCI_BASE_ADDRESS_1, FOURBYTES, 0, "Base Address 1 (B1): 0x%08x\n"},
{PCI_BASE_ADDRESS_2, FOURBYTES, 0, "Base Address 2 (B2): 0x%08x\n"},
{PCI_BASE_ADDRESS_3, FOURBYTES, 0, "Base Address 3 (B3): 0x%08x\n"},
{PCI_BASE_ADDRESS_4, FOURBYTES, 0, "Base Address 4 (B4): 0x%08x\n"},
{PCI_BASE_ADDRESS_5, FOURBYTES, 0, "Base Address 5 (B5): 0x%08x\n"},
{PCI_SUBSYSTEM_ID, TWOBYTES, 0, "Subsystem id: 0x%04x\n"},
{PCI_SUBSYSTEM_VENDOR_ID, TWOBYTES,0, "Subsystem vendor: 0x%04x\n"},
{PCI_ROM_ADDRESS, FOURBYTES, 0, "Expantion Rom base address: 0x%08x\n"},
{PCI_INTERRUPT_LINE, ONEBYTE, 0, "Interrupt line (decimal): %i\n"},
{PCI_INTERRUPT_PIN, ONEBYTE, 0, "Interrupt pin (decimal): %i\n"},
{PCI_MIN_GNT, ONEBYTE, 0, "Min bus grant time (decimal): %i\n"},
{PCI_MAX_LAT, ONEBYTE, 0, "Max bus latency acceptable (decimal): %i\n"},
{0x00, 0, 0, NULL}
};

unsigned char buffer[PAGE_SIZE];

int main(int argc, char **argv)
{
int fd, len;
char file[] = "/proc/bus/pci/00/00.0";
char *fname = file;

unsigned char *curr, *end;

if (argc>1) {
fname = argv[1];
}
if (argc != 2) {
printf("Usage: \"%s <file name>\"\n", argv[0]);
printf("\tfilename should embed binary pci configuration data\n");
printf("\tif filename is missing, \"%s\" is used\n", fname);

exit(0);
}

fd=open(fname, O_RDONLY);
if (fd<0) {
fprintf(stderr,"%s: %s: %s\n", argv[0], fname, strerror(errno));
exit(1);
}

switch (len=read(fd,buffer,PAGE_SIZE)) {
case 0:
fprintf(stderr,"%s: %s: no data\n", argv[0], fname);
exit(1);
case -1:
fprintf(stderr,"%s: %s: %s\n", argv[0], fname, strerror(errno));
exit(1);
default: break;
}
if (len < 64) {
buffer[len]='\0';
fprintf(stderr," %s: %s: %s\n", argv[0], fname, buffer);
exit(1);
}
if (len % 64) {
fprintf(stderr," %s: %s: incorrect data size: %i\n",
argv[0], fname, len);
exit(1);
}

for (end = buffer+len, curr = buffer; curr < end; curr += 256) {
struct pcidump_info *ptr;
unsigned int datum;

for (ptr = dumpinfo; ptr->string; ptr++) {
/*
* Perform a little-endian read of the item
*/
datum = curr[ptr->offset]
| (curr[ptr->offset+1]<<8)
| (curr[ptr->offset+2]<<16)
| (curr[ptr->offset+3]<<24);
datum &= ptr->bitmask;
printf(ptr->string, ptr->bool ? (datum ? 'y' : 'n') : datum);
}
printf("\n");
}
return 0;
}
lspci
gcc -o pcidump pcidump.c
./pcidump /proc/bus/pci/00/12.0
Compulsory registers:
Vendor id: 0x1022
Device id: 0x2000
Command Register: 0x0003
Status Register: 0x0280
Revision id (decimal): 16
Programmer Interface: 0x00
Class of device: 0x0200
Header type: 0x00
Multi function device: n
Optional registers:
Cache line size (decimal): 0
Latency timer (decimal): 64
Is Built-In-Self-Test available:
Base Address 0 (B0): 0x00001401
Base Address 1 (B1): 0x00000000
Base Address 2 (B2): 0x00000000
Base Address 3 (B3): 0x00000000
Base Address 4 (B4): 0x00000000
Base Address 5 (B5): 0x00000000
Subsystem id: 0x2000
Subsystem vendor: 0x1022
Expantion Rom base address: 0x00000000
Interrupt line (decimal): 9
Interrupt pin (decimal): 1
Min bus grant time (decimal): 6
Max bus latency acceptable (decimal): 255


Reference:
pcidump.c

No comments:

Post a Comment