File: | arch/amd64/pci/acpipci.c |
Warning: | line 271, column 3 Value stored to 'tra' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: acpipci.c,v 1.7 2022/02/21 11:03:39 mpi Exp $ */ |
2 | /* |
3 | * Copyright (c) 2018 Mark Kettenis |
4 | * |
5 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. |
8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ |
17 | |
18 | #include <sys/param.h> |
19 | #include <sys/device.h> |
20 | #include <sys/extent.h> |
21 | #include <sys/malloc.h> |
22 | #include <sys/systm.h> |
23 | |
24 | #include <dev/acpi/acpireg.h> |
25 | #include <dev/acpi/acpivar.h> |
26 | #include <dev/acpi/acpidev.h> |
27 | #include <dev/acpi/amltypes.h> |
28 | #include <dev/acpi/dsdt.h> |
29 | |
30 | #include <dev/pci/pcidevs.h> |
31 | #include <dev/pci/pcireg.h> |
32 | #include <dev/pci/pcivar.h> |
33 | |
34 | /* 33DB4D5B-1FF7-401C-9657-7441C03DD766 */ |
35 | #define ACPI_PCI_UUID{ 0x5b, 0x4d, 0xdb, 0x33, 0xf7, 0x1f, 0x1c, 0x40, 0x96, 0x57, 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 } \ |
36 | { 0x5b, 0x4d, 0xdb, 0x33, \ |
37 | 0xf7, 0x1f, \ |
38 | 0x1c, 0x40, \ |
39 | 0x96, 0x57, \ |
40 | 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 } |
41 | |
42 | /* Support field. */ |
43 | #define ACPI_PCI_PCIE_CONFIG0x00000001 0x00000001 |
44 | #define ACPI_PCI_ASPM0x00000002 0x00000002 |
45 | #define ACPI_PCI_CPMC0x00000004 0x00000004 |
46 | #define ACPI_PCI_SEGMENTS0x00000008 0x00000008 |
47 | #define ACPI_PCI_MSI0x00000010 0x00000010 |
48 | |
49 | /* Control field. */ |
50 | #define ACPI_PCI_PCIE_HOTPLUG0x00000001 0x00000001 |
51 | |
52 | struct acpipci_softc { |
53 | struct device sc_dev; |
54 | struct acpi_softc *sc_acpi; |
55 | struct aml_node *sc_node; |
56 | |
57 | bus_space_tag_t sc_iot; |
58 | bus_space_tag_t sc_memt; |
59 | bus_dma_tag_t sc_dmat; |
60 | |
61 | struct extent *sc_busex; |
62 | struct extent *sc_memex; |
63 | struct extent *sc_ioex; |
64 | char sc_busex_name[32]; |
65 | char sc_ioex_name[32]; |
66 | char sc_memex_name[32]; |
67 | int sc_bus; |
68 | uint32_t sc_seg; |
69 | }; |
70 | |
71 | int acpipci_match(struct device *, void *, void *); |
72 | void acpipci_attach(struct device *, struct device *, void *); |
73 | |
74 | const struct cfattach acpipci_ca = { |
75 | sizeof(struct acpipci_softc), acpipci_match, acpipci_attach |
76 | }; |
77 | |
78 | struct cfdriver acpipci_cd = { |
79 | NULL((void *)0), "acpipci", DV_DULL |
80 | }; |
81 | |
82 | const char *acpipci_hids[] = { |
83 | "PNP0A08", |
84 | "PNP0A03", |
85 | NULL((void *)0) |
86 | }; |
87 | |
88 | void acpipci_attach_deferred(struct device *); |
89 | int acpipci_print(void *, const char *); |
90 | int acpipci_parse_resources(int, union acpi_resource *, void *); |
91 | void acpipci_osc(struct acpipci_softc *); |
92 | |
93 | int |
94 | acpipci_match(struct device *parent, void *match, void *aux) |
95 | { |
96 | struct acpi_attach_args *aaa = aux; |
97 | struct cfdata *cf = match; |
98 | |
99 | return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); |
100 | } |
101 | |
102 | void |
103 | acpipci_attach(struct device *parent, struct device *self, void *aux) |
104 | { |
105 | struct acpi_attach_args *aaa = aux; |
106 | struct acpipci_softc *sc = (struct acpipci_softc *)self; |
107 | struct aml_value res; |
108 | uint64_t bbn = 0; |
109 | uint64_t seg = 0; |
110 | |
111 | acpi_haspci = 1; |
112 | |
113 | sc->sc_iot = aaa->aaa_iot; |
114 | sc->sc_memt = aaa->aaa_memt; |
115 | sc->sc_dmat = aaa->aaa_dmat; |
116 | |
117 | sc->sc_acpi = (struct acpi_softc *)parent; |
118 | sc->sc_node = aaa->aaa_node; |
119 | printf(" %s", sc->sc_node->name); |
120 | |
121 | acpipci_osc(sc); |
122 | |
123 | aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL((void *)0), &bbn); |
124 | sc->sc_bus = bbn; |
125 | |
126 | aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL((void *)0), &seg); |
127 | sc->sc_seg = seg; |
128 | |
129 | if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL((void *)0), &res)) { |
130 | printf(": can't find resources\n"); |
131 | |
132 | pci_init_extents(); |
133 | sc->sc_busex = pcibus_ex; |
134 | sc->sc_ioex = pciio_ex; |
135 | sc->sc_memex = pcimem_ex; |
136 | |
137 | return; |
138 | } |
139 | |
140 | /* Create extents for our address spaces. */ |
141 | snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), |
142 | "%s pcibus", sc->sc_dev.dv_xname); |
143 | snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), |
144 | "%s pciio", sc->sc_dev.dv_xname); |
145 | snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), |
146 | "%s pcimem", sc->sc_dev.dv_xname); |
147 | sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, |
148 | M_DEVBUF2, NULL((void *)0), 0, EX_WAITOK0x0001 | EX_FILLED0x0100); |
149 | sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, |
150 | M_DEVBUF2, NULL((void *)0), 0, EX_WAITOK0x0001 | EX_FILLED0x0100); |
151 | sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, |
152 | M_DEVBUF2, NULL((void *)0), 0, EX_WAITOK0x0001 | EX_FILLED0x0100); |
153 | |
154 | aml_parse_resource(&res, acpipci_parse_resources, sc); |
155 | |
156 | if (sc->sc_acpi->sc_major < 5) { |
157 | extent_destroy(sc->sc_ioex); |
158 | extent_destroy(sc->sc_memex); |
159 | |
160 | pci_init_extents(); |
161 | sc->sc_ioex = pciio_ex; |
162 | sc->sc_memex = pcimem_ex; |
163 | } |
164 | |
165 | printf("\n"); |
166 | |
167 | #ifdef ACPIPCI_DEBUG |
168 | extent_print(sc->sc_busex); |
169 | extent_print(sc->sc_ioex); |
170 | extent_print(sc->sc_memex); |
171 | #endif |
172 | } |
173 | |
174 | void |
175 | acpipci_attach_bus(struct device *parent, struct acpipci_softc *sc) |
176 | { |
177 | struct pcibus_attach_args pba; |
178 | pcitag_t tag; |
179 | pcireg_t id, class; |
180 | |
181 | memset(&pba, 0, sizeof(pba))__builtin_memset((&pba), (0), (sizeof(pba))); |
182 | pba.pba_busname = "pci"; |
183 | pba.pba_iot = sc->sc_iot; |
184 | pba.pba_memt = sc->sc_memt; |
185 | pba.pba_dmat = sc->sc_dmat; |
186 | pba.pba_busex = sc->sc_busex; |
187 | pba.pba_ioex = sc->sc_ioex; |
188 | pba.pba_memex = sc->sc_memex; |
189 | pba.pba_pmemex = sc->sc_memex; |
190 | pba.pba_domain = pci_ndomains++; |
191 | pba.pba_bus = sc->sc_bus; |
192 | |
193 | /* Enable MSI in ACPI 2.0 and above, unless we're told not to. */ |
194 | if (sc->sc_acpi->sc_fadt->hdr.revision >= 2 && |
195 | (sc->sc_acpi->sc_fadt->iapc_boot_arch & FADT_NO_MSI0x0008) == 0) |
196 | pba.pba_flags |= PCI_FLAGS_MSI_ENABLED0x20; |
197 | |
198 | /* |
199 | * Don't enable MSI on chipsets from low-end manufacturers |
200 | * like VIA and SiS. We do this by looking at the host |
201 | * bridge, which should be device 0 function 0. |
202 | */ |
203 | tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 0, 0); |
204 | id = pci_conf_read(pba.pba_pc, tag, PCI_ID_REG0x00); |
205 | class = pci_conf_read(pba.pba_pc, tag, PCI_CLASS_REG0x08); |
206 | if (PCI_CLASS(class)(((class) >> 24) & 0xff) == PCI_CLASS_BRIDGE0x06 && |
207 | PCI_SUBCLASS(class)(((class) >> 16) & 0xff) != PCI_SUBCLASS_BRIDGE_HOST0x00 && |
208 | PCI_VENDOR(id)(((id) >> 0) & 0xffff) != PCI_VENDOR_AMD0x1022 && |
209 | PCI_VENDOR(id)(((id) >> 0) & 0xffff) != PCI_VENDOR_NVIDIA0x10de && |
210 | PCI_VENDOR(id)(((id) >> 0) & 0xffff) != PCI_VENDOR_INTEL0x8086) |
211 | pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED0x20; |
212 | |
213 | /* |
214 | * Don't enable MSI on a HyperTransport bus. In order to |
215 | * determine that a bus is a HyperTransport bus, we look at |
216 | * device 24 function 0, which is the HyperTransport |
217 | * host/primary interface integrated on most 64-bit AMD CPUs. |
218 | * If that device has a HyperTransport capability, this must |
219 | * be a HyperTransport bus and we disable MSI. |
220 | */ |
221 | tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 24, 0); |
222 | if (pci_get_capability(pba.pba_pc, tag, PCI_CAP_HT0x08, NULL((void *)0), NULL((void *)0))) |
223 | pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED0x20; |
224 | |
225 | config_found(parent, &pba, acpipci_print)config_found_sm((parent), (&pba), (acpipci_print), ((void *)0)); |
226 | } |
227 | |
228 | void |
229 | acpipci_attach_busses(struct device *parent) |
230 | { |
231 | int i; |
232 | |
233 | for (i = 0; i < acpipci_cd.cd_ndevs; i++) { |
234 | if (acpipci_cd.cd_devs[i]) |
235 | acpipci_attach_bus(parent, acpipci_cd.cd_devs[i]); |
236 | } |
237 | } |
238 | |
239 | int |
240 | acpipci_print(void *aux, const char *pnp) |
241 | { |
242 | struct pcibus_attach_args *pba = aux; |
243 | |
244 | if (pnp) |
245 | printf("%s at %s", pba->pba_busname, pnp); |
246 | printf(" bus %d", pba->pba_bus); |
247 | return (UNCONF1); |
248 | } |
249 | |
250 | int |
251 | acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) |
252 | { |
253 | struct acpipci_softc *sc = arg; |
254 | int type = AML_CRSTYPE(crs)((crs)->hdr.typecode & 0x80 ? (crs)->hdr.typecode : (crs)->hdr.typecode >> 3); |
255 | int restype, tflags = 0; |
256 | u_long min, len = 0, tra = 0; |
257 | |
258 | switch (type) { |
259 | case LR_WORD0x88: |
260 | restype = crs->lr_word.type; |
261 | tflags = crs->lr_word.tflags; |
262 | min = crs->lr_word._min; |
263 | len = crs->lr_word._len; |
264 | tra = crs->lr_word._tra; |
265 | break; |
266 | case LR_DWORD0x87: |
267 | restype = crs->lr_dword.type; |
268 | tflags = crs->lr_dword.tflags; |
269 | min = crs->lr_dword._min; |
270 | len = crs->lr_dword._len; |
271 | tra = crs->lr_dword._tra; |
Value stored to 'tra' is never read | |
272 | break; |
273 | case LR_QWORD0x8A: |
274 | restype = crs->lr_qword.type; |
275 | tflags = crs->lr_qword.tflags; |
276 | min = crs->lr_qword._min; |
277 | len = crs->lr_qword._len; |
278 | tra = crs->lr_qword._tra; |
279 | break; |
280 | case LR_MEM32FIXED0x86: |
281 | /* |
282 | * Coreboot on the PC Engines apu2 incorrectly uses a |
283 | * Memory32Fixed resource descriptor to describe mmio |
284 | * address space forwarded to the PCI bus. |
285 | */ |
286 | restype = LR_TYPE_MEMORY0; |
287 | min = crs->lr_m32fixed._bas; |
288 | len = crs->lr_m32fixed._len; |
289 | break; |
290 | } |
291 | |
292 | if (len == 0) |
293 | return 0; |
294 | |
295 | switch (restype) { |
296 | case LR_TYPE_MEMORY0: |
297 | if (tflags & LR_MEMORY_TTP(1L << 5)) |
298 | return 0; |
299 | extent_free(sc->sc_memex, min, len, EX_WAITOK0x0001 | EX_CONFLICTOK0x0080); |
300 | break; |
301 | case LR_TYPE_IO1: |
302 | if (tflags & LR_IO_TTP(1L << 4)) |
303 | return 0; |
304 | extent_free(sc->sc_ioex, min, len, EX_WAITOK0x0001 | EX_CONFLICTOK0x0080); |
305 | break; |
306 | case LR_TYPE_BUS2: |
307 | extent_free(sc->sc_busex, min, len, EX_WAITOK0x0001); |
308 | /* |
309 | * Let _CRS minimum bus number override _BBN. |
310 | */ |
311 | sc->sc_bus = min; |
312 | break; |
313 | } |
314 | |
315 | return 0; |
316 | } |
317 | |
318 | void |
319 | acpipci_osc(struct acpipci_softc *sc) |
320 | { |
321 | struct aml_value args[4]; |
322 | struct aml_value res; |
323 | static uint8_t uuid[16] = ACPI_PCI_UUID{ 0x5b, 0x4d, 0xdb, 0x33, 0xf7, 0x1f, 0x1c, 0x40, 0x96, 0x57, 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 }; |
324 | uint32_t buf[3]; |
325 | |
326 | memset(args, 0, sizeof(args))__builtin_memset((args), (0), (sizeof(args))); |
327 | args[0].type = AML_OBJTYPE_BUFFER; |
328 | args[0].v_buffer_.vbuffer = uuid; |
329 | args[0].length = sizeof(uuid); |
330 | args[1].type = AML_OBJTYPE_INTEGER; |
331 | args[1].v_integer_.vinteger = 1; |
332 | args[2].type = AML_OBJTYPE_INTEGER; |
333 | args[2].v_integer_.vinteger = 3; |
334 | args[3].type = AML_OBJTYPE_BUFFER; |
335 | args[3].v_buffer_.vbuffer = (uint8_t *)buf; |
336 | args[3].length = sizeof(buf); |
337 | |
338 | memset(buf, 0, sizeof(buf))__builtin_memset((buf), (0), (sizeof(buf))); |
339 | buf[0] = 0x0; |
340 | buf[1] = ACPI_PCI_PCIE_CONFIG0x00000001 | ACPI_PCI_MSI0x00000010; |
341 | buf[2] = ACPI_PCI_PCIE_HOTPLUG0x00000001; |
342 | |
343 | if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res)) |
344 | return; |
345 | |
346 | if (res.type == AML_OBJTYPE_BUFFER) { |
347 | size_t len = res.length; |
348 | uint32_t *p = (uint32_t *)res.v_buffer_.vbuffer; |
349 | |
350 | printf(":"); |
351 | while (len >= 4) { |
352 | printf(" 0x%08x", *p); |
353 | p++; |
354 | len -= 4; |
355 | } |
356 | } |
357 | } |