#ifndef _SYS_PCI_H #define _SYS_PCI_H #include <inttypes.h> #include <sys/io.h> #define MAX_PCI_FUNC 8 #define MAX_PCI_DEVICES 32 #define MAX_PCI_BUSES 256 #define LINUX_KERNEL_MODULE_SIZE 64 #define PCI_VENDOR_NAME_SIZE 256 #define PCI_PRODUCT_NAME_SIZE 256 #define PCI_CLASS_NAME_SIZE 256 #define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10 #define MAX_PCI_CLASSES 256 typedef uint32_t pciaddr_t; enum { ENOPCIIDS = 100, ENOMODULESPCIMAP, ENOMODULESALIAS }; /* a structure for extended pci information */ /* XXX: use pointers for these? */ struct pci_dev_info { char vendor_name[PCI_VENDOR_NAME_SIZE]; char product_name[PCI_PRODUCT_NAME_SIZE]; char linux_kernel_module[LINUX_KERNEL_MODULE_SIZE] [MAX_KERNEL_MODULES_PER_PCI_DEVICE]; int linux_kernel_module_count; char class_name[PCI_CLASS_NAME_SIZE]; /* The most precise class name */ char category_name[PCI_CLASS_NAME_SIZE]; /*The general category */ uint8_t irq; uint8_t latency; }; /* PCI device (really, function) */ struct pci_device { union { struct { uint16_t vendor; uint16_t product; uint16_t sub_vendor; uint16_t sub_product; uint8_t revision; uint8_t class[3]; }; struct { uint32_t vid_did; uint32_t svid_sdid; uint32_t rid_class; }; }; struct pci_dev_info *dev_info; struct pci_device *next; }; /* PCI device ("slot") structure */ struct pci_slot { struct pci_device *func[MAX_PCI_FUNC]; }; /* PCI bus structure */ struct pci_bus { struct pci_slot *slot[MAX_PCI_DEVICES]; }; /* PCI domain structure */ struct pci_domain { struct pci_bus *bus[MAX_PCI_BUSES]; }; /* Iterate over a PCI domain */ #define for_each_pci_func(funcp, domain) \ for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \ if ((domain)->bus[__pci_bus]) \ for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \ if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \ for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \ if (((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \ func[__pci_func])) #define for_each_pci_func3(funcp, domain, addr) \ for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \ if ((domain)->bus[__pci_bus]) \ for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \ if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \ for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \ if (((addr) = pci_mkaddr(__pci_bus, __pci_slot, __pci_func, 0)), \ ((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \ func[__pci_func])) struct match { struct match *next; uint32_t did; uint32_t did_mask; uint32_t sid; uint32_t sid_mask; uint8_t rid_min, rid_max; char *filename; }; static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev, uint32_t func, uint32_t reg) { return 0x80000000 | ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) | ((func & 0x07) << 8) | (reg & 0xff); } static inline int pci_bus(pciaddr_t addr) { return (addr >> 16) & 0xff; } static inline int pci_dev(pciaddr_t addr) { return (addr >> 11) & 0x1f; } static inline int pci_func(pciaddr_t addr) { return (addr >> 8) & 0x07; } enum pci_config_type { PCI_CFG_NONE = -1, /* badness */ PCI_CFG_AUTO = 0, /* autodetect */ PCI_CFG_TYPE1 = 1, PCI_CFG_TYPE2 = 2, PCI_CFG_BIOS = 3, }; enum pci_config_type pci_set_config_type(enum pci_config_type); uint8_t pci_readb(pciaddr_t); uint16_t pci_readw(pciaddr_t); uint32_t pci_readl(pciaddr_t); void pci_writeb(uint8_t, pciaddr_t); void pci_writew(uint16_t, pciaddr_t); void pci_writel(uint32_t, pciaddr_t); struct pci_domain *pci_scan(void); void free_pci_domain(struct pci_domain *domain); struct match *find_pci_device(const struct pci_domain *pci_domain, struct match *list); int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path); int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path); int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); void gather_additional_pci_config(struct pci_domain *domain); #endif /* _SYS_PCI_H */