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