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