I am trying to familiarize myself with pciutils-dev C library, and I came across this example file.
For simplicity, let me write (a mildly changed version of) example.c here:
Code:
int main(int argc, char* argv[]) {
struct pci_access* pacc;
struct pci_dev* dev;
pacc = pci_alloc();
pci_init(pacc);
pci_scan_bus(pacc);
for (dev = pacc->devices; dev; dev = dev->next) {
pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS);
printf("%02x:%02x.%d vendor=%04x device=%04x class=%04x irq=%d base0=%lx\n",
dev->bus, dev->dev, dev->func, dev->vendor_id, dev->device_id,
dev->device_class, dev->irq, (long) dev->base_addr[0]);
}
pci_cleanup(pacc);
return 0;
}
I omitted things I'm not interested in right now.
So, I'm am trying to find out what does pci_fill_info() do.
Now, you're right, its name and arguments kinda give it away, and plus this helps revealing more (from here):
Code:
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
u16 domain; /* PCI domain (host bridge) */
u8 bus, dev, func; /* Bus inside domain, device and function */
/* These fields are set by pci_fill_info() */
int known_fields; /* Set of info fields already known */
u16 vendor_id, device_id; /* Identity of the device */
u16 device_class; /* PCI device class */
int irq; /* IRQ number */
pciaddr_t base_addr[6]; /* Base addresses including flags in lower bits */
pciaddr_t size[6]; /* Region sizes */
pciaddr_t rom_base_addr; /* Expansion ROM base address */
pciaddr_t rom_size; /* Expansion ROM size */
struct pci_cap *first_cap; /* List of capabilities */
char *phy_slot; /* Physical slot */
char *module_alias; /* Linux kernel module alias */
char *label; /* Device name as exported by BIOS */
int numa_node; /* NUMA node */
/* Fields used internally: */
struct pci_access *access;
struct pci_methods *methods;
u8 *cache; /* Cached config registers */
int cache_len;
int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */
void *aux; /* Auxillary data */
};
Nonetheless, I wanted to be sure that it does what I think it does.
So I looked everywhere for its definition and couldn't find it!
Please, if anyone knows where I can find its implementation. that would be great!
Another weird thing that happens; is that when I tried to confirm the function's mode of operation, something unexpected happened.
Consider this:
Code:
int main(int argc, char* argv[]) {
struct pci_access* pacc;
struct pci_dev* dev;
pacc = pci_alloc();
pci_init(pacc);
pci_scan_bus(pacc);
for (dev = pacc->devices; dev; dev = dev->next) {
struct pci_dev* temp = dev->next;
memset(dev, 0, sizeof(dev));
dev->next = temp;
pci_fill_info(dev, PCI_FILL_IDENT);
printf("%02x:%02x.%d vendor=%04x device=%04x class=%04x irq=%d base0=%lx\n",
dev->bus, dev->dev, dev->func, dev->vendor_id, dev->device_id,
dev->device_class, dev->irq, (long) dev->base_addr[0]);
}
pci_cleanup(pacc);
return 0;
}
Notice that the only flag I give to pci_fill_info() is PCI_FILL_IDENT, but the above still prints valid values for all the fields!
It is as if pci_fill_info() completely ignores the flags, and just populate the entire struct!
Is anyone familiar with this function and can shed some light?
Thanks.