1 /* $NetBSD: acpi_pci.c,v 1.37 2022/10/14 22:10:15 jmcneill Exp $ */
2
3 /*
4 * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christoph Egger and Gregoire Sutre.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.37 2022/10/14 22:10:15 jmcneill Exp $");
33
34 #include <sys/param.h>
35 #include <sys/device.h>
36 #include <sys/kmem.h>
37 #include <sys/systm.h>
38
39 #include <dev/pci/pcireg.h>
40 #include <dev/pci/pcivar.h>
41 #include <dev/pci/pcidevs.h>
42 #include <dev/pci/ppbreg.h>
43
44 #include <dev/pci/pci_calls.h>
45
46 #include <dev/acpi/acpireg.h>
47 #include <dev/acpi/acpivar.h>
48 #include <dev/acpi/acpi_pci.h>
49
50 #include "locators.h"
51
52 #define _COMPONENT ACPI_BUS_COMPONENT
53 ACPI_MODULE_NAME ("acpi_pci")
54
55 #define ACPI_HILODWORD(x) ACPI_HIWORD(ACPI_LODWORD((x)))
56 #define ACPI_LOLODWORD(x) ACPI_LOWORD(ACPI_LODWORD((x)))
57
58 static ACPI_STATUS acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *,
59 void *);
60
61 /*
62 * Regarding PCI Segment Groups (ACPI 4.0, p. 277):
63 *
64 * "The optional _SEG object is located under a PCI host bridge and
65 * evaluates to an integer that describes the PCI Segment Group (see PCI
66 * Firmware Specification v3.0)."
67 *
68 * "PCI Segment Group is purely a software concept managed by system
69 * firmware and used by OSPM. It is a logical collection of PCI buses
70 * (or bus segments). It is a way to logically group the PCI bus segments
71 * and PCI Express Hierarchies. _SEG is a level higher than _BBN."
72 *
73 * "PCI Segment Group supports more than 256 buses in a system by allowing
74 * the reuse of the PCI bus numbers. Within each PCI Segment Group, the bus
75 * numbers for the PCI buses must be unique. PCI buses in different PCI
76 * Segment Group are permitted to have the same bus number."
77 */
78
79 /*
80 * Regarding PCI Base Bus Numbers (ACPI 4.0, p. 277):
81 *
82 * "For multi-root PCI platforms, the _BBN object evaluates to the PCI bus
83 * number that the BIOS assigns. This is needed to access a PCI_Config
84 * operation region for the specified bus. The _BBN object is located under
85 * a PCI host bridge and must be unique for every host bridge within a
86 * segment since it is the PCI bus number."
87 *
88 * Moreover, the ACPI FAQ (http://www.acpi.info/acpi_faq.htm) says:
89 *
90 * "For a multiple root bus machine, _BBN is required for each bus. _BBN
91 * should provide the bus number assigned to this bus by the BIOS at boot
92 * time."
93 */
94
95 /*
96 * acpi_pcidev_pciroot_bus:
97 *
98 * Derive the PCI bus number of a PCI root bridge from its resources.
99 * If successful, return AE_OK and fill *busp. Otherwise, return an
100 * exception code and leave *busp unchanged.
101 */
102 ACPI_STATUS
acpi_pcidev_pciroot_bus(ACPI_HANDLE handle,uint16_t * busp)103 acpi_pcidev_pciroot_bus(ACPI_HANDLE handle, uint16_t *busp)
104 {
105 ACPI_STATUS rv;
106 int32_t bus;
107
108 bus = -1;
109
110 /*
111 * XXX: Use the ACPI resource parsing functions (acpi_resource.c)
112 * once bus number ranges have been implemented there.
113 */
114 rv = AcpiWalkResources(handle, "_CRS",
115 acpi_pcidev_pciroot_bus_callback, &bus);
116
117 if (ACPI_FAILURE(rv))
118 return rv;
119
120 if (bus == -1)
121 return AE_NOT_EXIST;
122
123 /* Here it holds that 0 <= bus <= 0xFFFF. */
124 *busp = (uint16_t)bus;
125
126 return rv;
127 }
128
129 static ACPI_STATUS
acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE * res,void * context)130 acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *res, void *context)
131 {
132 ACPI_RESOURCE_ADDRESS64 addr64;
133 int32_t *bus = context;
134
135 /* Always continue the walk by returning AE_OK. */
136 if ((res->Type != ACPI_RESOURCE_TYPE_ADDRESS16) &&
137 (res->Type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
138 (res->Type != ACPI_RESOURCE_TYPE_ADDRESS64))
139 return AE_OK;
140
141 if (ACPI_FAILURE(AcpiResourceToAddress64(res, &addr64)))
142 return AE_OK;
143
144 if (addr64.ResourceType != ACPI_BUS_NUMBER_RANGE)
145 return AE_OK;
146
147 if (*bus != -1)
148 return AE_ALREADY_EXISTS;
149
150 if (addr64.Address.Minimum > 0xFFFF)
151 return AE_BAD_DATA;
152
153 *bus = (int32_t)addr64.Address.Minimum;
154
155 return AE_OK;
156 }
157
158 /*
159 * acpi_pcidev_scan:
160 *
161 * Scan the ACPI device tree for PCI devices. A node is detected as a
162 * PCI device if it has an ancestor that is a PCI root bridge and such
163 * that all intermediate nodes are PCI-to-PCI bridges. Depth-first
164 * recursive implementation.
165 *
166 * PCI root bridges do not necessarily contain an _ADR, since they already
167 * contain an _HID (ACPI 4.0a, p. 197). However we require an _ADR for
168 * all non-root PCI devices.
169 */
170 ACPI_STATUS
acpi_pcidev_scan(struct acpi_devnode * ad)171 acpi_pcidev_scan(struct acpi_devnode *ad)
172 {
173 struct acpi_devnode *child;
174 struct acpi_pci_info *ap;
175 ACPI_INTEGER val;
176 ACPI_STATUS rv;
177
178 ad->ad_pciinfo = NULL;
179
180 /*
181 * We attach PCI information only to devices that are present,
182 * enabled, and functioning properly.
183 * Note: there is a possible race condition, because _STA may
184 * have changed since ad->ad_devinfo->CurrentStatus was set.
185 */
186 if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
187 goto rec;
188
189 if (!acpi_device_present(ad->ad_handle))
190 goto rec;
191
192 if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) {
193
194 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
195
196 /*
197 * If no _SEG exist, all PCI bus segments are assumed
198 * to be in the PCI segment group 0 (ACPI 4.0, p. 277).
199 * The segment group number is conveyed in the lower
200 * 16 bits of _SEG (the other bits are all reserved).
201 */
202 rv = acpi_eval_integer(ad->ad_handle, "_SEG", &val);
203
204 if (ACPI_SUCCESS(rv))
205 ap->ap_segment = ACPI_LOWORD(val);
206
207 /* Try to get downstream bus number using _CRS first. */
208 rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_downbus);
209
210 if (ACPI_FAILURE(rv)) {
211 rv = acpi_eval_integer(ad->ad_handle, "_BBN", &val);
212
213 if (ACPI_SUCCESS(rv))
214 ap->ap_downbus = ACPI_LOWORD(val);
215 }
216
217 if (ap->ap_downbus > 255) {
218 aprint_error_dev(ad->ad_root,
219 "invalid PCI downstream bus for %s\n", ad->ad_name);
220 kmem_free(ap, sizeof(*ap));
221 goto rec;
222 }
223
224 ap->ap_flags |= ACPI_PCI_INFO_BRIDGE;
225
226 ap->ap_pc = acpi_get_pci_chipset_tag(acpi_softc, ap->ap_segment, ap->ap_downbus);
227
228 /*
229 * This ACPI node denotes a PCI root bridge, but it may also
230 * denote a PCI device on the bridge's downstream bus segment.
231 */
232 if (ad->ad_devinfo->Valid & ACPI_VALID_ADR) {
233 ap->ap_bus = ap->ap_downbus;
234 ap->ap_device =
235 ACPI_HILODWORD(ad->ad_devinfo->Address);
236 ap->ap_function =
237 ACPI_LOLODWORD(ad->ad_devinfo->Address);
238
239 if (ap->ap_device > 31 ||
240 (ap->ap_function > 7 && ap->ap_function != 0xFFFF))
241 aprint_error_dev(ad->ad_root,
242 "invalid PCI address for %s\n", ad->ad_name);
243 else
244 ap->ap_flags |= ACPI_PCI_INFO_DEVICE;
245 }
246
247 ad->ad_pciinfo = ap;
248
249 goto rec;
250 }
251
252 if ((ad->ad_parent != NULL) &&
253 (ad->ad_parent->ad_pciinfo != NULL) &&
254 (ad->ad_parent->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) &&
255 (ad->ad_devinfo->Valid & ACPI_VALID_ADR)) {
256
257 /*
258 * Our parent is a PCI root bridge or a PCI-to-PCI
259 * bridge. We have the same PCI segment number, and
260 * our bus number is its downstream bus number.
261 */
262 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
263
264 ap->ap_pc = ad->ad_parent->ad_pciinfo->ap_pc;
265 ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment;
266 ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus;
267
268 ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address);
269 ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address);
270
271 if (ap->ap_device > 31 ||
272 (ap->ap_function > 7 && ap->ap_function != 0xFFFF)) {
273 aprint_error_dev(ad->ad_root,
274 "invalid PCI address for %s\n", ad->ad_name);
275 kmem_free(ap, sizeof(*ap));
276 goto rec;
277 }
278
279 ap->ap_flags |= ACPI_PCI_INFO_DEVICE;
280
281 if (ap->ap_function == 0xFFFF) {
282 /*
283 * Assume that this device is not a PCI-to-PCI bridge.
284 * XXX: Do we need to be smarter?
285 */
286 } else {
287 /*
288 * Check whether this device is a PCI-to-PCI
289 * bridge and get its secondary bus number.
290 */
291 rv = acpi_pcidev_ppb_downbus(
292 ad->ad_parent->ad_pciinfo->ap_pc,
293 ap->ap_segment, ap->ap_bus, ap->ap_device,
294 ap->ap_function, &ap->ap_downbus);
295
296 if (ACPI_SUCCESS(rv))
297 ap->ap_flags |= ACPI_PCI_INFO_BRIDGE;
298 }
299
300 ad->ad_pciinfo = ap;
301
302 goto rec;
303 }
304
305 rec:
306 SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) {
307 rv = acpi_pcidev_scan(child);
308
309 if (ACPI_FAILURE(rv))
310 return rv;
311 }
312
313 return AE_OK;
314 }
315
316 /*
317 * acpi_pcidev_ppb_downbus:
318 *
319 * Retrieve the secondary bus number of the PCI-to-PCI bridge having the
320 * given PCI id. If successful, return AE_OK and fill *downbus.
321 * Otherwise, return an exception code and leave *downbus unchanged.
322 *
323 * XXX Need to deal with PCI segment groups (see also acpica/OsdHardware.c).
324 */
325 ACPI_STATUS
acpi_pcidev_ppb_downbus(pci_chipset_tag_t pc,uint16_t segment,uint16_t bus,uint16_t device,uint16_t function,uint16_t * downbus)326 acpi_pcidev_ppb_downbus(pci_chipset_tag_t pc, uint16_t segment, uint16_t bus,
327 uint16_t device, uint16_t function, uint16_t *downbus)
328 {
329 pcitag_t tag;
330 pcireg_t val;
331
332 if (bus > 255 || device > 31 || function > 7)
333 return AE_BAD_PARAMETER;
334
335 tag = pci_make_tag(pc, bus, device, function);
336
337 /* Check that this device exists. */
338 val = pci_conf_read(pc, tag, PCI_ID_REG);
339
340 if (PCI_VENDOR(val) == PCI_VENDOR_INVALID ||
341 PCI_VENDOR(val) == 0)
342 return AE_NOT_EXIST;
343
344 /* Check that this device is a PCI-to-PCI bridge. */
345 val = pci_conf_read(pc, tag, PCI_BHLC_REG);
346
347 if (PCI_HDRTYPE_TYPE(val) != PCI_HDRTYPE_PPB)
348 return AE_TYPE;
349
350 /* This is a PCI-to-PCI bridge. Get its secondary bus#. */
351 val = pci_conf_read(pc, tag, PCI_BRIDGE_BUS_REG);
352 *downbus = PCI_BRIDGE_BUS_NUM_SECONDARY(val);
353
354 return AE_OK;
355 }
356
357 /*
358 * acpi_pcidev_find:
359 *
360 * Finds a PCI device in the ACPI name space.
361 *
362 * Returns an ACPI device node on success and NULL on failure.
363 */
364 struct acpi_devnode *
acpi_pcidev_find(uint16_t segment,uint16_t bus,uint16_t device,uint16_t function)365 acpi_pcidev_find(uint16_t segment, uint16_t bus,
366 uint16_t device, uint16_t function)
367 {
368 struct acpi_softc *sc = acpi_softc;
369 struct acpi_devnode *ad;
370
371 if (sc == NULL)
372 return NULL;
373
374 SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) {
375
376 if (ad->ad_pciinfo != NULL &&
377 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_DEVICE) &&
378 ad->ad_pciinfo->ap_segment == segment &&
379 ad->ad_pciinfo->ap_bus == bus &&
380 ad->ad_pciinfo->ap_device == device &&
381 ad->ad_pciinfo->ap_function == function)
382 return ad;
383 }
384
385 return NULL;
386 }
387
388 /*
389 * acpi_pcidev_get_tag:
390 *
391 * Returns a PCI chipset tag for a PCI device in the ACPI name space.
392 */
393 pci_chipset_tag_t
acpi_pcidev_get_tag(uint16_t segment,uint16_t bus,uint16_t device,uint16_t function)394 acpi_pcidev_get_tag(uint16_t segment, uint16_t bus,
395 uint16_t device, uint16_t function)
396 {
397 struct acpi_devnode *ad;
398
399 ad = acpi_pcidev_find(segment, bus, device, function);
400 if (ad == NULL || ad->ad_pciinfo == NULL)
401 return NULL;
402
403 return ad->ad_pciinfo->ap_pc;
404 }
405
406 /*
407 * acpi_pciroot_find:
408 *
409 * Finds a PCI root bridge in the ACPI name space.
410 *
411 * Returns an ACPI device node on success and NULL on failure.
412 */
413 struct acpi_devnode *
acpi_pciroot_find(uint16_t segment,uint16_t bus)414 acpi_pciroot_find(uint16_t segment, uint16_t bus)
415 {
416 struct acpi_softc *sc = acpi_softc;
417 struct acpi_devnode *ad;
418
419 if (sc == NULL)
420 return NULL;
421
422 SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) {
423
424 if (ad->ad_pciinfo != NULL &&
425 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) &&
426 ad->ad_pciinfo->ap_segment == segment &&
427 ad->ad_pciinfo->ap_bus == bus)
428 return ad;
429 }
430
431 return NULL;
432 }
433
434 /*
435 * acpi_pcidev_find_dev:
436 *
437 * Returns the device corresponding to the given PCI info, or NULL
438 * if it doesn't exist.
439 */
440 device_t
acpi_pcidev_find_dev(struct acpi_devnode * ad)441 acpi_pcidev_find_dev(struct acpi_devnode *ad)
442 {
443 struct acpi_pci_info *ap;
444 struct pci_softc *pci;
445 device_t dv, pr;
446 deviter_t di;
447
448 if (ad == NULL)
449 return NULL;
450
451 if (ad->ad_pciinfo == NULL)
452 return NULL;
453
454 ap = ad->ad_pciinfo;
455
456 if (ap->ap_function == 0xFFFF)
457 return NULL;
458
459 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
460 dv != NULL; dv = deviter_next(&di)) {
461
462 pr = device_parent(dv);
463
464 if (pr == NULL || device_is_a(pr, "pci") != true)
465 continue;
466
467 pci = device_private(pr);
468
469 if (pci->sc_bus == ap->ap_bus &&
470 device_locator(dv, PCICF_DEV) == ap->ap_device &&
471 device_locator(dv, PCICF_FUNCTION) == ap->ap_function)
472 break;
473 }
474
475 deviter_release(&di);
476
477 return dv;
478 }
479
480 /*
481 * acpi_pci_bus_get_child_devhandle:
482 *
483 * Implements the "pci-bus-get-child-devhandle" device call for
484 * ACPI device handles
485 */
486 static int
acpi_pci_bus_get_child_devhandle(device_t dev,devhandle_t call_handle,void * v)487 acpi_pci_bus_get_child_devhandle(device_t dev, devhandle_t call_handle, void *v)
488 {
489 struct pci_bus_get_child_devhandle_args *args = v;
490 struct acpi_devnode *ad;
491 ACPI_HANDLE hdl;
492 int b, d, f;
493 u_int segment;
494
495 segment = pci_get_segment(args->pc);
496
497 pci_decompose_tag(args->pc, args->tag, &b, &d, &f);
498
499 ad = acpi_pcidev_find(segment, b, d, f);
500
501 if (ad != NULL && (hdl = ad->ad_handle) != NULL) {
502 /* Found it! */
503 args->devhandle = devhandle_from_acpi(call_handle, hdl);
504 return 0;
505 }
506
507 return ENODEV;
508 }
509 ACPI_DEVICE_CALL_REGISTER(PCI_BUS_GET_CHILD_DEVHANDLE_STR,
510 acpi_pci_bus_get_child_devhandle)
511