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