1 /* $NetBSD: acpi_resource.c,v 1.26 2008/04/07 10:16:59 jmcneill 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.26 2008/04/07 10:16:59 jmcneill 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(__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(struct device *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(struct device *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("%s:", device_xname(dev)); 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 } 442 443 /* 444 * acpi_resource_cleanup: 445 * 446 * Free all allocated buffers 447 */ 448 void 449 acpi_resource_cleanup(struct acpi_resources *res) 450 { 451 while (!SIMPLEQ_EMPTY(&res->ar_io)) { 452 struct acpi_io *ar; 453 ar = SIMPLEQ_FIRST(&res->ar_io); 454 SIMPLEQ_REMOVE_HEAD(&res->ar_io, ar_list); 455 AcpiOsFree(ar); 456 } 457 458 while (!SIMPLEQ_EMPTY(&res->ar_iorange)) { 459 struct acpi_iorange *ar; 460 ar = SIMPLEQ_FIRST(&res->ar_iorange); 461 SIMPLEQ_REMOVE_HEAD(&res->ar_iorange, ar_list); 462 AcpiOsFree(ar); 463 } 464 465 while (!SIMPLEQ_EMPTY(&res->ar_mem)) { 466 struct acpi_mem *ar; 467 ar = SIMPLEQ_FIRST(&res->ar_mem); 468 SIMPLEQ_REMOVE_HEAD(&res->ar_mem, ar_list); 469 AcpiOsFree(ar); 470 } 471 472 while (!SIMPLEQ_EMPTY(&res->ar_memrange)) { 473 struct acpi_memrange *ar; 474 ar = SIMPLEQ_FIRST(&res->ar_memrange); 475 SIMPLEQ_REMOVE_HEAD(&res->ar_memrange, ar_list); 476 AcpiOsFree(ar); 477 } 478 479 while (!SIMPLEQ_EMPTY(&res->ar_irq)) { 480 struct acpi_irq *ar; 481 ar = SIMPLEQ_FIRST(&res->ar_irq); 482 SIMPLEQ_REMOVE_HEAD(&res->ar_irq, ar_list); 483 AcpiOsFree(ar); 484 } 485 486 while (!SIMPLEQ_EMPTY(&res->ar_drq)) { 487 struct acpi_drq *ar; 488 ar = SIMPLEQ_FIRST(&res->ar_drq); 489 SIMPLEQ_REMOVE_HEAD(&res->ar_drq, ar_list); 490 AcpiOsFree(ar); 491 } 492 493 res->ar_nio = res->ar_niorange = res->ar_nmem = 494 res->ar_nmemrange = res->ar_nirq = res->ar_ndrq = 0; 495 } 496 497 struct acpi_io * 498 acpi_res_io(struct acpi_resources *res, int idx) 499 { 500 struct acpi_io *ar; 501 502 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 503 if (ar->ar_index == idx) 504 return ar; 505 } 506 return NULL; 507 } 508 509 struct acpi_iorange * 510 acpi_res_iorange(struct acpi_resources *res, int idx) 511 { 512 struct acpi_iorange *ar; 513 514 SIMPLEQ_FOREACH(ar, &res->ar_iorange, ar_list) { 515 if (ar->ar_index == idx) 516 return ar; 517 } 518 return NULL; 519 } 520 521 struct acpi_mem * 522 acpi_res_mem(struct acpi_resources *res, int idx) 523 { 524 struct acpi_mem *ar; 525 526 SIMPLEQ_FOREACH(ar, &res->ar_mem, ar_list) { 527 if (ar->ar_index == idx) 528 return ar; 529 } 530 return NULL; 531 } 532 533 struct acpi_memrange * 534 acpi_res_memrange(struct acpi_resources *res, int idx) 535 { 536 struct acpi_memrange *ar; 537 538 SIMPLEQ_FOREACH(ar, &res->ar_memrange, ar_list) { 539 if (ar->ar_index == idx) 540 return ar; 541 } 542 return NULL; 543 } 544 545 struct acpi_irq * 546 acpi_res_irq(struct acpi_resources *res, int idx) 547 { 548 struct acpi_irq *ar; 549 550 SIMPLEQ_FOREACH(ar, &res->ar_irq, ar_list) { 551 if (ar->ar_index == idx) 552 return ar; 553 } 554 return NULL; 555 } 556 557 struct acpi_drq * 558 acpi_res_drq(struct acpi_resources *res, int idx) 559 { 560 struct acpi_drq *ar; 561 562 SIMPLEQ_FOREACH(ar, &res->ar_drq, ar_list) { 563 if (ar->ar_index == idx) 564 return ar; 565 } 566 return NULL; 567 } 568 569 /***************************************************************************** 570 * Default ACPI resource parse operations. 571 *****************************************************************************/ 572 573 static void acpi_res_parse_init(struct device *, void *, void **); 574 static void acpi_res_parse_fini(struct device *, void *); 575 576 static void acpi_res_parse_ioport(struct device *, void *, uint32_t, 577 uint32_t); 578 static void acpi_res_parse_iorange(struct device *, void *, uint32_t, 579 uint32_t, uint32_t, uint32_t); 580 581 static void acpi_res_parse_memory(struct device *, void *, uint32_t, 582 uint32_t); 583 static void acpi_res_parse_memrange(struct device *, void *, uint32_t, 584 uint32_t, uint32_t, uint32_t); 585 586 static void acpi_res_parse_irq(struct device *, void *, uint32_t, uint32_t); 587 static void acpi_res_parse_drq(struct device *, void *, uint32_t); 588 589 static void acpi_res_parse_start_dep(struct device *, void *, int); 590 static void acpi_res_parse_end_dep(struct device *, void *); 591 592 const struct acpi_resource_parse_ops acpi_resource_parse_ops_default = { 593 .init = acpi_res_parse_init, 594 .fini = acpi_res_parse_fini, 595 596 .ioport = acpi_res_parse_ioport, 597 .iorange = acpi_res_parse_iorange, 598 599 .memory = acpi_res_parse_memory, 600 .memrange = acpi_res_parse_memrange, 601 602 .irq = acpi_res_parse_irq, 603 .drq = acpi_res_parse_drq, 604 605 .start_dep = acpi_res_parse_start_dep, 606 .end_dep = acpi_res_parse_end_dep, 607 }; 608 609 static void 610 acpi_res_parse_init(struct device *dev, void *arg, void **contextp) 611 { 612 struct acpi_resources *res = arg; 613 614 SIMPLEQ_INIT(&res->ar_io); 615 res->ar_nio = 0; 616 617 SIMPLEQ_INIT(&res->ar_iorange); 618 res->ar_niorange = 0; 619 620 SIMPLEQ_INIT(&res->ar_mem); 621 res->ar_nmem = 0; 622 623 SIMPLEQ_INIT(&res->ar_memrange); 624 res->ar_nmemrange = 0; 625 626 SIMPLEQ_INIT(&res->ar_irq); 627 res->ar_nirq = 0; 628 629 SIMPLEQ_INIT(&res->ar_drq); 630 res->ar_ndrq = 0; 631 632 *contextp = res; 633 } 634 635 static void 636 acpi_res_parse_fini(struct device *dev, void *context) 637 { 638 struct acpi_resources *res = context; 639 640 /* Print the resources we're using. */ 641 acpi_resource_print(dev, res); 642 } 643 644 static void 645 acpi_res_parse_ioport(struct device *dev, void *context, uint32_t base, 646 uint32_t length) 647 { 648 struct acpi_resources *res = context; 649 struct acpi_io *ar; 650 651 /* 652 * Check if there is another I/O port directly below/under 653 * this one. 654 */ 655 SIMPLEQ_FOREACH(ar, &res->ar_io, ar_list) { 656 if (ar->ar_base == base + length ) { 657 /* 658 * Entry just below existing entry - adjust 659 * the entry and return. 660 */ 661 ar->ar_base = base; 662 ar->ar_length += length; 663 return; 664 } else if (ar->ar_base + ar->ar_length == base) { 665 /* 666 * Entry just above existing entry - adjust 667 * the entry and return. 668 */ 669 ar->ar_length += length; 670 return; 671 } 672 } 673 674 ar = AcpiOsAllocate(sizeof(*ar)); 675 if (ar == NULL) { 676 aprint_error_dev(dev, "ACPI: unable to allocate I/O resource %d\n", 677 res->ar_nio); 678 res->ar_nio++; 679 return; 680 } 681 682 ar->ar_index = res->ar_nio++; 683 ar->ar_base = base; 684 ar->ar_length = length; 685 686 SIMPLEQ_INSERT_TAIL(&res->ar_io, ar, ar_list); 687 } 688 689 static void 690 acpi_res_parse_iorange(struct device *dev, void *context, uint32_t low, 691 uint32_t high, uint32_t length, uint32_t align) 692 { 693 struct acpi_resources *res = context; 694 struct acpi_iorange *ar; 695 696 ar = AcpiOsAllocate(sizeof(*ar)); 697 if (ar == NULL) { 698 aprint_error_dev(dev, "ACPI: unable to allocate I/O range resource %d\n", 699 res->ar_niorange); 700 res->ar_niorange++; 701 return; 702 } 703 704 ar->ar_index = res->ar_niorange++; 705 ar->ar_low = low; 706 ar->ar_high = high; 707 ar->ar_length = length; 708 ar->ar_align = align; 709 710 SIMPLEQ_INSERT_TAIL(&res->ar_iorange, ar, ar_list); 711 } 712 713 static void 714 acpi_res_parse_memory(struct device *dev, void *context, uint32_t base, 715 uint32_t length) 716 { 717 struct acpi_resources *res = context; 718 struct acpi_mem *ar; 719 720 ar = AcpiOsAllocate(sizeof(*ar)); 721 if (ar == NULL) { 722 aprint_error_dev(dev, "ACPI: unable to allocate Memory resource %d\n", 723 res->ar_nmem); 724 res->ar_nmem++; 725 return; 726 } 727 728 ar->ar_index = res->ar_nmem++; 729 ar->ar_base = base; 730 ar->ar_length = length; 731 732 SIMPLEQ_INSERT_TAIL(&res->ar_mem, ar, ar_list); 733 } 734 735 static void 736 acpi_res_parse_memrange(struct device *dev, void *context, uint32_t low, 737 uint32_t high, uint32_t length, uint32_t align) 738 { 739 struct acpi_resources *res = context; 740 struct acpi_memrange *ar; 741 742 ar = AcpiOsAllocate(sizeof(*ar)); 743 if (ar == NULL) { 744 aprint_error_dev(dev, "ACPI: unable to allocate Memory range resource %d\n", 745 res->ar_nmemrange); 746 res->ar_nmemrange++; 747 return; 748 } 749 750 ar->ar_index = res->ar_nmemrange++; 751 ar->ar_low = low; 752 ar->ar_high = high; 753 ar->ar_length = length; 754 ar->ar_align = align; 755 756 SIMPLEQ_INSERT_TAIL(&res->ar_memrange, ar, ar_list); 757 } 758 759 static void 760 acpi_res_parse_irq(struct device *dev, void *context, uint32_t irq, uint32_t type) 761 { 762 struct acpi_resources *res = context; 763 struct acpi_irq *ar; 764 765 ar = AcpiOsAllocate(sizeof(*ar)); 766 if (ar == NULL) { 767 aprint_error_dev(dev, "ACPI: unable to allocate IRQ resource %d\n", 768 res->ar_nirq); 769 res->ar_nirq++; 770 return; 771 } 772 773 ar->ar_index = res->ar_nirq++; 774 ar->ar_irq = irq; 775 ar->ar_type = type; 776 777 SIMPLEQ_INSERT_TAIL(&res->ar_irq, ar, ar_list); 778 } 779 780 static void 781 acpi_res_parse_drq(struct device *dev, void *context, uint32_t drq) 782 { 783 struct acpi_resources *res = context; 784 struct acpi_drq *ar; 785 786 ar = AcpiOsAllocate(sizeof(*ar)); 787 if (ar == NULL) { 788 aprint_error_dev(dev, "ACPI: unable to allocate DRQ resource %d\n", 789 res->ar_ndrq); 790 res->ar_ndrq++; 791 return; 792 } 793 794 ar->ar_index = res->ar_ndrq++; 795 ar->ar_drq = drq; 796 797 SIMPLEQ_INSERT_TAIL(&res->ar_drq, ar, ar_list); 798 } 799 800 static void 801 acpi_res_parse_start_dep(struct device *dev, void *context, 802 int preference) 803 { 804 805 aprint_error_dev(dev, "ACPI: dependant functions not supported\n"); 806 } 807 808 static void 809 acpi_res_parse_end_dep(struct device *dev, void *context) 810 { 811 812 /* Nothing to do. */ 813 } 814