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