1 /* $NetBSD: acpi_resource.c,v 1.42 2021/08/07 18:39:40 jmcneill Exp $ */ 2 3 /* 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /*- 39 * Copyright (c) 2000 Michael Smith 40 * Copyright (c) 2000 BSDi 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 /* 66 * ACPI resource parsing. 67 */ 68 69 #include <sys/cdefs.h> 70 __KERNEL_RCSID(0, "$NetBSD: acpi_resource.c,v 1.42 2021/08/07 18:39:40 jmcneill Exp $"); 71 72 #include <sys/param.h> 73 #include <sys/device.h> 74 #include <sys/systm.h> 75 76 #include <dev/acpi/acpireg.h> 77 #include <dev/acpi/acpivar.h> 78 79 #define _COMPONENT ACPI_RESOURCE_COMPONENT 80 ACPI_MODULE_NAME("RESOURCE") 81 82 static ACPI_STATUS acpi_resource_parse_callback(ACPI_RESOURCE *, void *); 83 84 struct resource_parse_callback_arg { 85 const struct acpi_resource_parse_ops *ops; 86 bool include_producer; 87 device_t dev; 88 void *context; 89 }; 90 91 static ACPI_STATUS 92 acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context) 93 { 94 struct resource_parse_callback_arg *arg = context; 95 const struct acpi_resource_parse_ops *ops; 96 int i; 97 98 ACPI_FUNCTION_TRACE(__func__); 99 100 ops = arg->ops; 101 102 switch (res->Type) { 103 case ACPI_RESOURCE_TYPE_END_TAG: 104 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); 105 break; 106 case ACPI_RESOURCE_TYPE_FIXED_IO: 107 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 108 "FixedIo 0x%x/%u\n", 109 res->Data.FixedIo.Address, 110 res->Data.FixedIo.AddressLength)); 111 if (ops->ioport) 112 (*ops->ioport)(arg->dev, arg->context, 113 res->Data.FixedIo.Address, 114 res->Data.FixedIo.AddressLength); 115 break; 116 117 case ACPI_RESOURCE_TYPE_IO: 118 if (res->Data.Io.Minimum == 119 res->Data.Io.Maximum) { 120 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 121 "Io 0x%x/%u\n", 122 res->Data.Io.Minimum, 123 res->Data.Io.AddressLength)); 124 if (ops->ioport) 125 (*ops->ioport)(arg->dev, arg->context, 126 res->Data.Io.Minimum, 127 res->Data.Io.AddressLength); 128 } else { 129 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 130 "Io 0x%x-0x%x/%u\n", 131 res->Data.Io.Minimum, 132 res->Data.Io.Maximum, 133 res->Data.Io.AddressLength)); 134 if (ops->iorange) 135 (*ops->iorange)(arg->dev, arg->context, 136 res->Data.Io.Minimum, 137 res->Data.Io.Maximum, 138 res->Data.Io.AddressLength, 139 res->Data.Io.Alignment); 140 } 141 break; 142 143 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 144 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 145 "FixedMemory32 0x%x/%u\n", 146 res->Data.FixedMemory32.Address, 147 res->Data.FixedMemory32.AddressLength)); 148 if (ops->memory) 149 (*ops->memory)(arg->dev, arg->context, 150 res->Data.FixedMemory32.Address, 151 res->Data.FixedMemory32.AddressLength, 152 res->Data.FixedMemory32.Address); 153 break; 154 155 case ACPI_RESOURCE_TYPE_MEMORY32: 156 if (res->Data.Memory32.Minimum == 157 res->Data.Memory32.Maximum) { 158 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 159 "Memory32 0x%x/%u\n", 160 res->Data.Memory32.Minimum, 161 res->Data.Memory32.AddressLength)); 162 if (ops->memory) 163 (*ops->memory)(arg->dev, arg->context, 164 res->Data.Memory32.Minimum, 165 res->Data.Memory32.AddressLength, 166 res->Data.Memory32.Minimum); 167 } else { 168 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 169 "Memory32 0x%x-0x%x/%u\n", 170 res->Data.Memory32.Minimum, 171 res->Data.Memory32.Maximum, 172 res->Data.Memory32.AddressLength)); 173 if (ops->memrange) 174 (*ops->memrange)(arg->dev, arg->context, 175 res->Data.Memory32.Minimum, 176 res->Data.Memory32.Maximum, 177 res->Data.Memory32.AddressLength, 178 res->Data.Memory32.Alignment); 179 } 180 break; 181 182 case ACPI_RESOURCE_TYPE_MEMORY24: 183 if (res->Data.Memory24.Minimum == 184 res->Data.Memory24.Maximum) { 185 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 186 "Memory24 0x%x/%u\n", 187 res->Data.Memory24.Minimum, 188 res->Data.Memory24.AddressLength)); 189 if (ops->memory) 190 (*ops->memory)(arg->dev, arg->context, 191 res->Data.Memory24.Minimum, 192 res->Data.Memory24.AddressLength, 193 res->Data.Memory24.Minimum); 194 } else { 195 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 196 "Memory24 0x%x-0x%x/%u\n", 197 res->Data.Memory24.Minimum, 198 res->Data.Memory24.Maximum, 199 res->Data.Memory24.AddressLength)); 200 if (ops->memrange) 201 (*ops->memrange)(arg->dev, arg->context, 202 res->Data.Memory24.Minimum, 203 res->Data.Memory24.Maximum, 204 res->Data.Memory24.AddressLength, 205 res->Data.Memory24.Alignment); 206 } 207 break; 208 209 case ACPI_RESOURCE_TYPE_IRQ: 210 for (i = 0; i < res->Data.Irq.InterruptCount; i++) { 211 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 212 "IRQ %u\n", 213 res->Data.Irq.Interrupts[i])); 214 if (ops->irq) 215 (*ops->irq)(arg->dev, arg->context, 216 res->Data.Irq.Interrupts[i], 217 res->Data.Irq.Triggering); 218 } 219 break; 220 221 case ACPI_RESOURCE_TYPE_DMA: 222 for (i = 0; i < res->Data.Dma.ChannelCount; i++) { 223 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 224 "DRQ %u\n", 225 res->Data.Dma.Channels[i])); 226 if (ops->drq) 227 (*ops->drq)(arg->dev, arg->context, 228 res->Data.Dma.Channels[i]); 229 } 230 break; 231 232 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 233 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 234 "Start dependent functions: %u\n", 235 res->Data.StartDpf.CompatibilityPriority)); 236 if (ops->start_dep) 237 (*ops->start_dep)(arg->dev, arg->context, 238 res->Data.StartDpf.CompatibilityPriority); 239 break; 240 241 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 242 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 243 "End dependent functions\n")); 244 if (ops->end_dep) 245 (*ops->end_dep)(arg->dev, arg->context); 246 break; 247 248 case ACPI_RESOURCE_TYPE_ADDRESS32: 249 /* XXX Only fixed size supported for now */ 250 if (res->Data.Address32.Address.AddressLength == 0 || 251 (!arg->include_producer && 252 res->Data.Address32.ProducerConsumer != ACPI_CONSUMER)) 253 break; 254 #define ADDRESS32_FIXED2(r) \ 255 ((r)->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED && \ 256 (r)->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) 257 switch (res->Data.Address32.ResourceType) { 258 case ACPI_MEMORY_RANGE: 259 if (ADDRESS32_FIXED2(res)) { 260 if (ops->memory) 261 (*ops->memory)(arg->dev, arg->context, 262 res->Data.Address32.Address.Minimum, 263 res->Data.Address32.Address.AddressLength, 264 res->Data.Address32.Address.Minimum + 265 res->Data.Address32.Address.TranslationOffset); 266 } else { 267 if (ops->memrange) 268 (*ops->memrange)(arg->dev, arg->context, 269 res->Data.Address32.Address.Minimum, 270 res->Data.Address32.Address.Maximum, 271 res->Data.Address32.Address.AddressLength, 272 res->Data.Address32.Address.Granularity); 273 } 274 break; 275 case ACPI_IO_RANGE: 276 if (ADDRESS32_FIXED2(res)) { 277 if (ops->ioport) 278 (*ops->ioport)(arg->dev, arg->context, 279 res->Data.Address32.Address.Minimum, 280 res->Data.Address32.Address.AddressLength); 281 } else { 282 if (ops->iorange) 283 (*ops->iorange)(arg->dev, arg->context, 284 res->Data.Address32.Address.Minimum, 285 res->Data.Address32.Address.Maximum, 286 res->Data.Address32.Address.AddressLength, 287 res->Data.Address32.Address.Granularity); 288 } 289 break; 290 case ACPI_BUS_NUMBER_RANGE: 291 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 292 "Address32/BusNumber unimplemented\n")); 293 break; 294 } 295 #undef ADDRESS32_FIXED2 296 break; 297 298 case ACPI_RESOURCE_TYPE_ADDRESS16: 299 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 300 "Address16 unimplemented\n")); 301 break; 302 303 case ACPI_RESOURCE_TYPE_ADDRESS64: 304 #ifdef _LP64 305 /* XXX Only fixed size supported for now */ 306 if (res->Data.Address64.Address.AddressLength == 0 || 307 (!arg->include_producer && 308 res->Data.Address64.ProducerConsumer != ACPI_CONSUMER)) 309 break; 310 #define ADDRESS64_FIXED2(r) \ 311 ((r)->Data.Address64.MinAddressFixed == ACPI_ADDRESS_FIXED && \ 312 (r)->Data.Address64.MaxAddressFixed == ACPI_ADDRESS_FIXED) 313 switch (res->Data.Address64.ResourceType) { 314 case ACPI_MEMORY_RANGE: 315 if (ADDRESS64_FIXED2(res)) { 316 if (ops->memory) 317 (*ops->memory)(arg->dev, arg->context, 318 res->Data.Address64.Address.Minimum, 319 res->Data.Address64.Address.AddressLength, 320 res->Data.Address64.Address.Minimum + 321 res->Data.Address64.Address.TranslationOffset); 322 } else { 323 if (ops->memrange) 324 (*ops->memrange)(arg->dev, arg->context, 325 res->Data.Address64.Address.Minimum, 326 res->Data.Address64.Address.Maximum, 327 res->Data.Address64.Address.AddressLength, 328 res->Data.Address64.Address.Granularity); 329 } 330 break; 331 case ACPI_IO_RANGE: 332 if (ADDRESS64_FIXED2(res)) { 333 if (ops->ioport) 334 (*ops->ioport)(arg->dev, arg->context, 335 res->Data.Address64.Address.Minimum, 336 res->Data.Address64.Address.AddressLength); 337 } else { 338 if (ops->iorange) 339 (*ops->iorange)(arg->dev, arg->context, 340 res->Data.Address64.Address.Minimum, 341 res->Data.Address64.Address.Maximum, 342 res->Data.Address64.Address.AddressLength, 343 res->Data.Address64.Address.Granularity); 344 } 345 break; 346 case ACPI_BUS_NUMBER_RANGE: 347 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 348 "Address64/BusNumber unimplemented\n")); 349 break; 350 } 351 #undef ADDRESS64_FIXED2 352 #else 353 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 354 "Address64 unimplemented\n")); 355 #endif 356 break; 357 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 358 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 359 "Extended address64 unimplemented\n")); 360 break; 361 362 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 363 if (!arg->include_producer && 364 res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) { 365 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 366 "ignored ExtIRQ producer\n")); 367 break; 368 } 369 for (i = 0; i < res->Data.ExtendedIrq.InterruptCount; i++) { 370 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 371 "ExtIRQ %u\n", 372 res->Data.ExtendedIrq.Interrupts[i])); 373 if (ops->irq) 374 (*ops->irq)(arg->dev, arg->context, 375 res->Data.ExtendedIrq.Interrupts[i], 376 res->Data.ExtendedIrq.Triggering); 377 } 378 break; 379 380 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 381 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 382 "GenericRegister unimplemented\n")); 383 break; 384 385 case ACPI_RESOURCE_TYPE_VENDOR: 386 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 387 "VendorSpecific unimplemented\n")); 388 break; 389 390 default: 391 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 392 "Unknown resource type: %u\n", res->Type)); 393 break; 394 } 395 396 return_ACPI_STATUS(AE_OK); 397 } 398 399 400 /* 401 * acpi_resource_parse: 402 * 403 * Parse a device node's resources and fill them in for the 404 * client. 405 * 406 * This API supports _CRS (current resources) and 407 * _PRS (possible resources). 408 * 409 * Note that it might be nice to also locate ACPI-specific resource 410 * items, such as GPE bits. 411 */ 412 ACPI_STATUS 413 acpi_resource_parse(device_t dev, ACPI_HANDLE handle, const char *path, 414 void *arg, const struct acpi_resource_parse_ops *ops) 415 { 416 struct resource_parse_callback_arg cbarg; 417 ACPI_STATUS rv; 418 419 ACPI_FUNCTION_TRACE(__func__); 420 421 if (ops->init) 422 (*ops->init)(dev, arg, &cbarg.context); 423 else 424 cbarg.context = arg; 425 cbarg.ops = ops; 426 cbarg.dev = dev; 427 cbarg.include_producer = false; 428 429 rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback, 430 &cbarg); 431 if (ACPI_FAILURE(rv)) { 432 aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n", 433 path, AcpiFormatException(rv)); 434 return_ACPI_STATUS(rv); 435 } 436 437 if (ops->fini) 438 (*ops->fini)(dev, cbarg.context); 439 440 return_ACPI_STATUS(AE_OK); 441 } 442 443 /* 444 * acpi_resource_parse_any: 445 * 446 * Parse a device node's resources and fill them in for the 447 * client. Like acpi_resource_parse, but doesn't skip ResourceProducer 448 * type resources. 449 */ 450 ACPI_STATUS 451 acpi_resource_parse_any(device_t dev, ACPI_HANDLE handle, const char *path, 452 void *arg, const struct acpi_resource_parse_ops *ops) 453 { 454 struct resource_parse_callback_arg cbarg; 455 ACPI_STATUS rv; 456 457 ACPI_FUNCTION_TRACE(__func__); 458 459 if (ops->init) 460 (*ops->init)(dev, arg, &cbarg.context); 461 else 462 cbarg.context = arg; 463 cbarg.ops = ops; 464 cbarg.dev = dev; 465 cbarg.include_producer = true; 466 467 rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback, 468 &cbarg); 469 if (ACPI_FAILURE(rv)) { 470 aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n", 471 path, AcpiFormatException(rv)); 472 return_ACPI_STATUS(rv); 473 } 474 475 if (ops->fini) 476 (*ops->fini)(dev, cbarg.context); 477 478 return_ACPI_STATUS(AE_OK); 479 } 480 481 482 /* 483 * acpi_resource_print: 484 * 485 * Print the resources assigned to a device. 486 */ 487 void 488 acpi_resource_print(device_t dev, struct acpi_resources *res) 489 { 490 const char *sep; 491 492 if (SIMPLEQ_EMPTY(&res->ar_io) && 493 SIMPLEQ_EMPTY(&res->ar_iorange) && 494 SIMPLEQ_EMPTY(&res->ar_mem) && 495 SIMPLEQ_EMPTY(&res->ar_memrange) && 496 SIMPLEQ_EMPTY(&res->ar_irq) && 497 SIMPLEQ_EMPTY(&res->ar_drq)) 498 return; 499 500 aprint_normal(":"); 501 502 if (SIMPLEQ_EMPTY(&res->ar_io) == 0) { 503 struct acpi_io *ar; 504 505 sep = ""; 506 aprint_normal(" io "); 507 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 508 aprint_normal("%s0x%x", sep, ar->ar_base); 509 if (ar->ar_length > 1) 510 aprint_normal("-0x%x", ar->ar_base + 511 ar->ar_length - 1); 512 sep = ","; 513 } 514 } 515 516 /* XXX iorange */ 517 518 if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) { 519 struct acpi_mem *ar; 520 521 sep = ""; 522 aprint_normal(" mem "); 523 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 524 aprint_normal("%s0x%" PRIx64, sep, 525 (uint64_t)ar->ar_base); 526 if (ar->ar_length > 1) 527 aprint_normal("-0x%" PRIx64, 528 (uint64_t)ar->ar_base + 529 ar->ar_length - 1); 530 sep = ","; 531 } 532 } 533 534 /* XXX memrange */ 535 536 if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) { 537 struct acpi_irq *ar; 538 539 sep = ""; 540 aprint_normal(" irq "); 541 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 542 aprint_normal("%s%d", sep, ar->ar_irq); 543 sep = ","; 544 } 545 } 546 547 if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) { 548 struct acpi_drq *ar; 549 550 sep = ""; 551 aprint_normal(" drq "); 552 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 553 aprint_normal("%s%d", sep, ar->ar_drq); 554 sep = ","; 555 } 556 } 557 558 aprint_normal("\n"); 559 aprint_naive("\n"); 560 } 561 562 /* 563 * acpi_resource_cleanup: 564 * 565 * Free all allocated buffers 566 */ 567 void 568 acpi_resource_cleanup(struct acpi_resources *res) 569 { 570 while (!SIMPLEQ_EMPTY(&res->ar_io)) { 571 struct acpi_io *ar; 572 ar = SIMPLEQ_FIRST(&res->ar_io); 573 SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list); 574 ACPI_FREE(ar); 575 } 576 577 while (!SIMPLEQ_EMPTY(&res->ar_iorange)) { 578 struct acpi_iorange *ar; 579 ar = SIMPLEQ_FIRST(&res->ar_iorange); 580 SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list); 581 ACPI_FREE(ar); 582 } 583 584 while (!SIMPLEQ_EMPTY(&res->ar_mem)) { 585 struct acpi_mem *ar; 586 ar = SIMPLEQ_FIRST(&res->ar_mem); 587 SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list); 588 ACPI_FREE(ar); 589 } 590 591 while (!SIMPLEQ_EMPTY(&res->ar_memrange)) { 592 struct acpi_memrange *ar; 593 ar = SIMPLEQ_FIRST(&res->ar_memrange); 594 SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list); 595 ACPI_FREE(ar); 596 } 597 598 while (!SIMPLEQ_EMPTY(&res->ar_irq)) { 599 struct acpi_irq *ar; 600 ar = SIMPLEQ_FIRST(&res->ar_irq); 601 SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list); 602 ACPI_FREE(ar); 603 } 604 605 while (!SIMPLEQ_EMPTY(&res->ar_drq)) { 606 struct acpi_drq *ar; 607 ar = SIMPLEQ_FIRST(&res->ar_drq); 608 SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list); 609 ACPI_FREE(ar); 610 } 611 612 res->ar_nio = res->ar_niorange = res->ar_nmem = 613 res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0; 614 } 615 616 struct acpi_io * 617 acpi_res_io(struct acpi_resources *res, int idx) 618 { 619 struct acpi_io *ar; 620 621 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 622 if (ar->ar_index == idx) 623 return ar; 624 } 625 return NULL; 626 } 627 628 struct acpi_iorange * 629 acpi_res_iorange(struct acpi_resources *res, int idx) 630 { 631 struct acpi_iorange *ar; 632 633 SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) { 634 if (ar->ar_index == idx) 635 return ar; 636 } 637 return NULL; 638 } 639 640 struct acpi_mem * 641 acpi_res_mem(struct acpi_resources *res, int idx) 642 { 643 struct acpi_mem *ar; 644 645 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 646 if (ar->ar_index == idx) 647 return ar; 648 } 649 return NULL; 650 } 651 652 struct acpi_memrange * 653 acpi_res_memrange(struct acpi_resources *res, int idx) 654 { 655 struct acpi_memrange *ar; 656 657 SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) { 658 if (ar->ar_index == idx) 659 return ar; 660 } 661 return NULL; 662 } 663 664 struct acpi_irq * 665 acpi_res_irq(struct acpi_resources *res, int idx) 666 { 667 struct acpi_irq *ar; 668 669 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 670 if (ar->ar_index == idx) 671 return ar; 672 } 673 return NULL; 674 } 675 676 struct acpi_drq * 677 acpi_res_drq(struct acpi_resources *res, int idx) 678 { 679 struct acpi_drq *ar; 680 681 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 682 if (ar->ar_index == idx) 683 return ar; 684 } 685 return NULL; 686 } 687 688 /***************************************************************************** 689 * Default ACPI resource parse operations. 690 *****************************************************************************/ 691 692 static void acpi_res_parse_init(device_t, void *, void **); 693 static void acpi_res_parse_fini(device_t, void *); 694 695 static void acpi_res_parse_ioport(device_t, void *, uint32_t, 696 uint32_t); 697 static void acpi_res_parse_iorange(device_t, void *, uint32_t, 698 uint32_t, uint32_t, uint32_t); 699 700 static void acpi_res_parse_memory(device_t, void *, uint64_t, 701 uint64_t, uint64_t); 702 static void acpi_res_parse_memrange(device_t, void *, uint64_t, 703 uint64_t, uint64_t, uint64_t); 704 705 static void acpi_res_parse_irq(device_t, void *, uint32_t, uint32_t); 706 static void acpi_res_parse_drq(device_t, void *, uint32_t); 707 708 static void acpi_res_parse_start_dep(device_t, void *, int); 709 static void acpi_res_parse_end_dep(device_t, void *); 710 711 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = { 712 .init = acpi_res_parse_init, 713 .fini = acpi_res_parse_fini, 714 715 .ioport = acpi_res_parse_ioport, 716 .iorange = acpi_res_parse_iorange, 717 718 .memory = acpi_res_parse_memory, 719 .memrange = acpi_res_parse_memrange, 720 721 .irq = acpi_res_parse_irq, 722 .drq = acpi_res_parse_drq, 723 724 .start_dep = acpi_res_parse_start_dep, 725 .end_dep = acpi_res_parse_end_dep, 726 }; 727 728 const struct acpi_resource_parse_ops acpi_resource_parse_ops_quiet = { 729 .init = acpi_res_parse_init, 730 .fini = NULL, 731 732 .ioport = acpi_res_parse_ioport, 733 .iorange = acpi_res_parse_iorange, 734 735 .memory = acpi_res_parse_memory, 736 .memrange = acpi_res_parse_memrange, 737 738 .irq = acpi_res_parse_irq, 739 .drq = acpi_res_parse_drq, 740 741 .start_dep = acpi_res_parse_start_dep, 742 .end_dep = acpi_res_parse_end_dep, 743 }; 744 745 static void 746 acpi_res_parse_init(device_t dev, void *arg, void **contextp) 747 { 748 struct acpi_resources *res = arg; 749 750 SIMPLEQ_INIT(&res->ar_io); 751 res->ar_nio = 0; 752 753 SIMPLEQ_INIT(&res->ar_iorange); 754 res->ar_niorange = 0; 755 756 SIMPLEQ_INIT(&res->ar_mem); 757 res->ar_nmem = 0; 758 759 SIMPLEQ_INIT(&res->ar_memrange); 760 res->ar_nmemrange = 0; 761 762 SIMPLEQ_INIT(&res->ar_irq); 763 res->ar_nirq = 0; 764 765 SIMPLEQ_INIT(&res->ar_drq); 766 res->ar_ndrq = 0; 767 768 *contextp = res; 769 } 770 771 static void 772 acpi_res_parse_fini(device_t dev, void *context) 773 { 774 struct acpi_resources *res = context; 775 776 /* Print the resources we're using. */ 777 acpi_resource_print(dev, res); 778 } 779 780 static void 781 acpi_res_parse_ioport(device_t dev, void *context, uint32_t base, 782 uint32_t length) 783 { 784 struct acpi_resources *res = context; 785 struct acpi_io *ar; 786 787 /* 788 * Check if there is another I/O port directly below/under 789 * this one. 790 */ 791 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 792 if (ar->ar_base == base + length ) { 793 /* 794 * Entry just below existing entry - adjust 795 * the entry and return. 796 */ 797 ar->ar_base = base; 798 ar->ar_length += length; 799 return; 800 } else if (ar->ar_base + ar->ar_length == base) { 801 /* 802 * Entry just above existing entry - adjust 803 * the entry and return. 804 */ 805 ar->ar_length += length; 806 return; 807 } 808 } 809 810 ar = ACPI_ALLOCATE(sizeof(*ar)); 811 if (ar == NULL) { 812 aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n", 813 res->ar_nio); 814 res->ar_nio++; 815 return; 816 } 817 818 ar->ar_index = res->ar_nio++; 819 ar->ar_base = base; 820 ar->ar_length = length; 821 822 SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list); 823 } 824 825 static void 826 acpi_res_parse_iorange(device_t dev, void *context, uint32_t low, 827 uint32_t high, uint32_t length, uint32_t align) 828 { 829 struct acpi_resources *res = context; 830 struct acpi_iorange *ar; 831 832 ar = ACPI_ALLOCATE(sizeof(*ar)); 833 if (ar == NULL) { 834 aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n", 835 res->ar_niorange); 836 res->ar_niorange++; 837 return; 838 } 839 840 ar->ar_index = res->ar_niorange++; 841 ar->ar_low = low; 842 ar->ar_high = high; 843 ar->ar_length = length; 844 ar->ar_align = align; 845 846 SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list); 847 } 848 849 static void 850 acpi_res_parse_memory(device_t dev, void *context, uint64_t base, 851 uint64_t length, uint64_t xbase) 852 { 853 struct acpi_resources *res = context; 854 struct acpi_mem *ar; 855 856 ar = ACPI_ALLOCATE(sizeof(*ar)); 857 if (ar == NULL) { 858 aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n", 859 res->ar_nmem); 860 res->ar_nmem++; 861 return; 862 } 863 864 ar->ar_index = res->ar_nmem++; 865 ar->ar_base = base; 866 ar->ar_length = length; 867 ar->ar_xbase = xbase; 868 869 SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list); 870 } 871 872 static void 873 acpi_res_parse_memrange(device_t dev, void *context, uint64_t low, 874 uint64_t high, uint64_t length, uint64_t align) 875 { 876 struct acpi_resources *res = context; 877 struct acpi_memrange *ar; 878 879 ar = ACPI_ALLOCATE(sizeof(*ar)); 880 if (ar == NULL) { 881 aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n", 882 res->ar_nmemrange); 883 res->ar_nmemrange++; 884 return; 885 } 886 887 ar->ar_index = res->ar_nmemrange++; 888 ar->ar_low = low; 889 ar->ar_high = high; 890 ar->ar_length = length; 891 ar->ar_align = align; 892 893 SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list); 894 } 895 896 static void 897 acpi_res_parse_irq(device_t dev, void *context, uint32_t irq, uint32_t type) 898 { 899 struct acpi_resources *res = context; 900 struct acpi_irq *ar; 901 902 ar = ACPI_ALLOCATE(sizeof(*ar)); 903 if (ar == NULL) { 904 aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n", 905 res->ar_nirq); 906 res->ar_nirq++; 907 return; 908 } 909 910 ar->ar_index = res->ar_nirq++; 911 ar->ar_irq = irq; 912 ar->ar_type = type; 913 914 SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list); 915 } 916 917 static void 918 acpi_res_parse_drq(device_t dev, void *context, uint32_t drq) 919 { 920 struct acpi_resources *res = context; 921 struct acpi_drq *ar; 922 923 ar = ACPI_ALLOCATE(sizeof(*ar)); 924 if (ar == NULL) { 925 aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n", 926 res->ar_ndrq); 927 res->ar_ndrq++; 928 return; 929 } 930 931 ar->ar_index = res->ar_ndrq++; 932 ar->ar_drq = drq; 933 934 SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list); 935 } 936 937 static void 938 acpi_res_parse_start_dep(device_t dev, void *context, 939 int preference) 940 { 941 942 aprint_error_dev(dev, "ACPI: dependent functions not supported\n"); 943 } 944 945 static void 946 acpi_res_parse_end_dep(device_t dev, void *context) 947 { 948 949 /* Nothing to do. */ 950 } 951