1/* $NetBSD: pci_resource.c,v 1.4 2023/11/12 13:56:20 jmcneill Exp $ */ 2 3/*- 4 * Copyright (c) 2022 Jared McNeill <jmcneill@invisible.ca> 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, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* 30 * pci_resource.c -- 31 * 32 * Scan current PCI resource allocations and attempt to assign resources 33 * to devices that are not configured WITHOUT changing any configuration 34 * performed by system firmware. 35 */ 36 37#include <sys/cdefs.h> 38__KERNEL_RCSID(0, "$NetBSD: pci_resource.c,v 1.4 2023/11/12 13:56:20 jmcneill Exp $"); 39 40#include <sys/param.h> 41#include <sys/bus.h> 42#include <sys/systm.h> 43#include <sys/kmem.h> 44#include <sys/vmem.h> 45 46#include <dev/pci/pcireg.h> 47#include <dev/pci/pcivar.h> 48#include <dev/pci/pcidevs.h> 49#include <dev/pci/pci_resource.h> 50 51#define DPRINT aprint_debug 52 53#if defined(PCI_RESOURCE_TEST_VENDOR_ID) && \ 54 defined(PCI_RESOURCE_TEST_PRODUCT_ID) 55#define IS_TEST_DEVICE(_pd) \ 56 (PCI_VENDOR(pd->pd_id) == PCI_RESOURCE_TEST_VENDOR_ID && \ 57 PCI_PRODUCT(pd->pd_id) == PCI_RESOURCE_TEST_PRODUCT_ID) 58#else 59#define IS_TEST_DEVICE(_pd) 0 60#endif 61 62#define PCI_MAX_DEVICE 32 63#define PCI_MAX_FUNC 8 64 65#define PCI_MAX_IORES 6 66 67#define PCI_RANGE_FOREACH(_type) \ 68 for (u_int _type = PCI_RANGE_BUS; _type < NUM_PCI_RANGES; _type++) 69 70static const char *pci_range_typenames[NUM_PCI_RANGES] = { 71 [PCI_RANGE_BUS] = "bus", 72 [PCI_RANGE_IO] = "io", 73 [PCI_RANGE_MEM] = "mem", 74 [PCI_RANGE_PMEM] = "pmem", 75}; 76 77struct pci_bus; 78 79struct pci_iores { 80 uint64_t pi_base; /* Base address */ 81 uint64_t pi_size; /* Resource size */ 82 uint8_t pi_type; /* PCI_MAPREG_TYPE_* */ 83 u_int pi_bar; /* PCI bar number */ 84 union { 85 struct { 86 uint8_t memtype; 87 bool prefetch; 88 } pi_mem; 89 }; 90}; 91 92struct pci_device { 93 bool pd_present; /* Device is present */ 94 bool pd_configured; /* Device is configured */ 95 struct pci_bus *pd_bus; /* Parent bus */ 96 uint8_t pd_devno; /* Device number */ 97 uint8_t pd_funcno; /* Function number */ 98 pcitag_t pd_tag; /* PCI tag */ 99 100 pcireg_t pd_id; /* Vendor ID, Device ID */ 101 pcireg_t pd_class; /* Revision ID, Class Code */ 102 pcireg_t pd_bhlc; /* BIST, Header Type, Primary Latency 103 * Timer, Cache Line Size */ 104 105 struct pci_iores pd_iores[PCI_MAX_IORES]; 106 u_int pd_niores; 107 108 bool pd_ppb; /* PCI-PCI bridge */ 109 union { 110 struct { 111 pcireg_t bridge_bus; 112 struct pci_resource_range ranges[NUM_PCI_RANGES]; 113 } pd_bridge; 114 }; 115}; 116 117struct pci_bus { 118 uint8_t pb_busno; /* Bus number */ 119 struct pci_device *pb_bridge; /* Parent bridge, or NULL */ 120 121 struct pci_device pb_device[PCI_MAX_DEVICE * PCI_MAX_FUNC]; 122 /* Devices on bus */ 123 u_int pb_lastdevno; /* Last device found */ 124 125 struct pci_resource_range pb_ranges[NUM_PCI_RANGES]; 126 vmem_t *pb_res[NUM_PCI_RANGES]; 127}; 128 129struct pci_resources { 130 struct pci_bus **pr_bus; /* Bus list */ 131 pci_chipset_tag_t pr_pc; /* Chipset tag */ 132 uint8_t pr_startbus; /* First bus number */ 133 uint8_t pr_endbus; /* Last bus number */ 134 135 struct pci_resource_range pr_ranges[NUM_PCI_RANGES]; 136 vmem_t *pr_res[NUM_PCI_RANGES]; 137}; 138 139static void pci_resource_scan_bus(struct pci_resources *, 140 struct pci_device *, uint8_t); 141 142#define PCI_SBDF_FMT "%04x:%02x:%02x.%u" 143#define PCI_SBDF_FMT_ARGS(_pr, _pd) \ 144 pci_get_segment((_pr)->pr_pc), \ 145 (_pd)->pd_bus->pb_busno, \ 146 (_pd)->pd_devno, \ 147 (_pd)->pd_funcno 148 149#define PCICONF_RES_BUS(_pr, _busno) \ 150 ((_pr)->pr_bus[(_busno) - (_pr)->pr_startbus]) 151#define PCICONF_BUS_DEVICE(_pb, _devno, _funcno) \ 152 (&(_pb)->pb_device[(_devno) * PCI_MAX_FUNC + (_funcno)]) 153 154/* 155 * pci_create_vmem -- 156 * 157 * Create a vmem arena covering the specified range, used for tracking 158 * PCI resources. 159 */ 160static vmem_t * 161pci_create_vmem(const char *name, bus_addr_t start, bus_addr_t end) 162{ 163 vmem_t *arena; 164 int error __diagused; 165 166 arena = vmem_create(name, 0, 0, 1, NULL, NULL, NULL, 0, VM_SLEEP, 167 IPL_NONE); 168 error = vmem_add(arena, start, end - start + 1, VM_SLEEP); 169 KASSERTMSG(error == 0, "error=%d", error); 170 171 return arena; 172} 173 174/* 175 * pci_new_bus -- 176 * 177 * Create a new PCI bus and initialize its resource ranges. 178 */ 179static struct pci_bus * 180pci_new_bus(struct pci_resources *pr, uint8_t busno, struct pci_device *bridge) 181{ 182 struct pci_bus *pb; 183 struct pci_resource_range *ranges; 184 185 pb = kmem_zalloc(sizeof(*pb), KM_SLEEP); 186 pb->pb_busno = busno; 187 pb->pb_bridge = bridge; 188 if (bridge == NULL) { 189 /* 190 * No additional constraints on resource allocations for 191 * the root bus. 192 */ 193 ranges = pr->pr_ranges; 194 } else { 195 /* 196 * Resource allocations for this bus are constrained by the 197 * bridge forwarding settings. 198 */ 199 ranges = bridge->pd_bridge.ranges; 200 } 201 memcpy(pb->pb_ranges, ranges, sizeof(pb->pb_ranges)); 202 203 return pb; 204} 205 206/* 207 * pci_resource_device_functions -- 208 * 209 * Returns the number of PCI functions for a a given bus and device. 210 */ 211static uint8_t 212pci_resource_device_functions(struct pci_resources *pr, 213 uint8_t busno, uint8_t devno) 214{ 215 struct pci_bus *pb; 216 struct pci_device *pd; 217 218 pb = PCICONF_RES_BUS(pr, busno); 219 pd = PCICONF_BUS_DEVICE(pb, devno, 0); 220 if (!pd->pd_present) { 221 return 0; 222 } 223 224 return PCI_HDRTYPE_MULTIFN(pd->pd_bhlc) ? 8 : 1; 225} 226 227/* 228 * pci_resource_device_print -- 229 * 230 * Log details about a device. 231 */ 232static void 233pci_resource_device_print(struct pci_resources *pr, 234 struct pci_device *pd) 235{ 236 struct pci_iores *pi; 237 u_int res; 238 239 DPRINT("PCI: " PCI_SBDF_FMT " %04x:%04x %02x 0x%06x", 240 PCI_SBDF_FMT_ARGS(pr, pd), 241 PCI_VENDOR(pd->pd_id), PCI_PRODUCT(pd->pd_id), 242 PCI_REVISION(pd->pd_class), (pd->pd_class >> 8) & 0xffffff); 243 244 switch (PCI_HDRTYPE_TYPE(pd->pd_bhlc)) { 245 case PCI_HDRTYPE_DEVICE: 246 DPRINT(" (device)\n"); 247 break; 248 case PCI_HDRTYPE_PPB: 249 DPRINT(" (bridge %u -> %u-%u)\n", 250 PCI_BRIDGE_BUS_NUM_PRIMARY(pd->pd_bridge.bridge_bus), 251 PCI_BRIDGE_BUS_NUM_SECONDARY(pd->pd_bridge.bridge_bus), 252 PCI_BRIDGE_BUS_NUM_SUBORDINATE(pd->pd_bridge.bridge_bus)); 253 254 if (pd->pd_bridge.ranges[PCI_RANGE_IO].end) { 255 DPRINT("PCI: " PCI_SBDF_FMT 256 " [bridge] window io %#" PRIx64 "-%#" PRIx64 257 "\n", 258 PCI_SBDF_FMT_ARGS(pr, pd), 259 pd->pd_bridge.ranges[PCI_RANGE_IO].start, 260 pd->pd_bridge.ranges[PCI_RANGE_IO].end); 261 } 262 if (pd->pd_bridge.ranges[PCI_RANGE_MEM].end) { 263 DPRINT("PCI: " PCI_SBDF_FMT 264 " [bridge] window mem %#" PRIx64 "-%#" PRIx64 265 " (non-prefetchable)\n", 266 PCI_SBDF_FMT_ARGS(pr, pd), 267 pd->pd_bridge.ranges[PCI_RANGE_MEM].start, 268 pd->pd_bridge.ranges[PCI_RANGE_MEM].end); 269 } 270 if (pd->pd_bridge.ranges[PCI_RANGE_PMEM].end) { 271 DPRINT("PCI: " PCI_SBDF_FMT 272 " [bridge] window mem %#" PRIx64 "-%#" PRIx64 273 " (prefetchable)\n", 274 PCI_SBDF_FMT_ARGS(pr, pd), 275 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start, 276 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end); 277 } 278 279 break; 280 default: 281 DPRINT(" (0x%02x)\n", PCI_HDRTYPE_TYPE(pd->pd_bhlc)); 282 } 283 284 for (res = 0; res < pd->pd_niores; res++) { 285 pi = &pd->pd_iores[res]; 286 287 DPRINT("PCI: " PCI_SBDF_FMT 288 " [device] resource BAR%u: %s @ %#" PRIx64 " size %#" 289 PRIx64, 290 PCI_SBDF_FMT_ARGS(pr, pd), pi->pi_bar, 291 pi->pi_type == PCI_MAPREG_TYPE_MEM ? "mem" : "io ", 292 pi->pi_base, pi->pi_size); 293 294 if (pi->pi_type == PCI_MAPREG_TYPE_MEM) { 295 switch (pi->pi_mem.memtype) { 296 case PCI_MAPREG_MEM_TYPE_32BIT: 297 DPRINT(", 32-bit"); 298 break; 299 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 300 DPRINT(", 32-bit (1M)"); 301 break; 302 case PCI_MAPREG_MEM_TYPE_64BIT: 303 DPRINT(", 64-bit"); 304 break; 305 } 306 DPRINT(" %sprefetchable", 307 pi->pi_mem.prefetch ? "" : "non-"); 308 } 309 DPRINT("\n"); 310 } 311} 312 313/* 314 * pci_resource_scan_bar -- 315 * 316 * Determine the current BAR configuration for a given device. 317 */ 318static void 319pci_resource_scan_bar(struct pci_resources *pr, 320 struct pci_device *pd, pcireg_t mapreg_start, pcireg_t mapreg_end, 321 bool is_ppb) 322{ 323 pci_chipset_tag_t pc = pr->pr_pc; 324 pcitag_t tag = pd->pd_tag; 325 pcireg_t mapreg = mapreg_start; 326 pcireg_t ocmd, cmd, bar[2], mask[2]; 327 uint64_t addr, size; 328 struct pci_iores *pi; 329 330 if (!is_ppb) { 331 ocmd = cmd = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 332 cmd &= ~(PCI_COMMAND_MASTER_ENABLE | 333 PCI_COMMAND_MEM_ENABLE | 334 PCI_COMMAND_IO_ENABLE); 335 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmd); 336 } 337 338 while (mapreg < mapreg_end) { 339 u_int width = 4; 340 341 bar[0] = pci_conf_read(pc, tag, mapreg); 342 pci_conf_write(pc, tag, mapreg, 0xffffffff); 343 mask[0] = pci_conf_read(pc, tag, mapreg); 344 pci_conf_write(pc, tag, mapreg, bar[0]); 345 346 switch (PCI_MAPREG_TYPE(mask[0])) { 347 case PCI_MAPREG_TYPE_MEM: 348 switch (PCI_MAPREG_MEM_TYPE(mask[0])) { 349 case PCI_MAPREG_MEM_TYPE_32BIT: 350 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 351 size = PCI_MAPREG_MEM_SIZE(mask[0]); 352 addr = PCI_MAPREG_MEM_ADDR(bar[0]); 353 break; 354 case PCI_MAPREG_MEM_TYPE_64BIT: 355 bar[1] = pci_conf_read(pc, tag, mapreg + 4); 356 pci_conf_write(pc, tag, mapreg + 4, 0xffffffff); 357 mask[1] = pci_conf_read(pc, tag, mapreg + 4); 358 pci_conf_write(pc, tag, mapreg + 4, bar[1]); 359 360 size = PCI_MAPREG_MEM64_SIZE( 361 ((uint64_t)mask[1] << 32) | mask[0]); 362 addr = PCI_MAPREG_MEM64_ADDR( 363 ((uint64_t)bar[1] << 32) | bar[0]); 364 width = 8; 365 break; 366 default: 367 size = 0; 368 } 369 if (size > 0) { 370 pi = &pd->pd_iores[pd->pd_niores++]; 371 pi->pi_type = PCI_MAPREG_TYPE_MEM; 372 pi->pi_base = addr; 373 pi->pi_size = size; 374 pi->pi_bar = (mapreg - mapreg_start) / 4; 375 pi->pi_mem.memtype = 376 PCI_MAPREG_MEM_TYPE(mask[0]); 377 pi->pi_mem.prefetch = 378 PCI_MAPREG_MEM_PREFETCHABLE(mask[0]); 379 } 380 break; 381 case PCI_MAPREG_TYPE_IO: 382 size = PCI_MAPREG_IO_SIZE(mask[0] | 0xffff0000); 383 addr = PCI_MAPREG_IO_ADDR(bar[0]); 384 if (size > 0) { 385 pi = &pd->pd_iores[pd->pd_niores++]; 386 pi->pi_type = PCI_MAPREG_TYPE_IO; 387 pi->pi_base = addr; 388 pi->pi_size = size; 389 pi->pi_bar = (mapreg - mapreg_start) / 4; 390 } 391 break; 392 } 393 394 KASSERT(pd->pd_niores <= PCI_MAX_IORES); 395 396 mapreg += width; 397 } 398 399 if (!is_ppb) { 400 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, ocmd); 401 } 402} 403 404/* 405 * pci_resource_scan_bridge -- 406 * 407 * Determine the current configuration of a PCI-PCI bridge. 408 */ 409static void 410pci_resource_scan_bridge(struct pci_resources *pr, 411 struct pci_device *pd) 412{ 413 pci_chipset_tag_t pc = pr->pr_pc; 414 pcitag_t tag = pd->pd_tag; 415 pcireg_t res, reshigh; 416 417 pd->pd_ppb = true; 418 419 res = pci_conf_read(pc, tag, PCI_BRIDGE_BUS_REG); 420 pd->pd_bridge.bridge_bus = res; 421 pd->pd_bridge.ranges[PCI_RANGE_BUS].start = 422 PCI_BRIDGE_BUS_NUM_SECONDARY(res); 423 pd->pd_bridge.ranges[PCI_RANGE_BUS].end = 424 PCI_BRIDGE_BUS_NUM_SUBORDINATE(res); 425 426 res = pci_conf_read(pc, tag, PCI_BRIDGE_STATIO_REG); 427 pd->pd_bridge.ranges[PCI_RANGE_IO].start = 428 PCI_BRIDGE_STATIO_IOBASE_ADDR(res); 429 pd->pd_bridge.ranges[PCI_RANGE_IO].end = 430 PCI_BRIDGE_STATIO_IOLIMIT_ADDR(res); 431 if (PCI_BRIDGE_IO_32BITS(res)) { 432 reshigh = pci_conf_read(pc, tag, PCI_BRIDGE_IOHIGH_REG); 433 pd->pd_bridge.ranges[PCI_RANGE_IO].start |= 434 __SHIFTOUT(reshigh, PCI_BRIDGE_IOHIGH_BASE) << 16; 435 pd->pd_bridge.ranges[PCI_RANGE_IO].end |= 436 __SHIFTOUT(reshigh, PCI_BRIDGE_IOHIGH_LIMIT) << 16; 437 } 438 if (pd->pd_bridge.ranges[PCI_RANGE_IO].start >= 439 pd->pd_bridge.ranges[PCI_RANGE_IO].end) { 440 pd->pd_bridge.ranges[PCI_RANGE_IO].start = 0; 441 pd->pd_bridge.ranges[PCI_RANGE_IO].end = 0; 442 } 443 444 res = pci_conf_read(pc, tag, PCI_BRIDGE_MEMORY_REG); 445 pd->pd_bridge.ranges[PCI_RANGE_MEM].start = 446 PCI_BRIDGE_MEMORY_BASE_ADDR(res); 447 pd->pd_bridge.ranges[PCI_RANGE_MEM].end = 448 PCI_BRIDGE_MEMORY_LIMIT_ADDR(res); 449 if (pd->pd_bridge.ranges[PCI_RANGE_MEM].start >= 450 pd->pd_bridge.ranges[PCI_RANGE_MEM].end) { 451 pd->pd_bridge.ranges[PCI_RANGE_MEM].start = 0; 452 pd->pd_bridge.ranges[PCI_RANGE_MEM].end = 0; 453 } 454 455 res = pci_conf_read(pc, tag, PCI_BRIDGE_PREFETCHMEM_REG); 456 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start = 457 PCI_BRIDGE_PREFETCHMEM_BASE_ADDR(res); 458 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end = 459 PCI_BRIDGE_PREFETCHMEM_LIMIT_ADDR(res); 460 if (PCI_BRIDGE_PREFETCHMEM_64BITS(res)) { 461 reshigh = pci_conf_read(pc, tag, 462 PCI_BRIDGE_PREFETCHBASEUP32_REG); 463 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start |= 464 (uint64_t)reshigh << 32; 465 reshigh = pci_conf_read(pc, tag, 466 PCI_BRIDGE_PREFETCHLIMITUP32_REG); 467 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end |= 468 (uint64_t)reshigh << 32; 469 } 470 if (pd->pd_bridge.ranges[PCI_RANGE_PMEM].start >= 471 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end) { 472 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start = 0; 473 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end = 0; 474 } 475} 476 477/* 478 * pci_resource_scan_device -- 479 * 480 * Determine the current configuration of a PCI device. 481 */ 482static bool 483pci_resource_scan_device(struct pci_resources *pr, 484 struct pci_bus *parent_bus, uint8_t devno, uint8_t funcno) 485{ 486 struct pci_device *pd; 487 pcitag_t tag; 488 pcireg_t id, bridge_bus; 489 uint8_t sec_bus; 490 491 tag = pci_make_tag(pr->pr_pc, parent_bus->pb_busno, devno, funcno); 492 id = pci_conf_read(pr->pr_pc, tag, PCI_ID_REG); 493 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) { 494 return false; 495 } 496 497 pd = PCICONF_BUS_DEVICE(parent_bus, devno, funcno); 498 pd->pd_present = true; 499 pd->pd_bus = parent_bus; 500 pd->pd_tag = tag; 501 pd->pd_devno = devno; 502 pd->pd_funcno = funcno; 503 pd->pd_id = id; 504 pd->pd_class = pci_conf_read(pr->pr_pc, tag, PCI_CLASS_REG); 505 pd->pd_bhlc = pci_conf_read(pr->pr_pc, tag, PCI_BHLC_REG); 506 507 switch (PCI_HDRTYPE_TYPE(pd->pd_bhlc)) { 508 case PCI_HDRTYPE_DEVICE: 509 pci_resource_scan_bar(pr, pd, PCI_MAPREG_START, 510 PCI_MAPREG_END, false); 511 break; 512 case PCI_HDRTYPE_PPB: 513 pci_resource_scan_bar(pr, pd, PCI_MAPREG_START, 514 PCI_MAPREG_PPB_END, true); 515 pci_resource_scan_bridge(pr, pd); 516 break; 517 } 518 519 pci_resource_device_print(pr, pd); 520 521 if (PCI_HDRTYPE_TYPE(pd->pd_bhlc) == PCI_HDRTYPE_PPB && 522 PCI_CLASS(pd->pd_class) == PCI_CLASS_BRIDGE && 523 PCI_SUBCLASS(pd->pd_class) == PCI_SUBCLASS_BRIDGE_PCI) { 524 bridge_bus = pci_conf_read(pr->pr_pc, tag, PCI_BRIDGE_BUS_REG); 525 sec_bus = PCI_BRIDGE_BUS_NUM_SECONDARY(bridge_bus); 526 if (sec_bus <= pr->pr_endbus) { 527 pci_resource_scan_bus(pr, pd, sec_bus); 528 } 529 } 530 531 return true; 532} 533 534/* 535 * pci_resource_scan_bus -- 536 * 537 * Enumerate devices on a bus, recursively. 538 */ 539static void 540pci_resource_scan_bus(struct pci_resources *pr, 541 struct pci_device *bridge_dev, uint8_t busno) 542{ 543 struct pci_bus *pb; 544 uint8_t devno, funcno; 545 uint8_t nfunc; 546 547 KASSERT(busno >= pr->pr_startbus); 548 KASSERT(busno <= pr->pr_endbus); 549 550 if (PCICONF_RES_BUS(pr, busno) != NULL) { 551 /* 552 * Firmware has configured more than one bridge with the 553 * same secondary bus number. 554 */ 555 panic("Bus %u already scanned (firmware bug!)", busno); 556 return; 557 } 558 559 pb = pci_new_bus(pr, busno, bridge_dev); 560 PCICONF_RES_BUS(pr, busno) = pb; 561 562 for (devno = 0; devno < PCI_MAX_DEVICE; devno++) { 563 if (!pci_resource_scan_device(pr, pb, devno, 0)) { 564 continue; 565 } 566 pb->pb_lastdevno = devno; 567 568 nfunc = pci_resource_device_functions(pr, busno, devno); 569 for (funcno = 1; funcno < nfunc; funcno++) { 570 pci_resource_scan_device(pr, pb, devno, funcno); 571 } 572 } 573} 574 575/* 576 * pci_resource_claim -- 577 * 578 * Claim a resource from a vmem arena. This is called to inform the 579 * resource manager about resources already configured by system firmware. 580 */ 581static int 582pci_resource_claim(vmem_t *arena, vmem_addr_t start, vmem_addr_t end) 583{ 584 KASSERT(end >= start); 585 586 return vmem_xalloc(arena, end - start + 1, 0, 0, 0, start, end, 587 VM_BESTFIT | VM_NOSLEEP, NULL); 588} 589 590/* 591 * pci_resource_alloc -- 592 * 593 * Allocate a resource from a vmem arena. This is called when configuring 594 * devices that were not already configured by system firmware. 595 */ 596static int 597pci_resource_alloc(vmem_t *arena, vmem_size_t size, vmem_size_t align, 598 uint64_t *base) 599{ 600 vmem_addr_t addr; 601 int error; 602 603 KASSERT(size != 0); 604 605 error = vmem_xalloc(arena, size, align, 0, 0, VMEM_ADDR_MIN, 606 VMEM_ADDR_MAX, VM_BESTFIT | VM_NOSLEEP, &addr); 607 if (error == 0) { 608 *base = (uint64_t)addr; 609 } 610 611 return error; 612} 613 614/* 615 * pci_resource_init_device -- 616 * 617 * Discover resources assigned by system firmware, notify the resource 618 * manager of these ranges, and determine if the device has additional 619 * resources that need to be allocated. 620 */ 621static void 622pci_resource_init_device(struct pci_resources *pr, 623 struct pci_device *pd) 624{ 625 struct pci_iores *pi; 626 struct pci_bus *pb = pd->pd_bus; 627 vmem_t *res_io = pb->pb_res[PCI_RANGE_IO]; 628 vmem_t *res_mem = pb->pb_res[PCI_RANGE_MEM]; 629 vmem_t *res_pmem = pb->pb_res[PCI_RANGE_PMEM]; 630 pcireg_t cmd; 631 u_int enabled, required; 632 u_int iores; 633 int error; 634 635 KASSERT(pd->pd_present); 636 637 if (IS_TEST_DEVICE(pd)) { 638 cmd = pci_conf_read(pr->pr_pc, pd->pd_tag, 639 PCI_COMMAND_STATUS_REG); 640 cmd &= ~(PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE| 641 PCI_COMMAND_MASTER_ENABLE); 642 pci_conf_write(pr->pr_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG, 643 cmd); 644 } 645 646 enabled = required = 0; 647 cmd = pci_conf_read(pr->pr_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG); 648 if ((cmd & PCI_COMMAND_MEM_ENABLE) != 0) { 649 enabled |= __BIT(PCI_MAPREG_TYPE_MEM); 650 } 651 if ((cmd & PCI_COMMAND_IO_ENABLE) != 0) { 652 enabled |= __BIT(PCI_MAPREG_TYPE_IO); 653 } 654 655 for (iores = 0; iores < pd->pd_niores; iores++) { 656 pi = &pd->pd_iores[iores]; 657 658 required |= __BIT(pi->pi_type); 659 660 if (IS_TEST_DEVICE(pd)) { 661 pci_conf_write(pr->pr_pc, pd->pd_tag, 662 PCI_BAR(pi->pi_bar), 0); 663 continue; 664 } 665 if ((enabled & __BIT(pi->pi_type)) == 0) { 666 continue; 667 } 668 669 if (pi->pi_type == PCI_MAPREG_TYPE_IO) { 670 error = res_io == NULL ? ERANGE : 671 pci_resource_claim(res_io, pi->pi_base, 672 pi->pi_base + pi->pi_size - 1); 673 if (error) { 674 DPRINT("PCI: " PCI_SBDF_FMT " [device] io " 675 " %#" PRIx64 "-%#" PRIx64 676 " invalid (%d)\n", 677 PCI_SBDF_FMT_ARGS(pr, pd), 678 pi->pi_base, 679 pi->pi_base + pi->pi_size - 1, 680 error); 681 } 682 continue; 683 } 684 685 KASSERT(pi->pi_type == PCI_MAPREG_TYPE_MEM); 686 error = ERANGE; 687 if (pi->pi_mem.prefetch) { 688 /* 689 * Prefetchable memory must be allocated from the 690 * bridge's prefetchable region. 691 */ 692 if (res_pmem != NULL) { 693 error = pci_resource_claim(res_pmem, pi->pi_base, 694 pi->pi_base + pi->pi_size - 1); 695 } 696 } else if (pi->pi_mem.memtype == PCI_MAPREG_MEM_TYPE_64BIT) { 697 /* 698 * Non-prefetchable 64-bit memory can be allocated from 699 * any range. Prefer allocations from the prefetchable 700 * region to save 32-bit only resources for 32-bit BARs. 701 */ 702 if (res_pmem != NULL) { 703 error = pci_resource_claim(res_pmem, pi->pi_base, 704 pi->pi_base + pi->pi_size - 1); 705 } 706 if (error && res_mem != NULL) { 707 error = pci_resource_claim(res_mem, pi->pi_base, 708 pi->pi_base + pi->pi_size - 1); 709 } 710 } else { 711 /* 712 * Non-prefetchable 32-bit memory can be allocated from 713 * any range, provided that the range is below 4GB. Try 714 * the non-prefetchable range first, and if that fails, 715 * make one last attempt at allocating from the 716 * prefetchable range in case the platform provides 717 * memory below 4GB. 718 */ 719 if (res_mem != NULL) { 720 error = pci_resource_claim(res_mem, pi->pi_base, 721 pi->pi_base + pi->pi_size - 1); 722 } 723 if (error && res_pmem != NULL) { 724 error = pci_resource_claim(res_pmem, pi->pi_base, 725 pi->pi_base + pi->pi_size - 1); 726 } 727 } 728 if (error) { 729 DPRINT("PCI: " PCI_SBDF_FMT " [device] mem" 730 " (%sprefetchable)" 731 " %#" PRIx64 "-%#" PRIx64 732 " invalid (%d)\n", 733 PCI_SBDF_FMT_ARGS(pr, pd), 734 pi->pi_mem.prefetch ? "" : "non-", 735 pi->pi_base, 736 pi->pi_base + pi->pi_size - 1, 737 error); 738 } 739 } 740 741 pd->pd_configured = (enabled & required) == required; 742 743 if (!pd->pd_configured) { 744 DPRINT("PCI: " PCI_SBDF_FMT " [device] " 745 "not configured by firmware\n", 746 PCI_SBDF_FMT_ARGS(pr, pd)); 747 } 748} 749 750/* 751 * pci_resource_init_bus -- 752 * 753 * Discover resources in use on a given bus, recursively. 754 */ 755static void 756pci_resource_init_bus(struct pci_resources *pr, uint8_t busno) 757{ 758 struct pci_bus *pb, *parent_bus; 759 struct pci_device *pd, *bridge; 760 uint8_t devno, funcno; 761 uint8_t nfunc; 762 int error; 763 764 KASSERT(busno >= pr->pr_startbus); 765 KASSERT(busno <= pr->pr_endbus); 766 767 pb = PCICONF_RES_BUS(pr, busno); 768 bridge = pb->pb_bridge; 769 770 KASSERT(pb != NULL); 771 KASSERT((busno == pr->pr_startbus) == (bridge == NULL)); 772 773 if (bridge == NULL) { 774 /* Use resources provided by firmware. */ 775 PCI_RANGE_FOREACH(prtype) { 776 pb->pb_res[prtype] = pr->pr_res[prtype]; 777 pr->pr_res[prtype] = NULL; 778 } 779 } else { 780 /* 781 * Using the resources configured in to the bridge by 782 * firmware, claim the resources on the parent bus and 783 * create a new vmem arena for the secondary bus. 784 */ 785 KASSERT(bridge->pd_bus != NULL); 786 parent_bus = bridge->pd_bus; 787 PCI_RANGE_FOREACH(prtype) { 788 if (parent_bus->pb_res[prtype] == NULL || 789 !bridge->pd_bridge.ranges[prtype].end) { 790 continue; 791 } 792 error = pci_resource_claim( 793 parent_bus->pb_res[prtype], 794 bridge->pd_bridge.ranges[prtype].start, 795 bridge->pd_bridge.ranges[prtype].end); 796 if (error == 0) { 797 pb->pb_res[prtype] = pci_create_vmem( 798 pci_resource_typename(prtype), 799 bridge->pd_bridge.ranges[prtype].start, 800 bridge->pd_bridge.ranges[prtype].end); 801 KASSERT(pb->pb_res[prtype] != NULL); 802 } else { 803 DPRINT("PCI: " PCI_SBDF_FMT " bridge (bus %u)" 804 " %-4s %#" PRIx64 "-%#" PRIx64 805 " invalid\n", 806 PCI_SBDF_FMT_ARGS(pr, bridge), busno, 807 pci_resource_typename(prtype), 808 bridge->pd_bridge.ranges[prtype].start, 809 bridge->pd_bridge.ranges[prtype].end); 810 } 811 } 812 } 813 814 for (devno = 0; devno <= pb->pb_lastdevno; devno++) { 815 KASSERT(devno < PCI_MAX_DEVICE); 816 nfunc = pci_resource_device_functions(pr, busno, devno); 817 for (funcno = 0; funcno < nfunc; funcno++) { 818 pd = PCICONF_BUS_DEVICE(pb, devno, funcno); 819 if (!pd->pd_present) { 820 continue; 821 } 822 if (pd->pd_ppb) { 823 uint8_t sec_bus = PCI_BRIDGE_BUS_NUM_SECONDARY( 824 pd->pd_bridge.bridge_bus); 825 pci_resource_init_bus(pr, sec_bus); 826 } 827 pci_resource_init_device(pr, pd); 828 } 829 } 830} 831 832/* 833 * pci_resource_probe -- 834 * 835 * Scan for PCI devices and initialize the resource manager. 836 */ 837static void 838pci_resource_probe(struct pci_resources *pr, 839 const struct pci_resource_info *info) 840{ 841 uint8_t startbus = (uint8_t)info->ranges[PCI_RANGE_BUS].start; 842 uint8_t endbus = (uint8_t)info->ranges[PCI_RANGE_BUS].end; 843 u_int nbus; 844 845 KASSERT(startbus <= endbus); 846 KASSERT(pr->pr_bus == NULL); 847 848 nbus = endbus - startbus + 1; 849 850 pr->pr_pc = info->pc; 851 pr->pr_startbus = startbus; 852 pr->pr_endbus = endbus; 853 pr->pr_bus = kmem_zalloc(nbus * sizeof(struct pci_bus *), KM_SLEEP); 854 memcpy(pr->pr_ranges, info->ranges, sizeof(pr->pr_ranges)); 855 PCI_RANGE_FOREACH(prtype) { 856 if (prtype == PCI_RANGE_BUS || info->ranges[prtype].end) { 857 pr->pr_res[prtype] = pci_create_vmem( 858 pci_resource_typename(prtype), 859 info->ranges[prtype].start, 860 info->ranges[prtype].end); 861 KASSERT(pr->pr_res[prtype] != NULL); 862 } 863 } 864 865 /* Scan devices */ 866 pci_resource_scan_bus(pr, NULL, pr->pr_startbus); 867 868 /* 869 * Create per-bus resource pools and remove ranges that are already 870 * in use by devices and downstream bridges. 871 */ 872 pci_resource_init_bus(pr, pr->pr_startbus); 873} 874 875/* 876 * pci_resource_alloc_device -- 877 * 878 * Attempt to allocate resources for a given device. 879 */ 880static void 881pci_resource_alloc_device(struct pci_resources *pr, struct pci_device *pd) 882{ 883 struct pci_iores *pi; 884 vmem_t *arena; 885 pcireg_t cmd, ocmd, base; 886 uint64_t addr; 887 u_int enabled; 888 u_int res; 889 u_int align; 890 int error; 891 892 enabled = 0; 893 ocmd = cmd = pci_conf_read(pr->pr_pc, pd->pd_tag, 894 PCI_COMMAND_STATUS_REG); 895 if ((cmd & PCI_COMMAND_MEM_ENABLE) != 0) { 896 enabled |= __BIT(PCI_MAPREG_TYPE_MEM); 897 } 898 if ((cmd & PCI_COMMAND_IO_ENABLE) != 0) { 899 enabled |= __BIT(PCI_MAPREG_TYPE_IO); 900 } 901 902 for (res = 0; res < pd->pd_niores; res++) { 903 pi = &pd->pd_iores[res]; 904 905 if ((enabled & __BIT(pi->pi_type)) != 0) { 906 continue; 907 } 908 909 if (pi->pi_type == PCI_MAPREG_TYPE_IO) { 910 arena = pd->pd_bus->pb_res[PCI_RANGE_IO]; 911 align = uimax(pi->pi_size, 4); 912 } else { 913 KASSERT(pi->pi_type == PCI_MAPREG_TYPE_MEM); 914 arena = NULL; 915 align = uimax(pi->pi_size, 16); 916 if (pi->pi_mem.prefetch) { 917 arena = pd->pd_bus->pb_res[PCI_RANGE_PMEM]; 918 } 919 if (arena == NULL) { 920 arena = pd->pd_bus->pb_res[PCI_RANGE_MEM]; 921 } 922 } 923 if (arena == NULL) { 924 DPRINT("PCI: " PCI_SBDF_FMT " BAR%u failed to" 925 " allocate %#" PRIx64 " bytes (no arena)\n", 926 PCI_SBDF_FMT_ARGS(pr, pd), 927 pi->pi_bar, pi->pi_size); 928 return; 929 } 930 error = pci_resource_alloc(arena, pi->pi_size, align, &addr); 931 if (error != 0) { 932 DPRINT("PCI: " PCI_SBDF_FMT " BAR%u failed to" 933 " allocate %#" PRIx64 " bytes (no space)\n", 934 PCI_SBDF_FMT_ARGS(pr, pd), 935 pi->pi_bar, pi->pi_size); 936 return; 937 } 938 DPRINT("PCI: " PCI_SBDF_FMT " BAR%u assigned range" 939 " 0x%#" PRIx64 "-0x%#" PRIx64 "\n", 940 PCI_SBDF_FMT_ARGS(pr, pd), 941 pi->pi_bar, addr, addr + pi->pi_size - 1); 942 943 if (pi->pi_type == PCI_MAPREG_TYPE_IO) { 944 cmd |= PCI_COMMAND_IO_ENABLE; 945 pci_conf_write(pr->pr_pc, pd->pd_tag, 946 PCI_BAR(pi->pi_bar), 947 PCI_MAPREG_IO_ADDR(addr) | PCI_MAPREG_TYPE_IO); 948 } else { 949 cmd |= PCI_COMMAND_MEM_ENABLE; 950 base = pci_conf_read(pr->pr_pc, pd->pd_tag, 951 PCI_BAR(pi->pi_bar)); 952 base = PCI_MAPREG_MEM_ADDR(addr) | 953 PCI_MAPREG_MEM_TYPE(base); 954 pci_conf_write(pr->pr_pc, pd->pd_tag, 955 PCI_BAR(pi->pi_bar), base); 956 if (pi->pi_mem.memtype == PCI_MAPREG_MEM_TYPE_64BIT) { 957 base = (pcireg_t) 958 (PCI_MAPREG_MEM64_ADDR(addr) >> 32); 959 pci_conf_write(pr->pr_pc, pd->pd_tag, 960 PCI_BAR(pi->pi_bar + 1), base); 961 } 962 } 963 } 964 965 if (ocmd != cmd) { 966 pci_conf_write(pr->pr_pc, pd->pd_tag, 967 PCI_COMMAND_STATUS_REG, cmd); 968 } 969} 970 971/* 972 * pci_resource_alloc_bus -- 973 * 974 * Attempt to assign resources to all devices on a given bus, recursively. 975 */ 976static void 977pci_resource_alloc_bus(struct pci_resources *pr, uint8_t busno) 978{ 979 struct pci_bus *pb = PCICONF_RES_BUS(pr, busno); 980 struct pci_device *pd; 981 uint8_t devno, funcno; 982 983 for (devno = 0; devno <= pb->pb_lastdevno; devno++) { 984 for (funcno = 0; funcno < 8; funcno++) { 985 pd = PCICONF_BUS_DEVICE(pb, devno, funcno); 986 if (!pd->pd_present) { 987 if (funcno == 0) { 988 break; 989 } 990 continue; 991 } 992 if (!pd->pd_configured) { 993 pci_resource_alloc_device(pr, pd); 994 } 995 if (pd->pd_ppb) { 996 uint8_t sec_bus = PCI_BRIDGE_BUS_NUM_SECONDARY( 997 pd->pd_bridge.bridge_bus); 998 pci_resource_alloc_bus(pr, sec_bus); 999 } 1000 } 1001 } 1002} 1003 1004/* 1005 * pci_resource_init -- 1006 * 1007 * Public interface to PCI resource manager. Scans for available devices 1008 * and assigns resources. 1009 */ 1010void 1011pci_resource_init(const struct pci_resource_info *info) 1012{ 1013 struct pci_resources pr = {}; 1014 1015 pci_resource_probe(&pr, info); 1016 pci_resource_alloc_bus(&pr, pr.pr_startbus); 1017} 1018 1019/* 1020 * pci_resource_typename -- 1021 * 1022 * Return a string description of a PCI range type. 1023 */ 1024const char * 1025pci_resource_typename(enum pci_range_type prtype) 1026{ 1027 KASSERT(prtype < NUM_PCI_RANGES); 1028 return pci_range_typenames[prtype]; 1029} 1030