Create PCI_MATCH and pci_match_device

Create a covenience function to match PCI device IDs. It's about 15
years overdue.

Differential Revision: https://reviews.freebsd.org/D15999
This commit is contained in:
Warner Losh 2018-07-07 15:25:11 +00:00
parent f06b6fdcb1
commit 971b5f7632
3 changed files with 98 additions and 1 deletions

View File

@ -273,6 +273,7 @@ linsysfs_fill_vgapci(PFS_FILL_ARGS)
return (0);
}
#undef PCI_DEV
#define PCI_DEV "pci"
#define DRMN_DEV "drmn"
static int

View File

@ -6244,3 +6244,39 @@ pcie_flr(device_t dev, u_int max_delay, bool force)
pci_printf(&dinfo->cfg, "Transactions pending after FLR!\n");
return (true);
}
const struct pci_device_table *
pci_match_device(device_t child, const struct pci_device_table *id, size_t nelt)
{
bool match;
uint16_t vendor, device, subvendor, subdevice, class, subclass, revid;
vendor = pci_get_vendor(child);
device = pci_get_device(child);
subvendor = pci_get_subvendor(child);
subdevice = pci_get_subdevice(child);
class = pci_get_class(child);
subclass = pci_get_subclass(child);
revid = pci_get_revid(child);
while (nelt-- > 0) {
match = true;
if (id->match_flag_vendor)
match &= vendor == id->vendor;
if (id->match_flag_device)
match &= device == id->device;
if (id->match_flag_subvendor)
match &= subvendor == id->subvendor;
if (id->match_flag_subdevice)
match &= subdevice == id->subdevice;
if (id->match_flag_class)
match &= class == id->class_id;
if (id->match_flag_subclass)
match &= subclass == id->subclass;
if (id->match_flag_revid)
match &= revid == id->revid;
if (match)
return (id);
id++;
}
return (NULL);
}

View File

@ -259,6 +259,66 @@ typedef struct {
extern uint32_t pci_numdevs;
struct pci_device_table {
#if BYTE_ORDER == LITTLE_ENDIAN
uint16_t
match_flag_vendor:1,
match_flag_device:1,
match_flag_subvendor:1,
match_flag_subdevice:1,
match_flag_class:1,
match_flag_subclass:1,
match_flag_revid:1,
match_flag_unused:9;
#else
uint16_t
match_flag_unused:9,
match_flag_revid:1,
match_flag_subclass:1,
match_flag_class:1,
match_flag_subdevice:1,
match_flag_subvendor:1,
match_flag_device:1,
match_flag_vendor:1;
#endif
uint16_t vendor;
uint16_t device;
uint16_t subvendor;
uint16_t subdevice;
uint16_t class_id;
uint16_t subclass;
uint16_t revid;
uint16_t unused;
uintptr_t driver_data;
char *descr;
};
#define PCI_DEV(v, d) \
.match_flag_vendor = 1, .vendor = (v), \
.match_flag_device = 1, .device = (d)
#define PCI_SUBDEV(sv, sd) \
.match_flag_subvendor = 1, .subvendor = (sv), \
.match_flag_subdevice = 1, .subdevice = (sd)
#define PCI_CLASS(x) \
.match_flag_class = 1, .class_id = (x)
#define PCI_SUBCLASS(x) \
.match_flag_subclass = 1, .subclass = (x)
#define PCI_REVID(x) \
.match_flag_revid = 1, .revid = (x)
#define PCI_DESCR(x) \
.descr = (x)
#define PCI_PNP_STR \
"M16:mask;U16:vendor;U16:device;U16:subvendor;U16:subdevice;" \
"U16:class;U16:subclass;U16:revid;"
#define PCI_PNP_INFO(table) \
MODULE_PNP_INFO(PCI_PNP_STR, pci, table, table, sizeof(table[0]), \
sizeof(table) / sizeof(table[0]))
const struct pci_device_table *pci_match_device(device_t child,
const struct pci_device_table *id, size_t nelt);
#define PCI_MATCH(child, table) \
pci_match_device(child, (table), nitems(table));
/* Only if the prerequisites are present */
#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_)
struct pci_devinfo {
@ -416,7 +476,7 @@ pci_get_vpd_readonly(device_t dev, const char *kw, const char **vptr)
static __inline int
pci_is_vga_ioport_range(rman_res_t start, rman_res_t end)
{
return (((start >= 0x3b0 && end <= 0x3bb) ||
(start >= 0x3c0 && end <= 0x3df)) ? 1 : 0);
}