1 /* $NetBSD: acpi_mcfg.c,v 1.17 2019/10/14 00:15:13 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (C) 2015 NONAKA Kimihiro <nonaka@NetBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "opt_pci.h" 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: acpi_mcfg.c,v 1.17 2019/10/14 00:15:13 jmcneill Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/device.h> 35 #include <sys/kmem.h> 36 #include <sys/systm.h> 37 #include <sys/extent.h> 38 39 #include <dev/pci/pcireg.h> 40 #include <dev/pci/pcivar.h> 41 #include <dev/pci/pciconf.h> 42 #include <dev/pci/pcidevs.h> 43 44 #include <dev/acpi/acpireg.h> 45 #include <dev/acpi/acpivar.h> 46 #include <dev/acpi/acpi_mcfg.h> 47 48 #include "locators.h" 49 50 #define _COMPONENT ACPI_RESOURCE_COMPONENT 51 ACPI_MODULE_NAME ("acpi_mcfg") 52 53 #define EXTCONF_OFFSET(d, f, r) ((((d) * 8 + (f)) * PCI_EXTCONF_SIZE) + (r)) 54 55 #define PCIDEV_SET_VALID(mb, d, f) ((mb)->valid_devs[(d)] |= __BIT((f))) 56 #define PCIDEV_SET_INVALID(mb, d, f) ((mb)->valid_devs[(d)] &= ~__BIT((f))) 57 #define PCIDEV_IS_VALID(mb, d, f) ((mb)->valid_devs[(d)] & __BIT((f))) 58 59 #define EXTCONF_SET_VALID(mb, d, f) ((mb)->valid_extconf[(d)] |= __BIT((f))) 60 #define EXTCONF_SET_INVALID(mb, d, f) ((mb)->valid_extconf[(d)] &= ~__BIT((f))) 61 #define EXTCONF_IS_VALID(mb, d, f) ((mb)->valid_extconf[(d)] & __BIT((f))) 62 63 struct mcfg_segment { 64 uint64_t ms_address; /* Base address */ 65 int ms_segment; /* Segment # */ 66 int ms_bus_start; /* Start bus # */ 67 int ms_bus_end; /* End bus # */ 68 bus_space_tag_t ms_bst; 69 struct mcfg_bus { 70 bus_space_handle_t bsh[32][8]; 71 uint8_t valid_devs[32]; 72 uint8_t valid_extconf[32]; 73 int valid_ndevs; 74 pcitag_t last_probed; 75 } *ms_bus; 76 }; 77 78 static struct mcfg_segment *mcfg_segs; 79 static int mcfg_nsegs; 80 static ACPI_TABLE_MCFG *mcfg; 81 static int mcfg_inited; 82 static struct acpi_softc *acpi_sc; 83 84 static const struct acpimcfg_ops mcfg_default_ops = { 85 .ao_validate = acpimcfg_default_validate, 86 87 .ao_read = acpimcfg_default_read, 88 .ao_write = acpimcfg_default_write, 89 }; 90 static const struct acpimcfg_ops *mcfg_ops = &mcfg_default_ops; 91 92 /* 93 * default operations. 94 */ 95 bool 96 acpimcfg_default_validate(uint64_t address, int bus_start, int *bus_end) 97 { 98 99 /* Always Ok */ 100 return true; 101 } 102 103 uint32_t 104 acpimcfg_default_read(bus_space_tag_t bst, bus_space_handle_t bsh, 105 bus_addr_t addr) 106 { 107 108 return bus_space_read_4(bst, bsh, addr); 109 } 110 111 void 112 acpimcfg_default_write(bus_space_tag_t bst, bus_space_handle_t bsh, 113 bus_addr_t addr, uint32_t data) 114 { 115 116 bus_space_write_4(bst, bsh, addr, data); 117 } 118 119 120 /* 121 * Check MCFG memory region at system resource 122 */ 123 struct acpimcfg_memrange { 124 const char *hid; 125 uint64_t address; 126 int bus_start; 127 int bus_end; 128 bool found; 129 }; 130 131 static ACPI_STATUS 132 acpimcfg_parse_callback(ACPI_RESOURCE *res, void *ctx) 133 { 134 struct acpimcfg_memrange *mr = ctx; 135 const char *type; 136 uint64_t size, mapaddr, mapsize; 137 int n; 138 139 switch (res->Type) { 140 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 141 type = "FIXED_MEMORY32"; 142 mapaddr = res->Data.FixedMemory32.Address; 143 mapsize = res->Data.FixedMemory32.AddressLength; 144 break; 145 146 case ACPI_RESOURCE_TYPE_ADDRESS32: 147 /* XXX Only fixed size supported for now */ 148 if (res->Data.Address32.Address.AddressLength == 0 || 149 res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) 150 goto out; 151 152 if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE) 153 goto out; 154 155 if (res->Data.Address32.MinAddressFixed != ACPI_ADDRESS_FIXED || 156 res->Data.Address32.MaxAddressFixed != ACPI_ADDRESS_FIXED) 157 goto out; 158 159 type = "ADDRESS32"; 160 mapaddr = res->Data.Address32.Address.Minimum; 161 mapsize = res->Data.Address32.Address.AddressLength; 162 break; 163 164 #ifdef _LP64 165 case ACPI_RESOURCE_TYPE_ADDRESS64: 166 /* XXX Only fixed size supported for now */ 167 if (res->Data.Address64.Address.AddressLength == 0 || 168 res->Data.Address64.ProducerConsumer != ACPI_CONSUMER) 169 goto out; 170 171 if (res->Data.Address64.ResourceType != ACPI_MEMORY_RANGE) 172 goto out; 173 174 if (res->Data.Address64.MinAddressFixed != ACPI_ADDRESS_FIXED || 175 res->Data.Address64.MaxAddressFixed != ACPI_ADDRESS_FIXED) 176 goto out; 177 178 type = "ADDRESS64"; 179 mapaddr = res->Data.Address64.Address.Minimum; 180 mapsize = res->Data.Address64.Address.AddressLength; 181 break; 182 #endif 183 184 default: 185 out: 186 aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: Type=%d\n", 187 mr->hid, res->Type); 188 return_ACPI_STATUS(AE_OK); 189 } 190 191 aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: Type=%d(%s), " 192 "Address=0x%016" PRIx64 ", Length=0x%016" PRIx64 "\n", 193 mr->hid, res->Type, type, mapaddr, mapsize); 194 195 if (mr->address < mapaddr || mr->address >= mapaddr + mapsize) 196 return_ACPI_STATUS(AE_OK); 197 198 size = (mr->bus_end - mr->bus_start + 1) * ACPIMCFG_SIZE_PER_BUS; 199 200 /* full map */ 201 if (mr->address + size <= mapaddr + mapsize) { 202 mr->found = true; 203 return_ACPI_STATUS(AE_CTRL_TERMINATE); 204 } 205 206 /* partial map */ 207 n = (mapsize - (mr->address - mapaddr)) / ACPIMCFG_SIZE_PER_BUS; 208 /* bus_start == bus_end is not allowed. */ 209 if (n > 1) { 210 mr->bus_end = mr->bus_start + n - 1; 211 mr->found = true; 212 return_ACPI_STATUS(AE_CTRL_TERMINATE); 213 } 214 215 aprint_debug_dev(acpi_sc->sc_dev, "MCFG: bus %d-%d, " 216 "address 0x%016" PRIx64 ": invalid size: request 0x%016" PRIx64 217 ", actual 0x%016" PRIx64 "\n", 218 mr->bus_start, mr->bus_end, mr->address, size, mapsize); 219 220 return_ACPI_STATUS(AE_OK); 221 } 222 223 static ACPI_STATUS 224 acpimcfg_check_system_resource(ACPI_HANDLE handle, UINT32 level, void *ctx, 225 void **retval) 226 { 227 struct acpimcfg_memrange *mr = ctx; 228 ACPI_STATUS status; 229 230 status = AcpiWalkResources(handle, "_CRS", acpimcfg_parse_callback, mr); 231 if (ACPI_FAILURE(status)) 232 return_ACPI_STATUS(status); 233 234 if (mr->found) 235 return_ACPI_STATUS(AE_CTRL_TERMINATE); 236 237 aprint_debug_dev(acpi_sc->sc_dev, "MCFG: %s: bus %d-%d, " 238 "address 0x%016" PRIx64 ": no valid region\n", mr->hid, 239 mr->bus_start, mr->bus_end, mr->address); 240 241 return_ACPI_STATUS(AE_OK); 242 } 243 244 static bool 245 acpimcfg_find_system_resource(uint64_t address, int bus_start, int *bus_end) 246 { 247 static const char *system_resource_hid[] = { 248 "PNP0C01", /* System Board */ 249 "PNP0C02" /* General ID for reserving resources */ 250 }; 251 struct acpimcfg_memrange mr; 252 ACPI_STATUS status; 253 int i; 254 255 mr.address = address; 256 mr.bus_start = bus_start; 257 mr.bus_end = *bus_end; 258 mr.found = false; 259 260 for (i = 0; i < __arraycount(system_resource_hid); i++) { 261 mr.hid = system_resource_hid[i]; 262 status = AcpiGetDevices(__UNCONST(system_resource_hid[i]), 263 acpimcfg_check_system_resource, &mr, NULL); 264 if (ACPI_FAILURE(status)) 265 continue; 266 if (mr.found) { 267 *bus_end = mr.bus_end; 268 return true; 269 } 270 } 271 return false; 272 } 273 274 275 /* 276 * ACPI MCFG 277 */ 278 void 279 acpimcfg_probe(struct acpi_softc *sc) 280 { 281 ACPI_MCFG_ALLOCATION *ama; 282 ACPI_STATUS status; 283 uint32_t offset; 284 int i, nsegs; 285 286 if (acpi_sc != NULL) 287 panic("acpi_sc != NULL"); 288 acpi_sc = sc; 289 290 status = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); 291 if (ACPI_FAILURE(status)) { 292 mcfg = NULL; 293 return; 294 } 295 296 nsegs = 0; 297 offset = sizeof(ACPI_TABLE_MCFG); 298 ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset); 299 for (i = 0; offset + sizeof(ACPI_MCFG_ALLOCATION) <= 300 mcfg->Header.Length; i++) { 301 aprint_debug_dev(sc->sc_dev, 302 "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 "\n", 303 ama->PciSegment, ama->StartBusNumber, ama->EndBusNumber, 304 ama->Address); 305 nsegs++; 306 offset += sizeof(ACPI_MCFG_ALLOCATION); 307 ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset); 308 } 309 if (nsegs == 0) { 310 mcfg = NULL; 311 return; 312 } 313 314 mcfg_segs = kmem_zalloc(sizeof(*mcfg_segs) * nsegs, KM_SLEEP); 315 mcfg_nsegs = nsegs; 316 } 317 318 int 319 acpimcfg_init(bus_space_tag_t memt, const struct acpimcfg_ops *ops) 320 { 321 ACPI_MCFG_ALLOCATION *ama; 322 struct mcfg_segment *seg; 323 uint32_t offset; 324 int i, n, nsegs, bus_end; 325 326 if (mcfg == NULL) 327 return ENXIO; 328 329 if (mcfg_inited) 330 return 0; 331 332 if (ops != NULL) 333 mcfg_ops = ops; 334 335 nsegs = 0; 336 offset = sizeof(ACPI_TABLE_MCFG); 337 ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset); 338 for (i = 0; offset < mcfg->Header.Length; i++) { 339 #ifndef _LP64 340 if (ama->Address >= 0x100000000ULL) { 341 aprint_debug_dev(acpi_sc->sc_dev, 342 "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 343 ": ignore (64bit address)\n", ama->PciSegment, 344 ama->StartBusNumber, ama->EndBusNumber, 345 ama->Address); 346 goto next; 347 } 348 #endif 349 /* 350 * Some (broken?) BIOSen have an MCFG table for an empty 351 * bus range. Ignore those tables. 352 */ 353 if (ama->StartBusNumber > ama->EndBusNumber) { 354 aprint_debug_dev(acpi_sc->sc_dev, 355 "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 356 ": ignore (bus %d > %d)\n", ama->PciSegment, 357 ama->StartBusNumber, ama->EndBusNumber, 358 ama->Address, ama->StartBusNumber, 359 ama->EndBusNumber); 360 goto next; 361 } 362 363 /* Validate MCFG memory range */ 364 bus_end = ama->EndBusNumber; 365 if (mcfg_ops->ao_validate != NULL && 366 !mcfg_ops->ao_validate(ama->Address, ama->StartBusNumber, 367 &bus_end)) { 368 if (!acpimcfg_find_system_resource( ama->Address, 369 ama->StartBusNumber, &bus_end)) { 370 aprint_debug_dev(acpi_sc->sc_dev, 371 "MCFG: segment %d, bus %d-%d, " 372 "address 0x%016" PRIx64 373 ": ignore (invalid address)\n", 374 ama->PciSegment, 375 ama->StartBusNumber, ama->EndBusNumber, 376 ama->Address); 377 goto next; 378 } 379 } 380 if (ama->EndBusNumber != bus_end) { 381 aprint_debug_dev(acpi_sc->sc_dev, 382 "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 383 " -> bus %d-%d\n", ama->PciSegment, 384 ama->StartBusNumber, ama->EndBusNumber, 385 ama->Address, ama->StartBusNumber, bus_end); 386 } 387 388 #ifndef __HAVE_PCI_GET_SEGMENT 389 if (ama->PciSegment != 0) { 390 aprint_debug_dev(acpi_sc->sc_dev, 391 "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 392 ": ignore (non PCI segment 0)\n", ama->PciSegment, 393 ama->StartBusNumber, bus_end, ama->Address); 394 goto next; 395 } 396 #endif 397 398 seg = &mcfg_segs[nsegs++]; 399 seg->ms_address = ama->Address; 400 seg->ms_segment = ama->PciSegment; 401 seg->ms_bus_start = ama->StartBusNumber; 402 seg->ms_bus_end = bus_end; 403 seg->ms_bst = memt; 404 n = seg->ms_bus_end - seg->ms_bus_start + 1; 405 seg->ms_bus = kmem_zalloc(sizeof(*seg->ms_bus) * n, KM_SLEEP); 406 407 next: 408 offset += sizeof(ACPI_MCFG_ALLOCATION); 409 ama = ACPI_ADD_PTR(ACPI_MCFG_ALLOCATION, mcfg, offset); 410 } 411 if (nsegs == 0) 412 return ENOENT; 413 414 for (i = 0; i < nsegs; i++) { 415 seg = &mcfg_segs[i]; 416 aprint_verbose_dev(acpi_sc->sc_dev, 417 "MCFG: segment %d, bus %d-%d, address 0x%016" PRIx64 "\n", 418 seg->ms_segment, seg->ms_bus_start, seg->ms_bus_end, 419 seg->ms_address); 420 } 421 422 /* Update # of segment */ 423 mcfg_nsegs = nsegs; 424 mcfg_inited = true; 425 426 return 0; 427 } 428 429 static int 430 acpimcfg_ext_conf_is_aliased(pci_chipset_tag_t pc, pcitag_t tag) 431 { 432 pcireg_t id; 433 int i; 434 435 id = pci_conf_read(pc, tag, PCI_ID_REG); 436 for (i = PCI_CONF_SIZE; i < PCI_EXTCONF_SIZE; i += PCI_CONF_SIZE) { 437 if (pci_conf_read(pc, tag, i) != id) 438 return false; 439 } 440 return true; 441 } 442 443 static struct mcfg_segment * 444 acpimcfg_get_segment(pci_chipset_tag_t pc, int bus) 445 { 446 struct mcfg_segment *seg; 447 u_int segment; 448 int i; 449 450 #ifdef __HAVE_PCI_GET_SEGMENT 451 segment = pci_get_segment(pc); 452 #else 453 segment = 0; 454 #endif 455 456 for (i = 0; i < mcfg_nsegs; i++) { 457 seg = &mcfg_segs[i]; 458 if (segment == seg->ms_segment && 459 bus >= seg->ms_bus_start && bus <= seg->ms_bus_end) 460 return seg; 461 } 462 return NULL; 463 } 464 465 static int 466 acpimcfg_device_probe(const struct pci_attach_args *pa) 467 { 468 pci_chipset_tag_t pc = pa->pa_pc; 469 struct mcfg_segment *seg; 470 struct mcfg_bus *mb; 471 pcitag_t tag; 472 pcireg_t reg; 473 int bus = pa->pa_bus; 474 int dev = pa->pa_device; 475 int func = pa->pa_function; 476 int last_dev, last_func, end_func; 477 int alias = 0; 478 const struct pci_quirkdata *qd; 479 bool force_hasextcnf = false; 480 bool force_noextcnf = false; 481 int i, j; 482 483 seg = acpimcfg_get_segment(pc, bus); 484 if (seg == NULL) 485 return 0; 486 487 mb = &seg->ms_bus[bus - seg->ms_bus_start]; 488 tag = pci_make_tag(pc, bus, dev, func); 489 490 /* Mark invalid between last probed device to probed device. */ 491 pci_decompose_tag(pc, mb->last_probed, NULL, &last_dev, &last_func); 492 if (dev != 0 || func != 0) { 493 for (i = last_dev; i <= dev; i++) { 494 end_func = (i == dev) ? func : 8; 495 for (j = last_func; j < end_func; j++) { 496 if (i == last_dev && j == last_func) 497 continue; 498 PCIDEV_SET_INVALID(mb, i, j); 499 } 500 last_func = 0; 501 } 502 } 503 mb->last_probed = tag; 504 505 reg = pci_conf_read(pc, tag, PCI_ID_REG); 506 qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg)); 507 if (qd != NULL && (qd->quirks & PCI_QUIRK_HASEXTCNF) != 0) 508 force_hasextcnf = true; 509 if (qd != NULL && (qd->quirks & PCI_QUIRK_NOEXTCNF) != 0) 510 force_noextcnf = true; 511 512 /* Probe extended configuration space. */ 513 if ((!force_hasextcnf) && ((force_noextcnf) || 514 ((reg = pci_conf_read(pc, tag, PCI_CONF_SIZE)) == (pcireg_t)-1) 515 || (reg == 0) 516 || (alias = acpimcfg_ext_conf_is_aliased(pc, tag)))) { 517 aprint_debug_dev(acpi_sc->sc_dev, 518 "MCFG: %03d:%02d:%d: invalid config space " 519 "(cfg[0x%03x]=0x%08x, alias=%s)\n", bus, dev, func, 520 PCI_CONF_SIZE, reg, alias ? "true" : "false"); 521 EXTCONF_SET_INVALID(mb, dev, func); 522 } 523 524 aprint_debug_dev(acpi_sc->sc_dev, 525 "MCFG: %03d:%02d:%d: Ok (cfg[0x%03x]=0x%08x extconf=%c)\n", 526 bus, dev, func, PCI_CONF_SIZE, reg, 527 EXTCONF_IS_VALID(mb, dev, func) ? 'Y' : 'N'); 528 mb->valid_ndevs++; 529 530 return 0; 531 } 532 533 #ifdef PCI_MACHDEP_ENUMERATE_BUS 534 #define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS 535 #endif 536 537 static void 538 acpimcfg_scan_bus(struct pci_softc *sc, pci_chipset_tag_t pc, int bus) 539 { 540 static const int wildcard[PCICF_NLOCS] = { 541 PCICF_DEV_DEFAULT, PCICF_FUNCTION_DEFAULT 542 }; 543 544 sc->sc_bus = bus; /* XXX */ 545 sc->sc_pc = pc; 546 547 pci_enumerate_bus(sc, wildcard, acpimcfg_device_probe, NULL); 548 } 549 550 int 551 acpimcfg_map_bus(device_t self, pci_chipset_tag_t pc, int bus) 552 { 553 struct pci_softc *sc = device_private(self); 554 struct mcfg_segment *seg = NULL; 555 struct mcfg_bus *mb; 556 bus_space_handle_t bsh; 557 bus_addr_t baddr; 558 pcitag_t tag; 559 pcireg_t reg; 560 bool is_e7520_mch; 561 int boff; 562 int last_dev, last_func; 563 int i, j; 564 int error; 565 566 if (!mcfg_inited) 567 return ENXIO; 568 569 seg = acpimcfg_get_segment(pc, bus); 570 if (seg == NULL) 571 return ENOENT; 572 573 boff = bus - seg->ms_bus_start; 574 if (seg->ms_bus[boff].valid_ndevs > 0) 575 return 0; 576 577 mb = &seg->ms_bus[boff]; 578 baddr = seg->ms_address + (bus * ACPIMCFG_SIZE_PER_BUS); 579 580 /* Map extended configration space of all dev/func. */ 581 error = bus_space_map(seg->ms_bst, baddr, ACPIMCFG_SIZE_PER_BUS, 0, 582 &bsh); 583 if (error != 0) 584 return error; 585 for (i = 0; i < 32; i++) { 586 for (j = 0; j < 8; j++) { 587 error = bus_space_subregion(seg->ms_bst, bsh, 588 EXTCONF_OFFSET(i, j, 0), PCI_EXTCONF_SIZE, 589 &mb->bsh[i][j]); 590 if (error != 0) 591 break; 592 } 593 } 594 if (error != 0) 595 return error; 596 597 aprint_debug("\n"); 598 599 /* Probe extended configuration space of all devices. */ 600 memset(mb->valid_devs, 0xff, sizeof(mb->valid_devs)); 601 memset(mb->valid_extconf, 0xff, sizeof(mb->valid_extconf)); 602 mb->valid_ndevs = 0; 603 mb->last_probed = pci_make_tag(pc, bus, 0, 0); 604 605 /* 606 * On an Intel E7520 we have to temporarily disable 607 * Enhanced Config Access error detection and reporting 608 * by setting the appropriate error mask in HI_ERRMASK register. 609 * 610 * See "Intel E7520 Memory Controller Hub (MCH) Datasheet", 611 * Document 303006-002, pg. 82 612 */ 613 tag = pci_make_tag(pc, 0, 0, 1); 614 reg = pci_conf_read(pc, tag, PCI_ID_REG); 615 is_e7520_mch = (reg == 616 PCI_ID_CODE(PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_E7525_MCHER)); 617 if (is_e7520_mch) { 618 reg = pci_conf_read(pc, tag, 0x54); 619 pci_conf_write(pc, tag, 0x54, reg | 0x20); 620 } 621 622 acpimcfg_scan_bus(sc, pc, bus); 623 624 if (is_e7520_mch) { 625 pci_conf_write(pc, tag, 0x54, reg); 626 } 627 628 /* Unmap configuration space of all dev/func. */ 629 bus_space_unmap(seg->ms_bst, bsh, ACPIMCFG_SIZE_PER_BUS); 630 memset(mb->bsh, 0, sizeof(mb->bsh)); 631 632 if (mb->valid_ndevs == 0) { 633 aprint_debug_dev(acpi_sc->sc_dev, 634 "MCFG: bus %d: no valid devices.\n", bus); 635 memset(mb->valid_devs, 0, sizeof(mb->valid_devs)); 636 goto out; 637 } 638 639 /* Mark invalid on remaining all devices. */ 640 pci_decompose_tag(pc, mb->last_probed, NULL, &last_dev, &last_func); 641 for (i = last_dev; i < 32; i++) { 642 for (j = last_func; j < 8; j++) { 643 if (i == last_dev && j == last_func) { 644 /* Don't mark invalid to last probed device. */ 645 continue; 646 } 647 PCIDEV_SET_INVALID(mb, i, j); 648 } 649 last_func = 0; 650 } 651 652 /* Map configuration space per dev/func. */ 653 for (i = 0; i < 32; i++) { 654 for (j = 0; j < 8; j++) { 655 if (!PCIDEV_IS_VALID(mb, i, j)) 656 continue; 657 error = bus_space_map(seg->ms_bst, 658 baddr + EXTCONF_OFFSET(i, j, 0), PCI_EXTCONF_SIZE, 659 0, &mb->bsh[i][j]); 660 if (error != 0) { 661 /* Unmap all handles when map failed. */ 662 do { 663 while (--j >= 0) { 664 if (!PCIDEV_IS_VALID(mb, i, j)) 665 continue; 666 bus_space_unmap(seg->ms_bst, 667 mb->bsh[i][j], 668 PCI_EXTCONF_SIZE); 669 } 670 j = 8; 671 } while (--i >= 0); 672 memset(mb->valid_devs, 0, 673 sizeof(mb->valid_devs)); 674 goto out; 675 } 676 } 677 } 678 679 aprint_debug_dev(acpi_sc->sc_dev, "MCFG: bus %d: valid devices\n", bus); 680 for (i = 0; i < 32; i++) { 681 for (j = 0; j < 8; j++) { 682 if (PCIDEV_IS_VALID(mb, i, j)) { 683 aprint_debug_dev(acpi_sc->sc_dev, 684 "MCFG: %03d:%02d:%d\n", bus, i, j); 685 } 686 } 687 } 688 689 error = 0; 690 out: 691 aprint_debug_dev(acpi_sc->sc_dev, "%s done", __func__); 692 693 return error; 694 } 695 696 #ifdef PCI_NETBSD_CONFIGURE 697 struct acpimcfg_resource { 698 struct extent *ioext; 699 struct extent *memext; 700 struct extent *pmemext; 701 }; 702 703 static ACPI_STATUS 704 acpimcfg_configure_bus_cb(ACPI_RESOURCE *res, void *ctx) 705 { 706 struct acpimcfg_resource *pcires = ctx; 707 struct extent *ex; 708 const char *s; 709 int error; 710 711 if (res->Type != ACPI_RESOURCE_TYPE_ADDRESS16 && 712 res->Type != ACPI_RESOURCE_TYPE_ADDRESS32 && 713 res->Type != ACPI_RESOURCE_TYPE_ADDRESS64) 714 return AE_OK; 715 716 if (res->Data.Address.ProducerConsumer != ACPI_PRODUCER) 717 return AE_OK; 718 719 if (res->Data.Address.ResourceType != ACPI_MEMORY_RANGE && 720 res->Data.Address.ResourceType != ACPI_IO_RANGE) 721 return AE_OK; 722 723 if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE && 724 res->Data.Address.Info.Mem.Caching == ACPI_PREFETCHABLE_MEMORY) { 725 if (pcires->pmemext == NULL) { 726 pcires->pmemext = extent_create("pcipmem", 0, ULONG_MAX, 727 NULL, 0, EX_WAITOK); 728 error = extent_alloc_region(pcires->pmemext, 0, ULONG_MAX, 729 EX_WAITOK); 730 if (error) { 731 extent_destroy(pcires->pmemext); 732 pcires->pmemext = NULL; 733 return AE_NO_MEMORY; 734 } 735 } 736 ex = pcires->pmemext; 737 s = "prefetchable"; 738 } else if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE && 739 res->Data.Address.Info.Mem.Caching != ACPI_PREFETCHABLE_MEMORY) { 740 if (pcires->memext == NULL) { 741 pcires->memext = extent_create("pcimem", 0, ULONG_MAX, 742 NULL, 0, EX_WAITOK); 743 error = extent_alloc_region(pcires->memext, 0, ULONG_MAX, 744 EX_WAITOK); 745 if (error) { 746 extent_destroy(pcires->memext); 747 pcires->memext = NULL; 748 return AE_NO_MEMORY; 749 } 750 } 751 ex = pcires->memext; 752 s = "non-prefetchable"; 753 } else if (res->Data.Address.ResourceType == ACPI_IO_RANGE) { 754 if (pcires->ioext == NULL) { 755 pcires->ioext = extent_create("pciio", 0, ULONG_MAX, 756 NULL, 0, EX_WAITOK); 757 error = extent_alloc_region(pcires->ioext, 0, ULONG_MAX, 758 EX_WAITOK); 759 if (error) { 760 extent_destroy(pcires->ioext); 761 pcires->ioext = NULL; 762 return AE_NO_MEMORY; 763 } 764 } 765 ex = pcires->ioext; 766 s = "i/o"; 767 768 } 769 770 switch (res->Type) { 771 case ACPI_RESOURCE_TYPE_ADDRESS16: 772 aprint_debug( 773 "MCFG: range 0x%04" PRIx16 " size %#" PRIx16 " (16-bit %s)\n", 774 res->Data.Address16.Address.Minimum, 775 res->Data.Address16.Address.AddressLength, 776 s); 777 error = extent_free(ex, res->Data.Address16.Address.Minimum, 778 res->Data.Address16.Address.AddressLength, EX_WAITOK); 779 if (error) 780 return AE_NO_MEMORY; 781 break; 782 case ACPI_RESOURCE_TYPE_ADDRESS32: 783 aprint_debug( 784 "MCFG: range 0x%08" PRIx32 " size %#" PRIx32 " (32-bit %s)\n", 785 res->Data.Address32.Address.Minimum, 786 res->Data.Address32.Address.AddressLength, 787 s); 788 error = extent_free(ex, res->Data.Address32.Address.Minimum, 789 res->Data.Address32.Address.AddressLength, EX_WAITOK); 790 if (error) 791 return AE_NO_MEMORY; 792 break; 793 case ACPI_RESOURCE_TYPE_ADDRESS64: 794 aprint_debug( 795 "MCFG: range 0x%016" PRIx64 " size %#" PRIx64 " (64-bit %s)\n", 796 res->Data.Address64.Address.Minimum, 797 res->Data.Address64.Address.AddressLength, 798 s); 799 error = extent_free(ex, res->Data.Address64.Address.Minimum, 800 res->Data.Address64.Address.AddressLength, EX_WAITOK); 801 if (error) 802 return AE_NO_MEMORY; 803 break; 804 } 805 806 return AE_OK; 807 } 808 809 int 810 acpimcfg_configure_bus(device_t self, pci_chipset_tag_t pc, ACPI_HANDLE handle, 811 int bus, int cacheline_size) 812 { 813 struct acpimcfg_resource res; 814 struct mcfg_segment *seg; 815 struct mcfg_bus *mb; 816 bus_space_handle_t bsh[256]; 817 bool bsh_mapped[256]; 818 int error, boff, b, d, f; 819 bus_addr_t baddr; 820 ACPI_STATUS rv; 821 822 seg = acpimcfg_get_segment(pc, bus); 823 if (seg == NULL) 824 return ENOENT; 825 826 /* 827 * Map config space for all possible busses and mark them valid during 828 * configuration so pci_configure_bus can access them through our chipset 829 * tag with acpimcfg_conf_read/write below. 830 */ 831 memset(bsh_mapped, 0, sizeof(bsh_mapped)); 832 for (b = seg->ms_bus_start; b <= seg->ms_bus_end; b++) { 833 boff = b - seg->ms_bus_start; 834 mb = &seg->ms_bus[boff]; 835 baddr = seg->ms_address + (b * ACPIMCFG_SIZE_PER_BUS); 836 837 /* Map extended configration space of all dev/func. */ 838 error = bus_space_map(seg->ms_bst, baddr, ACPIMCFG_SIZE_PER_BUS, 0, 839 &bsh[b]); 840 if (error != 0) 841 goto cleanup; 842 bsh_mapped[b] = true; 843 for (d = 0; d < 32; d++) { 844 for (f = 0; f < 8; f++) { 845 error = bus_space_subregion(seg->ms_bst, bsh[b], 846 EXTCONF_OFFSET(d, f, 0), PCI_EXTCONF_SIZE, 847 &mb->bsh[d][f]); 848 if (error != 0) 849 break; 850 } 851 } 852 if (error != 0) 853 goto cleanup; 854 855 memset(mb->valid_devs, 0xff, sizeof(mb->valid_devs)); 856 } 857 858 memset(&res, 0, sizeof(res)); 859 rv = AcpiWalkResources(handle, "_CRS", acpimcfg_configure_bus_cb, &res); 860 if (ACPI_FAILURE(rv)) { 861 error = ENXIO; 862 goto cleanup; 863 } 864 865 error = pci_configure_bus(pc, res.ioext, res.memext, res.pmemext, bus, 866 cacheline_size); 867 868 cleanup: 869 /* 870 * Unmap config space for the segment's busses. Valid devices will be 871 * re-mapped later on by acpimcfg_map_bus. 872 */ 873 for (b = seg->ms_bus_start; b <= seg->ms_bus_end; b++) { 874 boff = b - seg->ms_bus_start; 875 mb = &seg->ms_bus[boff]; 876 memset(mb->valid_devs, 0, sizeof(mb->valid_devs)); 877 878 if (bsh_mapped[b]) 879 bus_space_unmap(seg->ms_bst, bsh[b], ACPIMCFG_SIZE_PER_BUS); 880 } 881 882 if (res.ioext) 883 extent_destroy(res.ioext); 884 if (res.memext) 885 extent_destroy(res.memext); 886 if (res.pmemext) 887 extent_destroy(res.pmemext); 888 889 return error; 890 } 891 #else 892 int 893 acpimcfg_configure_bus(device_t self, pci_chipset_tag_t pc, ACPI_HANDLE handle, 894 int bus, int cacheline_size) 895 { 896 return ENXIO; 897 } 898 #endif 899 900 int 901 acpimcfg_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data) 902 { 903 struct mcfg_segment *seg = NULL; 904 struct mcfg_bus *mb; 905 int bus, dev, func; 906 907 KASSERT(reg < PCI_EXTCONF_SIZE); 908 KASSERT((reg & 3) == 0); 909 910 if (!mcfg_inited) { 911 *data = -1; 912 return ENXIO; 913 } 914 915 pci_decompose_tag(pc, tag, &bus, &dev, &func); 916 917 seg = acpimcfg_get_segment(pc, bus); 918 if (seg == NULL) { 919 *data = -1; 920 return ERANGE; 921 } 922 923 mb = &seg->ms_bus[bus - seg->ms_bus_start]; 924 if (!PCIDEV_IS_VALID(mb, dev, func)) { 925 *data = -1; 926 return EINVAL; 927 } 928 if (!EXTCONF_IS_VALID(mb, dev, func) && reg >= PCI_CONF_SIZE) { 929 *data = -1; 930 return EINVAL; 931 } 932 933 *data = mcfg_ops->ao_read(seg->ms_bst, mb->bsh[dev][func], reg); 934 return 0; 935 } 936 937 int 938 acpimcfg_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) 939 { 940 struct mcfg_segment *seg = NULL; 941 struct mcfg_bus *mb; 942 int bus, dev, func; 943 944 KASSERT(reg < PCI_EXTCONF_SIZE); 945 KASSERT((reg & 3) == 0); 946 947 if (!mcfg_inited) 948 return ENXIO; 949 950 pci_decompose_tag(pc, tag, &bus, &dev, &func); 951 952 seg = acpimcfg_get_segment(pc, bus); 953 if (seg == NULL) 954 return ERANGE; 955 956 mb = &seg->ms_bus[bus - seg->ms_bus_start]; 957 if (!PCIDEV_IS_VALID(mb, dev, func)) 958 return EINVAL; 959 if (!EXTCONF_IS_VALID(mb, dev, func) && reg >= PCI_CONF_SIZE) 960 return EINVAL; 961 962 mcfg_ops->ao_write(seg->ms_bst, mb->bsh[dev][func], reg, data); 963 return 0; 964 } 965