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