pcireg: Add -i switch to display information. Not 100% complete yet, -d infobox will be removed once it is

This commit is contained in:
RichardG867
2021-08-17 01:21:19 -03:00
parent 98861b351c
commit 8b28da3b4c
8 changed files with 765 additions and 181 deletions

View File

@@ -19,6 +19,15 @@
#include "wlib.h"
int
comp_ui8(const void *elem1, const void *elem2)
{
uint8_t a = *((uint8_t *) elem1);
uint8_t b = *((uint8_t *) elem2);
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
}
uint32_t
pci_cf8(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg)
{

View File

@@ -68,8 +68,10 @@ void outl(uint16_t port, uint32_t data);
modify [ax cx];
#endif
/* Comparator functions. */
extern int comp_ui8(const void *elem1, const void *elem2);
/* PCI functions. */
/* PCI I/O functions. */
extern uint32_t pci_cf8(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);
extern uint8_t pci_readb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);
extern uint16_t pci_readw(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);

Binary file not shown.

Binary file not shown.

View File

@@ -11,6 +11,9 @@ PCIREG -s [-d]
PCIREG -t [-8]
∟ Display BIOS IRQ steering table. Specify -8 to display as 86Box code.
PCIREG -i [bus] device [function]
∟ Show information about the specified device.
PCIREG -r [bus] device [function] register
∟ Read the specified register.

View File

@@ -23,82 +23,192 @@ def main():
pciutil.load_pci_db()
# Start databases.
vendor_db = b''
device_db = b''
class_db = b''
string_db = struct.pack('<B', 0)
string_db_lookup = {b'': 0}
vendor_db = device_db = subdevice_db = class_db = subclass_db = progif_db = string_db = b''
vendor_devices_offset = {}
string_db_lookup = {}
vendor_has_termination = device_has_termination = class_has_termination = subclass_has_termination = progif_has_termination = False
end_entry = struct.pack('<H', 0xffff)
vendor_has_ffff = device_has_ffff = class_has_ffff = False
# Enumerate device IDs, while also going through vendor IDs.
print('Enumerating vendors and devices...')
last_vendor = None
# Enumerate device IDs, while also going through subdevice IDs.
print('Enumerating devices and subdevices...')
current_vendor_id = None
for pci_id in sorted(pciutil._pci_devices):
vendor = pciutil.clean_vendor(pciutil._pci_vendors.get(pci_id >> 16, '')).encode('cp437', 'ignore')[:256]
if not vendor:
continue
elif last_vendor != vendor:
if last_vendor != None and not device_has_ffff:
device_db += end_entry
# Check if the vendor ID has changed.
if (pci_id >> 16) != current_vendor_id:
# Add termination device entry if one isn't already present.
if current_vendor_id != None and not device_has_termination:
device_db += struct.pack('<HII', 0xffff, 0xffffffff, 0xffffffff)
# Mark this as the current vendor ID.
current_vendor_id = pci_id >> 16
# Store the device entries offset for this vendor.
vendor_devices_offset[current_vendor_id] = len(device_db)
# Enumerate this device's subdevices.
subdevice_db_pos = len(subdevice_db)
subdevice_has_termination = False
for pci_subid in sorted(pciutil._pci_subdevices.get(pci_id, {})):
# Store a null device entries offset for this vendor if one isn't already present.
subvendor_id = (pci_subid >> 16) & 0xffff
if subvendor_id not in vendor_devices_offset:
vendor_devices_offset[subvendor_id] = None
# Look up subdevice ID.
subdevice = pciutil.clean_device(pciutil._pci_subdevices[pci_id][pci_subid]).encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if subdevice:
string_db_pos = string_db_lookup.get(subdevice, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[subdevice] = len(string_db)
string_db += struct.pack('<B', len(subdevice))
string_db += subdevice
else:
string_db_pos = 0xffffffff
# Add to subdevice database.
subdevice_db += struct.pack('<HHI', subvendor_id, pci_subid & 0xffff, string_db_pos)
subdevice_has_termination = (pci_subid & 0xffff) == 0xffff
# Mark subdevice entry if there is at least one subdevice entry.
if len(subdevice_db) != subdevice_db_pos:
# Add termination subdevice entry if one isn't already present.
if not subdevice_has_termination:
subdevice_db += struct.pack('<HHI', 0xffff, 0xffff, 0xffffffff)
else:
subdevice_db_pos = 0xffffffff
# Look up device ID.
device = pciutil.clean_device(pciutil._pci_devices[pci_id]).encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if device:
string_db_pos = string_db_lookup.get(device, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[device] = len(string_db)
string_db += struct.pack('<B', len(device))
string_db += device
else:
string_db_pos = 0xffffffff
# Add to device database.
device_db += struct.pack('<HII', pci_id & 0xffff, subdevice_db_pos, string_db_pos)
device_has_termination = (pci_id & 0xffff) == 0xffff
# Enumerate vendor IDs.
print('Enumerating vendors...')
for vendor_id in sorted(vendor_devices_offset):
# Look up vendor ID.
vendor = pciutil.clean_vendor(pciutil._pci_vendors.get(vendor_id, '')).encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if vendor:
string_db_pos = string_db_lookup.get(vendor, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[vendor] = len(string_db)
string_db += struct.pack('<B', len(vendor))
string_db += vendor
else:
string_db_pos = 0xffffffff
vendor_db += struct.pack('<HII', pci_id >> 16, len(device_db), string_db_pos)
vendor_has_ffff = (pci_id >> 16) == 0xffff
# Add to vendor database.
devices_offset = vendor_devices_offset.get(vendor_id, None)
if devices_offset == None:
devices_offset = 0xffffffff
if string_db_pos != 0xffffffff and devices_offset != 0xffffffff:
vendor_db += struct.pack('<HII', vendor_id, devices_offset, string_db_pos)
vendor_has_termination = vendor_id == 0xffff
last_vendor = vendor
device = pciutil.clean_device(pciutil._pci_devices[pci_id]).encode('cp437', 'ignore')[:256]
string_db_pos = string_db_lookup.get(device, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[device] = len(string_db)
string_db += struct.pack('<B', len(device))
string_db += device
device_db += struct.pack('<HI', pci_id & 0xffff, string_db_pos)
device_has_ffff = (pci_id & 0xffff) == 0xffff
# Enumerate class-subclass IDs.
# Enumerate class IDs.
print('Enumerating classes...')
for pci_class in sorted(pciutil._pci_classes):
# Look up class ID.
class_name = pciutil._pci_classes[pci_class].encode('cp437', 'ignore')[:256]
# Add to string database if a valid result was found.
if class_name:
string_db_pos = string_db_lookup.get(class_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[class_name] = len(string_db)
string_db += struct.pack('<B', len(class_name))
string_db += class_name
else:
string_db_pos = 0xffffffff
# Add to class database.
class_db += struct.pack('<BI', pci_class, string_db_pos)
class_has_termination = pci_class == 0xff
# Enumerate subclass IDs.
print('Enumerating subclasses...')
for pci_subclass in sorted(pciutil._pci_subclasses):
class_name = pciutil._pci_subclasses[pci_subclass].encode('cp437', 'ignore')[:256]
# Look up class-subclass ID.
subclass_name = pciutil._pci_subclasses[pci_subclass].encode('cp437', 'ignore')[:256]
string_db_pos = string_db_lookup.get(class_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[class_name] = len(string_db)
string_db += struct.pack('<B', len(class_name))
string_db += class_name
# Add to string database if a valid result was found.
if subclass_name:
string_db_pos = string_db_lookup.get(subclass_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[subclass_name] = len(string_db)
string_db += struct.pack('<B', len(subclass_name))
string_db += subclass_name
else:
string_db_pos = 0xffffffff
class_db += struct.pack('<HI', pci_subclass, string_db_pos)
class_has_ffff = pci_subclass == 0xffff
# Add to subclass database.
subclass_db += struct.pack('<BBI', (pci_subclass >> 16) & 0xff, pci_subclass & 0xff, string_db_pos)
subclass_has_termination = pci_subclass == 0xffff
# Add ffff end entry to the databases if required.
if not device_has_ffff:
device_db += end_entry
if not vendor_has_ffff:
vendor_db += end_entry
if not class_has_ffff:
class_db += end_entry
# Enumerate progif IDs.
print('Enumerating progifs...')
for pci_progif in sorted(pciutil._pci_progifs):
# Look up class-subclass-progif ID.
progif_name = pciutil._pci_progifs[pci_progif].encode('cp437', 'ignore')[:256]
# Write binary file.
# Add to string database if a valid result was found.
if progif_name:
string_db_pos = string_db_lookup.get(progif_name, None)
if string_db_pos == None:
string_db_pos = string_db_lookup[progif_name] = len(string_db)
string_db += struct.pack('<B', len(progif_name))
string_db += progif_name
else:
string_db_pos = 0xffffffff
# Add to progif database.
progif_db += struct.pack('<BBBI', (pci_progif >> 16) & 0xff, (pci_progif >> 8) & 0xff, pci_progif & 0xff, string_db_pos)
progif_has_termination = pci_progif == 0xffffff
# Create binary file.
print('Writing binary database...')
f = open('PCIIDS.BIN', 'wb')
f.write(struct.pack('<III',
12 + len(vendor_db), # device DB offset
12 + len(vendor_db) + len(device_db), # class DB offset
12 + len(vendor_db) + len(device_db) + len(class_db) # string DB offset
))
f.write(vendor_db)
f.write(device_db)
f.write(class_db)
f.write(string_db)
# List all databases with their respective termination flags.
dbs = [
(vendor_db, 14, vendor_has_termination),
(device_db, 10, device_has_termination),
(subdevice_db, 8, True),
(class_db, 5, class_has_termination),
(subclass_db, 6, subclass_has_termination),
(progif_db, 7, progif_has_termination),
(string_db, None, True),
]
# Write header containing database offsets.
db_len = 4 * (len(dbs) - 1)
for db, entry_length, has_termination in dbs[:-1]:
db_len += len(db)
if not has_termination:
db_len += entry_length
f.write(struct.pack('<I', db_len))
# Write the databases themselves, adding termination if required.
for db, entry_length, has_termination in dbs:
f.write(db)
if not has_termination:
f.write(b'\xff' * entry_length)
# Finish file.
f.close()
if __name__ == '__main__':

View File

@@ -30,26 +30,94 @@
#include "wlib.h"
struct videoconfig vc;
union REGPACK rp; /* things break if this is not a global variable... */
static const char *command_flags[] = {
"I/O",
"Mem",
"Master",
"Special",
"Invalidate",
"Palette",
"Parity",
"Wait",
"SErr",
"FastBack",
"DisableINTx",
NULL,
NULL,
NULL,
NULL,
NULL,
};
static const char *status_flags[] = {
NULL,
NULL,
NULL,
"IRQ",
"CapList",
"66MHz",
"UDF",
"FastBack",
"ParityErr1",
NULL,
NULL,
"TargetAbort",
"TargetAbortAck",
"MasterAbort",
"SErr",
"ParityErr2"
};
static const char *devsel[] = {
"Fast",
"Medium",
"Slow",
"Invalid"
};
static struct videoconfig vc;
static union REGPACK rp; /* things break if this is not a global variable... */
static FILE *pciids_f = NULL;
#pragma pack(push, 0)
struct {
uint32_t dev_db_off, cls_db_off, string_db_offset;
static struct {
uint32_t device_db_offset,
subdevice_db_offset,
class_db_offset,
subclass_db_offset,
progif_db_offset,
string_db_offset;
} pciids_header;
struct {
uint16_t vendor;
uint32_t dev_off;
uint32_t string_offset;
static struct {
uint16_t vendor_id;
uint32_t devices_offset,
string_offset;
} pciids_vendor;
struct {
uint16_t device;
uint32_t string_offset;
static struct {
uint16_t device_id;
uint32_t subdevices_offset,
string_offset;
} pciids_device;
struct {
uint16_t subclass;
uint32_t string_offset;
static struct {
uint16_t subvendor_id,
subdevice_id;
uint32_t string_offset;
} pciids_subdevice;
static struct {
uint8_t class_id;
uint32_t string_offset;
} pciids_class;
static struct {
uint8_t class_id,
subclass_id;
uint32_t string_offset;
} pciids_subclass;
static struct {
uint8_t class_id,
subclass_id,
progif_id;
uint32_t string_offset;
} pciids_progif;
typedef struct {
uint8_t bus, dev;
@@ -69,21 +137,222 @@ typedef struct {
#pragma pack(pop)
char *
read_string(FILE *f, uint32_t offset)
static int
pciids_open_database()
{
/* No action is required if the file is already open. */
if (pciids_f)
return 0;
/* Open file, and stop if the open failed or the header couldn't be read. */
pciids_f = fopen("PCIIDS.BIN", "rb");
if (pciids_f && (fread(&pciids_header, sizeof(pciids_header), 1, pciids_f) < 1)) {
fclose(pciids_f);
pciids_f = NULL;
}
/* Return 0 if the file was opened successfully, 1 otherwise. */
return !pciids_f;
}
static char *
pciids_read_string(uint32_t offset)
{
uint8_t length, *buf;
fseek(f, pciids_header.string_db_offset + offset, SEEK_SET);
fread(&length, sizeof(length), 1, f);
/* Return nothing if the string offset is invalid. */
if (offset == 0xffffffff)
return NULL;
/* Open database if required. */
if (pciids_open_database())
return NULL;
/* Seek to string offset. */
fseek(pciids_f, pciids_header.string_db_offset + offset, SEEK_SET);
/* Read string length, and return nothing if it's an empty string. */
fread(&length, sizeof(length), 1, pciids_f);
if (length == 0)
return NULL;
/* Read string into buffer. */
buf = malloc(length + 1);
fread(buf, length, 1, f);
if (fread(buf, length, 1, pciids_f) < 1) {
/* Clean up and return nothing if the read failed. */
free(buf);
return NULL;
}
buf[length] = '\0';
return buf;
}
int
static int
pciids_find_vendor(uint16_t vendor_id)
{
/* Open database if required. */
if (pciids_open_database())
return 0;
/* Seek to vendor database. */
fseek(pciids_f, sizeof(pciids_header), SEEK_SET);
/* Read vendor entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_vendor, sizeof(pciids_vendor), 1, pciids_f) < 1)
break;
} while (pciids_vendor.vendor_id < vendor_id);
/* Return 1 if the ID was matched, 0 otherwise. */
return pciids_vendor.vendor_id == vendor_id;
}
static char *
pciids_get_vendor(uint16_t vendor_id)
{
/* Find vendor ID in the database, and return its name if found. */
if (pciids_find_vendor(vendor_id))
return pciids_read_string(pciids_vendor.string_offset);
/* Return nothing if the vendor ID was not found. */
return NULL;
}
static char *
pciids_get_device(uint16_t device_id)
{
/* Must be preceded by a call to {find|get}_vendor to establish the vendor ID! */
/* Open database if required. */
if (pciids_open_database())
return NULL;
/* Seek to device database entries for the established vendor. */
fseek(pciids_f, pciids_header.device_db_offset + pciids_vendor.devices_offset, SEEK_SET);
/* Read device entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_device, sizeof(pciids_device), 1, pciids_f) < 1)
break;
} while (pciids_device.device_id < device_id);
/* Return the device name if found. */
if (pciids_device.device_id == device_id)
return pciids_read_string(pciids_device.string_offset);
/* Return nothing if the device ID was not found. */
return NULL;
}
static char *
pciids_get_subdevice(uint16_t subvendor_id, uint16_t subdevice_id)
{
/* Must be preceded by calls to {find|get}_vendor and get_device to establish the vendor/device ID! */
/* Open database if required. */
if (pciids_open_database())
return NULL;
/* Seek to subdevice database entries for the established subvendor. */
fseek(pciids_f, pciids_header.subdevice_db_offset + pciids_device.subdevices_offset, SEEK_SET);
/* Read subdevice entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_subdevice, sizeof(pciids_subdevice), 1, pciids_f) < 1)
break;
} while ((pciids_subdevice.subvendor_id < subvendor_id) || (pciids_subdevice.subdevice_id < subdevice_id));
/* Return the subdevice name if found. */
if ((pciids_subdevice.subvendor_id == subvendor_id) && (pciids_subdevice.subdevice_id == subdevice_id))
return pciids_read_string(pciids_subdevice.string_offset);
/* Return nothing if the subdevice ID was not found. */
return NULL;
}
static char *
pciids_get_class(uint8_t class_id)
{
/* Open database if required. */
if (pciids_open_database())
return NULL;
/* Seek to class database. */
fseek(pciids_f, pciids_header.class_db_offset, SEEK_SET);
/* Read class entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_class, sizeof(pciids_class), 1, pciids_f) < 1)
break;
} while (pciids_class.class_id < class_id);
/* Return the class name if found. */
if (pciids_class.class_id == class_id)
return pciids_read_string(pciids_class.string_offset);
/* Return nothing if the class ID was not found. */
return NULL;
}
static char *
pciids_get_subclass(uint8_t class_id, uint8_t subclass_id)
{
/* Open database if required. */
if (pciids_open_database())
return NULL;
/* Seek to subclass database. */
fseek(pciids_f, pciids_header.subclass_db_offset, SEEK_SET);
/* Read subclass entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_subclass, sizeof(pciids_subclass), 1, pciids_f) < 1)
break;
} while ((pciids_subclass.class_id < class_id) || (pciids_subclass.subclass_id < subclass_id));
/* Return the subclass name if found. */
if ((pciids_subclass.class_id == class_id) && (pciids_subclass.subclass_id == subclass_id))
return pciids_read_string(pciids_subclass.string_offset);
/* Return nothing if the subclass ID was not found. */
return NULL;
}
static char *
pciids_get_progif(uint8_t class_id, uint8_t subclass_id, uint8_t progif_id)
{
/* Open database if required. */
if (pciids_open_database())
return NULL;
/* Seek to programming interface database. */
fseek(pciids_f, pciids_header.progif_db_offset, SEEK_SET);
/* Read programming interface entries until the ID is matched or overtaken. */
do {
if (fread(&pciids_progif, sizeof(pciids_progif), 1, pciids_f) < 1)
break;
} while ((pciids_progif.class_id < class_id) || (pciids_progif.subclass_id < subclass_id) || (pciids_progif.progif_id < progif_id));
/* Return the programming interface name if found. */
if ((pciids_progif.class_id == class_id) && (pciids_progif.subclass_id == subclass_id) && (pciids_progif.progif_id == progif_id))
return pciids_read_string(pciids_progif.string_offset);
/* Return nothing if the programming interface ID was not found. */
return NULL;
}
static int
dump_regs(uint8_t bus, uint8_t dev, uint8_t func, uint8_t start_reg, char sz)
{
int i, width, infobox, flags, bar_id;
@@ -489,7 +758,7 @@ blank:
}
int
static int
scan_bus(uint8_t bus, int nesting, char dump, FILE *f, char *buf)
{
int i, j, count, last_count, children;
@@ -539,55 +808,33 @@ scan_bus(uint8_t bus, int nesting, char dump, FILE *f, char *buf)
dev_rev_class.u32 = pci_readl(bus, dev, func, 0x08);
#endif
/* Look up vendor name in the database file. */
if (f) {
fseek(f, sizeof(pciids_header), SEEK_SET);
do {
if (fread(&pciids_vendor, sizeof(pciids_vendor), 1, f) < 1)
break;
} while (pciids_vendor.vendor < dev_id.u16[0]);
if (pciids_vendor.vendor == dev_id.u16[0]) {
/* Add vendor name to buffer. */
temp = read_string(f, pciids_vendor.string_offset);
strcat(buf, temp);
strcat(buf, " ");
free(temp);
/* Look up vendor name in the PCI ID database. */
temp = pciids_get_vendor(dev_id.u16[0]);
if (temp) {
/* Add vendor name to buffer. */
strcat(buf, temp);
strcat(buf, " ");
free(temp);
/* Look up device name. */
fseek(f, pciids_header.dev_db_off + pciids_vendor.dev_off, SEEK_SET);
do {
if (fread(&pciids_device, sizeof(pciids_device), 1, f) < 1)
break;
} while (pciids_device.device < dev_id.u16[1]);
if (pciids_device.device == dev_id.u16[1]) {
/* Add device name to buffer. */
temp = read_string(f, pciids_device.string_offset);
strcat(buf, temp);
free(temp);
} else {
/* Device name not found. */
goto unknown;
}
/* Look up device name. */
temp = pciids_get_device(dev_id.u16[1]);
if (temp) {
/* Add device name to buffer. */
strcat(buf, temp);
free(temp);
} else {
/* Vendor name not found. */
strcat(buf, "[Unknown] ");
goto unknown;
/* Device name not found. */
goto unknown_device;
}
} else {
unknown:
/* Look up class ID. */
/* Vendor name not found. */
strcat(buf, "[Unknown] ");
fseek(f, pciids_header.cls_db_off, SEEK_SET);
do {
if (fread(&pciids_class, sizeof(pciids_class), 1, f) < 1)
break;
} while (pciids_class.subclass < dev_rev_class.u16[1]);
if (pciids_class.subclass == dev_rev_class.u16[1]) {
unknown_device: /* Look up class ID. */
temp = pciids_get_class(dev_rev_class.u16[1]);
if (temp) {
/* Add class name to buffer. */
strcat(buf, "[");
temp = read_string(f, pciids_class.string_offset);
strcat(buf, temp);
strcat(buf, "]");
sprintf(&buf[strlen(buf)], "[%s]", temp);
free(temp);
} else {
/* Class name not found. */
@@ -632,8 +879,10 @@ unknown:
children--;
rp.h.dh--;
}
intr(0x10, &rp);
putchar('');
if (rp.h.dh != 0xff) {
intr(0x10, &rp);
putchar('');
}
/* Restore cursor position. */
rp.h.ah = 0x02;
@@ -689,7 +938,7 @@ unknown:
}
int
static int
scan_buses(char dump)
{
int i;
@@ -700,13 +949,6 @@ scan_buses(char dump)
buf = malloc(1024);
memset(buf, 0, 1024);
/* Initialize PCI ID database file. */
f = fopen("PCIIDS.BIN", "rb");
if (f && (fread(&pciids_header, sizeof(pciids_header), 1, f) < 1)) {
fclose(f);
f = NULL;
}
/* Get terminal size. */
_getvideoconfig(&vc);
@@ -727,42 +969,219 @@ scan_buses(char dump)
}
int
read_reg(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg)
static void
info_flags_helper(uint16_t bitfield, const char **table)
{
/* Small helper function for printing PCI command/status flags. */
int i, j;
/* Check each bit. */
j = 0;
for (i = 0; i < 16; i++) {
/* Ignore if there is no table entry. */
if (!table[i])
continue;
/* Print flag name in [brackets] if set. */
if (bitfield & (1 << i))
printf(" [%s]", table[i]);
else
printf(" %s ", table[i]);
/* Add line break and indentation after the 7th item. */
if (++j == 7) {
printf("\n ");
j = 0;
}
}
}
static int
dump_info(uint8_t bus, uint8_t dev, uint8_t func)
{
char *temp;
int i;
uint8_t header_type, subsys_reg, num_bars;
multi_t reg_val;
/* Print banner message. */
printf("Reading from PCI bus %02X device %02X function %d registers [%02X:%02X]\n",
bus, dev, func, reg | 3, reg & 0xfc);
printf("Displaying information for PCI bus %02X device %02X function %d\n",
bus, dev, func);
/* Read dword value from register. */
/* Read vendor/device ID, and stop if it's invalid. */
#ifdef DEBUG
reg_val.u32 = pci_cf8(bus, dev, func, reg);
reg_val.u32 = 0x05711106;
#else
reg_val.u32 = pci_readl(bus, dev, func, reg);
reg_val.u32 = pci_readl(bus, dev, func, 0x00);
if (!reg_val.u32 || (reg_val.u32 == 0xffffffff)) {
printf("\nNo device appears to exist here. (vendor:device %04X:%04X)",
reg_val.u16[0], reg_val.u16[1]);
return 1;
}
#endif
/* Print value as a dword and bytes. */
printf("Value: %04X%04X / %04X %04X / %02X %02X %02X %02X\n",
reg_val.u16[1], reg_val.u16[0],
reg_val.u16[0], reg_val.u16[1],
reg_val.u8[0], reg_val.u8[1], reg_val.u8[2], reg_val.u8[3]);
/* Print vendor ID. */
printf("\nVendor: [%04X] ", reg_val.u16[0]);
/* Print vendor name if found. */
temp = pciids_get_vendor(reg_val.u16[0]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
/* Print device ID. */
printf("\nDevice: [%04X] ", reg_val.u16[1]);
/* Print device name if found. */
temp = pciids_get_device(reg_val.u16[1]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
/* Read header type. We'll be using it a lot. */
header_type = pci_readb(bus, dev, func, 0x0e);
/* Determine the locations of common registers for this header type. */
switch (header_type & 0x7f) {
case 0x00: /* standard */
subsys_reg = 0x2c;
num_bars = 6;
break;
case 0x02: /* CardBus bridge */
subsys_reg = 0x40;
num_bars = 0;
break;
case 0x03: /* PCI bridge and others */
subsys_reg = 0xff;
num_bars = 2;
break;
default: /* others */
subsys_reg = 0xff;
num_bars = 0;
break;
}
if (subsys_reg != 0xff) {
/* Read subsystem ID and print it if valid. */
reg_val.u32 = pci_readl(bus, dev, func, subsys_reg);
if (reg_val.u32 && (reg_val.u32 != 0xffffffff)) {
/* Print subvendor ID. */
printf("\nSubvendor: [%04X] ", reg_val.u16[0]);
/* Print subvendor name if found. */
temp = pciids_get_vendor(reg_val.u16[0]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
/* Print subdevice ID. */
printf("\nSubdevice: [%04X] ", reg_val.u16[1]);
/* Print subdevice ID if found. */
temp = pciids_get_subdevice(reg_val.u16[0], reg_val.u16[1]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
}
}
/* Read command and status. */
reg_val.u32 = pci_readl(bus, dev, func, 0x04);
/* Print command and status flags. */
printf("\n\nCommand:");
info_flags_helper(reg_val.u16[0], command_flags);
printf("\n Status:");
info_flags_helper(reg_val.u16[1], status_flags);
printf(" DEVSEL[%s]", devsel[(reg_val.u16[1] >> 9) & 3]);
/* Read revision and class ID. */
reg_val.u32 = pci_readl(bus, dev, func, 0x08);
/* Print revision. */
printf("\n\nRevision: %02X", reg_val.u8[0]);
/* Print class ID. */
printf("\n\nClass: [%02X] ", reg_val.u8[3]);
/* Print class name if found. */
temp = pciids_get_class(reg_val.u8[3]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
/* Print subclass ID. */
printf("\n [%02X] ");
/* Print subclass name if found. */
temp = pciids_get_subclass(reg_val.u8[3], reg_val.u8[2]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
/* Print programming interface ID. */
printf("\n [%02X] ");
/* Print programming interface name if found. */
temp = pciids_get_progif(reg_val.u8[3], reg_val.u8[2], reg_val.u8[1]);
if (temp) {
printf(temp);
free(temp);
} else {
printf("[Unknown]");
}
/* Read and print BARs. */
for (i = 0; i < num_bars; i++) {
if (i == 0)
putchar('\n');
/* Read BAR. */
reg_val.u32 = pci_readl(bus, dev, func, 0x10 + (i << 2));
/* Move on to the next BAR if this one doesn't appear to be valid. */
if (!reg_val.u32 || (reg_val.u32 == 0xffffffff))
continue;
/* Print BAR index. */
printf("\nBAR %d: ", i);
/* Print BAR type and address. */
if (i & 1)
printf("I/O at %04X", reg_val.u16[0] & 0xfffc);
else
printf("Memory at %04X%04X", reg_val.u16[1], reg_val.u16[0] & 0xfff0);
}
printf("\n");
return 0;
}
int
comp_ui8(const void *elem1, const void *elem2)
{
uint8_t a = *((uint8_t *) elem1);
uint8_t b = *((uint8_t *) elem2);
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
}
int
static int
comp_irq_routing_entry(const void *elem1, const void *elem2)
{
irq_routing_entry_t *a = (irq_routing_entry_t *) elem1;
@@ -771,8 +1190,8 @@ comp_irq_routing_entry(const void *elem1, const void *elem2)
}
int
show_steering_table(char mode)
static int
dump_steering_table(char mode)
{
int i, j, entries;
uint8_t irq_bitmap[256], temp[4];
@@ -997,7 +1416,33 @@ next_entry:
}
int
static int
read_reg(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg)
{
multi_t reg_val;
/* Print banner message. */
printf("Reading from PCI bus %02X device %02X function %d registers [%02X:%02X]\n",
bus, dev, func, reg | 3, reg & 0xfc);
/* Read dword value from register. */
#ifdef DEBUG
reg_val.u32 = pci_cf8(bus, dev, func, reg);
#else
reg_val.u32 = pci_readl(bus, dev, func, reg);
#endif
/* Print value as a dword and bytes. */
printf("Value: %04X%04X / %04X %04X / %02X %02X %02X %02X\n",
reg_val.u16[1], reg_val.u16[0],
reg_val.u16[0], reg_val.u16[1],
reg_val.u8[0], reg_val.u8[1], reg_val.u8[2], reg_val.u8[3]);
return 0;
}
static int
write_reg(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, char *val)
{
uint16_t data_port;
@@ -1111,6 +1556,9 @@ usage:
printf("PCIREG -t [-8]\n");
printf("∟ Display BIOS IRQ steering table. Specify -8 to display as 86Box code.\n");
printf("\n");
printf("PCIREG -i [bus] device [function]\n");
printf("∟ Show information about the specified device.\n");
printf("\n");
printf("PCIREG -r [bus] device [function] register\n");
printf("∟ Read the specified register.\n");
printf("\n");
@@ -1155,9 +1603,9 @@ usage:
} else if (argv[1][1] == 't') {
/* Steering table display only requires a single optional parameter. */
if ((argc >= 3) && (strlen(argv[2]) > 1))
return show_steering_table(argv[2][1]);
return dump_steering_table(argv[2][1]);
else
return show_steering_table('\0');
return dump_steering_table('\0');
} else if ((argc >= 3) && (strlen(argv[1]) > 1)) {
/* Read second parameter as a dword. */
nonhex = 0;
@@ -1186,10 +1634,13 @@ usage:
goto usage;
}
if (argv[1][1] == 'd') {
/* Process parameters for a register dump. */
if ((argv[1][1] == 'd') || (argv[1][1] == 'i')) {
/* Process parameters for a register or information dump. */
switch (hexargc) {
case 4:
/* Specifying a register is not valid on an information dump. */
if (argv[1][1] == 'i')
goto usage;
reg = hexargv[3];
/* fall-through */
@@ -1215,7 +1666,15 @@ usage:
}
/* Start the operation. */
return dump_regs(bus, dev, func, reg, argv[1][2]);
switch (argv[1][1]) {
case 'd':
/* Start register dump. */
return dump_regs(bus, dev, func, reg, argv[1][2]);
case 'i':
/* Start information dump. */
return dump_info(bus, dev, func);
}
} else {
/* Subtract value parameter from a write operation. */
if (argv[1][1] == 'w')

View File

@@ -18,17 +18,15 @@
import re, urllib.request
clean_device_abbr = [
('100Base-T', 'FE'),
('100Base-TX', 'FE'),
('100Base-TX?', 'FE'),
('1000Base-T', 'GbE'),
('Acceleration', 'Accel.'),
('Accelerator', 'Accel.'),
('Accelerat(?:ion|or)', 'Accel.'),
('Alert on LAN', 'AoL'),
('Chipset Family', 'Chipset'),
('Chipset Graphics', 'iGPU'),
('Connection', 'Conn.'),
('DECchip', ''),
('Dual Port', '2-port'),
('Dual (Lane|Port)', '2-\\2'),
('Fast Ethernet', 'FE'),
('Fibre Channel', 'FC'),
('Function', 'Func.'),
@@ -42,25 +40,21 @@ clean_device_abbr = [
('Input/Output', 'I/O'),
('Integrated ([^\s]+) Graphics', '\\2 iGPU'), # VIA CLE266
('Integrated Graphics', 'iGPU'),
('([0-9]) lane', '\\2-lane'),
('([0-9]) (lane|port)', '\\2-\\3'),
('Local Area Network', 'LAN'),
('Low Pin Count', 'LPC'),
('Memory Controller Hub', 'MCH'),
('Network Adapter', 'NIC'),
('Network (?:Interface )?Card', 'NIC'),
('Network (?:Interface )?Controller', 'NIC'),
('Network (?:Interface )?(?:Adapter|Card|Controller)', 'NIC'),
('NVM Express', 'NVMe'),
('Parallel ATA', 'PATA'),
('PCI-E', 'PCIe'),
('PCI Express', 'PCIe'),
('PCI[- ]to[- ]PCI', 'PCI-PCI'),
('PCI(?:-E| Express)', 'PCIe'),
('([^- ]+)[- ]to[- ]([^- ]+)', '\\2-\\3'),
('Platform Controller Hub', 'PCH'),
('([0-9]) port', '\\2-port'),
('Processor Graphics', 'iGPU'),
('Quad Port', '4-port'),
('Quad (Lane|Port)', '4-\\2'),
('Serial ATA', 'SATA'),
('Serial Attached SCSI', 'SAS'),
('Single Port', '1-port'),
('Single (Lane|Port)', '1-\\2'),
('USB ?([0-9])\\.0', 'USB\\2'),
('USB ?([0-9])\\.[0-9] ?Gen([0-9x]+)', 'USB\\2.\\3'),
('USB ?([0-9]\\.[0-9])', 'USB\\2'),
@@ -69,7 +63,7 @@ clean_device_abbr = [
('Wireless LAN', 'WLAN'),
]
clean_device_bit_pattern = re.compile('''( |^|\(|\[|\{|/)(?:([0-9]{1,4}) )?(?:(K)(?:ilo)?|(M)(?:ega)?|(G)(?:iga)?)bit( |$|\)|\]|\})''', re.I)
clean_device_group_pattern = re.compile('''\\\\([0-9]+)''')
clean_device_doubleabbr_pattern = re.compile('''( |^|\(|\[|\{|/)([^ \(\[\{/]+) (?: |\(|\[|\{|/)\\2(?: |\)|\]|\})( |$|\)|\]|\})''')
clean_device_suffix_pattern = re.compile(''' (?:Adapter|Card|Device|(?:Host )?Controller)( (?: [0-9#]+)?|$|\)|\]|\})''', re.I)
clean_vendor_abbr_pattern = re.compile(''' \[([^\]]+)\]''')
clean_vendor_suffix_pattern = re.compile(''' (?:Semiconductors?|(?:Micro)?electronics?|Interactive|Technolog(?:y|ies)|(?:Micro)?systems|Computer(?: works)?|Products|Group|and subsidiaries|of(?: America)?|Co(?:rp(?:oration)?|mpany)?|Inc|LLC|Ltd|GmbH|AB|AG|SA|(?:\(|\[|\{).*)$''', re.I)
@@ -92,6 +86,7 @@ clean_vendor_final = {
_clean_device_abbr_cache = []
_pci_vendors = {}
_pci_devices = {}
_pci_subdevices = {}
_pci_classes = {}
_pci_subclasses = {}
_pci_progifs = {}
@@ -103,14 +98,15 @@ def clean_device(device, vendor=None):
if not _clean_device_abbr_cache:
for pattern, replace in clean_device_abbr:
_clean_device_abbr_cache.append((
re.compile('''( |^|\(|\[|\{|/)''' + pattern + '''( |$|\)|\]|\})''', re.I),
'\\g<1>' + replace + '\\g<' + str(1 + len(clean_device_group_pattern.findall(pattern))) + '>',
re.compile('''(?P<prefix> |^|\(|\[|\{|/)''' + pattern + '''(?P<suffix> |$|\)|\]|\})''', re.I),
'\\g<prefix>' + replace + '\\g<suffix>',
))
# Apply patterns.
device = clean_device_bit_pattern.sub('\\1\\2\\3\\4\\5bit\\6', device)
for pattern, replace in _clean_device_abbr_cache:
device = pattern.sub(replace, device)
device = clean_device_doubleabbr_pattern.sub('\\1\\2\\3', device)
device = clean_device_suffix_pattern.sub('\\1', device)
# Remove duplicate vendor ID.
@@ -193,6 +189,11 @@ def load_pci_db():
elif line[1] != 9: # device
device = (vendor << 16) | int(line[1:5], 16)
_pci_devices[device] = line[7:-1].decode('utf8', 'ignore')
else: # subdevice
subdevice = (int(line[2:6], 16) << 16) | int(line[7:11], 16)
if device not in _pci_subdevices:
_pci_subdevices[device] = {}
_pci_subdevices[device][subdevice] = line[13:-1].decode('utf8', 'ignore')
f.close()