Annotation of sys/dev/acpi/dsdt.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: dsdt.c,v 1.87 2007/04/11 02:51:11 jordan 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/device.h>
! 21: #include <sys/malloc.h>
! 22: #include <sys/proc.h>
! 23:
! 24: #include <machine/bus.h>
! 25:
! 26: #ifdef DDB
! 27: #include <machine/db_machdep.h>
! 28: #include <ddb/db_command.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: #define opsize(opcode) (((opcode) & 0xFF00) ? 2 : 1)
! 37:
! 38: #define AML_CHECKSTACK()
! 39:
! 40: #define AML_FIELD_RESERVED 0x00
! 41: #define AML_FIELD_ATTRIB 0x01
! 42:
! 43: #define AML_REVISION 0x01
! 44: #define AML_INTSTRLEN 16
! 45: #define AML_NAMESEG_LEN 4
! 46:
! 47: #define aml_valid(pv) ((pv) != NULL)
! 48:
! 49: #define aml_ipaddr(n) ((n)-aml_root.start)
! 50:
! 51: extern int hz;
! 52:
! 53: struct aml_scope;
! 54:
! 55: int aml_cmpvalue(struct aml_value *, struct aml_value *, int);
! 56: void aml_copyvalue(struct aml_value *, struct aml_value *);
! 57:
! 58: void aml_setvalue(struct aml_scope *, struct aml_value *,
! 59: struct aml_value *, int64_t);
! 60: void aml_freevalue(struct aml_value *);
! 61: struct aml_value *aml_allocvalue(int, int64_t, const void *);
! 62: struct aml_value *_aml_setvalue(struct aml_value *, int, int64_t,
! 63: const void *);
! 64:
! 65: u_int64_t aml_convradix(u_int64_t, int, int);
! 66: int64_t aml_evalexpr(int64_t, int64_t, int);
! 67: int aml_lsb(u_int64_t);
! 68: int aml_msb(u_int64_t);
! 69:
! 70: int aml_tstbit(const u_int8_t *, int);
! 71: void aml_setbit(u_int8_t *, int, int);
! 72:
! 73: void aml_bufcpy(void *, int, const void *, int, int);
! 74: int aml_evalinteger(struct acpi_softc *, struct aml_node *,
! 75: const char *, int, struct aml_value *, int64_t *);
! 76:
! 77: void _aml_delref(struct aml_value **val, const char *, int);
! 78: void aml_delref(struct aml_value **);
! 79: void aml_addref(struct aml_value *);
! 80: int aml_pc(uint8_t *);
! 81:
! 82: #define aml_delref(x) _aml_delref(x, __FUNCTION__, __LINE__)
! 83:
! 84: struct aml_value *aml_parseop(struct aml_scope *, struct aml_value *);
! 85: struct aml_value *aml_parsetarget(struct aml_scope *, struct aml_value *,
! 86: struct aml_value **);
! 87: struct aml_value *aml_parseterm(struct aml_scope *, struct aml_value *);
! 88:
! 89: struct aml_value *aml_evaltarget(struct aml_scope *scope,
! 90: struct aml_value *res);
! 91: int aml_evalterm(struct aml_scope *scope,
! 92: struct aml_value *raw, struct aml_value *dst);
! 93: void aml_gasio(struct acpi_softc *, int, uint64_t, uint64_t,
! 94: int, int, int, void *, int);
! 95:
! 96: struct aml_opcode *aml_findopcode(int);
! 97:
! 98: #define acpi_os_malloc(sz) _acpi_os_malloc(sz, __FUNCTION__, __LINE__)
! 99: #define acpi_os_free(ptr) _acpi_os_free(ptr, __FUNCTION__, __LINE__)
! 100:
! 101: void *_acpi_os_malloc(size_t, const char *, int);
! 102: void _acpi_os_free(void *, const char *, int);
! 103: void acpi_sleep(int);
! 104: void acpi_stall(int);
! 105:
! 106: struct aml_value *aml_callosi(struct aml_scope *, struct aml_value *);
! 107: struct aml_value *aml_callmethod(struct aml_scope *, struct aml_value *);
! 108: struct aml_value *aml_evalmethod(struct aml_scope *, struct aml_node *,
! 109: int, struct aml_value *, struct aml_value *);
! 110:
! 111: const char *aml_getname(const char *);
! 112: void aml_dump(int, u_int8_t *);
! 113: void _aml_die(const char *fn, int line, const char *fmt, ...);
! 114: #define aml_die(x...) _aml_die(__FUNCTION__, __LINE__, x)
! 115:
! 116: /*
! 117: * @@@: Global variables
! 118: */
! 119: int aml_intlen = 64;
! 120: struct aml_node aml_root;
! 121: struct aml_value *aml_global_lock;
! 122: struct acpi_softc *dsdt_softc;
! 123:
! 124: struct aml_value *aml_parsenamed(struct aml_scope *, int, struct aml_value *);
! 125: struct aml_value *aml_parsenamedscope(struct aml_scope *, int, struct aml_value *);
! 126: struct aml_value *aml_parsemath(struct aml_scope *, int, struct aml_value *);
! 127: struct aml_value *aml_parsecompare(struct aml_scope *, int, struct aml_value *);
! 128: struct aml_value *aml_parseif(struct aml_scope *, int, struct aml_value *);
! 129: struct aml_value *aml_parsewhile(struct aml_scope *, int, struct aml_value *);
! 130: struct aml_value *aml_parsebufpkg(struct aml_scope *, int, struct aml_value *);
! 131: struct aml_value *aml_parsemethod(struct aml_scope *, int, struct aml_value *);
! 132: struct aml_value *aml_parsesimple(struct aml_scope *, int, struct aml_value *);
! 133: struct aml_value *aml_parsefieldunit(struct aml_scope *, int, struct aml_value *);
! 134: struct aml_value *aml_parsebufferfield(struct aml_scope *, int, struct aml_value *);
! 135: struct aml_value *aml_parsemisc3(struct aml_scope *, int, struct aml_value *);
! 136: struct aml_value *aml_parsemuxaction(struct aml_scope *, int, struct aml_value *);
! 137: struct aml_value *aml_parsemisc2(struct aml_scope *, int, struct aml_value *);
! 138: struct aml_value *aml_parsematch(struct aml_scope *, int, struct aml_value *);
! 139: struct aml_value *aml_parseref(struct aml_scope *, int, struct aml_value *);
! 140: struct aml_value *aml_parsestring(struct aml_scope *, int, struct aml_value *);
! 141:
! 142: /* Perfect Hash key */
! 143: #define HASH_OFF 6904
! 144: #define HASH_SIZE 179
! 145: #define HASH_KEY(k) (((k) ^ HASH_OFF) % HASH_SIZE)
! 146:
! 147: /*
! 148: * XXX this array should be sorted, and then aml_findopcode() should
! 149: * do a binary search
! 150: */
! 151: struct aml_opcode **aml_ophash;
! 152: struct aml_opcode aml_table[] = {
! 153: /* Simple types */
! 154: { AMLOP_ZERO, "Zero", "c", aml_parsesimple },
! 155: { AMLOP_ONE, "One", "c", aml_parsesimple },
! 156: { AMLOP_ONES, "Ones", "c", aml_parsesimple },
! 157: { AMLOP_REVISION, "Revision", "R", aml_parsesimple },
! 158: { AMLOP_BYTEPREFIX, ".Byte", "b", aml_parsesimple },
! 159: { AMLOP_WORDPREFIX, ".Word", "w", aml_parsesimple },
! 160: { AMLOP_DWORDPREFIX, ".DWord", "d", aml_parsesimple },
! 161: { AMLOP_QWORDPREFIX, ".QWord", "q", aml_parsesimple },
! 162: { AMLOP_STRINGPREFIX, ".String", "a", aml_parsesimple },
! 163: { AMLOP_DEBUG, "DebugOp", "D", aml_parsesimple },
! 164: { AMLOP_BUFFER, "Buffer", "piB", aml_parsebufpkg },
! 165: { AMLOP_PACKAGE, "Package", "pbT", aml_parsebufpkg },
! 166: { AMLOP_VARPACKAGE, "VarPackage", "piT", aml_parsebufpkg },
! 167:
! 168: /* Simple objects */
! 169: { AMLOP_LOCAL0, "Local0", "L", aml_parseref },
! 170: { AMLOP_LOCAL1, "Local1", "L", aml_parseref },
! 171: { AMLOP_LOCAL2, "Local2", "L", aml_parseref },
! 172: { AMLOP_LOCAL3, "Local3", "L", aml_parseref },
! 173: { AMLOP_LOCAL4, "Local4", "L", aml_parseref },
! 174: { AMLOP_LOCAL5, "Local5", "L", aml_parseref },
! 175: { AMLOP_LOCAL6, "Local6", "L", aml_parseref },
! 176: { AMLOP_LOCAL7, "Local7", "L", aml_parseref },
! 177: { AMLOP_ARG0, "Arg0", "A", aml_parseref },
! 178: { AMLOP_ARG1, "Arg1", "A", aml_parseref },
! 179: { AMLOP_ARG2, "Arg2", "A", aml_parseref },
! 180: { AMLOP_ARG3, "Arg3", "A", aml_parseref },
! 181: { AMLOP_ARG4, "Arg4", "A", aml_parseref },
! 182: { AMLOP_ARG5, "Arg5", "A", aml_parseref },
! 183: { AMLOP_ARG6, "Arg6", "A", aml_parseref },
! 184:
! 185: /* Control flow */
! 186: { AMLOP_IF, "If", "pI", aml_parseif },
! 187: { AMLOP_ELSE, "Else", "pT" },
! 188: { AMLOP_WHILE, "While", "piT", aml_parsewhile },
! 189: { AMLOP_BREAK, "Break", "" },
! 190: { AMLOP_CONTINUE, "Continue", "" },
! 191: { AMLOP_RETURN, "Return", "t", aml_parseref },
! 192: { AMLOP_FATAL, "Fatal", "bdi", aml_parsemisc2 },
! 193: { AMLOP_NOP, "Nop", "", aml_parsesimple },
! 194: { AMLOP_BREAKPOINT, "BreakPoint", "" },
! 195:
! 196: /* Arithmetic operations */
! 197: { AMLOP_INCREMENT, "Increment", "t", aml_parsemath },
! 198: { AMLOP_DECREMENT, "Decrement", "t", aml_parsemath },
! 199: { AMLOP_ADD, "Add", "iir", aml_parsemath },
! 200: { AMLOP_SUBTRACT, "Subtract", "iir", aml_parsemath },
! 201: { AMLOP_MULTIPLY, "Multiply", "iir", aml_parsemath },
! 202: { AMLOP_DIVIDE, "Divide", "iirr", aml_parsemath },
! 203: { AMLOP_SHL, "ShiftLeft", "iir", aml_parsemath },
! 204: { AMLOP_SHR, "ShiftRight", "iir", aml_parsemath },
! 205: { AMLOP_AND, "And", "iir", aml_parsemath },
! 206: { AMLOP_NAND, "Nand", "iir", aml_parsemath },
! 207: { AMLOP_OR, "Or", "iir", aml_parsemath },
! 208: { AMLOP_NOR, "Nor", "iir", aml_parsemath },
! 209: { AMLOP_XOR, "Xor", "iir", aml_parsemath },
! 210: { AMLOP_NOT, "Not", "ir", aml_parsemath },
! 211: { AMLOP_MOD, "Mod", "iir", aml_parsemath },
! 212: { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "ir", aml_parsemath },
! 213: { AMLOP_FINDSETRIGHTBIT,"FindSetRightBit", "ir",aml_parsemath },
! 214:
! 215: /* Logical test operations */
! 216: { AMLOP_LAND, "LAnd", "ii", aml_parsemath },
! 217: { AMLOP_LOR, "LOr", "ii", aml_parsemath },
! 218: { AMLOP_LNOT, "LNot", "i", aml_parsemath },
! 219: { AMLOP_LNOTEQUAL, "LNotEqual", "tt", aml_parsecompare },
! 220: { AMLOP_LLESSEQUAL, "LLessEqual", "tt", aml_parsecompare },
! 221: { AMLOP_LGREATEREQUAL, "LGreaterEqual", "tt", aml_parsecompare },
! 222: { AMLOP_LEQUAL, "LEqual", "tt", aml_parsecompare },
! 223: { AMLOP_LGREATER, "LGreater", "tt", aml_parsecompare },
! 224: { AMLOP_LLESS, "LLess", "tt", aml_parsecompare },
! 225:
! 226: /* Named objects */
! 227: { AMLOP_NAMECHAR, ".NameRef", "n", aml_parsesimple },
! 228: { AMLOP_ALIAS, "Alias", "nN", aml_parsenamed },
! 229: { AMLOP_NAME, "Name", "Nt", aml_parsenamed },
! 230: { AMLOP_EVENT, "Event", "N", aml_parsenamed },
! 231: { AMLOP_MUTEX, "Mutex", "Nb", aml_parsenamed },
! 232: { AMLOP_DATAREGION, "DataRegion", "Nttt", aml_parsenamed },
! 233: { AMLOP_OPREGION, "OpRegion", "Nbii", aml_parsenamed },
! 234: { AMLOP_SCOPE, "Scope", "pNT", aml_parsenamedscope },
! 235: { AMLOP_DEVICE, "Device", "pNT", aml_parsenamedscope },
! 236: { AMLOP_POWERRSRC, "Power Resource", "pNbwT", aml_parsenamedscope },
! 237: { AMLOP_THERMALZONE, "ThermalZone", "pNT", aml_parsenamedscope },
! 238: { AMLOP_PROCESSOR, "Processor", "pNbdbT", aml_parsenamedscope },
! 239: { AMLOP_METHOD, "Method", "pNfM", aml_parsemethod },
! 240:
! 241: /* Field operations */
! 242: { AMLOP_FIELD, "Field", "pnfF", aml_parsefieldunit },
! 243: { AMLOP_INDEXFIELD, "IndexField", "pntfF", aml_parsefieldunit },
! 244: { AMLOP_BANKFIELD, "BankField", "pnnifF", aml_parsefieldunit },
! 245: { AMLOP_CREATEFIELD, "CreateField", "tiiN", aml_parsebufferfield },
! 246: { AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN", aml_parsebufferfield },
! 247: { AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN", aml_parsebufferfield },
! 248: { AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN", aml_parsebufferfield },
! 249: { AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN", aml_parsebufferfield },
! 250: { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", aml_parsebufferfield },
! 251:
! 252: /* Conversion operations */
! 253: { AMLOP_TOINTEGER, "ToInteger", "tr", aml_parsemath },
! 254: { AMLOP_TOBUFFER, "ToBuffer", "tr", },
! 255: { AMLOP_TODECSTRING, "ToDecString", "ir", aml_parsestring },
! 256: { AMLOP_TOHEXSTRING, "ToHexString", "ir", aml_parsestring },
! 257: { AMLOP_TOSTRING, "ToString", "t", aml_parsestring },
! 258: { AMLOP_MID, "Mid", "tiir", aml_parsestring },
! 259: { AMLOP_FROMBCD, "FromBCD", "ir", aml_parsemath },
! 260: { AMLOP_TOBCD, "ToBCD", "ir", aml_parsemath },
! 261:
! 262: /* Mutex/Signal operations */
! 263: { AMLOP_ACQUIRE, "Acquire", "tw", aml_parsemuxaction },
! 264: { AMLOP_RELEASE, "Release", "t", aml_parsemuxaction },
! 265: { AMLOP_SIGNAL, "Signal", "t", aml_parsemuxaction },
! 266: { AMLOP_WAIT, "Wait", "ti", aml_parsemuxaction },
! 267: { AMLOP_RESET, "Reset", "t", aml_parsemuxaction },
! 268:
! 269: { AMLOP_INDEX, "Index", "tir", aml_parseref },
! 270: { AMLOP_DEREFOF, "DerefOf", "t", aml_parseref },
! 271: { AMLOP_REFOF, "RefOf", "t", aml_parseref },
! 272: { AMLOP_CONDREFOF, "CondRef", "nr", aml_parseref },
! 273:
! 274: { AMLOP_LOADTABLE, "LoadTable", "tttttt" },
! 275: { AMLOP_STALL, "Stall", "i", aml_parsemisc2 },
! 276: { AMLOP_SLEEP, "Sleep", "i", aml_parsemisc2 },
! 277: { AMLOP_LOAD, "Load", "nt", aml_parseref },
! 278: { AMLOP_UNLOAD, "Unload", "t" },
! 279: { AMLOP_STORE, "Store", "tr", aml_parseref },
! 280: { AMLOP_CONCAT, "Concat", "ttr", aml_parsestring },
! 281: { AMLOP_CONCATRES, "ConcatRes", "ttt" },
! 282: { AMLOP_NOTIFY, "Notify", "ti", aml_parsemisc2 },
! 283: { AMLOP_SIZEOF, "Sizeof", "t", aml_parsemisc3 },
! 284: { AMLOP_MATCH, "Match", "tbibii", aml_parsematch },
! 285: { AMLOP_OBJECTTYPE, "ObjectType", "t", aml_parsemisc3 },
! 286: { AMLOP_COPYOBJECT, "CopyObject", "tr", aml_parseref },
! 287: };
! 288:
! 289: int aml_pc(uint8_t *src)
! 290: {
! 291: return src - aml_root.start;
! 292: }
! 293:
! 294: struct aml_scope *aml_lastscope;
! 295:
! 296: void _aml_die(const char *fn, int line, const char *fmt, ...)
! 297: {
! 298: struct aml_scope *root;
! 299: va_list ap;
! 300: int idx;
! 301:
! 302: va_start(ap, fmt);
! 303: vprintf(fmt, ap);
! 304: printf("\n");
! 305: va_end(ap);
! 306:
! 307: for (root = aml_lastscope; root && root->pos; root = root->parent) {
! 308: printf("%.4x Called: %s\n", aml_pc(root->pos),
! 309: aml_nodename(root->node));
! 310: for (idx = 0; idx < root->nargs; idx++) {
! 311: printf(" arg%d: ", idx);
! 312: aml_showvalue(&root->args[idx], 0);
! 313: }
! 314: for (idx = 0; root->locals && idx < AML_MAX_LOCAL; idx++) {
! 315: if (root->locals[idx].type) {
! 316: printf(" local%d: ", idx);
! 317: aml_showvalue(&root->locals[idx], 0);
! 318: }
! 319: }
! 320: }
! 321:
! 322: /* XXX: don't panic */
! 323: panic("aml_die %s:%d", fn, line);
! 324: }
! 325:
! 326: void
! 327: aml_hashopcodes(void)
! 328: {
! 329: int i;
! 330:
! 331: /* Dynamically allocate hash table */
! 332: aml_ophash = (struct aml_opcode **)acpi_os_malloc(HASH_SIZE*sizeof(struct aml_opcode *));
! 333: for (i = 0; i < sizeof(aml_table) / sizeof(aml_table[0]); i++)
! 334: aml_ophash[HASH_KEY(aml_table[i].opcode)] = &aml_table[i];
! 335: }
! 336:
! 337: struct aml_opcode *
! 338: aml_findopcode(int opcode)
! 339: {
! 340: struct aml_opcode *hop;
! 341:
! 342: hop = aml_ophash[HASH_KEY(opcode)];
! 343: if (hop && hop->opcode == opcode)
! 344: return hop;
! 345: return NULL;
! 346: }
! 347:
! 348: const char *
! 349: aml_mnem(int opcode, uint8_t *pos)
! 350: {
! 351: struct aml_opcode *tab;
! 352: static char mnemstr[32];
! 353:
! 354: if ((tab = aml_findopcode(opcode)) != NULL) {
! 355: strlcpy(mnemstr, tab->mnem, sizeof(mnemstr));
! 356: if (pos != NULL) {
! 357: switch (opcode) {
! 358: case AMLOP_STRINGPREFIX:
! 359: snprintf(mnemstr, sizeof(mnemstr), "\"%s\"", pos);
! 360: break;
! 361: case AMLOP_BYTEPREFIX:
! 362: snprintf(mnemstr, sizeof(mnemstr), "0x%.2x",
! 363: *(uint8_t *)pos);
! 364: break;
! 365: case AMLOP_WORDPREFIX:
! 366: snprintf(mnemstr, sizeof(mnemstr), "0x%.4x",
! 367: *(uint16_t *)pos);
! 368: break;
! 369: case AMLOP_DWORDPREFIX:
! 370: snprintf(mnemstr, sizeof(mnemstr), "0x%.4x",
! 371: *(uint16_t *)pos);
! 372: break;
! 373: case AMLOP_NAMECHAR:
! 374: strlcpy(mnemstr, aml_getname(pos), sizeof(mnemstr));
! 375: break;
! 376: }
! 377: }
! 378: return mnemstr;
! 379: }
! 380: return ("xxx");
! 381: }
! 382:
! 383: const char *
! 384: aml_args(int opcode)
! 385: {
! 386: struct aml_opcode *tab;
! 387:
! 388: if ((tab = aml_findopcode(opcode)) != NULL)
! 389: return tab->args;
! 390: return ("");
! 391: }
! 392:
! 393: struct aml_notify_data {
! 394: struct aml_node *node;
! 395: char pnpid[20];
! 396: void *cbarg;
! 397: int (*cbproc)(struct aml_node *, int, void *);
! 398: int poll;
! 399:
! 400: SLIST_ENTRY(aml_notify_data) link;
! 401: };
! 402:
! 403: SLIST_HEAD(aml_notify_head, aml_notify_data);
! 404: struct aml_notify_head aml_notify_list =
! 405: LIST_HEAD_INITIALIZER(&aml_notify_list);
! 406:
! 407: /*
! 408: * @@@: Memory management functions
! 409: */
! 410:
! 411: long acpi_nalloc;
! 412:
! 413: struct acpi_memblock {
! 414: size_t size;
! 415: };
! 416:
! 417: void *
! 418: _acpi_os_malloc(size_t size, const char *fn, int line)
! 419: {
! 420: struct acpi_memblock *sptr;
! 421:
! 422: sptr = malloc(size+sizeof(*sptr), M_DEVBUF, M_WAITOK);
! 423: dnprintf(99, "alloc: %x %s:%d\n", sptr, fn, line);
! 424: if (sptr) {
! 425: acpi_nalloc += size;
! 426: sptr->size = size;
! 427: memset(&sptr[1], 0, size);
! 428: return &sptr[1];
! 429: }
! 430: return NULL;
! 431: }
! 432:
! 433: void
! 434: _acpi_os_free(void *ptr, const char *fn, int line)
! 435: {
! 436: struct acpi_memblock *sptr;
! 437:
! 438: if (ptr != NULL) {
! 439: sptr = &(((struct acpi_memblock *)ptr)[-1]);
! 440: acpi_nalloc -= sptr->size;
! 441:
! 442: dnprintf(99, "free: %x %s:%d\n", sptr, fn, line);
! 443: free(sptr, M_DEVBUF);
! 444: }
! 445: }
! 446:
! 447: void
! 448: acpi_sleep(int ms)
! 449: {
! 450: int to = ms * hz / 1000;
! 451:
! 452: if (cold)
! 453: delay(ms * 1000);
! 454: else {
! 455: if (to <= 0)
! 456: to = 1;
! 457: while (tsleep(dsdt_softc, PWAIT, "asleep", to) !=
! 458: EWOULDBLOCK);
! 459: }
! 460: }
! 461:
! 462: void
! 463: acpi_stall(int us)
! 464: {
! 465: delay(us);
! 466: }
! 467:
! 468: int
! 469: acpi_mutex_acquire(struct aml_value *val, int timeout)
! 470: {
! 471: /* XXX we currently do not have concurrency so assume mutex succeeds */
! 472: dnprintf(50, "acpi_mutex_acquire\n");
! 473:
! 474: return (0);
! 475: #if 0
! 476: struct acpi_mutex *mtx = val->v_mutex;
! 477: int rv = 0, ts, tries = 0;
! 478:
! 479: if (val->type != AML_OBJTYPE_MUTEX) {
! 480: printf("acpi_mutex_acquire: invalid mutex\n");
! 481: return (1);
! 482: }
! 483:
! 484: if (timeout == 0xffff)
! 485: timeout = 0;
! 486:
! 487: /* lock recursion be damned, panic if that happens */
! 488: rw_enter_write(&mtx->amt_lock);
! 489: while (mtx->amt_ref_count) {
! 490: rw_exit_write(&mtx->amt_lock);
! 491: /* block access */
! 492: ts = tsleep(mtx, PWAIT, mtx->amt_name, timeout / hz);
! 493: if (ts == EWOULDBLOCK) {
! 494: rv = 1; /* mutex not acquired */
! 495: goto done;
! 496: }
! 497: tries++;
! 498: rw_enter_write(&mtx->amt_lock);
! 499: }
! 500:
! 501: mtx->amt_ref_count++;
! 502: rw_exit_write(&mtx->amt_lock);
! 503: done:
! 504: return (rv);
! 505: #endif
! 506: }
! 507:
! 508: void
! 509: acpi_mutex_release(struct aml_value *val)
! 510: {
! 511: dnprintf(50, "acpi_mutex_release\n");
! 512: #if 0
! 513: struct acpi_mutex *mtx = val->v_mutex;
! 514:
! 515: /* sanity */
! 516: if (val->type != AML_OBJTYPE_MUTEX) {
! 517: printf("acpi_mutex_acquire: invalid mutex\n");
! 518: return;
! 519: }
! 520:
! 521: rw_enter_write(&mtx->amt_lock);
! 522:
! 523: if (mtx->amt_ref_count == 0) {
! 524: printf("acpi_mutex_release underflow %s\n", mtx->amt_name);
! 525: goto done;
! 526: }
! 527:
! 528: mtx->amt_ref_count--;
! 529: wakeup(mtx); /* wake all of them up */
! 530: done:
! 531: rw_exit_write(&mtx->amt_lock);
! 532: #endif
! 533: }
! 534:
! 535: /*
! 536: * @@@: Misc utility functions
! 537: */
! 538:
! 539: void
! 540: aml_dump(int len, u_int8_t *buf)
! 541: {
! 542: int idx;
! 543:
! 544: dnprintf(50, "{ ");
! 545: for (idx = 0; idx < len; idx++) {
! 546: dnprintf(50, "%s0x%.2x", idx ? ", " : "", buf[idx]);
! 547: }
! 548: dnprintf(50, " }\n");
! 549: }
! 550:
! 551: /* Bit mangling code */
! 552: int
! 553: aml_tstbit(const u_int8_t *pb, int bit)
! 554: {
! 555: pb += aml_bytepos(bit);
! 556:
! 557: return (*pb & aml_bitmask(bit));
! 558: }
! 559:
! 560: void
! 561: aml_setbit(u_int8_t *pb, int bit, int val)
! 562: {
! 563: pb += aml_bytepos(bit);
! 564:
! 565: if (val)
! 566: *pb |= aml_bitmask(bit);
! 567: else
! 568: *pb &= ~aml_bitmask(bit);
! 569: }
! 570:
! 571: /* Read/Write to hardware I/O fields */
! 572: void
! 573: aml_gasio(struct acpi_softc *sc, int type, uint64_t base, uint64_t length,
! 574: int bitpos, int bitlen, int size, void *buf, int mode)
! 575: {
! 576: dnprintf(10, "-- aml_gasio: %.2x"
! 577: " base:%llx len:%llx bpos:%.4x blen:%.4x sz:%.2x mode=%s\n",
! 578: type, base, length, bitpos, bitlen, size,
! 579: mode==ACPI_IOREAD?"read":"write");
! 580: acpi_gasio(sc, mode, type, base+(bitpos>>3),
! 581: (size>>3), (bitlen>>3), buf);
! 582: #ifdef ACPI_DEBUG
! 583: while (bitlen > 0) {
! 584: dnprintf(10, "%.2x ", *(uint8_t *)buf);
! 585: buf++;
! 586: bitlen -=8;
! 587: }
! 588: dnprintf(10, "\n");
! 589: #endif
! 590: }
! 591:
! 592: /*
! 593: * @@@: Notify functions
! 594: */
! 595: void
! 596: acpi_poll(void *arg)
! 597: {
! 598: dsdt_softc->sc_poll = 1;
! 599: dsdt_softc->sc_wakeup = 0;
! 600: wakeup(dsdt_softc);
! 601:
! 602: timeout_add(&dsdt_softc->sc_dev_timeout, 10 * hz);
! 603: }
! 604:
! 605: void
! 606: aml_register_notify(struct aml_node *node, const char *pnpid,
! 607: int (*proc)(struct aml_node *, int, void *), void *arg, int poll)
! 608: {
! 609: struct aml_notify_data *pdata;
! 610: extern int acpi_poll_enabled;
! 611:
! 612: dnprintf(10, "aml_register_notify: %s %s %x\n",
! 613: node->name, pnpid ? pnpid : "", proc);
! 614:
! 615: pdata = acpi_os_malloc(sizeof(struct aml_notify_data));
! 616: pdata->node = node;
! 617: pdata->cbarg = arg;
! 618: pdata->cbproc = proc;
! 619: pdata->poll = poll;
! 620:
! 621: if (pnpid)
! 622: strlcpy(pdata->pnpid, pnpid, sizeof(pdata->pnpid));
! 623:
! 624: SLIST_INSERT_HEAD(&aml_notify_list, pdata, link);
! 625:
! 626: if (poll && !acpi_poll_enabled)
! 627: timeout_add(&dsdt_softc->sc_dev_timeout, 10 * hz);
! 628: }
! 629:
! 630: void
! 631: aml_notify(struct aml_node *node, int notify_value)
! 632: {
! 633: struct aml_notify_data *pdata = NULL;
! 634:
! 635: if (node == NULL)
! 636: return;
! 637:
! 638: SLIST_FOREACH(pdata, &aml_notify_list, link)
! 639: if (pdata->node == node)
! 640: pdata->cbproc(pdata->node, notify_value, pdata->cbarg);
! 641: }
! 642:
! 643: void
! 644: aml_notify_dev(const char *pnpid, int notify_value)
! 645: {
! 646: struct aml_notify_data *pdata = NULL;
! 647:
! 648: if (pnpid == NULL)
! 649: return;
! 650:
! 651: SLIST_FOREACH(pdata, &aml_notify_list, link)
! 652: if (pdata->pnpid && !strcmp(pdata->pnpid, pnpid))
! 653: pdata->cbproc(pdata->node, notify_value, pdata->cbarg);
! 654: }
! 655:
! 656: void acpi_poll_notify(void)
! 657: {
! 658: struct aml_notify_data *pdata = NULL;
! 659:
! 660: SLIST_FOREACH(pdata, &aml_notify_list, link)
! 661: if (pdata->cbproc && pdata->poll)
! 662: pdata->cbproc(pdata->node, 0, pdata->cbarg);
! 663: }
! 664:
! 665: /*
! 666: * @@@: Namespace functions
! 667: */
! 668:
! 669: struct aml_node *__aml_search(struct aml_node *, uint8_t *);
! 670: void aml_delchildren(struct aml_node *);
! 671:
! 672:
! 673: /* Search for a name in children nodes */
! 674: struct aml_node *
! 675: __aml_search(struct aml_node *root, uint8_t *nameseg)
! 676: {
! 677: if (root == NULL)
! 678: return NULL;
! 679: for (root = root->child; root; root = root->sibling) {
! 680: if (!memcmp(root->name, nameseg, AML_NAMESEG_LEN))
! 681: return root;
! 682: }
! 683: return NULL;
! 684: }
! 685:
! 686: /* Get absolute pathname of AML node */
! 687: const char *
! 688: aml_nodename(struct aml_node *node)
! 689: {
! 690: static char namebuf[128];
! 691:
! 692: namebuf[0] = 0;
! 693: if (node) {
! 694: aml_nodename(node->parent);
! 695: if (node->parent != &aml_root)
! 696: strlcat(namebuf, ".", sizeof(namebuf));
! 697: strlcat(namebuf, node->name, sizeof(namebuf));
! 698: return namebuf+1;
! 699: }
! 700: return namebuf;
! 701: }
! 702:
! 703: const char *
! 704: aml_getname(const char *name)
! 705: {
! 706: static char namebuf[128], *p;
! 707: int count;
! 708:
! 709: p = namebuf;
! 710: while (*name == AMLOP_ROOTCHAR || *name == AMLOP_PARENTPREFIX) {
! 711: *(p++) = *(name++);
! 712: }
! 713: switch (*name) {
! 714: case 0x00:
! 715: count = 0;
! 716: break;
! 717: case AMLOP_MULTINAMEPREFIX:
! 718: count = name[1];
! 719: name += 2;
! 720: break;
! 721: case AMLOP_DUALNAMEPREFIX:
! 722: count = 2;
! 723: name += 1;
! 724: break;
! 725: default:
! 726: count = 1;
! 727: }
! 728: while (count--) {
! 729: memcpy(p, name, 4);
! 730: p[4] = '.';
! 731: p += 5;
! 732: name += 4;
! 733: if (*name == '.') name++;
! 734: }
! 735: *(--p) = 0;
! 736: return namebuf;
! 737: }
! 738:
! 739: /* Create name/value pair in namespace */
! 740: struct aml_node *
! 741: aml_createname(struct aml_node *root, const void *vname, struct aml_value *value)
! 742: {
! 743: struct aml_node *node, **pp;
! 744: uint8_t *name = (uint8_t *)vname;
! 745: int count;
! 746:
! 747: if (*name == AMLOP_ROOTCHAR) {
! 748: root = &aml_root;
! 749: name++;
! 750: }
! 751: while (*name == AMLOP_PARENTPREFIX && root) {
! 752: root = root->parent;
! 753: name++;
! 754: }
! 755: switch (*name) {
! 756: case 0x00:
! 757: return root;
! 758: case AMLOP_MULTINAMEPREFIX:
! 759: count = name[1];
! 760: name += 2;
! 761: break;
! 762: case AMLOP_DUALNAMEPREFIX:
! 763: count = 2;
! 764: name += 1;
! 765: break;
! 766: default:
! 767: count = 1;
! 768: break;
! 769: }
! 770: node = NULL;
! 771: while (count-- && root) {
! 772: /* Create new name if it does not exist */
! 773: if ((node = __aml_search(root, name)) == NULL) {
! 774: node = acpi_os_malloc(sizeof(struct aml_node));
! 775:
! 776: memcpy((void *)node->name, name, AML_NAMESEG_LEN);
! 777: for (pp = &root->child; *pp; pp = &(*pp)->sibling)
! 778: ;
! 779: node->parent = root;
! 780: node->sibling = NULL;
! 781: *pp = node;
! 782: }
! 783: root = node;
! 784: name += AML_NAMESEG_LEN;
! 785: }
! 786: /* If node created, set value pointer */
! 787: if (node && value) {
! 788: node->value = value;
! 789: value->node = node;
! 790: }
! 791: return node;
! 792: }
! 793:
! 794: /* Search namespace for a named node */
! 795: struct aml_node *
! 796: aml_searchname(struct aml_node *root, const void *vname)
! 797: {
! 798: struct aml_node *node;
! 799: uint8_t *name = (uint8_t *)vname;
! 800: int count;
! 801:
! 802: if (*name == AMLOP_ROOTCHAR) {
! 803: root = &aml_root;
! 804: name++;
! 805: }
! 806: while (*name == AMLOP_PARENTPREFIX && root) {
! 807: root = root->parent;
! 808: name++;
! 809: }
! 810: if (strlen(name) < AML_NAMESEG_LEN) {
! 811: aml_die("bad name");
! 812: }
! 813: switch (*name) {
! 814: case 0x00:
! 815: return root;
! 816: case AMLOP_MULTINAMEPREFIX:
! 817: count = name[1];
! 818: name += 2;
! 819: break;
! 820: case AMLOP_DUALNAMEPREFIX:
! 821: count = 2;
! 822: name += 1;
! 823: break;
! 824: default:
! 825: if (name[4] == '.') {
! 826: /* Called from user code */
! 827: while (*name && (root = __aml_search(root, name)) != NULL) {
! 828: name += AML_NAMESEG_LEN+1;
! 829: }
! 830: return root;
! 831: }
! 832: /* Special case.. search relative for name */
! 833: while (root && (node = __aml_search(root, name)) == NULL) {
! 834: root = root->parent;
! 835: }
! 836: return node;
! 837: }
! 838: /* Search absolute for name*/
! 839: while (count-- && (root = __aml_search(root, name)) != NULL) {
! 840: name += AML_NAMESEG_LEN;
! 841: }
! 842: return root;
! 843: }
! 844:
! 845: /* Free all children nodes/values */
! 846: void
! 847: aml_delchildren(struct aml_node *node)
! 848: {
! 849: struct aml_node *onode;
! 850:
! 851: if (node == NULL)
! 852: return;
! 853: while ((onode = node->child) != NULL) {
! 854: node->child = onode->sibling;
! 855:
! 856: aml_delchildren(onode);
! 857:
! 858: /* Decrease reference count */
! 859: aml_delref(&onode->value);
! 860:
! 861: /* Delete node */
! 862: acpi_os_free(onode);
! 863: }
! 864: }
! 865:
! 866: /*
! 867: * @@@: Value functions
! 868: */
! 869:
! 870: struct aml_value *aml_alloctmp(struct aml_scope *, int);
! 871: struct aml_scope *aml_pushscope(struct aml_scope *, uint8_t *,
! 872: uint8_t *, struct aml_node *);
! 873: struct aml_scope *aml_popscope(struct aml_scope *);
! 874: int aml_parsenode(struct aml_scope *, struct aml_node *,
! 875: uint8_t *, uint8_t **, struct aml_value *);
! 876:
! 877: #define AML_LHS 0
! 878: #define AML_RHS 1
! 879: #define AML_DST 2
! 880: #define AML_DST2 3
! 881:
! 882: /* Allocate temporary storage in this scope */
! 883: struct aml_value *
! 884: aml_alloctmp(struct aml_scope *scope, int narg)
! 885: {
! 886: struct aml_vallist *tmp;
! 887:
! 888: /* Allocate array of temp values */
! 889: tmp = (struct aml_vallist *)acpi_os_malloc(sizeof(struct aml_vallist) +
! 890: narg * sizeof(struct aml_value));
! 891:
! 892: tmp->obj = (struct aml_value *)&tmp[1];
! 893: tmp->nobj = narg;
! 894:
! 895: /* Link into scope */
! 896: tmp->next = scope->tmpvals;
! 897: scope->tmpvals = tmp;
! 898:
! 899: /* Return array of values */
! 900: return tmp->obj;
! 901: }
! 902:
! 903: /* Allocate+push parser scope */
! 904: struct aml_scope *
! 905: aml_pushscope(struct aml_scope *parent, uint8_t *start, uint8_t *end,
! 906: struct aml_node *node)
! 907: {
! 908: struct aml_scope *scope;
! 909:
! 910: scope = acpi_os_malloc(sizeof(struct aml_scope));
! 911: scope->pos = start;
! 912: scope->end = end;
! 913: scope->node = node;
! 914: scope->parent = parent;
! 915: scope->sc = dsdt_softc;
! 916:
! 917: aml_lastscope = scope;
! 918:
! 919: return scope;
! 920: }
! 921:
! 922: struct aml_scope *
! 923: aml_popscope(struct aml_scope *scope)
! 924: {
! 925: struct aml_scope *nscope;
! 926: struct aml_vallist *ol;
! 927: int idx;
! 928:
! 929: if (scope == NULL)
! 930: return NULL;
! 931: nscope = scope->parent;
! 932:
! 933: /* Free temporary values */
! 934: while ((ol = scope->tmpvals) != NULL) {
! 935: scope->tmpvals = ol->next;
! 936: for (idx = 0; idx < ol->nobj; idx++) {
! 937: aml_freevalue(&ol->obj[idx]);
! 938: }
! 939: acpi_os_free(ol);
! 940: }
! 941: acpi_os_free(scope);
! 942:
! 943: aml_lastscope = nscope;
! 944:
! 945: return nscope;
! 946: }
! 947:
! 948: int
! 949: aml_parsenode(struct aml_scope *parent, struct aml_node *node, uint8_t *start,
! 950: uint8_t **end, struct aml_value *res)
! 951: {
! 952: struct aml_scope *scope;
! 953:
! 954: /* Don't parse zero-length scope */
! 955: if (start == *end)
! 956: return 0;
! 957: scope = aml_pushscope(parent, start, *end, node);
! 958: if (res == NULL)
! 959: res = aml_alloctmp(scope, 1);
! 960: while (scope != parent) {
! 961: while (scope->pos < scope->end)
! 962: aml_parseop(scope, res);
! 963: scope = aml_popscope(scope);
! 964: }
! 965: return 0;
! 966: }
! 967:
! 968: /*
! 969: * Field I/O code
! 970: */
! 971: void aml_setbufint(struct aml_value *, int, int, struct aml_value *);
! 972: void aml_getbufint(struct aml_value *, int, int, struct aml_value *);
! 973: void aml_fieldio(struct aml_scope *, struct aml_value *, struct aml_value *, int);
! 974: void aml_unlockfield(struct aml_scope *, struct aml_value *);
! 975: void aml_lockfield(struct aml_scope *, struct aml_value *);
! 976:
! 977: /* Copy from a bufferfield to an integer/buffer */
! 978: void
! 979: aml_setbufint(struct aml_value *dst, int bitpos, int bitlen,
! 980: struct aml_value *src)
! 981: {
! 982: if (src->type != AML_OBJTYPE_BUFFER)
! 983: aml_die("wrong setbufint type\n");
! 984:
! 985: #if 1
! 986: /* Return buffer type */
! 987: _aml_setvalue(dst, AML_OBJTYPE_BUFFER, (bitlen+7)>>3, NULL);
! 988: aml_bufcpy(dst->v_buffer, 0, src->v_buffer, bitpos, bitlen);
! 989: #else
! 990: if (bitlen < aml_intlen) {
! 991: /* XXX: Endian issues?? */
! 992: /* Return integer type */
! 993: _aml_setvalue(dst, AML_OBJTYPE_INTEGER, 0, NULL);
! 994: aml_bufcpy(&dst->v_integer, 0, src->v_buffer, bitpos, bitlen);
! 995: } else {
! 996: /* Return buffer type */
! 997: _aml_setvalue(dst, AML_OBJTYPE_BUFFER, (bitlen+7)>>3, NULL);
! 998: aml_bufcpy(dst->v_buffer, 0, src->v_buffer, bitpos, bitlen);
! 999: }
! 1000: #endif
! 1001: }
! 1002:
! 1003: /* Copy from a string/integer/buffer to a bufferfield */
! 1004: void
! 1005: aml_getbufint(struct aml_value *src, int bitpos, int bitlen,
! 1006: struct aml_value *dst)
! 1007: {
! 1008: if (dst->type != AML_OBJTYPE_BUFFER)
! 1009: aml_die("wrong getbufint type\n");
! 1010: switch (src->type) {
! 1011: case AML_OBJTYPE_INTEGER:
! 1012: if (bitlen >= aml_intlen)
! 1013: bitlen = aml_intlen;
! 1014: aml_bufcpy(dst->v_buffer, bitpos, &src->v_integer, 0, bitlen);
! 1015: break;
! 1016: case AML_OBJTYPE_BUFFER:
! 1017: if (bitlen >= 8*src->length)
! 1018: bitlen = 8*src->length;
! 1019: aml_bufcpy(dst->v_buffer, bitpos, src->v_buffer, 0, bitlen);
! 1020: break;
! 1021: case AML_OBJTYPE_STRING:
! 1022: if (bitlen >= 8*src->length)
! 1023: bitlen = 8*src->length;
! 1024: aml_bufcpy(dst->v_buffer, bitpos, src->v_string, 0, bitlen);
! 1025: break;
! 1026: }
! 1027: }
! 1028:
! 1029: void
! 1030: aml_lockfield(struct aml_scope *scope, struct aml_value *field)
! 1031: {
! 1032: if (AML_FIELD_LOCK(field->v_field.flags) == AML_FIELD_LOCK_ON) {
! 1033: /* XXX: do locking here */
! 1034: }
! 1035: }
! 1036:
! 1037: void
! 1038: aml_unlockfield(struct aml_scope *scope, struct aml_value *field)
! 1039: {
! 1040: if (AML_FIELD_LOCK(field->v_field.flags) == AML_FIELD_LOCK_ON) {
! 1041: /* XXX: do unlocking here */
! 1042: }
! 1043: }
! 1044:
! 1045: void *aml_getbuffer(struct aml_value *, int *);
! 1046:
! 1047: void *
! 1048: aml_getbuffer(struct aml_value *val, int *bitlen)
! 1049: {
! 1050: switch (val->type) {
! 1051: case AML_OBJTYPE_INTEGER:
! 1052: case AML_OBJTYPE_STATICINT:
! 1053: *bitlen = aml_intlen;
! 1054: return (&val->v_integer);
! 1055:
! 1056: case AML_OBJTYPE_BUFFER:
! 1057: case AML_OBJTYPE_STRING:
! 1058: *bitlen = val->length<<3;
! 1059: return (val->v_buffer);
! 1060:
! 1061: default:
! 1062: aml_die("getvbi");
! 1063: }
! 1064:
! 1065: return (NULL);
! 1066: }
! 1067:
! 1068: /*
! 1069: * Buffer/Region: read/write to bitfields
! 1070: */
! 1071: void
! 1072: aml_fieldio(struct aml_scope *scope, struct aml_value *field,
! 1073: struct aml_value *res, int mode)
! 1074: {
! 1075: struct aml_value *pop, tf;
! 1076: int bpos, blen, aligned, mask;
! 1077: void *iobuf, *iobuf2;
! 1078: uint64_t iobase;
! 1079:
! 1080: pop = field->v_field.ref1;
! 1081: bpos = field->v_field.bitpos;
! 1082: blen = field->v_field.bitlen;
! 1083:
! 1084: dnprintf(55,"--fieldio: %s [%s] bp:%.4x bl:%.4x\n",
! 1085: mode == ACPI_IOREAD ? "rd" : "wr",
! 1086: aml_nodename(field->node), bpos, blen);
! 1087:
! 1088: aml_lockfield(scope, field);
! 1089: switch (field->v_field.type) {
! 1090: case AMLOP_INDEXFIELD:
! 1091: /* Set Index */
! 1092: memcpy(&tf, field->v_field.ref2, sizeof(struct aml_value));
! 1093: tf.v_field.bitpos += (bpos & 7);
! 1094: tf.v_field.bitlen = blen;
! 1095:
! 1096: aml_setvalue(scope, pop, NULL, bpos>>3);
! 1097: aml_fieldio(scope, &tf, res, mode);
! 1098: #ifdef ACPI_DEBUG
! 1099: dnprintf(55, "-- post indexfield %x,%x @ %x,%x\n",
! 1100: bpos & 3, blen,
! 1101: field->v_field.ref2->v_field.bitpos,
! 1102: field->v_field.ref2->v_field.bitlen);
! 1103:
! 1104: iobuf = aml_getbuffer(res, &aligned);
! 1105: aml_dump(aligned >> 3, iobuf);
! 1106: #endif
! 1107: break;
! 1108: case AMLOP_BANKFIELD:
! 1109: /* Set Bank */
! 1110: memcpy(&tf, field->v_field.ref2, sizeof(struct aml_value));
! 1111: tf.v_field.bitpos += (bpos & 7);
! 1112: tf.v_field.bitlen = blen;
! 1113:
! 1114: aml_setvalue(scope, pop, NULL, field->v_field.ref3);
! 1115: aml_fieldio(scope, &tf, res, mode);
! 1116: #ifdef ACPI_DEBUG
! 1117: dnprintf(55, "-- post bankfield %x,%x @ %x,%x\n",
! 1118: bpos & 3, blen,
! 1119: field->v_field.ref2->v_field.bitpos,
! 1120: field->v_field.ref2->v_field.bitlen);
! 1121:
! 1122: iobuf = aml_getbuffer(res, &aligned);
! 1123: aml_dump(aligned >> 3, iobuf);
! 1124: #endif
! 1125: break;
! 1126: case AMLOP_FIELD:
! 1127: /* This is an I/O field */
! 1128: if (pop->type != AML_OBJTYPE_OPREGION)
! 1129: aml_die("Not an opregion!\n");
! 1130:
! 1131: /* Get field access size */
! 1132: switch (AML_FIELD_ACCESS(field->v_field.flags)) {
! 1133: case AML_FIELD_ANYACC:
! 1134: case AML_FIELD_BYTEACC:
! 1135: mask = 7;
! 1136: break;
! 1137: case AML_FIELD_WORDACC:
! 1138: mask = 15;
! 1139: break;
! 1140: case AML_FIELD_DWORDACC:
! 1141: mask = 31;
! 1142: break;
! 1143: case AML_FIELD_QWORDACC:
! 1144: mask = 63;
! 1145: break;
! 1146: }
! 1147:
! 1148: /* Pre-allocate return value for reads */
! 1149: if (mode == ACPI_IOREAD)
! 1150: _aml_setvalue(res, AML_OBJTYPE_BUFFER,
! 1151: (field->v_field.bitlen+7)>>3, NULL);
! 1152:
! 1153: /* Get aligned bitpos/bitlength */
! 1154: blen = ((bpos & mask) + blen + mask) & ~mask;
! 1155: bpos = bpos & ~mask;
! 1156: aligned = (bpos == field->v_field.bitpos &&
! 1157: blen == field->v_field.bitlen);
! 1158: iobase = pop->v_opregion.iobase;
! 1159:
! 1160: /* Check for aligned reads/writes */
! 1161: if (aligned) {
! 1162: iobuf = aml_getbuffer(res, &aligned);
! 1163: aml_gasio(scope->sc, pop->v_opregion.iospace,
! 1164: iobase, pop->v_opregion.iolen, bpos, blen,
! 1165: mask + 1, iobuf, mode);
! 1166: #ifdef ACPI_DEBUG
! 1167: dnprintf(55, "aligned: %s @ %.4x:%.4x + %.4x\n",
! 1168: mode == ACPI_IOREAD ? "rd" : "wr",
! 1169: bpos, blen, aligned);
! 1170:
! 1171: aml_dump(blen >> 3, iobuf);
! 1172: #endif
! 1173: }
! 1174: else if (mode == ACPI_IOREAD) {
! 1175: iobuf = acpi_os_malloc(blen>>3);
! 1176: aml_gasio(scope->sc, pop->v_opregion.iospace,
! 1177: iobase, pop->v_opregion.iolen, bpos, blen,
! 1178: mask + 1, iobuf, mode);
! 1179:
! 1180: /* ASSERT: res is buffer type as it was set above */
! 1181: aml_bufcpy(res->v_buffer, 0, iobuf,
! 1182: field->v_field.bitpos & mask,
! 1183: field->v_field.bitlen);
! 1184:
! 1185: #ifdef ACPI_DEBUG
! 1186: dnprintf(55,"non-aligned read: %.4x:%.4x : ",
! 1187: field->v_field.bitpos & mask,
! 1188: field->v_field.bitlen);
! 1189:
! 1190: aml_dump(blen >> 3, iobuf);
! 1191: dnprintf(55,"post-read: ");
! 1192: aml_dump((field->v_field.bitlen+7)>>3, res->v_buffer);
! 1193: #endif
! 1194: acpi_os_free(iobuf);
! 1195: }
! 1196: else {
! 1197: iobuf = acpi_os_malloc(blen >> 3);
! 1198: switch (AML_FIELD_UPDATE(field->v_field.flags)) {
! 1199: case AML_FIELD_WRITEASONES:
! 1200: memset(iobuf, 0xFF, blen >> 3);
! 1201: break;
! 1202: case AML_FIELD_PRESERVE:
! 1203: aml_gasio(scope->sc, pop->v_opregion.iospace,
! 1204: iobase, pop->v_opregion.iolen, bpos, blen,
! 1205: mask + 1, iobuf, ACPI_IOREAD);
! 1206: break;
! 1207: }
! 1208: /* Copy into IOBUF */
! 1209: iobuf2 = aml_getbuffer(res, &aligned);
! 1210: aml_bufcpy(iobuf, field->v_field.bitpos & mask,
! 1211: iobuf2, 0, field->v_field.bitlen);
! 1212:
! 1213: #ifdef ACPI_DEBUG
! 1214: dnprintf(55,"non-aligned write: %.4x:%.4x : ",
! 1215: field->v_field.bitpos & mask,
! 1216: field->v_field.bitlen);
! 1217:
! 1218: aml_dump(blen >> 3, iobuf);
! 1219: #endif
! 1220: aml_gasio(scope->sc, pop->v_opregion.iospace,
! 1221: iobase, pop->v_opregion.iolen, bpos, blen,
! 1222: mask + 1, iobuf, mode);
! 1223:
! 1224: acpi_os_free(iobuf);
! 1225: }
! 1226: /* Verify that I/O is in range */
! 1227: #if 0
! 1228: /*
! 1229: * XXX: some I/O ranges are on dword boundaries, but their
! 1230: * length is incorrect eg. dword access, but length of
! 1231: * opregion is 2 bytes.
! 1232: */
! 1233: if ((bpos+blen) >= (pop->v_opregion.iolen * 8)) {
! 1234: aml_die("Out of bounds I/O!!! region:%x:%llx:%x %x\n",
! 1235: pop->v_opregion.iospace, pop->v_opregion.iobase,
! 1236: pop->v_opregion.iolen, bpos+blen);
! 1237: }
! 1238: #endif
! 1239: break;
! 1240: default:
! 1241: /* This is a buffer field */
! 1242: if (mode == ACPI_IOREAD)
! 1243: aml_setbufint(res, bpos, blen, pop);
! 1244: else
! 1245: aml_getbufint(res, bpos, blen, pop);
! 1246: break;
! 1247: }
! 1248: aml_unlockfield(scope, field);
! 1249: }
! 1250:
! 1251: /*
! 1252: * @@@: Value set/compare/alloc/free routines
! 1253: */
! 1254: int64_t aml_str2int(const char *, int);
! 1255: struct aml_value *aml_derefvalue(struct aml_scope *, struct aml_value *, int);
! 1256: #define aml_dereftarget(s, v) aml_derefvalue(s, v, ACPI_IOWRITE)
! 1257: #define aml_derefterm(s, v, m) aml_derefvalue(s, v, ACPI_IOREAD)
! 1258:
! 1259: void
! 1260: aml_showvalue(struct aml_value *val, int lvl)
! 1261: {
! 1262: int idx;
! 1263:
! 1264: if (val == NULL)
! 1265: return;
! 1266:
! 1267: if (val->node)
! 1268: printf(" [%s]", aml_nodename(val->node));
! 1269: printf(" %p cnt:%.2x stk:%.2x", val, val->refcnt, val->stack);
! 1270: switch (val->type) {
! 1271: case AML_OBJTYPE_STATICINT:
! 1272: case AML_OBJTYPE_INTEGER:
! 1273: printf(" integer: %llx\n", val->v_integer);
! 1274: break;
! 1275: case AML_OBJTYPE_STRING:
! 1276: printf(" string: %s\n", val->v_string);
! 1277: break;
! 1278: case AML_OBJTYPE_METHOD:
! 1279: printf(" method: %.2x\n", val->v_method.flags);
! 1280: break;
! 1281: case AML_OBJTYPE_PACKAGE:
! 1282: printf(" package: %.2x\n", val->length);
! 1283: for (idx = 0; idx < val->length; idx++)
! 1284: aml_showvalue(val->v_package[idx], lvl);
! 1285: break;
! 1286: case AML_OBJTYPE_BUFFER:
! 1287: printf(" buffer: %.2x {", val->length);
! 1288: for (idx = 0; idx < val->length; idx++)
! 1289: printf("%s%.2x", idx ? ", " : "", val->v_buffer[idx]);
! 1290: printf("}\n");
! 1291: break;
! 1292: case AML_OBJTYPE_FIELDUNIT:
! 1293: case AML_OBJTYPE_BUFFERFIELD:
! 1294: printf(" field: bitpos=%.4x bitlen=%.4x ref1:%x ref2:%x [%s]\n",
! 1295: val->v_field.bitpos, val->v_field.bitlen,
! 1296: val->v_field.ref1, val->v_field.ref2,
! 1297: aml_mnem(val->v_field.type, NULL));
! 1298: aml_showvalue(val->v_field.ref1, lvl);
! 1299: aml_showvalue(val->v_field.ref2, lvl);
! 1300: break;
! 1301: case AML_OBJTYPE_MUTEX:
! 1302: printf(" mutex: %s ref: %d\n",
! 1303: val->v_mutex ? val->v_mutex->amt_name : "",
! 1304: val->v_mutex ? val->v_mutex->amt_ref_count : 0);
! 1305: break;
! 1306: case AML_OBJTYPE_EVENT:
! 1307: printf(" event:\n");
! 1308: break;
! 1309: case AML_OBJTYPE_OPREGION:
! 1310: printf(" opregion: %.2x,%.8llx,%x\n",
! 1311: val->v_opregion.iospace, val->v_opregion.iobase,
! 1312: val->v_opregion.iolen);
! 1313: break;
! 1314: case AML_OBJTYPE_NAMEREF:
! 1315: printf(" nameref: %s\n", aml_getname(val->v_nameref));
! 1316: break;
! 1317: case AML_OBJTYPE_DEVICE:
! 1318: printf(" device:\n");
! 1319: break;
! 1320: case AML_OBJTYPE_PROCESSOR:
! 1321: printf(" cpu: %.2x,%.4x,%.2x\n",
! 1322: val->v_processor.proc_id, val->v_processor.proc_addr,
! 1323: val->v_processor.proc_len);
! 1324: break;
! 1325: case AML_OBJTYPE_THERMZONE:
! 1326: printf(" thermzone:\n");
! 1327: break;
! 1328: case AML_OBJTYPE_POWERRSRC:
! 1329: printf(" pwrrsrc: %.2x,%.2x\n",
! 1330: val->v_powerrsrc.pwr_level, val->v_powerrsrc.pwr_order);
! 1331: break;
! 1332: case AML_OBJTYPE_OBJREF:
! 1333: printf(" objref: %p index:%x\n", val->v_objref.ref,
! 1334: val->v_objref.index);
! 1335: aml_showvalue(val->v_objref.ref, lvl);
! 1336: break;
! 1337: default:
! 1338: printf(" !!type: %x\n", val->type);
! 1339: }
! 1340: }
! 1341:
! 1342: /* Perform DeRef on value. If ACPI_IOREAD, will perform buffer/IO field read */
! 1343: struct aml_value *
! 1344: aml_derefvalue(struct aml_scope *scope, struct aml_value *ref, int mode)
! 1345: {
! 1346: struct aml_node *node;
! 1347: struct aml_value *tmp;
! 1348: int64_t tmpint;
! 1349: int argc, index;
! 1350:
! 1351: for (;;) {
! 1352: switch (ref->type) {
! 1353: case AML_OBJTYPE_NAMEREF:
! 1354: node = aml_searchname(scope->node, ref->v_nameref);
! 1355: if (node == NULL || node->value == NULL)
! 1356: return ref;
! 1357: ref = node->value;
! 1358: break;
! 1359:
! 1360: case AML_OBJTYPE_OBJREF:
! 1361: index = ref->v_objref.index;
! 1362: ref = aml_dereftarget(scope, ref->v_objref.ref);
! 1363: if (index != -1) {
! 1364: if (index >= ref->length)
! 1365: aml_die("index.buf out of bounds: "
! 1366: "%d/%d\n", index, ref->length);
! 1367: switch (ref->type) {
! 1368: case AML_OBJTYPE_PACKAGE:
! 1369: ref = ref->v_package[index];
! 1370: break;
! 1371: case AML_OBJTYPE_STATICINT:
! 1372: case AML_OBJTYPE_INTEGER:
! 1373: /* Convert to temporary buffer */
! 1374: if (ref->node)
! 1375: aml_die("named integer index\n");
! 1376: tmpint = ref->v_integer;
! 1377: _aml_setvalue(ref, AML_OBJTYPE_BUFFER,
! 1378: aml_intlen>>3, &tmpint);
! 1379: /* FALLTHROUGH */
! 1380: case AML_OBJTYPE_BUFFER:
! 1381: case AML_OBJTYPE_STRING:
! 1382: /* Return contents at this index */
! 1383: tmp = aml_alloctmp(scope, 1);
! 1384: if (mode == ACPI_IOREAD) {
! 1385: /* Shortcut: return integer
! 1386: * contents of buffer at index */
! 1387: _aml_setvalue(tmp,
! 1388: AML_OBJTYPE_INTEGER,
! 1389: ref->v_buffer[index], NULL);
! 1390: } else {
! 1391: _aml_setvalue(tmp,
! 1392: AML_OBJTYPE_BUFFERFIELD,
! 1393: 0, NULL);
! 1394: tmp->v_field.type =
! 1395: AMLOP_CREATEBYTEFIELD;
! 1396: tmp->v_field.bitpos = index * 8;
! 1397: tmp->v_field.bitlen = 8;
! 1398: tmp->v_field.ref1 = ref;
! 1399: aml_addref(ref);
! 1400: }
! 1401: return tmp;
! 1402: default:
! 1403: aml_die("unknown index type: %d", ref->type);
! 1404: break;
! 1405: }
! 1406: }
! 1407: break;
! 1408:
! 1409: case AML_OBJTYPE_METHOD:
! 1410: /* Read arguments from current scope */
! 1411: argc = AML_METHOD_ARGCOUNT(ref->v_method.flags);
! 1412: tmp = aml_alloctmp(scope, argc+1);
! 1413: for (index = 0; index < argc; index++) {
! 1414: aml_parseop(scope, &tmp[index]);
! 1415: aml_addref(&tmp[index]);
! 1416: }
! 1417: ref = aml_evalmethod(scope, ref->node, argc, tmp, &tmp[argc]);
! 1418: break;
! 1419:
! 1420: case AML_OBJTYPE_BUFFERFIELD:
! 1421: case AML_OBJTYPE_FIELDUNIT:
! 1422: if (mode == ACPI_IOREAD) {
! 1423: /* Read I/O field into temporary storage */
! 1424: tmp = aml_alloctmp(scope, 1);
! 1425: aml_fieldio(scope, ref, tmp, ACPI_IOREAD);
! 1426: return tmp;
! 1427: }
! 1428: return ref;
! 1429:
! 1430: default:
! 1431: return ref;
! 1432: }
! 1433:
! 1434: }
! 1435: }
! 1436:
! 1437: int64_t
! 1438: aml_str2int(const char *str, int radix)
! 1439: {
! 1440: /* XXX: fixme */
! 1441: return 0;
! 1442: }
! 1443:
! 1444: int64_t
! 1445: aml_val2int(struct aml_value *rval)
! 1446: {
! 1447: int64_t ival = 0;
! 1448:
! 1449: if (rval == NULL) {
! 1450: dnprintf(50, "null val2int\n");
! 1451: return (0);
! 1452: }
! 1453: switch (rval->type) {
! 1454: case AML_OBJTYPE_INTEGER:
! 1455: case AML_OBJTYPE_STATICINT:
! 1456: ival = rval->v_integer;
! 1457: break;
! 1458: case AML_OBJTYPE_BUFFER:
! 1459: aml_bufcpy(&ival, 0, rval->v_buffer, 0,
! 1460: min(aml_intlen, rval->length*8));
! 1461: break;
! 1462: case AML_OBJTYPE_STRING:
! 1463: ival = (strncmp(rval->v_string, "0x", 2) == 0) ?
! 1464: aml_str2int(rval->v_string+2, 16) :
! 1465: aml_str2int(rval->v_string, 10);
! 1466: break;
! 1467: }
! 1468: return (ival);
! 1469: }
! 1470:
! 1471: /* Sets value into LHS: lhs must already be cleared */
! 1472: struct aml_value *
! 1473: _aml_setvalue(struct aml_value *lhs, int type, int64_t ival, const void *bval)
! 1474: {
! 1475: memset(&lhs->_, 0x0, sizeof(lhs->_));
! 1476:
! 1477: lhs->type = type;
! 1478: switch (lhs->type) {
! 1479: case AML_OBJTYPE_INTEGER:
! 1480: case AML_OBJTYPE_STATICINT:
! 1481: lhs->length = aml_intlen>>3;
! 1482: lhs->v_integer = ival;
! 1483: break;
! 1484: case AML_OBJTYPE_METHOD:
! 1485: lhs->v_method.flags = ival;
! 1486: lhs->v_method.fneval = bval;
! 1487: break;
! 1488: case AML_OBJTYPE_NAMEREF:
! 1489: lhs->v_nameref = (uint8_t *)bval;
! 1490: break;
! 1491: case AML_OBJTYPE_OBJREF:
! 1492: lhs->v_objref.index = ival;
! 1493: lhs->v_objref.ref = (struct aml_value *)bval;
! 1494: break;
! 1495: case AML_OBJTYPE_BUFFER:
! 1496: lhs->length = ival;
! 1497: lhs->v_buffer = (uint8_t *)acpi_os_malloc(ival);
! 1498: if (bval)
! 1499: memcpy(lhs->v_buffer, bval, ival);
! 1500: break;
! 1501: case AML_OBJTYPE_STRING:
! 1502: if (ival == -1)
! 1503: ival = strlen((const char *)bval);
! 1504: lhs->length = ival;
! 1505: lhs->v_string = (char *)acpi_os_malloc(ival+1);
! 1506: if (bval)
! 1507: strncpy(lhs->v_string, (const char *)bval, ival);
! 1508: break;
! 1509: case AML_OBJTYPE_PACKAGE:
! 1510: lhs->length = ival;
! 1511: lhs->v_package = (struct aml_value **)acpi_os_malloc(ival *
! 1512: sizeof(struct aml_value *));
! 1513: for (ival = 0; ival < lhs->length; ival++)
! 1514: lhs->v_package[ival] = aml_allocvalue(
! 1515: AML_OBJTYPE_UNINITIALIZED, 0, NULL);
! 1516: break;
! 1517: }
! 1518: return lhs;
! 1519: }
! 1520:
! 1521: /* Copy object to another value: lhs must already be cleared */
! 1522: void
! 1523: aml_copyvalue(struct aml_value *lhs, struct aml_value *rhs)
! 1524: {
! 1525: int idx;
! 1526:
! 1527: lhs->type = rhs->type & ~AML_STATIC;
! 1528: switch (lhs->type) {
! 1529: case AML_OBJTYPE_UNINITIALIZED:
! 1530: break;
! 1531: case AML_OBJTYPE_STATICINT:
! 1532: case AML_OBJTYPE_INTEGER:
! 1533: lhs->length = aml_intlen>>3;
! 1534: lhs->v_integer = rhs->v_integer;
! 1535: break;
! 1536: case AML_OBJTYPE_MUTEX:
! 1537: lhs->v_mutex = rhs->v_mutex;
! 1538: break;
! 1539: case AML_OBJTYPE_POWERRSRC:
! 1540: lhs->v_powerrsrc = rhs->v_powerrsrc;
! 1541: break;
! 1542: case AML_OBJTYPE_METHOD:
! 1543: lhs->v_method = rhs->v_method;
! 1544: break;
! 1545: case AML_OBJTYPE_BUFFER:
! 1546: _aml_setvalue(lhs, rhs->type, rhs->length, rhs->v_buffer);
! 1547: break;
! 1548: case AML_OBJTYPE_STRING:
! 1549: _aml_setvalue(lhs, rhs->type, rhs->length, rhs->v_string);
! 1550: break;
! 1551: case AML_OBJTYPE_OPREGION:
! 1552: lhs->v_opregion = rhs->v_opregion;
! 1553: break;
! 1554: case AML_OBJTYPE_PROCESSOR:
! 1555: lhs->v_processor = rhs->v_processor;
! 1556: break;
! 1557: case AML_OBJTYPE_NAMEREF:
! 1558: lhs->v_nameref = rhs->v_nameref;
! 1559: break;
! 1560: case AML_OBJTYPE_PACKAGE:
! 1561: _aml_setvalue(lhs, rhs->type, rhs->length, NULL);
! 1562: for (idx = 0; idx < rhs->length; idx++)
! 1563: aml_copyvalue(lhs->v_package[idx], rhs->v_package[idx]);
! 1564: break;
! 1565: case AML_OBJTYPE_OBJREF:
! 1566: lhs->v_objref = rhs->v_objref;
! 1567: break;
! 1568: default:
! 1569: printf("copyvalue: %x", rhs->type);
! 1570: break;
! 1571: }
! 1572: }
! 1573:
! 1574: int is_local(struct aml_scope *, struct aml_value *);
! 1575:
! 1576: int is_local(struct aml_scope *scope, struct aml_value *val)
! 1577: {
! 1578: return val->stack;
! 1579: }
! 1580:
! 1581: /* Guts of the code: Assign one value to another. LHS may contain a previous value */
! 1582: void
! 1583: aml_setvalue(struct aml_scope *scope, struct aml_value *lhs,
! 1584: struct aml_value *rhs, int64_t ival)
! 1585: {
! 1586: struct aml_value tmpint;
! 1587:
! 1588: /* Use integer as result */
! 1589: if (rhs == NULL) {
! 1590: memset(&tmpint, 0, sizeof(tmpint));
! 1591: rhs = _aml_setvalue(&tmpint, AML_OBJTYPE_INTEGER, ival, NULL);
! 1592: }
! 1593:
! 1594: if (is_local(scope, lhs)) {
! 1595: /* ACPI: Overwrite writing to LocalX */
! 1596: aml_freevalue(lhs);
! 1597: }
! 1598: else {
! 1599: lhs = aml_dereftarget(scope, lhs);
! 1600: }
! 1601:
! 1602: switch (lhs->type) {
! 1603: case AML_OBJTYPE_UNINITIALIZED:
! 1604: aml_copyvalue(lhs, rhs);
! 1605: break;
! 1606: case AML_OBJTYPE_BUFFERFIELD:
! 1607: case AML_OBJTYPE_FIELDUNIT:
! 1608: aml_fieldio(scope, lhs, rhs, ACPI_IOWRITE);
! 1609: break;
! 1610: case AML_OBJTYPE_DEBUGOBJ:
! 1611: #ifdef ACPI_DEBUG
! 1612: printf("-- debug --\n");
! 1613: aml_showvalue(rhs, 50);
! 1614: #endif
! 1615: break;
! 1616: case AML_OBJTYPE_STATICINT:
! 1617: if (lhs->node) {
! 1618: lhs->v_integer = aml_val2int(rhs);
! 1619: }
! 1620: break;
! 1621: case AML_OBJTYPE_INTEGER:
! 1622: lhs->v_integer = aml_val2int(rhs);
! 1623: break;
! 1624: case AML_OBJTYPE_BUFFER:
! 1625: if (lhs->node)
! 1626: dnprintf(40, "named.buffer\n");
! 1627: aml_freevalue(lhs);
! 1628: if (rhs->type == AML_OBJTYPE_BUFFER)
! 1629: _aml_setvalue(lhs, AML_OBJTYPE_BUFFER, rhs->length,
! 1630: rhs->v_buffer);
! 1631: else if (rhs->type == AML_OBJTYPE_INTEGER ||
! 1632: rhs->type == AML_OBJTYPE_STATICINT)
! 1633: _aml_setvalue(lhs, AML_OBJTYPE_BUFFER,
! 1634: sizeof(rhs->v_integer), &rhs->v_integer);
! 1635: else if (rhs->type == AML_OBJTYPE_STRING)
! 1636: _aml_setvalue(lhs, AML_OBJTYPE_BUFFER, rhs->length+1,
! 1637: rhs->v_string);
! 1638: else {
! 1639: /* aml_showvalue(rhs); */
! 1640: aml_die("setvalue.buf : %x", aml_pc(scope->pos));
! 1641: }
! 1642: break;
! 1643: case AML_OBJTYPE_STRING:
! 1644: if (lhs->node)
! 1645: dnprintf(40, "named string\n");
! 1646: aml_freevalue(lhs);
! 1647: if (rhs->type == AML_OBJTYPE_STRING)
! 1648: _aml_setvalue(lhs, AML_OBJTYPE_STRING, rhs->length,
! 1649: rhs->v_string);
! 1650: else if (rhs->type == AML_OBJTYPE_BUFFER)
! 1651: _aml_setvalue(lhs, AML_OBJTYPE_STRING, rhs->length,
! 1652: rhs->v_buffer);
! 1653: else if (rhs->type == AML_OBJTYPE_INTEGER || rhs->type == AML_OBJTYPE_STATICINT) {
! 1654: _aml_setvalue(lhs, AML_OBJTYPE_STRING, 10, NULL);
! 1655: snprintf(lhs->v_string, lhs->length, "%lld",
! 1656: rhs->v_integer);
! 1657: } else {
! 1658: //aml_showvalue(rhs);
! 1659: aml_die("setvalue.str");
! 1660: }
! 1661: break;
! 1662: default:
! 1663: /* XXX: */
! 1664: dnprintf(10, "setvalue.unknown: %x", lhs->type);
! 1665: break;
! 1666: }
! 1667: }
! 1668:
! 1669: /* Allocate dynamic AML value
! 1670: * type : Type of object to allocate (AML_OBJTYPE_XXXX)
! 1671: * ival : Integer value (action depends on type)
! 1672: * bval : Buffer value (action depends on type)
! 1673: */
! 1674: struct aml_value *
! 1675: aml_allocvalue(int type, int64_t ival, const void *bval)
! 1676: {
! 1677: struct aml_value *rv;
! 1678:
! 1679: rv = (struct aml_value *)acpi_os_malloc(sizeof(struct aml_value));
! 1680: if (rv != NULL) {
! 1681: aml_addref(rv);
! 1682: return _aml_setvalue(rv, type, ival, bval);
! 1683: }
! 1684: return NULL;
! 1685: }
! 1686:
! 1687: void
! 1688: aml_freevalue(struct aml_value *val)
! 1689: {
! 1690: int idx;
! 1691:
! 1692: if (val == NULL)
! 1693: return;
! 1694: switch (val->type) {
! 1695: case AML_OBJTYPE_STRING:
! 1696: acpi_os_free(val->v_string);
! 1697: break;
! 1698: case AML_OBJTYPE_BUFFER:
! 1699: acpi_os_free(val->v_buffer);
! 1700: break;
! 1701: case AML_OBJTYPE_PACKAGE:
! 1702: for (idx = 0; idx < val->length; idx++) {
! 1703: aml_freevalue(val->v_package[idx]);
! 1704: acpi_os_free(val->v_package[idx]);
! 1705: }
! 1706: acpi_os_free(val->v_package);
! 1707: break;
! 1708: case AML_OBJTYPE_BUFFERFIELD:
! 1709: case AML_OBJTYPE_FIELDUNIT:
! 1710: aml_delref(&val->v_field.ref1);
! 1711: aml_delref(&val->v_field.ref2);
! 1712: break;
! 1713: }
! 1714: val->type = 0;
! 1715: memset(&val->_, 0, sizeof(val->_));
! 1716: }
! 1717:
! 1718: /* Increase reference count */
! 1719: void
! 1720: aml_addref(struct aml_value *val)
! 1721: {
! 1722: if (val)
! 1723: val->refcnt++;
! 1724: }
! 1725:
! 1726: /* Decrease reference count + delete value */
! 1727:
! 1728: void
! 1729: _aml_delref(struct aml_value **val, const char *fn, int line)
! 1730: {
! 1731: if (val == NULL || *val == NULL)
! 1732: return;
! 1733: if ((*val)->stack > 0) {
! 1734: /* Don't delete locals */
! 1735: return;
! 1736: }
! 1737: if ((*val)->refcnt & ~0xFF)
! 1738: printf("-- invalid ref: %x:%s:%d\n", (*val)->refcnt, fn, line);
! 1739: if (--(*val)->refcnt == 0) {
! 1740: aml_freevalue(*val);
! 1741: acpi_os_free(*val);
! 1742: *val = NULL;
! 1743: }
! 1744: }
! 1745:
! 1746: /*
! 1747: * @@@: Math eval routines
! 1748: */
! 1749:
! 1750: /* Convert number from one radix to another
! 1751: * Used in BCD conversion routines */
! 1752: u_int64_t
! 1753: aml_convradix(u_int64_t val, int iradix, int oradix)
! 1754: {
! 1755: u_int64_t rv = 0, pwr;
! 1756:
! 1757: rv = 0;
! 1758: pwr = 1;
! 1759: while (val) {
! 1760: rv += (val % iradix) * pwr;
! 1761: val /= iradix;
! 1762: pwr *= oradix;
! 1763: }
! 1764: return rv;
! 1765: }
! 1766:
! 1767: /* Calculate LSB */
! 1768: int
! 1769: aml_lsb(u_int64_t val)
! 1770: {
! 1771: int lsb;
! 1772:
! 1773: if (val == 0)
! 1774: return (0);
! 1775:
! 1776: for (lsb = 1; !(val & 0x1); lsb++)
! 1777: val >>= 1;
! 1778:
! 1779: return (lsb);
! 1780: }
! 1781:
! 1782: /* Calculate MSB */
! 1783: int
! 1784: aml_msb(u_int64_t val)
! 1785: {
! 1786: int msb;
! 1787:
! 1788: if (val == 0)
! 1789: return (0);
! 1790:
! 1791: for (msb = 1; val != 0x1; msb++)
! 1792: val >>= 1;
! 1793:
! 1794: return (msb);
! 1795: }
! 1796:
! 1797: /* Evaluate Math operands */
! 1798: int64_t
! 1799: aml_evalexpr(int64_t lhs, int64_t rhs, int opcode)
! 1800: {
! 1801: int64_t res;
! 1802:
! 1803: switch (opcode) {
! 1804: /* Math operations */
! 1805: case AMLOP_INCREMENT:
! 1806: case AMLOP_ADD:
! 1807: res = (lhs + rhs);
! 1808: break;
! 1809: case AMLOP_DECREMENT:
! 1810: case AMLOP_SUBTRACT:
! 1811: res = (lhs - rhs);
! 1812: break;
! 1813: case AMLOP_MULTIPLY:
! 1814: res = (lhs * rhs);
! 1815: break;
! 1816: case AMLOP_DIVIDE:
! 1817: res = (lhs / rhs);
! 1818: break;
! 1819: case AMLOP_MOD:
! 1820: res = (lhs % rhs);
! 1821: break;
! 1822: case AMLOP_SHL:
! 1823: res = (lhs << rhs);
! 1824: break;
! 1825: case AMLOP_SHR:
! 1826: res = (lhs >> rhs);
! 1827: break;
! 1828: case AMLOP_AND:
! 1829: res = (lhs & rhs);
! 1830: break;
! 1831: case AMLOP_NAND:
! 1832: res = ~(lhs & rhs);
! 1833: break;
! 1834: case AMLOP_OR:
! 1835: res = (lhs | rhs);
! 1836: break;
! 1837: case AMLOP_NOR:
! 1838: res = ~(lhs | rhs);
! 1839: break;
! 1840: case AMLOP_XOR:
! 1841: res = (lhs ^ rhs);
! 1842: break;
! 1843: case AMLOP_NOT:
! 1844: res = ~(lhs);
! 1845: break;
! 1846:
! 1847: /* Conversion/misc */
! 1848: case AMLOP_FINDSETLEFTBIT:
! 1849: res = aml_msb(lhs);
! 1850: break;
! 1851: case AMLOP_FINDSETRIGHTBIT:
! 1852: res = aml_lsb(lhs);
! 1853: break;
! 1854: case AMLOP_TOINTEGER:
! 1855: res = (lhs);
! 1856: break;
! 1857: case AMLOP_FROMBCD:
! 1858: res = aml_convradix(lhs, 16, 10);
! 1859: break;
! 1860: case AMLOP_TOBCD:
! 1861: res = aml_convradix(lhs, 10, 16);
! 1862: break;
! 1863:
! 1864: /* Logical/Comparison */
! 1865: case AMLOP_LAND:
! 1866: res = (lhs && rhs);
! 1867: break;
! 1868: case AMLOP_LOR:
! 1869: res = (lhs || rhs);
! 1870: break;
! 1871: case AMLOP_LNOT:
! 1872: res = (!lhs);
! 1873: break;
! 1874: case AMLOP_LNOTEQUAL:
! 1875: res = (lhs != rhs);
! 1876: break;
! 1877: case AMLOP_LLESSEQUAL:
! 1878: res = (lhs <= rhs);
! 1879: break;
! 1880: case AMLOP_LGREATEREQUAL:
! 1881: res = (lhs >= rhs);
! 1882: break;
! 1883: case AMLOP_LEQUAL:
! 1884: res = (lhs == rhs);
! 1885: break;
! 1886: case AMLOP_LGREATER:
! 1887: res = (lhs > rhs);
! 1888: break;
! 1889: case AMLOP_LLESS:
! 1890: res = (lhs < rhs);
! 1891: break;
! 1892: }
! 1893:
! 1894: dnprintf(50,"aml_evalexpr: %s %llx %llx = %llx\n",
! 1895: aml_mnem(opcode, NULL), lhs, rhs, res);
! 1896:
! 1897: return res;
! 1898: }
! 1899:
! 1900: int
! 1901: aml_cmpvalue(struct aml_value *lhs, struct aml_value *rhs, int opcode)
! 1902: {
! 1903: int rc, lt, rt;
! 1904:
! 1905: rc = 0;
! 1906: lt = lhs->type & ~AML_STATIC;
! 1907: rt = rhs->type & ~AML_STATIC;
! 1908: if (lt == rt) {
! 1909: switch (lt) {
! 1910: case AML_OBJTYPE_STATICINT:
! 1911: case AML_OBJTYPE_INTEGER:
! 1912: rc = (lhs->v_integer - rhs->v_integer);
! 1913: break;
! 1914: case AML_OBJTYPE_STRING:
! 1915: rc = strncmp(lhs->v_string, rhs->v_string,
! 1916: min(lhs->length, rhs->length));
! 1917: if (rc == 0)
! 1918: rc = lhs->length - rhs->length;
! 1919: break;
! 1920: case AML_OBJTYPE_BUFFER:
! 1921: rc = memcmp(lhs->v_buffer, rhs->v_buffer,
! 1922: min(lhs->length, rhs->length));
! 1923: if (rc == 0)
! 1924: rc = lhs->length - rhs->length;
! 1925: break;
! 1926: }
! 1927: } else if (lt == AML_OBJTYPE_INTEGER) {
! 1928: rc = lhs->v_integer - aml_val2int(rhs);
! 1929: } else if (rt == AML_OBJTYPE_INTEGER) {
! 1930: rc = aml_val2int(lhs) - rhs->v_integer;
! 1931: } else {
! 1932: aml_die("mismatched compare\n");
! 1933: }
! 1934: return aml_evalexpr(rc, 0, opcode);
! 1935: }
! 1936:
! 1937: /*
! 1938: * aml_bufcpy copies/shifts buffer data, special case for aligned transfers
! 1939: * dstPos/srcPos are bit positions within destination/source buffers
! 1940: */
! 1941: void
! 1942: aml_bufcpy(void *pvDst, int dstPos, const void *pvSrc, int srcPos, int len)
! 1943: {
! 1944: const u_int8_t *pSrc = pvSrc;
! 1945: u_int8_t *pDst = pvDst;
! 1946: int idx;
! 1947:
! 1948: if (aml_bytealigned(dstPos|srcPos|len)) {
! 1949: /* Aligned transfer: use memcpy */
! 1950: memcpy(pDst+aml_bytepos(dstPos), pSrc+aml_bytepos(srcPos),
! 1951: aml_bytelen(len));
! 1952: return;
! 1953: }
! 1954:
! 1955: /* Misaligned transfer: perform bitwise copy (slow) */
! 1956: for (idx = 0; idx < len; idx++)
! 1957: aml_setbit(pDst, idx + dstPos, aml_tstbit(pSrc, idx + srcPos));
! 1958: }
! 1959:
! 1960: struct aml_value *
! 1961: aml_callmethod(struct aml_scope *scope, struct aml_value *val)
! 1962: {
! 1963: while (scope->pos < scope->end)
! 1964: aml_parseterm(scope, val);
! 1965: return val;
! 1966: }
! 1967:
! 1968: /*
! 1969: * Evaluate an AML method
! 1970: *
! 1971: * Returns a copy of the result in res (must be freed by user)
! 1972: */
! 1973: struct aml_value *
! 1974: aml_evalmethod(struct aml_scope *parent, struct aml_node *node,
! 1975: int argc, struct aml_value *argv, struct aml_value *res)
! 1976: {
! 1977: struct aml_scope *scope;
! 1978:
! 1979: scope = aml_pushscope(parent, node->value->v_method.start,
! 1980: node->value->v_method.end, node);
! 1981: scope->args = argv;
! 1982: scope->nargs = argc;
! 1983:
! 1984: if (res == NULL)
! 1985: res = aml_alloctmp(scope, 1);
! 1986:
! 1987: #ifdef ACPI_DEBUG
! 1988: dnprintf(10, "calling [%s] (%d args)\n",
! 1989: aml_nodename(node), scope->nargs);
! 1990: for (argc = 0; argc < scope->nargs; argc++) {
! 1991: dnprintf(10, " arg%d: ", argc);
! 1992: aml_showvalue(&scope->args[argc], 10);
! 1993: }
! 1994: node->value->v_method.fneval(scope, res);
! 1995: dnprintf(10, "[%s] returns: ", aml_nodename(node));
! 1996: aml_showvalue(res, 10);
! 1997: #else
! 1998: node->value->v_method.fneval(scope, res);
! 1999: #endif
! 2000: /* Free any temporary children nodes */
! 2001: aml_delchildren(node);
! 2002: aml_popscope(scope);
! 2003:
! 2004: return res;
! 2005: }
! 2006:
! 2007: /*
! 2008: * @@@: External API
! 2009: *
! 2010: * evaluate an AML node
! 2011: * Returns a copy of the value in res (must be freed by user)
! 2012: */
! 2013: int
! 2014: aml_evalnode(struct acpi_softc *sc, struct aml_node *node,
! 2015: int argc, struct aml_value *argv, struct aml_value *res)
! 2016: {
! 2017: static int lastck;
! 2018: struct aml_node *ref;
! 2019:
! 2020: if (res)
! 2021: memset(res, 0, sizeof(struct aml_value));
! 2022: if (node == NULL || node->value == NULL)
! 2023: return (ACPI_E_BADVALUE);
! 2024:
! 2025: switch (node->value->type) {
! 2026: case AML_OBJTYPE_METHOD:
! 2027: aml_evalmethod(NULL, node, argc, argv, res);
! 2028: if (acpi_nalloc > lastck) {
! 2029: /* Check if our memory usage has increased */
! 2030: dnprintf(10, "Leaked: [%s] %d\n",
! 2031: aml_nodename(node), acpi_nalloc);
! 2032: lastck = acpi_nalloc;
! 2033: }
! 2034: break;
! 2035: case AML_OBJTYPE_STATICINT:
! 2036: case AML_OBJTYPE_INTEGER:
! 2037: case AML_OBJTYPE_STRING:
! 2038: case AML_OBJTYPE_BUFFER:
! 2039: case AML_OBJTYPE_PACKAGE:
! 2040: case AML_OBJTYPE_EVENT:
! 2041: case AML_OBJTYPE_DEVICE:
! 2042: case AML_OBJTYPE_MUTEX:
! 2043: case AML_OBJTYPE_OPREGION:
! 2044: case AML_OBJTYPE_POWERRSRC:
! 2045: case AML_OBJTYPE_PROCESSOR:
! 2046: case AML_OBJTYPE_THERMZONE:
! 2047: case AML_OBJTYPE_DEBUGOBJ:
! 2048: if (res)
! 2049: aml_copyvalue(res, node->value);
! 2050: break;
! 2051: case AML_OBJTYPE_NAMEREF:
! 2052: if (res == NULL)
! 2053: break;
! 2054: if ((ref = aml_searchname(node, node->value->v_nameref)) != NULL)
! 2055: _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, ref);
! 2056: else
! 2057: aml_copyvalue(res, node->value);
! 2058: break;
! 2059: default:
! 2060: break;
! 2061: }
! 2062: return (0);
! 2063: }
! 2064:
! 2065: /*
! 2066: * evaluate an AML name
! 2067: * Returns a copy of the value in res (must be freed by user)
! 2068: */
! 2069: int
! 2070: aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name,
! 2071: int argc, struct aml_value *argv, struct aml_value *res)
! 2072: {
! 2073: return aml_evalnode(sc, aml_searchname(parent, name), argc, argv, res);
! 2074: }
! 2075:
! 2076: int
! 2077: aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent,
! 2078: const char *name, int argc, struct aml_value *argv, int64_t *ival)
! 2079: {
! 2080: struct aml_value res;
! 2081:
! 2082: if (name != NULL)
! 2083: parent = aml_searchname(parent, name);
! 2084: if (aml_evalnode(sc, parent, argc, argv, &res) == 0) {
! 2085: *ival = aml_val2int(&res);
! 2086: aml_freevalue(&res);
! 2087: return 0;
! 2088: }
! 2089: return 1;
! 2090: }
! 2091:
! 2092: void
! 2093: aml_walknodes(struct aml_node *node, int mode,
! 2094: int (*nodecb)(struct aml_node *, void *), void *arg)
! 2095: {
! 2096: struct aml_node *child;
! 2097:
! 2098: if (node == NULL)
! 2099: return;
! 2100: if (mode == AML_WALK_PRE)
! 2101: nodecb(node, arg);
! 2102: for (child = node->child; child; child = child->sibling)
! 2103: aml_walknodes(child, mode, nodecb, arg);
! 2104: if (mode == AML_WALK_POST)
! 2105: nodecb(node, arg);
! 2106: }
! 2107:
! 2108: void
! 2109: aml_walktree(struct aml_node *node)
! 2110: {
! 2111: while (node) {
! 2112: aml_showvalue(node->value, 0);
! 2113: aml_walktree(node->child);
! 2114: node = node->sibling;
! 2115: }
! 2116: }
! 2117:
! 2118: void
! 2119: aml_walkroot(void)
! 2120: {
! 2121: aml_walktree(aml_root.child);
! 2122: }
! 2123:
! 2124: int
! 2125: aml_find_node(struct aml_node *node, const char *name,
! 2126: void (*cbproc)(struct aml_node *, void *arg), void *arg)
! 2127: {
! 2128: const char *nn;
! 2129:
! 2130: while (node) {
! 2131: if ((nn = node->name) != NULL) {
! 2132: if (*nn == AMLOP_ROOTCHAR) nn++;
! 2133: while (*nn == AMLOP_PARENTPREFIX) nn++;
! 2134: if (!strcmp(name, nn))
! 2135: cbproc(node, arg);
! 2136: }
! 2137: aml_find_node(node->child, name, cbproc, arg);
! 2138: node = node->sibling;
! 2139: }
! 2140: return (0);
! 2141: }
! 2142:
! 2143: /*
! 2144: * @@@: Parser functions
! 2145: */
! 2146: uint8_t *aml_parsename(struct aml_scope *);
! 2147: uint8_t *aml_parseend(struct aml_scope *scope);
! 2148: int aml_parselength(struct aml_scope *);
! 2149: int aml_parseopcode(struct aml_scope *);
! 2150:
! 2151: /* Get AML Opcode */
! 2152: int
! 2153: aml_parseopcode(struct aml_scope *scope)
! 2154: {
! 2155: int opcode = (scope->pos[0]);
! 2156: int twocode = (scope->pos[0]<<8) + scope->pos[1];
! 2157:
! 2158: /* Check if this is an embedded name */
! 2159: switch (opcode) {
! 2160: case AMLOP_ROOTCHAR:
! 2161: case AMLOP_PARENTPREFIX:
! 2162: case AMLOP_MULTINAMEPREFIX:
! 2163: case AMLOP_DUALNAMEPREFIX:
! 2164: case AMLOP_NAMECHAR:
! 2165: case 'A' ... 'Z':
! 2166: return AMLOP_NAMECHAR;
! 2167: }
! 2168: if (twocode == AMLOP_LNOTEQUAL || twocode == AMLOP_LLESSEQUAL ||
! 2169: twocode == AMLOP_LGREATEREQUAL || opcode == AMLOP_EXTPREFIX) {
! 2170: scope->pos += 2;
! 2171: return twocode;
! 2172: }
! 2173: scope->pos += 1;
! 2174: return opcode;
! 2175: }
! 2176:
! 2177: /* Decode embedded AML Namestring */
! 2178: uint8_t *
! 2179: aml_parsename(struct aml_scope *scope)
! 2180: {
! 2181: uint8_t *name = scope->pos;
! 2182:
! 2183: while (*scope->pos == AMLOP_ROOTCHAR || *scope->pos == AMLOP_PARENTPREFIX)
! 2184: scope->pos++;
! 2185:
! 2186: switch (*scope->pos) {
! 2187: case 0x00:
! 2188: break;
! 2189: case AMLOP_MULTINAMEPREFIX:
! 2190: scope->pos += 2+AML_NAMESEG_LEN*scope->pos[1];
! 2191: break;
! 2192: case AMLOP_DUALNAMEPREFIX:
! 2193: scope->pos += 1+AML_NAMESEG_LEN*2;
! 2194: break;
! 2195: default:
! 2196: scope->pos += AML_NAMESEG_LEN;
! 2197: break;
! 2198: }
! 2199: return name;
! 2200: }
! 2201:
! 2202: /* Decode AML Length field */
! 2203: int
! 2204: aml_parselength(struct aml_scope *scope)
! 2205: {
! 2206: int len = (*scope->pos & 0xF);
! 2207:
! 2208: switch (*scope->pos >> 6) {
! 2209: case 0x00:
! 2210: len = scope->pos[0] & 0x3F;
! 2211: scope->pos += 1;
! 2212: break;
! 2213: case 0x01:
! 2214: len += (scope->pos[1]<<4L);
! 2215: scope->pos += 2;
! 2216: break;
! 2217: case 0x02:
! 2218: len += (scope->pos[1]<<4L) + (scope->pos[2]<<12L);
! 2219: scope->pos += 3;
! 2220: break;
! 2221: case 0x03:
! 2222: len += (scope->pos[1]<<4L) + (scope->pos[2]<<12L) +
! 2223: (scope->pos[3]<<20L);
! 2224: scope->pos += 4;
! 2225: break;
! 2226: }
! 2227: return len;
! 2228: }
! 2229:
! 2230: /* Get address of end of scope; based on current address */
! 2231: uint8_t *
! 2232: aml_parseend(struct aml_scope *scope)
! 2233: {
! 2234: uint8_t *pos = scope->pos;
! 2235: int len;
! 2236:
! 2237: len = aml_parselength(scope);
! 2238: if (pos+len > scope->end) {
! 2239: dnprintf(10,
! 2240: "Bad scope... runover pos:%.4x new end:%.4x scope "
! 2241: "end:%.4x\n", aml_pc(pos), aml_pc(pos+len),
! 2242: aml_pc(scope->end));
! 2243: pos = scope->end;
! 2244: }
! 2245: return pos+len;
! 2246: }
! 2247:
! 2248: /*
! 2249: * @@@: Opcode utility functions
! 2250: */
! 2251: int aml_match(int, int64_t, struct aml_value *);
! 2252: void aml_fixref(struct aml_value **);
! 2253: int64_t aml_parseint(struct aml_scope *, int);
! 2254: void aml_resize(struct aml_value *val, int newsize);
! 2255:
! 2256: void
! 2257: aml_resize(struct aml_value *val, int newsize)
! 2258: {
! 2259: void *oldptr;
! 2260: int oldsize;
! 2261:
! 2262: if (val->length >= newsize)
! 2263: return;
! 2264: oldsize = val->length;
! 2265: switch (val->type) {
! 2266: case AML_OBJTYPE_BUFFER:
! 2267: oldptr = val->v_buffer;
! 2268: _aml_setvalue(val, val->type, newsize, NULL);
! 2269: memcpy(val->v_buffer, oldptr, oldsize);
! 2270: acpi_os_free(oldptr);
! 2271: break;
! 2272: case AML_OBJTYPE_STRING:
! 2273: oldptr = val->v_string;
! 2274: _aml_setvalue(val, val->type, newsize+1, NULL);
! 2275: memcpy(val->v_string, oldptr, oldsize);
! 2276: acpi_os_free(oldptr);
! 2277: break;
! 2278: }
! 2279: }
! 2280:
! 2281:
! 2282: int
! 2283: aml_match(int op, int64_t mv1, struct aml_value *mv2)
! 2284: {
! 2285: struct aml_value tmpint;
! 2286:
! 2287: memset(&tmpint, 0, sizeof(tmpint));
! 2288: _aml_setvalue(&tmpint, AML_OBJTYPE_INTEGER, mv1, NULL);
! 2289: switch (op) {
! 2290: case AML_MATCH_EQ:
! 2291: return aml_cmpvalue(&tmpint, mv2, AMLOP_LEQUAL);
! 2292: case AML_MATCH_LT:
! 2293: return aml_cmpvalue(&tmpint, mv2, AMLOP_LLESS);
! 2294: case AML_MATCH_LE:
! 2295: return aml_cmpvalue(&tmpint, mv2, AMLOP_LLESSEQUAL);
! 2296: case AML_MATCH_GE:
! 2297: return aml_cmpvalue(&tmpint, mv2, AMLOP_LGREATEREQUAL);
! 2298: case AML_MATCH_GT:
! 2299: return aml_cmpvalue(&tmpint, mv2, AMLOP_LGREATER);
! 2300: }
! 2301: return (1);
! 2302: }
! 2303:
! 2304: int amlop_delay;
! 2305:
! 2306: u_int64_t
! 2307: aml_getpciaddr(struct acpi_softc *sc, struct aml_node *root)
! 2308: {
! 2309: struct aml_value tmpres;
! 2310: u_int64_t pciaddr;
! 2311:
! 2312: /* PCI */
! 2313: pciaddr = 0;
! 2314: if (!aml_evalname(dsdt_softc, root, "_ADR", 0, NULL, &tmpres)) {
! 2315: /* Device:Function are bits 16-31,32-47 */
! 2316: pciaddr += (aml_val2int(&tmpres) << 16L);
! 2317: aml_freevalue(&tmpres);
! 2318: dnprintf(20, "got _adr [%s]\n", aml_nodename(root));
! 2319: } else {
! 2320: /* Mark invalid */
! 2321: pciaddr += (0xFFFF << 16L);
! 2322: return pciaddr;
! 2323: }
! 2324:
! 2325: if (!aml_evalname(dsdt_softc, root, "_BBN", 0, NULL, &tmpres)) {
! 2326: /* PCI bus is in bits 48-63 */
! 2327: pciaddr += (aml_val2int(&tmpres) << 48L);
! 2328: aml_freevalue(&tmpres);
! 2329: dnprintf(20, "got _bbn [%s]\n", aml_nodename(root));
! 2330: }
! 2331: dnprintf(20, "got pciaddr: %s:%llx\n", aml_nodename(root), pciaddr);
! 2332: return pciaddr;
! 2333: }
! 2334:
! 2335: /* Fixup references for BufferFields/FieldUnits */
! 2336: void
! 2337: aml_fixref(struct aml_value **res)
! 2338: {
! 2339: struct aml_value *oldres;
! 2340:
! 2341: while (*res && (*res)->type == AML_OBJTYPE_OBJREF &&
! 2342: (*res)->v_objref.index == -1) {
! 2343: oldres = (*res)->v_objref.ref;
! 2344: aml_delref(res);
! 2345: aml_addref(oldres);
! 2346: *res = oldres;
! 2347: }
! 2348: }
! 2349:
! 2350: int64_t
! 2351: aml_parseint(struct aml_scope *scope, int opcode)
! 2352: {
! 2353: uint8_t *np = scope->pos;
! 2354: struct aml_value *tmpval;
! 2355: int64_t rval;
! 2356:
! 2357: if (opcode == AML_ANYINT)
! 2358: opcode = aml_parseopcode(scope);
! 2359: switch (opcode) {
! 2360: case AMLOP_ZERO:
! 2361: rval = 0;
! 2362: break;
! 2363: case AMLOP_ONE:
! 2364: rval = 1;
! 2365: break;
! 2366: case AMLOP_ONES:
! 2367: rval = -1;
! 2368: break;
! 2369: case AMLOP_REVISION:
! 2370: rval = AML_REVISION;
! 2371: break;
! 2372: case AMLOP_BYTEPREFIX:
! 2373: np = scope->pos;
! 2374: rval = *(uint8_t *)scope->pos;
! 2375: scope->pos += 1;
! 2376: break;
! 2377: case AMLOP_WORDPREFIX:
! 2378: np = scope->pos;
! 2379: rval = aml_letohost16(*(uint16_t *)scope->pos);
! 2380: scope->pos += 2;
! 2381: break;
! 2382: case AMLOP_DWORDPREFIX:
! 2383: np = scope->pos;
! 2384: rval = aml_letohost32(*(uint32_t *)scope->pos);
! 2385: scope->pos += 4;
! 2386: break;
! 2387: case AMLOP_QWORDPREFIX:
! 2388: np = scope->pos;
! 2389: rval = aml_letohost64(*(uint64_t *)scope->pos);
! 2390: scope->pos += 8;
! 2391: break;
! 2392: default:
! 2393: scope->pos = np;
! 2394: tmpval = aml_alloctmp(scope, 1);
! 2395: aml_parseterm(scope, tmpval);
! 2396: return aml_val2int(tmpval);
! 2397: }
! 2398: dnprintf(15, "%.4x: [%s] %s\n", aml_pc(scope->pos-opsize(opcode)),
! 2399: aml_nodename(scope->node), aml_mnem(opcode, np));
! 2400: return rval;
! 2401: }
! 2402:
! 2403: struct aml_value *
! 2404: aml_evaltarget(struct aml_scope *scope, struct aml_value *res)
! 2405: {
! 2406: return res;
! 2407: }
! 2408:
! 2409: int
! 2410: aml_evalterm(struct aml_scope *scope, struct aml_value *raw,
! 2411: struct aml_value *dst)
! 2412: {
! 2413: struct aml_value *deref;
! 2414:
! 2415: aml_freevalue(dst);
! 2416: deref = aml_derefterm(scope, raw, 0);
! 2417: aml_copyvalue(dst, deref);
! 2418: return 0;
! 2419: }
! 2420:
! 2421:
! 2422: /*
! 2423: * @@@: Opcode functions
! 2424: */
! 2425:
! 2426: /* Parse named objects */
! 2427: struct aml_value *
! 2428: aml_parsenamed(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2429: {
! 2430: uint8_t *name;
! 2431: int s, offs = 0;
! 2432:
! 2433: AML_CHECKSTACK();
! 2434: name = aml_parsename(scope);
! 2435:
! 2436: res = aml_allocvalue(AML_OBJTYPE_UNINITIALIZED, 0, NULL);
! 2437: switch (opcode) {
! 2438: case AMLOP_NAME:
! 2439: aml_parseop(scope, res);
! 2440: break;
! 2441: case AMLOP_ALIAS:
! 2442: _aml_setvalue(res, AML_OBJTYPE_NAMEREF, 0, name);
! 2443: name = aml_parsename(scope);
! 2444: break;
! 2445: case AMLOP_EVENT:
! 2446: _aml_setvalue(res, AML_OBJTYPE_EVENT, 0, NULL);
! 2447: break;
! 2448: case AMLOP_MUTEX:
! 2449: /* XXX mutex is unused since we don't have concurrency */
! 2450: _aml_setvalue(res, AML_OBJTYPE_MUTEX, 0, NULL);
! 2451: res->v_mutex = (struct acpi_mutex *)acpi_os_malloc(
! 2452: sizeof(struct acpi_mutex));
! 2453: res->v_mutex->amt_synclevel = aml_parseint(scope,
! 2454: AMLOP_BYTEPREFIX);
! 2455: s = strlen(aml_getname(name));
! 2456: if (s > 4)
! 2457: offs = s - 4;
! 2458: strlcpy(res->v_mutex->amt_name, aml_getname(name) + offs,
! 2459: ACPI_MTX_MAXNAME);
! 2460: rw_init(&res->v_mutex->amt_lock, res->v_mutex->amt_name);
! 2461: break;
! 2462: case AMLOP_OPREGION:
! 2463: _aml_setvalue(res, AML_OBJTYPE_OPREGION, 0, NULL);
! 2464: res->v_opregion.iospace = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2465: res->v_opregion.iobase = aml_parseint(scope, AML_ANYINT);
! 2466: res->v_opregion.iolen = aml_parseint(scope, AML_ANYINT);
! 2467: if (res->v_opregion.iospace == GAS_PCI_CFG_SPACE) {
! 2468: res->v_opregion.iobase += aml_getpciaddr(dsdt_softc,
! 2469: scope->node);
! 2470: dnprintf(20, "got ioaddr: %s.%s:%llx\n",
! 2471: aml_nodename(scope->node), aml_getname(name),
! 2472: res->v_opregion.iobase);
! 2473: }
! 2474: break;
! 2475: }
! 2476: aml_createname(scope->node, name, res);
! 2477:
! 2478: return res;
! 2479: }
! 2480:
! 2481: /* Parse Named objects with scope */
! 2482: struct aml_value *
! 2483: aml_parsenamedscope(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2484: {
! 2485: uint8_t *end, *name;
! 2486: struct aml_node *node;
! 2487:
! 2488: AML_CHECKSTACK();
! 2489: end = aml_parseend(scope);
! 2490: name = aml_parsename(scope);
! 2491:
! 2492: switch (opcode) {
! 2493: case AMLOP_DEVICE:
! 2494: res = aml_allocvalue(AML_OBJTYPE_DEVICE, 0, NULL);
! 2495: break;
! 2496: case AMLOP_SCOPE:
! 2497: res = NULL;
! 2498: break;
! 2499: case AMLOP_PROCESSOR:
! 2500: res = aml_allocvalue(AML_OBJTYPE_PROCESSOR, 0, NULL);
! 2501: res->v_processor.proc_id = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2502: res->v_processor.proc_addr = aml_parseint(scope, AMLOP_DWORDPREFIX);
! 2503: res->v_processor.proc_len = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2504: break;
! 2505: case AMLOP_POWERRSRC:
! 2506: res = aml_allocvalue(AML_OBJTYPE_POWERRSRC, 0, NULL);
! 2507: res->v_powerrsrc.pwr_level = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2508: res->v_powerrsrc.pwr_order = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2509: break;
! 2510: case AMLOP_THERMALZONE:
! 2511: res = aml_allocvalue(AML_OBJTYPE_THERMZONE, 0, NULL);
! 2512: break;
! 2513: }
! 2514: node = aml_createname(scope->node, name, res);
! 2515: aml_parsenode(scope, node, scope->pos, &end, NULL);
! 2516: scope->pos = end;
! 2517:
! 2518: return res;
! 2519: }
! 2520:
! 2521: /* Parse math opcodes */
! 2522: struct aml_value *
! 2523: aml_parsemath(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2524: {
! 2525: struct aml_value *tmparg;
! 2526: int64_t i1, i2, i3;
! 2527:
! 2528: tmparg = aml_alloctmp(scope, 1);
! 2529: AML_CHECKSTACK();
! 2530: switch (opcode) {
! 2531: case AMLOP_LNOT:
! 2532: i2 = 0;
! 2533: i1 = aml_parseint(scope, AML_ANYINT);
! 2534: break;
! 2535: case AMLOP_LAND:
! 2536: case AMLOP_LOR:
! 2537: i1 = aml_parseint(scope, AML_ANYINT);
! 2538: i2 = aml_parseint(scope, AML_ANYINT);
! 2539: break;
! 2540: case AMLOP_NOT:
! 2541: case AMLOP_TOBCD:
! 2542: case AMLOP_FROMBCD:
! 2543: case AMLOP_TOINTEGER:
! 2544: case AMLOP_FINDSETLEFTBIT:
! 2545: case AMLOP_FINDSETRIGHTBIT:
! 2546: i2 = 0;
! 2547: i1 = aml_parseint(scope, AML_ANYINT);
! 2548: aml_parsetarget(scope, tmparg, NULL);
! 2549: break;
! 2550: case AMLOP_INCREMENT:
! 2551: case AMLOP_DECREMENT:
! 2552: aml_parsetarget(scope, tmparg, NULL);
! 2553: i1 = aml_val2int(aml_derefterm(scope, tmparg, 0));
! 2554: i2 = 1;
! 2555: break;
! 2556: case AMLOP_DIVIDE:
! 2557: i1 = aml_parseint(scope, AML_ANYINT);
! 2558: i2 = aml_parseint(scope, AML_ANYINT);
! 2559:
! 2560: aml_parsetarget(scope, tmparg, NULL); // remainder
! 2561: aml_setvalue(scope, tmparg, NULL, (i1 % i2));
! 2562:
! 2563: aml_parsetarget(scope, tmparg, NULL); // quotient
! 2564: break;
! 2565: default:
! 2566: i1 = aml_parseint(scope, AML_ANYINT);
! 2567: i2 = aml_parseint(scope, AML_ANYINT);
! 2568: aml_parsetarget(scope, tmparg, NULL);
! 2569: break;
! 2570: }
! 2571: i3 = aml_evalexpr(i1, i2, opcode);
! 2572: aml_setvalue(scope, res, NULL, i3);
! 2573: aml_setvalue(scope, tmparg, NULL, i3);
! 2574: return (res);
! 2575: }
! 2576:
! 2577: /* Parse logical comparison opcodes */
! 2578: struct aml_value *
! 2579: aml_parsecompare(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2580: {
! 2581: struct aml_value *tmparg;
! 2582: int rc;
! 2583:
! 2584: AML_CHECKSTACK();
! 2585: tmparg = aml_alloctmp(scope, 2);
! 2586: aml_parseterm(scope, &tmparg[AML_LHS]);
! 2587: aml_parseterm(scope, &tmparg[AML_RHS]);
! 2588:
! 2589: /* Compare both values */
! 2590: rc = aml_cmpvalue(&tmparg[AML_LHS], &tmparg[AML_RHS], opcode);
! 2591: aml_setvalue(scope, res, NULL, rc);
! 2592:
! 2593: return res;
! 2594: }
! 2595:
! 2596: /* Parse IF/ELSE opcodes */
! 2597: struct aml_value *
! 2598: aml_parseif(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2599: {
! 2600: int64_t test;
! 2601: uint8_t *end;
! 2602:
! 2603: AML_CHECKSTACK();
! 2604: end = aml_parseend(scope);
! 2605: test = aml_parseint(scope, AML_ANYINT);
! 2606:
! 2607: dnprintf(40, "@ iftest: %llx\n", test);
! 2608: while (test && scope->pos < end) {
! 2609: /* Parse if scope */
! 2610: aml_parseterm(scope, res);
! 2611: }
! 2612: if (scope->pos >= scope->end)
! 2613: return res;
! 2614:
! 2615: if (*end == AMLOP_ELSE) {
! 2616: scope->pos = ++end;
! 2617: end = aml_parseend(scope);
! 2618: while (!test && scope->pos < end) {
! 2619: /* Parse ELSE scope */
! 2620: aml_parseterm(scope, res);
! 2621: }
! 2622: }
! 2623: if (scope->pos < end)
! 2624: scope->pos = end;
! 2625: return res;
! 2626: }
! 2627:
! 2628: struct aml_value *
! 2629: aml_parsewhile(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2630: {
! 2631: uint8_t *end, *start;
! 2632: int test, cnt;
! 2633:
! 2634: AML_CHECKSTACK();
! 2635: end = aml_parseend(scope);
! 2636: start = scope->pos;
! 2637: cnt = 0;
! 2638: do {
! 2639: test = 1;
! 2640: if (scope->pos == start || scope->pos == end) {
! 2641: scope->pos = start;
! 2642: test = aml_parseint(scope, AML_ANYINT);
! 2643: dnprintf(40, "@whiletest = %d %x\n", test, cnt++);
! 2644: } else if (*scope->pos == AMLOP_BREAK) {
! 2645: scope->pos++;
! 2646: test = 0;
! 2647: } else if (*scope->pos == AMLOP_CONTINUE) {
! 2648: scope->pos = start;
! 2649: } else {
! 2650: aml_parseterm(scope, res);
! 2651: }
! 2652: } while (test && scope->pos <= end && cnt < 0x199);
! 2653: /* XXX: shouldn't need breakout counter */
! 2654:
! 2655: dnprintf(40, "Set While end : %x\n", cnt);
! 2656: if (scope->pos < end)
! 2657: scope->pos = end;
! 2658: return res;
! 2659: }
! 2660:
! 2661: /* Parse Buffer/Package opcodes */
! 2662: struct aml_value *
! 2663: aml_parsebufpkg(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2664: {
! 2665: uint8_t *end;
! 2666: int len;
! 2667:
! 2668: AML_CHECKSTACK();
! 2669: end = aml_parseend(scope);
! 2670: len = aml_parseint(scope, (opcode == AMLOP_PACKAGE) ?
! 2671: AMLOP_BYTEPREFIX : AML_ANYINT);
! 2672:
! 2673: switch (opcode) {
! 2674: case AMLOP_BUFFER:
! 2675: _aml_setvalue(res, AML_OBJTYPE_BUFFER, len, NULL);
! 2676: if (scope->pos < end) {
! 2677: memcpy(res->v_buffer, scope->pos, end-scope->pos);
! 2678: }
! 2679: if (len != end-scope->pos) {
! 2680: dnprintf(99, "buffer: %.4x %.4x\n", len, end-scope->pos);
! 2681: }
! 2682: break;
! 2683: case AMLOP_PACKAGE:
! 2684: case AMLOP_VARPACKAGE:
! 2685: _aml_setvalue(res, AML_OBJTYPE_PACKAGE, len, NULL);
! 2686: for (len = 0; len < res->length && scope->pos < end; len++) {
! 2687: aml_parseop(scope, res->v_package[len]);
! 2688: }
! 2689: if (scope->pos != end) {
! 2690: dnprintf(99, "Package not equiv!! %.4x %.4x %d of %d\n",
! 2691: aml_pc(scope->pos), aml_pc(end), len, res->length);
! 2692: }
! 2693: break;
! 2694: }
! 2695: scope->pos = end;
! 2696: return res;
! 2697: }
! 2698:
! 2699: struct aml_value *
! 2700: aml_parsemethod(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2701: {
! 2702: uint8_t *end, *name;
! 2703:
! 2704: AML_CHECKSTACK();
! 2705: end = aml_parseend(scope);
! 2706: name = aml_parsename(scope);
! 2707:
! 2708: res = aml_allocvalue(AML_OBJTYPE_METHOD, 0, NULL);
! 2709: res->v_method.flags = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2710: res->v_method.start = scope->pos;
! 2711: res->v_method.end = end;
! 2712: res->v_method.fneval = aml_callmethod;
! 2713: aml_createname(scope->node, name, res);
! 2714:
! 2715: scope->pos = end;
! 2716:
! 2717: return res;
! 2718: }
! 2719:
! 2720: /* Parse simple type opcodes */
! 2721: struct aml_value *
! 2722: aml_parsesimple(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2723: {
! 2724: struct aml_node *node;
! 2725:
! 2726: AML_CHECKSTACK();
! 2727: switch (opcode) {
! 2728: case AMLOP_ZERO:
! 2729: _aml_setvalue(res, AML_OBJTYPE_INTEGER+AML_STATIC,
! 2730: aml_parseint(scope, opcode), NULL);
! 2731: break;
! 2732: case AMLOP_ONE:
! 2733: case AMLOP_ONES:
! 2734: case AMLOP_BYTEPREFIX:
! 2735: case AMLOP_WORDPREFIX:
! 2736: case AMLOP_DWORDPREFIX:
! 2737: case AMLOP_QWORDPREFIX:
! 2738: case AMLOP_REVISION:
! 2739: _aml_setvalue(res, AML_OBJTYPE_INTEGER,
! 2740: aml_parseint(scope, opcode), NULL);
! 2741: break;
! 2742: case AMLOP_DEBUG:
! 2743: _aml_setvalue(res, AML_OBJTYPE_DEBUGOBJ, 0, NULL);
! 2744: break;
! 2745: case AMLOP_STRINGPREFIX:
! 2746: _aml_setvalue(res, AML_OBJTYPE_STRING, -1, scope->pos);
! 2747: scope->pos += res->length+1;
! 2748: break;
! 2749: case AMLOP_NAMECHAR:
! 2750: _aml_setvalue(res, AML_OBJTYPE_NAMEREF, 0, NULL);
! 2751: res->v_nameref = aml_parsename(scope);
! 2752: node = aml_searchname(scope->node, res->v_nameref);
! 2753: if (node && node->value)
! 2754: _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, node->value);
! 2755: break;
! 2756: }
! 2757: return res;
! 2758: }
! 2759:
! 2760: /* Parse field unit opcodes */
! 2761: struct aml_value *
! 2762: aml_parsefieldunit(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2763: {
! 2764: uint8_t *end, *name;
! 2765: struct aml_value *fld;
! 2766:
! 2767: AML_CHECKSTACK();
! 2768: end = aml_parseend(scope);
! 2769:
! 2770: switch (opcode) {
! 2771: case AMLOP_FIELD:
! 2772: aml_parsetarget(scope, NULL, &res->v_field.ref1);
! 2773: break;
! 2774: case AMLOP_INDEXFIELD:
! 2775: aml_parsetarget(scope, NULL, &res->v_field.ref1);
! 2776: aml_parsetarget(scope, NULL, &res->v_field.ref2);
! 2777: break;
! 2778: case AMLOP_BANKFIELD:
! 2779: aml_parsetarget(scope, NULL, &res->v_field.ref1);
! 2780: aml_parsetarget(scope, NULL, &res->v_field.ref2);
! 2781: res->v_field.ref3 = aml_parseint(scope, AML_ANYINT);
! 2782: break;
! 2783: }
! 2784: res->v_field.flags = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2785: res->v_field.type = opcode;
! 2786:
! 2787: aml_fixref(&res->v_field.ref1);
! 2788: aml_fixref(&res->v_field.ref2);
! 2789:
! 2790: while (scope->pos < end) {
! 2791: switch (*scope->pos) {
! 2792: case 0x00: // reserved
! 2793: scope->pos++;
! 2794: res->v_field.bitlen = aml_parselength(scope);
! 2795: break;
! 2796: case 0x01: // attrib
! 2797: scope->pos++;
! 2798: /* XXX: do something with this */
! 2799: aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2800: aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2801: res->v_field.bitlen = 0;
! 2802: break;
! 2803: default:
! 2804: name = aml_parsename(scope);
! 2805: res->v_field.bitlen = aml_parselength(scope);
! 2806:
! 2807: /* Allocate new fieldunit */
! 2808: fld = aml_allocvalue(AML_OBJTYPE_FIELDUNIT, 0, NULL);
! 2809:
! 2810: /* Increase reference count on field */
! 2811: fld->v_field = res->v_field;
! 2812: aml_addref(fld->v_field.ref1);
! 2813: aml_addref(fld->v_field.ref2);
! 2814:
! 2815: aml_createname(scope->node, name, fld);
! 2816: break;
! 2817: }
! 2818: res->v_field.bitpos += res->v_field.bitlen;
! 2819: }
! 2820: /* Delete redundant reference */
! 2821: aml_delref(&res->v_field.ref1);
! 2822: aml_delref(&res->v_field.ref2);
! 2823: return res;
! 2824: }
! 2825:
! 2826: /* Parse CreateXXXField opcodes */
! 2827: struct aml_value *
! 2828: aml_parsebufferfield(struct aml_scope *scope, int opcode,
! 2829: struct aml_value *res)
! 2830: {
! 2831: uint8_t *name;
! 2832:
! 2833: AML_CHECKSTACK();
! 2834: res = aml_allocvalue(AML_OBJTYPE_BUFFERFIELD, 0, NULL);
! 2835: res->v_field.type = opcode;
! 2836: aml_parsetarget(scope, NULL, &res->v_field.ref1);
! 2837: res->v_field.bitpos = aml_parseint(scope, AML_ANYINT);
! 2838:
! 2839: aml_fixref(&res->v_field.ref1);
! 2840:
! 2841: switch (opcode) {
! 2842: case AMLOP_CREATEFIELD:
! 2843: res->v_field.bitlen = aml_parseint(scope, AML_ANYINT);
! 2844: break;
! 2845: case AMLOP_CREATEBITFIELD:
! 2846: res->v_field.bitlen = 1;
! 2847: break;
! 2848: case AMLOP_CREATEBYTEFIELD:
! 2849: res->v_field.bitlen = 8;
! 2850: res->v_field.bitpos *= 8;
! 2851: break;
! 2852: case AMLOP_CREATEWORDFIELD:
! 2853: res->v_field.bitlen = 16;
! 2854: res->v_field.bitpos *= 8;
! 2855: break;
! 2856: case AMLOP_CREATEDWORDFIELD:
! 2857: res->v_field.bitlen = 32;
! 2858: res->v_field.bitpos *= 8;
! 2859: break;
! 2860: case AMLOP_CREATEQWORDFIELD:
! 2861: res->v_field.bitlen = 64;
! 2862: res->v_field.bitpos *= 8;
! 2863: break;
! 2864: }
! 2865: name = aml_parsename(scope);
! 2866: aml_createname(scope->node, name, res);
! 2867:
! 2868: return res;
! 2869: }
! 2870:
! 2871: /* Parse Mutex/Event action */
! 2872: struct aml_value *
! 2873: aml_parsemuxaction(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2874: {
! 2875: struct aml_value *tmparg;
! 2876: int64_t i1;
! 2877: int rv;
! 2878:
! 2879: AML_CHECKSTACK();
! 2880:
! 2881: tmparg = aml_alloctmp(scope, 1);
! 2882: aml_parsetarget(scope, tmparg, NULL);
! 2883: switch (opcode) {
! 2884: case AMLOP_ACQUIRE:
! 2885: /* Assert: tmparg is AML_OBJTYPE_MUTEX */
! 2886: i1 = aml_parseint(scope, AMLOP_WORDPREFIX);
! 2887: rv = acpi_mutex_acquire(tmparg->v_objref.ref, i1);
! 2888: /* Return true if timed out */
! 2889: aml_setvalue(scope, res, NULL, rv);
! 2890: break;
! 2891: case AMLOP_RELEASE:
! 2892: acpi_mutex_release(tmparg->v_objref.ref);
! 2893: break;
! 2894:
! 2895: case AMLOP_WAIT:
! 2896: /* Assert: tmparg is AML_OBJTYPE_EVENT */
! 2897: i1 = aml_parseint(scope, AML_ANYINT);
! 2898:
! 2899: /* Return true if timed out */
! 2900: aml_setvalue(scope, res, NULL, 0);
! 2901: break;
! 2902: case AMLOP_SIGNAL:
! 2903: break;
! 2904: case AMLOP_RESET:
! 2905: break;
! 2906: }
! 2907:
! 2908: return res;
! 2909: }
! 2910:
! 2911: /* Parse Miscellaneous opcodes */
! 2912: struct aml_value *
! 2913: aml_parsemisc2(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2914: {
! 2915: struct aml_value *tmparg, *dev;
! 2916: int i1, i2, i3;
! 2917:
! 2918: AML_CHECKSTACK();
! 2919:
! 2920: switch (opcode) {
! 2921: case AMLOP_NOTIFY:
! 2922: /* Assert: tmparg is nameref or objref */
! 2923: tmparg = aml_alloctmp(scope, 1);
! 2924: aml_parseop(scope, tmparg);
! 2925: dev = aml_dereftarget(scope, tmparg);
! 2926:
! 2927: i1 = aml_parseint(scope, AML_ANYINT);
! 2928: if (dev && dev->node) {
! 2929: dnprintf(10, "Notify: [%s] %.2x\n",
! 2930: aml_nodename(dev->node), i1);
! 2931: aml_notify(dev->node, i1);
! 2932: }
! 2933: break;
! 2934: case AMLOP_SLEEP:
! 2935: i1 = aml_parseint(scope, AML_ANYINT);
! 2936: dnprintf(50, "SLEEP: %x\n", i1);
! 2937: if (i1)
! 2938: acpi_sleep(i1);
! 2939: else {
! 2940: dnprintf(10, "acpi_sleep(0)\n");
! 2941: }
! 2942: break;
! 2943: case AMLOP_STALL:
! 2944: i1 = aml_parseint(scope, AML_ANYINT);
! 2945: dnprintf(50, "STALL: %x\n", i1);
! 2946: if (i1)
! 2947: acpi_stall(i1);
! 2948: else {
! 2949: dnprintf(10, "acpi_stall(0)\n");
! 2950: }
! 2951: break;
! 2952: case AMLOP_FATAL:
! 2953: i1 = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2954: i2 = aml_parseint(scope, AMLOP_DWORDPREFIX);
! 2955: i3 = aml_parseint(scope, AML_ANYINT);
! 2956: aml_die("FATAL: %x %x %x\n", i1, i2, i3);
! 2957: break;
! 2958: }
! 2959: return res;
! 2960: }
! 2961:
! 2962: /* Parse Miscellaneous opcodes */
! 2963: struct aml_value *
! 2964: aml_parsemisc3(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2965: {
! 2966: struct aml_value *tmparg;
! 2967:
! 2968: AML_CHECKSTACK();
! 2969: tmparg = aml_alloctmp(scope, 1);
! 2970: aml_parseterm(scope, tmparg);
! 2971: switch (opcode) {
! 2972: case AMLOP_SIZEOF:
! 2973: aml_setvalue(scope, res, NULL, tmparg->length);
! 2974: break;
! 2975: case AMLOP_OBJECTTYPE:
! 2976: aml_setvalue(scope, res, NULL, tmparg->type);
! 2977: break;
! 2978: }
! 2979:
! 2980: return res;
! 2981: }
! 2982:
! 2983: /* Parse AMLOP_MATCH */
! 2984: struct aml_value *
! 2985: aml_parsematch(struct aml_scope *scope, int opcode, struct aml_value *res)
! 2986: {
! 2987: struct aml_value *pkg;
! 2988: int op1, op2, idx, mv1, mv2;
! 2989:
! 2990: AML_CHECKSTACK();
! 2991: pkg = aml_parseterm(scope, NULL);
! 2992: op1 = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2993: mv1 = aml_parseint(scope, AML_ANYINT);
! 2994: op2 = aml_parseint(scope, AMLOP_BYTEPREFIX);
! 2995: mv2 = aml_parseint(scope, AML_ANYINT);
! 2996: idx = aml_parseint(scope, AML_ANYINT);
! 2997:
! 2998: aml_setvalue(scope, res, NULL, -1);
! 2999: while (idx < pkg->length) {
! 3000: if (aml_match(op1, mv1, pkg->v_package[idx]) ||
! 3001: aml_match(op2, mv2, pkg->v_package[idx])) {
! 3002: aml_setvalue(scope, res, NULL, idx);
! 3003: break;
! 3004: }
! 3005: idx++;
! 3006: }
! 3007: aml_delref(&pkg);
! 3008: return res;
! 3009: }
! 3010:
! 3011: /* Parse referenced objects */
! 3012: struct aml_value *
! 3013: aml_parseref(struct aml_scope *scope, int opcode, struct aml_value *res)
! 3014: {
! 3015: struct aml_value *tmparg;
! 3016:
! 3017: AML_CHECKSTACK();
! 3018:
! 3019: switch (opcode) {
! 3020: case AMLOP_INDEX:
! 3021: tmparg = aml_alloctmp(scope, 1);
! 3022: _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, NULL);
! 3023: aml_parsetarget(scope, tmparg, NULL);
! 3024:
! 3025: res->v_objref.index = aml_parseint(scope, AML_ANYINT);
! 3026: res->v_objref.ref = aml_dereftarget(scope, tmparg);
! 3027:
! 3028: aml_parsetarget(scope, tmparg, NULL);
! 3029: aml_setvalue(scope, tmparg, res, 0);
! 3030: break;
! 3031: case AMLOP_DEREFOF:
! 3032: aml_parseop(scope, res);
! 3033: break;
! 3034: case AMLOP_RETURN:
! 3035: tmparg = aml_alloctmp(scope, 1);
! 3036: aml_parseterm(scope, tmparg);
! 3037: aml_setvalue(scope, res, tmparg, 0);
! 3038: scope->pos = scope->end;
! 3039: break;
! 3040: case AMLOP_ARG0 ... AMLOP_ARG6:
! 3041: opcode -= AMLOP_ARG0;
! 3042: if (scope->args == NULL || opcode >= scope->nargs)
! 3043: aml_die("arg %d out of range", opcode);
! 3044:
! 3045: /* Create OBJREF to stack variable */
! 3046: _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1,
! 3047: &scope->args[opcode]);
! 3048: break;
! 3049: case AMLOP_LOCAL0 ... AMLOP_LOCAL7:
! 3050: opcode -= AMLOP_LOCAL0;
! 3051:
! 3052: /* No locals exist.. lazy allocate */
! 3053: if (scope->locals == NULL) {
! 3054: dnprintf(10, "Lazy alloc locals\n");
! 3055: scope->locals = aml_alloctmp(scope, AML_MAX_LOCAL);
! 3056: }
! 3057:
! 3058: /* Create OBJREF to stack variable */
! 3059: _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1,
! 3060: &scope->locals[opcode]);
! 3061: res->v_objref.ref->stack = opcode+AMLOP_LOCAL0;
! 3062: break;
! 3063: case AMLOP_LOAD:
! 3064: tmparg = aml_alloctmp(scope, 2);
! 3065: aml_parseop(scope, &tmparg[0]);
! 3066: aml_parseop(scope, &tmparg[1]);
! 3067: break;
! 3068: case AMLOP_STORE:
! 3069: tmparg = aml_alloctmp(scope, 1);
! 3070: aml_parseterm(scope, res);
! 3071: aml_parsetarget(scope, tmparg, NULL);
! 3072:
! 3073: while (tmparg->type == AML_OBJTYPE_OBJREF) {
! 3074: if (tmparg->v_objref.index != -1)
! 3075: break;
! 3076: tmparg = tmparg->v_objref.ref;
! 3077: }
! 3078: aml_setvalue(scope, tmparg, res, 0);
! 3079: break;
! 3080: case AMLOP_REFOF:
! 3081: _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, NULL);
! 3082: aml_parsetarget(scope, NULL, &res->v_objref.ref);
! 3083: break;
! 3084: case AMLOP_CONDREFOF:
! 3085: /* Returns true if object exists */
! 3086: tmparg = aml_alloctmp(scope, 2);
! 3087: aml_parsetarget(scope, &tmparg[0], NULL);
! 3088: aml_parsetarget(scope, &tmparg[1], NULL);
! 3089: if (tmparg[0].type != AML_OBJTYPE_NAMEREF) {
! 3090: /* Object exists */
! 3091: aml_freevalue(&tmparg[1]);
! 3092: aml_setvalue(scope, &tmparg[1], &tmparg[0], 0);
! 3093: aml_setvalue(scope, res, NULL, 1);
! 3094: } else {
! 3095: /* Object doesn't exist */
! 3096: aml_setvalue(scope, res, NULL, 0);
! 3097: }
! 3098: break;
! 3099: }
! 3100:
! 3101: return res;
! 3102: }
! 3103:
! 3104: struct aml_value *
! 3105: aml_parsestring(struct aml_scope *scope, int opcode, struct aml_value *res)
! 3106: {
! 3107: struct aml_value *tmpval;
! 3108: int i1, i2;
! 3109:
! 3110: AML_CHECKSTACK();
! 3111: switch (opcode) {
! 3112: case AMLOP_CONCAT:
! 3113: tmpval = aml_alloctmp(scope, 4);
! 3114: aml_parseterm(scope, &tmpval[AML_LHS]);
! 3115: aml_parseterm(scope, &tmpval[AML_RHS]);
! 3116: aml_parsetarget(scope, &tmpval[AML_DST], NULL);
! 3117: if (tmpval[AML_LHS].type == AML_OBJTYPE_BUFFER &&
! 3118: tmpval[AML_RHS].type == AML_OBJTYPE_BUFFER) {
! 3119: aml_resize(&tmpval[AML_LHS],
! 3120: tmpval[AML_LHS].length+tmpval[AML_RHS].length);
! 3121: memcpy(&tmpval[AML_LHS].v_buffer+tmpval[AML_LHS].length,
! 3122: tmpval[AML_RHS].v_buffer, tmpval[AML_RHS].length);
! 3123: aml_setvalue(scope, &tmpval[AML_DST], &tmpval[AML_LHS], 0);
! 3124: }
! 3125: if (tmpval[AML_LHS].type == AML_OBJTYPE_STRING &&
! 3126: tmpval[AML_RHS].type == AML_OBJTYPE_STRING) {
! 3127: aml_resize(&tmpval[AML_LHS],
! 3128: tmpval[AML_LHS].length+tmpval[AML_RHS].length);
! 3129: memcpy(&tmpval[AML_LHS].v_string+tmpval[AML_LHS].length,
! 3130: tmpval[AML_RHS].v_buffer, tmpval[AML_RHS].length);
! 3131: aml_setvalue(scope, &tmpval[AML_DST], &tmpval[AML_LHS], 0);
! 3132: } else {
! 3133: aml_die("concat");
! 3134: }
! 3135: break;
! 3136: case AMLOP_MID:
! 3137: tmpval = aml_alloctmp(scope, 2);
! 3138: aml_parseterm(scope, &tmpval[0]);
! 3139: i1 = aml_parseint(scope, AML_ANYINT); // start
! 3140: i2 = aml_parseint(scope, AML_ANYINT); // length
! 3141: aml_parsetarget(scope, &tmpval[1], NULL);
! 3142: if (i1 > tmpval[0].length)
! 3143: i1 = tmpval[0].length;
! 3144: if (i1+i2 > tmpval[0].length)
! 3145: i2 = tmpval[0].length-i1;
! 3146: _aml_setvalue(res, AML_OBJTYPE_STRING, i2, tmpval[0].v_string+i1);
! 3147: break;
! 3148: case AMLOP_TODECSTRING:
! 3149: case AMLOP_TOHEXSTRING:
! 3150: i1 = aml_parseint(scope, AML_ANYINT);
! 3151: _aml_setvalue(res, AML_OBJTYPE_STRING, 20, NULL);
! 3152: snprintf(res->v_string, res->length,
! 3153: ((opcode == AMLOP_TODECSTRING) ? "%d" : "%x"), i1);
! 3154: break;
! 3155: default:
! 3156: aml_die("to_string");
! 3157: break;
! 3158: }
! 3159:
! 3160: return res;
! 3161: }
! 3162:
! 3163: struct aml_value *
! 3164: aml_parseterm(struct aml_scope *scope, struct aml_value *res)
! 3165: {
! 3166: struct aml_value *tmpres;
! 3167:
! 3168: /* If no value specified, allocate dynamic */
! 3169: if (res == NULL)
! 3170: res = aml_allocvalue(AML_OBJTYPE_UNINITIALIZED, 0, NULL);
! 3171: tmpres = aml_alloctmp(scope, 1);
! 3172: aml_parseop(scope, tmpres);
! 3173: aml_evalterm(scope, tmpres, res);
! 3174: return res;
! 3175: }
! 3176:
! 3177: struct aml_value *
! 3178: aml_parsetarget(struct aml_scope *scope, struct aml_value *res,
! 3179: struct aml_value **opt)
! 3180: {
! 3181: struct aml_value *dummy;
! 3182:
! 3183: /* If no value specified, allocate dynamic */
! 3184: if (res == NULL)
! 3185: res = aml_allocvalue(AML_OBJTYPE_UNINITIALIZED, 0, NULL);
! 3186: aml_parseop(scope, res);
! 3187: if (opt == NULL)
! 3188: opt = &dummy;
! 3189:
! 3190: *opt = aml_evaltarget(scope, res);
! 3191:
! 3192: return res;
! 3193: }
! 3194:
! 3195: int odp;
! 3196:
! 3197: /* Main Opcode Parser/Evaluator */
! 3198: struct aml_value *
! 3199: aml_parseop(struct aml_scope *scope, struct aml_value *res)
! 3200: {
! 3201: int opcode;
! 3202: struct aml_opcode *htab;
! 3203: struct aml_value *rv = NULL;
! 3204:
! 3205: if (odp++ > 25)
! 3206: panic("depth");
! 3207:
! 3208: aml_freevalue(res);
! 3209: opcode = aml_parseopcode(scope);
! 3210: dnprintf(15, "%.4x: [%s] %s\n", aml_pc(scope->pos-opsize(opcode)),
! 3211: aml_nodename(scope->node), aml_mnem(opcode, scope->pos));
! 3212: delay(amlop_delay);
! 3213:
! 3214: htab = aml_findopcode(opcode);
! 3215: if (htab && htab->handler) {
! 3216: rv = htab->handler(scope, opcode, res);
! 3217: } else {
! 3218: /* No opcode handler */
! 3219: aml_die("Unknown opcode: %.4x @ %.4x", opcode,
! 3220: aml_pc(scope->pos - opsize(opcode)));
! 3221: }
! 3222: odp--;
! 3223: return rv;
! 3224: }
! 3225:
! 3226: const char hext[] = "0123456789ABCDEF";
! 3227:
! 3228: const char *
! 3229: aml_eisaid(u_int32_t pid)
! 3230: {
! 3231: static char id[8];
! 3232:
! 3233: id[0] = '@' + ((pid >> 2) & 0x1F);
! 3234: id[1] = '@' + ((pid << 3) & 0x18) + ((pid >> 13) & 0x7);
! 3235: id[2] = '@' + ((pid >> 8) & 0x1F);
! 3236: id[3] = hext[(pid >> 20) & 0xF];
! 3237: id[4] = hext[(pid >> 16) & 0xF];
! 3238: id[5] = hext[(pid >> 28) & 0xF];
! 3239: id[6] = hext[(pid >> 24) & 0xF];
! 3240: id[7] = 0;
! 3241: return id;
! 3242: }
! 3243:
! 3244: /*
! 3245: * @@@: Fixup DSDT code
! 3246: */
! 3247: struct aml_fixup {
! 3248: int offset;
! 3249: u_int8_t oldv, newv;
! 3250: } __ibm300gl[] = {
! 3251: { 0x19, 0x3a, 0x3b },
! 3252: { -1 }
! 3253: };
! 3254:
! 3255: struct aml_blacklist {
! 3256: const char *oem, *oemtbl;
! 3257: struct aml_fixup *fixtab;
! 3258: u_int8_t cksum;
! 3259: } amlfix_list[] = {
! 3260: { "IBM ", "CDTPWSNH", __ibm300gl, 0x41 },
! 3261: { NULL },
! 3262: };
! 3263:
! 3264: void
! 3265: aml_fixup_dsdt(u_int8_t *acpi_hdr, u_int8_t *base, int len)
! 3266: {
! 3267: struct acpi_table_header *hdr = (struct acpi_table_header *)acpi_hdr;
! 3268: struct aml_blacklist *fixlist;
! 3269: struct aml_fixup *fixtab;
! 3270:
! 3271: for (fixlist = amlfix_list; fixlist->oem; fixlist++) {
! 3272: if (!memcmp(fixlist->oem, hdr->oemid, 6) &&
! 3273: !memcmp(fixlist->oemtbl, hdr->oemtableid, 8) &&
! 3274: fixlist->cksum == hdr->checksum) {
! 3275: /* Found a potential fixup entry */
! 3276: for (fixtab = fixlist->fixtab; fixtab->offset != -1;
! 3277: fixtab++) {
! 3278: if (base[fixtab->offset] == fixtab->oldv)
! 3279: base[fixtab->offset] = fixtab->newv;
! 3280: }
! 3281: }
! 3282: }
! 3283: }
! 3284:
! 3285: /*
! 3286: * @@@: Default Object creation
! 3287: */
! 3288: struct aml_defval {
! 3289: const char *name;
! 3290: int type;
! 3291: int64_t ival;
! 3292: const void *bval;
! 3293: struct aml_value **gval;
! 3294: } aml_defobj[] = {
! 3295: { "_OS_", AML_OBJTYPE_STRING, -1, "OpenBSD" },
! 3296: { "_REV", AML_OBJTYPE_INTEGER, 2, NULL },
! 3297: { "_GL", AML_OBJTYPE_MUTEX, 1, NULL, &aml_global_lock },
! 3298: { "_OSI", AML_OBJTYPE_METHOD, 1, aml_callosi },
! 3299: { NULL }
! 3300: };
! 3301:
! 3302: /* _OSI Default Method:
! 3303: * Returns True if string argument matches list of known OS strings
! 3304: * We return True for Windows to fake out nasty bad AML
! 3305: */
! 3306: char *aml_valid_osi[] = {
! 3307: "OpenBSD",
! 3308: "Windows 2000",
! 3309: "Windows 2001",
! 3310: "Windows 2001.1",
! 3311: "Windows 2001 SP0",
! 3312: "Windows 2001 SP1",
! 3313: "Windows 2001 SP2",
! 3314: "Windows 2001 SP3",
! 3315: "Windows 2001 SP4",
! 3316: "Windows 2006",
! 3317: NULL
! 3318: };
! 3319:
! 3320: struct aml_value *
! 3321: aml_callosi(struct aml_scope *scope, struct aml_value *val)
! 3322: {
! 3323: struct aml_value tmpstr, *arg;
! 3324: int idx, result;
! 3325:
! 3326: /* Perform comparison with valid strings */
! 3327: result = 0;
! 3328: memset(&tmpstr, 0, sizeof(tmpstr));
! 3329: tmpstr.type = AML_OBJTYPE_STRING;
! 3330: arg = aml_derefvalue(scope, &scope->args[0], ACPI_IOREAD);
! 3331:
! 3332: for (idx=0; !result && aml_valid_osi[idx] != NULL; idx++) {
! 3333: tmpstr.v_string = aml_valid_osi[idx];
! 3334: tmpstr.length = strlen(tmpstr.v_string);
! 3335:
! 3336: result = aml_cmpvalue(arg, &tmpstr, AMLOP_LEQUAL);
! 3337: }
! 3338: aml_setvalue(scope, val, NULL, result);
! 3339: return val;
! 3340: }
! 3341:
! 3342: void
! 3343: aml_create_defaultobjects()
! 3344: {
! 3345: struct aml_value *tmp;
! 3346: struct aml_defval *def;
! 3347:
! 3348: for (def = aml_defobj; def->name; def++) {
! 3349: /* Allocate object value + add to namespace */
! 3350: tmp = aml_allocvalue(def->type, def->ival, def->bval);
! 3351: aml_createname(&aml_root, def->name, tmp);
! 3352: if (def->gval) {
! 3353: /* Set root object pointer */
! 3354: *def->gval = tmp;
! 3355: }
! 3356: }
! 3357: }
! 3358:
! 3359: int
! 3360: aml_print_resource(union acpi_resource *crs, void *arg)
! 3361: {
! 3362: int typ = AML_CRSTYPE(crs);
! 3363:
! 3364: switch (typ) {
! 3365: case LR_EXTIRQ:
! 3366: printf("extirq\tflags:%.2x len:%.2x irq:%.4x\n",
! 3367: crs->lr_extirq.flags, crs->lr_extirq.irq_count,
! 3368: aml_letohost32(crs->lr_extirq.irq[0]));
! 3369: break;
! 3370: case SR_IRQ:
! 3371: printf("irq\t%.4x %.2x\n", aml_letohost16(crs->sr_irq.irq_mask),
! 3372: crs->sr_irq.irq_flags);
! 3373: break;
! 3374: case SR_DMA:
! 3375: printf("dma\t%.2x %.2x\n", crs->sr_dma.channel,
! 3376: crs->sr_dma.flags);
! 3377: break;
! 3378: case SR_IOPORT:
! 3379: printf("ioport\tflags:%.2x _min:%.4x _max:%.4x _aln:%.2x _len:%.2x\n",
! 3380: crs->sr_ioport.flags, crs->sr_ioport._min,
! 3381: crs->sr_ioport._max, crs->sr_ioport._aln,
! 3382: crs->sr_ioport._len);
! 3383: break;
! 3384: case SR_STARTDEP:
! 3385: printf("startdep\n");
! 3386: break;
! 3387: case SR_ENDDEP:
! 3388: printf("enddep\n");
! 3389: break;
! 3390: case LR_WORD:
! 3391: printf("word\ttype:%.2x flags:%.2x tflag:%.2x gra:%.4x min:%.4x max:%.4x tra:%.4x len:%.4x\n",
! 3392: crs->lr_word.type, crs->lr_word.flags, crs->lr_word.tflags,
! 3393: crs->lr_word._gra, crs->lr_word._min, crs->lr_word._max,
! 3394: crs->lr_word._tra, crs->lr_word._len);
! 3395: break;
! 3396: case LR_DWORD:
! 3397: printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.8x min:%.8x max:%.8x tra:%.8x len:%.8x\n",
! 3398: crs->lr_dword.type, crs->lr_dword.flags, crs->lr_dword.tflags,
! 3399: crs->lr_dword._gra, crs->lr_dword._min, crs->lr_dword._max,
! 3400: crs->lr_dword._tra, crs->lr_dword._len);
! 3401: break;
! 3402: case LR_QWORD:
! 3403: printf("dword\ttype:%.2x flags:%.2x tflag:%.2x gra:%.16llx min:%.16llx max:%.16llx tra:%.16llx len:%.16llx\n",
! 3404: crs->lr_qword.type, crs->lr_qword.flags, crs->lr_qword.tflags,
! 3405: crs->lr_qword._gra, crs->lr_qword._min, crs->lr_qword._max,
! 3406: crs->lr_qword._tra, crs->lr_qword._len);
! 3407: break;
! 3408: default:
! 3409: printf("unknown type: %x\n", typ);
! 3410: break;
! 3411: }
! 3412: return (0);
! 3413: }
! 3414:
! 3415: union acpi_resource *aml_mapresource(union acpi_resource *);
! 3416:
! 3417: union acpi_resource *
! 3418: aml_mapresource(union acpi_resource *crs)
! 3419: {
! 3420: static union acpi_resource map;
! 3421: int rlen;
! 3422:
! 3423: rlen = AML_CRSLEN(crs);
! 3424: if (rlen >= sizeof(map))
! 3425: return crs;
! 3426:
! 3427: memset(&map, 0, sizeof(map));
! 3428: memcpy(&map, crs, rlen);
! 3429:
! 3430: return ↦
! 3431: }
! 3432:
! 3433: int
! 3434: aml_parse_resource(int length, uint8_t *buffer,
! 3435: int (*crs_enum)(union acpi_resource *, void *), void *arg)
! 3436: {
! 3437: int off, rlen;
! 3438: union acpi_resource *crs;
! 3439:
! 3440: for (off = 0; off < length; off += rlen) {
! 3441: crs = (union acpi_resource *)(buffer+off);
! 3442:
! 3443: rlen = AML_CRSLEN(crs);
! 3444: if (crs->hdr.typecode == 0x79 || rlen <= 3)
! 3445: break;
! 3446:
! 3447: crs = aml_mapresource(crs);
! 3448: #ifdef ACPI_DEBUG
! 3449: aml_print_resource(crs, NULL);
! 3450: #endif
! 3451: crs_enum(crs, arg);
! 3452: }
! 3453:
! 3454: return 0;
! 3455: }
! 3456:
! 3457: void
! 3458: aml_foreachpkg(struct aml_value *pkg, int start,
! 3459: void (*fn)(struct aml_value *, void *),
! 3460: void *arg)
! 3461: {
! 3462: int idx;
! 3463:
! 3464: if (pkg->type != AML_OBJTYPE_PACKAGE)
! 3465: return;
! 3466: for (idx=start; idx<pkg->length; idx++)
! 3467: fn(pkg->v_package[idx], arg);
! 3468: }
! 3469:
! 3470: int
! 3471: acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length)
! 3472: {
! 3473: u_int8_t *end;
! 3474:
! 3475: dsdt_softc = sc;
! 3476:
! 3477: strlcpy(aml_root.name, "\\", sizeof(aml_root.name));
! 3478: if (aml_root.start == NULL) {
! 3479: aml_root.start = start;
! 3480: aml_root.end = start+length;
! 3481: }
! 3482: end = start+length;
! 3483: aml_parsenode(NULL, &aml_root, start, &end, NULL);
! 3484: dnprintf(50, " : parsed %d AML bytes\n", length);
! 3485:
! 3486: return (0);
! 3487: }
! 3488:
! 3489: /*
! 3490: * Walk nodes and perform fixups for nameref
! 3491: */
! 3492: int aml_fixup_node(struct aml_node *, void *);
! 3493:
! 3494: int aml_fixup_node(struct aml_node *node, void *arg)
! 3495: {
! 3496: struct aml_value *val = arg;
! 3497: int i;
! 3498:
! 3499: if (node->value == NULL)
! 3500: return (0);
! 3501: if (arg == NULL)
! 3502: aml_fixup_node(node, node->value);
! 3503: else if (val->type == AML_OBJTYPE_NAMEREF) {
! 3504: node = aml_searchname(node, val->v_nameref);
! 3505: if (node && node->value) {
! 3506: _aml_setvalue(val, AML_OBJTYPE_OBJREF, -1,
! 3507: node->value);
! 3508: }
! 3509: } else if (val->type == AML_OBJTYPE_PACKAGE) {
! 3510: for (i = 0; i < val->length; i++)
! 3511: aml_fixup_node(node, val->v_package[i]);
! 3512: } else if (val->type == AML_OBJTYPE_OPREGION) {
! 3513: if (val->v_opregion.iospace != GAS_PCI_CFG_SPACE)
! 3514: return (0);
! 3515: if (ACPI_PCI_FN(val->v_opregion.iobase) != 0xFFFF)
! 3516: return (0);
! 3517: val->v_opregion.iobase =
! 3518: ACPI_PCI_REG(val->v_opregion.iobase) +
! 3519: aml_getpciaddr(dsdt_softc, node);
! 3520: dnprintf(20, "late ioaddr : %s:%llx\n",
! 3521: aml_nodename(node), val->v_opregion.iobase);
! 3522: }
! 3523: return (0);
! 3524: }
! 3525:
! 3526: void
! 3527: aml_postparse()
! 3528: {
! 3529: aml_walknodes(&aml_root, AML_WALK_PRE, aml_fixup_node, NULL);
! 3530: }
CVSweb