1#ifndef _SYS_PCI_H
2#define _SYS_PCI_H
3
4#include <inttypes.h>
5#include <sys/io.h>
6
7#define MAX_PCI_FUNC		  8
8#define MAX_PCI_DEVICES		 32
9#define MAX_PCI_BUSES		256
10#define LINUX_KERNEL_MODULE_SIZE 64
11#define PCI_VENDOR_NAME_SIZE	256
12#define PCI_PRODUCT_NAME_SIZE	256
13#define PCI_CLASS_NAME_SIZE	256
14#define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10
15#define MAX_PCI_CLASSES		256
16
17typedef uint32_t pciaddr_t;
18
19enum {
20	ENOPCIIDS = 100,
21	ENOMODULESPCIMAP,
22	ENOMODULESALIAS
23};
24
25/* a structure for extended pci information */
26/* XXX: use pointers for these? */
27struct pci_dev_info {
28    char vendor_name[PCI_VENDOR_NAME_SIZE];
29    char product_name[PCI_PRODUCT_NAME_SIZE];
30    char linux_kernel_module[LINUX_KERNEL_MODULE_SIZE]
31	[MAX_KERNEL_MODULES_PER_PCI_DEVICE];
32    int linux_kernel_module_count;
33    char class_name[PCI_CLASS_NAME_SIZE];	/* The most precise class name */
34    char category_name[PCI_CLASS_NAME_SIZE];	/*The general category */
35    uint8_t irq;
36    uint8_t latency;
37};
38
39/* PCI device (really, function) */
40struct pci_device {
41    union {
42	struct {
43	    uint16_t vendor;
44	    uint16_t product;
45	    uint16_t sub_vendor;
46	    uint16_t sub_product;
47	    uint8_t revision;
48	    uint8_t class[3];
49	};
50	struct {
51	    uint32_t vid_did;
52	    uint32_t svid_sdid;
53	    uint32_t rid_class;
54	};
55    };
56    struct pci_dev_info *dev_info;
57    struct pci_device *next;
58};
59
60/* PCI device ("slot") structure */
61struct pci_slot {
62    struct pci_device *func[MAX_PCI_FUNC];
63};
64
65/* PCI bus structure */
66struct pci_bus {
67    struct pci_slot *slot[MAX_PCI_DEVICES];
68};
69
70/* PCI domain structure */
71struct pci_domain {
72    struct pci_bus *bus[MAX_PCI_BUSES];
73};
74
75/* Iterate over a PCI domain */
76#define for_each_pci_func(funcp, domain) \
77  for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
78    if ((domain)->bus[__pci_bus]) \
79      for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
80	if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
81	  for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
82	    if (((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
83		 func[__pci_func]))
84
85#define for_each_pci_func3(funcp, domain, addr) \
86  for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
87    if ((domain)->bus[__pci_bus]) \
88      for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
89	if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
90	  for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
91	    if (((addr) = pci_mkaddr(__pci_bus, __pci_slot, __pci_func, 0)), \
92		((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
93		 func[__pci_func]))
94
95struct match {
96    struct match *next;
97    uint32_t did;
98    uint32_t did_mask;
99    uint32_t sid;
100    uint32_t sid_mask;
101    uint8_t rid_min, rid_max;
102    char *filename;
103};
104
105static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev,
106				   uint32_t func, uint32_t reg)
107{
108    return 0x80000000 | ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) |
109	((func & 0x07) << 8) | (reg & 0xff);
110}
111
112static inline int pci_bus(pciaddr_t addr)
113{
114    return (addr >> 16) & 0xff;
115}
116
117static inline int pci_dev(pciaddr_t addr)
118{
119    return (addr >> 11) & 0x1f;
120}
121
122static inline int pci_func(pciaddr_t addr)
123{
124    return (addr >> 8) & 0x07;
125}
126
127enum pci_config_type {
128    PCI_CFG_NONE = -1,		/* badness */
129    PCI_CFG_AUTO = 0,		/* autodetect */
130    PCI_CFG_TYPE1 = 1,
131    PCI_CFG_TYPE2 = 2,
132    PCI_CFG_BIOS = 3,
133};
134
135enum pci_config_type pci_set_config_type(enum pci_config_type);
136
137uint8_t pci_readb(pciaddr_t);
138uint16_t pci_readw(pciaddr_t);
139uint32_t pci_readl(pciaddr_t);
140void pci_writeb(uint8_t, pciaddr_t);
141void pci_writew(uint16_t, pciaddr_t);
142void pci_writel(uint32_t, pciaddr_t);
143
144struct pci_domain *pci_scan(void);
145void free_pci_domain(struct pci_domain *domain);
146struct match *find_pci_device(const struct pci_domain *pci_domain,
147			      struct match *list);
148int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path);
149int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path);
150int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path);
151int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path);
152void gather_additional_pci_config(struct pci_domain *domain);
153#endif /* _SYS_PCI_H */
154