1 /* $NetBSD: acpi_resource.c,v 1.19 2006/01/29 03:12:22 kochi 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.19 2006/01/29 03:12:22 kochi 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 struct device *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(__FUNCTION__); 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->ioport) 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 241 case ACPI_RESOURCE_TYPE_ADDRESS32: 242 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 243 "Address32 unimplemented\n")); 244 break; 245 246 case ACPI_RESOURCE_TYPE_ADDRESS16: 247 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 248 "Address16 unimplemented\n")); 249 break; 250 251 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 252 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 253 "Extended address64 unimplemented\n")); 254 break; 255 256 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 257 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 258 "ExtendedIrq unimplemented\n")); 259 break; 260 261 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 262 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 263 "ExtendedIrq unimplemented\n")); 264 break; 265 266 case ACPI_RESOURCE_TYPE_VENDOR: 267 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 268 "VendorSpecific unimplemented\n")); 269 break; 270 271 default: 272 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 273 "Unknown resource type: %d\n", res->Type)); 274 break; 275 } 276 277 return_ACPI_STATUS(AE_OK); 278 } 279 280 281 /* 282 * acpi_resource_parse: 283 * 284 * Parse a device node's resources and fill them in for the 285 * client. 286 * 287 * This API supports _CRS (current resources) and 288 * _PRS (possible resources). 289 * 290 * Note that it might be nice to also locate ACPI-specific resource 291 * items, such as GPE bits. 292 */ 293 ACPI_STATUS 294 acpi_resource_parse(struct device *dev, ACPI_HANDLE handle, const char *path, 295 void *arg, const struct acpi_resource_parse_ops *ops) 296 { 297 struct resource_parse_callback_arg cbarg; 298 ACPI_STATUS rv; 299 300 ACPI_FUNCTION_TRACE(__FUNCTION__); 301 302 if (ops->init) 303 (*ops->init)(dev, arg, &cbarg.context); 304 else 305 cbarg.context = arg; 306 cbarg.ops = ops; 307 cbarg.dev = dev; 308 309 rv = AcpiWalkResources(handle, path, acpi_resource_parse_callback, 310 &cbarg); 311 if (ACPI_FAILURE(rv)) { 312 printf("%s: ACPI: unable to get %s resources: %s\n", 313 dev->dv_xname, path, AcpiFormatException(rv)); 314 return_ACPI_STATUS(rv); 315 } 316 317 if (ops->fini) 318 (*ops->fini)(dev, cbarg.context); 319 320 return_ACPI_STATUS(AE_OK); 321 } 322 323 /* 324 * acpi_resource_print: 325 * 326 * Print the resources assigned to a device. 327 */ 328 void 329 acpi_resource_print(struct device *dev, struct acpi_resources *res) 330 { 331 const char *sep; 332 333 if (SIMPLEQ_EMPTY(&res->ar_io) && 334 SIMPLEQ_EMPTY(&res->ar_iorange) && 335 SIMPLEQ_EMPTY(&res->ar_mem) && 336 SIMPLEQ_EMPTY(&res->ar_memrange) && 337 SIMPLEQ_EMPTY(&res->ar_irq) && 338 SIMPLEQ_EMPTY(&res->ar_drq)) 339 return; 340 341 printf("%s:", dev->dv_xname); 342 343 if (SIMPLEQ_EMPTY(&res->ar_io) == 0) { 344 struct acpi_io *ar; 345 346 sep = ""; 347 printf(" io "); 348 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 349 printf("%s0x%x", sep, ar->ar_base); 350 if (ar->ar_length > 1) 351 printf("-0x%x", ar->ar_base + 352 ar->ar_length - 1); 353 sep = ","; 354 } 355 } 356 357 /* XXX iorange */ 358 359 if (SIMPLEQ_EMPTY(&res->ar_mem) == 0) { 360 struct acpi_mem *ar; 361 362 sep = ""; 363 printf(" mem "); 364 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 365 printf("%s0x%x", sep, ar->ar_base); 366 if (ar->ar_length > 1) 367 printf("-0x%x", ar->ar_base + 368 ar->ar_length - 1); 369 sep = ","; 370 } 371 } 372 373 /* XXX memrange */ 374 375 if (SIMPLEQ_EMPTY(&res->ar_irq) == 0) { 376 struct acpi_irq *ar; 377 378 sep = ""; 379 printf(" irq "); 380 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 381 printf("%s%d", sep, ar->ar_irq); 382 sep = ","; 383 } 384 } 385 386 if (SIMPLEQ_EMPTY(&res->ar_drq) == 0) { 387 struct acpi_drq *ar; 388 389 sep = ""; 390 printf(" drq "); 391 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 392 printf("%s%d", sep, ar->ar_drq); 393 sep = ","; 394 } 395 } 396 397 printf("\n"); 398 } 399 400 /* 401 * acpi_resource_cleanup: 402 * 403 * Free all allocated buffers 404 */ 405 void 406 acpi_resource_cleanup(struct acpi_resources *res) 407 { 408 while (!SIMPLEQ_EMPTY(&res->ar_io)) { 409 struct acpi_io *ar; 410 ar = SIMPLEQ_FIRST(&res->ar_io); 411 SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list); 412 AcpiOsFree(ar); 413 } 414 415 while (!SIMPLEQ_EMPTY(&res->ar_iorange)) { 416 struct acpi_iorange *ar; 417 ar = SIMPLEQ_FIRST(&res->ar_iorange); 418 SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list); 419 AcpiOsFree(ar); 420 } 421 422 while (!SIMPLEQ_EMPTY(&res->ar_mem)) { 423 struct acpi_mem *ar; 424 ar = SIMPLEQ_FIRST(&res->ar_mem); 425 SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list); 426 AcpiOsFree(ar); 427 } 428 429 while (!SIMPLEQ_EMPTY(&res->ar_memrange)) { 430 struct acpi_memrange *ar; 431 ar = SIMPLEQ_FIRST(&res->ar_memrange); 432 SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list); 433 AcpiOsFree(ar); 434 } 435 436 while (!SIMPLEQ_EMPTY(&res->ar_irq)) { 437 struct acpi_irq *ar; 438 ar = SIMPLEQ_FIRST(&res->ar_irq); 439 SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list); 440 AcpiOsFree(ar); 441 } 442 443 while (!SIMPLEQ_EMPTY(&res->ar_drq)) { 444 struct acpi_drq *ar; 445 ar = SIMPLEQ_FIRST(&res->ar_drq); 446 SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list); 447 AcpiOsFree(ar); 448 } 449 450 res->ar_nio = res->ar_niorange = res->ar_nmem = 451 res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0; 452 } 453 454 struct acpi_io * 455 acpi_res_io(struct acpi_resources *res, int idx) 456 { 457 struct acpi_io *ar; 458 459 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 460 if (ar->ar_index == idx) 461 return ar; 462 } 463 return NULL; 464 } 465 466 struct acpi_iorange * 467 acpi_res_iorange(struct acpi_resources *res, int idx) 468 { 469 struct acpi_iorange *ar; 470 471 SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) { 472 if (ar->ar_index == idx) 473 return ar; 474 } 475 return NULL; 476 } 477 478 struct acpi_mem * 479 acpi_res_mem(struct acpi_resources *res, int idx) 480 { 481 struct acpi_mem *ar; 482 483 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 484 if (ar->ar_index == idx) 485 return ar; 486 } 487 return NULL; 488 } 489 490 struct acpi_memrange * 491 acpi_res_memrange(struct acpi_resources *res, int idx) 492 { 493 struct acpi_memrange *ar; 494 495 SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) { 496 if (ar->ar_index == idx) 497 return ar; 498 } 499 return NULL; 500 } 501 502 struct acpi_irq * 503 acpi_res_irq(struct acpi_resources *res, int idx) 504 { 505 struct acpi_irq *ar; 506 507 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 508 if (ar->ar_index == idx) 509 return ar; 510 } 511 return NULL; 512 } 513 514 struct acpi_drq * 515 acpi_res_drq(struct acpi_resources *res, int idx) 516 { 517 struct acpi_drq *ar; 518 519 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 520 if (ar->ar_index == idx) 521 return ar; 522 } 523 return NULL; 524 } 525 526 /***************************************************************************** 527 * Default ACPI resource parse operations. 528 *****************************************************************************/ 529 530 static void acpi_res_parse_init(struct device *, void *, void **); 531 static void acpi_res_parse_fini(struct device *, void *); 532 533 static void acpi_res_parse_ioport(struct device *, void *, uint32_t, 534 uint32_t); 535 static void acpi_res_parse_iorange(struct device *, void *, uint32_t, 536 uint32_t, uint32_t, uint32_t); 537 538 static void acpi_res_parse_memory(struct device *, void *, uint32_t, 539 uint32_t); 540 static void acpi_res_parse_memrange(struct device *, void *, uint32_t, 541 uint32_t, uint32_t, uint32_t); 542 543 static void acpi_res_parse_irq(struct device *, void *, uint32_t, uint32_t); 544 static void acpi_res_parse_drq(struct device *, void *, uint32_t); 545 546 static void acpi_res_parse_start_dep(struct device *, void *, int); 547 static void acpi_res_parse_end_dep(struct device *, void *); 548 549 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = { 550 .init = acpi_res_parse_init, 551 .fini = acpi_res_parse_fini, 552 553 .ioport = acpi_res_parse_ioport, 554 .iorange = acpi_res_parse_iorange, 555 556 .memory = acpi_res_parse_memory, 557 .memrange = acpi_res_parse_memrange, 558 559 .irq = acpi_res_parse_irq, 560 .drq = acpi_res_parse_drq, 561 562 .start_dep = acpi_res_parse_start_dep, 563 .end_dep = acpi_res_parse_end_dep, 564 }; 565 566 static void 567 acpi_res_parse_init(struct device *dev, void *arg, void **contextp) 568 { 569 struct acpi_resources *res = arg; 570 571 SIMPLEQ_INIT(&res->ar_io); 572 res->ar_nio = 0; 573 574 SIMPLEQ_INIT(&res->ar_iorange); 575 res->ar_niorange = 0; 576 577 SIMPLEQ_INIT(&res->ar_mem); 578 res->ar_nmem = 0; 579 580 SIMPLEQ_INIT(&res->ar_memrange); 581 res->ar_nmemrange = 0; 582 583 SIMPLEQ_INIT(&res->ar_irq); 584 res->ar_nirq = 0; 585 586 SIMPLEQ_INIT(&res->ar_drq); 587 res->ar_ndrq = 0; 588 589 *contextp = res; 590 } 591 592 static void 593 acpi_res_parse_fini(struct device *dev, void *context) 594 { 595 struct acpi_resources *res = context; 596 597 /* Print the resources we're using. */ 598 acpi_resource_print(dev, res); 599 } 600 601 static void 602 acpi_res_parse_ioport(struct device *dev, void *context, uint32_t base, 603 uint32_t length) 604 { 605 struct acpi_resources *res = context; 606 struct acpi_io *ar; 607 608 /* 609 * Check if there is another I/O port directly below/under 610 * this one. 611 */ 612 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 613 if (ar->ar_base == base + length ) { 614 /* 615 * Entry just below existing entry - adjust 616 * the entry and return. 617 */ 618 ar->ar_base = base; 619 ar->ar_length += length; 620 return; 621 } else if (ar->ar_base + ar->ar_length == base) { 622 /* 623 * Entry just above existing entry - adjust 624 * the entry and return. 625 */ 626 ar->ar_length += length; 627 return; 628 } 629 } 630 631 ar = AcpiOsAllocate(sizeof(*ar)); 632 if (ar == NULL) { 633 printf("%s: ACPI: unable to allocate I/O resource %d\n", 634 dev->dv_xname, res->ar_nio); 635 res->ar_nio++; 636 return; 637 } 638 639 ar->ar_index = res->ar_nio++; 640 ar->ar_base = base; 641 ar->ar_length = length; 642 643 SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list); 644 } 645 646 static void 647 acpi_res_parse_iorange(struct device *dev, void *context, uint32_t low, 648 uint32_t high, uint32_t length, uint32_t align) 649 { 650 struct acpi_resources *res = context; 651 struct acpi_iorange *ar; 652 653 ar = AcpiOsAllocate(sizeof(*ar)); 654 if (ar == NULL) { 655 printf("%s: ACPI: unable to allocate I/O range resource %d\n", 656 dev->dv_xname, res->ar_niorange); 657 res->ar_niorange++; 658 return; 659 } 660 661 ar->ar_index = res->ar_niorange++; 662 ar->ar_low = low; 663 ar->ar_high = high; 664 ar->ar_length = length; 665 ar->ar_align = align; 666 667 SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list); 668 } 669 670 static void 671 acpi_res_parse_memory(struct device *dev, void *context, uint32_t base, 672 uint32_t length) 673 { 674 struct acpi_resources *res = context; 675 struct acpi_mem *ar; 676 677 ar = AcpiOsAllocate(sizeof(*ar)); 678 if (ar == NULL) { 679 printf("%s: ACPI: unable to allocate Memory resource %d\n", 680 dev->dv_xname, res->ar_nmem); 681 res->ar_nmem++; 682 return; 683 } 684 685 ar->ar_index = res->ar_nmem++; 686 ar->ar_base = base; 687 ar->ar_length = length; 688 689 SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list); 690 } 691 692 static void 693 acpi_res_parse_memrange(struct device *dev, void *context, uint32_t low, 694 uint32_t high, uint32_t length, uint32_t align) 695 { 696 struct acpi_resources *res = context; 697 struct acpi_memrange *ar; 698 699 ar = AcpiOsAllocate(sizeof(*ar)); 700 if (ar == NULL) { 701 printf("%s: ACPI: unable to allocate Memory range resource " 702 "%d\n", dev->dv_xname, res->ar_nmemrange); 703 res->ar_nmemrange++; 704 return; 705 } 706 707 ar->ar_index = res->ar_nmemrange++; 708 ar->ar_low = low; 709 ar->ar_high = high; 710 ar->ar_length = length; 711 ar->ar_align = align; 712 713 SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list); 714 } 715 716 static void 717 acpi_res_parse_irq(struct device *dev, void *context, uint32_t irq, uint32_t type) 718 { 719 struct acpi_resources *res = context; 720 struct acpi_irq *ar; 721 722 ar = AcpiOsAllocate(sizeof(*ar)); 723 if (ar == NULL) { 724 printf("%s: ACPI: unable to allocate IRQ resource %d\n", 725 dev->dv_xname, res->ar_nirq); 726 res->ar_nirq++; 727 return; 728 } 729 730 ar->ar_index = res->ar_nirq++; 731 ar->ar_irq = irq; 732 ar->ar_type = type; 733 734 SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list); 735 } 736 737 static void 738 acpi_res_parse_drq(struct device *dev, void *context, uint32_t drq) 739 { 740 struct acpi_resources *res = context; 741 struct acpi_drq *ar; 742 743 ar = AcpiOsAllocate(sizeof(*ar)); 744 if (ar == NULL) { 745 printf("%s: ACPI: unable to allocate DRQ resource %d\n", 746 dev->dv_xname, res->ar_ndrq); 747 res->ar_ndrq++; 748 return; 749 } 750 751 ar->ar_index = res->ar_ndrq++; 752 ar->ar_drq = drq; 753 754 SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list); 755 } 756 757 static void 758 acpi_res_parse_start_dep(struct device *dev, void *context, int preference) 759 { 760 761 printf("%s: ACPI: dependant functions not supported\n", 762 dev->dv_xname); 763 } 764 765 static void 766 acpi_res_parse_end_dep(struct device *dev, void *context) 767 { 768 769 /* Nothing to do. */ 770 } 771