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 | |
---|
17 | typedef uint32_t pciaddr_t; |
---|
18 | |
---|
19 | enum { |
---|
20 | ENOPCIIDS = 100, |
---|
21 | ENOMODULESPCIMAP, |
---|
22 | ENOMODULESALIAS |
---|
23 | }; |
---|
24 | |
---|
25 | /* a structure for extended pci information */ |
---|
26 | /* XXX: use pointers for these? */ |
---|
27 | struct 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) */ |
---|
40 | struct 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 */ |
---|
61 | struct pci_slot { |
---|
62 | struct pci_device *func[MAX_PCI_FUNC]; |
---|
63 | }; |
---|
64 | |
---|
65 | /* PCI bus structure */ |
---|
66 | struct pci_bus { |
---|
67 | struct pci_slot *slot[MAX_PCI_DEVICES]; |
---|
68 | }; |
---|
69 | |
---|
70 | /* PCI domain structure */ |
---|
71 | struct 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 | |
---|
95 | struct 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 | |
---|
105 | static 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 | |
---|
112 | static inline int pci_bus(pciaddr_t addr) |
---|
113 | { |
---|
114 | return (addr >> 16) & 0xff; |
---|
115 | } |
---|
116 | |
---|
117 | static inline int pci_dev(pciaddr_t addr) |
---|
118 | { |
---|
119 | return (addr >> 11) & 0x1f; |
---|
120 | } |
---|
121 | |
---|
122 | static inline int pci_func(pciaddr_t addr) |
---|
123 | { |
---|
124 | return (addr >> 8) & 0x07; |
---|
125 | } |
---|
126 | |
---|
127 | enum 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 | |
---|
135 | enum pci_config_type pci_set_config_type(enum pci_config_type); |
---|
136 | |
---|
137 | uint8_t pci_readb(pciaddr_t); |
---|
138 | uint16_t pci_readw(pciaddr_t); |
---|
139 | uint32_t pci_readl(pciaddr_t); |
---|
140 | void pci_writeb(uint8_t, pciaddr_t); |
---|
141 | void pci_writew(uint16_t, pciaddr_t); |
---|
142 | void pci_writel(uint32_t, pciaddr_t); |
---|
143 | |
---|
144 | struct pci_domain *pci_scan(void); |
---|
145 | void free_pci_domain(struct pci_domain *domain); |
---|
146 | struct match *find_pci_device(const struct pci_domain *pci_domain, |
---|
147 | struct match *list); |
---|
148 | int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); |
---|
149 | int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path); |
---|
150 | int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path); |
---|
151 | int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); |
---|
152 | void gather_additional_pci_config(struct pci_domain *domain); |
---|
153 | #endif /* _SYS_PCI_H */ |
---|