/root/src/xen/xen/include/xen/pci.h
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * pci.h |
3 | | * |
4 | | * PCI access functions. |
5 | | */ |
6 | | |
7 | | #ifndef __XEN_PCI_H__ |
8 | | #define __XEN_PCI_H__ |
9 | | |
10 | | #include <xen/types.h> |
11 | | #include <xen/list.h> |
12 | | #include <xen/spinlock.h> |
13 | | #include <xen/irq.h> |
14 | | #include <xen/pci_regs.h> |
15 | | #include <xen/pfn.h> |
16 | | #include <asm/device.h> |
17 | | #include <asm/numa.h> |
18 | | #include <asm/pci.h> |
19 | | |
20 | | /* |
21 | | * The PCI interface treats multi-function devices as independent |
22 | | * devices. The slot/function address of each device is encoded |
23 | | * in a single byte as follows: |
24 | | * |
25 | | * 15:8 = bus |
26 | | * 7:3 = slot |
27 | | * 2:0 = function |
28 | | */ |
29 | 0 | #define PCI_SEG(sbdf) (((sbdf) >> 16) & 0xffff) |
30 | 0 | #define PCI_BUS(bdf) (((bdf) >> 8) & 0xff) |
31 | 3.50k | #define PCI_SLOT(bdf) (((bdf) >> 3) & 0x1f) |
32 | 3.50k | #define PCI_FUNC(bdf) ((bdf) & 0x07) |
33 | 80 | #define PCI_DEVFN(d,f) ((((d) & 0x1f) << 3) | ((f) & 0x07)) |
34 | 0 | #define PCI_DEVFN2(bdf) ((bdf) & 0xff) |
35 | 10 | #define PCI_BDF(b,d,f) ((((b) & 0xff) << 8) | PCI_DEVFN(d,f)) |
36 | 24.9k | #define PCI_BDF2(b,df) ((((b) & 0xff) << 8) | ((df) & 0xff)) |
37 | 0 | #define PCI_SBDF(s,b,d,f) ((((s) & 0xffff) << 16) | PCI_BDF(b,d,f)) |
38 | 0 | #define PCI_SBDF2(s,bdf) ((((s) & 0xffff) << 16) | ((bdf) & 0xffff)) |
39 | 0 | #define PCI_SBDF3(s,b,df) ((((s) & 0xffff) << 16) | PCI_BDF2(b, df)) |
40 | | |
41 | | typedef union { |
42 | | uint32_t sbdf; |
43 | | struct { |
44 | | union { |
45 | | uint16_t bdf; |
46 | | struct { |
47 | | union { |
48 | | struct { |
49 | | uint8_t func : 3, |
50 | | dev : 5; |
51 | | }; |
52 | | uint8_t extfunc; |
53 | | }; |
54 | | uint8_t bus; |
55 | | }; |
56 | | }; |
57 | | uint16_t seg; |
58 | | }; |
59 | | } pci_sbdf_t; |
60 | | |
61 | | struct pci_dev_info { |
62 | | /* |
63 | | * VF's 'is_extfn' field is used to indicate whether its PF is an extended |
64 | | * function. |
65 | | */ |
66 | | bool_t is_extfn; |
67 | | bool_t is_virtfn; |
68 | | struct { |
69 | | u8 bus; |
70 | | u8 devfn; |
71 | | } physfn; |
72 | | }; |
73 | | |
74 | | struct pci_dev { |
75 | | struct list_head alldevs_list; |
76 | | struct list_head domain_list; |
77 | | |
78 | | struct list_head msi_list; |
79 | | |
80 | | struct arch_msix *msix; |
81 | | |
82 | | struct domain *domain; |
83 | | const u16 seg; |
84 | | const u8 bus; |
85 | | const u8 devfn; |
86 | | |
87 | | u8 phantom_stride; |
88 | | |
89 | | nodeid_t node; /* NUMA node */ |
90 | | |
91 | | enum pdev_type { |
92 | | DEV_TYPE_PCI_UNKNOWN, |
93 | | DEV_TYPE_PCIe_ENDPOINT, |
94 | | DEV_TYPE_PCIe_BRIDGE, // PCIe root port, switch |
95 | | DEV_TYPE_PCIe2PCI_BRIDGE, // PCIe-to-PCI/PCIx bridge |
96 | | DEV_TYPE_PCI2PCIe_BRIDGE, // PCI/PCIx-to-PCIe bridge |
97 | | DEV_TYPE_LEGACY_PCI_BRIDGE, // Legacy PCI bridge |
98 | | DEV_TYPE_PCI_HOST_BRIDGE, // PCI Host bridge |
99 | | DEV_TYPE_PCI, |
100 | | } type; |
101 | | |
102 | | struct pci_dev_info info; |
103 | | struct arch_pci_dev arch; |
104 | | struct { |
105 | | struct list_head list; |
106 | | unsigned int cap_pos; |
107 | | unsigned int queue_depth; |
108 | | } ats; |
109 | | struct { |
110 | | s_time_t time; |
111 | | unsigned int count; |
112 | 0 | #define PT_FAULT_THRESHOLD 10 |
113 | | } fault; |
114 | | u64 vf_rlen[6]; |
115 | | |
116 | | /* Data for vPCI. */ |
117 | | struct vpci *vpci; |
118 | | }; |
119 | | |
120 | | #define for_each_pdev(domain, pdev) \ |
121 | 0 | list_for_each_entry(pdev, &(domain->arch.pdev_list), domain_list) |
122 | | |
123 | | /* |
124 | | * The pcidevs_lock protect alldevs_list, and the assignment for the |
125 | | * devices, it also sync the access to the msi capability that is not |
126 | | * interrupt handling related (the mask bit register). |
127 | | */ |
128 | | |
129 | | void pcidevs_lock(void); |
130 | | void pcidevs_unlock(void); |
131 | | bool_t __must_check pcidevs_locked(void); |
132 | | bool_t __must_check pcidevs_trylock(void); |
133 | | |
134 | | bool_t pci_known_segment(u16 seg); |
135 | | bool_t pci_device_detect(u16 seg, u8 bus, u8 dev, u8 func); |
136 | | int scan_pci_devices(void); |
137 | | enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn); |
138 | | int find_upstream_bridge(u16 seg, u8 *bus, u8 *devfn, u8 *secbus); |
139 | | struct pci_dev *pci_lock_pdev(int seg, int bus, int devfn); |
140 | | struct pci_dev *pci_lock_domain_pdev( |
141 | | struct domain *, int seg, int bus, int devfn); |
142 | | |
143 | | void setup_hwdom_pci_devices(struct domain *, |
144 | | int (*)(u8 devfn, struct pci_dev *)); |
145 | | int pci_release_devices(struct domain *d); |
146 | | int pci_add_segment(u16 seg); |
147 | | const unsigned long *pci_get_ro_map(u16 seg); |
148 | | int pci_add_device(u16 seg, u8 bus, u8 devfn, |
149 | | const struct pci_dev_info *, nodeid_t node); |
150 | | int pci_remove_device(u16 seg, u8 bus, u8 devfn); |
151 | | int pci_ro_device(int seg, int bus, int devfn); |
152 | | int pci_hide_device(int bus, int devfn); |
153 | | struct pci_dev *pci_get_pdev(int seg, int bus, int devfn); |
154 | | struct pci_dev *pci_get_real_pdev(int seg, int bus, int devfn); |
155 | | struct pci_dev *pci_get_pdev_by_domain(const struct domain *, int seg, |
156 | | int bus, int devfn); |
157 | | void pci_check_disable_device(u16 seg, u8 bus, u8 devfn); |
158 | | |
159 | | uint8_t pci_conf_read8( |
160 | | unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func, |
161 | | unsigned int reg); |
162 | | uint16_t pci_conf_read16( |
163 | | unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func, |
164 | | unsigned int reg); |
165 | | uint32_t pci_conf_read32( |
166 | | unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func, |
167 | | unsigned int reg); |
168 | | void pci_conf_write8( |
169 | | unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func, |
170 | | unsigned int reg, uint8_t data); |
171 | | void pci_conf_write16( |
172 | | unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func, |
173 | | unsigned int reg, uint16_t data); |
174 | | void pci_conf_write32( |
175 | | unsigned int seg, unsigned int bus, unsigned int dev, unsigned int func, |
176 | | unsigned int reg, uint32_t data); |
177 | | uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes); |
178 | | void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t data); |
179 | | int pci_mmcfg_read(unsigned int seg, unsigned int bus, |
180 | | unsigned int devfn, int reg, int len, u32 *value); |
181 | | int pci_mmcfg_write(unsigned int seg, unsigned int bus, |
182 | | unsigned int devfn, int reg, int len, u32 value); |
183 | | int pci_find_cap_offset(u16 seg, u8 bus, u8 dev, u8 func, u8 cap); |
184 | | int pci_find_next_cap(u16 seg, u8 bus, unsigned int devfn, u8 pos, int cap); |
185 | | int pci_find_ext_capability(int seg, int bus, int devfn, int cap); |
186 | | int pci_find_next_ext_capability(int seg, int bus, int devfn, int pos, int cap); |
187 | | const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus, |
188 | | unsigned int *dev, unsigned int *func); |
189 | | const char *parse_pci_seg(const char *, unsigned int *seg, unsigned int *bus, |
190 | | unsigned int *dev, unsigned int *func, bool *def_seg); |
191 | | |
192 | 0 | #define PCI_BAR_VF (1u << 0) |
193 | 75 | #define PCI_BAR_LAST (1u << 1) |
194 | 890 | #define PCI_BAR_ROM (1u << 2) |
195 | | int pci_size_mem_bar(pci_sbdf_t sbdf, unsigned int pos, uint64_t *addr, |
196 | | uint64_t *size, unsigned int flags); |
197 | | |
198 | | bool_t pcie_aer_get_firmware_first(const struct pci_dev *); |
199 | | |
200 | | struct pirq; |
201 | | int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable); |
202 | | void msixtbl_pt_unregister(struct domain *, struct pirq *); |
203 | | void msixtbl_pt_cleanup(struct domain *d); |
204 | | |
205 | | #endif /* __XEN_PCI_H__ */ |