1 /* $NetBSD: acpi_util.c,v 1.24 2021/02/05 17:12:43 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2003, 2007, 2021 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum of By Noon Software, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright 2001, 2003 Wasabi Systems, Inc. 34 * All rights reserved. 35 * 36 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed for the NetBSD Project by 49 * Wasabi Systems, Inc. 50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 51 * or promote products derived from this software without specific prior 52 * written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 #include <sys/cdefs.h> 68 __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.24 2021/02/05 17:12:43 thorpej Exp $"); 69 70 #include <sys/param.h> 71 #include <sys/kmem.h> 72 #include <sys/cpu.h> 73 74 #include <dev/acpi/acpireg.h> 75 #include <dev/acpi/acpivar.h> 76 #include <dev/acpi/acpi_intr.h> 77 78 #include <machine/acpi_machdep.h> 79 80 #define _COMPONENT ACPI_BUS_COMPONENT 81 ACPI_MODULE_NAME ("acpi_util") 82 83 static void acpi_clean_node(ACPI_HANDLE, void *); 84 85 static const char * const acpicpu_ids[] = { 86 "ACPI0007", 87 NULL 88 }; 89 90 /* 91 * ACPI device handle support. 92 */ 93 94 static device_call_t 95 acpi_devhandle_lookup_device_call(devhandle_t handle, const char *name, 96 devhandle_t *call_handlep) 97 { 98 __link_set_decl(acpi_device_calls, struct device_call_descriptor); 99 struct device_call_descriptor * const *desc; 100 101 __link_set_foreach(desc, acpi_device_calls) { 102 if (strcmp((*desc)->name, name) == 0) { 103 return (*desc)->call; 104 } 105 } 106 return NULL; 107 } 108 109 static const struct devhandle_impl acpi_devhandle_impl = { 110 .type = DEVHANDLE_TYPE_ACPI, 111 .lookup_device_call = acpi_devhandle_lookup_device_call, 112 }; 113 114 devhandle_t 115 devhandle_from_acpi(ACPI_HANDLE const hdl) 116 { 117 devhandle_t handle = { 118 .impl = &acpi_devhandle_impl, 119 .pointer = hdl, 120 }; 121 122 return handle; 123 } 124 125 ACPI_HANDLE 126 devhandle_to_acpi(devhandle_t const handle) 127 { 128 KASSERT(devhandle_type(handle) == DEVHANDLE_TYPE_ACPI); 129 130 return handle.pointer; 131 } 132 133 static int 134 acpi_device_enumerate_children(device_t dev, devhandle_t call_handle, void *v) 135 { 136 struct device_enumerate_children_args *args = v; 137 ACPI_HANDLE hdl = devhandle_to_acpi(call_handle); 138 struct acpi_devnode *devnode, *ad; 139 140 devnode = acpi_match_node(hdl); 141 KASSERT(devnode != NULL); 142 143 SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { 144 if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || 145 !acpi_device_present(ad->ad_handle)) { 146 continue; 147 } 148 if (!args->callback(dev, devhandle_from_acpi(ad->ad_handle), 149 args->callback_arg)) { 150 break; 151 } 152 } 153 154 return 0; 155 } 156 ACPI_DEVICE_CALL_REGISTER("device-enumerate-children", 157 acpi_device_enumerate_children) 158 159 /* 160 * Evaluate an integer object. 161 */ 162 ACPI_STATUS 163 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) 164 { 165 ACPI_OBJECT obj; 166 ACPI_BUFFER buf; 167 ACPI_STATUS rv; 168 169 if (handle == NULL) 170 handle = ACPI_ROOT_OBJECT; 171 172 (void)memset(&obj, 0, sizeof(obj)); 173 buf.Pointer = &obj; 174 buf.Length = sizeof(obj); 175 176 rv = AcpiEvaluateObject(handle, path, NULL, &buf); 177 178 if (ACPI_FAILURE(rv)) 179 return rv; 180 181 /* Check that evaluation produced a return value. */ 182 if (buf.Length == 0) 183 return AE_NULL_OBJECT; 184 185 if (obj.Type != ACPI_TYPE_INTEGER) 186 return AE_TYPE; 187 188 if (valp != NULL) 189 *valp = obj.Integer.Value; 190 191 return AE_OK; 192 } 193 194 /* 195 * Evaluate an integer object with a single integer input parameter. 196 */ 197 ACPI_STATUS 198 acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) 199 { 200 ACPI_OBJECT_LIST arg; 201 ACPI_OBJECT obj; 202 203 if (handle == NULL) 204 handle = ACPI_ROOT_OBJECT; 205 206 obj.Type = ACPI_TYPE_INTEGER; 207 obj.Integer.Value = val; 208 209 arg.Count = 1; 210 arg.Pointer = &obj; 211 212 return AcpiEvaluateObject(handle, path, &arg, NULL); 213 } 214 215 /* 216 * Evaluate a (Unicode) string object. 217 */ 218 ACPI_STATUS 219 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) 220 { 221 ACPI_OBJECT *obj; 222 ACPI_BUFFER buf; 223 ACPI_STATUS rv; 224 225 rv = acpi_eval_struct(handle, path, &buf); 226 227 if (ACPI_FAILURE(rv)) 228 return rv; 229 230 obj = buf.Pointer; 231 232 if (obj->Type != ACPI_TYPE_STRING) { 233 rv = AE_TYPE; 234 goto out; 235 } 236 237 if (obj->String.Length == 0) { 238 rv = AE_BAD_DATA; 239 goto out; 240 } 241 242 *stringp = ACPI_ALLOCATE(obj->String.Length + 1); 243 244 if (*stringp == NULL) { 245 rv = AE_NO_MEMORY; 246 goto out; 247 } 248 249 (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); 250 251 (*stringp)[obj->String.Length] = '\0'; 252 253 out: 254 ACPI_FREE(buf.Pointer); 255 256 return rv; 257 } 258 259 /* 260 * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). 261 */ 262 ACPI_STATUS 263 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) 264 { 265 266 if (handle == NULL) 267 handle = ACPI_ROOT_OBJECT; 268 269 buf->Pointer = NULL; 270 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 271 272 return AcpiEvaluateObject(handle, path, NULL, buf); 273 } 274 275 /* 276 * Evaluate a reference handle from an element in a package. 277 */ 278 ACPI_STATUS 279 acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) 280 { 281 282 if (elm == NULL || handle == NULL) 283 return AE_BAD_PARAMETER; 284 285 switch (elm->Type) { 286 287 case ACPI_TYPE_ANY: 288 case ACPI_TYPE_LOCAL_REFERENCE: 289 290 if (elm->Reference.Handle == NULL) 291 return AE_NULL_ENTRY; 292 293 *handle = elm->Reference.Handle; 294 295 return AE_OK; 296 297 case ACPI_TYPE_STRING: 298 return AcpiGetHandle(NULL, elm->String.Pointer, handle); 299 300 default: 301 return AE_TYPE; 302 } 303 } 304 305 /* 306 * Iterate over all objects in a package, and pass them all 307 * to a function. If the called function returns non-AE_OK, 308 * the iteration is stopped and that value is returned. 309 */ 310 ACPI_STATUS 311 acpi_foreach_package_object(ACPI_OBJECT *pkg, 312 ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) 313 { 314 ACPI_STATUS rv = AE_OK; 315 uint32_t i; 316 317 if (pkg == NULL) 318 return AE_BAD_PARAMETER; 319 320 if (pkg->Type != ACPI_TYPE_PACKAGE) 321 return AE_TYPE; 322 323 for (i = 0; i < pkg->Package.Count; i++) { 324 325 rv = (*func)(&pkg->Package.Elements[i], arg); 326 327 if (ACPI_FAILURE(rv)) 328 break; 329 } 330 331 return rv; 332 } 333 334 /* 335 * Fetch data info the specified (empty) ACPI buffer. 336 * Caller must free buf.Pointer by ACPI_FREE(). 337 */ 338 ACPI_STATUS 339 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, 340 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) 341 { 342 343 buf->Pointer = NULL; 344 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; 345 346 return (*getit)(handle, buf); 347 } 348 349 /* 350 * Return a complete pathname from a handle. 351 * 352 * Note that the function uses static data storage; 353 * if the data is needed for future use, it should be 354 * copied before any subsequent calls overwrite it. 355 */ 356 const char * 357 acpi_name(ACPI_HANDLE handle) 358 { 359 static char name[80]; 360 ACPI_BUFFER buf; 361 ACPI_STATUS rv; 362 363 if (handle == NULL) 364 handle = ACPI_ROOT_OBJECT; 365 366 buf.Pointer = name; 367 buf.Length = sizeof(name); 368 369 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); 370 371 if (ACPI_FAILURE(rv)) 372 return "UNKNOWN"; 373 374 return name; 375 } 376 377 /* 378 * Pack _HID and _CID ID strings into an OpenFirmware-style 379 * string list. 380 */ 381 char * 382 acpi_pack_compat_list(ACPI_DEVICE_INFO *ad, size_t *sizep) 383 { 384 KASSERT(sizep != NULL); 385 386 char *sl = NULL; 387 size_t slsize = 0; 388 uint32_t i; 389 390 if ((ad->Valid & ACPI_VALID_HID) != 0) { 391 strlist_append(&sl, &slsize, ad->HardwareId.String); 392 } 393 394 if ((ad->Valid & ACPI_VALID_CID) != 0) { 395 for (i = 0; i < ad->CompatibleIdList.Count; i++) { 396 strlist_append(&sl, &slsize, 397 ad->CompatibleIdList.Ids[i].String); 398 } 399 } 400 401 *sizep = slsize; 402 return sl; 403 } 404 405 /* 406 * The ACPI_PNP_DEVICE_ID type is somewhat inconvenient for us to 407 * use. We'll need some temporary space to pack it into an array 408 * of C strings. Room for 8 should be plenty, but we can allocate 409 * more if necessary. 410 */ 411 #define ACPI_COMPATSTR_MAX 8 412 413 static const char ** 414 acpi_compatible_alloc_strarray(ACPI_PNP_DEVICE_ID *ids, 415 unsigned int count, const char **buf) 416 { 417 unsigned int i; 418 419 buf = kmem_tmpbuf_alloc(count * sizeof(const char *), 420 buf, ACPI_COMPATSTR_MAX * sizeof(const char *), KM_SLEEP); 421 for (i = 0; i < count; i++) { 422 buf[i] = ids[i].String; 423 } 424 return buf; 425 } 426 427 static void 428 acpi_compatible_free_strarray(const char **cpp, unsigned int count, 429 const char **buf) 430 { 431 kmem_tmpbuf_free(cpp, count * sizeof(const char *), buf); 432 } 433 434 /* 435 * acpi_compatible_match -- 436 * 437 * Returns a weighted match value, comparing the _HID and _CID 438 * IDs against a driver's compatbility data. 439 */ 440 int 441 acpi_compatible_match(const struct acpi_attach_args * const aa, 442 const struct device_compatible_entry * const dce) 443 { 444 const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)]; 445 const char **cpp; 446 447 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) { 448 return 0; 449 } 450 451 ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo; 452 453 if ((ad->Valid & ACPI_VALID_HID) != 0) { 454 strings[0] = ad->HardwareId.String; 455 456 /* Matching _HID wins big. */ 457 if (device_compatible_pmatch(strings, 1, dce) != 0) { 458 return ACPI_MATCHSCORE_HID; 459 } 460 } 461 462 if ((ad->Valid & ACPI_VALID_CID) != 0) { 463 cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids, 464 ad->CompatibleIdList.Count, strings); 465 int rv; 466 467 rv = device_compatible_pmatch(cpp, 468 ad->CompatibleIdList.Count, dce); 469 acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count, 470 strings); 471 if (rv) { 472 rv = (rv - 1) + ACPI_MATCHSCORE_CID; 473 if (rv > ACPI_MATCHSCORE_CID_MAX) { 474 rv = ACPI_MATCHSCORE_CID_MAX; 475 } 476 return rv; 477 } 478 } 479 480 return 0; 481 } 482 483 /* 484 * acpi_compatible_lookup -- 485 * 486 * Returns the device_compatible_entry that matches the _HID 487 * or _CID ID. 488 */ 489 const struct device_compatible_entry * 490 acpi_compatible_lookup(const struct acpi_attach_args * const aa, 491 const struct device_compatible_entry * const dce) 492 { 493 const struct device_compatible_entry *rv = NULL; 494 const char *strings[ACPI_COMPATSTR_MAX]; 495 const char **cpp; 496 497 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) { 498 return NULL; 499 } 500 501 ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo; 502 503 if ((ad->Valid & ACPI_VALID_HID) != 0) { 504 strings[0] = ad->HardwareId.String; 505 506 rv = device_compatible_plookup(strings, 1, dce); 507 if (rv != NULL) 508 return rv; 509 } 510 511 if ((ad->Valid & ACPI_VALID_CID) != 0) { 512 cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids, 513 ad->CompatibleIdList.Count, strings); 514 515 rv = device_compatible_plookup(cpp, 516 ad->CompatibleIdList.Count, dce); 517 acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count, 518 strings); 519 } 520 521 return rv; 522 } 523 524 /* 525 * Match given IDs against _HID and _CIDs. 526 */ 527 int 528 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) 529 { 530 uint32_t i, n; 531 char *id; 532 533 while (*ids) { 534 535 if ((ad->Valid & ACPI_VALID_HID) != 0) { 536 537 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) 538 return 1; 539 } 540 541 if ((ad->Valid & ACPI_VALID_CID) != 0) { 542 543 n = ad->CompatibleIdList.Count; 544 545 for (i = 0; i < n; i++) { 546 547 id = ad->CompatibleIdList.Ids[i].String; 548 549 if (pmatch(id, *ids, NULL) == 2) 550 return 1; 551 } 552 } 553 554 ids++; 555 } 556 557 return 0; 558 } 559 560 /* 561 * Match a PCI-defined bass-class, sub-class, and programming interface 562 * against a handle's _CLS object. 563 */ 564 int 565 acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass, 566 uint8_t pci_interface) 567 { 568 ACPI_BUFFER buf; 569 ACPI_OBJECT *obj; 570 ACPI_STATUS rv; 571 int match = 0; 572 573 rv = acpi_eval_struct(handle, "_CLS", &buf); 574 if (ACPI_FAILURE(rv)) 575 goto done; 576 577 obj = buf.Pointer; 578 if (obj->Type != ACPI_TYPE_PACKAGE) 579 goto done; 580 if (obj->Package.Count != 3) 581 goto done; 582 if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER || 583 obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER || 584 obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER) 585 goto done; 586 587 match = obj->Package.Elements[0].Integer.Value == pci_class && 588 obj->Package.Elements[1].Integer.Value == pci_subclass && 589 obj->Package.Elements[2].Integer.Value == pci_interface; 590 591 done: 592 if (buf.Pointer) 593 ACPI_FREE(buf.Pointer); 594 return match ? ACPI_MATCHSCORE_CLS : 0; 595 } 596 597 /* 598 * Match a device node from a handle. 599 */ 600 struct acpi_devnode * 601 acpi_match_node(ACPI_HANDLE handle) 602 { 603 struct acpi_devnode *ad; 604 ACPI_STATUS rv; 605 606 if (handle == NULL) 607 return NULL; 608 609 rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); 610 611 if (ACPI_FAILURE(rv)) 612 return NULL; 613 614 return ad; 615 } 616 617 /* 618 * Permanently associate a device node with a handle. 619 */ 620 void 621 acpi_match_node_init(struct acpi_devnode *ad) 622 { 623 (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); 624 } 625 626 static void 627 acpi_clean_node(ACPI_HANDLE handle, void *aux) 628 { 629 /* Nothing. */ 630 } 631 632 /* 633 * Match a handle from a cpu_info. Returns NULL on failure. 634 * 635 * Note that acpi_match_node() can be used if the device node 636 * is also required. 637 */ 638 ACPI_HANDLE 639 acpi_match_cpu_info(struct cpu_info *ci) 640 { 641 struct acpi_softc *sc = acpi_softc; 642 struct acpi_devnode *ad; 643 ACPI_INTEGER val; 644 ACPI_OBJECT *obj; 645 ACPI_BUFFER buf; 646 ACPI_HANDLE hdl; 647 ACPI_STATUS rv; 648 649 if (sc == NULL || acpi_active == 0) 650 return NULL; 651 652 /* 653 * CPUs are declared in the ACPI namespace 654 * either as a Processor() or as a Device(). 655 * In both cases the MADT entries are used 656 * for the match (see ACPI 4.0, section 8.4). 657 */ 658 SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { 659 660 hdl = ad->ad_handle; 661 662 switch (ad->ad_type) { 663 664 case ACPI_TYPE_DEVICE: 665 666 if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0) 667 break; 668 669 rv = acpi_eval_integer(hdl, "_UID", &val); 670 671 if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid) 672 return hdl; 673 674 break; 675 676 case ACPI_TYPE_PROCESSOR: 677 678 rv = acpi_eval_struct(hdl, NULL, &buf); 679 680 if (ACPI_FAILURE(rv)) 681 break; 682 683 obj = buf.Pointer; 684 685 if (obj->Processor.ProcId == ci->ci_acpiid) { 686 ACPI_FREE(buf.Pointer); 687 return hdl; 688 } 689 690 ACPI_FREE(buf.Pointer); 691 break; 692 } 693 } 694 695 return NULL; 696 } 697 698 /* 699 * Match a CPU from a handle. Returns NULL on failure. 700 */ 701 struct cpu_info * 702 acpi_match_cpu_handle(ACPI_HANDLE hdl) 703 { 704 struct cpu_info *ci; 705 ACPI_DEVICE_INFO *di; 706 CPU_INFO_ITERATOR cii; 707 ACPI_INTEGER val; 708 ACPI_OBJECT *obj; 709 ACPI_BUFFER buf; 710 ACPI_STATUS rv; 711 712 ci = NULL; 713 di = NULL; 714 buf.Pointer = NULL; 715 716 rv = AcpiGetObjectInfo(hdl, &di); 717 718 if (ACPI_FAILURE(rv)) 719 return NULL; 720 721 switch (di->Type) { 722 723 case ACPI_TYPE_DEVICE: 724 725 if (acpi_match_hid(di, acpicpu_ids) == 0) 726 goto out; 727 728 rv = acpi_eval_integer(hdl, "_UID", &val); 729 730 if (ACPI_FAILURE(rv)) 731 goto out; 732 733 break; 734 735 case ACPI_TYPE_PROCESSOR: 736 737 rv = acpi_eval_struct(hdl, NULL, &buf); 738 739 if (ACPI_FAILURE(rv)) 740 goto out; 741 742 obj = buf.Pointer; 743 val = obj->Processor.ProcId; 744 break; 745 746 default: 747 goto out; 748 } 749 750 for (CPU_INFO_FOREACH(cii, ci)) { 751 752 if (ci->ci_acpiid == val) 753 goto out; 754 } 755 756 ci = NULL; 757 758 out: 759 if (di != NULL) 760 ACPI_FREE(di); 761 762 if (buf.Pointer != NULL) 763 ACPI_FREE(buf.Pointer); 764 765 return ci; 766 } 767 768 struct acpi_irq_handler { 769 uint32_t aih_irq; 770 void *aih_ih; 771 }; 772 773 void * 774 acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe, 775 int (*intr)(void *), void *iarg, const char *xname) 776 { 777 ACPI_STATUS rv; 778 ACPI_HANDLE hdl = (void *)(uintptr_t)c; 779 struct acpi_resources res; 780 struct acpi_irq *irq; 781 void *aih = NULL; 782 783 rv = acpi_resource_parse(dev, hdl, "_CRS", &res, 784 &acpi_resource_parse_ops_quiet); 785 if (ACPI_FAILURE(rv)) 786 return NULL; 787 788 irq = acpi_res_irq(&res, 0); 789 if (irq == NULL) 790 goto end; 791 792 aih = acpi_intr_establish_irq(dev, irq, ipl, mpsafe, 793 intr, iarg, xname); 794 795 end: 796 acpi_resource_cleanup(&res); 797 798 return aih; 799 } 800 801 void * 802 acpi_intr_establish_irq(device_t dev, struct acpi_irq *irq, int ipl, 803 bool mpsafe, int (*intr)(void *), void *iarg, const char *xname) 804 { 805 struct acpi_irq_handler *aih; 806 void *ih; 807 808 const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL; 809 ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname); 810 if (ih == NULL) 811 return NULL; 812 813 aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP); 814 aih->aih_irq = irq->ar_irq; 815 aih->aih_ih = ih; 816 817 return aih; 818 } 819 820 void 821 acpi_intr_mask(void *c) 822 { 823 struct acpi_irq_handler * const aih = c; 824 825 acpi_md_intr_mask(aih->aih_ih); 826 } 827 828 void 829 acpi_intr_unmask(void *c) 830 { 831 struct acpi_irq_handler * const aih = c; 832 833 acpi_md_intr_unmask(aih->aih_ih); 834 } 835 836 void 837 acpi_intr_disestablish(void *c) 838 { 839 struct acpi_irq_handler *aih = c; 840 841 acpi_md_intr_disestablish(aih->aih_ih); 842 kmem_free(aih, sizeof(struct acpi_irq_handler)); 843 } 844 845 const char * 846 acpi_intr_string(void *c, char *buf, size_t size) 847 { 848 struct acpi_irq_handler *aih = c; 849 intr_handle_t ih = aih->aih_irq; 850 851 return intr_string(ih, buf, size); 852 } 853 854 /* 855 * Device-Specific Data (_DSD) support 856 */ 857 858 static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = { 859 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, 860 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 861 }; 862 863 static ACPI_STATUS 864 acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret) 865 { 866 ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval; 867 ACPI_STATUS rv; 868 int n; 869 870 rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE); 871 if (ACPI_FAILURE(rv)) 872 return rv; 873 874 props = NULL; 875 obj = (ACPI_OBJECT *)pbuf->Pointer; 876 for (n = 0; (n + 1) < obj->Package.Count; n += 2) { 877 uuid = &obj->Package.Elements[n]; 878 if (uuid->Buffer.Length == ACPI_UUID_LENGTH && 879 memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) { 880 props = &obj->Package.Elements[n + 1]; 881 break; 882 } 883 } 884 if (props == NULL) 885 return AE_NOT_FOUND; 886 887 for (n = 0; n < props->Package.Count; n++) { 888 pobj = &props->Package.Elements[n]; 889 if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2) 890 continue; 891 propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0]; 892 propval = (ACPI_OBJECT *)&pobj->Package.Elements[1]; 893 if (propkey->Type != ACPI_TYPE_STRING) 894 continue; 895 if (strcmp(propkey->String.Pointer, prop) != 0) 896 continue; 897 898 if (propval->Type != type) { 899 return AE_TYPE; 900 } else { 901 *ret = propval; 902 return AE_OK; 903 } 904 break; 905 } 906 907 return AE_NOT_FOUND; 908 } 909 910 ACPI_STATUS 911 acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val) 912 { 913 ACPI_OBJECT *propval; 914 ACPI_STATUS rv; 915 ACPI_BUFFER buf; 916 917 buf.Pointer = NULL; 918 buf.Length = ACPI_ALLOCATE_BUFFER; 919 920 rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval); 921 if (ACPI_SUCCESS(rv)) 922 *val = propval->Integer.Value; 923 924 if (buf.Pointer != NULL) 925 ACPI_FREE(buf.Pointer); 926 return rv; 927 } 928 929 ACPI_STATUS 930 acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val) 931 { 932 ACPI_OBJECT *propval; 933 ACPI_STATUS rv; 934 ACPI_BUFFER buf; 935 936 buf.Pointer = NULL; 937 buf.Length = ACPI_ALLOCATE_BUFFER; 938 939 rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval); 940 if (ACPI_SUCCESS(rv)) 941 *val = kmem_strdup(propval->String.Pointer, KM_SLEEP); 942 943 if (buf.Pointer != NULL) 944 ACPI_FREE(buf.Pointer); 945 return rv; 946 } 947 948 /* 949 * Device Specific Method (_DSM) support 950 */ 951 952 ACPI_STATUS 953 acpi_dsm_typed(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 954 ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT_TYPE return_type, 955 ACPI_OBJECT **return_obj) 956 { 957 ACPI_OBJECT_LIST arg; 958 ACPI_OBJECT obj[4]; 959 ACPI_BUFFER buf; 960 ACPI_STATUS status; 961 962 arg.Count = 4; 963 arg.Pointer = obj; 964 965 obj[0].Type = ACPI_TYPE_BUFFER; 966 obj[0].Buffer.Length = ACPI_UUID_LENGTH; 967 obj[0].Buffer.Pointer = uuid; 968 969 obj[1].Type = ACPI_TYPE_INTEGER; 970 obj[1].Integer.Value = rev; 971 972 obj[2].Type = ACPI_TYPE_INTEGER; 973 obj[2].Integer.Value = func; 974 975 if (arg3 != NULL) { 976 obj[3] = *arg3; 977 } else { 978 obj[3].Type = ACPI_TYPE_PACKAGE; 979 obj[3].Package.Count = 0; 980 obj[3].Package.Elements = NULL; 981 } 982 983 buf.Pointer = NULL; 984 buf.Length = ACPI_ALLOCATE_BUFFER; 985 986 if (return_obj == NULL && return_type == ACPI_TYPE_ANY) { 987 status = AcpiEvaluateObject(handle, "_DSM", &arg, NULL); 988 } else { 989 *return_obj = NULL; 990 status = AcpiEvaluateObjectTyped(handle, "_DSM", &arg, &buf, 991 return_type); 992 } 993 if (ACPI_FAILURE(status)) { 994 return status; 995 } 996 if (return_obj != NULL) { 997 *return_obj = buf.Pointer; 998 } else if (buf.Pointer != NULL) { 999 ACPI_FREE(buf.Pointer); 1000 } 1001 return AE_OK; 1002 } 1003 1004 ACPI_STATUS 1005 acpi_dsm_integer(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 1006 ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_INTEGER *ret) 1007 { 1008 ACPI_OBJECT *obj; 1009 ACPI_STATUS status; 1010 1011 status = acpi_dsm_typed(handle, uuid, rev, func, arg3, 1012 ACPI_TYPE_INTEGER, &obj); 1013 if (ACPI_FAILURE(status)) { 1014 return status; 1015 } 1016 1017 *ret = obj->Integer.Value; 1018 ACPI_FREE(obj); 1019 1020 return AE_OK; 1021 } 1022 1023 ACPI_STATUS 1024 acpi_dsm(ACPI_HANDLE handle, uint8_t *uuid, ACPI_INTEGER rev, 1025 ACPI_INTEGER func, const ACPI_OBJECT *arg3, ACPI_OBJECT **return_obj) 1026 { 1027 return acpi_dsm_typed(handle, uuid, rev, func, arg3, ACPI_TYPE_ANY, 1028 return_obj); 1029 } 1030 1031 ACPI_STATUS 1032 acpi_claim_childdevs(device_t dev, struct acpi_devnode *devnode) 1033 { 1034 struct acpi_devnode *ad; 1035 1036 SIMPLEQ_FOREACH(ad, &devnode->ad_child_head, ad_child_list) { 1037 if (ad->ad_device != NULL) 1038 continue; 1039 aprint_debug_dev(dev, "claiming %s\n", 1040 acpi_name(ad->ad_handle)); 1041 ad->ad_device = dev; 1042 acpi_claim_childdevs(dev, ad); 1043 } 1044 1045 return AE_OK; 1046 } 1047