Skip to content

Commit

Permalink
pcireg: Use libpci lookup if our own database isn't available
Browse files Browse the repository at this point in the history
  • Loading branch information
richardg867 committed Oct 25, 2024
1 parent 08ced83 commit be6d0e6
Showing 1 changed file with 73 additions and 20 deletions.
93 changes: 73 additions & 20 deletions pcireg/pcireg.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@ static struct PACKED {
# pragma pack(pop)
#endif

static int pciids_cur_vendor;
static int pciids_cur_device;
static int pciids_cur_vendor = -1;
static int pciids_cur_device = -1;
static char *pciids_lookup;
#ifdef PCI_LIB_VERSION
static char pciids_buf[256];
#endif
#pragma pack(push, 1)
static struct PACKED {
uint16_t vendor_id;
Expand Down Expand Up @@ -297,18 +301,26 @@ pciids_get_vendor(uint16_t vendor_id)
if (find_vendor(vendor_id))
return pciids_read_string(pciids_vendor[pciids_cur_vendor].string_offset);

#ifdef PCI_LIB_VERSION
/* Find vendor ID in the system pci.ids. */
pciids_cur_vendor = -1;
pciids_lookup = pci_lookup_name(pacc, pciids_buf, sizeof(pciids_buf), PCI_LOOKUP_VENDOR | PCI_LOOKUP_NO_NUMBERS, vendor_id);
#else
pciids_lookup = NULL;
#endif

/* Return nothing if the vendor ID was not found. */
return NULL;
return pciids_lookup;
}

static char *
pciids_get_device(uint16_t device_id)
pciids_get_device(uint16_t vendor_id, 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((void **) &pciids_device, 'D'))
return NULL;
if ((pciids_cur_vendor < 0) || pciids_open_database((void **) &pciids_device, 'D'))
goto no_device_db;

/* Go through device entries until the ID is matched or overtaken. */
for (pciids_cur_device = pciids_vendor[pciids_cur_vendor].devices_offset; pciids_device[pciids_cur_device].device_id < device_id; pciids_cur_device++)
Expand All @@ -318,19 +330,28 @@ pciids_get_device(uint16_t device_id)
if (pciids_device[pciids_cur_device].device_id == device_id)
return pciids_read_string(pciids_device[pciids_cur_device].string_offset);

no_device_db:
#ifdef PCI_LIB_VERSION
/* Find device ID in the system pci.ids. */
pciids_cur_device = -1;
pciids_lookup = pci_lookup_name(pacc, pciids_buf, sizeof(pciids_buf), PCI_LOOKUP_DEVICE | PCI_LOOKUP_NO_NUMBERS, vendor_id, device_id);
#else
pciids_lookup = NULL;
#endif

/* Return nothing if the device ID was not found. */
return NULL;
return pciids_lookup;
}

static char *
pciids_get_subdevice(uint16_t subvendor_id, uint16_t subdevice_id)
pciids_get_subdevice(uint16_t vendor_id, uint16_t device_id, 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! */
int i;

/* Open database if required. */
if (pciids_open_database((void **) &pciids_subdevice, 'S'))
return NULL;
if ((pciids_cur_device < 0) || pciids_open_database((void **) &pciids_subdevice, 'S'))
goto no_subdevice_db;

/* Go through subdevice entries until the ID is matched or overtaken. */
for (i = pciids_device[pciids_cur_device].subdevices_offset; (pciids_subdevice[i].subvendor_id < subvendor_id) || (pciids_subdevice[i].subdevice_id < subdevice_id); i++)
Expand All @@ -340,8 +361,16 @@ pciids_get_subdevice(uint16_t subvendor_id, uint16_t subdevice_id)
if ((pciids_subdevice[i].subvendor_id == subvendor_id) && (pciids_subdevice[i].subdevice_id == subdevice_id))
return pciids_read_string(pciids_subdevice[i].string_offset);

no_subdevice_db:
#ifdef PCI_LIB_VERSION
/* Find subdevice ID in the system pci.ids. */
pciids_lookup = pci_lookup_name(pacc, pciids_buf, sizeof(pciids_buf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_DEVICE | PCI_LOOKUP_NO_NUMBERS, vendor_id, device_id, subvendor_id, subdevice_id);
#else
pciids_lookup = NULL;
#endif

/* Return nothing if the subdevice ID was not found. */
return NULL;
return pciids_lookup;
}

static char *
Expand All @@ -351,7 +380,7 @@ pciids_get_class(uint8_t class_id)

/* Open database if required. */
if (pciids_open_database((void **) &pciids_class, 'C'))
return NULL;
goto no_class_db;

/* Go through class entries until the ID is matched or overtaken. */
for (i = 0; pciids_class[i].class_id < class_id; i++)
Expand All @@ -361,8 +390,16 @@ pciids_get_class(uint8_t class_id)
if (pciids_class[i].class_id == class_id)
return pciids_read_string(pciids_class[i].string_offset);

no_class_db:
#ifdef PCI_LIB_VERSION
/* Find class ID in the system pci.ids. */
pciids_lookup = pci_lookup_name(pacc, pciids_buf, sizeof(pciids_buf), PCI_LOOKUP_CLASS | PCI_LOOKUP_NO_NUMBERS, (class_id << 8) | 0x80); /* no way to look up by class without subclass, but several classes repeat their name in subclass 80 */
#else
pciids_lookup = NULL;
#endif

/* Return nothing if the class ID was not found. */
return NULL;
return pciids_lookup;
}

static char *
Expand All @@ -372,7 +409,7 @@ pciids_get_subclass(uint8_t class_id, uint8_t subclass_id)

/* Open database if required. */
if (pciids_open_database((void **) &pciids_subclass, 'U'))
return NULL;
goto no_subclass_db;

/* Go through subclass entries until the ID is matched or overtaken. */
for (i = 0; (pciids_subclass[i].class_id < class_id) || (pciids_subclass[i].subclass_id < subclass_id); i++)
Expand All @@ -382,8 +419,16 @@ pciids_get_subclass(uint8_t class_id, uint8_t subclass_id)
if ((pciids_subclass[i].class_id == class_id) && (pciids_subclass[i].subclass_id == subclass_id))
return pciids_read_string(pciids_subclass[i].string_offset);

no_subclass_db:
#ifdef PCI_LIB_VERSION
/* Find subclass ID in the system pci.ids. */
pciids_lookup = pci_lookup_name(pacc, pciids_buf, sizeof(pciids_buf), PCI_LOOKUP_CLASS | PCI_LOOKUP_NO_NUMBERS, (class_id << 8) | subclass_id);
#else
pciids_lookup = NULL;
#endif

/* Return nothing if the subclass ID was not found. */
return NULL;
return pciids_lookup;
}

static char *
Expand All @@ -393,7 +438,7 @@ pciids_get_progif(uint8_t class_id, uint8_t subclass_id, uint8_t progif_id)

/* Open database if required. */
if (pciids_open_database((void **) &pciids_progif, 'P'))
return NULL;
goto no_progif_db;

/* Go through programming interface entries until the ID is matched or overtaken. */
for (i = 0; (pciids_progif[i].class_id < class_id) || (pciids_progif[i].subclass_id < subclass_id) || (pciids_progif[i].progif_id < progif_id); i++)
Expand All @@ -403,8 +448,16 @@ pciids_get_progif(uint8_t class_id, uint8_t subclass_id, uint8_t progif_id)
if ((pciids_progif[i].class_id == class_id) && (pciids_progif[i].subclass_id == subclass_id) && (pciids_progif[i].progif_id == progif_id))
return pciids_read_string(pciids_progif[i].string_offset);

no_progif_db:
#ifdef PCI_LIB_VERSION
/* Find programming interface ID in the system pci.ids. */
pciids_lookup = pci_lookup_name(pacc, pciids_buf, sizeof(pciids_buf), PCI_LOOKUP_PROGIF | PCI_LOOKUP_NO_NUMBERS, (class_id << 8) | subclass_id, progif_id);
#else
pciids_lookup = NULL;
#endif

/* Return nothing if the programming interface ID was not found. */
return NULL;
return pciids_lookup;
}

static int
Expand Down Expand Up @@ -650,7 +703,7 @@ scan_bus(uint8_t bus, unsigned int nesting, char *nesting_buf, char dump, char *
i -= printf("%s ", temp);

/* Look up device name. */
temp = pciids_get_device(dev_id.u16[1]);
temp = pciids_get_device(dev_id.u16[0], dev_id.u16[1]);
if (temp)
strcpy(&buf[strlen(buf)], temp);
else /* name not found */
Expand Down Expand Up @@ -828,7 +881,7 @@ dump_info(uint8_t bus, uint8_t dev, uint8_t func)
printf("\nDevice: [%04X] ", reg_val.u16[1]);

/* Print device name if found. */
temp = pciids_get_device(reg_val.u16[1]);
temp = pciids_get_device(i = reg_val.u16[0], j = reg_val.u16[1]);
if (temp)
printf("%s", temp ? temp : "[Unknown]");

Expand Down Expand Up @@ -876,7 +929,7 @@ dump_info(uint8_t bus, uint8_t dev, uint8_t func)
printf("\nSubdevice: [%04X] ", reg_val.u16[1]);

/* Print subdevice ID if found. */
temp = pciids_get_subdevice(reg_val.u16[0], reg_val.u16[1]);
temp = pciids_get_subdevice(i, j, reg_val.u16[0], reg_val.u16[1]);
printf("%s", temp ? temp : "[Unknown]");
}
}
Expand Down

0 comments on commit be6d0e6

Please sign in to comment.