1 /* $OpenBSD: dsdt.c,v 1.267 2024/05/13 01:15:50 jsg Exp $ */ 2 /* 3 * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/kernel.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 #include <sys/time.h> 24 25 #include <machine/bus.h> 26 27 #ifdef DDB 28 #include <machine/db_machdep.h> 29 #endif 30 31 #include <dev/acpi/acpireg.h> 32 #include <dev/acpi/acpivar.h> 33 #include <dev/acpi/amltypes.h> 34 #include <dev/acpi/dsdt.h> 35 36 #include <dev/i2c/i2cvar.h> 37 38 #ifdef SMALL_KERNEL 39 #undef ACPI_DEBUG 40 #endif 41 42 #define opsize(opcode) (((opcode) & 0xFF00) ? 2 : 1) 43 44 #define AML_FIELD_RESERVED 0x00 45 #define AML_FIELD_ATTRIB 0x01 46 47 #define AML_REVISION 0x01 48 #define AML_INTSTRLEN 16 49 #define AML_NAMESEG_LEN 4 50 51 struct aml_value *aml_loadtable(struct acpi_softc *, const char *, 52 const char *, const char *, const char *, 53 const char *, struct aml_value *); 54 struct aml_scope *aml_load(struct acpi_softc *, struct aml_scope *, 55 struct aml_value *, struct aml_value *); 56 57 void aml_copyvalue(struct aml_value *, struct aml_value *); 58 59 void aml_setvalue(struct aml_scope *, struct aml_value *, 60 struct aml_value *, int64_t); 61 void aml_freevalue(struct aml_value *); 62 struct aml_value *aml_allocvalue(int, int64_t, const void *); 63 struct aml_value *_aml_setvalue(struct aml_value *, int, int64_t, 64 const void *); 65 66 uint64_t aml_convradix(uint64_t, int, int); 67 uint64_t aml_evalexpr(uint64_t, uint64_t, int); 68 int aml_lsb(uint64_t); 69 int aml_msb(uint64_t); 70 71 int aml_tstbit(const uint8_t *, int); 72 void aml_setbit(uint8_t *, int, int); 73 74 void aml_addref(struct aml_value *, const char *); 75 void aml_delref(struct aml_value **, const char *); 76 77 void aml_bufcpy(void *, int, const void *, int, int); 78 79 int aml_pc(uint8_t *); 80 81 int aml_evalterm(struct aml_scope *scope, 82 struct aml_value *raw, struct aml_value *dst); 83 84 struct aml_opcode *aml_findopcode(int); 85 86 #define acpi_os_malloc(sz) _acpi_os_malloc(sz, __FUNCTION__, __LINE__) 87 #define acpi_os_free(ptr) _acpi_os_free(ptr, __FUNCTION__, __LINE__) 88 89 void *_acpi_os_malloc(size_t, const char *, int); 90 void _acpi_os_free(void *, const char *, int); 91 void acpi_stall(int); 92 93 struct aml_value *aml_callosi(struct aml_scope *, struct aml_value *); 94 95 const char *aml_getname(const char *); 96 int64_t aml_hextoint(const char *); 97 void aml_dump(int, uint8_t *); 98 __dead void _aml_die(const char *fn, int line, const char *fmt, ...); 99 #define aml_die(x...) _aml_die(__FUNCTION__, __LINE__, x) 100 101 void aml_notify_task(void *, int); 102 void acpi_poll_notify_task(void *, int); 103 104 /* 105 * @@@: Global variables 106 */ 107 int aml_intlen = 64; 108 struct aml_node aml_root; 109 struct aml_value *aml_global_lock; 110 111 /* Perfect Hash key */ 112 #define HASH_OFF 6904 113 #define HASH_SIZE 179 114 #define HASH_KEY(k) (((k) ^ HASH_OFF) % HASH_SIZE) 115 116 /* 117 * XXX this array should be sorted, and then aml_findopcode() should 118 * do a binary search 119 */ 120 struct aml_opcode **aml_ophash; 121 struct aml_opcode aml_table[] = { 122 /* Simple types */ 123 { AMLOP_ZERO, "Zero", "c", }, 124 { AMLOP_ONE, "One", "c", }, 125 { AMLOP_ONES, "Ones", "c", }, 126 { AMLOP_REVISION, "Revision", "R", }, 127 { AMLOP_BYTEPREFIX, ".Byte", "b", }, 128 { AMLOP_WORDPREFIX, ".Word", "w", }, 129 { AMLOP_DWORDPREFIX, ".DWord", "d", }, 130 { AMLOP_QWORDPREFIX, ".QWord", "q", }, 131 { AMLOP_STRINGPREFIX, ".String", "a", }, 132 { AMLOP_DEBUG, "DebugOp", "D", }, 133 { AMLOP_BUFFER, "Buffer", "piB", }, 134 { AMLOP_PACKAGE, "Package", "pbT", }, 135 { AMLOP_VARPACKAGE, "VarPackage", "piT", }, 136 137 /* Simple objects */ 138 { AMLOP_LOCAL0, "Local0", "L", }, 139 { AMLOP_LOCAL1, "Local1", "L", }, 140 { AMLOP_LOCAL2, "Local2", "L", }, 141 { AMLOP_LOCAL3, "Local3", "L", }, 142 { AMLOP_LOCAL4, "Local4", "L", }, 143 { AMLOP_LOCAL5, "Local5", "L", }, 144 { AMLOP_LOCAL6, "Local6", "L", }, 145 { AMLOP_LOCAL7, "Local7", "L", }, 146 { AMLOP_ARG0, "Arg0", "A", }, 147 { AMLOP_ARG1, "Arg1", "A", }, 148 { AMLOP_ARG2, "Arg2", "A", }, 149 { AMLOP_ARG3, "Arg3", "A", }, 150 { AMLOP_ARG4, "Arg4", "A", }, 151 { AMLOP_ARG5, "Arg5", "A", }, 152 { AMLOP_ARG6, "Arg6", "A", }, 153 154 /* Control flow */ 155 { AMLOP_IF, "If", "piI", }, 156 { AMLOP_ELSE, "Else", "pT" }, 157 { AMLOP_WHILE, "While", "piT", }, 158 { AMLOP_BREAK, "Break", "" }, 159 { AMLOP_CONTINUE, "Continue", "" }, 160 { AMLOP_RETURN, "Return", "t", }, 161 { AMLOP_FATAL, "Fatal", "bdi", }, 162 { AMLOP_NOP, "Nop", "", }, 163 { AMLOP_BREAKPOINT, "BreakPoint", "", }, 164 165 /* Arithmetic operations */ 166 { AMLOP_INCREMENT, "Increment", "S", }, 167 { AMLOP_DECREMENT, "Decrement", "S", }, 168 { AMLOP_ADD, "Add", "iir", }, 169 { AMLOP_SUBTRACT, "Subtract", "iir", }, 170 { AMLOP_MULTIPLY, "Multiply", "iir", }, 171 { AMLOP_DIVIDE, "Divide", "iirr", }, 172 { AMLOP_SHL, "ShiftLeft", "iir", }, 173 { AMLOP_SHR, "ShiftRight", "iir", }, 174 { AMLOP_AND, "And", "iir", }, 175 { AMLOP_NAND, "Nand", "iir", }, 176 { AMLOP_OR, "Or", "iir", }, 177 { AMLOP_NOR, "Nor", "iir", }, 178 { AMLOP_XOR, "Xor", "iir", }, 179 { AMLOP_NOT, "Not", "ir", }, 180 { AMLOP_MOD, "Mod", "iir", }, 181 { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "ir", }, 182 { AMLOP_FINDSETRIGHTBIT,"FindSetRightBit", "ir",}, 183 184 /* Logical test operations */ 185 { AMLOP_LAND, "LAnd", "ii", }, 186 { AMLOP_LOR, "LOr", "ii", }, 187 { AMLOP_LNOT, "LNot", "i", }, 188 { AMLOP_LNOTEQUAL, "LNotEqual", "tt", }, 189 { AMLOP_LLESSEQUAL, "LLessEqual", "tt", }, 190 { AMLOP_LGREATEREQUAL, "LGreaterEqual", "tt", }, 191 { AMLOP_LEQUAL, "LEqual", "tt", }, 192 { AMLOP_LGREATER, "LGreater", "tt", }, 193 { AMLOP_LLESS, "LLess", "tt", }, 194 195 /* Named objects */ 196 { AMLOP_NAMECHAR, ".NameRef", "n", }, 197 { AMLOP_ALIAS, "Alias", "nN", }, 198 { AMLOP_NAME, "Name", "Nt", }, 199 { AMLOP_EVENT, "Event", "N", }, 200 { AMLOP_MUTEX, "Mutex", "Nb", }, 201 { AMLOP_DATAREGION, "DataRegion", "Nttt", }, 202 { AMLOP_OPREGION, "OpRegion", "Nbii", }, 203 { AMLOP_SCOPE, "Scope", "pnT", }, 204 { AMLOP_DEVICE, "Device", "pNT", }, 205 { AMLOP_POWERRSRC, "Power Resource", "pNbwT",}, 206 { AMLOP_THERMALZONE, "ThermalZone", "pNT", }, 207 { AMLOP_PROCESSOR, "Processor", "pNbdbT", }, 208 { AMLOP_METHOD, "Method", "pNbM", }, 209 210 /* Field operations */ 211 { AMLOP_FIELD, "Field", "pnbF", }, 212 { AMLOP_INDEXFIELD, "IndexField", "pnnbF",}, 213 { AMLOP_BANKFIELD, "BankField", "pnnibF",}, 214 { AMLOP_CREATEFIELD, "CreateField", "tiiN", }, 215 { AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN",}, 216 { AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN",}, 217 { AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN",}, 218 { AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN",}, 219 { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", }, 220 221 /* Conversion operations */ 222 { AMLOP_TOINTEGER, "ToInteger", "tr", }, 223 { AMLOP_TOBUFFER, "ToBuffer", "tr", }, 224 { AMLOP_TODECSTRING, "ToDecString", "tr", }, 225 { AMLOP_TOHEXSTRING, "ToHexString", "tr", }, 226 { AMLOP_TOSTRING, "ToString", "tir", }, 227 { AMLOP_MID, "Mid", "tiir", }, 228 { AMLOP_FROMBCD, "FromBCD", "ir", }, 229 { AMLOP_TOBCD, "ToBCD", "ir", }, 230 231 /* Mutex/Signal operations */ 232 { AMLOP_ACQUIRE, "Acquire", "Sw", }, 233 { AMLOP_RELEASE, "Release", "S", }, 234 { AMLOP_SIGNAL, "Signal", "S", }, 235 { AMLOP_WAIT, "Wait", "Si", }, 236 { AMLOP_RESET, "Reset", "S", }, 237 238 { AMLOP_INDEX, "Index", "tir", }, 239 { AMLOP_DEREFOF, "DerefOf", "t", }, 240 { AMLOP_REFOF, "RefOf", "S", }, 241 { AMLOP_CONDREFOF, "CondRef", "Sr", }, 242 243 { AMLOP_LOADTABLE, "LoadTable", "tttttt" }, 244 { AMLOP_STALL, "Stall", "i", }, 245 { AMLOP_SLEEP, "Sleep", "i", }, 246 { AMLOP_TIMER, "Timer", "", }, 247 { AMLOP_LOAD, "Load", "nS", }, 248 { AMLOP_UNLOAD, "Unload", "t" }, 249 { AMLOP_STORE, "Store", "tS", }, 250 { AMLOP_CONCAT, "Concat", "ttr", }, 251 { AMLOP_CONCATRES, "ConcatRes", "ttt" }, 252 { AMLOP_NOTIFY, "Notify", "Si", }, 253 { AMLOP_SIZEOF, "Sizeof", "S", }, 254 { AMLOP_MATCH, "Match", "tbibii", }, 255 { AMLOP_OBJECTTYPE, "ObjectType", "S", }, 256 { AMLOP_COPYOBJECT, "CopyObject", "tS", }, 257 }; 258 259 int aml_pc(uint8_t *src) 260 { 261 return src - aml_root.start; 262 } 263 264 struct aml_scope *aml_lastscope; 265 266 void 267 _aml_die(const char *fn, int line, const char *fmt, ...) 268 { 269 #ifndef SMALL_KERNEL 270 struct aml_scope *root; 271 struct aml_value *sp; 272 int idx; 273 #endif /* SMALL_KERNEL */ 274 va_list ap; 275 276 va_start(ap, fmt); 277 vprintf(fmt, ap); 278 printf("\n"); 279 va_end(ap); 280 281 #ifndef SMALL_KERNEL 282 for (root = aml_lastscope; root && root->pos; root = root->parent) { 283 printf("%.4x Called: %s\n", aml_pc(root->pos), 284 aml_nodename(root->node)); 285 for (idx = 0; idx < AML_MAX_ARG; idx++) { 286 sp = aml_getstack(root, AMLOP_ARG0+idx); 287 if (sp && sp->type) { 288 printf(" arg%d: ", idx); 289 aml_showvalue(sp); 290 } 291 } 292 for (idx = 0; idx < AML_MAX_LOCAL; idx++) { 293 sp = aml_getstack(root, AMLOP_LOCAL0+idx); 294 if (sp && sp->type) { 295 printf(" local%d: ", idx); 296 aml_showvalue(sp); 297 } 298 } 299 } 300 #endif /* SMALL_KERNEL */ 301 302 /* XXX: don't panic */ 303 panic("aml_die %s:%d", fn, line); 304 } 305 306 void 307 aml_hashopcodes(void) 308 { 309 int i; 310 311 /* Dynamically allocate hash table */ 312 aml_ophash = (struct aml_opcode **)acpi_os_malloc(HASH_SIZE * 313 sizeof(struct aml_opcode *)); 314 for (i = 0; i < sizeof(aml_table) / sizeof(aml_table[0]); i++) 315 aml_ophash[HASH_KEY(aml_table[i].opcode)] = &aml_table[i]; 316 } 317 318 struct aml_opcode * 319 aml_findopcode(int opcode) 320 { 321 struct aml_opcode *hop; 322 323 hop = aml_ophash[HASH_KEY(opcode)]; 324 if (hop && hop->opcode == opcode) 325 return hop; 326 return NULL; 327 } 328 329 #if defined(DDB) || !defined(SMALL_KERNEL) 330 const char * 331 aml_mnem(int opcode, uint8_t *pos) 332 { 333 struct aml_opcode *tab; 334 static char mnemstr[32]; 335 336 if ((tab = aml_findopcode(opcode)) != NULL) { 337 strlcpy(mnemstr, tab->mnem, sizeof(mnemstr)); 338 if (pos != NULL) { 339 switch (opcode) { 340 case AMLOP_STRINGPREFIX: 341 snprintf(mnemstr, sizeof(mnemstr), "\"%s\"", pos); 342 break; 343 case AMLOP_BYTEPREFIX: 344 snprintf(mnemstr, sizeof(mnemstr), "0x%.2x", 345 *(uint8_t *)pos); 346 break; 347 case AMLOP_WORDPREFIX: 348 snprintf(mnemstr, sizeof(mnemstr), "0x%.4x", 349 *(uint16_t *)pos); 350 break; 351 case AMLOP_DWORDPREFIX: 352 snprintf(mnemstr, sizeof(mnemstr), "0x%.4x", 353 *(uint16_t *)pos); 354 break; 355 case AMLOP_NAMECHAR: 356 strlcpy(mnemstr, aml_getname(pos), sizeof(mnemstr)); 357 break; 358 } 359 } 360 return mnemstr; 361 } 362 return ("xxx"); 363 } 364 #endif /* defined(DDB) || !defined(SMALL_KERNEL) */ 365 366 struct aml_notify_data { 367 struct aml_node *node; 368 char pnpid[20]; 369 void *cbarg; 370 int (*cbproc)(struct aml_node *, int, void *); 371 int poll; 372 373 SLIST_ENTRY(aml_notify_data) link; 374 }; 375 376 SLIST_HEAD(aml_notify_head, aml_notify_data); 377 struct aml_notify_head aml_notify_list = 378 SLIST_HEAD_INITIALIZER(aml_notify_list); 379 380 /* 381 * @@@: Memory management functions 382 */ 383 384 long acpi_nalloc; 385 386 struct acpi_memblock { 387 size_t size; 388 #ifdef ACPI_MEMDEBUG 389 const char *fn; 390 int line; 391 int sig; 392 LIST_ENTRY(acpi_memblock) link; 393 #endif 394 }; 395 396 #ifdef ACPI_MEMDEBUG 397 LIST_HEAD(, acpi_memblock) acpi_memhead; 398 int acpi_memsig; 399 400 int 401 acpi_walkmem(int sig, const char *lbl) 402 { 403 struct acpi_memblock *sptr; 404 405 printf("--- walkmem:%s %x --- %lx bytes alloced\n", lbl, sig, 406 acpi_nalloc); 407 LIST_FOREACH(sptr, &acpi_memhead, link) { 408 if (sptr->sig < sig) 409 break; 410 printf("%.4x Alloc %.8lx bytes @ %s:%d\n", 411 sptr->sig, sptr->size, sptr->fn, sptr->line); 412 } 413 return acpi_memsig; 414 } 415 #endif /* ACPI_MEMDEBUG */ 416 417 void * 418 _acpi_os_malloc(size_t size, const char *fn, int line) 419 { 420 struct acpi_memblock *sptr; 421 422 sptr = malloc(size+sizeof(*sptr), M_ACPI, M_WAITOK | M_ZERO); 423 dnprintf(99, "alloc: %p %s:%d\n", sptr, fn, line); 424 acpi_nalloc += size; 425 sptr->size = size; 426 #ifdef ACPI_MEMDEBUG 427 sptr->line = line; 428 sptr->fn = fn; 429 sptr->sig = ++acpi_memsig; 430 431 LIST_INSERT_HEAD(&acpi_memhead, sptr, link); 432 #endif 433 434 return &sptr[1]; 435 } 436 437 void 438 _acpi_os_free(void *ptr, const char *fn, int line) 439 { 440 struct acpi_memblock *sptr; 441 442 if (ptr != NULL) { 443 sptr = &(((struct acpi_memblock *)ptr)[-1]); 444 acpi_nalloc -= sptr->size; 445 446 #ifdef ACPI_MEMDEBUG 447 LIST_REMOVE(sptr, link); 448 #endif 449 450 dnprintf(99, "free: %p %s:%d\n", sptr, fn, line); 451 free(sptr, M_ACPI, sizeof(*sptr) + sptr->size); 452 } 453 } 454 455 void 456 acpi_sleep(int ms, char *reason) 457 { 458 static int acpinowait; 459 460 /* XXX ACPI integers are supposed to be unsigned. */ 461 ms = MAX(1, ms); 462 463 if (cold) 464 delay(ms * 1000); 465 else 466 tsleep_nsec(&acpinowait, PWAIT, reason, MSEC_TO_NSEC(ms)); 467 } 468 469 void 470 acpi_stall(int us) 471 { 472 delay(us); 473 } 474 475 /* 476 * @@@: Misc utility functions 477 */ 478 479 #ifdef ACPI_DEBUG 480 void 481 aml_dump(int len, uint8_t *buf) 482 { 483 int idx; 484 485 dnprintf(50, "{ "); 486 for (idx = 0; idx < len; idx++) { 487 dnprintf(50, "%s0x%.2x", idx ? ", " : "", buf[idx]); 488 } 489 dnprintf(50, " }\n"); 490 } 491 #endif 492 493 /* Bit mangling code */ 494 int 495 aml_tstbit(const uint8_t *pb, int bit) 496 { 497 pb += aml_bytepos(bit); 498 499 return (*pb & aml_bitmask(bit)); 500 } 501 502 void 503 aml_setbit(uint8_t *pb, int bit, int val) 504 { 505 pb += aml_bytepos(bit); 506 507 if (val) 508 *pb |= aml_bitmask(bit); 509 else 510 *pb &= ~aml_bitmask(bit); 511 } 512 513 /* 514 * @@@: Notify functions 515 */ 516 void 517 acpi_poll(void *arg) 518 { 519 int s; 520 521 s = splbio(); 522 acpi_addtask(acpi_softc, acpi_poll_notify_task, NULL, 0); 523 acpi_softc->sc_threadwaiting = 0; 524 wakeup(acpi_softc); 525 splx(s); 526 527 timeout_add_sec(&acpi_softc->sc_dev_timeout, 10); 528 } 529 530 void 531 aml_notify_task(void *node, int notify_value) 532 { 533 struct aml_notify_data *pdata = NULL; 534 535 dnprintf(10,"run notify: %s %x\n", aml_nodename(node), notify_value); 536 SLIST_FOREACH(pdata, &aml_notify_list, link) 537 if (pdata->node == node) 538 pdata->cbproc(pdata->node, notify_value, pdata->cbarg); 539 } 540 541 void 542 aml_register_notify(struct aml_node *node, const char *pnpid, 543 int (*proc)(struct aml_node *, int, void *), void *arg, int poll) 544 { 545 struct aml_notify_data *pdata; 546 extern int acpi_poll_enabled; 547 548 dnprintf(10, "aml_register_notify: %s %s %p\n", 549 node->name, pnpid ? pnpid : "", proc); 550 551 pdata = acpi_os_malloc(sizeof(struct aml_notify_data)); 552 pdata->node = node; 553 pdata->cbarg = arg; 554 pdata->cbproc = proc; 555 pdata->poll = poll; 556 557 if (pnpid) 558 strlcpy(pdata->pnpid, pnpid, sizeof(pdata->pnpid)); 559 560 SLIST_INSERT_HEAD(&aml_notify_list, pdata, link); 561 562 if (poll && !acpi_poll_enabled) 563 timeout_add_sec(&acpi_softc->sc_dev_timeout, 10); 564 } 565 566 void 567 aml_notify(struct aml_node *node, int notify_value) 568 { 569 if (node == NULL) 570 return; 571 572 dnprintf(10,"queue notify: %s %x\n", aml_nodename(node), notify_value); 573 acpi_addtask(acpi_softc, aml_notify_task, node, notify_value); 574 } 575 576 void 577 aml_notify_dev(const char *pnpid, int notify_value) 578 { 579 struct aml_notify_data *pdata = NULL; 580 581 if (pnpid == NULL) 582 return; 583 584 SLIST_FOREACH(pdata, &aml_notify_list, link) 585 if (strcmp(pdata->pnpid, pnpid) == 0) 586 pdata->cbproc(pdata->node, notify_value, pdata->cbarg); 587 } 588 589 void 590 acpi_poll_notify_task(void *arg0, int arg1) 591 { 592 struct aml_notify_data *pdata = NULL; 593 594 SLIST_FOREACH(pdata, &aml_notify_list, link) 595 if (pdata->cbproc && pdata->poll) 596 pdata->cbproc(pdata->node, 0, pdata->cbarg); 597 } 598 599 /* 600 * @@@: Namespace functions 601 */ 602 603 struct aml_node *__aml_search(struct aml_node *, uint8_t *, int); 604 struct aml_node *__aml_searchname(struct aml_node *, const void *, int); 605 void aml_delchildren(struct aml_node *); 606 607 608 /* Search for a name in children nodes */ 609 struct aml_node * 610 __aml_search(struct aml_node *root, uint8_t *nameseg, int create) 611 { 612 struct aml_node *node; 613 614 /* XXX: Replace with SLIST/SIMPLEQ routines */ 615 if (root == NULL) 616 return NULL; 617 SIMPLEQ_FOREACH(node, &root->son, sib) { 618 if (!strncmp(node->name, nameseg, AML_NAMESEG_LEN)) 619 return node; 620 } 621 if (create) { 622 node = acpi_os_malloc(sizeof(struct aml_node)); 623 memcpy((void *)node->name, nameseg, AML_NAMESEG_LEN); 624 node->value = aml_allocvalue(0,0,NULL); 625 node->value->node = node; 626 node->parent = root; 627 628 SIMPLEQ_INIT(&node->son); 629 SIMPLEQ_INSERT_TAIL(&root->son, node, sib); 630 return node; 631 } 632 return NULL; 633 } 634 635 /* Get absolute pathname of AML node */ 636 const char * 637 aml_nodename(struct aml_node *node) 638 { 639 static char namebuf[128]; 640 641 namebuf[0] = 0; 642 if (node) { 643 aml_nodename(node->parent); 644 if (node->parent != &aml_root) 645 strlcat(namebuf, ".", sizeof(namebuf)); 646 strlcat(namebuf, node->name, sizeof(namebuf)); 647 return namebuf+1; 648 } 649 return namebuf; 650 } 651 652 const char * 653 aml_getname(const char *name) 654 { 655 static char namebuf[128], *p; 656 int count; 657 658 p = namebuf; 659 while (*name == AMLOP_ROOTCHAR || *name == AMLOP_PARENTPREFIX) 660 *(p++) = *(name++); 661 switch (*name) { 662 case 0x00: 663 count = 0; 664 break; 665 case AMLOP_MULTINAMEPREFIX: 666 count = name[1]; 667 name += 2; 668 break; 669 case AMLOP_DUALNAMEPREFIX: 670 count = 2; 671 name += 1; 672 break; 673 default: 674 count = 1; 675 } 676 while (count--) { 677 memcpy(p, name, 4); 678 p[4] = '.'; 679 p += 5; 680 name += 4; 681 if (*name == '.') name++; 682 } 683 *(--p) = 0; 684 return namebuf; 685 } 686 687 /* Free all children nodes/values */ 688 void 689 aml_delchildren(struct aml_node *node) 690 { 691 struct aml_node *onode; 692 693 if (node == NULL) 694 return; 695 while ((onode = SIMPLEQ_FIRST(&node->son)) != NULL) { 696 SIMPLEQ_REMOVE_HEAD(&node->son, sib); 697 698 aml_delchildren(onode); 699 700 /* Don't delete values that have references */ 701 if (onode->value && onode->value->refcnt > 1) 702 onode->value->node = NULL; 703 704 /* Decrease reference count */ 705 aml_delref(&onode->value, ""); 706 707 /* Delete node */ 708 acpi_os_free(onode); 709 } 710 } 711 712 /* 713 * @@@: Value functions 714 */ 715 716 /* 717 * Field I/O code 718 */ 719 void aml_unlockfield(struct aml_scope *, struct aml_value *); 720 void aml_lockfield(struct aml_scope *, struct aml_value *); 721 722 static long global_lock_count = 0; 723 724 void 725 acpi_glk_enter(void) 726 { 727 int st = 0; 728 729 /* If lock is already ours, just continue. */ 730 if (global_lock_count++) 731 return; 732 733 /* Spin to acquire the lock. */ 734 while (!st) { 735 st = acpi_acquire_glk(&acpi_softc->sc_facs->global_lock); 736 /* XXX - yield/delay? */ 737 } 738 } 739 740 void 741 acpi_glk_leave(void) 742 { 743 int st, x; 744 745 /* If we are the last one, turn out the lights. */ 746 if (--global_lock_count) 747 return; 748 749 st = acpi_release_glk(&acpi_softc->sc_facs->global_lock); 750 if (!st) 751 return; 752 753 /* 754 * If pending, notify the BIOS that the lock was released by 755 * OSPM. No locking is needed because nobody outside the ACPI 756 * thread is supposed to touch this register. 757 */ 758 x = acpi_read_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0); 759 x |= ACPI_PM1_GBL_RLS; 760 acpi_write_pmreg(acpi_softc, ACPIREG_PM1_CNT, 0, x); 761 } 762 763 void 764 aml_lockfield(struct aml_scope *scope, struct aml_value *field) 765 { 766 if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) 767 return; 768 769 acpi_glk_enter(); 770 } 771 772 void 773 aml_unlockfield(struct aml_scope *scope, struct aml_value *field) 774 { 775 if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON) 776 return; 777 778 acpi_glk_leave(); 779 } 780 781 /* 782 * @@@: Value set/compare/alloc/free routines 783 */ 784 785 #ifndef SMALL_KERNEL 786 void 787 aml_showvalue(struct aml_value *val) 788 { 789 int idx; 790 791 if (val == NULL) 792 return; 793 794 if (val->node) 795 printf(" [%s]", aml_nodename(val->node)); 796 printf(" %p cnt:%.2x stk:%.2x", val, val->refcnt, val->stack); 797 switch (val->type) { 798 case AML_OBJTYPE_INTEGER: 799 printf(" integer: %llx\n", val->v_integer); 800 break; 801 case AML_OBJTYPE_STRING: 802 printf(" string: %s\n", val->v_string); 803 break; 804 case AML_OBJTYPE_METHOD: 805 printf(" method: %.2x\n", val->v_method.flags); 806 break; 807 case AML_OBJTYPE_PACKAGE: 808 printf(" package: %.2x\n", val->length); 809 for (idx = 0; idx < val->length; idx++) 810 aml_showvalue(val->v_package[idx]); 811 break; 812 case AML_OBJTYPE_BUFFER: 813 printf(" buffer: %.2x {", val->length); 814 for (idx = 0; idx < val->length; idx++) 815 printf("%s%.2x", idx ? ", " : "", val->v_buffer[idx]); 816 printf("}\n"); 817 break; 818 case AML_OBJTYPE_FIELDUNIT: 819 case AML_OBJTYPE_BUFFERFIELD: 820 printf(" field: bitpos=%.4x bitlen=%.4x ref1:%p ref2:%p [%s]\n", 821 val->v_field.bitpos, val->v_field.bitlen, 822 val->v_field.ref1, val->v_field.ref2, 823 aml_mnem(val->v_field.type, NULL)); 824 if (val->v_field.ref1) 825 printf(" ref1: %s\n", aml_nodename(val->v_field.ref1->node)); 826 if (val->v_field.ref2) 827 printf(" ref2: %s\n", aml_nodename(val->v_field.ref2->node)); 828 break; 829 case AML_OBJTYPE_MUTEX: 830 printf(" mutex: %s ref: %d\n", 831 val->v_mutex ? val->v_mutex->amt_name : "", 832 val->v_mutex ? val->v_mutex->amt_ref_count : 0); 833 break; 834 case AML_OBJTYPE_EVENT: 835 printf(" event:\n"); 836 break; 837 case AML_OBJTYPE_OPREGION: 838 printf(" opregion: %.2x,%.8llx,%x\n", 839 val->v_opregion.iospace, val->v_opregion.iobase, 840 val->v_opregion.iolen); 841 break; 842 case AML_OBJTYPE_NAMEREF: 843 printf(" nameref: %s\n", aml_getname(val->v_nameref)); 844 break; 845 case AML_OBJTYPE_DEVICE: 846 printf(" device:\n"); 847 break; 848 case AML_OBJTYPE_PROCESSOR: 849 printf(" cpu: %.2x,%.4x,%.2x\n", 850 val->v_processor.proc_id, val->v_processor.proc_addr, 851 val->v_processor.proc_len); 852 break; 853 case AML_OBJTYPE_THERMZONE: 854 printf(" thermzone:\n"); 855 break; 856 case AML_OBJTYPE_POWERRSRC: 857 printf(" pwrrsrc: %.2x,%.2x\n", 858 val->v_powerrsrc.pwr_level, val->v_powerrsrc.pwr_order); 859 break; 860 case AML_OBJTYPE_OBJREF: 861 printf(" objref: %p index:%x opcode:%s\n", val->v_objref.ref, 862 val->v_objref.index, aml_mnem(val->v_objref.type, 0)); 863 aml_showvalue(val->v_objref.ref); 864 break; 865 default: 866 printf(" !!type: %x\n", val->type); 867 } 868 } 869 #endif /* SMALL_KERNEL */ 870 871 int64_t 872 aml_val2int(struct aml_value *rval) 873 { 874 int64_t ival = 0; 875 876 if (rval == NULL) { 877 dnprintf(50, "null val2int\n"); 878 return (0); 879 } 880 switch (rval->type) { 881 case AML_OBJTYPE_INTEGER: 882 ival = rval->v_integer; 883 break; 884 case AML_OBJTYPE_BUFFER: 885 aml_bufcpy(&ival, 0, rval->v_buffer, 0, 886 min(aml_intlen, rval->length*8)); 887 break; 888 case AML_OBJTYPE_STRING: 889 ival = aml_hextoint(rval->v_string); 890 break; 891 } 892 return (ival); 893 } 894 895 /* Sets value into LHS: lhs must already be cleared */ 896 struct aml_value * 897 _aml_setvalue(struct aml_value *lhs, int type, int64_t ival, const void *bval) 898 { 899 memset(&lhs->_, 0x0, sizeof(lhs->_)); 900 901 lhs->type = type; 902 switch (lhs->type) { 903 case AML_OBJTYPE_INTEGER: 904 lhs->length = aml_intlen>>3; 905 lhs->v_integer = ival; 906 break; 907 case AML_OBJTYPE_METHOD: 908 lhs->v_method.flags = ival; 909 lhs->v_method.fneval = bval; 910 break; 911 case AML_OBJTYPE_NAMEREF: 912 lhs->v_nameref = (uint8_t *)bval; 913 break; 914 case AML_OBJTYPE_OBJREF: 915 lhs->v_objref.type = ival; 916 lhs->v_objref.ref = (struct aml_value *)bval; 917 break; 918 case AML_OBJTYPE_BUFFER: 919 lhs->length = ival; 920 lhs->v_buffer = (uint8_t *)acpi_os_malloc(ival); 921 if (bval) 922 memcpy(lhs->v_buffer, bval, ival); 923 break; 924 case AML_OBJTYPE_STRING: 925 if (ival == -1) 926 ival = strlen((const char *)bval); 927 lhs->length = ival; 928 lhs->v_string = (char *)acpi_os_malloc(ival+1); 929 if (bval) 930 strncpy(lhs->v_string, (const char *)bval, ival); 931 break; 932 case AML_OBJTYPE_PACKAGE: 933 lhs->length = ival; 934 lhs->v_package = (struct aml_value **)acpi_os_malloc(ival * 935 sizeof(struct aml_value *)); 936 for (ival = 0; ival < lhs->length; ival++) 937 lhs->v_package[ival] = aml_allocvalue( 938 AML_OBJTYPE_UNINITIALIZED, 0, NULL); 939 break; 940 } 941 return lhs; 942 } 943 944 /* Copy object to another value: lhs must already be cleared */ 945 void 946 aml_copyvalue(struct aml_value *lhs, struct aml_value *rhs) 947 { 948 int idx; 949 950 lhs->type = rhs->type; 951 switch (lhs->type) { 952 case AML_OBJTYPE_UNINITIALIZED: 953 break; 954 case AML_OBJTYPE_INTEGER: 955 lhs->length = aml_intlen>>3; 956 lhs->v_integer = rhs->v_integer; 957 break; 958 case AML_OBJTYPE_MUTEX: 959 lhs->v_mutex = rhs->v_mutex; 960 break; 961 case AML_OBJTYPE_POWERRSRC: 962 lhs->node = rhs->node; 963 lhs->v_powerrsrc = rhs->v_powerrsrc; 964 break; 965 case AML_OBJTYPE_METHOD: 966 lhs->v_method = rhs->v_method; 967 break; 968 case AML_OBJTYPE_BUFFER: 969 _aml_setvalue(lhs, rhs->type, rhs->length, rhs->v_buffer); 970 break; 971 case AML_OBJTYPE_STRING: 972 _aml_setvalue(lhs, rhs->type, rhs->length, rhs->v_string); 973 break; 974 case AML_OBJTYPE_OPREGION: 975 lhs->v_opregion = rhs->v_opregion; 976 break; 977 case AML_OBJTYPE_PROCESSOR: 978 lhs->node = rhs->node; 979 lhs->v_processor = rhs->v_processor; 980 break; 981 case AML_OBJTYPE_NAMEREF: 982 lhs->v_nameref = rhs->v_nameref; 983 break; 984 case AML_OBJTYPE_PACKAGE: 985 _aml_setvalue(lhs, rhs->type, rhs->length, NULL); 986 for (idx = 0; idx < rhs->length; idx++) 987 aml_copyvalue(lhs->v_package[idx], rhs->v_package[idx]); 988 break; 989 case AML_OBJTYPE_OBJREF: 990 lhs->v_objref = rhs->v_objref; 991 aml_addref(lhs->v_objref.ref, ""); 992 break; 993 case AML_OBJTYPE_DEVICE: 994 case AML_OBJTYPE_THERMZONE: 995 lhs->node = rhs->node; 996 break; 997 default: 998 printf("copyvalue: %x", rhs->type); 999 break; 1000 } 1001 } 1002 1003 /* Allocate dynamic AML value 1004 * type : Type of object to allocate (AML_OBJTYPE_XXXX) 1005 * ival : Integer value (action depends on type) 1006 * bval : Buffer value (action depends on type) 1007 */ 1008 struct aml_value * 1009 aml_allocvalue(int type, int64_t ival, const void *bval) 1010 { 1011 struct aml_value *rv; 1012 1013 rv = (struct aml_value *)acpi_os_malloc(sizeof(struct aml_value)); 1014 if (rv != NULL) { 1015 aml_addref(rv, ""); 1016 return _aml_setvalue(rv, type, ival, bval); 1017 } 1018 return NULL; 1019 } 1020 1021 void 1022 aml_freevalue(struct aml_value *val) 1023 { 1024 int idx; 1025 1026 if (val == NULL) 1027 return; 1028 switch (val->type) { 1029 case AML_OBJTYPE_STRING: 1030 acpi_os_free(val->v_string); 1031 break; 1032 case AML_OBJTYPE_BUFFER: 1033 acpi_os_free(val->v_buffer); 1034 break; 1035 case AML_OBJTYPE_PACKAGE: 1036 for (idx = 0; idx < val->length; idx++) 1037 aml_delref(&val->v_package[idx], ""); 1038 acpi_os_free(val->v_package); 1039 break; 1040 case AML_OBJTYPE_OBJREF: 1041 aml_delref(&val->v_objref.ref, ""); 1042 break; 1043 case AML_OBJTYPE_BUFFERFIELD: 1044 case AML_OBJTYPE_FIELDUNIT: 1045 aml_delref(&val->v_field.ref1, ""); 1046 aml_delref(&val->v_field.ref2, ""); 1047 break; 1048 } 1049 val->type = 0; 1050 memset(&val->_, 0, sizeof(val->_)); 1051 } 1052 1053 /* 1054 * @@@: Math eval routines 1055 */ 1056 1057 /* Convert number from one radix to another 1058 * Used in BCD conversion routines */ 1059 uint64_t 1060 aml_convradix(uint64_t val, int iradix, int oradix) 1061 { 1062 uint64_t rv = 0, pwr; 1063 1064 rv = 0; 1065 pwr = 1; 1066 while (val) { 1067 rv += (val % iradix) * pwr; 1068 val /= iradix; 1069 pwr *= oradix; 1070 } 1071 return rv; 1072 } 1073 1074 /* Calculate LSB */ 1075 int 1076 aml_lsb(uint64_t val) 1077 { 1078 int lsb; 1079 1080 if (val == 0) 1081 return (0); 1082 1083 for (lsb = 1; !(val & 0x1); lsb++) 1084 val >>= 1; 1085 1086 return (lsb); 1087 } 1088 1089 /* Calculate MSB */ 1090 int 1091 aml_msb(uint64_t val) 1092 { 1093 int msb; 1094 1095 if (val == 0) 1096 return (0); 1097 1098 for (msb = 1; val != 0x1; msb++) 1099 val >>= 1; 1100 1101 return (msb); 1102 } 1103 1104 /* Evaluate Math operands */ 1105 uint64_t 1106 aml_evalexpr(uint64_t lhs, uint64_t rhs, int opcode) 1107 { 1108 uint64_t res = 0; 1109 1110 switch (opcode) { 1111 /* Math operations */ 1112 case AMLOP_INCREMENT: 1113 case AMLOP_ADD: 1114 res = (lhs + rhs); 1115 break; 1116 case AMLOP_DECREMENT: 1117 case AMLOP_SUBTRACT: 1118 res = (lhs - rhs); 1119 break; 1120 case AMLOP_MULTIPLY: 1121 res = (lhs * rhs); 1122 break; 1123 case AMLOP_DIVIDE: 1124 res = (lhs / rhs); 1125 break; 1126 case AMLOP_MOD: 1127 res = (lhs % rhs); 1128 break; 1129 case AMLOP_SHL: 1130 res = (lhs << rhs); 1131 break; 1132 case AMLOP_SHR: 1133 res = (lhs >> rhs); 1134 break; 1135 case AMLOP_AND: 1136 res = (lhs & rhs); 1137 break; 1138 case AMLOP_NAND: 1139 res = ~(lhs & rhs); 1140 break; 1141 case AMLOP_OR: 1142 res = (lhs | rhs); 1143 break; 1144 case AMLOP_NOR: 1145 res = ~(lhs | rhs); 1146 break; 1147 case AMLOP_XOR: 1148 res = (lhs ^ rhs); 1149 break; 1150 case AMLOP_NOT: 1151 res = ~(lhs); 1152 break; 1153 1154 /* Conversion/misc */ 1155 case AMLOP_FINDSETLEFTBIT: 1156 res = aml_msb(lhs); 1157 break; 1158 case AMLOP_FINDSETRIGHTBIT: 1159 res = aml_lsb(lhs); 1160 break; 1161 case AMLOP_TOINTEGER: 1162 res = (lhs); 1163 break; 1164 case AMLOP_FROMBCD: 1165 res = aml_convradix(lhs, 16, 10); 1166 break; 1167 case AMLOP_TOBCD: 1168 res = aml_convradix(lhs, 10, 16); 1169 break; 1170 1171 /* Logical/Comparison */ 1172 case AMLOP_LAND: 1173 res = -(lhs && rhs); 1174 break; 1175 case AMLOP_LOR: 1176 res = -(lhs || rhs); 1177 break; 1178 case AMLOP_LNOT: 1179 res = -(!lhs); 1180 break; 1181 case AMLOP_LNOTEQUAL: 1182 res = -(lhs != rhs); 1183 break; 1184 case AMLOP_LLESSEQUAL: 1185 res = -(lhs <= rhs); 1186 break; 1187 case AMLOP_LGREATEREQUAL: 1188 res = -(lhs >= rhs); 1189 break; 1190 case AMLOP_LEQUAL: 1191 res = -(lhs == rhs); 1192 break; 1193 case AMLOP_LGREATER: 1194 res = -(lhs > rhs); 1195 break; 1196 case AMLOP_LLESS: 1197 res = -(lhs < rhs); 1198 break; 1199 } 1200 1201 dnprintf(15,"aml_evalexpr: %s %llx %llx = %llx\n", 1202 aml_mnem(opcode, NULL), lhs, rhs, res); 1203 1204 return res; 1205 } 1206 1207 /* 1208 * aml_bufcpy copies/shifts buffer data, special case for aligned transfers 1209 * dstPos/srcPos are bit positions within destination/source buffers 1210 */ 1211 void 1212 aml_bufcpy(void *pvDst, int dstPos, const void *pvSrc, int srcPos, int len) 1213 { 1214 const uint8_t *pSrc = pvSrc; 1215 uint8_t *pDst = pvDst; 1216 int idx; 1217 1218 if (aml_bytealigned(dstPos|srcPos|len)) { 1219 /* Aligned transfer: use memcpy */ 1220 memcpy(pDst+aml_bytepos(dstPos), pSrc+aml_bytepos(srcPos), 1221 aml_bytelen(len)); 1222 return; 1223 } 1224 1225 /* Misaligned transfer: perform bitwise copy (slow) */ 1226 for (idx = 0; idx < len; idx++) 1227 aml_setbit(pDst, idx + dstPos, aml_tstbit(pSrc, idx + srcPos)); 1228 } 1229 1230 /* 1231 * @@@: External API 1232 * 1233 * evaluate an AML node 1234 * Returns a copy of the value in res (must be freed by user) 1235 */ 1236 1237 void 1238 aml_walknodes(struct aml_node *node, int mode, 1239 int (*nodecb)(struct aml_node *, void *), void *arg) 1240 { 1241 struct aml_node *child; 1242 1243 if (node == NULL) 1244 return; 1245 if (mode == AML_WALK_PRE) 1246 if (nodecb(node, arg)) 1247 return; 1248 SIMPLEQ_FOREACH(child, &node->son, sib) 1249 aml_walknodes(child, mode, nodecb, arg); 1250 if (mode == AML_WALK_POST) 1251 nodecb(node, arg); 1252 } 1253 1254 void 1255 aml_find_node(struct aml_node *node, const char *name, 1256 int (*cbproc)(struct aml_node *, void *arg), void *arg) 1257 { 1258 struct aml_node *child; 1259 const char *nn; 1260 1261 /* match child of this node first before recursing */ 1262 SIMPLEQ_FOREACH(child, &node->son, sib) { 1263 nn = child->name; 1264 if (nn != NULL) { 1265 if (*nn == AMLOP_ROOTCHAR) nn++; 1266 while (*nn == AMLOP_PARENTPREFIX) nn++; 1267 if (strcmp(name, nn) == 0) { 1268 /* Only recurse if cbproc() wants us to */ 1269 if (cbproc(child, arg) != 0) 1270 return; 1271 } 1272 } 1273 } 1274 1275 SIMPLEQ_FOREACH(child, &node->son, sib) 1276 aml_find_node(child, name, cbproc, arg); 1277 } 1278 1279 /* 1280 * @@@: Parser functions 1281 */ 1282 uint8_t *aml_parsename(struct aml_node *, uint8_t *, struct aml_value **, int); 1283 uint8_t *aml_parseend(struct aml_scope *scope); 1284 int aml_parselength(struct aml_scope *); 1285 int aml_parseopcode(struct aml_scope *); 1286 1287 /* Get AML Opcode */ 1288 int 1289 aml_parseopcode(struct aml_scope *scope) 1290 { 1291 int opcode = (scope->pos[0]); 1292 int twocode = (scope->pos[0]<<8) + scope->pos[1]; 1293 1294 /* Check if this is an embedded name */ 1295 switch (opcode) { 1296 case AMLOP_ROOTCHAR: 1297 case AMLOP_PARENTPREFIX: 1298 case AMLOP_MULTINAMEPREFIX: 1299 case AMLOP_DUALNAMEPREFIX: 1300 case AMLOP_NAMECHAR: 1301 return AMLOP_NAMECHAR; 1302 } 1303 if (opcode >= 'A' && opcode <= 'Z') 1304 return AMLOP_NAMECHAR; 1305 if (twocode == AMLOP_LNOTEQUAL || twocode == AMLOP_LLESSEQUAL || 1306 twocode == AMLOP_LGREATEREQUAL || opcode == AMLOP_EXTPREFIX) { 1307 scope->pos += 2; 1308 return twocode; 1309 } 1310 scope->pos += 1; 1311 return opcode; 1312 } 1313 1314 /* Decode embedded AML Namestring */ 1315 uint8_t * 1316 aml_parsename(struct aml_node *inode, uint8_t *pos, struct aml_value **rval, int create) 1317 { 1318 struct aml_node *relnode, *node = inode; 1319 uint8_t *start = pos; 1320 int i; 1321 1322 if (*pos == AMLOP_ROOTCHAR) { 1323 pos++; 1324 node = &aml_root; 1325 } 1326 while (*pos == AMLOP_PARENTPREFIX) { 1327 pos++; 1328 if ((node = node->parent) == NULL) 1329 node = &aml_root; 1330 } 1331 switch (*pos) { 1332 case 0x00: 1333 pos++; 1334 break; 1335 case AMLOP_MULTINAMEPREFIX: 1336 for (i=0; i<pos[1]; i++) 1337 node = __aml_search(node, pos+2+i*AML_NAMESEG_LEN, 1338 create); 1339 pos += 2+i*AML_NAMESEG_LEN; 1340 break; 1341 case AMLOP_DUALNAMEPREFIX: 1342 node = __aml_search(node, pos+1, create); 1343 node = __aml_search(node, pos+1+AML_NAMESEG_LEN, create); 1344 pos += 1+2*AML_NAMESEG_LEN; 1345 break; 1346 default: 1347 /* If Relative Search (pos == start), recursively go up root */ 1348 relnode = node; 1349 do { 1350 node = __aml_search(relnode, pos, create); 1351 relnode = relnode->parent; 1352 } while (!node && pos == start && relnode); 1353 pos += AML_NAMESEG_LEN; 1354 break; 1355 } 1356 if (node) { 1357 *rval = node->value; 1358 1359 /* Dereference ALIAS here */ 1360 if ((*rval)->type == AML_OBJTYPE_OBJREF && 1361 (*rval)->v_objref.type == AMLOP_ALIAS) { 1362 dnprintf(10, "deref alias: %s\n", aml_nodename(node)); 1363 *rval = (*rval)->v_objref.ref; 1364 } 1365 aml_addref(*rval, 0); 1366 1367 dnprintf(10, "parsename: %s %x\n", aml_nodename(node), 1368 (*rval)->type); 1369 } else { 1370 *rval = aml_allocvalue(AML_OBJTYPE_NAMEREF, 0, start); 1371 1372 dnprintf(10, "%s:%s not found\n", aml_nodename(inode), 1373 aml_getname(start)); 1374 } 1375 1376 return pos; 1377 } 1378 1379 /* Decode AML Length field 1380 * AML Length field is encoded: 1381 * byte0 byte1 byte2 byte3 1382 * 00xxxxxx : if upper bits == 00, length = xxxxxx 1383 * 01--xxxx yyyyyyyy : if upper bits == 01, length = yyyyyyyyxxxx 1384 * 10--xxxx yyyyyyyy zzzzzzzz : if upper bits == 10, length = zzzzzzzzyyyyyyyyxxxx 1385 * 11--xxxx yyyyyyyy zzzzzzzz wwwwwwww : if upper bits == 11, length = wwwwwwwwzzzzzzzzyyyyyyyyxxxx 1386 */ 1387 int 1388 aml_parselength(struct aml_scope *scope) 1389 { 1390 int len; 1391 uint8_t lcode; 1392 1393 lcode = *(scope->pos++); 1394 if (lcode <= 0x3F) 1395 return lcode; 1396 1397 /* lcode >= 0x40, multibyte length, get first byte of extended length */ 1398 len = lcode & 0xF; 1399 len += *(scope->pos++) << 4L; 1400 if (lcode >= 0x80) 1401 len += *(scope->pos++) << 12L; 1402 if (lcode >= 0xC0) 1403 len += *(scope->pos++) << 20L; 1404 return len; 1405 } 1406 1407 /* Get address of end of scope; based on current address */ 1408 uint8_t * 1409 aml_parseend(struct aml_scope *scope) 1410 { 1411 uint8_t *pos = scope->pos; 1412 int len; 1413 1414 len = aml_parselength(scope); 1415 if (pos+len > scope->end) { 1416 dnprintf(10, 1417 "Bad scope... runover pos:%.4x new end:%.4x scope " 1418 "end:%.4x\n", aml_pc(pos), aml_pc(pos+len), 1419 aml_pc(scope->end)); 1420 return scope->end; 1421 } 1422 return pos+len; 1423 } 1424 1425 /* 1426 * @@@: Opcode utility functions 1427 */ 1428 1429 /* 1430 * @@@: Opcode functions 1431 */ 1432 1433 int odp; 1434 1435 const char hext[] = "0123456789ABCDEF"; 1436 1437 const char * 1438 aml_eisaid(uint32_t pid) 1439 { 1440 static char id[8]; 1441 1442 id[0] = '@' + ((pid >> 2) & 0x1F); 1443 id[1] = '@' + ((pid << 3) & 0x18) + ((pid >> 13) & 0x7); 1444 id[2] = '@' + ((pid >> 8) & 0x1F); 1445 id[3] = hext[(pid >> 20) & 0xF]; 1446 id[4] = hext[(pid >> 16) & 0xF]; 1447 id[5] = hext[(pid >> 28) & 0xF]; 1448 id[6] = hext[(pid >> 24) & 0xF]; 1449 id[7] = 0; 1450 return id; 1451 } 1452 1453 /* 1454 * @@@: Default Object creation 1455 */ 1456 static char osstring[] = "Macrosift Windogs MT"; 1457 struct aml_defval { 1458 const char *name; 1459 int type; 1460 int64_t ival; 1461 const void *bval; 1462 struct aml_value **gval; 1463 } aml_defobj[] = { 1464 { "_OS_", AML_OBJTYPE_STRING, -1, osstring }, 1465 { "_REV", AML_OBJTYPE_INTEGER, 2, NULL }, 1466 { "_GL", AML_OBJTYPE_MUTEX, 1, NULL, &aml_global_lock }, 1467 { "_OSI", AML_OBJTYPE_METHOD, 1, aml_callosi }, 1468 1469 /* Create default scopes */ 1470 { "_GPE", AML_OBJTYPE_DEVICE }, 1471 { "_PR_", AML_OBJTYPE_DEVICE }, 1472 { "_SB_", AML_OBJTYPE_DEVICE }, 1473 { "_TZ_", AML_OBJTYPE_DEVICE }, 1474 { "_SI_", AML_OBJTYPE_DEVICE }, 1475 1476 { NULL } 1477 }; 1478 1479 /* _OSI Default Method: 1480 * Returns True if string argument matches list of known OS strings 1481 * We return True for Windows to fake out nasty bad AML 1482 */ 1483 char *aml_valid_osi[] = { 1484 AML_VALID_OSI, 1485 NULL 1486 }; 1487 1488 enum acpi_osi acpi_max_osi = OSI_UNKNOWN; 1489 1490 struct aml_value * 1491 aml_callosi(struct aml_scope *scope, struct aml_value *val) 1492 { 1493 int idx, result=0; 1494 struct aml_value *fa; 1495 1496 fa = aml_getstack(scope, AMLOP_ARG0); 1497 1498 if (hw_vendor != NULL && 1499 (strcmp(hw_vendor, "Apple Inc.") == 0 || 1500 strcmp(hw_vendor, "Apple Computer, Inc.") == 0)) { 1501 if (strcmp(fa->v_string, "Darwin") == 0) { 1502 dnprintf(10,"osi: returning 1 for %s on %s hardware\n", 1503 fa->v_string, hw_vendor); 1504 result = 1; 1505 } else 1506 dnprintf(10,"osi: on %s hardware, but ignoring %s\n", 1507 hw_vendor, fa->v_string); 1508 1509 return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL); 1510 } 1511 1512 for (idx=0; !result && aml_valid_osi[idx] != NULL; idx++) { 1513 dnprintf(10,"osi: %s,%s\n", fa->v_string, aml_valid_osi[idx]); 1514 result = !strcmp(fa->v_string, aml_valid_osi[idx]); 1515 if (result) { 1516 if (idx > acpi_max_osi) 1517 acpi_max_osi = idx; 1518 break; 1519 } 1520 } 1521 dnprintf(10,"@@ OSI found: %x\n", result); 1522 return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL); 1523 } 1524 1525 void 1526 aml_create_defaultobjects(void) 1527 { 1528 struct aml_value *tmp; 1529 struct aml_defval *def; 1530 1531 #ifdef ACPI_MEMDEBUG 1532 LIST_INIT(&acpi_memhead); 1533 #endif 1534 1535 osstring[1] = 'i'; 1536 osstring[6] = 'o'; 1537 osstring[15] = 'w'; 1538 osstring[18] = 'N'; 1539 1540 SIMPLEQ_INIT(&aml_root.son); 1541 strlcpy(aml_root.name, "\\", sizeof(aml_root.name)); 1542 aml_root.value = aml_allocvalue(0, 0, NULL); 1543 aml_root.value->node = &aml_root; 1544 1545 for (def = aml_defobj; def->name; def++) { 1546 /* Allocate object value + add to namespace */ 1547 aml_parsename(&aml_root, (uint8_t *)def->name, &tmp, 1); 1548 _aml_setvalue(tmp, def->type, def->ival, def->bval); 1549 if (def->gval) { 1550 /* Set root object pointer */ 1551 *def->gval = tmp; 1552 } 1553 aml_delref(&tmp, 0); 1554 } 1555 } 1556 1557 #ifdef ACPI_DEBUG 1558 int 1559 aml_print_resource(union acpi_resource *crs, void *arg) 1560 { 1561 int typ = AML_CRSTYPE(crs); 1562 1563 switch (typ) { 1564 case LR_EXTIRQ: 1565 printf("extirq\tflags:%.2x len:%.2x irq:%.4x\n", 1566 crs->lr_extirq.flags, crs->lr_extirq.irq_count, 1567 letoh32(crs->lr_extirq.irq[0])); 1568 break; 1569 case SR_IRQ: 1570 printf("irq\t%.4x %.2x\n", letoh16(crs->sr_irq.irq_mask), 1571 crs->sr_irq.irq_flags); 1572 break; 1573 case SR_DMA: 1574 printf("dma\t%.2x %.2x\n", crs->sr_dma.channel, 1575 crs->sr_dma.flags); 1576 break; 1577 case SR_IOPORT: 1578 printf("ioport\tflags:%.2x _min:%.4x _max:%.4x _aln:%.2x _len:%.2x\n", 1579 crs->sr_ioport.flags, crs->sr_ioport._min, 1580 crs->sr_ioport._max, crs->sr_ioport._aln, 1581 crs->sr_ioport._len); 1582 break; 1583 case SR_STARTDEP: 1584 printf("startdep\n"); 1585 break; 1586 case SR_ENDDEP: 1587 printf("enddep\n"); 1588 break; 1589 case LR_WORD: 1590 printf("word\ttype:%.2x flags:%.2x tflag:%.2x gra:%.4x min:%.4x max:%.4x tra:%.4x len:%.4x\n", 1591 crs->lr_word.type, crs->lr_word.flags, crs->lr_word.tflags, 1592 crs->lr_word._gra, crs->lr_word._min, crs->lr_word._max, 1593 crs->lr_word._tra, crs->lr_word._len); 1594 break; 1595 case LR_DWORD: 1596 printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.8x min:%.8x max:%.8x tra:%.8x len:%.8x\n", 1597 crs->lr_dword.type, crs->lr_dword.flags, crs->lr_dword.tflags, 1598 crs->lr_dword._gra, crs->lr_dword._min, crs->lr_dword._max, 1599 crs->lr_dword._tra, crs->lr_dword._len); 1600 break; 1601 case LR_QWORD: 1602 printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.16llx min:%.16llx max:%.16llx tra:%.16llx len:%.16llx\n", 1603 crs->lr_qword.type, crs->lr_qword.flags, crs->lr_qword.tflags, 1604 crs->lr_qword._gra, crs->lr_qword._min, crs->lr_qword._max, 1605 crs->lr_qword._tra, crs->lr_qword._len); 1606 break; 1607 default: 1608 printf("unknown type: %x\n", typ); 1609 break; 1610 } 1611 return (0); 1612 } 1613 #endif /* ACPI_DEBUG */ 1614 1615 union acpi_resource *aml_mapresource(union acpi_resource *); 1616 1617 union acpi_resource * 1618 aml_mapresource(union acpi_resource *crs) 1619 { 1620 static union acpi_resource map; 1621 int rlen; 1622 1623 rlen = AML_CRSLEN(crs); 1624 if (rlen >= sizeof(map)) 1625 return crs; 1626 1627 memset(&map, 0, sizeof(map)); 1628 memcpy(&map, crs, rlen); 1629 1630 return ↦ 1631 } 1632 1633 int 1634 aml_parse_resource(struct aml_value *res, 1635 int (*crs_enum)(int, union acpi_resource *, void *), void *arg) 1636 { 1637 int off, rlen, crsidx; 1638 union acpi_resource *crs; 1639 1640 if (res->type != AML_OBJTYPE_BUFFER || res->length < 5) 1641 return (-1); 1642 for (off = 0, crsidx = 0; off < res->length; off += rlen, crsidx++) { 1643 crs = (union acpi_resource *)(res->v_buffer+off); 1644 1645 rlen = AML_CRSLEN(crs); 1646 if (crs->hdr.typecode == SRT_ENDTAG || !rlen) 1647 break; 1648 1649 crs = aml_mapresource(crs); 1650 #ifdef ACPI_DEBUG 1651 aml_print_resource(crs, NULL); 1652 #endif 1653 crs_enum(crsidx, crs, arg); 1654 } 1655 1656 return (0); 1657 } 1658 1659 void 1660 aml_foreachpkg(struct aml_value *pkg, int start, 1661 void (*fn)(struct aml_value *, void *), void *arg) 1662 { 1663 int idx; 1664 1665 if (pkg->type != AML_OBJTYPE_PACKAGE) 1666 return; 1667 for (idx=start; idx<pkg->length; idx++) 1668 fn(pkg->v_package[idx], arg); 1669 } 1670 1671 /* 1672 * Walk nodes and perform fixups for nameref 1673 */ 1674 int aml_fixup_node(struct aml_node *, void *); 1675 1676 int aml_fixup_node(struct aml_node *node, void *arg) 1677 { 1678 struct aml_value *val = arg; 1679 int i; 1680 1681 if (node->value == NULL) 1682 return (0); 1683 if (arg == NULL) 1684 aml_fixup_node(node, node->value); 1685 else if (val->type == AML_OBJTYPE_NAMEREF) { 1686 node = aml_searchname(node, aml_getname(val->v_nameref)); 1687 if (node && node->value) { 1688 _aml_setvalue(val, AML_OBJTYPE_OBJREF, AMLOP_NAMECHAR, 1689 node->value); 1690 } 1691 } else if (val->type == AML_OBJTYPE_PACKAGE) { 1692 for (i = 0; i < val->length; i++) 1693 aml_fixup_node(node, val->v_package[i]); 1694 } 1695 return (0); 1696 } 1697 1698 void 1699 aml_postparse(void) 1700 { 1701 aml_walknodes(&aml_root, AML_WALK_PRE, aml_fixup_node, NULL); 1702 } 1703 1704 #ifndef SMALL_KERNEL 1705 const char * 1706 aml_val_to_string(const struct aml_value *val) 1707 { 1708 static char buffer[256]; 1709 1710 int len; 1711 1712 switch (val->type) { 1713 case AML_OBJTYPE_BUFFER: 1714 len = val->length; 1715 if (len >= sizeof(buffer)) 1716 len = sizeof(buffer) - 1; 1717 memcpy(buffer, val->v_buffer, len); 1718 buffer[len] = 0; 1719 break; 1720 case AML_OBJTYPE_STRING: 1721 strlcpy(buffer, val->v_string, sizeof(buffer)); 1722 break; 1723 case AML_OBJTYPE_INTEGER: 1724 snprintf(buffer, sizeof(buffer), "%llx", val->v_integer); 1725 break; 1726 default: 1727 snprintf(buffer, sizeof(buffer), 1728 "Failed to convert type %d to string!", val->type); 1729 }; 1730 1731 return (buffer); 1732 } 1733 #endif /* SMALL_KERNEL */ 1734 1735 int aml_error; 1736 1737 struct aml_value *aml_gettgt(struct aml_value *, int); 1738 struct aml_value *aml_eval(struct aml_scope *, struct aml_value *, int, int, 1739 struct aml_value *); 1740 struct aml_value *aml_parsesimple(struct aml_scope *, char, 1741 struct aml_value *); 1742 struct aml_value *aml_parse(struct aml_scope *, int, const char *); 1743 struct aml_value *aml_seterror(struct aml_scope *, const char *, ...); 1744 1745 struct aml_scope *aml_findscope(struct aml_scope *, int, int); 1746 struct aml_scope *aml_pushscope(struct aml_scope *, struct aml_value *, 1747 struct aml_node *, int); 1748 struct aml_scope *aml_popscope(struct aml_scope *); 1749 1750 void aml_showstack(struct aml_scope *); 1751 struct aml_value *aml_convert(struct aml_value *, int, int); 1752 1753 int aml_matchtest(int64_t, int64_t, int); 1754 int aml_match(struct aml_value *, int, int, int, int, int); 1755 1756 int aml_compare(struct aml_value *, struct aml_value *, int); 1757 struct aml_value *aml_concat(struct aml_value *, struct aml_value *); 1758 struct aml_value *aml_concatres(struct aml_value *, struct aml_value *); 1759 struct aml_value *aml_mid(struct aml_value *, int, int); 1760 int aml_ccrlen(int, union acpi_resource *, void *); 1761 1762 void aml_store(struct aml_scope *, struct aml_value *, int64_t, 1763 struct aml_value *); 1764 1765 /* 1766 * Reference Count functions 1767 */ 1768 void 1769 aml_addref(struct aml_value *val, const char *lbl) 1770 { 1771 if (val == NULL) 1772 return; 1773 dnprintf(50, "XAddRef: %p %s:[%s] %d\n", 1774 val, lbl, 1775 val->node ? aml_nodename(val->node) : "INTERNAL", 1776 val->refcnt); 1777 val->refcnt++; 1778 } 1779 1780 /* Decrease reference counter */ 1781 void 1782 aml_delref(struct aml_value **pv, const char *lbl) 1783 { 1784 struct aml_value *val; 1785 1786 if (pv == NULL || *pv == NULL) 1787 return; 1788 val = *pv; 1789 val->refcnt--; 1790 if (val->refcnt == 0) { 1791 dnprintf(50, "XDelRef: %p %s %2d [%s] %s\n", 1792 val, lbl, 1793 val->refcnt, 1794 val->node ? aml_nodename(val->node) : "INTERNAL", 1795 val->refcnt ? "" : "---------------- FREEING"); 1796 1797 aml_freevalue(val); 1798 acpi_os_free(val); 1799 *pv = NULL; 1800 } 1801 } 1802 1803 /* Walk list of parent scopes until we find one of 'type' 1804 * If endscope is set, mark all intermediate scopes as invalid (used for Method/While) */ 1805 struct aml_scope * 1806 aml_findscope(struct aml_scope *scope, int type, int endscope) 1807 { 1808 while (scope) { 1809 switch (endscope) { 1810 case AMLOP_RETURN: 1811 scope->pos = scope->end; 1812 if (scope->type == AMLOP_WHILE) 1813 scope->pos = NULL; 1814 break; 1815 case AMLOP_CONTINUE: 1816 scope->pos = scope->end; 1817 break; 1818 case AMLOP_BREAK: 1819 scope->pos = scope->end; 1820 if (scope->type == type) 1821 scope->parent->pos = scope->end; 1822 break; 1823 } 1824 if (scope->type == type) 1825 break; 1826 scope = scope->parent; 1827 } 1828 return scope; 1829 } 1830 1831 struct aml_value * 1832 aml_getstack(struct aml_scope *scope, int opcode) 1833 { 1834 struct aml_value *sp; 1835 1836 sp = NULL; 1837 scope = aml_findscope(scope, AMLOP_METHOD, 0); 1838 if (scope == NULL) 1839 return NULL; 1840 if (opcode >= AMLOP_LOCAL0 && opcode <= AMLOP_LOCAL7) { 1841 if (scope->locals == NULL) 1842 scope->locals = aml_allocvalue(AML_OBJTYPE_PACKAGE, 8, NULL); 1843 sp = scope->locals->v_package[opcode - AMLOP_LOCAL0]; 1844 sp->stack = opcode; 1845 } else if (opcode >= AMLOP_ARG0 && opcode <= AMLOP_ARG6) { 1846 if (scope->args == NULL) 1847 scope->args = aml_allocvalue(AML_OBJTYPE_PACKAGE, 7, NULL); 1848 sp = scope->args->v_package[opcode - AMLOP_ARG0]; 1849 if (sp->type == AML_OBJTYPE_OBJREF) 1850 sp = sp->v_objref.ref; 1851 } 1852 return sp; 1853 } 1854 1855 #ifdef ACPI_DEBUG 1856 /* Dump AML Stack */ 1857 void 1858 aml_showstack(struct aml_scope *scope) 1859 { 1860 struct aml_value *sp; 1861 int idx; 1862 1863 dnprintf(10, "===== Stack %s:%s\n", aml_nodename(scope->node), 1864 aml_mnem(scope->type, 0)); 1865 for (idx=0; scope->args && idx<7; idx++) { 1866 sp = aml_getstack(scope, AMLOP_ARG0+idx); 1867 if (sp && sp->type) { 1868 dnprintf(10," Arg%d: ", idx); 1869 aml_showvalue(sp); 1870 } 1871 } 1872 for (idx=0; scope->locals && idx<8; idx++) { 1873 sp = aml_getstack(scope, AMLOP_LOCAL0+idx); 1874 if (sp && sp->type) { 1875 dnprintf(10," Local%d: ", idx); 1876 aml_showvalue(sp); 1877 } 1878 } 1879 } 1880 #endif 1881 1882 /* Create a new scope object */ 1883 struct aml_scope * 1884 aml_pushscope(struct aml_scope *parent, struct aml_value *range, 1885 struct aml_node *node, int type) 1886 { 1887 struct aml_scope *scope; 1888 uint8_t *start, *end; 1889 1890 if (range->type == AML_OBJTYPE_METHOD) { 1891 start = range->v_method.start; 1892 end = range->v_method.end; 1893 } else { 1894 start = range->v_buffer; 1895 end = start + range->length; 1896 if (start == end) 1897 return NULL; 1898 } 1899 scope = acpi_os_malloc(sizeof(struct aml_scope)); 1900 if (scope == NULL) 1901 return NULL; 1902 1903 scope->node = node; 1904 scope->start = start; 1905 scope->end = end; 1906 scope->pos = scope->start; 1907 scope->parent = parent; 1908 scope->type = type; 1909 scope->sc = acpi_softc; 1910 1911 if (parent) 1912 scope->depth = parent->depth+1; 1913 1914 aml_lastscope = scope; 1915 1916 return scope; 1917 } 1918 1919 /* Free a scope object and any children */ 1920 struct aml_scope * 1921 aml_popscope(struct aml_scope *scope) 1922 { 1923 struct aml_scope *nscope; 1924 1925 if (scope == NULL) 1926 return NULL; 1927 1928 nscope = scope->parent; 1929 1930 if (scope->type == AMLOP_METHOD) 1931 aml_delchildren(scope->node); 1932 if (scope->locals) { 1933 aml_freevalue(scope->locals); 1934 acpi_os_free(scope->locals); 1935 scope->locals = NULL; 1936 } 1937 if (scope->args) { 1938 aml_freevalue(scope->args); 1939 acpi_os_free(scope->args); 1940 scope->args = NULL; 1941 } 1942 acpi_os_free(scope); 1943 aml_lastscope = nscope; 1944 1945 return nscope; 1946 } 1947 1948 /* Test AMLOP_MATCH codes */ 1949 int 1950 aml_matchtest(int64_t a, int64_t b, int op) 1951 { 1952 switch (op) { 1953 case AML_MATCH_TR: 1954 return (1); 1955 case AML_MATCH_EQ: 1956 return (a == b); 1957 case AML_MATCH_LT: 1958 return (a < b); 1959 case AML_MATCH_LE: 1960 return (a <= b); 1961 case AML_MATCH_GE: 1962 return (a >= b); 1963 case AML_MATCH_GT: 1964 return (a > b); 1965 } 1966 return (0); 1967 } 1968 1969 /* Search a package for a matching value */ 1970 int 1971 aml_match(struct aml_value *pkg, int index, 1972 int op1, int v1, 1973 int op2, int v2) 1974 { 1975 struct aml_value *tmp; 1976 int flag; 1977 1978 while (index < pkg->length) { 1979 /* Convert package value to integer */ 1980 tmp = aml_convert(pkg->v_package[index], 1981 AML_OBJTYPE_INTEGER, -1); 1982 1983 /* Perform test */ 1984 flag = aml_matchtest(tmp->v_integer, v1, op1) && 1985 aml_matchtest(tmp->v_integer, v2, op2); 1986 aml_delref(&tmp, "xmatch"); 1987 1988 if (flag) 1989 return index; 1990 index++; 1991 } 1992 return -1; 1993 } 1994 1995 /* 1996 * Conversion routines 1997 */ 1998 int64_t 1999 aml_hextoint(const char *str) 2000 { 2001 int64_t v = 0; 2002 char c; 2003 2004 while (*str) { 2005 if (*str >= '0' && *str <= '9') 2006 c = *(str++) - '0'; 2007 else if (*str >= 'a' && *str <= 'f') 2008 c = *(str++) - 'a' + 10; 2009 else if (*str >= 'A' && *str <= 'F') 2010 c = *(str++) - 'A' + 10; 2011 else 2012 break; 2013 v = (v << 4) + c; 2014 } 2015 return v; 2016 2017 } 2018 2019 struct aml_value * 2020 aml_convert(struct aml_value *a, int ctype, int clen) 2021 { 2022 struct aml_value *c = NULL; 2023 2024 /* Object is already this type */ 2025 if (clen == -1) 2026 clen = a->length; 2027 if (a->type == ctype) { 2028 aml_addref(a, "XConvert"); 2029 return a; 2030 } 2031 switch (ctype) { 2032 case AML_OBJTYPE_BUFFER: 2033 dnprintf(10,"convert to buffer\n"); 2034 switch (a->type) { 2035 case AML_OBJTYPE_INTEGER: 2036 c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, 2037 &a->v_integer); 2038 break; 2039 case AML_OBJTYPE_STRING: 2040 c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, 2041 a->v_string); 2042 break; 2043 } 2044 break; 2045 case AML_OBJTYPE_INTEGER: 2046 dnprintf(10,"convert to integer : %x\n", a->type); 2047 switch (a->type) { 2048 case AML_OBJTYPE_BUFFER: 2049 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2050 memcpy(&c->v_integer, a->v_buffer, 2051 min(a->length, c->length)); 2052 break; 2053 case AML_OBJTYPE_STRING: 2054 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2055 c->v_integer = aml_hextoint(a->v_string); 2056 break; 2057 case AML_OBJTYPE_UNINITIALIZED: 2058 c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); 2059 break; 2060 } 2061 break; 2062 case AML_OBJTYPE_STRING: 2063 case AML_OBJTYPE_HEXSTRING: 2064 case AML_OBJTYPE_DECSTRING: 2065 dnprintf(10,"convert to string\n"); 2066 switch (a->type) { 2067 case AML_OBJTYPE_INTEGER: 2068 c = aml_allocvalue(AML_OBJTYPE_STRING, 20, NULL); 2069 snprintf(c->v_string, c->length, (ctype == AML_OBJTYPE_HEXSTRING) ? 2070 "0x%llx" : "%lld", a->v_integer); 2071 break; 2072 case AML_OBJTYPE_BUFFER: 2073 c = aml_allocvalue(AML_OBJTYPE_STRING, a->length, 2074 a->v_buffer); 2075 break; 2076 case AML_OBJTYPE_STRING: 2077 aml_addref(a, "XConvert"); 2078 return a; 2079 case AML_OBJTYPE_PACKAGE: /* XXX Deal with broken Lenovo X1 BIOS. */ 2080 c = aml_allocvalue(AML_OBJTYPE_STRING, 0, NULL); 2081 break; 2082 } 2083 break; 2084 } 2085 if (c == NULL) { 2086 #ifndef SMALL_KERNEL 2087 aml_showvalue(a); 2088 #endif 2089 aml_die("Could not convert %x to %x\n", a->type, ctype); 2090 } 2091 return c; 2092 } 2093 2094 int 2095 aml_compare(struct aml_value *a1, struct aml_value *a2, int opcode) 2096 { 2097 int rc = 0; 2098 2099 /* Convert A2 to type of A1 */ 2100 a2 = aml_convert(a2, a1->type, -1); 2101 if (a1->type == AML_OBJTYPE_INTEGER) 2102 rc = aml_evalexpr(a1->v_integer, a2->v_integer, opcode); 2103 else { 2104 /* Perform String/Buffer comparison */ 2105 rc = memcmp(a1->v_buffer, a2->v_buffer, 2106 min(a1->length, a2->length)); 2107 if (rc == 0) { 2108 /* If buffers match, which one is longer */ 2109 rc = a1->length - a2->length; 2110 } 2111 /* Perform comparison against zero */ 2112 rc = aml_evalexpr(rc, 0, opcode); 2113 } 2114 /* Either deletes temp buffer, or decrease refcnt on original A2 */ 2115 aml_delref(&a2, "xcompare"); 2116 return rc; 2117 } 2118 2119 /* Concatenate two objects, returning pointer to new object */ 2120 struct aml_value * 2121 aml_concat(struct aml_value *a1, struct aml_value *a2) 2122 { 2123 struct aml_value *c = NULL; 2124 2125 /* Convert arg2 to type of arg1 */ 2126 a2 = aml_convert(a2, a1->type, -1); 2127 switch (a1->type) { 2128 case AML_OBJTYPE_INTEGER: 2129 c = aml_allocvalue(AML_OBJTYPE_BUFFER, 2130 a1->length + a2->length, NULL); 2131 memcpy(c->v_buffer, &a1->v_integer, a1->length); 2132 memcpy(c->v_buffer+a1->length, &a2->v_integer, a2->length); 2133 break; 2134 case AML_OBJTYPE_BUFFER: 2135 c = aml_allocvalue(AML_OBJTYPE_BUFFER, 2136 a1->length + a2->length, NULL); 2137 memcpy(c->v_buffer, a1->v_buffer, a1->length); 2138 memcpy(c->v_buffer+a1->length, a2->v_buffer, a2->length); 2139 break; 2140 case AML_OBJTYPE_STRING: 2141 c = aml_allocvalue(AML_OBJTYPE_STRING, 2142 a1->length + a2->length, NULL); 2143 memcpy(c->v_string, a1->v_string, a1->length); 2144 memcpy(c->v_string+a1->length, a2->v_string, a2->length); 2145 break; 2146 default: 2147 aml_die("concat type mismatch %d != %d\n", a1->type, a2->type); 2148 break; 2149 } 2150 /* Either deletes temp buffer, or decrease refcnt on original A2 */ 2151 aml_delref(&a2, "xconcat"); 2152 return c; 2153 } 2154 2155 /* Calculate length of Resource Template */ 2156 int 2157 aml_ccrlen(int crsidx, union acpi_resource *rs, void *arg) 2158 { 2159 int *plen = arg; 2160 2161 *plen += AML_CRSLEN(rs); 2162 return (0); 2163 } 2164 2165 /* Concatenate resource templates, returning pointer to new object */ 2166 struct aml_value * 2167 aml_concatres(struct aml_value *a1, struct aml_value *a2) 2168 { 2169 struct aml_value *c; 2170 int l1 = 0, l2 = 0, l3 = 2; 2171 uint8_t a3[] = { SRT_ENDTAG, 0x00 }; 2172 2173 if (a1->type != AML_OBJTYPE_BUFFER || a2->type != AML_OBJTYPE_BUFFER) 2174 aml_die("concatres: not buffers\n"); 2175 2176 /* Walk a1, a2, get length minus end tags, concatenate buffers, add end tag */ 2177 aml_parse_resource(a1, aml_ccrlen, &l1); 2178 aml_parse_resource(a2, aml_ccrlen, &l2); 2179 2180 /* Concatenate buffers, add end tag */ 2181 c = aml_allocvalue(AML_OBJTYPE_BUFFER, l1+l2+l3, NULL); 2182 memcpy(c->v_buffer, a1->v_buffer, l1); 2183 memcpy(c->v_buffer+l1, a2->v_buffer, l2); 2184 memcpy(c->v_buffer+l1+l2, a3, l3); 2185 2186 return c; 2187 } 2188 2189 /* Extract substring from string or buffer */ 2190 struct aml_value * 2191 aml_mid(struct aml_value *src, int index, int length) 2192 { 2193 if (index > src->length) 2194 index = src->length; 2195 if ((index + length) > src->length) 2196 length = src->length - index; 2197 return aml_allocvalue(src->type, length, src->v_buffer + index); 2198 } 2199 2200 /* 2201 * Field I/O utility functions 2202 */ 2203 void aml_createfield(struct aml_value *, int, struct aml_value *, int, int, 2204 struct aml_value *, int, int); 2205 void aml_parsefieldlist(struct aml_scope *, int, int, 2206 struct aml_value *, struct aml_value *, int); 2207 2208 int 2209 aml_evalhid(struct aml_node *node, struct aml_value *val) 2210 { 2211 if (aml_evalname(acpi_softc, node, "_HID", 0, NULL, val)) 2212 return (-1); 2213 2214 /* Integer _HID: convert to EISA ID */ 2215 if (val->type == AML_OBJTYPE_INTEGER) 2216 _aml_setvalue(val, AML_OBJTYPE_STRING, -1, aml_eisaid(val->v_integer)); 2217 return (0); 2218 } 2219 2220 int 2221 aml_opreg_sysmem_handler(void *cookie, int iodir, uint64_t address, int size, 2222 uint64_t *value) 2223 { 2224 return acpi_gasio(acpi_softc, iodir, GAS_SYSTEM_MEMORY, 2225 address, size, size, value); 2226 } 2227 2228 int 2229 aml_opreg_sysio_handler(void *cookie, int iodir, uint64_t address, int size, 2230 uint64_t *value) 2231 { 2232 return acpi_gasio(acpi_softc, iodir, GAS_SYSTEM_IOSPACE, 2233 address, size, size, value); 2234 } 2235 2236 int 2237 aml_opreg_pcicfg_handler(void *cookie, int iodir, uint64_t address, int size, 2238 uint64_t *value) 2239 { 2240 return acpi_gasio(acpi_softc, iodir, GAS_PCI_CFG_SPACE, 2241 address, size, size, value); 2242 } 2243 2244 int 2245 aml_opreg_ec_handler(void *cookie, int iodir, uint64_t address, int size, 2246 uint64_t *value) 2247 { 2248 return acpi_gasio(acpi_softc, iodir, GAS_EMBEDDED, 2249 address, size, size, value); 2250 } 2251 2252 struct aml_regionspace { 2253 void *cookie; 2254 int (*handler)(void *, int, uint64_t, int, uint64_t *); 2255 }; 2256 2257 struct aml_regionspace aml_regionspace[256] = { 2258 [ACPI_OPREG_SYSMEM] = { NULL, aml_opreg_sysmem_handler }, 2259 [ACPI_OPREG_SYSIO] = { NULL, aml_opreg_sysio_handler }, 2260 [ACPI_OPREG_PCICFG] = { NULL, aml_opreg_pcicfg_handler }, 2261 [ACPI_OPREG_EC] = { NULL, aml_opreg_ec_handler }, 2262 }; 2263 2264 void 2265 aml_register_regionspace(struct aml_node *node, int iospace, void *cookie, 2266 int (*handler)(void *, int, uint64_t, int, uint64_t *)) 2267 { 2268 struct aml_value arg[2]; 2269 2270 KASSERT(iospace >= 0 && iospace < 256); 2271 2272 aml_regionspace[iospace].cookie = cookie; 2273 aml_regionspace[iospace].handler = handler; 2274 2275 /* Register address space. */ 2276 memset(&arg, 0, sizeof(arg)); 2277 arg[0].type = AML_OBJTYPE_INTEGER; 2278 arg[0].v_integer = iospace; 2279 arg[1].type = AML_OBJTYPE_INTEGER; 2280 arg[1].v_integer = 1; 2281 node = aml_searchname(node, "_REG"); 2282 if (node) 2283 aml_evalnode(acpi_softc, node, 2, arg, NULL); 2284 } 2285 2286 void aml_rwgen(struct aml_value *, int, int, struct aml_value *, int, int); 2287 void aml_rwgpio(struct aml_value *, int, int, struct aml_value *, int, int); 2288 void aml_rwgsb(struct aml_value *, int, int, int, struct aml_value *, int, int); 2289 void aml_rwindexfield(struct aml_value *, struct aml_value *val, int); 2290 void aml_rwfield(struct aml_value *, int, int, struct aml_value *, int); 2291 2292 /* Get PCI address for opregion objects */ 2293 int 2294 aml_rdpciaddr(struct aml_node *pcidev, union amlpci_t *addr) 2295 { 2296 int64_t res; 2297 2298 addr->bus = 0; 2299 addr->seg = 0; 2300 if (aml_evalinteger(acpi_softc, pcidev, "_ADR", 0, NULL, &res) == 0) { 2301 addr->fun = res & 0xFFFF; 2302 addr->dev = res >> 16; 2303 } 2304 while (pcidev != NULL) { 2305 /* HID device (PCI or PCIE root): eval _SEG and _BBN */ 2306 if (__aml_search(pcidev, "_HID", 0)) { 2307 if (aml_evalinteger(acpi_softc, pcidev, "_SEG", 2308 0, NULL, &res) == 0) { 2309 addr->seg = res; 2310 } 2311 if (aml_evalinteger(acpi_softc, pcidev, "_BBN", 2312 0, NULL, &res) == 0) { 2313 addr->bus = res; 2314 break; 2315 } 2316 } 2317 pcidev = pcidev->parent; 2318 } 2319 return (0); 2320 } 2321 2322 int 2323 acpi_genio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, 2324 int access_size, int len, void *buffer) 2325 { 2326 struct aml_regionspace *region = &aml_regionspace[iospace]; 2327 uint8_t *pb; 2328 int reg; 2329 2330 dnprintf(50, "genio: %.2x 0x%.8llx %s\n", 2331 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read"); 2332 2333 KASSERT((len % access_size) == 0); 2334 2335 pb = (uint8_t *)buffer; 2336 for (reg = 0; reg < len; reg += access_size) { 2337 uint64_t value; 2338 int err; 2339 2340 if (iodir == ACPI_IOREAD) { 2341 err = region->handler(region->cookie, iodir, 2342 address + reg, access_size, &value); 2343 if (err) 2344 return err; 2345 switch (access_size) { 2346 case 1: 2347 *(uint8_t *)(pb + reg) = value; 2348 break; 2349 case 2: 2350 *(uint16_t *)(pb + reg) = value; 2351 break; 2352 case 4: 2353 *(uint32_t *)(pb + reg) = value; 2354 break; 2355 default: 2356 printf("%s: invalid access size %d on read\n", 2357 __func__, access_size); 2358 return -1; 2359 } 2360 } else { 2361 switch (access_size) { 2362 case 1: 2363 value = *(uint8_t *)(pb + reg); 2364 break; 2365 case 2: 2366 value = *(uint16_t *)(pb + reg); 2367 break; 2368 case 4: 2369 value = *(uint32_t *)(pb + reg); 2370 break; 2371 default: 2372 printf("%s: invalid access size %d on write\n", 2373 __func__, access_size); 2374 return -1; 2375 } 2376 err = region->handler(region->cookie, iodir, 2377 address + reg, access_size, &value); 2378 if (err) 2379 return err; 2380 } 2381 } 2382 2383 return 0; 2384 } 2385 2386 /* Read/Write from opregion object */ 2387 void 2388 aml_rwgen(struct aml_value *rgn, int bpos, int blen, struct aml_value *val, 2389 int mode, int flag) 2390 { 2391 struct aml_value tmp; 2392 union amlpci_t pi; 2393 void *tbit, *vbit; 2394 int tlen, type, sz; 2395 2396 dnprintf(10," %5s %.2x %.8llx %.4x [%s]\n", 2397 mode == ACPI_IOREAD ? "read" : "write", 2398 rgn->v_opregion.iospace, 2399 rgn->v_opregion.iobase + (bpos >> 3), 2400 blen, aml_nodename(rgn->node)); 2401 memset(&tmp, 0, sizeof(tmp)); 2402 2403 /* Get field access size */ 2404 switch (AML_FIELD_ACCESS(flag)) { 2405 case AML_FIELD_WORDACC: 2406 sz = 2; 2407 break; 2408 case AML_FIELD_DWORDACC: 2409 sz = 4; 2410 break; 2411 case AML_FIELD_QWORDACC: 2412 sz = 8; 2413 break; 2414 default: 2415 sz = 1; 2416 break; 2417 } 2418 2419 pi.addr = (rgn->v_opregion.iobase + (bpos >> 3)) & ~(sz - 1); 2420 bpos += ((rgn->v_opregion.iobase & (sz - 1)) << 3); 2421 bpos &= ((sz << 3) - 1); 2422 2423 if (rgn->v_opregion.iospace == ACPI_OPREG_PCICFG) { 2424 /* Get PCI Root Address for this opregion */ 2425 aml_rdpciaddr(rgn->node->parent, &pi); 2426 } 2427 2428 tbit = &tmp.v_integer; 2429 vbit = &val->v_integer; 2430 tlen = roundup(bpos + blen, sz << 3); 2431 type = rgn->v_opregion.iospace; 2432 2433 if (aml_regionspace[type].handler == NULL) { 2434 printf("%s: unregistered RegionSpace 0x%x\n", __func__, type); 2435 return; 2436 } 2437 2438 /* Allocate temporary storage */ 2439 if (tlen > aml_intlen) { 2440 _aml_setvalue(&tmp, AML_OBJTYPE_BUFFER, tlen >> 3, 0); 2441 tbit = tmp.v_buffer; 2442 } 2443 2444 if (blen > aml_intlen) { 2445 if (mode == ACPI_IOREAD) { 2446 /* Read from a large field: create buffer */ 2447 _aml_setvalue(val, AML_OBJTYPE_BUFFER, (blen + 7) >> 3, 0); 2448 } else { 2449 /* Write to a large field.. create or convert buffer */ 2450 val = aml_convert(val, AML_OBJTYPE_BUFFER, -1); 2451 2452 if (blen > (val->length << 3)) 2453 blen = val->length << 3; 2454 } 2455 vbit = val->v_buffer; 2456 } else { 2457 if (mode == ACPI_IOREAD) { 2458 /* Read from a short field.. initialize integer */ 2459 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2460 } else { 2461 /* Write to a short field.. convert to integer */ 2462 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2463 } 2464 } 2465 2466 if (mode == ACPI_IOREAD) { 2467 /* Read bits from opregion */ 2468 acpi_genio(acpi_softc, ACPI_IOREAD, type, pi.addr, 2469 sz, tlen >> 3, tbit); 2470 aml_bufcpy(vbit, 0, tbit, bpos, blen); 2471 } else { 2472 /* Write bits to opregion */ 2473 if (AML_FIELD_UPDATE(flag) == AML_FIELD_PRESERVE && 2474 (bpos != 0 || blen != tlen)) { 2475 acpi_genio(acpi_softc, ACPI_IOREAD, type, pi.addr, 2476 sz, tlen >> 3, tbit); 2477 } else if (AML_FIELD_UPDATE(flag) == AML_FIELD_WRITEASONES) { 2478 memset(tbit, 0xff, tmp.length); 2479 } 2480 /* Copy target bits, then write to region */ 2481 aml_bufcpy(tbit, bpos, vbit, 0, blen); 2482 acpi_genio(acpi_softc, ACPI_IOWRITE, type, pi.addr, 2483 sz, tlen >> 3, tbit); 2484 2485 aml_delref(&val, "fld.write"); 2486 } 2487 aml_freevalue(&tmp); 2488 } 2489 2490 void 2491 aml_rwgpio(struct aml_value *conn, int bpos, int blen, struct aml_value *val, 2492 int mode, int flag) 2493 { 2494 union acpi_resource *crs = (union acpi_resource *)conn->v_buffer; 2495 struct aml_node *node; 2496 uint16_t pin; 2497 int v = 0; 2498 2499 if (conn->type != AML_OBJTYPE_BUFFER || conn->length < 5 || 2500 AML_CRSTYPE(crs) != LR_GPIO || AML_CRSLEN(crs) > conn->length) 2501 aml_die("Invalid GpioIo"); 2502 if (bpos != 0 || blen != 1) 2503 aml_die("Invalid GpioIo access"); 2504 2505 node = aml_searchname(conn->node, 2506 (char *)&crs->pad[crs->lr_gpio.res_off]); 2507 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 2508 2509 if (node == NULL || node->gpio == NULL) 2510 aml_die("Could not find GpioIo pin"); 2511 2512 if (mode == ACPI_IOWRITE) { 2513 v = aml_val2int(val); 2514 node->gpio->write_pin(node->gpio->cookie, pin, v); 2515 } else { 2516 v = node->gpio->read_pin(node->gpio->cookie, pin); 2517 _aml_setvalue(val, AML_OBJTYPE_INTEGER, v, NULL); 2518 } 2519 } 2520 2521 #ifndef SMALL_KERNEL 2522 2523 void 2524 aml_rwgsb(struct aml_value *conn, int len, int bpos, int blen, 2525 struct aml_value *val, int mode, int flag) 2526 { 2527 union acpi_resource *crs = (union acpi_resource *)conn->v_buffer; 2528 struct aml_node *node; 2529 i2c_tag_t tag; 2530 i2c_op_t op; 2531 i2c_addr_t addr; 2532 int cmdlen, buflen; 2533 uint8_t cmd[2]; 2534 uint8_t *buf; 2535 int err; 2536 2537 if (conn->type != AML_OBJTYPE_BUFFER || conn->length < 5 || 2538 AML_CRSTYPE(crs) != LR_SERBUS || AML_CRSLEN(crs) > conn->length || 2539 crs->lr_i2cbus.revid != 1 || crs->lr_i2cbus.type != LR_SERBUS_I2C) 2540 aml_die("Invalid GenericSerialBus"); 2541 if (AML_FIELD_ACCESS(flag) != AML_FIELD_BUFFERACC || 2542 bpos & 0x3 || (blen % 8) != 0 || blen > 16) 2543 aml_die("Invalid GenericSerialBus access"); 2544 2545 node = aml_searchname(conn->node, 2546 (char *)&crs->lr_i2cbus.vdata[crs->lr_i2cbus.tlength - 6]); 2547 2548 switch (((flag >> 6) & 0x3)) { 2549 case 0: /* Normal */ 2550 switch (AML_FIELD_ATTR(flag)) { 2551 case 0x02: /* AttribQuick */ 2552 cmdlen = 0; 2553 buflen = 0; 2554 break; 2555 case 0x04: /* AttribSendReceive */ 2556 cmdlen = 0; 2557 buflen = 1; 2558 break; 2559 case 0x06: /* AttribByte */ 2560 cmdlen = blen / 8; 2561 buflen = 1; 2562 break; 2563 case 0x08: /* AttribWord */ 2564 cmdlen = blen / 8; 2565 buflen = 2; 2566 break; 2567 case 0x0b: /* AttribBytes */ 2568 cmdlen = blen / 8; 2569 buflen = len; 2570 break; 2571 case 0x0e: /* AttribRawBytes */ 2572 cmdlen = 0; 2573 buflen = len; 2574 break; 2575 default: 2576 aml_die("unsupported access type 0x%x", flag); 2577 break; 2578 } 2579 break; 2580 case 1: /* AttribBytes */ 2581 cmdlen = blen / 8; 2582 buflen = AML_FIELD_ATTR(flag); 2583 break; 2584 case 2: /* AttribRawBytes */ 2585 cmdlen = 0; 2586 buflen = AML_FIELD_ATTR(flag); 2587 break; 2588 default: 2589 aml_die("unsupported access type 0x%x", flag); 2590 break; 2591 } 2592 2593 if (mode == ACPI_IOREAD) { 2594 _aml_setvalue(val, AML_OBJTYPE_BUFFER, buflen + 2, NULL); 2595 op = I2C_OP_READ_WITH_STOP; 2596 } else { 2597 op = I2C_OP_WRITE_WITH_STOP; 2598 } 2599 2600 buf = val->v_buffer; 2601 2602 /* 2603 * Return an error if we can't find the I2C controller that 2604 * we're supposed to use for this request. 2605 */ 2606 if (node == NULL || node->i2c == NULL) { 2607 buf[0] = EIO; 2608 return; 2609 } 2610 2611 tag = node->i2c; 2612 addr = crs->lr_i2cbus._adr; 2613 cmd[0] = bpos >> 3; 2614 cmd[1] = bpos >> 11; 2615 2616 iic_acquire_bus(tag, 0); 2617 err = iic_exec(tag, op, addr, &cmd, cmdlen, &buf[2], buflen, 0); 2618 iic_release_bus(tag, 0); 2619 2620 /* 2621 * The ACPI specification doesn't tell us what the status 2622 * codes mean beyond implying that zero means success. So use 2623 * the error returned from the transfer. All possible error 2624 * numbers should fit in a single byte. 2625 */ 2626 buf[0] = err; 2627 } 2628 2629 #else 2630 2631 /* 2632 * We don't support GenericSerialBus in RAMDISK kernels. Provide a 2633 * dummy implementation that returns a non-zero error status. 2634 */ 2635 2636 void 2637 aml_rwgsb(struct aml_value *conn, int len, int bpos, int blen, 2638 struct aml_value *val, int mode, int flag) 2639 { 2640 int buflen; 2641 uint8_t *buf; 2642 2643 if (AML_FIELD_ACCESS(flag) != AML_FIELD_BUFFERACC || 2644 bpos & 0x3 || (blen % 8) != 0 || blen > 16) 2645 aml_die("Invalid GenericSerialBus access"); 2646 2647 switch (((flag >> 6) & 0x3)) { 2648 case 0: /* Normal */ 2649 switch (AML_FIELD_ATTR(flag)) { 2650 case 0x02: /* AttribQuick */ 2651 buflen = 0; 2652 break; 2653 case 0x04: /* AttribSendReceive */ 2654 case 0x06: /* AttribByte */ 2655 buflen = 1; 2656 break; 2657 case 0x08: /* AttribWord */ 2658 buflen = 2; 2659 break; 2660 case 0x0b: /* AttribBytes */ 2661 case 0x0e: /* AttribRawBytes */ 2662 buflen = len; 2663 break; 2664 default: 2665 aml_die("unsupported access type 0x%x", flag); 2666 break; 2667 } 2668 break; 2669 case 1: /* AttribBytes */ 2670 case 2: /* AttribRawBytes */ 2671 buflen = AML_FIELD_ATTR(flag); 2672 break; 2673 default: 2674 aml_die("unsupported access type 0x%x", flag); 2675 break; 2676 } 2677 2678 if (mode == ACPI_IOREAD) 2679 _aml_setvalue(val, AML_OBJTYPE_BUFFER, buflen + 2, NULL); 2680 2681 buf = val->v_buffer; 2682 buf[0] = EIO; 2683 } 2684 2685 #endif 2686 2687 void 2688 aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode) 2689 { 2690 struct aml_value tmp, *ref1, *ref2; 2691 void *tbit, *vbit; 2692 int vpos, bpos, blen; 2693 int indexval; 2694 int sz, len; 2695 2696 ref2 = fld->v_field.ref2; 2697 ref1 = fld->v_field.ref1; 2698 bpos = fld->v_field.bitpos; 2699 blen = fld->v_field.bitlen; 2700 2701 memset(&tmp, 0, sizeof(tmp)); 2702 tmp.refcnt = 99; 2703 2704 /* Get field access size */ 2705 switch (AML_FIELD_ACCESS(fld->v_field.flags)) { 2706 case AML_FIELD_WORDACC: 2707 sz = 2; 2708 break; 2709 case AML_FIELD_DWORDACC: 2710 sz = 4; 2711 break; 2712 case AML_FIELD_QWORDACC: 2713 sz = 8; 2714 break; 2715 default: 2716 sz = 1; 2717 break; 2718 } 2719 2720 if (blen > aml_intlen) { 2721 if (mode == ACPI_IOREAD) { 2722 /* Read from a large field: create buffer */ 2723 _aml_setvalue(val, AML_OBJTYPE_BUFFER, 2724 (blen + 7) >> 3, 0); 2725 } 2726 vbit = val->v_buffer; 2727 } else { 2728 if (mode == ACPI_IOREAD) { 2729 /* Read from a short field: initialize integer */ 2730 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2731 } 2732 vbit = &val->v_integer; 2733 } 2734 tbit = &tmp.v_integer; 2735 vpos = 0; 2736 2737 indexval = (bpos >> 3) & ~(sz - 1); 2738 bpos = bpos - (indexval << 3); 2739 2740 while (blen > 0) { 2741 len = min(blen, (sz << 3) - bpos); 2742 2743 /* Write index register */ 2744 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, indexval, 0); 2745 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2746 indexval += sz; 2747 2748 /* Read/write data register */ 2749 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, 0, 0); 2750 if (mode == ACPI_IOWRITE) 2751 aml_bufcpy(tbit, 0, vbit, vpos, len); 2752 aml_rwfield(ref1, bpos, len, &tmp, mode); 2753 if (mode == ACPI_IOREAD) 2754 aml_bufcpy(vbit, vpos, tbit, 0, len); 2755 vpos += len; 2756 blen -= len; 2757 bpos = 0; 2758 } 2759 } 2760 2761 void 2762 aml_rwfield(struct aml_value *fld, int bpos, int blen, struct aml_value *val, 2763 int mode) 2764 { 2765 struct aml_value tmp, *ref1, *ref2; 2766 2767 ref2 = fld->v_field.ref2; 2768 ref1 = fld->v_field.ref1; 2769 if (blen > fld->v_field.bitlen) 2770 blen = fld->v_field.bitlen; 2771 2772 aml_lockfield(NULL, fld); 2773 memset(&tmp, 0, sizeof(tmp)); 2774 aml_addref(&tmp, "fld.write"); 2775 if (fld->v_field.type == AMLOP_INDEXFIELD) { 2776 aml_rwindexfield(fld, val, mode); 2777 } else if (fld->v_field.type == AMLOP_BANKFIELD) { 2778 _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, fld->v_field.ref3, 0); 2779 aml_rwfield(ref2, 0, aml_intlen, &tmp, ACPI_IOWRITE); 2780 aml_rwgen(ref1, fld->v_field.bitpos, fld->v_field.bitlen, 2781 val, mode, fld->v_field.flags); 2782 } else if (fld->v_field.type == AMLOP_FIELD) { 2783 switch (ref1->v_opregion.iospace) { 2784 case ACPI_OPREG_GPIO: 2785 aml_rwgpio(ref2, bpos, blen, val, mode, 2786 fld->v_field.flags); 2787 break; 2788 case ACPI_OPREG_GSB: 2789 aml_rwgsb(ref2, fld->v_field.ref3, 2790 fld->v_field.bitpos + bpos, blen, 2791 val, mode, fld->v_field.flags); 2792 break; 2793 default: 2794 aml_rwgen(ref1, fld->v_field.bitpos + bpos, blen, 2795 val, mode, fld->v_field.flags); 2796 break; 2797 } 2798 } else if (mode == ACPI_IOREAD) { 2799 /* bufferfield:read */ 2800 _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0); 2801 aml_bufcpy(&val->v_integer, 0, ref1->v_buffer, 2802 fld->v_field.bitpos, fld->v_field.bitlen); 2803 } else { 2804 /* bufferfield:write */ 2805 val = aml_convert(val, AML_OBJTYPE_INTEGER, -1); 2806 aml_bufcpy(ref1->v_buffer, fld->v_field.bitpos, &val->v_integer, 2807 0, fld->v_field.bitlen); 2808 aml_delref(&val, "wrbuffld"); 2809 } 2810 aml_unlockfield(NULL, fld); 2811 } 2812 2813 /* Create Field Object data index 2814 * AMLOP_FIELD n:OpRegion NULL 2815 * AMLOP_INDEXFIELD n:Field n:Field 2816 * AMLOP_BANKFIELD n:OpRegion n:Field 2817 * AMLOP_CREATEFIELD t:Buffer NULL 2818 * AMLOP_CREATEBITFIELD t:Buffer NULL 2819 * AMLOP_CREATEBYTEFIELD t:Buffer NULL 2820 * AMLOP_CREATEWORDFIELD t:Buffer NULL 2821 * AMLOP_CREATEDWORDFIELD t:Buffer NULL 2822 * AMLOP_CREATEQWORDFIELD t:Buffer NULL 2823 * AMLOP_INDEX t:Buffer NULL 2824 */ 2825 void 2826 aml_createfield(struct aml_value *field, int opcode, 2827 struct aml_value *data, int bpos, int blen, 2828 struct aml_value *index, int indexval, int flags) 2829 { 2830 dnprintf(10, "## %s(%s): %s %.4x-%.4x\n", 2831 aml_mnem(opcode, 0), 2832 blen > aml_intlen ? "BUF" : "INT", 2833 aml_nodename(field->node), bpos, blen); 2834 if (index) { 2835 dnprintf(10, " index:%s:%.2x\n", aml_nodename(index->node), 2836 indexval); 2837 } 2838 dnprintf(10, " data:%s\n", aml_nodename(data->node)); 2839 field->type = (opcode == AMLOP_FIELD || 2840 opcode == AMLOP_INDEXFIELD || 2841 opcode == AMLOP_BANKFIELD) ? 2842 AML_OBJTYPE_FIELDUNIT : 2843 AML_OBJTYPE_BUFFERFIELD; 2844 2845 if (field->type == AML_OBJTYPE_BUFFERFIELD && 2846 data->type != AML_OBJTYPE_BUFFER) 2847 data = aml_convert(data, AML_OBJTYPE_BUFFER, -1); 2848 2849 field->v_field.type = opcode; 2850 field->v_field.bitpos = bpos; 2851 field->v_field.bitlen = blen; 2852 field->v_field.ref3 = indexval; 2853 field->v_field.ref2 = index; 2854 field->v_field.ref1 = data; 2855 field->v_field.flags = flags; 2856 2857 /* Increase reference count */ 2858 aml_addref(data, "Field.Data"); 2859 aml_addref(index, "Field.Index"); 2860 } 2861 2862 /* Parse Field/IndexField/BankField scope */ 2863 void 2864 aml_parsefieldlist(struct aml_scope *mscope, int opcode, int flags, 2865 struct aml_value *data, struct aml_value *index, int indexval) 2866 { 2867 struct aml_value *conn = NULL; 2868 struct aml_value *rv; 2869 int bpos, blen; 2870 2871 if (mscope == NULL) 2872 return; 2873 bpos = 0; 2874 while (mscope->pos < mscope->end) { 2875 switch (*mscope->pos) { 2876 case 0x00: /* ReservedField */ 2877 mscope->pos++; 2878 blen = aml_parselength(mscope); 2879 break; 2880 case 0x01: /* AccessField */ 2881 mscope->pos++; 2882 blen = 0; 2883 flags = aml_get8(mscope->pos++); 2884 flags |= aml_get8(mscope->pos++) << 8; 2885 break; 2886 case 0x02: /* ConnectionField */ 2887 mscope->pos++; 2888 blen = 0; 2889 conn = aml_parse(mscope, 'o', "Connection"); 2890 if (conn == NULL) 2891 aml_die("Could not parse connection"); 2892 conn->node = mscope->node; 2893 break; 2894 case 0x03: /* ExtendedAccessField */ 2895 mscope->pos++; 2896 blen = 0; 2897 flags = aml_get8(mscope->pos++); 2898 flags |= aml_get8(mscope->pos++) << 8; 2899 indexval = aml_get8(mscope->pos++); 2900 break; 2901 default: /* NamedField */ 2902 mscope->pos = aml_parsename(mscope->node, mscope->pos, 2903 &rv, 1); 2904 blen = aml_parselength(mscope); 2905 aml_createfield(rv, opcode, data, bpos, blen, 2906 conn ? conn : index, indexval, flags); 2907 aml_delref(&rv, 0); 2908 break; 2909 } 2910 bpos += blen; 2911 } 2912 aml_popscope(mscope); 2913 } 2914 2915 /* 2916 * Mutex/Event utility functions 2917 */ 2918 int acpi_mutex_acquire(struct aml_scope *, struct aml_value *, int); 2919 void acpi_mutex_release(struct aml_scope *, struct aml_value *); 2920 int acpi_event_wait(struct aml_scope *, struct aml_value *, int); 2921 void acpi_event_signal(struct aml_scope *, struct aml_value *); 2922 void acpi_event_reset(struct aml_scope *, struct aml_value *); 2923 2924 int 2925 acpi_mutex_acquire(struct aml_scope *scope, struct aml_value *mtx, 2926 int timeout) 2927 { 2928 if (mtx->v_mtx.owner == NULL || scope == mtx->v_mtx.owner) { 2929 /* We are now the owner */ 2930 mtx->v_mtx.owner = scope; 2931 if (mtx == aml_global_lock) { 2932 dnprintf(10,"LOCKING GLOBAL\n"); 2933 acpi_glk_enter(); 2934 } 2935 dnprintf(5,"%s acquires mutex %s\n", scope->node->name, 2936 mtx->node->name); 2937 return (0); 2938 } else if (timeout == 0) { 2939 return (-1); 2940 } 2941 /* Wait for mutex */ 2942 return (0); 2943 } 2944 2945 void 2946 acpi_mutex_release(struct aml_scope *scope, struct aml_value *mtx) 2947 { 2948 if (mtx == aml_global_lock) { 2949 dnprintf(10,"UNLOCKING GLOBAL\n"); 2950 acpi_glk_leave(); 2951 } 2952 dnprintf(5, "%s releases mutex %s\n", scope->node->name, 2953 mtx->node->name); 2954 mtx->v_mtx.owner = NULL; 2955 /* Wakeup waiters */ 2956 } 2957 2958 int 2959 acpi_event_wait(struct aml_scope *scope, struct aml_value *evt, int timeout) 2960 { 2961 /* Wait for event to occur; do work in meantime */ 2962 while (evt->v_evt.state == 0 && timeout >= 0) { 2963 if (acpi_dotask(acpi_softc)) 2964 continue; 2965 if (!cold) { 2966 if (rwsleep(evt, &acpi_softc->sc_lck, PWAIT, 2967 "acpievt", 1) == EWOULDBLOCK) { 2968 if (timeout < AML_NO_TIMEOUT) 2969 timeout -= (1000 / hz); 2970 } 2971 } else { 2972 delay(1000); 2973 if (timeout < AML_NO_TIMEOUT) 2974 timeout--; 2975 } 2976 } 2977 if (evt->v_evt.state == 0) 2978 return (-1); 2979 evt->v_evt.state--; 2980 return (0); 2981 } 2982 2983 void 2984 acpi_event_signal(struct aml_scope *scope, struct aml_value *evt) 2985 { 2986 evt->v_evt.state++; 2987 if (evt->v_evt.state > 0) 2988 wakeup_one(evt); 2989 } 2990 2991 void 2992 acpi_event_reset(struct aml_scope *scope, struct aml_value *evt) 2993 { 2994 evt->v_evt.state = 0; 2995 } 2996 2997 /* Store result value into an object */ 2998 void 2999 aml_store(struct aml_scope *scope, struct aml_value *lhs , int64_t ival, 3000 struct aml_value *rhs) 3001 { 3002 struct aml_value tmp; 3003 struct aml_node *node; 3004 int mlen; 3005 3006 /* Already set */ 3007 if (lhs == rhs || lhs == NULL || lhs->type == AML_OBJTYPE_NOTARGET) { 3008 return; 3009 } 3010 memset(&tmp, 0, sizeof(tmp)); 3011 tmp.refcnt=99; 3012 if (rhs == NULL) { 3013 rhs = _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, ival, NULL); 3014 } 3015 if (rhs->type == AML_OBJTYPE_BUFFERFIELD || 3016 rhs->type == AML_OBJTYPE_FIELDUNIT) { 3017 aml_rwfield(rhs, 0, rhs->v_field.bitlen, &tmp, ACPI_IOREAD); 3018 rhs = &tmp; 3019 } 3020 /* Store to LocalX: free value */ 3021 if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7) 3022 aml_freevalue(lhs); 3023 3024 lhs = aml_gettgt(lhs, AMLOP_STORE); 3025 3026 /* Store to LocalX: free value again */ 3027 if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7) 3028 aml_freevalue(lhs); 3029 switch (lhs->type) { 3030 case AML_OBJTYPE_UNINITIALIZED: 3031 aml_copyvalue(lhs, rhs); 3032 break; 3033 case AML_OBJTYPE_BUFFERFIELD: 3034 case AML_OBJTYPE_FIELDUNIT: 3035 aml_rwfield(lhs, 0, lhs->v_field.bitlen, rhs, ACPI_IOWRITE); 3036 break; 3037 case AML_OBJTYPE_DEBUGOBJ: 3038 break; 3039 case AML_OBJTYPE_INTEGER: 3040 rhs = aml_convert(rhs, lhs->type, -1); 3041 lhs->v_integer = rhs->v_integer; 3042 aml_delref(&rhs, "store.int"); 3043 break; 3044 case AML_OBJTYPE_BUFFER: 3045 case AML_OBJTYPE_STRING: 3046 rhs = aml_convert(rhs, lhs->type, -1); 3047 if (lhs->length < rhs->length) { 3048 dnprintf(10, "Overrun! %d,%d\n", 3049 lhs->length, rhs->length); 3050 aml_freevalue(lhs); 3051 _aml_setvalue(lhs, rhs->type, rhs->length, NULL); 3052 } 3053 mlen = min(lhs->length, rhs->length); 3054 memset(lhs->v_buffer, 0x00, lhs->length); 3055 memcpy(lhs->v_buffer, rhs->v_buffer, mlen); 3056 aml_delref(&rhs, "store.bufstr"); 3057 break; 3058 case AML_OBJTYPE_PACKAGE: 3059 /* Convert to LHS type, copy into LHS */ 3060 if (rhs->type != AML_OBJTYPE_PACKAGE) { 3061 aml_die("Copy non-package into package?"); 3062 } 3063 aml_freevalue(lhs); 3064 aml_copyvalue(lhs, rhs); 3065 break; 3066 case AML_OBJTYPE_NAMEREF: 3067 node = __aml_searchname(scope->node, 3068 aml_getname(lhs->v_nameref), 1); 3069 if (node == NULL) { 3070 aml_die("Could not create node %s", 3071 aml_getname(lhs->v_nameref)); 3072 } 3073 aml_copyvalue(node->value, rhs); 3074 break; 3075 case AML_OBJTYPE_METHOD: 3076 /* Method override */ 3077 if (rhs->type != AML_OBJTYPE_INTEGER) { 3078 aml_die("Overriding a method with a non-int?"); 3079 } 3080 aml_freevalue(lhs); 3081 aml_copyvalue(lhs, rhs); 3082 break; 3083 default: 3084 aml_die("Store to default type! %x\n", lhs->type); 3085 break; 3086 } 3087 aml_freevalue(&tmp); 3088 } 3089 3090 #ifdef DDB 3091 /* Disassembler routines */ 3092 void aml_disprintf(void *arg, const char *fmt, ...); 3093 3094 void 3095 aml_disprintf(void *arg, const char *fmt, ...) 3096 { 3097 va_list ap; 3098 3099 va_start(ap, fmt); 3100 vprintf(fmt, ap); 3101 va_end(ap); 3102 } 3103 3104 void 3105 aml_disasm(struct aml_scope *scope, int lvl, 3106 void (*dbprintf)(void *, const char *, ...) 3107 __attribute__((__format__(__kprintf__,2,3))), 3108 void *arg) 3109 { 3110 int pc, opcode; 3111 struct aml_opcode *htab; 3112 uint64_t ival; 3113 struct aml_value *rv, tmp; 3114 uint8_t *end = NULL; 3115 struct aml_scope ms; 3116 char *ch; 3117 char mch[64]; 3118 3119 if (dbprintf == NULL) 3120 dbprintf = aml_disprintf; 3121 3122 pc = aml_pc(scope->pos); 3123 opcode = aml_parseopcode(scope); 3124 htab = aml_findopcode(opcode); 3125 3126 /* Display address + indent */ 3127 if (lvl <= 0x7FFF) { 3128 dbprintf(arg, "%.4x ", pc); 3129 for (pc=0; pc<lvl; pc++) { 3130 dbprintf(arg, " "); 3131 } 3132 } 3133 ch = NULL; 3134 switch (opcode) { 3135 case AMLOP_NAMECHAR: 3136 scope->pos = aml_parsename(scope->node, scope->pos, &rv, 0); 3137 if (rv->type == AML_OBJTYPE_NAMEREF) { 3138 ch = "@@@"; 3139 aml_delref(&rv, "disasm"); 3140 break; 3141 } 3142 /* if this is a method, get arguments */ 3143 strlcpy(mch, aml_nodename(rv->node), sizeof(mch)); 3144 if (rv->type == AML_OBJTYPE_METHOD) { 3145 strlcat(mch, "(", sizeof(mch)); 3146 for (ival=0; 3147 ival < AML_METHOD_ARGCOUNT(rv->v_method.flags); 3148 ival++) { 3149 strlcat(mch, ival ? ", %z" : "%z", 3150 sizeof(mch)); 3151 } 3152 strlcat(mch, ")", sizeof(mch)); 3153 } 3154 aml_delref(&rv, ""); 3155 ch = mch; 3156 break; 3157 3158 case AMLOP_ZERO: 3159 case AMLOP_ONE: 3160 case AMLOP_ONES: 3161 case AMLOP_LOCAL0: 3162 case AMLOP_LOCAL1: 3163 case AMLOP_LOCAL2: 3164 case AMLOP_LOCAL3: 3165 case AMLOP_LOCAL4: 3166 case AMLOP_LOCAL5: 3167 case AMLOP_LOCAL6: 3168 case AMLOP_LOCAL7: 3169 case AMLOP_ARG0: 3170 case AMLOP_ARG1: 3171 case AMLOP_ARG2: 3172 case AMLOP_ARG3: 3173 case AMLOP_ARG4: 3174 case AMLOP_ARG5: 3175 case AMLOP_ARG6: 3176 case AMLOP_NOP: 3177 case AMLOP_REVISION: 3178 case AMLOP_DEBUG: 3179 case AMLOP_CONTINUE: 3180 case AMLOP_BREAKPOINT: 3181 case AMLOP_BREAK: 3182 ch="%m"; 3183 break; 3184 case AMLOP_BYTEPREFIX: 3185 ch="%b"; 3186 break; 3187 case AMLOP_WORDPREFIX: 3188 ch="%w"; 3189 break; 3190 case AMLOP_DWORDPREFIX: 3191 ch="%d"; 3192 break; 3193 case AMLOP_QWORDPREFIX: 3194 ch="%q"; 3195 break; 3196 case AMLOP_STRINGPREFIX: 3197 ch="%a"; 3198 break; 3199 3200 case AMLOP_INCREMENT: 3201 case AMLOP_DECREMENT: 3202 case AMLOP_LNOT: 3203 case AMLOP_SIZEOF: 3204 case AMLOP_DEREFOF: 3205 case AMLOP_REFOF: 3206 case AMLOP_OBJECTTYPE: 3207 case AMLOP_UNLOAD: 3208 case AMLOP_RELEASE: 3209 case AMLOP_SIGNAL: 3210 case AMLOP_RESET: 3211 case AMLOP_STALL: 3212 case AMLOP_SLEEP: 3213 case AMLOP_RETURN: 3214 ch="%m(%n)"; 3215 break; 3216 case AMLOP_OR: 3217 case AMLOP_ADD: 3218 case AMLOP_AND: 3219 case AMLOP_NAND: 3220 case AMLOP_XOR: 3221 case AMLOP_SHL: 3222 case AMLOP_SHR: 3223 case AMLOP_NOR: 3224 case AMLOP_MOD: 3225 case AMLOP_SUBTRACT: 3226 case AMLOP_MULTIPLY: 3227 case AMLOP_INDEX: 3228 case AMLOP_CONCAT: 3229 case AMLOP_CONCATRES: 3230 case AMLOP_TOSTRING: 3231 ch="%m(%n, %n, %n)"; 3232 break; 3233 case AMLOP_CREATEBYTEFIELD: 3234 case AMLOP_CREATEWORDFIELD: 3235 case AMLOP_CREATEDWORDFIELD: 3236 case AMLOP_CREATEQWORDFIELD: 3237 case AMLOP_CREATEBITFIELD: 3238 ch="%m(%n, %n, %N)"; 3239 break; 3240 case AMLOP_CREATEFIELD: 3241 ch="%m(%n, %n, %n, %N)"; 3242 break; 3243 case AMLOP_DIVIDE: 3244 case AMLOP_MID: 3245 ch="%m(%n, %n, %n, %n)"; 3246 break; 3247 case AMLOP_LAND: 3248 case AMLOP_LOR: 3249 case AMLOP_LNOTEQUAL: 3250 case AMLOP_LLESSEQUAL: 3251 case AMLOP_LLESS: 3252 case AMLOP_LEQUAL: 3253 case AMLOP_LGREATEREQUAL: 3254 case AMLOP_LGREATER: 3255 case AMLOP_NOT: 3256 case AMLOP_FINDSETLEFTBIT: 3257 case AMLOP_FINDSETRIGHTBIT: 3258 case AMLOP_TOINTEGER: 3259 case AMLOP_TOBUFFER: 3260 case AMLOP_TOHEXSTRING: 3261 case AMLOP_TODECSTRING: 3262 case AMLOP_FROMBCD: 3263 case AMLOP_TOBCD: 3264 case AMLOP_WAIT: 3265 case AMLOP_LOAD: 3266 case AMLOP_STORE: 3267 case AMLOP_NOTIFY: 3268 case AMLOP_COPYOBJECT: 3269 ch="%m(%n, %n)"; 3270 break; 3271 case AMLOP_ACQUIRE: 3272 ch = "%m(%n, %w)"; 3273 break; 3274 case AMLOP_CONDREFOF: 3275 ch="%m(%R, %n)"; 3276 break; 3277 case AMLOP_ALIAS: 3278 ch="%m(%n, %N)"; 3279 break; 3280 case AMLOP_NAME: 3281 ch="%m(%N, %n)"; 3282 break; 3283 case AMLOP_EVENT: 3284 ch="%m(%N)"; 3285 break; 3286 case AMLOP_MUTEX: 3287 ch = "%m(%N, %b)"; 3288 break; 3289 case AMLOP_OPREGION: 3290 ch = "%m(%N, %b, %n, %n)"; 3291 break; 3292 case AMLOP_DATAREGION: 3293 ch="%m(%N, %n, %n, %n)"; 3294 break; 3295 case AMLOP_FATAL: 3296 ch = "%m(%b, %d, %n)"; 3297 break; 3298 case AMLOP_IF: 3299 case AMLOP_WHILE: 3300 case AMLOP_SCOPE: 3301 case AMLOP_THERMALZONE: 3302 case AMLOP_VARPACKAGE: 3303 end = aml_parseend(scope); 3304 ch = "%m(%n) {\n%T}"; 3305 break; 3306 case AMLOP_DEVICE: 3307 end = aml_parseend(scope); 3308 ch = "%m(%N) {\n%T}"; 3309 break; 3310 case AMLOP_POWERRSRC: 3311 end = aml_parseend(scope); 3312 ch = "%m(%N, %b, %w) {\n%T}"; 3313 break; 3314 case AMLOP_PROCESSOR: 3315 end = aml_parseend(scope); 3316 ch = "%m(%N, %b, %d, %b) {\n%T}"; 3317 break; 3318 case AMLOP_METHOD: 3319 end = aml_parseend(scope); 3320 ch = "%m(%N, %b) {\n%T}"; 3321 break; 3322 case AMLOP_PACKAGE: 3323 end = aml_parseend(scope); 3324 ch = "%m(%b) {\n%T}"; 3325 break; 3326 case AMLOP_ELSE: 3327 end = aml_parseend(scope); 3328 ch = "%m {\n%T}"; 3329 break; 3330 case AMLOP_BUFFER: 3331 end = aml_parseend(scope); 3332 ch = "%m(%n) { %B }"; 3333 break; 3334 case AMLOP_INDEXFIELD: 3335 end = aml_parseend(scope); 3336 ch = "%m(%n, %n, %b) {\n%F}"; 3337 break; 3338 case AMLOP_BANKFIELD: 3339 end = aml_parseend(scope); 3340 ch = "%m(%n, %n, %n, %b) {\n%F}"; 3341 break; 3342 case AMLOP_FIELD: 3343 end = aml_parseend(scope); 3344 ch = "%m(%n, %b) {\n%F}"; 3345 break; 3346 case AMLOP_MATCH: 3347 ch = "%m(%n, %b, %n, %b, %n, %n)"; 3348 break; 3349 case AMLOP_LOADTABLE: 3350 ch = "%m(%n, %n, %n, %n, %n, %n)"; 3351 break; 3352 default: 3353 aml_die("opcode = %x\n", opcode); 3354 break; 3355 } 3356 3357 /* Parse printable buffer args */ 3358 while (ch && *ch) { 3359 char c; 3360 3361 if (*ch != '%') { 3362 dbprintf(arg,"%c", *(ch++)); 3363 continue; 3364 } 3365 c = *(++ch); 3366 switch (c) { 3367 case 'b': 3368 case 'w': 3369 case 'd': 3370 case 'q': 3371 /* Parse simple object: don't allocate */ 3372 aml_parsesimple(scope, c, &tmp); 3373 dbprintf(arg,"0x%llx", tmp.v_integer); 3374 break; 3375 case 'a': 3376 dbprintf(arg, "\'%s\'", scope->pos); 3377 scope->pos += strlen(scope->pos)+1; 3378 break; 3379 case 'N': 3380 /* Create Name */ 3381 rv = aml_parsesimple(scope, c, NULL); 3382 dbprintf(arg, "%s", aml_nodename(rv->node)); 3383 break; 3384 case 'm': 3385 /* display mnemonic */ 3386 dbprintf(arg, "%s", htab->mnem); 3387 break; 3388 case 'R': 3389 /* Search name */ 3390 printf("%s", aml_getname(scope->pos)); 3391 scope->pos = aml_parsename(scope->node, scope->pos, 3392 &rv, 0); 3393 aml_delref(&rv, 0); 3394 break; 3395 case 'z': 3396 case 'n': 3397 /* generic arg: recurse */ 3398 aml_disasm(scope, lvl | 0x8000, dbprintf, arg); 3399 break; 3400 case 'B': 3401 /* Buffer */ 3402 scope->pos = end; 3403 break; 3404 case 'F': 3405 /* Scope: Field List */ 3406 memset(&ms, 0, sizeof(ms)); 3407 ms.node = scope->node; 3408 ms.start = scope->pos; 3409 ms.end = end; 3410 ms.pos = ms.start; 3411 ms.type = AMLOP_FIELD; 3412 3413 while (ms.pos < ms.end) { 3414 if (*ms.pos == 0x00) { 3415 ms.pos++; 3416 aml_parselength(&ms); 3417 } else if (*ms.pos == 0x01) { 3418 ms.pos+=3; 3419 } else { 3420 ms.pos = aml_parsename(ms.node, 3421 ms.pos, &rv, 1); 3422 aml_parselength(&ms); 3423 dbprintf(arg," %s\n", 3424 aml_nodename(rv->node)); 3425 aml_delref(&rv, 0); 3426 } 3427 } 3428 3429 /* Display address and closing bracket */ 3430 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 3431 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 3432 dbprintf(arg," "); 3433 } 3434 scope->pos = end; 3435 break; 3436 case 'T': 3437 /* Scope: Termlist */ 3438 memset(&ms, 0, sizeof(ms)); 3439 ms.node = scope->node; 3440 ms.start = scope->pos; 3441 ms.end = end; 3442 ms.pos = ms.start; 3443 ms.type = AMLOP_SCOPE; 3444 3445 while (ms.pos < ms.end) { 3446 aml_disasm(&ms, (lvl + 1) & 0x7FFF, 3447 dbprintf, arg); 3448 } 3449 3450 /* Display address and closing bracket */ 3451 dbprintf(arg,"%.4x ", aml_pc(scope->pos)); 3452 for (pc=0; pc<(lvl & 0x7FFF); pc++) { 3453 dbprintf(arg," "); 3454 } 3455 scope->pos = end; 3456 break; 3457 } 3458 ch++; 3459 } 3460 if (lvl <= 0x7FFF) { 3461 dbprintf(arg,"\n"); 3462 } 3463 } 3464 #endif /* DDB */ 3465 3466 int aml_busy; 3467 3468 /* Evaluate method or buffervalue objects */ 3469 struct aml_value * 3470 aml_eval(struct aml_scope *scope, struct aml_value *my_ret, int ret_type, 3471 int argc, struct aml_value *argv) 3472 { 3473 struct aml_value *tmp = my_ret; 3474 struct aml_scope *ms; 3475 int idx; 3476 3477 switch (tmp->type) { 3478 case AML_OBJTYPE_NAMEREF: 3479 my_ret = aml_seterror(scope, "Undefined name: %s", 3480 aml_getname(my_ret->v_nameref)); 3481 break; 3482 case AML_OBJTYPE_METHOD: 3483 dnprintf(10,"\n--== Eval Method [%s, %d args] to %c ==--\n", 3484 aml_nodename(tmp->node), 3485 AML_METHOD_ARGCOUNT(tmp->v_method.flags), 3486 ret_type); 3487 ms = aml_pushscope(scope, tmp, tmp->node, AMLOP_METHOD); 3488 3489 /* Parse method arguments */ 3490 for (idx=0; idx<AML_METHOD_ARGCOUNT(tmp->v_method.flags); idx++) { 3491 struct aml_value *sp; 3492 3493 sp = aml_getstack(ms, AMLOP_ARG0+idx); 3494 if (argv) { 3495 aml_copyvalue(sp, &argv[idx]); 3496 } else { 3497 _aml_setvalue(sp, AML_OBJTYPE_OBJREF, AMLOP_ARG0 + idx, 0); 3498 sp->v_objref.ref = aml_parse(scope, 't', "ARGX"); 3499 } 3500 } 3501 #ifdef ACPI_DEBUG 3502 aml_showstack(ms); 3503 #endif 3504 3505 /* Evaluate method scope */ 3506 aml_root.start = tmp->v_method.base; 3507 if (tmp->v_method.fneval != NULL) { 3508 my_ret = tmp->v_method.fneval(ms, NULL); 3509 } else { 3510 aml_parse(ms, 'T', "METHEVAL"); 3511 my_ret = ms->retv; 3512 } 3513 dnprintf(10,"\n--==Finished evaluating method: %s %c\n", 3514 aml_nodename(tmp->node), ret_type); 3515 #ifdef ACPI_DEBUG 3516 aml_showvalue(my_ret); 3517 aml_showstack(ms); 3518 #endif 3519 aml_popscope(ms); 3520 break; 3521 case AML_OBJTYPE_BUFFERFIELD: 3522 case AML_OBJTYPE_FIELDUNIT: 3523 my_ret = aml_allocvalue(0,0,NULL); 3524 dnprintf(20,"quick: Convert Bufferfield to %c %p\n", 3525 ret_type, my_ret); 3526 aml_rwfield(tmp, 0, tmp->v_field.bitlen, my_ret, ACPI_IOREAD); 3527 break; 3528 } 3529 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 3530 #ifndef SMALL_KERNEL 3531 aml_showvalue(my_ret); 3532 #endif 3533 aml_die("Not Integer"); 3534 } 3535 return my_ret; 3536 } 3537 3538 /* 3539 * The following opcodes produce return values 3540 * TOSTRING -> Str 3541 * TOHEXSTR -> Str 3542 * TODECSTR -> Str 3543 * STRINGPFX -> Str 3544 * BUFFER -> Buf 3545 * CONCATRES -> Buf 3546 * TOBUFFER -> Buf 3547 * MID -> Buf|Str 3548 * CONCAT -> Buf|Str 3549 * PACKAGE -> Pkg 3550 * VARPACKAGE -> Pkg 3551 * LOCALx -> Obj 3552 * ARGx -> Obj 3553 * NAMECHAR -> Obj 3554 * REFOF -> ObjRef 3555 * INDEX -> ObjRef 3556 * DEREFOF -> DataRefObj 3557 * COPYOBJECT -> DataRefObj 3558 * STORE -> DataRefObj 3559 3560 * ZERO -> Int 3561 * ONE -> Int 3562 * ONES -> Int 3563 * REVISION -> Int 3564 * B/W/D/Q -> Int 3565 * OR -> Int 3566 * AND -> Int 3567 * ADD -> Int 3568 * NAND -> Int 3569 * XOR -> Int 3570 * SHL -> Int 3571 * SHR -> Int 3572 * NOR -> Int 3573 * MOD -> Int 3574 * SUBTRACT -> Int 3575 * MULTIPLY -> Int 3576 * DIVIDE -> Int 3577 * NOT -> Int 3578 * TOBCD -> Int 3579 * FROMBCD -> Int 3580 * FSLEFTBIT -> Int 3581 * FSRIGHTBIT -> Int 3582 * INCREMENT -> Int 3583 * DECREMENT -> Int 3584 * TOINTEGER -> Int 3585 * MATCH -> Int 3586 * SIZEOF -> Int 3587 * OBJECTTYPE -> Int 3588 * TIMER -> Int 3589 3590 * CONDREFOF -> Bool 3591 * ACQUIRE -> Bool 3592 * WAIT -> Bool 3593 * LNOT -> Bool 3594 * LAND -> Bool 3595 * LOR -> Bool 3596 * LLESS -> Bool 3597 * LEQUAL -> Bool 3598 * LGREATER -> Bool 3599 * LNOTEQUAL -> Bool 3600 * LLESSEQUAL -> Bool 3601 * LGREATEREQ -> Bool 3602 3603 * LOADTABLE -> DDB 3604 * DEBUG -> Debug 3605 3606 * The following opcodes do not generate a return value: 3607 * NOP 3608 * BREAKPOINT 3609 * RELEASE 3610 * RESET 3611 * SIGNAL 3612 * NAME 3613 * ALIAS 3614 * OPREGION 3615 * DATAREGION 3616 * EVENT 3617 * MUTEX 3618 * SCOPE 3619 * DEVICE 3620 * THERMALZONE 3621 * POWERRSRC 3622 * PROCESSOR 3623 * METHOD 3624 * CREATEFIELD 3625 * CREATEBITFIELD 3626 * CREATEBYTEFIELD 3627 * CREATEWORDFIELD 3628 * CREATEDWORDFIELD 3629 * CREATEQWORDFIELD 3630 * FIELD 3631 * INDEXFIELD 3632 * BANKFIELD 3633 * STALL 3634 * SLEEP 3635 * NOTIFY 3636 * FATAL 3637 * LOAD 3638 * UNLOAD 3639 * IF 3640 * ELSE 3641 * WHILE 3642 * BREAK 3643 * CONTINUE 3644 */ 3645 3646 /* Parse a simple object from AML Bytestream */ 3647 struct aml_value * 3648 aml_parsesimple(struct aml_scope *scope, char ch, struct aml_value *rv) 3649 { 3650 if (rv == NULL) 3651 rv = aml_allocvalue(0,0,NULL); 3652 switch (ch) { 3653 case AML_ARG_REVISION: 3654 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, AML_REVISION, NULL); 3655 break; 3656 case AML_ARG_DEBUG: 3657 _aml_setvalue(rv, AML_OBJTYPE_DEBUGOBJ, 0, NULL); 3658 break; 3659 case AML_ARG_BYTE: 3660 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3661 aml_get8(scope->pos), NULL); 3662 scope->pos += 1; 3663 break; 3664 case AML_ARG_WORD: 3665 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3666 aml_get16(scope->pos), NULL); 3667 scope->pos += 2; 3668 break; 3669 case AML_ARG_DWORD: 3670 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3671 aml_get32(scope->pos), NULL); 3672 scope->pos += 4; 3673 break; 3674 case AML_ARG_QWORD: 3675 _aml_setvalue(rv, AML_OBJTYPE_INTEGER, 3676 aml_get64(scope->pos), NULL); 3677 scope->pos += 8; 3678 break; 3679 case AML_ARG_STRING: 3680 _aml_setvalue(rv, AML_OBJTYPE_STRING, -1, scope->pos); 3681 scope->pos += rv->length+1; 3682 break; 3683 } 3684 return rv; 3685 } 3686 3687 /* 3688 * Main Opcode Parser/Evaluator 3689 * 3690 * ret_type is expected type for return value 3691 * 'o' = Data Object (Int/Str/Buf/Pkg/Name) 3692 * 'i' = Integer 3693 * 't' = TermArg (Int/Str/Buf/Pkg) 3694 * 'r' = Target (NamedObj/Local/Arg/Null) 3695 * 'S' = SuperName (NamedObj/Local/Arg) 3696 * 'T' = TermList 3697 */ 3698 #define aml_debugger(x) 3699 3700 int maxdp; 3701 3702 struct aml_value * 3703 aml_gettgt(struct aml_value *val, int opcode) 3704 { 3705 while (val && val->type == AML_OBJTYPE_OBJREF) { 3706 val = val->v_objref.ref; 3707 } 3708 return val; 3709 } 3710 3711 struct aml_value * 3712 aml_seterror(struct aml_scope *scope, const char *fmt, ...) 3713 { 3714 va_list ap; 3715 3716 va_start(ap, fmt); 3717 printf("### AML PARSE ERROR (0x%x): ", aml_pc(scope->pos)); 3718 vprintf(fmt, ap); 3719 printf("\n"); 3720 va_end(ap); 3721 3722 while (scope) { 3723 scope->pos = scope->end; 3724 scope = scope->parent; 3725 } 3726 aml_error++; 3727 return aml_allocvalue(AML_OBJTYPE_INTEGER, 0, 0); 3728 } 3729 3730 struct aml_value * 3731 aml_loadtable(struct acpi_softc *sc, const char *signature, 3732 const char *oemid, const char *oemtableid, const char *rootpath, 3733 const char *parameterpath, struct aml_value *parameterdata) 3734 { 3735 struct acpi_table_header *hdr; 3736 struct acpi_dsdt *p_dsdt; 3737 struct acpi_q *entry; 3738 3739 if (strlen(parameterpath) > 0) 3740 aml_die("LoadTable: ParameterPathString unsupported"); 3741 3742 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) { 3743 hdr = entry->q_table; 3744 if (strncmp(hdr->signature, signature, 3745 sizeof(hdr->signature)) == 0 && 3746 strncmp(hdr->oemid, oemid, sizeof(hdr->oemid)) == 0 && 3747 strncmp(hdr->oemtableid, oemtableid, 3748 sizeof(hdr->oemtableid)) == 0) { 3749 p_dsdt = entry->q_table; 3750 acpi_parse_aml(sc, rootpath, p_dsdt->aml, 3751 p_dsdt->hdr_length - sizeof(p_dsdt->hdr)); 3752 return aml_allocvalue(AML_OBJTYPE_DDBHANDLE, 0, 0); 3753 } 3754 } 3755 3756 return aml_allocvalue(AML_OBJTYPE_INTEGER, 0, 0); 3757 } 3758 3759 /* Load new SSDT scope from memory address */ 3760 struct aml_scope * 3761 aml_load(struct acpi_softc *sc, struct aml_scope *scope, 3762 struct aml_value *rgn, struct aml_value *ddb) 3763 { 3764 struct acpi_q *entry; 3765 struct acpi_dsdt *p_ssdt; 3766 struct aml_value tmp; 3767 3768 ddb->type = AML_OBJTYPE_DDBHANDLE; 3769 ddb->v_integer = 0; 3770 3771 memset(&tmp, 0, sizeof(tmp)); 3772 if (rgn->type != AML_OBJTYPE_OPREGION || 3773 rgn->v_opregion.iospace != GAS_SYSTEM_MEMORY) 3774 goto fail; 3775 3776 /* Load SSDT from memory */ 3777 entry = acpi_maptable(sc, rgn->v_opregion.iobase, "SSDT", NULL, NULL, 1); 3778 if (entry == NULL) 3779 goto fail; 3780 3781 dnprintf(10, "%s: loaded SSDT %s @ %llx\n", sc->sc_dev.dv_xname, 3782 aml_nodename(rgn->node), rgn->v_opregion.iobase); 3783 ddb->v_integer = entry->q_id; 3784 3785 p_ssdt = entry->q_table; 3786 tmp.v_buffer = p_ssdt->aml; 3787 tmp.length = p_ssdt->hdr_length - sizeof(p_ssdt->hdr); 3788 3789 return aml_pushscope(scope, &tmp, scope->node, 3790 AMLOP_LOAD); 3791 fail: 3792 printf("%s: unable to load %s\n", sc->sc_dev.dv_xname, 3793 aml_nodename(rgn->node)); 3794 return NULL; 3795 } 3796 3797 struct aml_value * 3798 aml_parse(struct aml_scope *scope, int ret_type, const char *stype) 3799 { 3800 int opcode, idx, pc; 3801 struct aml_opcode *htab; 3802 struct aml_value *opargs[8], *my_ret, *rv; 3803 struct aml_scope *mscope, *iscope; 3804 uint8_t *start, *end; 3805 const char *ch; 3806 int64_t ival; 3807 struct timespec ts; 3808 3809 my_ret = NULL; 3810 if (scope == NULL || scope->pos >= scope->end) { 3811 return NULL; 3812 } 3813 if (odp++ > 125) 3814 panic("depth"); 3815 if (odp > maxdp) { 3816 maxdp = odp; 3817 dnprintf(10, "max depth: %d\n", maxdp); 3818 } 3819 end = NULL; 3820 iscope = scope; 3821 start: 3822 /* --== Stage 0: Get Opcode ==-- */ 3823 start = scope->pos; 3824 pc = aml_pc(scope->pos); 3825 aml_debugger(scope); 3826 3827 opcode = aml_parseopcode(scope); 3828 htab = aml_findopcode(opcode); 3829 if (htab == NULL) { 3830 /* No opcode handler */ 3831 aml_die("Unknown opcode: %.4x @ %.4x", opcode, pc); 3832 } 3833 dnprintf(18,"%.4x %s\n", pc, aml_mnem(opcode, scope->pos)); 3834 3835 /* --== Stage 1: Process opcode arguments ==-- */ 3836 memset(opargs, 0, sizeof(opargs)); 3837 idx = 0; 3838 for (ch = htab->args; *ch; ch++) { 3839 rv = NULL; 3840 switch (*ch) { 3841 case AML_ARG_OBJLEN: 3842 end = aml_parseend(scope); 3843 break; 3844 case AML_ARG_IFELSE: 3845 /* Special Case: IF-ELSE:piTbpT or IF:piT */ 3846 ch = (*end == AMLOP_ELSE && end < scope->end) ? 3847 "-TbpT" : "-T"; 3848 break; 3849 3850 /* Complex arguments */ 3851 case 's': 3852 case 'S': 3853 case AML_ARG_TARGET: 3854 case AML_ARG_TERMOBJ: 3855 case AML_ARG_INTEGER: 3856 if (*ch == 'r' && *scope->pos == AMLOP_ZERO) { 3857 /* Special case: NULL Target */ 3858 rv = aml_allocvalue(AML_OBJTYPE_NOTARGET, 0, NULL); 3859 scope->pos++; 3860 } 3861 else { 3862 rv = aml_parse(scope, *ch, htab->mnem); 3863 if (rv == NULL || aml_error) 3864 goto parse_error; 3865 } 3866 break; 3867 3868 /* Simple arguments */ 3869 case AML_ARG_BUFFER: 3870 case AML_ARG_METHOD: 3871 case AML_ARG_FIELDLIST: 3872 case AML_ARG_TERMOBJLIST: 3873 rv = aml_allocvalue(AML_OBJTYPE_SCOPE, 0, NULL); 3874 rv->v_buffer = scope->pos; 3875 rv->length = end - scope->pos; 3876 scope->pos = end; 3877 break; 3878 case AML_ARG_CONST: 3879 rv = aml_allocvalue(AML_OBJTYPE_INTEGER, 3880 (char)opcode, NULL); 3881 break; 3882 case AML_ARG_CREATENAME: 3883 scope->pos = aml_parsename(scope->node, scope->pos, 3884 &rv, 1); 3885 break; 3886 case AML_ARG_SEARCHNAME: 3887 scope->pos = aml_parsename(scope->node, scope->pos, 3888 &rv, 0); 3889 break; 3890 case AML_ARG_BYTE: 3891 case AML_ARG_WORD: 3892 case AML_ARG_DWORD: 3893 case AML_ARG_QWORD: 3894 case AML_ARG_DEBUG: 3895 case AML_ARG_STRING: 3896 case AML_ARG_REVISION: 3897 rv = aml_parsesimple(scope, *ch, NULL); 3898 break; 3899 case AML_ARG_STKLOCAL: 3900 case AML_ARG_STKARG: 3901 rv = aml_getstack(scope, opcode); 3902 break; 3903 default: 3904 aml_die("Unknown arg type: %c\n", *ch); 3905 break; 3906 } 3907 if (rv != NULL) 3908 opargs[idx++] = rv; 3909 } 3910 3911 /* --== Stage 2: Process opcode ==-- */ 3912 ival = 0; 3913 my_ret = NULL; 3914 mscope = NULL; 3915 switch (opcode) { 3916 case AMLOP_NOP: 3917 case AMLOP_BREAKPOINT: 3918 break; 3919 case AMLOP_LOCAL0: 3920 case AMLOP_LOCAL1: 3921 case AMLOP_LOCAL2: 3922 case AMLOP_LOCAL3: 3923 case AMLOP_LOCAL4: 3924 case AMLOP_LOCAL5: 3925 case AMLOP_LOCAL6: 3926 case AMLOP_LOCAL7: 3927 case AMLOP_ARG0: 3928 case AMLOP_ARG1: 3929 case AMLOP_ARG2: 3930 case AMLOP_ARG3: 3931 case AMLOP_ARG4: 3932 case AMLOP_ARG5: 3933 case AMLOP_ARG6: 3934 my_ret = opargs[0]; 3935 aml_addref(my_ret, htab->mnem); 3936 break; 3937 case AMLOP_NAMECHAR: 3938 /* opargs[0] = named object (node != NULL), or nameref */ 3939 my_ret = opargs[0]; 3940 if (scope->type == AMLOP_PACKAGE && my_ret->node) { 3941 /* Special case for package */ 3942 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, 3943 AMLOP_NAMECHAR, 0); 3944 my_ret->v_objref.ref = opargs[0]; 3945 aml_addref(my_ret, "package"); 3946 } else if (my_ret->type == AML_OBJTYPE_OBJREF) { 3947 my_ret = my_ret->v_objref.ref; 3948 aml_addref(my_ret, "de-alias"); 3949 } 3950 if (ret_type == 'i' || ret_type == 't' || ret_type == 'T') { 3951 /* Return TermArg or Integer: Evaluate object */ 3952 my_ret = aml_eval(scope, my_ret, ret_type, 0, NULL); 3953 } else if (my_ret->type == AML_OBJTYPE_METHOD) { 3954 /* This should only happen with CondRef */ 3955 dnprintf(12,"non-termarg method : %s\n", stype); 3956 aml_addref(my_ret, "zoom"); 3957 } 3958 break; 3959 3960 case AMLOP_ZERO: 3961 case AMLOP_ONE: 3962 case AMLOP_ONES: 3963 case AMLOP_DEBUG: 3964 case AMLOP_REVISION: 3965 case AMLOP_BYTEPREFIX: 3966 case AMLOP_WORDPREFIX: 3967 case AMLOP_DWORDPREFIX: 3968 case AMLOP_QWORDPREFIX: 3969 case AMLOP_STRINGPREFIX: 3970 my_ret = opargs[0]; 3971 break; 3972 3973 case AMLOP_BUFFER: 3974 /* Buffer: iB => Buffer */ 3975 my_ret = aml_allocvalue(AML_OBJTYPE_BUFFER, 3976 opargs[0]->v_integer, NULL); 3977 memcpy(my_ret->v_buffer, opargs[1]->v_buffer, 3978 opargs[1]->length); 3979 break; 3980 case AMLOP_PACKAGE: 3981 case AMLOP_VARPACKAGE: 3982 /* Package/VarPackage: bT/iT => Package */ 3983 my_ret = aml_allocvalue(AML_OBJTYPE_PACKAGE, 3984 opargs[0]->v_integer, 0); 3985 mscope = aml_pushscope(scope, opargs[1], scope->node, 3986 AMLOP_PACKAGE); 3987 3988 /* Recursively parse package contents */ 3989 for (idx=0; idx<my_ret->length; idx++) { 3990 rv = aml_parse(mscope, 'o', "Package"); 3991 if (rv != NULL) { 3992 aml_delref(&my_ret->v_package[idx], "pkginit"); 3993 my_ret->v_package[idx] = rv; 3994 } 3995 } 3996 aml_popscope(mscope); 3997 mscope = NULL; 3998 break; 3999 4000 /* Math/Logical operations */ 4001 case AMLOP_OR: 4002 case AMLOP_ADD: 4003 case AMLOP_AND: 4004 case AMLOP_NAND: 4005 case AMLOP_XOR: 4006 case AMLOP_SHL: 4007 case AMLOP_SHR: 4008 case AMLOP_NOR: 4009 case AMLOP_MOD: 4010 case AMLOP_SUBTRACT: 4011 case AMLOP_MULTIPLY: 4012 /* XXX: iir => I */ 4013 ival = aml_evalexpr(opargs[0]->v_integer, 4014 opargs[1]->v_integer, opcode); 4015 aml_store(scope, opargs[2], ival, NULL); 4016 break; 4017 case AMLOP_DIVIDE: 4018 /* Divide: iirr => I */ 4019 if (opargs[1]->v_integer == 0) { 4020 my_ret = aml_seterror(scope, "Divide by Zero!"); 4021 break; 4022 } 4023 ival = aml_evalexpr(opargs[0]->v_integer, 4024 opargs[1]->v_integer, AMLOP_MOD); 4025 aml_store(scope, opargs[2], ival, NULL); 4026 4027 ival = aml_evalexpr(opargs[0]->v_integer, 4028 opargs[1]->v_integer, AMLOP_DIVIDE); 4029 aml_store(scope, opargs[3], ival, NULL); 4030 break; 4031 case AMLOP_NOT: 4032 case AMLOP_TOBCD: 4033 case AMLOP_FROMBCD: 4034 case AMLOP_FINDSETLEFTBIT: 4035 case AMLOP_FINDSETRIGHTBIT: 4036 /* XXX: ir => I */ 4037 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 4038 aml_store(scope, opargs[1], ival, NULL); 4039 break; 4040 case AMLOP_INCREMENT: 4041 case AMLOP_DECREMENT: 4042 /* Inc/Dec: S => I */ 4043 my_ret = aml_eval(scope, opargs[0], AML_ARG_INTEGER, 0, NULL); 4044 ival = aml_evalexpr(my_ret->v_integer, 1, opcode); 4045 aml_store(scope, opargs[0], ival, NULL); 4046 break; 4047 case AMLOP_LNOT: 4048 /* LNot: i => Bool */ 4049 ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); 4050 break; 4051 case AMLOP_LOR: 4052 case AMLOP_LAND: 4053 /* XXX: ii => Bool */ 4054 ival = aml_evalexpr(opargs[0]->v_integer, 4055 opargs[1]->v_integer, opcode); 4056 break; 4057 case AMLOP_LLESS: 4058 case AMLOP_LEQUAL: 4059 case AMLOP_LGREATER: 4060 case AMLOP_LNOTEQUAL: 4061 case AMLOP_LLESSEQUAL: 4062 case AMLOP_LGREATEREQUAL: 4063 /* XXX: tt => Bool */ 4064 ival = aml_compare(opargs[0], opargs[1], opcode); 4065 break; 4066 4067 /* Reference/Store operations */ 4068 case AMLOP_CONDREFOF: 4069 /* CondRef: rr => I */ 4070 ival = 0; 4071 if (opargs[0]->node != NULL) { 4072 /* Create Object Reference */ 4073 rv = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, 4074 opargs[0]); 4075 aml_addref(opargs[0], "CondRef"); 4076 aml_store(scope, opargs[1], 0, rv); 4077 aml_delref(&rv, 0); 4078 4079 /* Mark that we found it */ 4080 ival = -1; 4081 } 4082 break; 4083 case AMLOP_REFOF: 4084 /* RefOf: r => ObjRef */ 4085 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, opcode, opargs[0]); 4086 aml_addref(my_ret->v_objref.ref, "RefOf"); 4087 break; 4088 case AMLOP_INDEX: 4089 /* Index: tir => ObjRef */ 4090 idx = opargs[1]->v_integer; 4091 /* Reading past the end of the array? - Ignore */ 4092 if (idx >= opargs[0]->length || idx < 0) 4093 break; 4094 switch (opargs[0]->type) { 4095 case AML_OBJTYPE_PACKAGE: 4096 /* Don't set opargs[0] to NULL */ 4097 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 4098 my_ret = opargs[0]->v_package[idx]; 4099 aml_addref(my_ret, "Index.Package"); 4100 } else { 4101 my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, AMLOP_PACKAGE, 4102 opargs[0]->v_package[idx]); 4103 aml_addref(my_ret->v_objref.ref, 4104 "Index.Package"); 4105 } 4106 break; 4107 case AML_OBJTYPE_BUFFER: 4108 case AML_OBJTYPE_STRING: 4109 case AML_OBJTYPE_INTEGER: 4110 rv = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 4111 if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { 4112 dnprintf(12,"Index.Buf Term: %d = %x\n", 4113 idx, rv->v_buffer[idx]); 4114 ival = rv->v_buffer[idx]; 4115 } else { 4116 dnprintf(12, "Index.Buf Targ\n"); 4117 my_ret = aml_allocvalue(0,0,NULL); 4118 aml_createfield(my_ret, AMLOP_INDEX, rv, 4119 8 * idx, 8, NULL, 0, AML_FIELD_BYTEACC); 4120 } 4121 aml_delref(&rv, "Index.BufStr"); 4122 break; 4123 default: 4124 aml_die("Unknown index : %x\n", opargs[0]->type); 4125 break; 4126 } 4127 aml_store(scope, opargs[2], ival, my_ret); 4128 break; 4129 case AMLOP_DEREFOF: 4130 /* DerefOf: t:ObjRef => DataRefObj */ 4131 if (opargs[0]->type == AML_OBJTYPE_OBJREF) { 4132 my_ret = opargs[0]->v_objref.ref; 4133 aml_addref(my_ret, "DerefOf"); 4134 } else { 4135 my_ret = opargs[0]; 4136 //aml_addref(my_ret, "DerefOf"); 4137 } 4138 break; 4139 case AMLOP_COPYOBJECT: 4140 /* CopyObject: t:DataRefObj, s:implename => DataRefObj */ 4141 my_ret = opargs[0]; 4142 aml_freevalue(opargs[1]); 4143 aml_copyvalue(opargs[1], opargs[0]); 4144 break; 4145 case AMLOP_STORE: 4146 /* Store: t:DataRefObj, S:upername => DataRefObj */ 4147 my_ret = opargs[0]; 4148 aml_store(scope, opargs[1], 0, opargs[0]); 4149 break; 4150 4151 /* Conversion */ 4152 case AMLOP_TOINTEGER: 4153 /* Source:CData, Result => Integer */ 4154 my_ret = aml_convert(opargs[0], AML_OBJTYPE_INTEGER, -1); 4155 aml_store(scope, opargs[1], 0, my_ret); 4156 break; 4157 case AMLOP_TOBUFFER: 4158 /* Source:CData, Result => Buffer */ 4159 my_ret = aml_convert(opargs[0], AML_OBJTYPE_BUFFER, -1); 4160 aml_store(scope, opargs[1], 0, my_ret); 4161 break; 4162 case AMLOP_TOHEXSTRING: 4163 /* Source:CData, Result => String */ 4164 my_ret = aml_convert(opargs[0], AML_OBJTYPE_HEXSTRING, -1); 4165 aml_store(scope, opargs[1], 0, my_ret); 4166 break; 4167 case AMLOP_TODECSTRING: 4168 /* Source:CData, Result => String */ 4169 my_ret = aml_convert(opargs[0], AML_OBJTYPE_DECSTRING, -1); 4170 aml_store(scope, opargs[1], 0, my_ret); 4171 break; 4172 case AMLOP_TOSTRING: 4173 /* Source:B, Length:I, Result => String */ 4174 my_ret = aml_convert(opargs[0], AML_OBJTYPE_STRING, 4175 opargs[1]->v_integer); 4176 aml_store(scope, opargs[2], 0, my_ret); 4177 break; 4178 case AMLOP_CONCAT: 4179 /* Source1:CData, Source2:CData, Result => CData */ 4180 my_ret = aml_concat(opargs[0], opargs[1]); 4181 aml_store(scope, opargs[2], 0, my_ret); 4182 break; 4183 case AMLOP_CONCATRES: 4184 /* Concat two resource buffers: buf1, buf2, result => Buffer */ 4185 my_ret = aml_concatres(opargs[0], opargs[1]); 4186 aml_store(scope, opargs[2], 0, my_ret); 4187 break; 4188 case AMLOP_MID: 4189 /* Source:BS, Index:I, Length:I, Result => BS */ 4190 my_ret = aml_mid(opargs[0], opargs[1]->v_integer, 4191 opargs[2]->v_integer); 4192 aml_store(scope, opargs[3], 0, my_ret); 4193 break; 4194 case AMLOP_MATCH: 4195 /* Match: Pkg, Op1, Val1, Op2, Val2, Index */ 4196 ival = aml_match(opargs[0], opargs[5]->v_integer, 4197 opargs[1]->v_integer, opargs[2]->v_integer, 4198 opargs[3]->v_integer, opargs[4]->v_integer); 4199 break; 4200 case AMLOP_SIZEOF: 4201 /* Sizeof: S => i */ 4202 rv = aml_gettgt(opargs[0], opcode); 4203 ival = rv->length; 4204 break; 4205 case AMLOP_OBJECTTYPE: 4206 /* ObjectType: S => i */ 4207 rv = aml_gettgt(opargs[0], opcode); 4208 ival = rv->type; 4209 break; 4210 4211 /* Mutex/Event handlers */ 4212 case AMLOP_ACQUIRE: 4213 /* Acquire: Sw => Bool */ 4214 rv = aml_gettgt(opargs[0], opcode); 4215 ival = acpi_mutex_acquire(scope, rv, 4216 opargs[1]->v_integer); 4217 break; 4218 case AMLOP_RELEASE: 4219 /* Release: S */ 4220 rv = aml_gettgt(opargs[0], opcode); 4221 acpi_mutex_release(scope, rv); 4222 break; 4223 case AMLOP_WAIT: 4224 /* Wait: Si => Bool */ 4225 rv = aml_gettgt(opargs[0], opcode); 4226 ival = acpi_event_wait(scope, rv, 4227 opargs[1]->v_integer); 4228 break; 4229 case AMLOP_RESET: 4230 /* Reset: S */ 4231 rv = aml_gettgt(opargs[0], opcode); 4232 acpi_event_reset(scope, rv); 4233 break; 4234 case AMLOP_SIGNAL: 4235 /* Signal: S */ 4236 rv = aml_gettgt(opargs[0], opcode); 4237 acpi_event_signal(scope, rv); 4238 break; 4239 4240 /* Named objects */ 4241 case AMLOP_NAME: 4242 /* Name: Nt */ 4243 rv = opargs[0]; 4244 aml_freevalue(rv); 4245 aml_copyvalue(rv, opargs[1]); 4246 break; 4247 case AMLOP_ALIAS: 4248 /* Alias: nN */ 4249 rv = _aml_setvalue(opargs[1], AML_OBJTYPE_OBJREF, opcode, 0); 4250 rv->v_objref.ref = aml_gettgt(opargs[0], opcode); 4251 aml_addref(rv->v_objref.ref, "Alias"); 4252 break; 4253 case AMLOP_OPREGION: 4254 /* OpRegion: Nbii */ 4255 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 4256 rv->v_opregion.iospace = opargs[1]->v_integer; 4257 rv->v_opregion.iobase = opargs[2]->v_integer; 4258 rv->v_opregion.iolen = opargs[3]->v_integer; 4259 rv->v_opregion.flag = 0; 4260 break; 4261 case AMLOP_DATAREGION: 4262 /* DataTableRegion: N,t:SigStr,t:OemIDStr,t:OemTableIDStr */ 4263 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_OPREGION, 0, 0); 4264 rv->v_opregion.iospace = GAS_SYSTEM_MEMORY; 4265 rv->v_opregion.iobase = 0; 4266 rv->v_opregion.iolen = 0; 4267 aml_die("AML-DataTableRegion\n"); 4268 break; 4269 case AMLOP_EVENT: 4270 /* Event: N */ 4271 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_EVENT, 0, 0); 4272 rv->v_evt.state = 0; 4273 break; 4274 case AMLOP_MUTEX: 4275 /* Mutex: Nw */ 4276 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_MUTEX, 0, 0); 4277 rv->v_mtx.synclvl = opargs[1]->v_integer; 4278 break; 4279 case AMLOP_SCOPE: 4280 /* Scope: NT */ 4281 rv = opargs[0]; 4282 if (rv->type == AML_OBJTYPE_NAMEREF) { 4283 printf("Undefined scope: %s\n", aml_getname(rv->v_nameref)); 4284 break; 4285 } 4286 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 4287 break; 4288 case AMLOP_DEVICE: 4289 /* Device: NT */ 4290 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_DEVICE, 0, 0); 4291 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 4292 break; 4293 case AMLOP_THERMALZONE: 4294 /* ThermalZone: NT */ 4295 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_THERMZONE, 0, 0); 4296 mscope = aml_pushscope(scope, opargs[1], rv->node, opcode); 4297 break; 4298 case AMLOP_POWERRSRC: 4299 /* PowerRsrc: NbwT */ 4300 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_POWERRSRC, 0, 0); 4301 rv->v_powerrsrc.pwr_level = opargs[1]->v_integer; 4302 rv->v_powerrsrc.pwr_order = opargs[2]->v_integer; 4303 mscope = aml_pushscope(scope, opargs[3], rv->node, opcode); 4304 break; 4305 case AMLOP_PROCESSOR: 4306 /* Processor: NbdbT */ 4307 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_PROCESSOR, 0, 0); 4308 rv->v_processor.proc_id = opargs[1]->v_integer; 4309 rv->v_processor.proc_addr = opargs[2]->v_integer; 4310 rv->v_processor.proc_len = opargs[3]->v_integer; 4311 mscope = aml_pushscope(scope, opargs[4], rv->node, opcode); 4312 break; 4313 case AMLOP_METHOD: 4314 /* Method: NbM */ 4315 rv = _aml_setvalue(opargs[0], AML_OBJTYPE_METHOD, 0, 0); 4316 rv->v_method.flags = opargs[1]->v_integer; 4317 rv->v_method.start = opargs[2]->v_buffer; 4318 rv->v_method.end = rv->v_method.start + opargs[2]->length; 4319 rv->v_method.base = aml_root.start; 4320 break; 4321 4322 /* Field objects */ 4323 case AMLOP_CREATEFIELD: 4324 /* Source:B, BitIndex:I, NumBits:I, FieldName */ 4325 rv = _aml_setvalue(opargs[3], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4326 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 4327 opargs[2]->v_integer, NULL, 0, 0); 4328 break; 4329 case AMLOP_CREATEBITFIELD: 4330 /* Source:B, BitIndex:I, FieldName */ 4331 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4332 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer, 4333 1, NULL, 0, 0); 4334 break; 4335 case AMLOP_CREATEBYTEFIELD: 4336 /* Source:B, ByteIndex:I, FieldName */ 4337 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4338 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 4339 8, NULL, 0, AML_FIELD_BYTEACC); 4340 break; 4341 case AMLOP_CREATEWORDFIELD: 4342 /* Source:B, ByteIndex:I, FieldName */ 4343 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4344 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 4345 16, NULL, 0, AML_FIELD_WORDACC); 4346 break; 4347 case AMLOP_CREATEDWORDFIELD: 4348 /* Source:B, ByteIndex:I, FieldName */ 4349 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4350 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 4351 32, NULL, 0, AML_FIELD_DWORDACC); 4352 break; 4353 case AMLOP_CREATEQWORDFIELD: 4354 /* Source:B, ByteIndex:I, FieldName */ 4355 rv = _aml_setvalue(opargs[2], AML_OBJTYPE_BUFFERFIELD, 0, 0); 4356 aml_createfield(rv, opcode, opargs[0], opargs[1]->v_integer*8, 4357 64, NULL, 0, AML_FIELD_QWORDACC); 4358 break; 4359 case AMLOP_FIELD: 4360 /* Field: n:OpRegion, b:Flags, F:ieldlist */ 4361 mscope = aml_pushscope(scope, opargs[2], scope->node, opcode); 4362 aml_parsefieldlist(mscope, opcode, opargs[1]->v_integer, 4363 opargs[0], NULL, 0); 4364 mscope = NULL; 4365 break; 4366 case AMLOP_INDEXFIELD: 4367 /* IndexField: n:Index, n:Data, b:Flags, F:ieldlist */ 4368 mscope = aml_pushscope(scope, opargs[3], scope->node, opcode); 4369 aml_parsefieldlist(mscope, opcode, opargs[2]->v_integer, 4370 opargs[1], opargs[0], 0); 4371 mscope = NULL; 4372 break; 4373 case AMLOP_BANKFIELD: 4374 /* BankField: n:OpRegion, n:Field, i:Bank, b:Flags, F:ieldlist */ 4375 mscope = aml_pushscope(scope, opargs[4], scope->node, opcode); 4376 aml_parsefieldlist(mscope, opcode, opargs[3]->v_integer, 4377 opargs[0], opargs[1], opargs[2]->v_integer); 4378 mscope = NULL; 4379 break; 4380 4381 /* Misc functions */ 4382 case AMLOP_STALL: 4383 /* Stall: i */ 4384 acpi_stall(opargs[0]->v_integer); 4385 break; 4386 case AMLOP_SLEEP: 4387 /* Sleep: i */ 4388 acpi_sleep(opargs[0]->v_integer, "amlsleep"); 4389 break; 4390 case AMLOP_NOTIFY: 4391 /* Notify: Si */ 4392 rv = aml_gettgt(opargs[0], opcode); 4393 dnprintf(50,"Notifying: %s %llx\n", 4394 aml_nodename(rv->node), 4395 opargs[1]->v_integer); 4396 aml_notify(rv->node, opargs[1]->v_integer); 4397 break; 4398 case AMLOP_TIMER: 4399 /* Timer: => i */ 4400 nanouptime(&ts); 4401 ival = ts.tv_sec * 10000000 + ts.tv_nsec / 100; 4402 break; 4403 case AMLOP_FATAL: 4404 /* Fatal: bdi */ 4405 aml_die("AML FATAL ERROR: %x,%x,%x\n", 4406 opargs[0]->v_integer, opargs[1]->v_integer, 4407 opargs[2]->v_integer); 4408 break; 4409 case AMLOP_LOADTABLE: 4410 /* LoadTable(Sig:Str, OEMID:Str, OEMTable:Str, [RootPath:Str], [ParmPath:Str], 4411 [ParmData:DataRefObj]) => DDBHandle */ 4412 my_ret = aml_loadtable(acpi_softc, opargs[0]->v_string, 4413 opargs[1]->v_string, opargs[2]->v_string, 4414 opargs[3]->v_string, opargs[4]->v_string, opargs[5]); 4415 break; 4416 case AMLOP_LOAD: 4417 /* Load(Object:NameString, DDBHandle:SuperName) */ 4418 mscope = aml_load(acpi_softc, scope, opargs[0], opargs[1]); 4419 break; 4420 case AMLOP_UNLOAD: 4421 /* DDBHandle */ 4422 aml_die("Unload"); 4423 break; 4424 4425 /* Control Flow */ 4426 case AMLOP_IF: 4427 /* Arguments: iT or iTbT */ 4428 if (opargs[0]->v_integer) { 4429 dnprintf(10,"parse-if @ %.4x\n", pc); 4430 mscope = aml_pushscope(scope, opargs[1], scope->node, 4431 AMLOP_IF); 4432 } else if (opargs[3] != NULL) { 4433 dnprintf(10,"parse-else @ %.4x\n", pc); 4434 mscope = aml_pushscope(scope, opargs[3], scope->node, 4435 AMLOP_ELSE); 4436 } 4437 break; 4438 case AMLOP_WHILE: 4439 if (opargs[0]->v_integer) { 4440 /* Set parent position to start of WHILE */ 4441 scope->pos = start; 4442 mscope = aml_pushscope(scope, opargs[1], scope->node, 4443 AMLOP_WHILE); 4444 } 4445 break; 4446 case AMLOP_BREAK: 4447 /* Break: Find While Scope parent, mark type as null */ 4448 aml_findscope(scope, AMLOP_WHILE, AMLOP_BREAK); 4449 break; 4450 case AMLOP_CONTINUE: 4451 /* Find Scope.. mark all objects as invalid on way to root */ 4452 aml_findscope(scope, AMLOP_WHILE, AMLOP_CONTINUE); 4453 break; 4454 case AMLOP_RETURN: 4455 mscope = aml_findscope(scope, AMLOP_METHOD, AMLOP_RETURN); 4456 if (mscope->retv) { 4457 aml_die("already allocated\n"); 4458 } 4459 mscope->retv = aml_allocvalue(0,0,NULL); 4460 aml_copyvalue(mscope->retv, opargs[0]); 4461 mscope = NULL; 4462 break; 4463 default: 4464 /* may be set direct result */ 4465 aml_die("Unknown opcode: %x:%s\n", opcode, htab->mnem); 4466 break; 4467 } 4468 if (mscope != NULL) { 4469 /* Change our scope to new scope */ 4470 scope = mscope; 4471 } 4472 if ((ret_type == 'i' || ret_type == 't') && my_ret == NULL) { 4473 dnprintf(10,"quick: %.4x [%s] alloc return integer = 0x%llx\n", 4474 pc, htab->mnem, ival); 4475 my_ret = aml_allocvalue(AML_OBJTYPE_INTEGER, ival, NULL); 4476 } 4477 if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { 4478 dnprintf(10,"quick: %.4x convert to integer %s -> %s\n", 4479 pc, htab->mnem, stype); 4480 my_ret = aml_convert(my_ret, AML_OBJTYPE_INTEGER, -1); 4481 } 4482 if (my_ret != NULL) { 4483 /* Display result */ 4484 dnprintf(20,"quick: %.4x %18s %c %.4x\n", pc, stype, 4485 ret_type, my_ret->stack); 4486 } 4487 4488 /* End opcode: display/free arguments */ 4489 parse_error: 4490 for (idx=0; idx<8; idx++) { 4491 if (opargs[idx] == my_ret) 4492 opargs[idx] = NULL; 4493 aml_delref(&opargs[idx], "oparg"); 4494 } 4495 4496 /* If parsing whole scope and not done, start again */ 4497 if (ret_type == 'T') { 4498 aml_delref(&my_ret, "scope.loop"); 4499 while (scope->pos >= scope->end && scope != iscope) { 4500 /* Pop intermediate scope */ 4501 scope = aml_popscope(scope); 4502 } 4503 if (scope->pos && scope->pos < scope->end) 4504 goto start; 4505 } 4506 4507 odp--; 4508 dnprintf(50, ">>return [%s] %s %c %p\n", aml_nodename(scope->node), 4509 stype, ret_type, my_ret); 4510 4511 return my_ret; 4512 } 4513 4514 int 4515 acpi_parse_aml(struct acpi_softc *sc, const char *rootpath, 4516 uint8_t *start, uint32_t length) 4517 { 4518 struct aml_node *root = &aml_root; 4519 struct aml_scope *scope; 4520 struct aml_value res; 4521 4522 if (rootpath) { 4523 root = aml_searchname(&aml_root, rootpath); 4524 if (root == NULL) 4525 aml_die("Invalid RootPathName %s\n", rootpath); 4526 } 4527 4528 aml_root.start = start; 4529 memset(&res, 0, sizeof(res)); 4530 res.type = AML_OBJTYPE_SCOPE; 4531 res.length = length; 4532 res.v_buffer = start; 4533 4534 /* Push toplevel scope, parse AML */ 4535 aml_error = 0; 4536 scope = aml_pushscope(NULL, &res, &aml_root, AMLOP_SCOPE); 4537 aml_busy++; 4538 aml_parse(scope, 'T', "TopLevel"); 4539 aml_busy--; 4540 aml_popscope(scope); 4541 4542 if (aml_error) { 4543 printf("error in acpi_parse_aml\n"); 4544 return -1; 4545 } 4546 return (0); 4547 } 4548 4549 /* 4550 * @@@: External API 4551 * 4552 * evaluate an AML node 4553 * Returns a copy of the value in res (must be freed by user) 4554 */ 4555 int 4556 aml_evalnode(struct acpi_softc *sc, struct aml_node *node, 4557 int argc, struct aml_value *argv, struct aml_value *res) 4558 { 4559 struct aml_value *xres; 4560 4561 if (res) 4562 memset(res, 0, sizeof(*res)); 4563 if (node == NULL || node->value == NULL) 4564 return (ACPI_E_BADVALUE); 4565 dnprintf(12,"EVALNODE: %s %lx\n", aml_nodename(node), acpi_nalloc); 4566 4567 aml_error = 0; 4568 xres = aml_eval(NULL, node->value, 't', argc, argv); 4569 if (xres) { 4570 if (res) 4571 aml_copyvalue(res, xres); 4572 if (xres != node->value) 4573 aml_delref(&xres, "evalnode"); 4574 } 4575 if (aml_error) { 4576 printf("error evaluating: %s\n", aml_nodename(node)); 4577 return (-1); 4578 } 4579 return (0); 4580 } 4581 4582 int 4583 aml_node_setval(struct acpi_softc *sc, struct aml_node *node, int64_t val) 4584 { 4585 struct aml_value env; 4586 4587 if (!node) 4588 return (0); 4589 4590 memset(&env, 0, sizeof(env)); 4591 env.type = AML_OBJTYPE_INTEGER; 4592 env.v_integer = val; 4593 4594 return aml_evalnode(sc, node, 1, &env, NULL); 4595 } 4596 4597 /* 4598 * evaluate an AML name 4599 * Returns a copy of the value in res (must be freed by user) 4600 */ 4601 int 4602 aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name, 4603 int argc, struct aml_value *argv, struct aml_value *res) 4604 { 4605 parent = aml_searchname(parent, name); 4606 return aml_evalnode(sc, parent, argc, argv, res); 4607 } 4608 4609 /* 4610 * evaluate an AML integer object 4611 */ 4612 int 4613 aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent, 4614 const char *name, int argc, struct aml_value *argv, int64_t *ival) 4615 { 4616 struct aml_value res; 4617 int rc; 4618 4619 parent = aml_searchname(parent, name); 4620 rc = aml_evalnode(sc, parent, argc, argv, &res); 4621 if (rc == 0) { 4622 *ival = aml_val2int(&res); 4623 aml_freevalue(&res); 4624 } 4625 return rc; 4626 } 4627 4628 /* 4629 * Search for an AML name in namespace.. root only 4630 */ 4631 struct aml_node * 4632 __aml_searchname(struct aml_node *root, const void *vname, int create) 4633 { 4634 char *name = (char *)vname; 4635 char nseg[AML_NAMESEG_LEN + 1]; 4636 int i; 4637 4638 dnprintf(25,"Searchname: %s:%s = ", aml_nodename(root), name); 4639 while (*name == AMLOP_ROOTCHAR) { 4640 root = &aml_root; 4641 name++; 4642 } 4643 while (*name != 0) { 4644 /* Ugh.. we can have short names here: append '_' */ 4645 strlcpy(nseg, "____", sizeof(nseg)); 4646 for (i=0; i < AML_NAMESEG_LEN && *name && *name != '.'; i++) 4647 nseg[i] = *name++; 4648 if (*name == '.') 4649 name++; 4650 root = __aml_search(root, nseg, create); 4651 } 4652 dnprintf(25,"%p %s\n", root, aml_nodename(root)); 4653 return root; 4654 } 4655 4656 struct aml_node * 4657 aml_searchname(struct aml_node *root, const void *vname) 4658 { 4659 return __aml_searchname(root, vname, 0); 4660 } 4661 4662 /* 4663 * Search for relative name 4664 */ 4665 struct aml_node * 4666 aml_searchrel(struct aml_node *root, const void *vname) 4667 { 4668 struct aml_node *res; 4669 4670 while (root) { 4671 res = aml_searchname(root, vname); 4672 if (res != NULL) 4673 return res; 4674 root = root->parent; 4675 } 4676 return NULL; 4677 } 4678 4679 #ifndef SMALL_KERNEL 4680 4681 void 4682 acpi_getdevlist(struct acpi_devlist_head *list, struct aml_node *root, 4683 struct aml_value *pkg, int off) 4684 { 4685 struct acpi_devlist *dl; 4686 struct aml_value *val; 4687 struct aml_node *node; 4688 int idx; 4689 4690 for (idx = off; idx < pkg->length; idx++) { 4691 val = pkg->v_package[idx]; 4692 if (val->type == AML_OBJTYPE_NAMEREF) { 4693 node = aml_searchrel(root, aml_getname(val->v_nameref)); 4694 if (node == NULL) { 4695 printf("%s: device %s not found\n", __func__, 4696 aml_getname(val->v_nameref)); 4697 continue; 4698 } 4699 val = node->value; 4700 } 4701 if (val->type == AML_OBJTYPE_OBJREF) 4702 val = val->v_objref.ref; 4703 if (val->node) { 4704 dl = acpi_os_malloc(sizeof(*dl)); 4705 if (dl) { 4706 dl->dev_node = val->node; 4707 TAILQ_INSERT_TAIL(list, dl, dev_link); 4708 } 4709 } 4710 } 4711 } 4712 4713 void 4714 acpi_freedevlist(struct acpi_devlist_head *list) 4715 { 4716 struct acpi_devlist *dl; 4717 4718 while ((dl = TAILQ_FIRST(list)) != NULL) { 4719 TAILQ_REMOVE(list, dl, dev_link); 4720 acpi_os_free(dl); 4721 } 4722 } 4723 4724 #endif /* SMALL_KERNEL */ 4725