1 /*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #include "opt_acpi.h" 30 #include <sys/param.h> 31 #include <sys/kernel.h> 32 #include <sys/bus.h> 33 #include <sys/limits.h> 34 #include <sys/malloc.h> 35 #include <sys/module.h> 36 37 #if defined(__i386__) || defined(__amd64__) 38 #include <machine/pci_cfgreg.h> 39 #endif 40 #include <machine/bus.h> 41 #include <machine/resource.h> 42 #include <sys/rman.h> 43 44 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 47 #include <dev/acpica/acpivar.h> 48 49 #ifdef INTRNG 50 #include "acpi_bus_if.h" 51 #endif 52 53 /* Hooks for the ACPI CA debugging infrastructure */ 54 #define _COMPONENT ACPI_BUS 55 ACPI_MODULE_NAME("RESOURCE") 56 57 struct lookup_irq_request { 58 ACPI_RESOURCE *acpi_res; 59 u_int irq; 60 int counter; 61 int rid; 62 int found; 63 int checkrid; 64 int trig; 65 int pol; 66 }; 67 68 static char *pcilink_ids[] = { "PNP0C0F", NULL }; 69 70 static ACPI_STATUS 71 acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context) 72 { 73 struct lookup_irq_request *req; 74 size_t len; 75 u_int irqnum, irq, trig, pol; 76 77 switch (res->Type) { 78 case ACPI_RESOURCE_TYPE_IRQ: 79 irqnum = res->Data.Irq.InterruptCount; 80 irq = res->Data.Irq.Interrupts[0]; 81 len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ); 82 trig = res->Data.Irq.Triggering; 83 pol = res->Data.Irq.Polarity; 84 break; 85 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 86 irqnum = res->Data.ExtendedIrq.InterruptCount; 87 irq = res->Data.ExtendedIrq.Interrupts[0]; 88 len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ); 89 trig = res->Data.ExtendedIrq.Triggering; 90 pol = res->Data.ExtendedIrq.Polarity; 91 break; 92 default: 93 return (AE_OK); 94 } 95 if (irqnum != 1) 96 return (AE_OK); 97 req = (struct lookup_irq_request *)context; 98 if (req->checkrid) { 99 if (req->counter != req->rid) { 100 req->counter++; 101 return (AE_OK); 102 } 103 KASSERT(irq == req->irq, ("IRQ resources do not match")); 104 } else { 105 if (req->irq != irq) 106 return (AE_OK); 107 } 108 req->found = 1; 109 req->pol = pol; 110 req->trig = trig; 111 if (req->acpi_res != NULL) 112 bcopy(res, req->acpi_res, len); 113 return (AE_CTRL_TERMINATE); 114 } 115 116 ACPI_STATUS 117 acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res, 118 ACPI_RESOURCE *acpi_res) 119 { 120 struct lookup_irq_request req; 121 ACPI_STATUS status; 122 123 req.acpi_res = acpi_res; 124 req.irq = rman_get_start(res); 125 req.counter = 0; 126 req.rid = rid; 127 req.found = 0; 128 req.checkrid = 1; 129 status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", 130 acpi_lookup_irq_handler, &req); 131 if (ACPI_SUCCESS(status) && req.found == 0) 132 status = AE_NOT_FOUND; 133 return (status); 134 } 135 136 void 137 acpi_config_intr(device_t dev, ACPI_RESOURCE *res) 138 { 139 u_int irq; 140 int pol, trig; 141 142 switch (res->Type) { 143 case ACPI_RESOURCE_TYPE_IRQ: 144 KASSERT(res->Data.Irq.InterruptCount == 1, 145 ("%s: multiple interrupts", __func__)); 146 irq = res->Data.Irq.Interrupts[0]; 147 trig = res->Data.Irq.Triggering; 148 pol = res->Data.Irq.Polarity; 149 break; 150 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 151 KASSERT(res->Data.ExtendedIrq.InterruptCount == 1, 152 ("%s: multiple interrupts", __func__)); 153 irq = res->Data.ExtendedIrq.Interrupts[0]; 154 trig = res->Data.ExtendedIrq.Triggering; 155 pol = res->Data.ExtendedIrq.Polarity; 156 break; 157 default: 158 panic("%s: bad resource type %u", __func__, res->Type); 159 } 160 161 #if defined(__amd64__) || defined(__i386__) 162 if (irq < 16 && trig == ACPI_EDGE_SENSITIVE && pol == ACPI_ACTIVE_LOW && 163 acpi_override_isa_irq_polarity) { 164 device_printf(dev, "forcing active-hi polarity for IRQ %u\n", irq); 165 pol = ACPI_ACTIVE_HIGH; 166 } 167 #endif 168 BUS_CONFIG_INTR(dev, irq, (trig == ACPI_EDGE_SENSITIVE) ? 169 INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ? 170 INTR_POLARITY_HIGH : INTR_POLARITY_LOW); 171 } 172 173 #ifdef INTRNG 174 int 175 acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle) 176 { 177 struct lookup_irq_request req; 178 int trig, pol; 179 180 trig = ACPI_LEVEL_SENSITIVE; 181 pol = ACPI_ACTIVE_HIGH; 182 if (handle != NULL) { 183 req.found = 0; 184 req.acpi_res = NULL; 185 req.irq = irq; 186 req.counter = 0; 187 req.rid = 0; 188 req.checkrid = 0; 189 AcpiWalkResources(handle, "_CRS", acpi_lookup_irq_handler, &req); 190 if (req.found != 0) { 191 trig = req.trig; 192 pol = req.pol; 193 } 194 } 195 return ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, irq, 196 (trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, 197 (pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW); 198 } 199 #endif 200 201 struct acpi_resource_context { 202 struct acpi_parse_resource_set *set; 203 device_t dev; 204 void *context; 205 bool ignore_producer_flag; 206 }; 207 208 #ifdef ACPI_DEBUG_OUTPUT 209 static const char * 210 acpi_address_range_name(UINT8 ResourceType) 211 { 212 static char buf[16]; 213 214 switch (ResourceType) { 215 case ACPI_MEMORY_RANGE: 216 return ("Memory"); 217 case ACPI_IO_RANGE: 218 return ("IO"); 219 case ACPI_BUS_NUMBER_RANGE: 220 return ("Bus Number"); 221 default: 222 snprintf(buf, sizeof(buf), "type %u", ResourceType); 223 return (buf); 224 } 225 } 226 #endif 227 228 static ACPI_STATUS 229 acpi_parse_resource(ACPI_RESOURCE *res, void *context) 230 { 231 struct acpi_parse_resource_set *set; 232 struct acpi_resource_context *arc; 233 UINT64 min, max, length, gran; 234 #ifdef ACPI_DEBUG 235 const char *name; 236 #endif 237 device_t dev; 238 239 arc = context; 240 dev = arc->dev; 241 set = arc->set; 242 243 switch (res->Type) { 244 case ACPI_RESOURCE_TYPE_END_TAG: 245 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); 246 break; 247 case ACPI_RESOURCE_TYPE_FIXED_IO: 248 if (res->Data.FixedIo.AddressLength <= 0) 249 break; 250 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n", 251 res->Data.FixedIo.Address, res->Data.FixedIo.AddressLength)); 252 set->set_ioport(dev, arc->context, res->Data.FixedIo.Address, 253 res->Data.FixedIo.AddressLength); 254 break; 255 case ACPI_RESOURCE_TYPE_IO: 256 if (res->Data.Io.AddressLength <= 0) 257 break; 258 if (res->Data.Io.Minimum == res->Data.Io.Maximum) { 259 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n", 260 res->Data.Io.Minimum, res->Data.Io.AddressLength)); 261 set->set_ioport(dev, arc->context, res->Data.Io.Minimum, 262 res->Data.Io.AddressLength); 263 } else { 264 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n", 265 res->Data.Io.Minimum, res->Data.Io.Maximum, 266 res->Data.Io.AddressLength)); 267 set->set_iorange(dev, arc->context, res->Data.Io.Minimum, 268 res->Data.Io.Maximum, res->Data.Io.AddressLength, 269 res->Data.Io.Alignment); 270 } 271 break; 272 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 273 if (res->Data.FixedMemory32.AddressLength <= 0) 274 break; 275 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n", 276 res->Data.FixedMemory32.Address, 277 res->Data.FixedMemory32.AddressLength)); 278 set->set_memory(dev, arc->context, res->Data.FixedMemory32.Address, 279 res->Data.FixedMemory32.AddressLength); 280 break; 281 case ACPI_RESOURCE_TYPE_MEMORY32: 282 if (res->Data.Memory32.AddressLength <= 0) 283 break; 284 if (res->Data.Memory32.Minimum == res->Data.Memory32.Maximum) { 285 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n", 286 res->Data.Memory32.Minimum, res->Data.Memory32.AddressLength)); 287 set->set_memory(dev, arc->context, res->Data.Memory32.Minimum, 288 res->Data.Memory32.AddressLength); 289 } else { 290 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n", 291 res->Data.Memory32.Minimum, res->Data.Memory32.Maximum, 292 res->Data.Memory32.AddressLength)); 293 set->set_memoryrange(dev, arc->context, res->Data.Memory32.Minimum, 294 res->Data.Memory32.Maximum, res->Data.Memory32.AddressLength, 295 res->Data.Memory32.Alignment); 296 } 297 break; 298 case ACPI_RESOURCE_TYPE_MEMORY24: 299 if (res->Data.Memory24.AddressLength <= 0) 300 break; 301 if (res->Data.Memory24.Minimum == res->Data.Memory24.Maximum) { 302 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n", 303 res->Data.Memory24.Minimum, res->Data.Memory24.AddressLength)); 304 set->set_memory(dev, arc->context, res->Data.Memory24.Minimum, 305 res->Data.Memory24.AddressLength); 306 } else { 307 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n", 308 res->Data.Memory24.Minimum, res->Data.Memory24.Maximum, 309 res->Data.Memory24.AddressLength)); 310 set->set_memoryrange(dev, arc->context, res->Data.Memory24.Minimum, 311 res->Data.Memory24.Maximum, res->Data.Memory24.AddressLength, 312 res->Data.Memory24.Alignment); 313 } 314 break; 315 case ACPI_RESOURCE_TYPE_IRQ: 316 /* 317 * from 1.0b 6.4.2 318 * "This structure is repeated for each separate interrupt 319 * required" 320 */ 321 set->set_irq(dev, arc->context, res->Data.Irq.Interrupts, 322 res->Data.Irq.InterruptCount, res->Data.Irq.Triggering, 323 res->Data.Irq.Polarity); 324 break; 325 case ACPI_RESOURCE_TYPE_DMA: 326 /* 327 * from 1.0b 6.4.3 328 * "This structure is repeated for each separate DMA channel 329 * required" 330 */ 331 set->set_drq(dev, arc->context, res->Data.Dma.Channels, 332 res->Data.Dma.ChannelCount); 333 break; 334 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 335 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n")); 336 set->set_start_dependent(dev, arc->context, 337 res->Data.StartDpf.CompatibilityPriority); 338 break; 339 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 340 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n")); 341 set->set_end_dependent(dev, arc->context); 342 break; 343 case ACPI_RESOURCE_TYPE_ADDRESS16: 344 case ACPI_RESOURCE_TYPE_ADDRESS32: 345 case ACPI_RESOURCE_TYPE_ADDRESS64: 346 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 347 switch (res->Type) { 348 case ACPI_RESOURCE_TYPE_ADDRESS16: 349 gran = res->Data.Address16.Address.Granularity; 350 min = res->Data.Address16.Address.Minimum; 351 max = res->Data.Address16.Address.Maximum; 352 length = res->Data.Address16.Address.AddressLength; 353 #ifdef ACPI_DEBUG 354 name = "Address16"; 355 #endif 356 break; 357 case ACPI_RESOURCE_TYPE_ADDRESS32: 358 gran = res->Data.Address32.Address.Granularity; 359 min = res->Data.Address32.Address.Minimum; 360 max = res->Data.Address32.Address.Maximum; 361 length = res->Data.Address32.Address.AddressLength; 362 #ifdef ACPI_DEBUG 363 name = "Address32"; 364 #endif 365 break; 366 case ACPI_RESOURCE_TYPE_ADDRESS64: 367 gran = res->Data.Address64.Address.Granularity; 368 min = res->Data.Address64.Address.Minimum; 369 max = res->Data.Address64.Address.Maximum; 370 length = res->Data.Address64.Address.AddressLength; 371 #ifdef ACPI_DEBUG 372 name = "Address64"; 373 #endif 374 break; 375 default: 376 KASSERT(res->Type == ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, 377 ("should never happen")); 378 gran = res->Data.ExtAddress64.Address.Granularity; 379 min = res->Data.ExtAddress64.Address.Minimum; 380 max = res->Data.ExtAddress64.Address.Maximum; 381 length = res->Data.ExtAddress64.Address.AddressLength; 382 #ifdef ACPI_DEBUG 383 name = "ExtAddress64"; 384 #endif 385 break; 386 } 387 if (length <= 0) 388 break; 389 if (!arc->ignore_producer_flag && 390 res->Data.Address.ProducerConsumer != ACPI_CONSUMER) { 391 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 392 "ignored %s %s producer\n", name, 393 acpi_address_range_name(res->Data.Address.ResourceType))); 394 break; 395 } 396 if (res->Data.Address.ResourceType != ACPI_MEMORY_RANGE && 397 res->Data.Address.ResourceType != ACPI_IO_RANGE) { 398 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 399 "ignored %s for non-memory, non-I/O\n", name)); 400 break; 401 } 402 403 #ifdef __i386__ 404 if (min > ULONG_MAX || (res->Data.Address.MaxAddressFixed && max > 405 ULONG_MAX)) { 406 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored %s above 4G\n", 407 name)); 408 break; 409 } 410 if (max > ULONG_MAX) 411 max = ULONG_MAX; 412 #endif 413 if (res->Data.Address.MinAddressFixed == ACPI_ADDRESS_FIXED && 414 res->Data.Address.MaxAddressFixed == ACPI_ADDRESS_FIXED) { 415 if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) { 416 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%jx/%ju\n", 417 name, (uintmax_t)min, (uintmax_t)length)); 418 set->set_memory(dev, arc->context, min, length); 419 } else { 420 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx/%ju\n", name, 421 (uintmax_t)min, (uintmax_t)length)); 422 set->set_ioport(dev, arc->context, min, length); 423 } 424 } else if (res->Data.Address.MinAddressFixed != ACPI_ADDRESS_FIXED && 425 res->Data.Address.MaxAddressFixed != ACPI_ADDRESS_FIXED) { 426 /* Fixed size, variable location resource descriptor */ 427 min = roundup(min, gran + 1); 428 if ((min + length - 1) > max) { 429 device_printf(dev, 430 "invalid memory range: start: %jx end: %jx max: %jx\n", 431 (uintmax_t)min, (uintmax_t)(min + length - 1), 432 (uintmax_t)max); 433 } else { 434 if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) { 435 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 436 "%s/Memory 0x%jx/%ju\n", name, (uintmax_t)min, 437 (uintmax_t)length)); 438 set->set_memory(dev, arc->context, min, length); 439 } else { 440 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx/%ju\n", 441 name, (uintmax_t)min, (uintmax_t)length)); 442 set->set_ioport(dev, arc->context, min, length); 443 } 444 } 445 } else { 446 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { 447 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 448 "%s/Memory 0x%jx-0x%jx/%ju\n", name, (uintmax_t)min, 449 (uintmax_t)max, (uintmax_t)length)); 450 set->set_memoryrange(dev, arc->context, min, max, length, gran); 451 } else { 452 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx-0x%jx/%ju\n", 453 name, (uintmax_t)min, (uintmax_t)max, (uintmax_t)length)); 454 set->set_iorange(dev, arc->context, min, max, length, gran); 455 } 456 } 457 break; 458 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 459 if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) { 460 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored ExtIRQ producer\n")); 461 break; 462 } 463 set->set_ext_irq(dev, arc->context, res->Data.ExtendedIrq.Interrupts, 464 res->Data.ExtendedIrq.InterruptCount, 465 res->Data.ExtendedIrq.Triggering, res->Data.ExtendedIrq.Polarity); 466 break; 467 case ACPI_RESOURCE_TYPE_VENDOR: 468 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 469 "unimplemented VendorSpecific resource\n")); 470 break; 471 default: 472 break; 473 } 474 return (AE_OK); 475 } 476 477 /* 478 * Fetch a device's resources and associate them with the device. 479 * 480 * Note that it might be nice to also locate ACPI-specific resource items, such 481 * as GPE bits. 482 * 483 * We really need to split the resource-fetching code out from the 484 * resource-parsing code, since we may want to use the parsing 485 * code for _PRS someday. 486 */ 487 ACPI_STATUS 488 acpi_parse_resources(device_t dev, ACPI_HANDLE handle, 489 struct acpi_parse_resource_set *set, void *arg) 490 { 491 struct acpi_resource_context arc; 492 ACPI_STATUS status; 493 494 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 495 496 set->set_init(dev, arg, &arc.context); 497 arc.set = set; 498 arc.dev = dev; 499 arc.ignore_producer_flag = false; 500 501 /* 502 * UARTs on ThunderX2 set ResourceProducer on memory resources, with 503 * 7.2 firmware. 504 */ 505 if (acpi_MatchHid(handle, "ARMH0011") != ACPI_MATCHHID_NOMATCH) 506 arc.ignore_producer_flag = true; 507 508 /* 509 * ARM Coresight on N1SDP set ResourceProducer on memory resources. 510 * Coresight devices: ETM, STM, TPIU, ETF/ETR, REP, FUN. 511 */ 512 if (acpi_MatchHid(handle, "ARMHC500") != ACPI_MATCHHID_NOMATCH || 513 acpi_MatchHid(handle, "ARMHC502") != ACPI_MATCHHID_NOMATCH || 514 acpi_MatchHid(handle, "ARMHC600") != ACPI_MATCHHID_NOMATCH || 515 acpi_MatchHid(handle, "ARMHC979") != ACPI_MATCHHID_NOMATCH || 516 acpi_MatchHid(handle, "ARMHC97C") != ACPI_MATCHHID_NOMATCH || 517 acpi_MatchHid(handle, "ARMHC98D") != ACPI_MATCHHID_NOMATCH || 518 acpi_MatchHid(handle, "ARMHC9FF") != ACPI_MATCHHID_NOMATCH || 519 acpi_MatchHid(handle, "ARMHD620") != ACPI_MATCHHID_NOMATCH) 520 arc.ignore_producer_flag = true; 521 522 /* 523 * The DesignWare I2C Controller on Ampere Altra sets ResourceProducer on 524 * memory resources. 525 */ 526 if (acpi_MatchHid(handle, "APMC0D0F") != ACPI_MATCHHID_NOMATCH) 527 arc.ignore_producer_flag = true; 528 529 status = AcpiWalkResources(handle, "_CRS", acpi_parse_resource, &arc); 530 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 531 printf("can't fetch resources for %s - %s\n", 532 acpi_name(handle), AcpiFormatException(status)); 533 return_ACPI_STATUS (status); 534 } 535 set->set_done(dev, arc.context); 536 return_ACPI_STATUS (AE_OK); 537 } 538 539 /* 540 * Resource-set vectors used to attach _CRS-derived resources 541 * to an ACPI device. 542 */ 543 static void acpi_res_set_init(device_t dev, void *arg, void **context); 544 static void acpi_res_set_done(device_t dev, void *context); 545 static void acpi_res_set_ioport(device_t dev, void *context, 546 uint64_t base, uint64_t length); 547 static void acpi_res_set_iorange(device_t dev, void *context, 548 uint64_t low, uint64_t high, 549 uint64_t length, uint64_t align); 550 static void acpi_res_set_memory(device_t dev, void *context, 551 uint64_t base, uint64_t length); 552 static void acpi_res_set_memoryrange(device_t dev, void *context, 553 uint64_t low, uint64_t high, 554 uint64_t length, uint64_t align); 555 static void acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, 556 int count, int trig, int pol); 557 static void acpi_res_set_ext_irq(device_t dev, void *context, 558 uint32_t *irq, int count, int trig, int pol); 559 static void acpi_res_set_drq(device_t dev, void *context, uint8_t *drq, 560 int count); 561 static void acpi_res_set_start_dependent(device_t dev, void *context, 562 int preference); 563 static void acpi_res_set_end_dependent(device_t dev, void *context); 564 565 struct acpi_parse_resource_set acpi_res_parse_set = { 566 acpi_res_set_init, 567 acpi_res_set_done, 568 acpi_res_set_ioport, 569 acpi_res_set_iorange, 570 acpi_res_set_memory, 571 acpi_res_set_memoryrange, 572 acpi_res_set_irq, 573 acpi_res_set_ext_irq, 574 acpi_res_set_drq, 575 acpi_res_set_start_dependent, 576 acpi_res_set_end_dependent 577 }; 578 579 struct acpi_res_context { 580 int ar_nio; 581 int ar_nmem; 582 int ar_nirq; 583 int ar_ndrq; 584 void *ar_parent; 585 }; 586 587 /* 588 * Some resources reported via _CRS should not be added as bus 589 * resources. This function returns true if a resource reported via 590 * _CRS should be ignored. 591 */ 592 static bool 593 acpi_res_ignore(device_t dev, int type, rman_res_t start, rman_res_t count) 594 { 595 struct acpi_device *ad = device_get_ivars(dev); 596 ACPI_DEVICE_INFO *devinfo; 597 bool allow; 598 599 /* Ignore IRQ resources for PCI link devices. */ 600 if (type == SYS_RES_IRQ && 601 ACPI_ID_PROBE(device_get_parent(dev), dev, pcilink_ids, NULL) <= 0) 602 return (true); 603 604 /* 605 * Ignore most resources for PCI root bridges. Some BIOSes 606 * incorrectly enumerate the memory ranges they decode as plain 607 * memory resources instead of as ResourceProducer ranges. Other 608 * BIOSes incorrectly list system resource entries for I/O ranges 609 * under the PCI bridge. Do allow the one known-correct case on 610 * x86 of a PCI bridge claiming the I/O ports used for PCI config 611 * access. 612 */ 613 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { 614 if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) { 615 if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { 616 #if defined(__i386__) || defined(__amd64__) 617 allow = (type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT); 618 #else 619 allow = false; 620 #endif 621 if (!allow) { 622 AcpiOsFree(devinfo); 623 return (true); 624 } 625 } 626 AcpiOsFree(devinfo); 627 } 628 } 629 630 return (false); 631 } 632 633 static void 634 acpi_res_set_init(device_t dev, void *arg, void **context) 635 { 636 struct acpi_res_context *cp; 637 638 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) { 639 bzero(cp, sizeof(*cp)); 640 cp->ar_parent = arg; 641 *context = cp; 642 } 643 } 644 645 static void 646 acpi_res_set_done(device_t dev, void *context) 647 { 648 struct acpi_res_context *cp = (struct acpi_res_context *)context; 649 650 if (cp == NULL) 651 return; 652 AcpiOsFree(cp); 653 } 654 655 static void 656 acpi_res_set_ioport(device_t dev, void *context, uint64_t base, 657 uint64_t length) 658 { 659 struct acpi_res_context *cp = (struct acpi_res_context *)context; 660 661 if (cp == NULL) 662 return; 663 if (acpi_res_ignore(dev, SYS_RES_IOPORT, base, length)) 664 return; 665 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length); 666 } 667 668 static void 669 acpi_res_set_iorange(device_t dev, void *context, uint64_t low, 670 uint64_t high, uint64_t length, uint64_t align) 671 { 672 struct acpi_res_context *cp = (struct acpi_res_context *)context; 673 674 if (cp == NULL) 675 return; 676 677 /* 678 * XXX: Some BIOSes contain buggy _CRS entries where fixed I/O 679 * ranges have the maximum base address (_MAX) to the end of the 680 * I/O range instead of the start. These are then treated as a 681 * relocatable I/O range rather than a fixed I/O resource. As a 682 * workaround, treat I/O resources encoded this way as fixed I/O 683 * ports. 684 */ 685 if (high == (low + length)) { 686 if (bootverbose) 687 device_printf(dev, 688 "_CRS has fixed I/O port range defined as relocatable\n"); 689 690 if (acpi_res_ignore(dev, SYS_RES_IOPORT, low, length)) 691 return; 692 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, low, length); 693 return; 694 } 695 696 device_printf(dev, "I/O range not supported\n"); 697 } 698 699 static void 700 acpi_res_set_memory(device_t dev, void *context, uint64_t base, 701 uint64_t length) 702 { 703 struct acpi_res_context *cp = (struct acpi_res_context *)context; 704 705 if (cp == NULL) 706 return; 707 if (acpi_res_ignore(dev, SYS_RES_MEMORY, base, length)) 708 return; 709 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length); 710 } 711 712 static void 713 acpi_res_set_memoryrange(device_t dev, void *context, uint64_t low, 714 uint64_t high, uint64_t length, uint64_t align) 715 { 716 struct acpi_res_context *cp = (struct acpi_res_context *)context; 717 718 if (cp == NULL) 719 return; 720 device_printf(dev, "memory range not supported\n"); 721 } 722 723 static void 724 acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count, 725 int trig, int pol) 726 { 727 struct acpi_res_context *cp = (struct acpi_res_context *)context; 728 int i; 729 730 if (cp == NULL || irq == NULL) 731 return; 732 733 for (i = 0; i < count; i++) { 734 if (acpi_res_ignore(dev, SYS_RES_IRQ, irq[i], 1)) 735 continue; 736 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq[i], 1); 737 } 738 } 739 740 static void 741 acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count, 742 int trig, int pol) 743 { 744 struct acpi_res_context *cp = (struct acpi_res_context *)context; 745 int i; 746 747 if (cp == NULL || irq == NULL) 748 return; 749 750 for (i = 0; i < count; i++) { 751 if (acpi_res_ignore(dev, SYS_RES_IRQ, irq[i], 1)) 752 continue; 753 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq[i], 1); 754 } 755 } 756 757 static void 758 acpi_res_set_drq(device_t dev, void *context, uint8_t *drq, int count) 759 { 760 struct acpi_res_context *cp = (struct acpi_res_context *)context; 761 762 if (cp == NULL || drq == NULL) 763 return; 764 765 /* This implements no resource relocation. */ 766 if (count != 1) 767 return; 768 769 if (acpi_res_ignore(dev, SYS_RES_DRQ, *drq, 1)) 770 return; 771 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1); 772 } 773 774 static void 775 acpi_res_set_start_dependent(device_t dev, void *context, int preference) 776 { 777 struct acpi_res_context *cp = (struct acpi_res_context *)context; 778 779 if (cp == NULL) 780 return; 781 device_printf(dev, "dependent functions not supported\n"); 782 } 783 784 static void 785 acpi_res_set_end_dependent(device_t dev, void *context) 786 { 787 struct acpi_res_context *cp = (struct acpi_res_context *)context; 788 789 if (cp == NULL) 790 return; 791 device_printf(dev, "dependent functions not supported\n"); 792 } 793 794 /* 795 * Resource-owning placeholders for IO and memory pseudo-devices. 796 * 797 * This code allocates system resources that will be used by ACPI 798 * child devices. The acpi parent manages these resources through a 799 * private rman. 800 */ 801 802 static int acpi_sysres_probe(device_t dev); 803 static int acpi_sysres_attach(device_t dev); 804 805 static device_method_t acpi_sysres_methods[] = { 806 /* Device interface */ 807 DEVMETHOD(device_probe, acpi_sysres_probe), 808 DEVMETHOD(device_attach, acpi_sysres_attach), 809 810 DEVMETHOD_END 811 }; 812 813 static driver_t acpi_sysres_driver = { 814 "acpi_sysresource", 815 acpi_sysres_methods, 816 0, 817 }; 818 819 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, 0, 0); 820 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1); 821 822 static int 823 acpi_sysres_probe(device_t dev) 824 { 825 static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; 826 int rv; 827 828 if (acpi_disabled("sysresource")) 829 return (ENXIO); 830 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, sysres_ids, NULL); 831 if (rv > 0){ 832 return (rv); 833 } 834 device_set_desc(dev, "System Resource"); 835 device_quiet(dev); 836 return (rv); 837 } 838 839 static int 840 acpi_sysres_attach(device_t dev) 841 { 842 device_t bus; 843 struct acpi_softc *bus_sc; 844 struct resource_list_entry *bus_rle, *dev_rle; 845 struct resource_list *bus_rl, *dev_rl; 846 int done, type; 847 rman_res_t start, end, count; 848 849 /* 850 * Loop through all current resources to see if the new one overlaps 851 * any existing ones. If so, grow the old one up and/or down 852 * accordingly. Discard any that are wholly contained in the old. If 853 * the resource is unique, add it to the parent. It will later go into 854 * the rman pool. 855 */ 856 bus = device_get_parent(dev); 857 dev_rl = BUS_GET_RESOURCE_LIST(bus, dev); 858 bus_sc = acpi_device_get_parent_softc(dev); 859 bus_rl = &bus_sc->sysres_rl; 860 STAILQ_FOREACH(dev_rle, dev_rl, link) { 861 if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY) 862 continue; 863 864 start = dev_rle->start; 865 end = dev_rle->end; 866 count = dev_rle->count; 867 type = dev_rle->type; 868 done = FALSE; 869 870 STAILQ_FOREACH(bus_rle, bus_rl, link) { 871 if (bus_rle->type != type) 872 continue; 873 874 /* New resource wholly contained in old, discard. */ 875 if (start >= bus_rle->start && end <= bus_rle->end) 876 break; 877 878 /* New tail overlaps old head, grow existing resource downward. */ 879 if (start < bus_rle->start && end >= bus_rle->start) { 880 bus_rle->count += bus_rle->start - start; 881 bus_rle->start = start; 882 done = TRUE; 883 } 884 885 /* New head overlaps old tail, grow existing resource upward. */ 886 if (start <= bus_rle->end && end > bus_rle->end) { 887 bus_rle->count += end - bus_rle->end; 888 bus_rle->end = end; 889 done = TRUE; 890 } 891 892 /* If we adjusted the old resource, we're finished. */ 893 if (done) 894 break; 895 } 896 897 /* If we didn't merge with anything, add this resource. */ 898 if (bus_rle == NULL) 899 resource_list_add_next(bus_rl, type, start, end, count); 900 } 901 902 /* After merging/moving resources to the parent, free the list. */ 903 resource_list_free(dev_rl); 904 905 return (0); 906 } 907