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