1 /* $NetBSD: acpi_pci.c,v 1.33 2021/12/20 11:17:40 skrll 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.33 2021/12/20 11:17:40 skrll 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 * UUID for _DSM control method, from PCI Firmware Specification. 63 */ 64 static UINT8 acpi_pci_dsm_uuid[ACPI_UUID_LENGTH] = { 65 0xd0, 0x37, 0xc9, 0xe5, 0x53, 0x35, 0x7a, 0x4d, 66 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d 67 }; 68 69 /* 70 * Regarding PCI Segment Groups (ACPI 4.0, p. 277): 71 * 72 * "The optional _SEG object is located under a PCI host bridge and 73 * evaluates to an integer that describes the PCI Segment Group (see PCI 74 * Firmware Specification v3.0)." 75 * 76 * "PCI Segment Group is purely a software concept managed by system 77 * firmware and used by OSPM. It is a logical collection of PCI buses 78 * (or bus segments). It is a way to logically group the PCI bus segments 79 * and PCI Express Hierarchies. _SEG is a level higher than _BBN." 80 * 81 * "PCI Segment Group supports more than 256 buses in a system by allowing 82 * the reuse of the PCI bus numbers. Within each PCI Segment Group, the bus 83 * numbers for the PCI buses must be unique. PCI buses in different PCI 84 * Segment Group are permitted to have the same bus number." 85 */ 86 87 /* 88 * Regarding PCI Base Bus Numbers (ACPI 4.0, p. 277): 89 * 90 * "For multi-root PCI platforms, the _BBN object evaluates to the PCI bus 91 * number that the BIOS assigns. This is needed to access a PCI_Config 92 * operation region for the specified bus. The _BBN object is located under 93 * a PCI host bridge and must be unique for every host bridge within a 94 * segment since it is the PCI bus number." 95 * 96 * Moreover, the ACPI FAQ (http://www.acpi.info/acpi_faq.htm) says: 97 * 98 * "For a multiple root bus machine, _BBN is required for each bus. _BBN 99 * should provide the bus number assigned to this bus by the BIOS at boot 100 * time." 101 */ 102 103 /* 104 * acpi_pcidev_pciroot_bus: 105 * 106 * Derive the PCI bus number of a PCI root bridge from its resources. 107 * If successful, return AE_OK and fill *busp. Otherwise, return an 108 * exception code and leave *busp unchanged. 109 */ 110 ACPI_STATUS 111 acpi_pcidev_pciroot_bus(ACPI_HANDLE handle, uint16_t *busp) 112 { 113 ACPI_STATUS rv; 114 int32_t bus; 115 116 bus = -1; 117 118 /* 119 * XXX: Use the ACPI resource parsing functions (acpi_resource.c) 120 * once bus number ranges have been implemented there. 121 */ 122 rv = AcpiWalkResources(handle, "_CRS", 123 acpi_pcidev_pciroot_bus_callback, &bus); 124 125 if (ACPI_FAILURE(rv)) 126 return rv; 127 128 if (bus == -1) 129 return AE_NOT_EXIST; 130 131 /* Here it holds that 0 <= bus <= 0xFFFF. */ 132 *busp = (uint16_t)bus; 133 134 return rv; 135 } 136 137 static ACPI_STATUS 138 acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *res, void *context) 139 { 140 ACPI_RESOURCE_ADDRESS64 addr64; 141 int32_t *bus = context; 142 143 /* Always continue the walk by returning AE_OK. */ 144 if ((res->Type != ACPI_RESOURCE_TYPE_ADDRESS16) && 145 (res->Type != ACPI_RESOURCE_TYPE_ADDRESS32) && 146 (res->Type != ACPI_RESOURCE_TYPE_ADDRESS64)) 147 return AE_OK; 148 149 if (ACPI_FAILURE(AcpiResourceToAddress64(res, &addr64))) 150 return AE_OK; 151 152 if (addr64.ResourceType != ACPI_BUS_NUMBER_RANGE) 153 return AE_OK; 154 155 if (*bus != -1) 156 return AE_ALREADY_EXISTS; 157 158 if (addr64.Address.Minimum > 0xFFFF) 159 return AE_BAD_DATA; 160 161 *bus = (int32_t)addr64.Address.Minimum; 162 163 return AE_OK; 164 } 165 166 /* 167 * acpi_pcidev_scan: 168 * 169 * Scan the ACPI device tree for PCI devices. A node is detected as a 170 * PCI device if it has an ancestor that is a PCI root bridge and such 171 * that all intermediate nodes are PCI-to-PCI bridges. Depth-first 172 * recursive implementation. 173 * 174 * PCI root bridges do not necessarily contain an _ADR, since they already 175 * contain an _HID (ACPI 4.0a, p. 197). However we require an _ADR for 176 * all non-root PCI devices. 177 */ 178 ACPI_STATUS 179 acpi_pcidev_scan(struct acpi_devnode *ad) 180 { 181 struct acpi_devnode *child; 182 struct acpi_pci_info *ap; 183 ACPI_INTEGER val; 184 ACPI_STATUS rv; 185 186 ad->ad_pciinfo = NULL; 187 188 /* 189 * We attach PCI information only to devices that are present, 190 * enabled, and functioning properly. 191 * Note: there is a possible race condition, because _STA may 192 * have changed since ad->ad_devinfo->CurrentStatus was set. 193 */ 194 if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) 195 goto rec; 196 197 if (!acpi_device_present(ad->ad_handle)) 198 goto rec; 199 200 if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) { 201 202 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP); 203 204 /* 205 * If no _SEG exist, all PCI bus segments are assumed 206 * to be in the PCI segment group 0 (ACPI 4.0, p. 277). 207 * The segment group number is conveyed in the lower 208 * 16 bits of _SEG (the other bits are all reserved). 209 */ 210 rv = acpi_eval_integer(ad->ad_handle, "_SEG", &val); 211 212 if (ACPI_SUCCESS(rv)) 213 ap->ap_segment = ACPI_LOWORD(val); 214 215 /* Try to get downstream bus number using _CRS first. */ 216 rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_downbus); 217 218 if (ACPI_FAILURE(rv)) { 219 rv = acpi_eval_integer(ad->ad_handle, "_BBN", &val); 220 221 if (ACPI_SUCCESS(rv)) 222 ap->ap_downbus = ACPI_LOWORD(val); 223 } 224 225 if (ap->ap_downbus > 255) { 226 aprint_error_dev(ad->ad_root, 227 "invalid PCI downstream bus for %s\n", ad->ad_name); 228 kmem_free(ap, sizeof(*ap)); 229 goto rec; 230 } 231 232 ap->ap_flags |= ACPI_PCI_INFO_BRIDGE; 233 234 ap->ap_pc = acpi_get_pci_chipset_tag(acpi_softc, ap->ap_segment, ap->ap_downbus); 235 236 /* 237 * This ACPI node denotes a PCI root bridge, but it may also 238 * denote a PCI device on the bridge's downstream bus segment. 239 */ 240 if (ad->ad_devinfo->Valid & ACPI_VALID_ADR) { 241 ap->ap_bus = ap->ap_downbus; 242 ap->ap_device = 243 ACPI_HILODWORD(ad->ad_devinfo->Address); 244 ap->ap_function = 245 ACPI_LOLODWORD(ad->ad_devinfo->Address); 246 247 if (ap->ap_device > 31 || 248 (ap->ap_function > 7 && ap->ap_function != 0xFFFF)) 249 aprint_error_dev(ad->ad_root, 250 "invalid PCI address for %s\n", ad->ad_name); 251 else 252 ap->ap_flags |= ACPI_PCI_INFO_DEVICE; 253 } 254 255 ad->ad_pciinfo = ap; 256 257 goto rec; 258 } 259 260 if ((ad->ad_parent != NULL) && 261 (ad->ad_parent->ad_pciinfo != NULL) && 262 (ad->ad_parent->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) && 263 (ad->ad_devinfo->Valid & ACPI_VALID_ADR)) { 264 265 /* 266 * Our parent is a PCI root bridge or a PCI-to-PCI 267 * bridge. We have the same PCI segment number, and 268 * our bus number is its downstream bus number. 269 */ 270 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP); 271 272 ap->ap_pc = ad->ad_parent->ad_pciinfo->ap_pc; 273 ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment; 274 ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus; 275 276 ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address); 277 ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address); 278 279 if (ap->ap_device > 31 || 280 (ap->ap_function > 7 && ap->ap_function != 0xFFFF)) { 281 aprint_error_dev(ad->ad_root, 282 "invalid PCI address for %s\n", ad->ad_name); 283 kmem_free(ap, sizeof(*ap)); 284 goto rec; 285 } 286 287 ap->ap_flags |= ACPI_PCI_INFO_DEVICE; 288 289 if (ap->ap_function == 0xFFFF) { 290 /* 291 * Assume that this device is not a PCI-to-PCI bridge. 292 * XXX: Do we need to be smarter? 293 */ 294 } else { 295 /* 296 * Check whether this device is a PCI-to-PCI 297 * bridge and get its secondary bus number. 298 */ 299 rv = acpi_pcidev_ppb_downbus( 300 ad->ad_parent->ad_pciinfo->ap_pc, 301 ap->ap_segment, ap->ap_bus, ap->ap_device, 302 ap->ap_function, &ap->ap_downbus); 303 304 if (ACPI_SUCCESS(rv)) 305 ap->ap_flags |= ACPI_PCI_INFO_BRIDGE; 306 } 307 308 ad->ad_pciinfo = ap; 309 310 goto rec; 311 } 312 313 rec: 314 SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) { 315 rv = acpi_pcidev_scan(child); 316 317 if (ACPI_FAILURE(rv)) 318 return rv; 319 } 320 321 return AE_OK; 322 } 323 324 /* 325 * acpi_pcidev_ppb_downbus: 326 * 327 * Retrieve the secondary bus number of the PCI-to-PCI bridge having the 328 * given PCI id. If successful, return AE_OK and fill *downbus. 329 * Otherwise, return an exception code and leave *downbus unchanged. 330 * 331 * XXX Need to deal with PCI segment groups (see also acpica/OsdHardware.c). 332 */ 333 ACPI_STATUS 334 acpi_pcidev_ppb_downbus(pci_chipset_tag_t pc, uint16_t segment, uint16_t bus, 335 uint16_t device, uint16_t function, uint16_t *downbus) 336 { 337 pcitag_t tag; 338 pcireg_t val; 339 340 if (bus > 255 || device > 31 || function > 7) 341 return AE_BAD_PARAMETER; 342 343 tag = pci_make_tag(pc, bus, device, function); 344 345 /* Check that this device exists. */ 346 val = pci_conf_read(pc, tag, PCI_ID_REG); 347 348 if (PCI_VENDOR(val) == PCI_VENDOR_INVALID || 349 PCI_VENDOR(val) == 0) 350 return AE_NOT_EXIST; 351 352 /* Check that this device is a PCI-to-PCI bridge. */ 353 val = pci_conf_read(pc, tag, PCI_BHLC_REG); 354 355 if (PCI_HDRTYPE_TYPE(val) != PCI_HDRTYPE_PPB) 356 return AE_TYPE; 357 358 /* This is a PCI-to-PCI bridge. Get its secondary bus#. */ 359 val = pci_conf_read(pc, tag, PCI_BRIDGE_BUS_REG); 360 *downbus = PCI_BRIDGE_BUS_NUM_SECONDARY(val); 361 362 return AE_OK; 363 } 364 365 /* 366 * acpi_pcidev_find: 367 * 368 * Finds a PCI device in the ACPI name space. 369 * 370 * Returns an ACPI device node on success and NULL on failure. 371 */ 372 struct acpi_devnode * 373 acpi_pcidev_find(uint16_t segment, uint16_t bus, 374 uint16_t device, uint16_t function) 375 { 376 struct acpi_softc *sc = acpi_softc; 377 struct acpi_devnode *ad; 378 379 if (sc == NULL) 380 return NULL; 381 382 SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) { 383 384 if (ad->ad_pciinfo != NULL && 385 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_DEVICE) && 386 ad->ad_pciinfo->ap_segment == segment && 387 ad->ad_pciinfo->ap_bus == bus && 388 ad->ad_pciinfo->ap_device == device && 389 ad->ad_pciinfo->ap_function == function) 390 return ad; 391 } 392 393 return NULL; 394 } 395 396 /* 397 * acpi_pcidev_get_tag: 398 * 399 * Returns a PCI chipset tag for a PCI device in the ACPI name space. 400 */ 401 pci_chipset_tag_t 402 acpi_pcidev_get_tag(uint16_t segment, uint16_t bus, 403 uint16_t device, uint16_t function) 404 { 405 struct acpi_devnode *ad; 406 407 ad = acpi_pcidev_find(segment, bus, device, function); 408 if (ad == NULL || ad->ad_pciinfo == NULL) 409 return NULL; 410 411 return ad->ad_pciinfo->ap_pc; 412 } 413 414 /* 415 * acpi_pciroot_find: 416 * 417 * Finds a PCI root bridge in the ACPI name space. 418 * 419 * Returns an ACPI device node on success and NULL on failure. 420 */ 421 struct acpi_devnode * 422 acpi_pciroot_find(uint16_t segment, uint16_t bus) 423 { 424 struct acpi_softc *sc = acpi_softc; 425 struct acpi_devnode *ad; 426 427 if (sc == NULL) 428 return NULL; 429 430 SIMPLEQ_FOREACH(ad, &sc->sc_head, ad_list) { 431 432 if (ad->ad_pciinfo != NULL && 433 (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) && 434 ad->ad_pciinfo->ap_segment == segment && 435 ad->ad_pciinfo->ap_bus == bus) 436 return ad; 437 } 438 439 return NULL; 440 } 441 442 /* 443 * acpi_pcidev_find_dev: 444 * 445 * Returns the device corresponding to the given PCI info, or NULL 446 * if it doesn't exist. 447 */ 448 device_t 449 acpi_pcidev_find_dev(struct acpi_devnode *ad) 450 { 451 struct acpi_pci_info *ap; 452 struct pci_softc *pci; 453 device_t dv, pr; 454 deviter_t di; 455 456 if (ad == NULL) 457 return NULL; 458 459 if (ad->ad_pciinfo == NULL) 460 return NULL; 461 462 ap = ad->ad_pciinfo; 463 464 if (ap->ap_function == 0xFFFF) 465 return NULL; 466 467 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); 468 dv != NULL; dv = deviter_next(&di)) { 469 470 pr = device_parent(dv); 471 472 if (pr == NULL || device_is_a(pr, "pci") != true) 473 continue; 474 475 if (dv->dv_locators == NULL) /* This should not happen. */ 476 continue; 477 478 pci = device_private(pr); 479 480 if (pci->sc_bus == ap->ap_bus && 481 device_locator(dv, PCICF_DEV) == ap->ap_device && 482 device_locator(dv, PCICF_FUNCTION) == ap->ap_function) 483 break; 484 } 485 486 deviter_release(&di); 487 488 return dv; 489 } 490 491 /* 492 * acpi_pci_ignore_boot_config: 493 * 494 * Returns 1 if the operating system may ignore the boot configuration 495 * of PCI resources. 496 */ 497 ACPI_INTEGER 498 acpi_pci_ignore_boot_config(ACPI_HANDLE handle) 499 { 500 ACPI_OBJECT *pobj = NULL; 501 ACPI_INTEGER ret; 502 503 /* 504 * This one is a little confusing, but the result of 505 * evaluating _DSM #5 is: 506 * 507 * 0: The operating system may not ignore the boot configuration 508 * of PCI resources. 509 * 510 * 1: The operating system may ignore the boot configuration of 511 * PCI resources, and reconfigure or rebalance these resources 512 * in the hierarchy as required. 513 */ 514 515 if (ACPI_FAILURE(acpi_dsm(handle, acpi_pci_dsm_uuid, 516 1, 5, NULL, &pobj))) { 517 /* 518 * In the absence of _DSM #5, we may assume that the 519 * boot config can be ignored. 520 */ 521 return 1; 522 } 523 524 /* 525 * ...and we default to "may ignore" in the event that the 526 * method returns nonsense. 527 */ 528 ret = 1; 529 530 if (pobj != NULL) { 531 switch (pobj->Type) { 532 case ACPI_TYPE_INTEGER: 533 ret = pobj->Integer.Value; 534 break; 535 536 case ACPI_TYPE_PACKAGE: 537 if (pobj->Package.Count == 1 && 538 pobj->Package.Elements[0].Type == ACPI_TYPE_INTEGER) 539 ret = pobj->Package.Elements[0].Integer.Value; 540 break; 541 } 542 ACPI_FREE(pobj); 543 } 544 545 return ret; 546 } 547 548 /* 549 * acpi_pci_bus_get_child_devhandle: 550 * 551 * Implements the "pci-bus-get-child-devhandle" device call for 552 * ACPI device handles 553 */ 554 static int 555 acpi_pci_bus_get_child_devhandle(device_t dev, devhandle_t call_handle, void *v) 556 { 557 struct pci_bus_get_child_devhandle_args *args = v; 558 struct acpi_devnode *ad; 559 ACPI_HANDLE hdl; 560 int b, d, f; 561 u_int segment; 562 563 #ifdef __HAVE_PCI_GET_SEGMENT 564 segment = pci_get_segment(args->pc); 565 #else 566 segment = 0; 567 #endif /* __HAVE_PCI_GET_SEGMENT */ 568 569 pci_decompose_tag(args->pc, args->tag, &b, &d, &f); 570 571 ad = acpi_pcidev_find(segment, b, d, f); 572 573 if (ad != NULL && (hdl = ad->ad_handle) != NULL) { 574 /* Found it! */ 575 args->devhandle = devhandle_from_acpi(hdl); 576 return 0; 577 } 578 579 return ENODEV; 580 } 581 ACPI_DEVICE_CALL_REGISTER(PCI_BUS_GET_CHILD_DEVHANDLE_STR, 582 acpi_pci_bus_get_child_devhandle) 583