1 /* $NetBSD: acpi_resource.c,v 1.35 2011/06/30 20:09:39 wiz 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.35 2011/06/30 20:09:39 wiz 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 device_t dev; 87 void *context; 88 }; 89 90 static ACPI_STATUS 91 acpi_resource_parse_callback(ACPI_RESOURCE *res, void *context) 92 { 93 struct resource_parse_callback_arg *arg = context; 94 const struct acpi_resource_parse_ops *ops; 95 int i; 96 97 ACPI_FUNCTION_TRACE(__func__); 98 99 ops = arg->ops; 100 101 switch (res->Type) { 102 case ACPI_RESOURCE_TYPE_FIXED_IO: 103 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 104 "FixedIo 0x%x/%u\n", 105 res->Data.FixedIo.Address, 106 res->Data.FixedIo.AddressLength)); 107 if (ops->ioport) 108 (*ops->ioport)(arg->dev, arg->context, 109 res->Data.FixedIo.Address, 110 res->Data.FixedIo.AddressLength); 111 break; 112 113 case ACPI_RESOURCE_TYPE_IO: 114 if (res->Data.Io.Minimum == 115 res->Data.Io.Maximum) { 116 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 117 "Io 0x%x/%u\n", 118 res->Data.Io.Minimum, 119 res->Data.Io.AddressLength)); 120 if (ops->ioport) 121 (*ops->ioport)(arg->dev, arg->context, 122 res->Data.Io.Minimum, 123 res->Data.Io.AddressLength); 124 } else { 125 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 126 "Io 0x%x-0x%x/%u\n", 127 res->Data.Io.Minimum, 128 res->Data.Io.Maximum, 129 res->Data.Io.AddressLength)); 130 if (ops->iorange) 131 (*ops->iorange)(arg->dev, arg->context, 132 res->Data.Io.Minimum, 133 res->Data.Io.Maximum, 134 res->Data.Io.AddressLength, 135 res->Data.Io.Alignment); 136 } 137 break; 138 139 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 140 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 141 "FixedMemory32 0x%x/%u\n", 142 res->Data.FixedMemory32.Address, 143 res->Data.FixedMemory32.AddressLength)); 144 if (ops->memory) 145 (*ops->memory)(arg->dev, arg->context, 146 res->Data.FixedMemory32.Address, 147 res->Data.FixedMemory32.AddressLength); 148 break; 149 150 case ACPI_RESOURCE_TYPE_MEMORY32: 151 if (res->Data.Memory32.Minimum == 152 res->Data.Memory32.Maximum) { 153 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 154 "Memory32 0x%x/%u\n", 155 res->Data.Memory32.Minimum, 156 res->Data.Memory32.AddressLength)); 157 if (ops->memory) 158 (*ops->memory)(arg->dev, arg->context, 159 res->Data.Memory32.Minimum, 160 res->Data.Memory32.AddressLength); 161 } else { 162 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 163 "Memory32 0x%x-0x%x/%u\n", 164 res->Data.Memory32.Minimum, 165 res->Data.Memory32.Maximum, 166 res->Data.Memory32.AddressLength)); 167 if (ops->memrange) 168 (*ops->memrange)(arg->dev, arg->context, 169 res->Data.Memory32.Minimum, 170 res->Data.Memory32.Maximum, 171 res->Data.Memory32.AddressLength, 172 res->Data.Memory32.Alignment); 173 } 174 break; 175 176 case ACPI_RESOURCE_TYPE_MEMORY24: 177 if (res->Data.Memory24.Minimum == 178 res->Data.Memory24.Maximum) { 179 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 180 "Memory24 0x%x/%u\n", 181 res->Data.Memory24.Minimum, 182 res->Data.Memory24.AddressLength)); 183 if (ops->memory) 184 (*ops->memory)(arg->dev, arg->context, 185 res->Data.Memory24.Minimum, 186 res->Data.Memory24.AddressLength); 187 } else { 188 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 189 "Memory24 0x%x-0x%x/%u\n", 190 res->Data.Memory24.Minimum, 191 res->Data.Memory24.Maximum, 192 res->Data.Memory24.AddressLength)); 193 if (ops->memrange) 194 (*ops->memrange)(arg->dev, arg->context, 195 res->Data.Memory24.Minimum, 196 res->Data.Memory24.Maximum, 197 res->Data.Memory24.AddressLength, 198 res->Data.Memory24.Alignment); 199 } 200 break; 201 202 case ACPI_RESOURCE_TYPE_IRQ: 203 for (i = 0; i < res->Data.Irq.InterruptCount; i++) { 204 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 205 "IRQ %u\n", 206 res->Data.Irq.Interrupts[i])); 207 if (ops->irq) 208 (*ops->irq)(arg->dev, arg->context, 209 res->Data.Irq.Interrupts[i], 210 res->Data.Irq.Triggering); 211 } 212 break; 213 214 case ACPI_RESOURCE_TYPE_DMA: 215 for (i = 0; i < res->Data.Dma.ChannelCount; i++) { 216 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 217 "DRQ %u\n", 218 res->Data.Dma.Channels[i])); 219 if (ops->drq) 220 (*ops->drq)(arg->dev, arg->context, 221 res->Data.Dma.Channels[i]); 222 } 223 break; 224 225 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 226 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 227 "Start dependent functions: %u\n", 228 res->Data.StartDpf.CompatibilityPriority)); 229 if (ops->start_dep) 230 (*ops->start_dep)(arg->dev, arg->context, 231 res->Data.StartDpf.CompatibilityPriority); 232 break; 233 234 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 235 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 236 "End dependent functions\n")); 237 if (ops->end_dep) 238 (*ops->end_dep)(arg->dev, arg->context); 239 break; 240 241 case ACPI_RESOURCE_TYPE_ADDRESS32: 242 /* XXX Only fixed size supported for now */ 243 if (res->Data.Address32.AddressLength == 0 || 244 res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) 245 break; 246 #define ADRRESS32_FIXED2(r) \ 247 ((r)->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED && \ 248 (r)->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) 249 switch (res->Data.Address32.ResourceType) { 250 case ACPI_MEMORY_RANGE: 251 if (ADRRESS32_FIXED2(res)) { 252 if (ops->memory) 253 (*ops->memory)(arg->dev, arg->context, 254 res->Data.Address32.Minimum, 255 res->Data.Address32.AddressLength); 256 } else { 257 if (ops->memrange) 258 (*ops->memrange)(arg->dev, arg->context, 259 res->Data.Address32.Minimum, 260 res->Data.Address32.Maximum, 261 res->Data.Address32.AddressLength, 262 res->Data.Address32.Granularity); 263 } 264 break; 265 case ACPI_IO_RANGE: 266 if (ADRRESS32_FIXED2(res)) { 267 if (ops->ioport) 268 (*ops->ioport)(arg->dev, arg->context, 269 res->Data.Address32.Minimum, 270 res->Data.Address32.AddressLength); 271 } else { 272 if (ops->iorange) 273 (*ops->iorange)(arg->dev, arg->context, 274 res->Data.Address32.Minimum, 275 res->Data.Address32.Maximum, 276 res->Data.Address32.AddressLength, 277 res->Data.Address32.Granularity); 278 } 279 break; 280 case ACPI_BUS_NUMBER_RANGE: 281 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 282 "Address32/BusNumber unimplemented\n")); 283 break; 284 } 285 #undef ADRRESS32_FIXED2 286 break; 287 288 case ACPI_RESOURCE_TYPE_ADDRESS16: 289 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 290 "Address16 unimplemented\n")); 291 break; 292 293 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 294 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 295 "Extended address64 unimplemented\n")); 296 break; 297 298 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 299 if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) { 300 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 301 "ignored ExtIRQ producer\n")); 302 break; 303 } 304 for (i = 0; i < res->Data.ExtendedIrq.InterruptCount; i++) { 305 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 306 "ExtIRQ %u\n", 307 res->Data.ExtendedIrq.Interrupts[i])); 308 if (ops->irq) 309 (*ops->irq)(arg->dev, arg->context, 310 res->Data.ExtendedIrq.Interrupts[i], 311 res->Data.ExtendedIrq.Triggering); 312 } 313 break; 314 315 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 316 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 317 "GenericRegister unimplemented\n")); 318 break; 319 320 case ACPI_RESOURCE_TYPE_VENDOR: 321 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 322 "VendorSpecific unimplemented\n")); 323 break; 324 325 default: 326 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 327 "Unknown resource type: %u\n", res->Type)); 328 break; 329 } 330 331 return_ACPI_STATUS(AE_OK); 332 } 333 334 335 /* 336 * acpi_resource_parse: 337 * 338 * Parse a device node's resources and fill them in for the 339 * client. 340 * 341 * This API supports _CRS (current resources) and 342 * _PRS (possible resources). 343 * 344 * Note that it might be nice to also locate ACPI-specific resource 345 * items, such as GPE bits. 346 */ 347 ACPI_STATUS 348 acpi_resource_parse(device_t dev, ACPI_HANDLE handle, const char *path, 349 void *arg, const struct acpi_resource_parse_ops *ops) 350 { 351 struct resource_parse_callback_arg cbarg; 352 ACPI_STATUS rv; 353 354 ACPI_FUNCTION_TRACE(__func__); 355 356 if (ops->init) 357 (*ops->init)(dev, arg, &cbarg.context); 358 else 359 cbarg.context = arg; 360 cbarg.ops = ops; 361 cbarg.dev = dev; 362 363 rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback, 364 &cbarg); 365 if (ACPI_FAILURE(rv)) { 366 aprint_error_dev(dev, "ACPI: unable to get %s resources: %s\n", 367 path, AcpiFormatException(rv)); 368 return_ACPI_STATUS(rv); 369 } 370 371 if (ops->fini) 372 (*ops->fini)(dev, cbarg.context); 373 374 return_ACPI_STATUS(AE_OK); 375 } 376 377 /* 378 * acpi_resource_print: 379 * 380 * Print the resources assigned to a device. 381 */ 382 void 383 acpi_resource_print(device_t dev, struct acpi_resources *res) 384 { 385 const char *sep; 386 387 if (SIMPLEQ_EMPTY(&res->ar_io) && 388 SIMPLEQ_EMPTY(&res->ar_iorange) && 389 SIMPLEQ_EMPTY(&res->ar_mem) && 390 SIMPLEQ_EMPTY(&res->ar_memrange) && 391 SIMPLEQ_EMPTY(&res->ar_irq) && 392 SIMPLEQ_EMPTY(&res->ar_drq)) 393 return; 394 395 aprint_normal(":"); 396 397 if (SIMPLEQ_EMPTY(&res->ar_io) == 0) { 398 struct acpi_io *ar; 399 400 sep = ""; 401 aprint_normal(" io "); 402 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 403 aprint_normal("%s0x%x", sep, ar->ar_base); 404 if (ar->ar_length > 1) 405 aprint_normal("-0x%x", ar->ar_base + 406 ar->ar_length - 1); 407 sep = ","; 408 } 409 } 410 411 /* XXX iorange */ 412 413 if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) { 414 struct acpi_mem *ar; 415 416 sep = ""; 417 aprint_normal(" mem "); 418 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 419 aprint_normal("%s0x%x", sep, ar->ar_base); 420 if (ar->ar_length > 1) 421 aprint_normal("-0x%x", ar->ar_base + 422 ar->ar_length - 1); 423 sep = ","; 424 } 425 } 426 427 /* XXX memrange */ 428 429 if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) { 430 struct acpi_irq *ar; 431 432 sep = ""; 433 aprint_normal(" irq "); 434 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 435 aprint_normal("%s%d", sep, ar->ar_irq); 436 sep = ","; 437 } 438 } 439 440 if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) { 441 struct acpi_drq *ar; 442 443 sep = ""; 444 aprint_normal(" drq "); 445 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 446 aprint_normal("%s%d", sep, ar->ar_drq); 447 sep = ","; 448 } 449 } 450 451 aprint_normal("\n"); 452 aprint_naive("\n"); 453 } 454 455 /* 456 * acpi_resource_cleanup: 457 * 458 * Free all allocated buffers 459 */ 460 void 461 acpi_resource_cleanup(struct acpi_resources *res) 462 { 463 while (!SIMPLEQ_EMPTY(&res->ar_io)) { 464 struct acpi_io *ar; 465 ar = SIMPLEQ_FIRST(&res->ar_io); 466 SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list); 467 ACPI_FREE(ar); 468 } 469 470 while (!SIMPLEQ_EMPTY(&res->ar_iorange)) { 471 struct acpi_iorange *ar; 472 ar = SIMPLEQ_FIRST(&res->ar_iorange); 473 SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list); 474 ACPI_FREE(ar); 475 } 476 477 while (!SIMPLEQ_EMPTY(&res->ar_mem)) { 478 struct acpi_mem *ar; 479 ar = SIMPLEQ_FIRST(&res->ar_mem); 480 SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list); 481 ACPI_FREE(ar); 482 } 483 484 while (!SIMPLEQ_EMPTY(&res->ar_memrange)) { 485 struct acpi_memrange *ar; 486 ar = SIMPLEQ_FIRST(&res->ar_memrange); 487 SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list); 488 ACPI_FREE(ar); 489 } 490 491 while (!SIMPLEQ_EMPTY(&res->ar_irq)) { 492 struct acpi_irq *ar; 493 ar = SIMPLEQ_FIRST(&res->ar_irq); 494 SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list); 495 ACPI_FREE(ar); 496 } 497 498 while (!SIMPLEQ_EMPTY(&res->ar_drq)) { 499 struct acpi_drq *ar; 500 ar = SIMPLEQ_FIRST(&res->ar_drq); 501 SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list); 502 ACPI_FREE(ar); 503 } 504 505 res->ar_nio = res->ar_niorange = res->ar_nmem = 506 res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0; 507 } 508 509 struct acpi_io * 510 acpi_res_io(struct acpi_resources *res, int idx) 511 { 512 struct acpi_io *ar; 513 514 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 515 if (ar->ar_index == idx) 516 return ar; 517 } 518 return NULL; 519 } 520 521 struct acpi_iorange * 522 acpi_res_iorange(struct acpi_resources *res, int idx) 523 { 524 struct acpi_iorange *ar; 525 526 SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) { 527 if (ar->ar_index == idx) 528 return ar; 529 } 530 return NULL; 531 } 532 533 struct acpi_mem * 534 acpi_res_mem(struct acpi_resources *res, int idx) 535 { 536 struct acpi_mem *ar; 537 538 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 539 if (ar->ar_index == idx) 540 return ar; 541 } 542 return NULL; 543 } 544 545 struct acpi_memrange * 546 acpi_res_memrange(struct acpi_resources *res, int idx) 547 { 548 struct acpi_memrange *ar; 549 550 SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) { 551 if (ar->ar_index == idx) 552 return ar; 553 } 554 return NULL; 555 } 556 557 struct acpi_irq * 558 acpi_res_irq(struct acpi_resources *res, int idx) 559 { 560 struct acpi_irq *ar; 561 562 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 563 if (ar->ar_index == idx) 564 return ar; 565 } 566 return NULL; 567 } 568 569 struct acpi_drq * 570 acpi_res_drq(struct acpi_resources *res, int idx) 571 { 572 struct acpi_drq *ar; 573 574 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 575 if (ar->ar_index == idx) 576 return ar; 577 } 578 return NULL; 579 } 580 581 /***************************************************************************** 582 * Default ACPI resource parse operations. 583 *****************************************************************************/ 584 585 static void acpi_res_parse_init(device_t, void *, void **); 586 static void acpi_res_parse_fini(device_t, void *); 587 588 static void acpi_res_parse_ioport(device_t, void *, uint32_t, 589 uint32_t); 590 static void acpi_res_parse_iorange(device_t, void *, uint32_t, 591 uint32_t, uint32_t, uint32_t); 592 593 static void acpi_res_parse_memory(device_t, void *, uint32_t, 594 uint32_t); 595 static void acpi_res_parse_memrange(device_t, void *, uint32_t, 596 uint32_t, uint32_t, uint32_t); 597 598 static void acpi_res_parse_irq(device_t, void *, uint32_t, uint32_t); 599 static void acpi_res_parse_drq(device_t, void *, uint32_t); 600 601 static void acpi_res_parse_start_dep(device_t, void *, int); 602 static void acpi_res_parse_end_dep(device_t, void *); 603 604 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = { 605 .init = acpi_res_parse_init, 606 .fini = acpi_res_parse_fini, 607 608 .ioport = acpi_res_parse_ioport, 609 .iorange = acpi_res_parse_iorange, 610 611 .memory = acpi_res_parse_memory, 612 .memrange = acpi_res_parse_memrange, 613 614 .irq = acpi_res_parse_irq, 615 .drq = acpi_res_parse_drq, 616 617 .start_dep = acpi_res_parse_start_dep, 618 .end_dep = acpi_res_parse_end_dep, 619 }; 620 621 const struct acpi_resource_parse_ops acpi_resource_parse_ops_quiet = { 622 .init = acpi_res_parse_init, 623 .fini = NULL, 624 625 .ioport = acpi_res_parse_ioport, 626 .iorange = acpi_res_parse_iorange, 627 628 .memory = acpi_res_parse_memory, 629 .memrange = acpi_res_parse_memrange, 630 631 .irq = acpi_res_parse_irq, 632 .drq = acpi_res_parse_drq, 633 634 .start_dep = acpi_res_parse_start_dep, 635 .end_dep = acpi_res_parse_end_dep, 636 }; 637 638 static void 639 acpi_res_parse_init(device_t dev, void *arg, void **contextp) 640 { 641 struct acpi_resources *res = arg; 642 643 SIMPLEQ_INIT(&res->ar_io); 644 res->ar_nio = 0; 645 646 SIMPLEQ_INIT(&res->ar_iorange); 647 res->ar_niorange = 0; 648 649 SIMPLEQ_INIT(&res->ar_mem); 650 res->ar_nmem = 0; 651 652 SIMPLEQ_INIT(&res->ar_memrange); 653 res->ar_nmemrange = 0; 654 655 SIMPLEQ_INIT(&res->ar_irq); 656 res->ar_nirq = 0; 657 658 SIMPLEQ_INIT(&res->ar_drq); 659 res->ar_ndrq = 0; 660 661 *contextp = res; 662 } 663 664 static void 665 acpi_res_parse_fini(device_t dev, void *context) 666 { 667 struct acpi_resources *res = context; 668 669 /* Print the resources we're using. */ 670 acpi_resource_print(dev, res); 671 } 672 673 static void 674 acpi_res_parse_ioport(device_t dev, void *context, uint32_t base, 675 uint32_t length) 676 { 677 struct acpi_resources *res = context; 678 struct acpi_io *ar; 679 680 /* 681 * Check if there is another I/O port directly below/under 682 * this one. 683 */ 684 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 685 if (ar->ar_base == base + length ) { 686 /* 687 * Entry just below existing entry - adjust 688 * the entry and return. 689 */ 690 ar->ar_base = base; 691 ar->ar_length += length; 692 return; 693 } else if (ar->ar_base + ar->ar_length == base) { 694 /* 695 * Entry just above existing entry - adjust 696 * the entry and return. 697 */ 698 ar->ar_length += length; 699 return; 700 } 701 } 702 703 ar = ACPI_ALLOCATE(sizeof(*ar)); 704 if (ar == NULL) { 705 aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n", 706 res->ar_nio); 707 res->ar_nio++; 708 return; 709 } 710 711 ar->ar_index = res->ar_nio++; 712 ar->ar_base = base; 713 ar->ar_length = length; 714 715 SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list); 716 } 717 718 static void 719 acpi_res_parse_iorange(device_t dev, void *context, uint32_t low, 720 uint32_t high, uint32_t length, uint32_t align) 721 { 722 struct acpi_resources *res = context; 723 struct acpi_iorange *ar; 724 725 ar = ACPI_ALLOCATE(sizeof(*ar)); 726 if (ar == NULL) { 727 aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n", 728 res->ar_niorange); 729 res->ar_niorange++; 730 return; 731 } 732 733 ar->ar_index = res->ar_niorange++; 734 ar->ar_low = low; 735 ar->ar_high = high; 736 ar->ar_length = length; 737 ar->ar_align = align; 738 739 SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list); 740 } 741 742 static void 743 acpi_res_parse_memory(device_t dev, void *context, uint32_t base, 744 uint32_t length) 745 { 746 struct acpi_resources *res = context; 747 struct acpi_mem *ar; 748 749 ar = ACPI_ALLOCATE(sizeof(*ar)); 750 if (ar == NULL) { 751 aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n", 752 res->ar_nmem); 753 res->ar_nmem++; 754 return; 755 } 756 757 ar->ar_index = res->ar_nmem++; 758 ar->ar_base = base; 759 ar->ar_length = length; 760 761 SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list); 762 } 763 764 static void 765 acpi_res_parse_memrange(device_t dev, void *context, uint32_t low, 766 uint32_t high, uint32_t length, uint32_t align) 767 { 768 struct acpi_resources *res = context; 769 struct acpi_memrange *ar; 770 771 ar = ACPI_ALLOCATE(sizeof(*ar)); 772 if (ar == NULL) { 773 aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n", 774 res->ar_nmemrange); 775 res->ar_nmemrange++; 776 return; 777 } 778 779 ar->ar_index = res->ar_nmemrange++; 780 ar->ar_low = low; 781 ar->ar_high = high; 782 ar->ar_length = length; 783 ar->ar_align = align; 784 785 SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list); 786 } 787 788 static void 789 acpi_res_parse_irq(device_t dev, void *context, uint32_t irq, uint32_t type) 790 { 791 struct acpi_resources *res = context; 792 struct acpi_irq *ar; 793 794 ar = ACPI_ALLOCATE(sizeof(*ar)); 795 if (ar == NULL) { 796 aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n", 797 res->ar_nirq); 798 res->ar_nirq++; 799 return; 800 } 801 802 ar->ar_index = res->ar_nirq++; 803 ar->ar_irq = irq; 804 ar->ar_type = type; 805 806 SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list); 807 } 808 809 static void 810 acpi_res_parse_drq(device_t dev, void *context, uint32_t drq) 811 { 812 struct acpi_resources *res = context; 813 struct acpi_drq *ar; 814 815 ar = ACPI_ALLOCATE(sizeof(*ar)); 816 if (ar == NULL) { 817 aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n", 818 res->ar_ndrq); 819 res->ar_ndrq++; 820 return; 821 } 822 823 ar->ar_index = res->ar_ndrq++; 824 ar->ar_drq = drq; 825 826 SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list); 827 } 828 829 static void 830 acpi_res_parse_start_dep(device_t dev, void *context, 831 int preference) 832 { 833 834 aprint_error_dev(dev, "ACPI: dependent functions not supported\n"); 835 } 836 837 static void 838 acpi_res_parse_end_dep(device_t dev, void *context) 839 { 840 841 /* Nothing to do. */ 842 } 843