Annotation of sys/dev/acpi/dsdt.c, Revision 1.1.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