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 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 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 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 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 * 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 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 * 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 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 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