diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2008-05-16 06:50:56 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2008-05-16 06:50:56 +0000 |
commit | 1b882095f169e506c0d98c8ddbb86c6e2e8856af (patch) | |
tree | 4fd5ddca8f701a398926df6a1863a08e5606b9c9 | |
parent | 3093a6ff905bedc86e26f69bd1e69be1d02e5d46 (diff) |
back out jordans new parser.
it didnt have enough oks from the right people, it did break machines
that were previously working, and it bloated the RAMDISKS and install
media beyond the constraints of the media.
requested by deraadt@
-rw-r--r-- | sys/dev/acpi/acpi.c | 180 | ||||
-rw-r--r-- | sys/dev/acpi/acpiac.c | 8 | ||||
-rw-r--r-- | sys/dev/acpi/acpiasus.c | 6 | ||||
-rw-r--r-- | sys/dev/acpi/acpibat.c | 18 | ||||
-rw-r--r-- | sys/dev/acpi/acpibtn.c | 10 | ||||
-rw-r--r-- | sys/dev/acpi/acpidebug.c | 54 | ||||
-rw-r--r-- | sys/dev/acpi/acpidock.c | 14 | ||||
-rw-r--r-- | sys/dev/acpi/acpiec.c | 4 | ||||
-rw-r--r-- | sys/dev/acpi/acpiprt.c | 56 | ||||
-rw-r--r-- | sys/dev/acpi/acpithinkpad.c | 96 | ||||
-rw-r--r-- | sys/dev/acpi/acpitz.c | 14 | ||||
-rw-r--r-- | sys/dev/acpi/amltypes.h | 3 | ||||
-rw-r--r-- | sys/dev/acpi/dsdt.c | 4655 | ||||
-rw-r--r-- | sys/dev/acpi/dsdt.h | 3 |
14 files changed, 1975 insertions, 3146 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 21a8b6c1060..d1b4692f283 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.117 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpi.c,v 1.118 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> @@ -87,8 +87,6 @@ void acpi_enable_onegpe(struct acpi_softc *, int, int); int acpi_gpe_level(struct acpi_softc *, int, void *); int acpi_gpe_edge(struct acpi_softc *, int, void *); -struct gpe_block *acpi_find_gpe(struct acpi_softc *, int); - #define ACPI_LOCK(sc) #define ACPI_UNLOCK(sc) @@ -175,9 +173,6 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, *(uint32_t *)(pb+reg) = bus_space_read_4( sc->sc_iot, ioh, reg); break; - default: - printf("rdio: invalid size %d\n", access_size); - break; } } else { switch (access_size) { @@ -197,9 +192,6 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address, bus_space_write_4(sc->sc_iot, ioh, reg, *(uint32_t *)(pb+reg)); break; - default: - printf("wrio: invalid size %d\n", access_size); - break; } } @@ -274,7 +266,7 @@ acpi_inidev(struct aml_node *node, void *arg) */ /* Evaluate _STA to decide _INI fate and walk fate */ - if (!aml_evalname(sc, node->parent, "_STA", 0, NULL, &res)) + if (!aml_evalname(sc, node, "_STA", 0, NULL, &res)) st = (int)aml_val2int(&res); aml_freevalue(&res); @@ -312,7 +304,7 @@ acpi_foundprt(struct aml_node *node, void *arg) st |= STA_BATTERY; /* Evaluate _STA to decide _PRT fate and walk fate */ - if (!aml_evalname(sc, node->parent, "_STA", 0, NULL, &res)) + if (!aml_evalname(sc, node, "_STA", 0, NULL, &res)) st = (int)aml_val2int(&res); aml_freevalue(&res); @@ -620,22 +612,22 @@ acpi_attach(struct device *parent, struct device *self, void *aux) acpi_softc = sc; /* initialize runtime environment */ - aml_find_node(&aml_root, "_INI", acpi_inidev, sc); + aml_find_node(aml_root.child, "_INI", acpi_inidev, sc); /* attach pci interrupt routing tables */ - aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc); + aml_find_node(aml_root.child, "_PRT", acpi_foundprt, sc); #ifndef SMALL_KERNEL /* XXX EC needs to be attached first on some systems */ - aml_find_node(&aml_root, "_HID", acpi_foundec, sc); + aml_find_node(aml_root.child, "_HID", acpi_foundec, sc); aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc); /* attach battery, power supply and button devices */ - aml_find_node(&aml_root, "_HID", acpi_foundhid, sc); + aml_find_node(aml_root.child, "_HID", acpi_foundhid, sc); /* attach docks */ - aml_find_node(&aml_root, "_DCK", acpi_founddock, sc); + aml_find_node(aml_root.child, "_DCK", acpi_founddock, sc); /* create list of devices we want to query when APM come in */ SLIST_INIT(&sc->sc_ac); @@ -1146,9 +1138,6 @@ acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval) sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval); } -void -acpi_add_gpeblock(struct acpi_softc *sc, int reg, int len, int gpe); - int acpi_interrupt(void *arg) { @@ -1157,12 +1146,6 @@ acpi_interrupt(void *arg) processed = 0; -#if 0 - acpi_add_gpeblock(sc, sc->sc_fadt->gpe0_blk, sc->sc_fadt->gpe0_blk_len>>1, 0); - acpi_add_gpeblock(sc, sc->sc_fadt->gpe1_blk, sc->sc_fadt->gpe1_blk_len>>1, - sc->sc_fadt->gpe1_base); -#endif - dnprintf(40, "ACPI Interrupt\n"); for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3); @@ -1261,18 +1244,19 @@ int acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler) (struct acpi_softc *, int, void *), void *arg, const char *label) { - struct gpe_block *ptbl; - - ptbl = acpi_find_gpe(sc, gpe); - if (ptbl == NULL || handler == NULL) + if (gpe >= sc->sc_lastgpe || handler == NULL) return -EINVAL; - if (ptbl->handler != NULL) { + + if (sc->gpe_table[gpe].handler != NULL) { dnprintf(10, "error: GPE %.2x already enabled\n", gpe); return -EBUSY; } + dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, label); - ptbl->handler = handler; - ptbl->arg = arg; + sc->gpe_table[gpe].handler = handler; + sc->gpe_table[gpe].arg = arg; + + /* Defer enabling GPEs */ return (0); } @@ -1357,112 +1341,6 @@ acpi_foundprw(struct aml_node *node, void *arg) return 0; } -struct gpe_block * -acpi_find_gpe(struct acpi_softc *sc, int gpe) -{ -#if 1 - if (gpe >= sc->sc_lastgpe) - return NULL; - return &sc->gpe_table[gpe]; -#else - SIMPLEQ_FOREACH(pgpe, &sc->sc_gpes, gpe_link) { - if (gpe >= pgpe->start && gpe <= (pgpe->start+7)) - return &pgpe->table[gpe & 7]; - } - return NULL; -#endif -} - -#if 0 -/* New GPE handling code: Create GPE block */ -void -acpi_init_gpeblock(struct acpi_softc *sc, int reg, int len, int base) -{ - int i, j; - - if (!reg || !len) - return; - for (i=0; i<len; i++) { - pgpe = acpi_os_malloc(sizeof(gpeblock)); - if (pgpe == NULL) - return; - - /* Allocate GPE Handler Block */ - pgpe->start = base + i; - acpi_bus_space_map(sc->sc_iot, reg+i, 1, 0, &pgpe->sts_ioh); - acpi_bus_space_map(sc->sc_iot, reg+i+len, 1, 0, &pgpe->en_ioh); - SIMPLEQ_INSERT_TAIL(&sc->sc_gpes, gpe, gpe_link); - - /* Clear pending GPEs */ - bus_space_write_1(sc->sc_iot, pgpe->sts_ioh, 0, 0xFF); - bus_space_write_1(sc->sc_iot, pgpe->en_ioh, 0, 0x00); - } - - /* Search for GPE handlers */ - for (i=0; i<len*8; i++) { - char gpestr[32]; - struct aml_node *h; - - snprintf(gpestr, sizeof(gpestr), "\\_GPE._L%.2X", base+i); - h = aml_searchnode(&aml_root, gpestr); - if (acpi_set_gpehandler(sc, base+i, acpi_gpe_level, h, "level") != 0) { - snprintf(gpestr, sizeof(gpestr), "\\_GPE._E%.2X", base+i); - h = aml_searchnode(&aml_root, gpestr); - acpi_set_gpehandler(sc, base+i, acpi_gpe_edge, h, "edge"); - } - } -} - -/* Process GPE interrupts */ -int -acpi_handle_gpes(struct acpi_softc *sc) -{ - uint8_t en, sts; - int processed, i; - - processed=0; - SIMPLEQ_FOREACH(pgpe, &sc->sc_gpes, gpe_link) { - sts = bus_space_read_1(sc->sc_iot, pgpe->sts_ioh, 0); - en = bus_space_read_1(sc->sc_iot, pgpe->en_ioh, 0); - for (i=0; i<8; i++) { - if (en & sts & (1L << i)) { - pgpe->table[i].active = 1; - processed=1; - } - } - } - return processed; -} -#endif - -void -acpi_add_gpeblock(struct acpi_softc *sc, int reg, int len, int gpe) -{ - int idx, jdx; - u_int8_t en, sts; - - if (!reg || !len) - return; - for (idx=0; idx<len; idx++) { - sts = inb(reg + idx); - en = inb(reg + len + idx); - printf("-- gpe %.2x-%.2x : en:%.2x sts:%.2x %.2x\n", - gpe+idx*8, gpe+idx*8+7, en, sts, en&sts); - for (jdx=0; jdx<8; jdx++) { - char gpestr[32]; - struct aml_node *l, *e; - - if (en & sts & (1L << jdx)) { - snprintf(gpestr,sizeof(gpestr), "\\_GPE._L%.2X", gpe+idx*8+jdx); - l = aml_searchname(&aml_root, gpestr); - snprintf(gpestr,sizeof(gpestr), "\\_GPE._E%.2X", gpe+idx*8+jdx); - e = aml_searchname(&aml_root, gpestr); - printf(" GPE %.2x active L%x E%x\n", gpe+idx*8+jdx, l, e); - } - } - } -} - void acpi_init_gpes(struct acpi_softc *sc) { @@ -1470,12 +1348,6 @@ acpi_init_gpes(struct acpi_softc *sc) char name[12]; int idx, ngpe; -#if 0 - acpi_add_gpeblock(sc, sc->sc_fadt->gpe0_blk, sc->sc_fadt->gpe0_blk_len>>1, 0); - acpi_add_gpeblock(sc, sc->sc_fadt->gpe1_blk, sc->sc_fadt->gpe1_blk_len>>1, - sc->sc_fadt->gpe1_base); -#endif - sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2; if (sc->sc_fadt->gpe1_blk_len) { } @@ -1508,7 +1380,7 @@ acpi_init_gpes(struct acpi_softc *sc) "edge"); } } - aml_find_node(&aml_root, "_PRW", acpi_foundprw, sc); + aml_find_node(aml_root.child, "_PRW", acpi_foundprw, sc); sc->sc_maxgpe = ngpe; } @@ -1523,7 +1395,7 @@ acpi_init_states(struct acpi_softc *sc) snprintf(name, sizeof(name), "_S%d_", i); sc->sc_sleeptype[i].slp_typa = -1; sc->sc_sleeptype[i].slp_typb = -1; - if (aml_evalname(sc, &aml_root, name, 0, NULL, &res) == 0) { + if (aml_evalname(sc, aml_root.child, name, 0, NULL, &res) == 0) { if (res.type == AML_OBJTYPE_PACKAGE) { sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]); sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]); @@ -1536,11 +1408,11 @@ acpi_init_states(struct acpi_softc *sc) void acpi_init_pm(struct acpi_softc *sc) { - sc->sc_tts = aml_searchname(&aml_root, "_TTS"); - sc->sc_pts = aml_searchname(&aml_root, "_PTS"); - sc->sc_wak = aml_searchname(&aml_root, "_WAK"); - sc->sc_bfs = aml_searchname(&aml_root, "_BFS"); - sc->sc_gts = aml_searchname(&aml_root, "_GTS"); + sc->sc_tts = aml_searchname(aml_root.child, "_TTS"); + sc->sc_pts = aml_searchname(aml_root.child, "_PTS"); + sc->sc_wak = aml_searchname(aml_root.child, "_WAK"); + sc->sc_bfs = aml_searchname(aml_root.child, "_BFS"); + sc->sc_gts = aml_searchname(aml_root.child, "_GTS"); } void @@ -1559,7 +1431,6 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state) return; } - memset(&env, 0, sizeof(env)); env.type = AML_OBJTYPE_INTEGER; env.v_integer = state; /* _TTS(state) */ @@ -1637,7 +1508,6 @@ acpi_resume(struct acpi_softc *sc) { struct aml_value env; - memset(&env, 0, sizeof(env)); env.type = AML_OBJTYPE_INTEGER; env.v_integer = sc->sc_state; @@ -1671,8 +1541,6 @@ acpi_powerdown(void) acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5); } -extern int aml_busy; - void acpi_isr_thread(void *arg) { @@ -1717,8 +1585,6 @@ acpi_isr_thread(void *arg) tsleep(sc, PWAIT, "acpi_idle", 0); sc->sc_wakeup = 1; dnprintf(10, "wakeup..\n"); - if (aml_busy) - continue; for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) { struct gpe_block *pgpe = &sc->gpe_table[gpe]; diff --git a/sys/dev/acpi/acpiac.c b/sys/dev/acpi/acpiac.c index bd349ede386..899d2344229 100644 --- a/sys/dev/acpi/acpiac.c +++ b/sys/dev/acpi/acpiac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiac.c,v 1.20 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpiac.c,v 1.21 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -66,9 +66,9 @@ acpiac_attach(struct device *parent, struct device *self, void *aux) struct acpi_attach_args *aa = aux; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; - aml_register_notify(sc->sc_devnode, aa->aaa_dev, + aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, acpiac_notify, sc, ACPIDEV_NOPOLL); acpiac_getsta(sc); @@ -125,7 +125,7 @@ acpiac_notify(struct aml_node *node, int notify_type, void *arg) struct acpiac_softc *sc = arg; dnprintf(10, "acpiac_notify: %.2x %s\n", notify_type, - sc->sc_devnode->name); + sc->sc_devnode->parent->name); switch (notify_type) { case 0x00: diff --git a/sys/dev/acpi/acpiasus.c b/sys/dev/acpi/acpiasus.c index 2d1a83d1c03..33b1d4a21bb 100644 --- a/sys/dev/acpi/acpiasus.c +++ b/sys/dev/acpi/acpiasus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiasus.c,v 1.2 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpiasus.c,v 1.3 2008/05/16 06:50:55 dlg Exp $ */ /* $NetBSD: asus_acpi.c,v 1.2.2.2 2008/04/03 12:42:37 mjf Exp $ */ /*- @@ -115,7 +115,7 @@ acpiasus_attach(struct device *parent, struct device *self, void *aux) struct acpi_attach_args *aa = aux; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; sc->sc_powerhook = powerhook_establish(acpiasus_power, sc); @@ -123,7 +123,7 @@ acpiasus_attach(struct device *parent, struct device *self, void *aux) acpiasus_init(self); - aml_register_notify(sc->sc_devnode, aa->aaa_dev, + aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, acpiasus_notify, sc, ACPIDEV_NOPOLL); } diff --git a/sys/dev/acpi/acpibat.c b/sys/dev/acpi/acpibat.c index 9ba4516ab09..d5ca76e6428 100644 --- a/sys/dev/acpi/acpibat.c +++ b/sys/dev/acpi/acpibat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpibat.c,v 1.47 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpibat.c,v 1.48 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -70,7 +70,7 @@ acpibat_attach(struct device *parent, struct device *self, void *aux) struct aml_value res; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, &res)) { dnprintf(10, "%s: no _STA\n", DEVNAME(sc)); @@ -81,7 +81,7 @@ acpibat_attach(struct device *parent, struct device *self, void *aux) acpibat_getbif(sc); acpibat_getbst(sc); - printf(": %s", sc->sc_devnode->name); + printf(": %s", sc->sc_devnode->parent->name); if (sc->sc_bif.bif_model[0]) printf(" model \"%s\"", sc->sc_bif.bif_model); if (sc->sc_bif.bif_serial[0]) @@ -92,7 +92,7 @@ acpibat_attach(struct device *parent, struct device *self, void *aux) printf(" oem \"%s\"", sc->sc_bif.bif_oem); printf("\n"); } else - printf(": %s not present\n", sc->sc_devnode->name); + printf(": %s not present\n", sc->sc_devnode->parent->name); aml_freevalue(&res); @@ -102,7 +102,7 @@ acpibat_attach(struct device *parent, struct device *self, void *aux) /* populate sensors */ acpibat_refresh(sc); - aml_register_notify(sc->sc_devnode, aa->aaa_dev, + aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, acpibat_notify, sc, ACPIDEV_POLL); } @@ -173,7 +173,7 @@ acpibat_refresh(void *arg) int i; dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc), - sc->sc_devnode->name); + sc->sc_devnode->parent->name); if (!sc->sc_bat_present) { for (i = 0; i < 8; i++) { @@ -398,13 +398,13 @@ acpibat_notify(struct aml_node *node, int notify_type, void *arg) struct acpibat_softc *sc = arg; dnprintf(10, "acpibat_notify: %.2x %s\n", notify_type, - sc->sc_devnode->name); + sc->sc_devnode->parent->name); switch (notify_type) { case 0x80: /* _BST changed */ if (!sc->sc_bat_present) { printf("%s: %s: inserted\n", DEVNAME(sc), - sc->sc_devnode->name); + sc->sc_devnode->parent->name); sc->sc_bat_present = 1; } break; @@ -412,7 +412,7 @@ acpibat_notify(struct aml_node *node, int notify_type, void *arg) /* XXX consider this a device removal */ if (sc->sc_bat_present) { printf("%s: %s: removed\n", DEVNAME(sc), - sc->sc_devnode->name); + sc->sc_devnode->parent->name); sc->sc_bat_present = 0; } break; diff --git a/sys/dev/acpi/acpibtn.c b/sys/dev/acpi/acpibtn.c index cc1e70853f3..d21b87789a0 100644 --- a/sys/dev/acpi/acpibtn.c +++ b/sys/dev/acpi/acpibtn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpibtn.c,v 1.17 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpibtn.c,v 1.18 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -84,7 +84,7 @@ acpibtn_attach(struct device *parent, struct device *self, void *aux) struct acpi_attach_args *aa = aux; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; if (!strcmp(aa->aaa_dev, ACPI_DEV_LD)) sc->sc_btn_type = ACPIBTN_LID; @@ -97,9 +97,9 @@ acpibtn_attach(struct device *parent, struct device *self, void *aux) acpibtn_getsta(sc); - printf(": %s\n", sc->sc_devnode->name); + printf(": %s\n", sc->sc_devnode->parent->name); - aml_register_notify(sc->sc_devnode, aa->aaa_dev, acpibtn_notify, + aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, acpibtn_notify, sc, ACPIDEV_NOPOLL); } @@ -120,7 +120,7 @@ acpibtn_notify(struct aml_node *node, int notify_type, void *arg) struct acpibtn_softc *sc = arg; dnprintf(10, "acpibtn_notify: %.2x %s\n", notify_type, - sc->sc_devnode->name); + sc->sc_devnode->parent->name); switch (sc->sc_btn_type) { case ACPIBTN_LID: diff --git a/sys/dev/acpi/acpidebug.c b/sys/dev/acpi/acpidebug.c index 5bcb8b86535..75bae88352f 100644 --- a/sys/dev/acpi/acpidebug.c +++ b/sys/dev/acpi/acpidebug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpidebug.c,v 1.17 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpidebug.c,v 1.18 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@openbsd.org> * @@ -165,21 +165,21 @@ db_aml_showvalue(struct aml_value *value) AML_FIELD_UPDATE(value->v_field.flags), value->v_field.bitpos, value->v_field.bitlen); - if (value->v_field.ref2) - db_printf(" index: %.3x %s\n", - value->v_field.ref3, - aml_nodename(value->v_field.ref2->node)); - if (value->v_field.ref1) - db_printf(" data: %s\n", - aml_nodename(value->v_field.ref1->node)); + + db_aml_showvalue(value->v_field.ref1); + db_aml_showvalue(value->v_field.ref2); break; case AML_OBJTYPE_BUFFERFIELD: - db_printf("%s: pos=%.4x len=%.4x\n", + db_printf("%s: pos=%.4x len=%.4x ", aml_mnem(value->v_field.type, NULL), value->v_field.bitpos, value->v_field.bitlen); - db_printf(" buffer: %s\n", - aml_nodename(value->v_field.ref1->node)); + + db_aml_dump(aml_bytelen(value->v_field.bitlen), + value->v_field.ref1->v_buffer + + aml_bytepos(value->v_field.bitpos)); + + db_aml_showvalue(value->v_field.ref1); break; case AML_OBJTYPE_OPREGION: db_printf("opregion: %s,0x%llx,0x%x\n", @@ -306,24 +306,6 @@ db_acpi_showval(db_expr_t addr, int haddr, db_expr_t count, char *modif) } void -aml_disasm(struct aml_scope *scope, int lvl, - void (*dbprintf)(void *, const char *, ...), - void *arg); -void db_disprint(void *, const char *, ...); - -void db_disprint(void *arg, const char *fmt, ...) -{ - va_list ap; - char stre[64]; - - va_start(ap,fmt); - vsnprintf(stre, sizeof(stre), fmt, ap); - va_end(ap); - - db_printf(stre); -} - -void db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif) { struct aml_node *node; @@ -333,24 +315,10 @@ db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif) node = aml_searchname(&aml_root, scope); if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) { - struct aml_scope ns; - - memset(&ns, 0, sizeof(ns)); - ns.pos = node->value->v_method.start; - ns.end = node->value->v_method.end; - ns.node = node; - while (ns.pos < ns.end) - aml_disasm(&ns, 0, db_disprint, 0); - } - else - db_printf("Not a valid method\n"); -#if 0 - if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) { db_aml_disasm(node, node->value->v_method.start, node->value->v_method.end, -1, 0); } else db_printf("Not a valid method\n"); -#endif } void diff --git a/sys/dev/acpi/acpidock.c b/sys/dev/acpi/acpidock.c index 397de321206..e6848e89576 100644 --- a/sys/dev/acpi/acpidock.c +++ b/sys/dev/acpi/acpidock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpidock.c,v 1.28 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpidock.c,v 1.29 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2006,2007 Michael Knudsen <mk@openbsd.org> * @@ -76,9 +76,9 @@ acpidock_attach(struct device *parent, struct device *self, void *aux) extern struct aml_node aml_root; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; - printf(": %s", sc->sc_devnode->name); + printf(": %s", sc->sc_devnode->parent->name); acpidock_status(sc); if (sc->sc_docked == ACPIDOCK_STATUS_DOCKED) { @@ -111,7 +111,7 @@ acpidock_attach(struct device *parent, struct device *self, void *aux) TAILQ_INIT(&sc->sc_deps_h); aml_find_node(aml_root.child, "_EJD", acpidock_foundejd, sc); - aml_register_notify(sc->sc_devnode, aa->aaa_dev, + aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, acpidock_notify, sc, ACPIDEV_NOPOLL); } @@ -270,7 +270,7 @@ acpidock_foundejd(struct aml_node *node, void *arg) struct acpidock_softc *sc = (struct acpidock_softc *)arg; struct aml_value res; - dnprintf(15, "%s: %s", DEVNAME(sc), node->name); + dnprintf(15, "%s: %s", DEVNAME(sc), node->parent->name); if (aml_evalnode(sc->sc_acpi, node, 0, NULL, &res) == -1) { printf(": error\n"); @@ -279,11 +279,11 @@ acpidock_foundejd(struct aml_node *node, void *arg) /* XXX debug */ dnprintf(10, "%s: %s depends on %s\n", DEVNAME(sc), - node->name, res.v_string); + node->parent->name, res.v_string); /* XXX more than one dock? */ n = malloc(sizeof(struct aml_nodelist), M_DEVBUF, M_WAITOK); - n->node = node; + n->node = node->parent; TAILQ_INSERT_TAIL(&sc->sc_deps_h, n, entries); } diff --git a/sys/dev/acpi/acpiec.c b/sys/dev/acpi/acpiec.c index e505f552919..a960c6f8dfd 100644 --- a/sys/dev/acpi/acpiec.c +++ b/sys/dev/acpi/acpiec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiec.c,v 1.22 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpiec.c,v 1.23 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2006 Can Erkin Acar <canacar@openbsd.org> * @@ -279,7 +279,7 @@ acpiec_attach(struct device *parent, struct device *self, void *aux) struct acpi_attach_args *aa = aux; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; if (sc->sc_acpi->sc_ec != NULL) { printf(": Only single EC is supported\n"); diff --git a/sys/dev/acpi/acpiprt.c b/sys/dev/acpi/acpiprt.c index e333bcf97f0..3051294b851 100644 --- a/sys/dev/acpi/acpiprt.c +++ b/sys/dev/acpi/acpiprt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiprt.c,v 1.23 2008/05/14 16:26:44 jordan Exp $ */ +/* $OpenBSD: acpiprt.c,v 1.24 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org> * @@ -45,7 +45,6 @@ int acpiprt_match(struct device *, void *, void *); void acpiprt_attach(struct device *, struct device *, void *); int acpiprt_getirq(union acpi_resource *crs, void *arg); int acpiprt_getminbus(union acpi_resource *, void *); -int acpiprt_showprs(union acpi_resource *, void *); struct acpiprt_softc { @@ -120,35 +119,6 @@ acpiprt_attach(struct device *parent, struct device *self, void *aux) } int -acpiprt_showprs(union acpi_resource *crs, void *arg) -{ - int *irq = (int *)arg; - int typ; - - typ = AML_CRSTYPE(crs); - switch (typ) { - case SR_IRQ: - printf("possible irq:[ "); - for (typ = 0; typ < sizeof(crs->sr_irq.irq_mask) * 8; typ++) { - if (crs->sr_irq.irq_mask & (1L << typ)) - printf("%d%s ", typ, (typ == *irq) ? "*" : ""); - } - printf("]\n"); - break; - case LR_EXTIRQ: - printf("possible irq: [ "); - for (typ = 0; typ < crs->lr_extirq.irq_count; typ++) - printf("%d%s ", crs->lr_extirq.irq[typ], - crs->lr_extirq.irq[typ] == *irq ? "*" : ""); - printf("]\n"); - break; - default: - printf("Unknown interrupt : %x\n", typ); - } - return (0); -} - -int acpiprt_getirq(union acpi_resource *crs, void *arg) { int *irq = (int *)arg; @@ -196,16 +166,8 @@ acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v) } pp = v->v_package[2]; - if (pp->type == AML_OBJTYPE_STRING) { - node = aml_searchrel(sc->sc_devnode, pp->v_string); - if (node == NULL) { - printf("Invalid device\n"); - return; - } - pp = node->value; - } if (pp->type == AML_OBJTYPE_NAMEREF) { - node = aml_searchrel(sc->sc_devnode, pp->v_nameref); + node = aml_searchname(sc->sc_devnode, pp->v_nameref); if (node == NULL) { printf("Invalid device\n"); return; @@ -236,19 +198,6 @@ acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v) aml_parse_resource(res.length, res.v_buffer, acpiprt_getirq, &irq); aml_freevalue(&res); - -#if 0 - /* Get Possible IRQs */ - if (!aml_evalname(sc->sc_acpi, node, "_PRS.", 0, NULL, &res)){ - if (res.type == AML_OBJTYPE_BUFFER && - res.length >= 6) - { - aml_parse_resource(res.length, res.v_buffer, - acpiprt_showprs, &irq); - } - aml_freevalue(&res); - } -#endif } else { irq = aml_val2int(v->v_package[3]); } @@ -391,5 +340,6 @@ acpiprt_getpcibus(struct acpiprt_softc *sc, struct aml_node *node) return (PPB_BUSINFO_SECONDARY(reg)); } } + return (0); } diff --git a/sys/dev/acpi/acpithinkpad.c b/sys/dev/acpi/acpithinkpad.c index a956d774127..37d7a087a42 100644 --- a/sys/dev/acpi/acpithinkpad.c +++ b/sys/dev/acpi/acpithinkpad.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpithinkpad.c,v 1.3 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpithinkpad.c,v 1.4 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2008 joshua stein <jcs@openbsd.org> @@ -27,9 +27,6 @@ #define THINKPAD_HKEY_VERSION 0x0100 -#define THINKPAD_CMOS_VOLUME_DOWN 0x00 -#define THINKPAD_CMOS_VOLUME_UP 0x01 -#define THINKPAD_CMOS_VOLUME_MUTE 0x02 #define THINKPAD_CMOS_BRIGHTNESS_UP 0x04 #define THINKPAD_CMOS_BRIGHTNESS_DOWN 0x05 @@ -54,9 +51,6 @@ #define THINKPAD_BUTTON_BRIGHTNESS_DOWN 0x011 #define THINKPAD_BUTTON_THINKLIGHT 0x012 #define THINKPAD_BUTTON_FN_SPACE 0x014 -#define THINKPAD_BUTTON_VOLUME_UP 0x015 -#define THINKPAD_BUTTON_VOLUME_DOWN 0x016 -#define THINKPAD_BUTTON_VOLUME_MUTE 0x017 #define THINKPAD_BUTTON_THINKVANTAGE 0x018 #define THINKPAD_BUTTON_FN_F11 0x00b #define THINKPAD_BUTTON_HIBERNATE 0x00c @@ -69,9 +63,6 @@ #define THINKPAD_TABLET_PEN_INSERTED 0x00b #define THINKPAD_TABLET_PEN_REMOVED 0x00c -/* type 7 events */ -#define THINKPAD_SWITCH_WIRELESS 0x000 - struct acpithinkpad_softc { struct device sc_dev; @@ -86,9 +77,6 @@ int thinkpad_enable_events(struct acpithinkpad_softc *); int thinkpad_toggle_bluetooth(struct acpithinkpad_softc *); int thinkpad_toggle_wan(struct acpithinkpad_softc *); int thinkpad_cmos(struct acpithinkpad_softc *sc, uint8_t); -int thinkpad_volume_down(struct acpithinkpad_softc *); -int thinkpad_volume_up(struct acpithinkpad_softc *); -int thinkpad_volume_mute(struct acpithinkpad_softc *); int thinkpad_brightness_up(struct acpithinkpad_softc *); int thinkpad_brightness_down(struct acpithinkpad_softc *); @@ -112,14 +100,13 @@ thinkpad_match(struct device *parent, void *match, void *aux) aa->aaa_table != NULL) return (0); - if (aml_evalname((struct acpi_softc *)parent, aa->aaa_node, + if (aml_evalname((struct acpi_softc *)parent, aa->aaa_node->child, "MHKV", 0, NULL, &res)) goto fail; if (aml_val2int(&res) != THINKPAD_HKEY_VERSION) goto fail; - aml_freevalue(&res); return (1); fail: @@ -131,10 +118,10 @@ void thinkpad_attach(struct device *parent, struct device *self, void *aux) { struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self; - struct acpi_attach_args *aa = aux; + struct acpi_attach_args *aa = aux; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; printf("\n"); @@ -142,7 +129,7 @@ thinkpad_attach(struct device *parent, struct device *self, void *aux) thinkpad_enable_events(sc); /* run thinkpad_hotkey on button presses */ - aml_register_notify(sc->sc_devnode, aa->aaa_dev, + aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, thinkpad_hotkey, sc, ACPIDEV_NOPOLL); return; @@ -158,7 +145,8 @@ thinkpad_enable_events(struct acpithinkpad_softc *sc) /* get the supported event mask */ if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKA", 0, NULL, &res)) { printf("%s: no MHKA\n", DEVNAME(sc)); - goto fail; + aml_freevalue(&res); + return (1); } mask = aml_val2int(&res); @@ -172,7 +160,7 @@ thinkpad_enable_events(struct acpithinkpad_softc *sc) if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKM", 2, args, NULL)) { printf("%s: couldn't toggle MHKM\n", DEVNAME(sc)); - goto fail; + return (1); } } @@ -182,24 +170,10 @@ thinkpad_enable_events(struct acpithinkpad_softc *sc) arg.v_integer = 1; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKC", 1, &arg, NULL)) { printf("%s: couldn't enable hotkeys\n", DEVNAME(sc)); - goto fail; + return (1); } - aml_freevalue(&res); - aml_freevalue(&args[0]); - aml_freevalue(&args[1]); - aml_freevalue(&args[2]); - aml_freevalue(&arg); - return (0); - -fail: - aml_freevalue(&res); - aml_freevalue(&args[0]); - aml_freevalue(&args[1]); - aml_freevalue(&args[2]); - aml_freevalue(&arg); - return (1); } int @@ -217,7 +191,6 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg) } val = aml_val2int(&res); - aml_freevalue(&res); if (val == 0) return (1); @@ -257,22 +230,9 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg) case THINKPAD_BUTTON_EJECT: case THINKPAD_BUTTON_THINKLIGHT: case THINKPAD_BUTTON_FN_SPACE: - handled = 1; - break; - case THINKPAD_BUTTON_VOLUME_DOWN: - thinkpad_volume_down(sc); - handled = 1; - break; - case THINKPAD_BUTTON_VOLUME_UP: - thinkpad_volume_up(sc); - handled = 1; - break; - case THINKPAD_BUTTON_VOLUME_MUTE: - thinkpad_volume_mute(sc); - handled = 1; - break; case THINKPAD_BUTTON_THINKVANTAGE: case THINKPAD_BUTTON_FN_F11: + /* TODO: notify userland */ handled = 1; break; } @@ -286,19 +246,12 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg) case THINKPAD_LID_CLOSED: case THINKPAD_TABLET_PEN_INSERTED: case THINKPAD_TABLET_PEN_REMOVED: + /* TODO: notify userland */ handled = 1; break; } break; - case 7: - switch (event) { - case THINKPAD_SWITCH_WIRELESS: - handled = 1; - - break; - } - break; } if (!handled) @@ -329,12 +282,9 @@ thinkpad_toggle_bluetooth(struct acpithinkpad_softc *sc) arg.v_integer = bluetooth ^= THINKPAD_BLUETOOTH_ENABLED; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SBDC", 1, &arg, NULL)) { printf("%s: couldn't toggle bluetooth\n", DEVNAME(sc)); - aml_freevalue(&arg); return (1); } - aml_freevalue(&arg); - return (0); } @@ -359,12 +309,9 @@ thinkpad_toggle_wan(struct acpithinkpad_softc *sc) arg.v_integer = wan ^= THINKPAD_WAN_ENABLED; if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SWAN", 1, &arg, NULL)) { printf("%s: couldn't toggle wan\n", DEVNAME(sc)); - aml_freevalue(&arg); return (1); } - aml_freevalue(&arg); - return (0); } @@ -380,34 +327,13 @@ thinkpad_cmos(struct acpithinkpad_softc *sc, uint8_t cmd) if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "\\UCMS", 1, &arg, NULL)) { printf("%s: cmos command 0x%x failed\n", DEVNAME(sc), cmd); - aml_freevalue(&arg); return (1); } - aml_freevalue(&arg); - return (0); } int -thinkpad_volume_down(struct acpithinkpad_softc *sc) -{ - return thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_DOWN); -} - -int -thinkpad_volume_up(struct acpithinkpad_softc *sc) -{ - return thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_UP); -} - -int -thinkpad_volume_mute(struct acpithinkpad_softc *sc) -{ - return thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_MUTE); -} - -int thinkpad_brightness_up(struct acpithinkpad_softc *sc) { return thinkpad_cmos(sc, THINKPAD_CMOS_BRIGHTNESS_UP); diff --git a/sys/dev/acpi/acpitz.c b/sys/dev/acpi/acpitz.c index be6d35bbe41..952f6e5bb09 100644 --- a/sys/dev/acpi/acpitz.c +++ b/sys/dev/acpi/acpitz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpitz.c,v 1.24 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: acpitz.c,v 1.25 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2006 Can Erkin Acar <canacar@openbsd.org> * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> @@ -104,7 +104,7 @@ acpitz_attach(struct device *parent, struct device *self, void *aux) char name[8]; sc->sc_acpi = (struct acpi_softc *)parent; - sc->sc_devnode = aa->aaa_node; + sc->sc_devnode = aa->aaa_node->child; sc->sc_lasttmp = -1; if ((sc->sc_tmp = acpitz_gettempreading(sc, "_TMP")) == -1) { @@ -142,7 +142,7 @@ acpitz_attach(struct device *parent, struct device *self, void *aux) sensordev_install(&sc->sc_sensdev); sc->sc_sens.value = 0; - aml_register_notify(sc->sc_devnode, NULL, + aml_register_notify(sc->sc_devnode->parent, NULL, acpitz_notify, sc, ACPIDEV_POLL); } @@ -252,12 +252,12 @@ acpitz_refresh(void *arg) int i, perc; dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc), - sc->sc_devnode->name); + sc->sc_devnode->parent->name); /* get _TMP and debounce the value */ if (-1 == (sc->sc_tmp = acpitz_gettempreading(sc, "_TMP"))) { printf("%s: %s: failed to read temp\n", DEVNAME(sc), - sc->sc_devnode->name); + sc->sc_devnode->parent->name); return; } /* critical trip points */ @@ -351,7 +351,7 @@ acpitz_gettempreading(struct acpitz_softc *sc, char *name) } if (i >= ACPITZ_TMP_RETRY) { printf("%s: %s: failed to read %s\n", DEVNAME(sc), - sc->sc_devnode->name, name); + sc->sc_devnode->parent->name, name); goto out; } out: @@ -367,7 +367,7 @@ acpitz_notify(struct aml_node *node, int notify_type, void *arg) int crt; dnprintf(10, "%s notify: %.2x %s\n", DEVNAME(sc), notify_type, - sc->sc_devnode->name); + sc->sc_devnode->parent->name); switch (notify_type) { case 0x80: /* hardware notifications */ diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h index daa7d03fe30..54f1a816f6a 100644 --- a/sys/dev/acpi/amltypes.h +++ b/sys/dev/acpi/amltypes.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amltypes.h,v 1.27 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: amltypes.h,v 1.28 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> * @@ -275,7 +275,6 @@ struct aml_value { u_int8_t iospace; u_int64_t iobase; u_int32_t iolen; - int flag; } vopregion; struct { int flags; diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c index 61ef7922589..b86b5913a3a 100644 --- a/sys/dev/acpi/dsdt.c +++ b/sys/dev/acpi/dsdt.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dsdt.c,v 1.114 2008/05/15 23:23:09 jordan Exp $ */ +/* $OpenBSD: dsdt.c,v 1.115 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> * @@ -34,10 +34,6 @@ #include <dev/acpi/amltypes.h> #include <dev/acpi/dsdt.h> -#ifdef SMALL_KERNEL -#undef ACPI_DEBUG -#endif - #define opsize(opcode) (((opcode) & 0xFF00) ? 2 : 1) #define AML_CHECKSTACK() @@ -126,6 +122,24 @@ struct aml_node aml_root; struct aml_value *aml_global_lock; struct acpi_softc *dsdt_softc; +struct aml_value *aml_parsenamed(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsenamedscope(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsemath(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsecompare(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parseif(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsewhile(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsebufpkg(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsemethod(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsesimple(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsefieldunit(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsebufferfield(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsemisc3(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsemuxaction(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsemisc2(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsematch(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parseref(struct aml_scope *, int, struct aml_value *); +struct aml_value *aml_parsestring(struct aml_scope *, int, struct aml_value *); + /* Perfect Hash key */ #define HASH_OFF 6904 #define HASH_SIZE 179 @@ -138,139 +152,139 @@ struct acpi_softc *dsdt_softc; struct aml_opcode **aml_ophash; struct aml_opcode aml_table[] = { /* Simple types */ - { AMLOP_ZERO, "Zero", "c", }, - { AMLOP_ONE, "One", "c", }, - { AMLOP_ONES, "Ones", "c", }, - { AMLOP_REVISION, "Revision", "R", }, - { AMLOP_BYTEPREFIX, ".Byte", "b", }, - { AMLOP_WORDPREFIX, ".Word", "w", }, - { AMLOP_DWORDPREFIX, ".DWord", "d", }, - { AMLOP_QWORDPREFIX, ".QWord", "q", }, - { AMLOP_STRINGPREFIX, ".String", "a", }, - { AMLOP_DEBUG, "DebugOp", "D", }, - { AMLOP_BUFFER, "Buffer", "piB", }, - { AMLOP_PACKAGE, "Package", "pbT", }, - { AMLOP_VARPACKAGE, "VarPackage", "piT", }, + { AMLOP_ZERO, "Zero", "c", aml_parsesimple }, + { AMLOP_ONE, "One", "c", aml_parsesimple }, + { AMLOP_ONES, "Ones", "c", aml_parsesimple }, + { AMLOP_REVISION, "Revision", "R", aml_parsesimple }, + { AMLOP_BYTEPREFIX, ".Byte", "b", aml_parsesimple }, + { AMLOP_WORDPREFIX, ".Word", "w", aml_parsesimple }, + { AMLOP_DWORDPREFIX, ".DWord", "d", aml_parsesimple }, + { AMLOP_QWORDPREFIX, ".QWord", "q", aml_parsesimple }, + { AMLOP_STRINGPREFIX, ".String", "a", aml_parsesimple }, + { AMLOP_DEBUG, "DebugOp", "D", aml_parsesimple }, + { AMLOP_BUFFER, "Buffer", "piB", aml_parsebufpkg }, + { AMLOP_PACKAGE, "Package", "pbT", aml_parsebufpkg }, + { AMLOP_VARPACKAGE, "VarPackage", "piT", aml_parsebufpkg }, /* Simple objects */ - { AMLOP_LOCAL0, "Local0", "L", }, - { AMLOP_LOCAL1, "Local1", "L", }, - { AMLOP_LOCAL2, "Local2", "L", }, - { AMLOP_LOCAL3, "Local3", "L", }, - { AMLOP_LOCAL4, "Local4", "L", }, - { AMLOP_LOCAL5, "Local5", "L", }, - { AMLOP_LOCAL6, "Local6", "L", }, - { AMLOP_LOCAL7, "Local7", "L", }, - { AMLOP_ARG0, "Arg0", "A", }, - { AMLOP_ARG1, "Arg1", "A", }, - { AMLOP_ARG2, "Arg2", "A", }, - { AMLOP_ARG3, "Arg3", "A", }, - { AMLOP_ARG4, "Arg4", "A", }, - { AMLOP_ARG5, "Arg5", "A", }, - { AMLOP_ARG6, "Arg6", "A", }, + { AMLOP_LOCAL0, "Local0", "L", aml_parseref }, + { AMLOP_LOCAL1, "Local1", "L", aml_parseref }, + { AMLOP_LOCAL2, "Local2", "L", aml_parseref }, + { AMLOP_LOCAL3, "Local3", "L", aml_parseref }, + { AMLOP_LOCAL4, "Local4", "L", aml_parseref }, + { AMLOP_LOCAL5, "Local5", "L", aml_parseref }, + { AMLOP_LOCAL6, "Local6", "L", aml_parseref }, + { AMLOP_LOCAL7, "Local7", "L", aml_parseref }, + { AMLOP_ARG0, "Arg0", "A", aml_parseref }, + { AMLOP_ARG1, "Arg1", "A", aml_parseref }, + { AMLOP_ARG2, "Arg2", "A", aml_parseref }, + { AMLOP_ARG3, "Arg3", "A", aml_parseref }, + { AMLOP_ARG4, "Arg4", "A", aml_parseref }, + { AMLOP_ARG5, "Arg5", "A", aml_parseref }, + { AMLOP_ARG6, "Arg6", "A", aml_parseref }, /* Control flow */ - { AMLOP_IF, "If", "piI", }, + { AMLOP_IF, "If", "pI", aml_parseif }, { AMLOP_ELSE, "Else", "pT" }, - { AMLOP_WHILE, "While", "pW", }, + { AMLOP_WHILE, "While", "piT", aml_parsewhile }, { AMLOP_BREAK, "Break", "" }, { AMLOP_CONTINUE, "Continue", "" }, - { AMLOP_RETURN, "Return", "t", }, - { AMLOP_FATAL, "Fatal", "bdi", }, - { AMLOP_NOP, "Nop", "", }, - { AMLOP_BREAKPOINT, "BreakPoint", "", }, + { AMLOP_RETURN, "Return", "t", aml_parseref }, + { AMLOP_FATAL, "Fatal", "bdi", aml_parsemisc2 }, + { AMLOP_NOP, "Nop", "", aml_parsesimple }, + { AMLOP_BREAKPOINT, "BreakPoint", "", aml_parsesimple }, /* Arithmetic operations */ - { AMLOP_INCREMENT, "Increment", "t", }, - { AMLOP_DECREMENT, "Decrement", "t", }, - { AMLOP_ADD, "Add", "iir", }, - { AMLOP_SUBTRACT, "Subtract", "iir", }, - { AMLOP_MULTIPLY, "Multiply", "iir", }, - { AMLOP_DIVIDE, "Divide", "iirr", }, - { AMLOP_SHL, "ShiftLeft", "iir", }, - { AMLOP_SHR, "ShiftRight", "iir", }, - { AMLOP_AND, "And", "iir", }, - { AMLOP_NAND, "Nand", "iir", }, - { AMLOP_OR, "Or", "iir", }, - { AMLOP_NOR, "Nor", "iir", }, - { AMLOP_XOR, "Xor", "iir", }, - { AMLOP_NOT, "Not", "ir", }, - { AMLOP_MOD, "Mod", "iir", }, - { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "ir", }, - { AMLOP_FINDSETRIGHTBIT,"FindSetRightBit", "ir",}, + { AMLOP_INCREMENT, "Increment", "t", aml_parsemath }, + { AMLOP_DECREMENT, "Decrement", "t", aml_parsemath }, + { AMLOP_ADD, "Add", "iir", aml_parsemath }, + { AMLOP_SUBTRACT, "Subtract", "iir", aml_parsemath }, + { AMLOP_MULTIPLY, "Multiply", "iir", aml_parsemath }, + { AMLOP_DIVIDE, "Divide", "iirr", aml_parsemath }, + { AMLOP_SHL, "ShiftLeft", "iir", aml_parsemath }, + { AMLOP_SHR, "ShiftRight", "iir", aml_parsemath }, + { AMLOP_AND, "And", "iir", aml_parsemath }, + { AMLOP_NAND, "Nand", "iir", aml_parsemath }, + { AMLOP_OR, "Or", "iir", aml_parsemath }, + { AMLOP_NOR, "Nor", "iir", aml_parsemath }, + { AMLOP_XOR, "Xor", "iir", aml_parsemath }, + { AMLOP_NOT, "Not", "ir", aml_parsemath }, + { AMLOP_MOD, "Mod", "iir", aml_parsemath }, + { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "ir", aml_parsemath }, + { AMLOP_FINDSETRIGHTBIT,"FindSetRightBit", "ir",aml_parsemath }, /* Logical test operations */ - { AMLOP_LAND, "LAnd", "ii", }, - { AMLOP_LOR, "LOr", "ii", }, - { AMLOP_LNOT, "LNot", "i", }, - { AMLOP_LNOTEQUAL, "LNotEqual", "tt", }, - { AMLOP_LLESSEQUAL, "LLessEqual", "tt", }, - { AMLOP_LGREATEREQUAL, "LGreaterEqual", "tt", }, - { AMLOP_LEQUAL, "LEqual", "tt", }, - { AMLOP_LGREATER, "LGreater", "tt", }, - { AMLOP_LLESS, "LLess", "tt", }, + { AMLOP_LAND, "LAnd", "ii", aml_parsemath }, + { AMLOP_LOR, "LOr", "ii", aml_parsemath }, + { AMLOP_LNOT, "LNot", "i", aml_parsemath }, + { AMLOP_LNOTEQUAL, "LNotEqual", "tt", aml_parsecompare }, + { AMLOP_LLESSEQUAL, "LLessEqual", "tt", aml_parsecompare }, + { AMLOP_LGREATEREQUAL, "LGreaterEqual", "tt", aml_parsecompare }, + { AMLOP_LEQUAL, "LEqual", "tt", aml_parsecompare }, + { AMLOP_LGREATER, "LGreater", "tt", aml_parsecompare }, + { AMLOP_LLESS, "LLess", "tt", aml_parsecompare }, /* Named objects */ - { AMLOP_NAMECHAR, ".NameRef", "n", }, - { AMLOP_ALIAS, "Alias", "nN", }, - { AMLOP_NAME, "Name", "Nt", }, - { AMLOP_EVENT, "Event", "N", }, - { AMLOP_MUTEX, "Mutex", "Nb", }, - { AMLOP_DATAREGION, "DataRegion", "Nttt", }, - { AMLOP_OPREGION, "OpRegion", "Nbii", }, - { AMLOP_SCOPE, "Scope", "pNT", }, - { AMLOP_DEVICE, "Device", "pNT", }, - { AMLOP_POWERRSRC, "Power Resource", "pNbwT",}, - { AMLOP_THERMALZONE, "ThermalZone", "pNT", }, - { AMLOP_PROCESSOR, "Processor", "pNbdbT", }, - { AMLOP_METHOD, "Method", "pNbM", }, + { AMLOP_NAMECHAR, ".NameRef", "n", aml_parsesimple }, + { AMLOP_ALIAS, "Alias", "nN", aml_parsenamed }, + { AMLOP_NAME, "Name", "Nt", aml_parsenamed }, + { AMLOP_EVENT, "Event", "N", aml_parsenamed }, + { AMLOP_MUTEX, "Mutex", "Nb", aml_parsenamed }, + { AMLOP_DATAREGION, "DataRegion", "Nttt", aml_parsenamed }, + { AMLOP_OPREGION, "OpRegion", "Nbii", aml_parsenamed }, + { AMLOP_SCOPE, "Scope", "pNT", aml_parsenamedscope }, + { AMLOP_DEVICE, "Device", "pNT", aml_parsenamedscope }, + { AMLOP_POWERRSRC, "Power Resource", "pNbwT", aml_parsenamedscope }, + { AMLOP_THERMALZONE, "ThermalZone", "pNT", aml_parsenamedscope }, + { AMLOP_PROCESSOR, "Processor", "pNbdbT", aml_parsenamedscope }, + { AMLOP_METHOD, "Method", "pNfM", aml_parsemethod }, /* Field operations */ - { AMLOP_FIELD, "Field", "pnbF", }, - { AMLOP_INDEXFIELD, "IndexField", "pnnbF",}, - { AMLOP_BANKFIELD, "BankField", "pnnibF",}, - { AMLOP_CREATEFIELD, "CreateField", "tiiN", }, - { AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN",}, - { AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN",}, - { AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN",}, - { AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN",}, - { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", }, + { AMLOP_FIELD, "Field", "pnfF", aml_parsefieldunit }, + { AMLOP_INDEXFIELD, "IndexField", "pntfF", aml_parsefieldunit }, + { AMLOP_BANKFIELD, "BankField", "pnnifF", aml_parsefieldunit }, + { AMLOP_CREATEFIELD, "CreateField", "tiiN", aml_parsebufferfield }, + { AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN", aml_parsebufferfield }, + { AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN", aml_parsebufferfield }, + { AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN", aml_parsebufferfield }, + { AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN", aml_parsebufferfield }, + { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", aml_parsebufferfield }, /* Conversion operations */ - { AMLOP_TOINTEGER, "ToInteger", "tr", }, + { AMLOP_TOINTEGER, "ToInteger", "tr", aml_parsemath }, { AMLOP_TOBUFFER, "ToBuffer", "tr", }, - { AMLOP_TODECSTRING, "ToDecString", "ir", }, - { AMLOP_TOHEXSTRING, "ToHexString", "ir", }, - { AMLOP_TOSTRING, "ToString", "tir", }, - { AMLOP_MID, "Mid", "tiir", }, - { AMLOP_FROMBCD, "FromBCD", "ir", }, - { AMLOP_TOBCD, "ToBCD", "ir", }, + { AMLOP_TODECSTRING, "ToDecString", "ir", aml_parsestring }, + { AMLOP_TOHEXSTRING, "ToHexString", "ir", aml_parsestring }, + { AMLOP_TOSTRING, "ToString", "t", aml_parsestring }, + { AMLOP_MID, "Mid", "tiir", aml_parsestring }, + { AMLOP_FROMBCD, "FromBCD", "ir", aml_parsemath }, + { AMLOP_TOBCD, "ToBCD", "ir", aml_parsemath }, /* Mutex/Signal operations */ - { AMLOP_ACQUIRE, "Acquire", "Sw", }, - { AMLOP_RELEASE, "Release", "S", }, - { AMLOP_SIGNAL, "Signal", "S", }, - { AMLOP_WAIT, "Wait", "Si", }, - { AMLOP_RESET, "Reset", "S", }, + { AMLOP_ACQUIRE, "Acquire", "tw", aml_parsemuxaction }, + { AMLOP_RELEASE, "Release", "t", aml_parsemuxaction }, + { AMLOP_SIGNAL, "Signal", "t", aml_parsemuxaction }, + { AMLOP_WAIT, "Wait", "ti", aml_parsemuxaction }, + { AMLOP_RESET, "Reset", "t", aml_parsemuxaction }, - { AMLOP_INDEX, "Index", "tir", }, - { AMLOP_DEREFOF, "DerefOf", "t", }, - { AMLOP_REFOF, "RefOf", "S", }, - { AMLOP_CONDREFOF, "CondRef", "SS", }, + { AMLOP_INDEX, "Index", "tir", aml_parseref }, + { AMLOP_DEREFOF, "DerefOf", "t", aml_parseref }, + { AMLOP_REFOF, "RefOf", "t", aml_parseref }, + { AMLOP_CONDREFOF, "CondRef", "nr", aml_parseref }, { AMLOP_LOADTABLE, "LoadTable", "tttttt" }, - { AMLOP_STALL, "Stall", "i", }, - { AMLOP_SLEEP, "Sleep", "i", }, - { AMLOP_LOAD, "Load", "nS", }, + { AMLOP_STALL, "Stall", "i", aml_parsemisc2 }, + { AMLOP_SLEEP, "Sleep", "i", aml_parsemisc2 }, + { AMLOP_LOAD, "Load", "nt", aml_parseref }, { AMLOP_UNLOAD, "Unload", "t" }, - { AMLOP_STORE, "Store", "tS", }, - { AMLOP_CONCAT, "Concat", "ttr", }, + { AMLOP_STORE, "Store", "tr", aml_parseref }, + { AMLOP_CONCAT, "Concat", "ttr", aml_parsestring }, { AMLOP_CONCATRES, "ConcatRes", "ttt" }, - { AMLOP_NOTIFY, "Notify", "Si", }, - { AMLOP_SIZEOF, "Sizeof", "S", }, - { AMLOP_MATCH, "Match", "tbibii", }, - { AMLOP_OBJECTTYPE, "ObjectType", "S", }, - { AMLOP_COPYOBJECT, "CopyObject", "tS", }, + { AMLOP_NOTIFY, "Notify", "ti", aml_parsemisc2 }, + { AMLOP_SIZEOF, "Sizeof", "t", aml_parsemisc3 }, + { AMLOP_MATCH, "Match", "tbibii", aml_parsematch }, + { AMLOP_OBJECTTYPE, "ObjectType", "t", aml_parsemisc3 }, + { AMLOP_COPYOBJECT, "CopyObject", "tr", aml_parseref }, }; int aml_pc(uint8_t *src) @@ -453,11 +467,77 @@ acpi_stall(int us) delay(us); } +int +acpi_mutex_acquire(struct aml_value *val, int timeout) +{ + /* XXX we currently do not have concurrency so assume mutex succeeds */ + dnprintf(50, "acpi_mutex_acquire\n"); + + return (0); +#if 0 + struct acpi_mutex *mtx = val->v_mutex; + int rv = 0, ts, tries = 0; + + if (val->type != AML_OBJTYPE_MUTEX) { + printf("acpi_mutex_acquire: invalid mutex\n"); + return (1); + } + + if (timeout == 0xffff) + timeout = 0; + + /* lock recursion be damned, panic if that happens */ + rw_enter_write(&mtx->amt_lock); + while (mtx->amt_ref_count) { + rw_exit_write(&mtx->amt_lock); + /* block access */ + ts = tsleep(mtx, PWAIT, mtx->amt_name, timeout / hz); + if (ts == EWOULDBLOCK) { + rv = 1; /* mutex not acquired */ + goto done; + } + tries++; + rw_enter_write(&mtx->amt_lock); + } + + mtx->amt_ref_count++; + rw_exit_write(&mtx->amt_lock); +done: + return (rv); +#endif +} + +void +acpi_mutex_release(struct aml_value *val) +{ + dnprintf(50, "acpi_mutex_release\n"); +#if 0 + struct acpi_mutex *mtx = val->v_mutex; + + /* sanity */ + if (val->type != AML_OBJTYPE_MUTEX) { + printf("acpi_mutex_acquire: invalid mutex\n"); + return; + } + + rw_enter_write(&mtx->amt_lock); + + if (mtx->amt_ref_count == 0) { + printf("acpi_mutex_release underflow %s\n", mtx->amt_name); + goto done; + } + + mtx->amt_ref_count--; + wakeup(mtx); /* wake all of them up */ +done: + rw_exit_write(&mtx->amt_lock); +#endif +} + /* * @@@: Misc utility functions */ -#ifdef ACPI_DEBUG void aml_dump(int len, u_int8_t *buf) { @@ -469,7 +549,6 @@ aml_dump(int len, u_int8_t *buf) } dnprintf(50, " }\n"); } -#endif /* Bit mangling code */ int @@ -491,6 +570,27 @@ aml_setbit(u_int8_t *pb, int bit, int val) *pb &= ~aml_bitmask(bit); } +/* Read/Write to hardware I/O fields */ +void +aml_gasio(struct acpi_softc *sc, int type, uint64_t base, uint64_t length, + int bitpos, int bitlen, int size, void *buf, int mode) +{ + dnprintf(10, "-- aml_gasio: %.2x" + " base:%llx len:%llx bpos:%.4x blen:%.4x sz:%.2x mode=%s\n", + type, base, length, bitpos, bitlen, size, + mode==ACPI_IOREAD?"read":"write"); + acpi_gasio(sc, mode, type, base+(bitpos>>3), + (size>>3), (bitlen>>3), buf); +#ifdef ACPI_DEBUG + while (bitlen > 0) { + dnprintf(10, "%.2x ", *(uint8_t *)buf); + buf++; + bitlen -=8; + } + dnprintf(10, "\n"); +#endif +} + /* * @@@: Notify functions */ @@ -568,40 +668,21 @@ void acpi_poll_notify(void) * @@@: Namespace functions */ -struct aml_node *__aml_search(struct aml_node *, uint8_t *, int); +struct aml_node *__aml_search(struct aml_node *, uint8_t *); void aml_delchildren(struct aml_node *); /* Search for a name in children nodes */ struct aml_node * -__aml_search(struct aml_node *root, uint8_t *nameseg, int create) +__aml_search(struct aml_node *root, uint8_t *nameseg) { - struct aml_node **sp, *node; - - /* XXX: Replace with SLIST/SIMPLEQ routines */ if (root == NULL) return NULL; - //rw_enter_read(&aml_nslock); - for (sp = &root->child; *sp; sp = &(*sp)->sibling) { - if (!strncmp((*sp)->name, nameseg, AML_NAMESEG_LEN)) { - //rw_exit_read(&aml_nslock); - return *sp; + for (root = root->child; root; root = root->sibling) { + if (!memcmp(root->name, nameseg, AML_NAMESEG_LEN)) + return root; } - } - //rw_exit_read(&aml_nslock); - if (create) { - node = acpi_os_malloc(sizeof(struct aml_node)); - memcpy((void *)node->name, nameseg, AML_NAMESEG_LEN); - node->value = aml_allocvalue(0,0,NULL); - node->value->node = node; - node->parent = root; - node->sibling = NULL; - - //rw_enter_write(&aml_nslock); - *sp = node; - //rw_exit_write(&aml_nslock); - } - return *sp; + return NULL; } /* Get absolute pathname of AML node */ @@ -691,7 +772,7 @@ aml_createname(struct aml_node *root, const void *vname, struct aml_value *value node = NULL; while (count-- && root) { /* Create new name if it does not exist */ - if ((node = __aml_search(root, name, 0)) == NULL) { + if ((node = __aml_search(root, name)) == NULL) { node = acpi_os_malloc(sizeof(struct aml_node)); memcpy((void *)node->name, name, AML_NAMESEG_LEN); @@ -712,6 +793,57 @@ aml_createname(struct aml_node *root, const void *vname, struct aml_value *value return node; } +/* Search namespace for a named node */ +struct aml_node * +aml_searchname(struct aml_node *root, const void *vname) +{ + struct aml_node *node; + uint8_t *name = (uint8_t *)vname; + int count; + + if (*name == AMLOP_ROOTCHAR) { + root = &aml_root; + name++; + } + while (*name == AMLOP_PARENTPREFIX && root) { + root = root->parent; + name++; + } + if (strlen(name) < AML_NAMESEG_LEN) { + aml_die("bad name"); + } + switch (*name) { + case 0x00: + return root; + case AMLOP_MULTINAMEPREFIX: + count = name[1]; + name += 2; + break; + case AMLOP_DUALNAMEPREFIX: + count = 2; + name += 1; + break; + default: + if (name[4] == '.') { + /* Called from user code */ + while (*name && (root = __aml_search(root, name)) != NULL) { + name += AML_NAMESEG_LEN+1; + } + return root; + } + /* Special case.. search relative for name */ + while (root && (node = __aml_search(root, name)) == NULL) { + root = root->parent; + } + return node; + } + /* Search absolute for name*/ + while (count-- && (root = __aml_search(root, name)) != NULL) { + name += AML_NAMESEG_LEN; + } + return root; +} + /* Free all children nodes/values */ void aml_delchildren(struct aml_node *node) @@ -737,15 +869,39 @@ aml_delchildren(struct aml_node *node) * @@@: Value functions */ +struct aml_value *aml_alloctmp(struct aml_scope *, int); struct aml_scope *aml_pushscope(struct aml_scope *, uint8_t *, uint8_t *, struct aml_node *); struct aml_scope *aml_popscope(struct aml_scope *); +int aml_parsenode(struct aml_scope *, struct aml_node *, + uint8_t *, uint8_t **, struct aml_value *); #define AML_LHS 0 #define AML_RHS 1 #define AML_DST 2 #define AML_DST2 3 +/* Allocate temporary storage in this scope */ +struct aml_value * +aml_alloctmp(struct aml_scope *scope, int narg) +{ + struct aml_vallist *tmp; + + /* Allocate array of temp values */ + tmp = (struct aml_vallist *)acpi_os_malloc(sizeof(struct aml_vallist) + + narg * sizeof(struct aml_value)); + + tmp->obj = (struct aml_value *)&tmp[1]; + tmp->nobj = narg; + + /* Link into scope */ + tmp->next = scope->tmpvals; + scope->tmpvals = tmp; + + /* Return array of values */ + return tmp->obj; +} + /* Allocate+push parser scope */ struct aml_scope * aml_pushscope(struct aml_scope *parent, uint8_t *start, uint8_t *end, @@ -791,17 +947,94 @@ aml_popscope(struct aml_scope *scope) return nscope; } +int +aml_parsenode(struct aml_scope *parent, struct aml_node *node, uint8_t *start, + uint8_t **end, struct aml_value *res) +{ + struct aml_scope *scope; + + /* Don't parse zero-length scope */ + if (start == *end) + return 0; + scope = aml_pushscope(parent, start, *end, node); + if (res == NULL) + res = aml_alloctmp(scope, 1); + while (scope != parent) { + while (scope->pos < scope->end) + aml_parseop(scope, res, 't'); + scope = aml_popscope(scope); + } + return 0; +} + /* * Field I/O code */ +void aml_setbufint(struct aml_value *, int, int, struct aml_value *); +void aml_getbufint(struct aml_value *, int, int, struct aml_value *); +void aml_fieldio(struct aml_scope *, struct aml_value *, struct aml_value *, int); void aml_unlockfield(struct aml_scope *, struct aml_value *); void aml_lockfield(struct aml_scope *, struct aml_value *); +/* Copy from a bufferfield to an integer/buffer */ +void +aml_setbufint(struct aml_value *dst, int bitpos, int bitlen, + struct aml_value *src) +{ + if (src->type != AML_OBJTYPE_BUFFER) { +#ifndef SMALL_KERNEL + aml_showvalue(src, 0); +#endif + aml_die("wrong setbufint type %d\n", src->type); + } +#if 1 + /* Return buffer type */ + _aml_setvalue(dst, AML_OBJTYPE_BUFFER, (bitlen+7)>>3, NULL); + aml_bufcpy(dst->v_buffer, 0, src->v_buffer, bitpos, bitlen); +#else + if (bitlen < aml_intlen) { + /* XXX: Endian issues?? */ + /* Return integer type */ + _aml_setvalue(dst, AML_OBJTYPE_INTEGER, 0, NULL); + aml_bufcpy(&dst->v_integer, 0, src->v_buffer, bitpos, bitlen); + } else { + /* Return buffer type */ + _aml_setvalue(dst, AML_OBJTYPE_BUFFER, (bitlen+7)>>3, NULL); + aml_bufcpy(dst->v_buffer, 0, src->v_buffer, bitpos, bitlen); + } +#endif +} + +/* Copy from a string/integer/buffer to a bufferfield */ +void +aml_getbufint(struct aml_value *src, int bitpos, int bitlen, + struct aml_value *dst) +{ + if (dst->type != AML_OBJTYPE_BUFFER) + aml_die("wrong getbufint type %d\n", src->type); + switch (src->type) { + case AML_OBJTYPE_INTEGER: + if (bitlen >= aml_intlen) + bitlen = aml_intlen; + aml_bufcpy(dst->v_buffer, bitpos, &src->v_integer, 0, bitlen); + break; + case AML_OBJTYPE_BUFFER: + if (bitlen >= 8*src->length) + bitlen = 8*src->length; + aml_bufcpy(dst->v_buffer, bitpos, src->v_buffer, 0, bitlen); + break; + case AML_OBJTYPE_STRING: + if (bitlen >= 8*src->length) + bitlen = 8*src->length; + aml_bufcpy(dst->v_buffer, bitpos, src->v_string, 0, bitlen); + break; + } +} + long acpi_acquire_global_lock(void*); long acpi_release_global_lock(void*); static long global_lock_count = 0; -#define acpi_acquire_global_lock(x) 1 -#define acpi_release_global_lock(x) 0 + void aml_lockfield(struct aml_scope *scope, struct aml_value *field) { @@ -848,10 +1081,219 @@ aml_unlockfield(struct aml_scope *scope, struct aml_value *field) return; } +void *aml_getbuffer(struct aml_value *, int *); + +void * +aml_getbuffer(struct aml_value *val, int *bitlen) +{ + switch (val->type) { + case AML_OBJTYPE_INTEGER: + case AML_OBJTYPE_STATICINT: + *bitlen = aml_intlen; + return (&val->v_integer); + + case AML_OBJTYPE_BUFFER: + case AML_OBJTYPE_STRING: + *bitlen = val->length<<3; + return (val->v_buffer); + + default: + aml_die("getvbi"); + } + + return (NULL); +} + +/* + * Buffer/Region: read/write to bitfields + */ +void +aml_fieldio(struct aml_scope *scope, struct aml_value *field, + struct aml_value *res, int mode) +{ + struct aml_value *pop, tf; + int bpos, blen, aligned, mask; + void *iobuf, *iobuf2; + uint64_t iobase; + + pop = field->v_field.ref1; + bpos = field->v_field.bitpos; + blen = field->v_field.bitlen; + + dnprintf(55,"--fieldio: %s [%s] bp:%.4x bl:%.4x\n", + mode == ACPI_IOREAD ? "rd" : "wr", + aml_nodename(field->node), bpos, blen); + + aml_lockfield(scope, field); + switch (field->v_field.type) { + case AMLOP_INDEXFIELD: + /* Set Index */ + memcpy(&tf, field->v_field.ref2, sizeof(struct aml_value)); + tf.v_field.bitpos += (bpos & 7); + tf.v_field.bitlen = blen; + + aml_setvalue(scope, pop, NULL, bpos>>3); + aml_fieldio(scope, &tf, res, mode); +#ifdef ACPI_DEBUG + dnprintf(55, "-- post indexfield %x,%x @ %x,%x\n", + bpos & 3, blen, + field->v_field.ref2->v_field.bitpos, + field->v_field.ref2->v_field.bitlen); + + iobuf = aml_getbuffer(res, &aligned); + aml_dump(aligned >> 3, iobuf); +#endif + break; + case AMLOP_BANKFIELD: + /* Set Bank */ + memcpy(&tf, field->v_field.ref2, sizeof(struct aml_value)); + tf.v_field.bitpos += (bpos & 7); + tf.v_field.bitlen = blen; + + aml_setvalue(scope, pop, NULL, field->v_field.ref3); + aml_fieldio(scope, &tf, res, mode); +#ifdef ACPI_DEBUG + dnprintf(55, "-- post bankfield %x,%x @ %x,%x\n", + bpos & 3, blen, + field->v_field.ref2->v_field.bitpos, + field->v_field.ref2->v_field.bitlen); + + iobuf = aml_getbuffer(res, &aligned); + aml_dump(aligned >> 3, iobuf); +#endif + break; + case AMLOP_FIELD: + /* This is an I/O field */ + if (pop->type != AML_OBJTYPE_OPREGION) + aml_die("Not an opregion\n"); + + /* Get field access size */ + switch (AML_FIELD_ACCESS(field->v_field.flags)) { + case AML_FIELD_ANYACC: + case AML_FIELD_BYTEACC: + mask = 7; + break; + case AML_FIELD_WORDACC: + mask = 15; + break; + case AML_FIELD_DWORDACC: + mask = 31; + break; + case AML_FIELD_QWORDACC: + mask = 63; + break; + } + + /* Pre-allocate return value for reads */ + if (mode == ACPI_IOREAD) + _aml_setvalue(res, AML_OBJTYPE_BUFFER, + (field->v_field.bitlen+7)>>3, NULL); + + /* Get aligned bitpos/bitlength */ + blen = ((bpos & mask) + blen + mask) & ~mask; + bpos = bpos & ~mask; + aligned = (bpos == field->v_field.bitpos && + blen == field->v_field.bitlen); + iobase = pop->v_opregion.iobase; + + /* Check for aligned reads/writes */ + if (aligned) { + iobuf = aml_getbuffer(res, &aligned); + aml_gasio(scope->sc, pop->v_opregion.iospace, + iobase, pop->v_opregion.iolen, bpos, blen, + mask + 1, iobuf, mode); +#ifdef ACPI_DEBUG + dnprintf(55, "aligned: %s @ %.4x:%.4x + %.4x\n", + mode == ACPI_IOREAD ? "rd" : "wr", + bpos, blen, aligned); + + aml_dump(blen >> 3, iobuf); +#endif + } + else if (mode == ACPI_IOREAD) { + iobuf = acpi_os_malloc(blen>>3); + aml_gasio(scope->sc, pop->v_opregion.iospace, + iobase, pop->v_opregion.iolen, bpos, blen, + mask + 1, iobuf, mode); + + /* ASSERT: res is buffer type as it was set above */ + aml_bufcpy(res->v_buffer, 0, iobuf, + field->v_field.bitpos & mask, + field->v_field.bitlen); + +#ifdef ACPI_DEBUG + dnprintf(55,"non-aligned read: %.4x:%.4x : ", + field->v_field.bitpos & mask, + field->v_field.bitlen); + + aml_dump(blen >> 3, iobuf); + dnprintf(55,"post-read: "); + aml_dump((field->v_field.bitlen+7)>>3, res->v_buffer); +#endif + acpi_os_free(iobuf); + } + else { + iobuf = acpi_os_malloc(blen >> 3); + switch (AML_FIELD_UPDATE(field->v_field.flags)) { + case AML_FIELD_WRITEASONES: + memset(iobuf, 0xFF, blen >> 3); + break; + case AML_FIELD_PRESERVE: + aml_gasio(scope->sc, pop->v_opregion.iospace, + iobase, pop->v_opregion.iolen, bpos, blen, + mask + 1, iobuf, ACPI_IOREAD); + break; + } + /* Copy into IOBUF */ + iobuf2 = aml_getbuffer(res, &aligned); + aml_bufcpy(iobuf, field->v_field.bitpos & mask, + iobuf2, 0, field->v_field.bitlen); + +#ifdef ACPI_DEBUG + dnprintf(55,"non-aligned write: %.4x:%.4x : ", + field->v_field.bitpos & mask, + field->v_field.bitlen); + + aml_dump(blen >> 3, iobuf); +#endif + aml_gasio(scope->sc, pop->v_opregion.iospace, + iobase, pop->v_opregion.iolen, bpos, blen, + mask + 1, iobuf, mode); + + acpi_os_free(iobuf); + } + /* Verify that I/O is in range */ +#if 0 + /* + * XXX: some I/O ranges are on dword boundaries, but their + * length is incorrect eg. dword access, but length of + * opregion is 2 bytes. + */ + if ((bpos+blen) >= (pop->v_opregion.iolen * 8)) { + aml_die("Out of bounds I/O!!! region:%x:%llx:%x %x\n", + pop->v_opregion.iospace, pop->v_opregion.iobase, + pop->v_opregion.iolen, bpos+blen); + } +#endif + break; + default: + /* This is a buffer field */ + if (mode == ACPI_IOREAD) + aml_setbufint(res, bpos, blen, pop); + else + aml_getbufint(res, bpos, blen, pop); + break; + } + aml_unlockfield(scope, field); +} + /* * @@@: Value set/compare/alloc/free routines */ int64_t aml_str2int(const char *, int); +struct aml_value *aml_derefvalue(struct aml_scope *, struct aml_value *, int); +#define aml_dereftarget(s, v) aml_derefvalue(s, v, ACPI_IOWRITE) +#define aml_derefterm(s, v, m) aml_derefvalue(s, v, ACPI_IOREAD) #ifndef SMALL_KERNEL void @@ -893,10 +1335,8 @@ aml_showvalue(struct aml_value *val, int lvl) val->v_field.bitpos, val->v_field.bitlen, val->v_field.ref1, val->v_field.ref2, aml_mnem(val->v_field.type, NULL)); - if (val->v_field.ref1) - printf(" ref1: %s\n", aml_nodename(val->v_field.ref1->node)); - if (val->v_field.ref2) - printf(" ref2: %s\n", aml_nodename(val->v_field.ref2->node)); + aml_showvalue(val->v_field.ref1, lvl); + aml_showvalue(val->v_field.ref2, lvl); break; case AML_OBJTYPE_MUTEX: printf(" mutex: %s ref: %d\n", @@ -930,8 +1370,8 @@ aml_showvalue(struct aml_value *val, int lvl) val->v_powerrsrc.pwr_level, val->v_powerrsrc.pwr_order); break; case AML_OBJTYPE_OBJREF: - printf(" objref: %p index:%x opcode:%s\n", val->v_objref.ref, - val->v_objref.index, aml_mnem(val->v_objref.type, 0)); + printf(" objref: %p index:%x\n", val->v_objref.ref, + val->v_objref.index); aml_showvalue(val->v_objref.ref, lvl); break; default: @@ -940,6 +1380,101 @@ aml_showvalue(struct aml_value *val, int lvl) } #endif /* SMALL_KERNEL */ +/* Perform DeRef on value. If ACPI_IOREAD, will perform buffer/IO field read */ +struct aml_value * +aml_derefvalue(struct aml_scope *scope, struct aml_value *ref, int mode) +{ + struct aml_node *node; + struct aml_value *tmp; + int64_t tmpint; + int argc, index; + + for (;;) { + switch (ref->type) { + case AML_OBJTYPE_NAMEREF: + node = aml_searchname(scope->node, ref->v_nameref); + if (node == NULL || node->value == NULL) + return ref; + ref = node->value; + break; + + case AML_OBJTYPE_OBJREF: + index = ref->v_objref.index; + ref = aml_dereftarget(scope, ref->v_objref.ref); + if (index != -1) { + if (index >= ref->length) + aml_die("index.buf out of bounds: " + "%d/%d\n", index, ref->length); + switch (ref->type) { + case AML_OBJTYPE_PACKAGE: + ref = ref->v_package[index]; + break; + case AML_OBJTYPE_STATICINT: + case AML_OBJTYPE_INTEGER: + /* Convert to temporary buffer */ + if (ref->node) + aml_die("named integer index\n"); + tmpint = ref->v_integer; + _aml_setvalue(ref, AML_OBJTYPE_BUFFER, + aml_intlen>>3, &tmpint); + /* FALLTHROUGH */ + case AML_OBJTYPE_BUFFER: + case AML_OBJTYPE_STRING: + /* Return contents at this index */ + tmp = aml_alloctmp(scope, 1); + if (mode == ACPI_IOREAD) { + /* Shortcut: return integer + * contents of buffer at index */ + _aml_setvalue(tmp, + AML_OBJTYPE_INTEGER, + ref->v_buffer[index], NULL); + } else { + _aml_setvalue(tmp, + AML_OBJTYPE_BUFFERFIELD, + 0, NULL); + tmp->v_field.type = + AMLOP_CREATEBYTEFIELD; + tmp->v_field.bitpos = index * 8; + tmp->v_field.bitlen = 8; + tmp->v_field.ref1 = ref; + aml_addref(ref); + } + return tmp; + default: + aml_die("unknown index type: %d", ref->type); + break; + } + } + break; + + case AML_OBJTYPE_METHOD: + /* Read arguments from current scope */ + argc = AML_METHOD_ARGCOUNT(ref->v_method.flags); + tmp = aml_alloctmp(scope, argc+1); + for (index = 0; index < argc; index++) { + aml_parseop(scope, &tmp[index], 't'); + aml_addref(&tmp[index]); + } + ref = aml_evalmethod(scope, ref->node, argc, tmp, &tmp[argc]); + break; + + case AML_OBJTYPE_BUFFERFIELD: + case AML_OBJTYPE_FIELDUNIT: + if (mode == ACPI_IOREAD) { + /* Read I/O field into temporary storage */ + tmp = aml_alloctmp(scope, 1); + aml_fieldio(scope, ref, tmp, ACPI_IOREAD); + return tmp; + } + return ref; + + default: + return ref; + } + + } +} + int64_t aml_str2int(const char *str, int radix) { @@ -1077,6 +1612,132 @@ aml_copyvalue(struct aml_value *lhs, struct aml_value *rhs) } } +int is_local(struct aml_scope *, struct aml_value *); + +int +is_local(struct aml_scope *scope, struct aml_value *val) +{ + int idx; + + if (val->stack == 0 || scope->locals == NULL) + return (0); + + idx = val->stack - AMLOP_LOCAL0; + if (idx < 0 || idx >= AML_MAX_LOCAL) + aml_die("Invalid stack value!"); + + return (val == &scope->locals[idx]); +} + +/* Guts of the code: Assign one value to another. LHS may contain a previous value */ +void +aml_setvalue(struct aml_scope *scope, struct aml_value *lhs, + struct aml_value *rhs, int64_t ival) +{ + struct aml_value tmpint; + + /* Use integer as result */ + memset(&tmpint, 0, sizeof(tmpint)); + if (rhs == NULL) { + rhs = _aml_setvalue(&tmpint, AML_OBJTYPE_INTEGER, ival, NULL); + } + else if (rhs->type == AML_OBJTYPE_BUFFERFIELD || + rhs->type == AML_OBJTYPE_FIELDUNIT) + { + aml_fieldio(scope, rhs, &tmpint, ACPI_IOREAD); + rhs = &tmpint; + } + + if (!is_local(scope, lhs)) + lhs = aml_dereftarget(scope, lhs); + + if (is_local(scope, lhs)) { + /* ACPI: Overwrite writing to LocalX */ + aml_freevalue(lhs); + } + + switch (lhs->type) { + case AML_OBJTYPE_UNINITIALIZED: + aml_copyvalue(lhs, rhs); + break; + case AML_OBJTYPE_BUFFERFIELD: + case AML_OBJTYPE_FIELDUNIT: + aml_fieldio(scope, lhs, rhs, ACPI_IOWRITE); + break; + case AML_OBJTYPE_DEBUGOBJ: +#ifdef ACPI_DEBUG + printf("-- debug --\n"); + aml_showvalue(rhs, 50); +#endif + break; + case AML_OBJTYPE_STATICINT: + if (lhs->node) { + lhs->v_integer = aml_val2int(rhs); + } + break; + case AML_OBJTYPE_INTEGER: + lhs->v_integer = aml_val2int(rhs); + break; + case AML_OBJTYPE_BUFFER: + { + char *buf; + int len; + + if (lhs->node) + dnprintf(40, "named.buffer\n"); + + if (rhs->type == AML_OBJTYPE_BUFFER) { + buf = rhs->v_buffer; + len = rhs->length; + } else if (rhs->type == AML_OBJTYPE_INTEGER || + rhs->type == AML_OBJTYPE_STATICINT) { + buf = (char *)&rhs->v_integer; + len = sizeof(rhs->v_integer); + } else if (rhs->type == AML_OBJTYPE_STRING) { + len = rhs->length + 1; + buf = rhs->v_string; + } else { + /* aml_showvalue(rhs); */ + aml_die("setvalue.buf : %x", aml_pc(scope->pos)); + } + if (lhs->length < len) + len = lhs->length; + else + memset(lhs->v_buffer, 0, lhs->length); + memcpy(lhs->v_buffer, buf, len); + /* XXX ACPI v30b 17.2.5.7 says truncate string "before + copying", so make sure the string is terminated */ + if (rhs->type == AML_OBJTYPE_STRING) + lhs->v_buffer[lhs->length - 1] = '\0'; + break; + } + case AML_OBJTYPE_STRING: + if (lhs->node) + dnprintf(40, "named string\n"); + aml_freevalue(lhs); + if (rhs->type == AML_OBJTYPE_STRING) + _aml_setvalue(lhs, AML_OBJTYPE_STRING, rhs->length, + rhs->v_string); + else if (rhs->type == AML_OBJTYPE_BUFFER) + _aml_setvalue(lhs, AML_OBJTYPE_STRING, rhs->length, + rhs->v_buffer); + else if (rhs->type == AML_OBJTYPE_INTEGER || rhs->type == AML_OBJTYPE_STATICINT) { + _aml_setvalue(lhs, AML_OBJTYPE_STRING, 10, NULL); + snprintf(lhs->v_string, lhs->length, "%lld", + rhs->v_integer); + } else { + /* aml_showvalue(rhs); */ + aml_die("setvalue.str"); + } + break; + default: + /* XXX: */ + dnprintf(10, "setvalue.unknown: %x", lhs->type); + break; + } + aml_freevalue(&tmpint); +} + /* Allocate dynamic AML value * type : Type of object to allocate (AML_OBJTYPE_XXXX) * ival : Integer value (action depends on type) @@ -1302,7 +1963,7 @@ aml_evalexpr(int64_t lhs, int64_t rhs, int opcode) break; } - dnprintf(15,"aml_evalexpr: %s %llx %llx = %llx\n", + dnprintf(50,"aml_evalexpr: %s %llx %llx = %llx\n", aml_mnem(opcode, NULL), lhs, rhs, res); return res; @@ -1368,12 +2029,137 @@ aml_bufcpy(void *pvDst, int dstPos, const void *pvSrc, int srcPos, int len) aml_setbit(pDst, idx + dstPos, aml_tstbit(pSrc, idx + srcPos)); } +struct aml_value * +aml_callmethod(struct aml_scope *scope, struct aml_value *val) +{ + while (scope->pos < scope->end) + aml_parseterm(scope, val); + return val; +} + +/* + * Evaluate an AML method + * + * Returns a copy of the result in res (must be freed by user) + */ +struct aml_value * +aml_evalmethod(struct aml_scope *parent, struct aml_node *node, + int argc, struct aml_value *argv, struct aml_value *res) +{ + struct aml_scope *scope; + + scope = aml_pushscope(parent, node->value->v_method.start, + node->value->v_method.end, node); + scope->args = argv; + scope->nargs = argc; + + if (res == NULL) + res = aml_alloctmp(scope, 1); + +#ifdef ACPI_DEBUG + dnprintf(10, "calling [%s] (%d args)\n", + aml_nodename(node), scope->nargs); + for (argc = 0; argc < scope->nargs; argc++) { + dnprintf(10, " arg%d: ", argc); + aml_showvalue(&scope->args[argc], 10); + } + node->value->v_method.fneval(scope, res); + dnprintf(10, "[%s] returns: ", aml_nodename(node)); + aml_showvalue(res, 10); +#else + node->value->v_method.fneval(scope, res); +#endif + /* Free any temporary children nodes */ + aml_delchildren(node); + aml_popscope(scope); + + return res; +} + /* * @@@: External API * * evaluate an AML node * Returns a copy of the value in res (must be freed by user) */ +int +aml_evalnode(struct acpi_softc *sc, struct aml_node *node, + int argc, struct aml_value *argv, struct aml_value *res) +{ + static int lastck; + struct aml_node *ref; + + if (res) + memset(res, 0, sizeof(struct aml_value)); + if (node == NULL || node->value == NULL) + return (ACPI_E_BADVALUE); + + switch (node->value->type) { + case AML_OBJTYPE_METHOD: + aml_evalmethod(NULL, node, argc, argv, res); + if (acpi_nalloc > lastck) { + /* Check if our memory usage has increased */ + dnprintf(10, "Leaked: [%s] %d\n", + aml_nodename(node), acpi_nalloc); + lastck = acpi_nalloc; + } + break; + case AML_OBJTYPE_STATICINT: + case AML_OBJTYPE_INTEGER: + case AML_OBJTYPE_STRING: + case AML_OBJTYPE_BUFFER: + case AML_OBJTYPE_PACKAGE: + case AML_OBJTYPE_EVENT: + case AML_OBJTYPE_DEVICE: + case AML_OBJTYPE_MUTEX: + case AML_OBJTYPE_OPREGION: + case AML_OBJTYPE_POWERRSRC: + case AML_OBJTYPE_PROCESSOR: + case AML_OBJTYPE_THERMZONE: + case AML_OBJTYPE_DEBUGOBJ: + if (res) + aml_copyvalue(res, node->value); + break; + case AML_OBJTYPE_NAMEREF: + if (res == NULL) + break; + if ((ref = aml_searchname(node, node->value->v_nameref)) != NULL) + _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, ref); + else + aml_copyvalue(res, node->value); + break; + default: + break; + } + return (0); +} + +/* + * evaluate an AML name + * Returns a copy of the value in res (must be freed by user) + */ +int +aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name, + int argc, struct aml_value *argv, struct aml_value *res) +{ + return aml_evalnode(sc, aml_searchname(parent, name), argc, argv, res); +} + +int +aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent, + const char *name, int argc, struct aml_value *argv, int64_t *ival) +{ + struct aml_value res; + + if (name != NULL) + parent = aml_searchname(parent, name); + if (aml_evalnode(sc, parent, argc, argv, &res) == 0) { + *ival = aml_val2int(&res); + aml_freevalue(&res); + return 0; + } + return 1; +} void aml_walknodes(struct aml_node *node, int mode, @@ -1526,7 +2312,58 @@ aml_parseend(struct aml_scope *scope) /* * @@@: Opcode utility functions */ +int aml_match(int, int64_t, struct aml_value *); void aml_fixref(struct aml_value **); +int64_t aml_parseint(struct aml_scope *, int); +void aml_resize(struct aml_value *val, int newsize); + +void +aml_resize(struct aml_value *val, int newsize) +{ + void *oldptr; + int oldsize; + + if (val->length >= newsize) + return; + oldsize = val->length; + switch (val->type) { + case AML_OBJTYPE_BUFFER: + oldptr = val->v_buffer; + _aml_setvalue(val, val->type, newsize, NULL); + memcpy(val->v_buffer, oldptr, oldsize); + acpi_os_free(oldptr); + break; + case AML_OBJTYPE_STRING: + oldptr = val->v_string; + _aml_setvalue(val, val->type, newsize+1, NULL); + memcpy(val->v_string, oldptr, oldsize); + acpi_os_free(oldptr); + break; + } +} + + +int +aml_match(int op, int64_t mv1, struct aml_value *mv2) +{ + struct aml_value tmpint; + + memset(&tmpint, 0, sizeof(tmpint)); + _aml_setvalue(&tmpint, AML_OBJTYPE_INTEGER, mv1, NULL); + switch (op) { + case AML_MATCH_EQ: + return aml_cmpvalue(&tmpint, mv2, AMLOP_LEQUAL); + case AML_MATCH_LT: + return aml_cmpvalue(&tmpint, mv2, AMLOP_LLESS); + case AML_MATCH_LE: + return aml_cmpvalue(&tmpint, mv2, AMLOP_LLESSEQUAL); + case AML_MATCH_GE: + return aml_cmpvalue(&tmpint, mv2, AMLOP_LGREATEREQUAL); + case AML_MATCH_GT: + return aml_cmpvalue(&tmpint, mv2, AMLOP_LGREATER); + } + return (1); +} int amlop_delay; @@ -1574,12 +2411,899 @@ aml_fixref(struct aml_value **res) } } +int64_t +aml_parseint(struct aml_scope *scope, int opcode) +{ + uint8_t *np = scope->pos; + struct aml_value *tmpval; + int64_t rval; + + if (opcode == AML_ANYINT) + opcode = aml_parseopcode(scope); + switch (opcode) { + case AMLOP_ZERO: + rval = 0; + break; + case AMLOP_ONE: + rval = 1; + break; + case AMLOP_ONES: + rval = -1; + break; + case AMLOP_REVISION: + rval = AML_REVISION; + break; + case AMLOP_BYTEPREFIX: + np = scope->pos; + rval = *(uint8_t *)scope->pos; + scope->pos += 1; + break; + case AMLOP_WORDPREFIX: + np = scope->pos; + rval = aml_letohost16(*(uint16_t *)scope->pos); + scope->pos += 2; + break; + case AMLOP_DWORDPREFIX: + np = scope->pos; + rval = aml_letohost32(*(uint32_t *)scope->pos); + scope->pos += 4; + break; + case AMLOP_QWORDPREFIX: + np = scope->pos; + rval = aml_letohost64(*(uint64_t *)scope->pos); + scope->pos += 8; + break; + default: + scope->pos = np; + tmpval = aml_alloctmp(scope, 1); + aml_parseop(scope, tmpval, 'i'); + return aml_val2int(tmpval); + } + dnprintf(15, "%.4x: [%s] %s\n", aml_pc(scope->pos-opsize(opcode)), + aml_nodename(scope->node), aml_mnem(opcode, np)); + return rval; +} + +struct aml_value * +aml_evaltarget(struct aml_scope *scope, struct aml_value *res) +{ + return res; +} + +int +aml_evalterm(struct aml_scope *scope, struct aml_value *raw, + struct aml_value *dst) +{ + struct aml_value *deref; + + aml_freevalue(dst); + deref = aml_derefterm(scope, raw, 0); + aml_copyvalue(dst, deref); + return 0; +} + + /* * @@@: Opcode functions */ +/* Parse named objects */ +struct aml_value * +aml_parsenamed(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + uint8_t *name; + int s, offs = 0; + + AML_CHECKSTACK(); + name = aml_parsename(scope); + + res = aml_allocvalue(AML_OBJTYPE_UNINITIALIZED, 0, NULL); + switch (opcode) { + case AMLOP_NAME: + aml_parseop(scope, res, 't'); + break; + case AMLOP_ALIAS: + _aml_setvalue(res, AML_OBJTYPE_NAMEREF, 0, name); + name = aml_parsename(scope); + break; + case AMLOP_EVENT: + _aml_setvalue(res, AML_OBJTYPE_EVENT, 0, NULL); + break; + case AMLOP_MUTEX: + /* XXX mutex is unused since we don't have concurrency */ + _aml_setvalue(res, AML_OBJTYPE_MUTEX, 0, NULL); + res->v_mutex = (struct acpi_mutex *)acpi_os_malloc( + sizeof(struct acpi_mutex)); + res->v_mutex->amt_synclevel = aml_parseint(scope, + AMLOP_BYTEPREFIX); + s = strlen(aml_getname(name)); + if (s > 4) + offs = s - 4; + strlcpy(res->v_mutex->amt_name, aml_getname(name) + offs, + ACPI_MTX_MAXNAME); + rw_init(&res->v_mutex->amt_lock, res->v_mutex->amt_name); + break; + case AMLOP_OPREGION: + _aml_setvalue(res, AML_OBJTYPE_OPREGION, 0, NULL); + res->v_opregion.iospace = aml_parseint(scope, AMLOP_BYTEPREFIX); + res->v_opregion.iobase = aml_parseint(scope, AML_ANYINT); + res->v_opregion.iolen = aml_parseint(scope, AML_ANYINT); + if (res->v_opregion.iospace == GAS_PCI_CFG_SPACE) { + res->v_opregion.iobase += aml_getpciaddr(dsdt_softc, + scope->node); + dnprintf(20, "got ioaddr: %s.%s:%llx\n", + aml_nodename(scope->node), aml_getname(name), + res->v_opregion.iobase); + } + break; + } + aml_createname(scope->node, name, res); + + return res; +} + +/* Parse Named objects with scope */ +struct aml_value * +aml_parsenamedscope(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + uint8_t *end, *name; + struct aml_node *node; + + AML_CHECKSTACK(); + end = aml_parseend(scope); + name = aml_parsename(scope); + + switch (opcode) { + case AMLOP_DEVICE: + res = aml_allocvalue(AML_OBJTYPE_DEVICE, 0, NULL); + break; + case AMLOP_SCOPE: + res = NULL; + break; + case AMLOP_PROCESSOR: + res = aml_allocvalue(AML_OBJTYPE_PROCESSOR, 0, NULL); + res->v_processor.proc_id = aml_parseint(scope, AMLOP_BYTEPREFIX); + res->v_processor.proc_addr = aml_parseint(scope, AMLOP_DWORDPREFIX); + res->v_processor.proc_len = aml_parseint(scope, AMLOP_BYTEPREFIX); + break; + case AMLOP_POWERRSRC: + res = aml_allocvalue(AML_OBJTYPE_POWERRSRC, 0, NULL); + res->v_powerrsrc.pwr_level = aml_parseint(scope, AMLOP_BYTEPREFIX); + res->v_powerrsrc.pwr_order = aml_parseint(scope, AMLOP_BYTEPREFIX); + break; + case AMLOP_THERMALZONE: + res = aml_allocvalue(AML_OBJTYPE_THERMZONE, 0, NULL); + break; + } + node = aml_createname(scope->node, name, res); + aml_parsenode(scope, node, scope->pos, &end, NULL); + scope->pos = end; + + return res; +} + +/* Parse math opcodes */ +struct aml_value * +aml_parsemath(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmparg; + int64_t i1, i2, i3; + + tmparg = aml_alloctmp(scope, 1); + AML_CHECKSTACK(); + switch (opcode) { + case AMLOP_LNOT: + i2 = 0; + i1 = aml_parseint(scope, AML_ANYINT); + break; + case AMLOP_LAND: + case AMLOP_LOR: + i1 = aml_parseint(scope, AML_ANYINT); + i2 = aml_parseint(scope, AML_ANYINT); + break; + case AMLOP_NOT: + case AMLOP_TOBCD: + case AMLOP_FROMBCD: + case AMLOP_TOINTEGER: + case AMLOP_FINDSETLEFTBIT: + case AMLOP_FINDSETRIGHTBIT: + i2 = 0; + i1 = aml_parseint(scope, AML_ANYINT); + aml_parsetarget(scope, tmparg, NULL); + break; + case AMLOP_INCREMENT: + case AMLOP_DECREMENT: + aml_parsetarget(scope, tmparg, NULL); + i1 = aml_val2int(aml_derefterm(scope, tmparg, 0)); + i2 = 1; + break; + case AMLOP_DIVIDE: + i1 = aml_parseint(scope, AML_ANYINT); + i2 = aml_parseint(scope, AML_ANYINT); + + aml_parsetarget(scope, tmparg, NULL); // remainder + aml_setvalue(scope, tmparg, NULL, (i1 % i2)); + + aml_parsetarget(scope, tmparg, NULL); // quotient + break; + default: + i1 = aml_parseint(scope, AML_ANYINT); + i2 = aml_parseint(scope, AML_ANYINT); + aml_parsetarget(scope, tmparg, NULL); + break; + } + i3 = aml_evalexpr(i1, i2, opcode); + aml_setvalue(scope, res, NULL, i3); + aml_setvalue(scope, tmparg, NULL, i3); + return (res); +} + +/* Parse logical comparison opcodes */ +struct aml_value * +aml_parsecompare(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmparg; + int rc; + + AML_CHECKSTACK(); + tmparg = aml_alloctmp(scope, 2); + aml_parseterm(scope, &tmparg[AML_LHS]); + aml_parseterm(scope, &tmparg[AML_RHS]); + + /* Compare both values */ + rc = aml_cmpvalue(&tmparg[AML_LHS], &tmparg[AML_RHS], opcode); + aml_setvalue(scope, res, NULL, rc); + + return res; +} + +/* Parse IF/ELSE opcodes */ +struct aml_value * +aml_parseif(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + int64_t test; + uint8_t *end; + + AML_CHECKSTACK(); + end = aml_parseend(scope); + test = aml_parseint(scope, AML_ANYINT); + + dnprintf(40, "@ iftest: %llx\n", test); + while (test && scope->pos < end) { + /* Parse if scope */ + aml_parseterm(scope, res); + } + if (scope->pos >= scope->end) + return res; + + if (*end == AMLOP_ELSE) { + scope->pos = ++end; + end = aml_parseend(scope); + while (!test && scope->pos < end) { + /* Parse ELSE scope */ + aml_parseterm(scope, res); + } + } + if (scope->pos < end) + scope->pos = end; + return res; +} + +struct aml_value * +aml_parsewhile(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + uint8_t *end, *start; + int test, cnt; + + AML_CHECKSTACK(); + end = aml_parseend(scope); + start = scope->pos; + cnt = 0; + do { + test = 1; + if (scope->pos == start || scope->pos == end) { + scope->pos = start; + test = aml_parseint(scope, AML_ANYINT); + dnprintf(40, "@whiletest = %d %x\n", test, cnt++); + } else if (*scope->pos == AMLOP_BREAK) { + scope->pos++; + test = 0; + } else if (*scope->pos == AMLOP_CONTINUE) { + scope->pos = start; + } else { + aml_parseterm(scope, res); + } + } while (test && scope->pos <= end && cnt < 0x199); + /* XXX: shouldn't need breakout counter */ + + dnprintf(40, "Set While end : %x\n", cnt); + if (scope->pos < end) + scope->pos = end; + return res; +} + +/* Parse Buffer/Package opcodes */ +struct aml_value * +aml_parsebufpkg(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + uint8_t *end; + int len; + + AML_CHECKSTACK(); + end = aml_parseend(scope); + len = aml_parseint(scope, (opcode == AMLOP_PACKAGE) ? + AMLOP_BYTEPREFIX : AML_ANYINT); + + switch (opcode) { + case AMLOP_BUFFER: + _aml_setvalue(res, AML_OBJTYPE_BUFFER, len, NULL); + if (scope->pos < end) { + memcpy(res->v_buffer, scope->pos, end-scope->pos); + } + if (len != end-scope->pos) { + dnprintf(99, "buffer: %.4x %.4x\n", len, end-scope->pos); + } + break; + case AMLOP_PACKAGE: + case AMLOP_VARPACKAGE: + _aml_setvalue(res, AML_OBJTYPE_PACKAGE, len, NULL); + for (len = 0; len < res->length && scope->pos < end; len++) { + aml_parseop(scope, res->v_package[len], 't'); + } + if (scope->pos != end) { + dnprintf(99, "Package not equiv!! %.4x %.4x %d of %d\n", + aml_pc(scope->pos), aml_pc(end), len, res->length); + } + break; + } + scope->pos = end; + return res; +} + +struct aml_value * +aml_parsemethod(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + uint8_t *end, *name; + + AML_CHECKSTACK(); + end = aml_parseend(scope); + name = aml_parsename(scope); + + res = aml_allocvalue(AML_OBJTYPE_METHOD, 0, NULL); + res->v_method.flags = aml_parseint(scope, AMLOP_BYTEPREFIX); + res->v_method.start = scope->pos; + res->v_method.end = end; + res->v_method.fneval = aml_callmethod; + aml_createname(scope->node, name, res); + + scope->pos = end; + + return res; +} + +/* Parse simple type opcodes */ +struct aml_value * +aml_parsesimple(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_node *node; + + AML_CHECKSTACK(); + switch (opcode) { + case AMLOP_ZERO: + _aml_setvalue(res, AML_OBJTYPE_INTEGER+AML_STATIC, + aml_parseint(scope, opcode), NULL); + break; + case AMLOP_ONE: + case AMLOP_ONES: + case AMLOP_BYTEPREFIX: + case AMLOP_WORDPREFIX: + case AMLOP_DWORDPREFIX: + case AMLOP_QWORDPREFIX: + case AMLOP_REVISION: + _aml_setvalue(res, AML_OBJTYPE_INTEGER, + aml_parseint(scope, opcode), NULL); + break; + case AMLOP_DEBUG: + _aml_setvalue(res, AML_OBJTYPE_DEBUGOBJ, 0, NULL); + break; + case AMLOP_STRINGPREFIX: + _aml_setvalue(res, AML_OBJTYPE_STRING, -1, scope->pos); + scope->pos += res->length+1; + break; + case AMLOP_NAMECHAR: + _aml_setvalue(res, AML_OBJTYPE_NAMEREF, 0, NULL); + res->v_nameref = aml_parsename(scope); + node = aml_searchname(scope->node, res->v_nameref); + if (node && node->value) + _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, node->value); + break; + } + return res; +} + +/* Parse field unit opcodes */ +struct aml_value * +aml_parsefieldunit(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + uint8_t *end, *name; + struct aml_value *fld; + + AML_CHECKSTACK(); + end = aml_parseend(scope); + + switch (opcode) { + case AMLOP_FIELD: + aml_parsetarget(scope, NULL, &res->v_field.ref1); + break; + case AMLOP_INDEXFIELD: + aml_parsetarget(scope, NULL, &res->v_field.ref1); + aml_parsetarget(scope, NULL, &res->v_field.ref2); + break; + case AMLOP_BANKFIELD: + aml_parsetarget(scope, NULL, &res->v_field.ref1); + aml_parsetarget(scope, NULL, &res->v_field.ref2); + res->v_field.ref3 = aml_parseint(scope, AML_ANYINT); + break; + } + res->v_field.flags = aml_parseint(scope, AMLOP_BYTEPREFIX); + res->v_field.type = opcode; + + aml_fixref(&res->v_field.ref1); + aml_fixref(&res->v_field.ref2); + + while (scope->pos < end) { + switch (*scope->pos) { + case 0x00: // reserved + scope->pos++; + res->v_field.bitlen = aml_parselength(scope); + break; + case 0x01: // attrib + scope->pos++; + /* XXX: do something with this */ + aml_parseint(scope, AMLOP_BYTEPREFIX); + aml_parseint(scope, AMLOP_BYTEPREFIX); + res->v_field.bitlen = 0; + break; + default: + name = aml_parsename(scope); + res->v_field.bitlen = aml_parselength(scope); + + /* Allocate new fieldunit */ + fld = aml_allocvalue(AML_OBJTYPE_FIELDUNIT, 0, NULL); + + /* Increase reference count on field */ + fld->v_field = res->v_field; + aml_addref(fld->v_field.ref1); + aml_addref(fld->v_field.ref2); + + aml_createname(scope->node, name, fld); + break; + } + res->v_field.bitpos += res->v_field.bitlen; + } + /* Delete redundant reference */ + aml_delref(&res->v_field.ref1); + aml_delref(&res->v_field.ref2); + return res; +} + +/* Parse CreateXXXField opcodes */ +struct aml_value * +aml_parsebufferfield(struct aml_scope *scope, int opcode, + struct aml_value *res) +{ + uint8_t *name; + + AML_CHECKSTACK(); + res = aml_allocvalue(AML_OBJTYPE_BUFFERFIELD, 0, NULL); + res->v_field.type = opcode; + aml_parsetarget(scope, NULL, &res->v_field.ref1); + res->v_field.bitpos = aml_parseint(scope, AML_ANYINT); + + aml_fixref(&res->v_field.ref1); + + switch (opcode) { + case AMLOP_CREATEFIELD: + res->v_field.bitlen = aml_parseint(scope, AML_ANYINT); + break; + case AMLOP_CREATEBITFIELD: + res->v_field.bitlen = 1; + break; + case AMLOP_CREATEBYTEFIELD: + res->v_field.bitlen = 8; + res->v_field.bitpos *= 8; + break; + case AMLOP_CREATEWORDFIELD: + res->v_field.bitlen = 16; + res->v_field.bitpos *= 8; + break; + case AMLOP_CREATEDWORDFIELD: + res->v_field.bitlen = 32; + res->v_field.bitpos *= 8; + break; + case AMLOP_CREATEQWORDFIELD: + res->v_field.bitlen = 64; + res->v_field.bitpos *= 8; + break; + } + name = aml_parsename(scope); + aml_createname(scope->node, name, res); + + return res; +} + +/* Parse Mutex/Event action */ +struct aml_value * +aml_parsemuxaction(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmparg; + int64_t i1; + int rv; + + AML_CHECKSTACK(); + + tmparg = aml_alloctmp(scope, 1); + aml_parsetarget(scope, tmparg, NULL); + switch (opcode) { + case AMLOP_ACQUIRE: + /* Assert: tmparg is AML_OBJTYPE_MUTEX */ + i1 = aml_parseint(scope, AMLOP_WORDPREFIX); + rv = acpi_mutex_acquire(tmparg->v_objref.ref, i1); + /* Return true if timed out */ + aml_setvalue(scope, res, NULL, rv); + break; + case AMLOP_RELEASE: + acpi_mutex_release(tmparg->v_objref.ref); + break; + + case AMLOP_WAIT: + /* Assert: tmparg is AML_OBJTYPE_EVENT */ + i1 = aml_parseint(scope, AML_ANYINT); + + /* Return true if timed out */ + aml_setvalue(scope, res, NULL, 0); + break; + case AMLOP_SIGNAL: + break; + case AMLOP_RESET: + break; + } + + return res; +} + +/* Parse Miscellaneous opcodes */ +struct aml_value * +aml_parsemisc2(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmparg, *dev; + int i1, i2, i3; + + AML_CHECKSTACK(); + + switch (opcode) { + case AMLOP_NOTIFY: + /* Assert: tmparg is nameref or objref */ + tmparg = aml_alloctmp(scope, 1); + aml_parseop(scope, tmparg, 'r'); + dev = aml_dereftarget(scope, tmparg); + + i1 = aml_parseint(scope, AML_ANYINT); + if (dev && dev->node) { + dnprintf(10, "Notify: [%s] %.2x\n", + aml_nodename(dev->node), i1); + aml_notify(dev->node, i1); + } + break; + case AMLOP_SLEEP: + i1 = aml_parseint(scope, AML_ANYINT); + dnprintf(50, "SLEEP: %x\n", i1); + if (i1) + acpi_sleep(i1); + else { + dnprintf(10, "acpi_sleep(0)\n"); + } + break; + case AMLOP_STALL: + i1 = aml_parseint(scope, AML_ANYINT); + dnprintf(50, "STALL: %x\n", i1); + if (i1) + acpi_stall(i1); + else { + dnprintf(10, "acpi_stall(0)\n"); + } + break; + case AMLOP_FATAL: + i1 = aml_parseint(scope, AMLOP_BYTEPREFIX); + i2 = aml_parseint(scope, AMLOP_DWORDPREFIX); + i3 = aml_parseint(scope, AML_ANYINT); + aml_die("FATAL: %x %x %x\n", i1, i2, i3); + break; + } + return res; +} + +/* Parse Miscellaneous opcodes */ +struct aml_value * +aml_parsemisc3(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmparg; + + AML_CHECKSTACK(); + tmparg = aml_alloctmp(scope, 1); + aml_parseterm(scope, tmparg); + switch (opcode) { + case AMLOP_SIZEOF: + aml_setvalue(scope, res, NULL, tmparg->length); + break; + case AMLOP_OBJECTTYPE: + aml_setvalue(scope, res, NULL, tmparg->type); + break; + } + + return res; +} + +/* Parse AMLOP_MATCH */ +struct aml_value * +aml_parsematch(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *pkg; + int op1, op2, idx, mv1, mv2; + + AML_CHECKSTACK(); + pkg = aml_parseterm(scope, NULL); + op1 = aml_parseint(scope, AMLOP_BYTEPREFIX); + mv1 = aml_parseint(scope, AML_ANYINT); + op2 = aml_parseint(scope, AMLOP_BYTEPREFIX); + mv2 = aml_parseint(scope, AML_ANYINT); + idx = aml_parseint(scope, AML_ANYINT); + + aml_setvalue(scope, res, NULL, -1); + while (idx < pkg->length) { + if (aml_match(op1, mv1, pkg->v_package[idx]) || + aml_match(op2, mv2, pkg->v_package[idx])) { + aml_setvalue(scope, res, NULL, idx); + break; + } + idx++; + } + aml_delref(&pkg); + return res; +} + +/* Parse referenced objects */ +struct aml_value * +aml_parseref(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmparg; + + AML_CHECKSTACK(); + + switch (opcode) { + case AMLOP_INDEX: + tmparg = aml_alloctmp(scope, 1); + _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, NULL); + aml_parsetarget(scope, tmparg, NULL); + + res->v_objref.index = aml_parseint(scope, AML_ANYINT); + res->v_objref.ref = aml_dereftarget(scope, tmparg); + + aml_parsetarget(scope, tmparg, NULL); + aml_setvalue(scope, tmparg, res, 0); + break; + case AMLOP_DEREFOF: + aml_parseop(scope, res, 't'); + break; + case AMLOP_RETURN: + tmparg = aml_alloctmp(scope, 1); + aml_parseterm(scope, tmparg); + aml_setvalue(scope, res, tmparg, 0); + scope->pos = scope->end; + break; + case AMLOP_ARG0: + case AMLOP_ARG1: + case AMLOP_ARG2: + case AMLOP_ARG3: + case AMLOP_ARG4: + case AMLOP_ARG5: + case AMLOP_ARG6: + opcode -= AMLOP_ARG0; + if (scope->args == NULL || opcode >= scope->nargs) + aml_die("arg %d out of range", opcode); + + /* Create OBJREF to stack variable */ + _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, + &scope->args[opcode]); + break; + case AMLOP_LOCAL0: + case AMLOP_LOCAL1: + case AMLOP_LOCAL2: + case AMLOP_LOCAL3: + case AMLOP_LOCAL4: + case AMLOP_LOCAL5: + case AMLOP_LOCAL6: + case AMLOP_LOCAL7: + opcode -= AMLOP_LOCAL0; + + /* No locals exist.. lazy allocate */ + if (scope->locals == NULL) { + dnprintf(10, "Lazy alloc locals\n"); + scope->locals = aml_alloctmp(scope, AML_MAX_LOCAL); + } + + /* Create OBJREF to stack variable */ + _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, + &scope->locals[opcode]); + res->v_objref.ref->stack = opcode+AMLOP_LOCAL0; + break; + case AMLOP_LOAD: + tmparg = aml_alloctmp(scope, 2); + aml_parseop(scope, &tmparg[0], 't'); + aml_parseop(scope, &tmparg[1], 't'); + break; + case AMLOP_STORE: + tmparg = aml_alloctmp(scope, 1); + aml_parseterm(scope, res); + aml_parsetarget(scope, tmparg, NULL); + + while (tmparg->type == AML_OBJTYPE_OBJREF) { + if (tmparg->v_objref.index != -1) + break; + tmparg = tmparg->v_objref.ref; + } + aml_setvalue(scope, tmparg, res, 0); + break; + case AMLOP_REFOF: + _aml_setvalue(res, AML_OBJTYPE_OBJREF, -1, NULL); + aml_parsetarget(scope, NULL, &res->v_objref.ref); + break; + case AMLOP_CONDREFOF: + /* Returns true if object exists */ + tmparg = aml_alloctmp(scope, 2); + aml_parsetarget(scope, &tmparg[0], NULL); + aml_parsetarget(scope, &tmparg[1], NULL); + if (tmparg[0].type != AML_OBJTYPE_NAMEREF) { + /* Object exists */ + aml_freevalue(&tmparg[1]); + aml_setvalue(scope, &tmparg[1], &tmparg[0], 0); + aml_setvalue(scope, res, NULL, 1); + } else { + /* Object doesn't exist */ + aml_setvalue(scope, res, NULL, 0); + } + break; + } + + return res; +} + +struct aml_value * +aml_parsestring(struct aml_scope *scope, int opcode, struct aml_value *res) +{ + struct aml_value *tmpval; + int i1, i2; + + AML_CHECKSTACK(); + switch (opcode) { + case AMLOP_CONCAT: + tmpval = aml_alloctmp(scope, 4); + aml_parseterm(scope, &tmpval[AML_LHS]); + aml_parseterm(scope, &tmpval[AML_RHS]); + aml_parsetarget(scope, &tmpval[AML_DST], NULL); + if (tmpval[AML_LHS].type == AML_OBJTYPE_BUFFER && + tmpval[AML_RHS].type == AML_OBJTYPE_BUFFER) { + aml_resize(&tmpval[AML_LHS], + tmpval[AML_LHS].length+tmpval[AML_RHS].length); + memcpy(tmpval[AML_LHS].v_buffer+tmpval[AML_LHS].length, + tmpval[AML_RHS].v_buffer, tmpval[AML_RHS].length); + aml_setvalue(scope, &tmpval[AML_DST], &tmpval[AML_LHS], 0); + } else if (tmpval[AML_LHS].type == AML_OBJTYPE_STRING && + tmpval[AML_RHS].type == AML_OBJTYPE_STRING) { + aml_resize(&tmpval[AML_LHS], + tmpval[AML_LHS].length+tmpval[AML_RHS].length); + memcpy(tmpval[AML_LHS].v_string+tmpval[AML_LHS].length, + tmpval[AML_RHS].v_buffer, tmpval[AML_RHS].length); + aml_setvalue(scope, &tmpval[AML_DST], &tmpval[AML_LHS], 0); + } else { + aml_die("concat"); + } + break; + case AMLOP_MID: + tmpval = aml_alloctmp(scope, 2); + aml_parseterm(scope, &tmpval[0]); + i1 = aml_parseint(scope, AML_ANYINT); // start + i2 = aml_parseint(scope, AML_ANYINT); // length + aml_parsetarget(scope, &tmpval[1], NULL); + if (i1 > tmpval[0].length) + i1 = tmpval[0].length; + if (i1+i2 > tmpval[0].length) + i2 = tmpval[0].length-i1; + _aml_setvalue(res, AML_OBJTYPE_STRING, i2, tmpval[0].v_string+i1); + break; + case AMLOP_TODECSTRING: + case AMLOP_TOHEXSTRING: + i1 = aml_parseint(scope, AML_ANYINT); + _aml_setvalue(res, AML_OBJTYPE_STRING, 20, NULL); + snprintf(res->v_string, res->length, + ((opcode == AMLOP_TODECSTRING) ? "%d" : "%x"), i1); + break; + default: + aml_die("to_string"); + break; + } + + return res; +} + +struct aml_value * +aml_parseterm(struct aml_scope *scope, struct aml_value *res) +{ + struct aml_value *tmpres; + + /* If no value specified, allocate dynamic */ + if (res == NULL) + res = aml_allocvalue(AML_OBJTYPE_UNINITIALIZED, 0, NULL); + tmpres = aml_alloctmp(scope, 1); + aml_parseop(scope, tmpres, 't'); + aml_evalterm(scope, tmpres, res); + return res; +} + +struct aml_value * +aml_parsetarget(struct aml_scope *scope, struct aml_value *res, + struct aml_value **opt) +{ + struct aml_value *dummy; + + /* If no value specified, allocate dynamic */ + if (res == NULL) + res = aml_allocvalue(AML_OBJTYPE_UNINITIALIZED, 0, NULL); + aml_parseop(scope, res, 'r'); + if (opt == NULL) + opt = &dummy; + + *opt = aml_evaltarget(scope, res); + + return res; +} + int odp; +/* Main Opcode Parser/Evaluator */ +struct aml_value * +aml_parseop(struct aml_scope *scope, struct aml_value *res, int ctype) +{ + int opcode; + struct aml_opcode *htab; + struct aml_value *rv = NULL; + + if (odp++ > 25) + panic("depth"); + + aml_freevalue(res); + opcode = aml_parseopcode(scope); + dnprintf(15, "%.4x: [%s] %s\n", aml_pc(scope->pos-opsize(opcode)), + aml_nodename(scope->node), aml_mnem(opcode, scope->pos)); + delay(amlop_delay); + + htab = aml_findopcode(opcode); + if (htab && htab->handler) { + rv = htab->handler(scope, opcode, res); + } else { + /* No opcode handler */ + aml_die("Unknown opcode: %.4x @ %.4x", opcode, + aml_pc(scope->pos - opsize(opcode))); + } + if (ctype == 'i' && res->type != AML_OBJTYPE_INTEGER) { + rv = aml_derefterm(scope, res, 0); + aml_freevalue(res); + aml_copyvalue(res, rv); + } + odp--; + return rv; +} + const char hext[] = "0123456789ABCDEF"; const char * @@ -1677,16 +3401,23 @@ char *aml_valid_osi[] = { struct aml_value * aml_callosi(struct aml_scope *scope, struct aml_value *val) { - int idx, result=0; - struct aml_value *fa; + struct aml_value tmpstr, *arg; + int idx, result; + + /* Perform comparison with valid strings */ + result = 0; + memset(&tmpstr, 0, sizeof(tmpstr)); + tmpstr.type = AML_OBJTYPE_STRING; + arg = aml_derefvalue(scope, &scope->args[0], ACPI_IOREAD); - fa = scope->args[0].v_objref.ref; for (idx=0; !result && aml_valid_osi[idx] != NULL; idx++) { - dnprintf(10,"osi: %s,%s\n", fa->v_string, aml_valid_osi[idx]); - result = !strcmp(fa->v_string, aml_valid_osi[idx]); + tmpstr.v_string = aml_valid_osi[idx]; + tmpstr.length = strlen(tmpstr.v_string); + + result = aml_cmpvalue(arg, &tmpstr, AMLOP_LEQUAL); } - dnprintf(10,"@@ OSI found: %x\n", result); - return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL); + aml_setvalue(scope, val, NULL, result); + return val; } void @@ -1700,10 +3431,6 @@ aml_create_defaultobjects() osstring[15] = 'w'; osstring[18] = 'N'; - strlcpy(aml_root.name, "\\", sizeof(aml_root.name)); - aml_root.value = aml_allocvalue(0, 0, NULL); - aml_root.value->node = &aml_root; - for (def = aml_defobj; def->name; def++) { /* Allocate object value + add to namespace */ tmp = aml_allocvalue(def->type, def->ival, def->bval); @@ -1827,7 +3554,6 @@ aml_foreachpkg(struct aml_value *pkg, int start, fn(pkg->v_package[idx], arg); } -#if 0 int acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length) { @@ -1846,7 +3572,6 @@ acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length) return (0); } -#endif /* * Walk nodes and perform fixups for nameref @@ -1919,2607 +3644,3 @@ aml_val_to_string(const struct aml_value *val) return (buffer); } - -/* - * XXX: NEW PARSER CODE GOES HERE - */ -struct aml_value *aml_xeval(struct aml_scope *, struct aml_value *, int, int, - struct aml_value *); -struct aml_value *aml_xparsesimple(struct aml_scope *, char, - struct aml_value *); -struct aml_value *aml_xparse(struct aml_scope *, int, const char *); - -struct aml_scope *aml_xfindscope(struct aml_scope *, int, int); -struct aml_scope *aml_xpushscope(struct aml_scope *, struct aml_value *, - struct aml_node *, int); -struct aml_scope *aml_xpopscope(struct aml_scope *); - -void aml_showstack(struct aml_scope *); -void aml_xaddref(struct aml_value *, const char *); -void aml_xdelref(struct aml_value **, const char *); -void aml_xconvert(struct aml_value *, struct aml_value **, int, int); -int64_t aml_hextoint(const char *); - -int aml_xmatchtest(int64_t, int64_t, int); -int aml_xmatch(struct aml_value *, int, int, int, int, int); - -int aml_xcompare(struct aml_value *, struct aml_value *, int); -void aml_xconcat(struct aml_value *, struct aml_value *, - struct aml_value **); -void aml_xconcatres(struct aml_value *, struct aml_value *, - struct aml_value **); -int aml_ccrlen(union acpi_resource *, void *); -void aml_xmid(struct aml_value *, int, int, struct aml_value **); - -void aml_xstore(struct aml_scope *, struct aml_value *, int64_t, - struct aml_value *); - -int -valid_acpihdr(void *buf, int len, const char *sig) -{ - struct acpi_table_header *hdr = buf; - - if (sig && strncmp(hdr->signature, sig, 4)) { - return 0; - } - if (len < hdr->length) { - return 0; - } - if (acpi_checksum(hdr, hdr->length) != 0) { - return 0; - } - return 1; -} - -/* - * Reference Count functions - */ -void -aml_xaddref(struct aml_value *val, const char *lbl) -{ - if (val == NULL) - return; - dnprintf(50, "XAddRef: %p %s:[%s] %d\n", - val, lbl, - val->node ? aml_nodename(val->node) : "INTERNAL", - val->refcnt); - val->refcnt++; -} - -/* Decrease reference counter */ -void -aml_xdelref(struct aml_value **pv, const char *lbl) -{ - struct aml_value *val; - - if (pv == NULL || *pv == NULL) - return; - val = *pv; - val->refcnt--; - if (val->refcnt == 0) { - dnprintf(50, "XDelRef: %p %s %2d [%s] %s\n", - val, lbl, - val->refcnt, - val->node ? aml_nodename(val->node) : "INTERNAL", - val->refcnt ? "" : "---------------- FREEING"); - - aml_freevalue(val); - acpi_os_free(val); - *pv = NULL; - } -} - -/* Walk list of parent scopes until we find one of 'type' - * If endscope is set, mark all intermediate scopes as invalid (used for Method/While) */ -struct aml_scope * -aml_xfindscope(struct aml_scope *scope, int type, int endscope) -{ - while (scope) { - if (endscope) - scope->pos = NULL; - if (scope->type == type) - break; - scope = scope->parent; - } - return scope; -} - -#ifdef ACPI_DEBUG -/* Dump AML Stack */ -void -aml_showstack(struct aml_scope *scope) -{ - int idx; - - dnprintf(10, "===== Stack %s:%s\n", aml_nodename(scope->node), - aml_mnem(scope->type, 0)); - scope = aml_xfindscope(scope, AMLOP_METHOD, 0); - if (scope == NULL) - return; - for (idx=0; scope->args && idx<7; idx++) { - if (scope->args[idx].type) { - dnprintf(10," Arg%d: ", idx); - aml_showvalue(scope->args[idx].v_objref.ref, 10); - } - } - for (idx=0; scope->locals && idx<8; idx++) { - if (scope->locals[idx].type) { - dnprintf(10," Local%d: ", idx); - aml_showvalue(&scope->locals[idx], 10); - } - } -} -#endif - -/* Create a new scope object */ -struct aml_scope * -aml_xpushscope(struct aml_scope *parent, struct aml_value *range, - struct aml_node *node, int type) -{ - struct aml_scope *scope; - uint8_t *start, *end; - - if (range->type == AML_OBJTYPE_METHOD) { - start = range->v_method.start; - end = range->v_method.end; - } - else { - start = range->v_buffer; - end = start + range->length; - if (start == end) { - return NULL; - } - } - scope = acpi_os_malloc(sizeof(struct aml_scope)); - if (scope == NULL) - return NULL; - - scope->node = node; - scope->start = start; - scope->end = end; - scope->pos = scope->start; - scope->parent = parent; - scope->type = type; - scope->sc = dsdt_softc; - - aml_lastscope = scope; - - return scope; -} - -/* Free a scope object and any children */ -struct aml_scope * -aml_xpopscope(struct aml_scope *scope) -{ - struct aml_scope *nscope; - int idx; - - if (scope == NULL) - return NULL; - - nscope = scope->parent; - - if (scope->type == AMLOP_METHOD) { - aml_delchildren(scope->node); - } - if (scope->locals) { - for (idx=0; idx<8; idx++) { - aml_freevalue(&scope->locals[idx]); - } - acpi_os_free(scope->locals); - scope->locals = NULL; - } - if (scope->args) { - for (idx=0; idx<7; idx++) { - aml_freevalue(&scope->args[idx]); - } - acpi_os_free(scope->args); - scope->args = NULL; - } - acpi_os_free(scope); - aml_lastscope = nscope; - - return nscope; -} - -/* Test AMLOP_MATCH codes */ -int -aml_xmatchtest(int64_t a, int64_t b, int op) -{ - switch (op) { - case AML_MATCH_TR: - return (1); - case AML_MATCH_EQ: - return (a == b); - case AML_MATCH_LT: - return (a < b); - case AML_MATCH_LE: - return (a <= b); - case AML_MATCH_GE: - return (a >= b); - case AML_MATCH_GT: - return (a > b); - } - return 0; -} - -/* Search a package for a matching value */ -int -aml_xmatch(struct aml_value *pkg, int index, - int op1, int v1, - int op2, int v2) -{ - struct aml_value *tmp; - int flag; - - while (index < pkg->length) { - /* Convert package value to integer */ - aml_xconvert(pkg->v_package[index], &tmp, - AML_OBJTYPE_INTEGER, 0); - - /* Perform test */ - flag = aml_xmatchtest(tmp->v_integer, v1, op1) && - aml_xmatchtest(tmp->v_integer, v2, op2); - aml_xdelref(&tmp, "xmatch"); - - if (flag) - return index; - index++; - } - return -1; -} - -/* - * Namespace functions - */ -void ns_xdis(struct aml_node *node, int n, uint8_t *pos, void *arg); -void ns_xcreate(struct aml_node *node, int n, uint8_t *pos, void *arg); -void ns_xsearch(struct aml_node *node, int n, uint8_t *pos, void *arg); -uint8_t *aml_xparsename(uint8_t *pos, struct aml_node *node, - void (*fn)(struct aml_node *, int, uint8_t *, void *), void *arg); - -/* Search for name in namespace */ -void -ns_xsearch(struct aml_node *node, int n, uint8_t *pos, void *arg) -{ - struct aml_value **rv = arg; - struct aml_node *rnode; - - /* If name search is relative, check up parent nodes */ - for (rnode=node; n == 1 && rnode; rnode=rnode->parent) { - if (__aml_search(rnode, pos, 0) != NULL) { - break; - } - } - while (n--) { - rnode = __aml_search(rnode, pos, 0); - pos += 4; - } - if (rnode != NULL) { - *rv = rnode->value; - return; - } - *rv = NULL; -} - -/* Create name in namespace */ -void -ns_xcreate(struct aml_node *node, int n, uint8_t *pos, void *arg) -{ - struct aml_value **rv = arg; - - while (n--) { - node = __aml_search(node, pos, 1); - pos += 4; - } - *rv = node->value; -} - -void -ns_xdis(struct aml_node *node, int n, uint8_t *pos, void *arg) -{ - printf(aml_nodename(node)); - while (n--) { - printf("%s%c%c%c%c", n ? "." : "", - pos[0], pos[1], pos[2], pos[3]); - pos+=4; - } -} - -uint8_t * -aml_xparsename(uint8_t *pos, struct aml_node *node, - void (*fn)(struct aml_node *, int, uint8_t *, void *), void *arg) -{ - uint8_t *rpos = pos; - struct aml_value **rv = arg; - - if (*pos == AMLOP_ROOTCHAR) { - node = &aml_root; - pos++; - } - while (*pos == AMLOP_PARENTPREFIX) { - node = node ? node->parent : &aml_root; - pos++; - } - if (*pos == 0) { - fn(node, 0, pos, arg); - pos++; - } - else if (*pos == AMLOP_MULTINAMEPREFIX) { - fn(node, pos[1], pos+2, arg); - pos += 2 + 4 * pos[1]; - } - else if (*pos == AMLOP_DUALNAMEPREFIX) { - fn(node, 2, pos+1, arg); - pos += 9; - } - else if (*pos == '_' || (*pos >= 'A' && *pos <= 'Z')) { - fn(node, 1, pos, arg); - pos += 4; - } - else { - printf("Invalid name!!!\n"); - } - if (rv && *rv == NULL) { - *rv = aml_allocvalue(AML_OBJTYPE_NAMEREF, 0, rpos); - } - return pos; -} - -/* - * Conversion routines - */ -int64_t -aml_hextoint(const char *str) -{ - int64_t v = 0; - char c; - - while (*str) { - if (*str >= '0' && *str <= '9') { - c = *(str++) - '0'; - } - else if (*str >= 'a' && *str <= 'f') { - c = *(str++) - 'a' + 10; - } - else if (*str >= 'A' && *str <= 'F') { - c = *(str++) - 'A' + 10; - } - else { - break; - } - v = (v << 4) + c; - } - return v; - -} - -void -aml_xconvert(struct aml_value *a, struct aml_value **b, int ctype, int mode) -{ - struct aml_value *c = NULL; - - /* Object is already this type */ - if (a->type == ctype) { - aml_xaddref(a, "XConvert"); - *b = a; - return; - } - switch (ctype) { - case AML_OBJTYPE_BUFFER: - dnprintf(10,"convert to buffer\n"); - switch (a->type) { - case AML_OBJTYPE_INTEGER: - c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, - &a->v_integer); - break; - case AML_OBJTYPE_STRING: - c = aml_allocvalue(AML_OBJTYPE_BUFFER, a->length, - a->v_string); - break; - } - break; - case AML_OBJTYPE_INTEGER: - dnprintf(10,"convert to integer : %x\n", a->type); - switch (a->type) { - case AML_OBJTYPE_BUFFER: - c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); - memcpy(&c->v_integer, a->v_buffer, - min(a->length, c->length)); - break; - case AML_OBJTYPE_STRING: - c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); - c->v_integer = aml_hextoint(a->v_string); - break; - case AML_OBJTYPE_UNINITIALIZED: - c = aml_allocvalue(AML_OBJTYPE_INTEGER, 0, NULL); - break; - } - break; - case AML_OBJTYPE_STRING: - dnprintf(10,"convert to string\n"); - switch (a->type) { - case AML_OBJTYPE_INTEGER: - c = aml_allocvalue(AML_OBJTYPE_STRING, 20, NULL); - snprintf(c->v_string, c->length, (mode == 'x') ? - "0x%llx" : "%lld", a->v_integer); - break; - case AML_OBJTYPE_BUFFER: - c = aml_allocvalue(AML_OBJTYPE_STRING, a->length, - a->v_buffer); - break; - } - break; - } - if (c == NULL) { -#ifndef SMALL_KERNEL - aml_showvalue(a, 0); -#endif - aml_die("Could not convert!!!\n"); - } - *b = c; -} - -int -aml_xcompare(struct aml_value *a1, struct aml_value *a2, int opcode) -{ - int rc = 0; - - /* Convert A2 to type of A1 */ - aml_xconvert(a2, &a2, a1->type, 0); - if (a1->type == AML_OBJTYPE_INTEGER) { - rc = aml_evalexpr(a1->v_integer, a2->v_integer, opcode); - } - else { - /* Perform String/Buffer comparison */ - rc = memcmp(a1->v_buffer, a2->v_buffer, - min(a1->length, a2->length)); - if (rc == 0) { - /* If buffers match, which one is longer */ - rc = a1->length - a2->length; - } - /* Perform comparison against zero */ - rc = aml_evalexpr(rc, 0, opcode); - } - /* Either deletes temp buffer, or decrease refcnt on original A2 */ - aml_xdelref(&a2, "xcompare"); - return rc; -} - -/* Concatenate two objects, returning pointer to new object */ -void -aml_xconcat(struct aml_value *a1, struct aml_value *a2, struct aml_value **res) -{ - struct aml_value *c; - - /* Convert arg2 to type of arg1 */ - aml_xconvert(a2, &a2, a1->type, 0); - switch (a1->type) { - case AML_OBJTYPE_INTEGER: - c = aml_allocvalue(AML_OBJTYPE_BUFFER, - a1->length + a2->length, NULL); - memcpy(c->v_buffer, &a1->v_integer, a1->length); - memcpy(c->v_buffer+a1->length, &a2->v_integer, a2->length); - break; - case AML_OBJTYPE_BUFFER: - c = aml_allocvalue(AML_OBJTYPE_BUFFER, - a1->length + a2->length, NULL); - memcpy(c->v_buffer, a1->v_buffer, a1->length); - memcpy(c->v_buffer+a1->length, a2->v_buffer, a2->length); - break; - case AML_OBJTYPE_STRING: - c = aml_allocvalue(AML_OBJTYPE_STRING, - a1->length + a2->length, NULL); - memcpy(c->v_string, a1->v_string, a1->length); - memcpy(c->v_string+a1->length, a2->v_string, a2->length); - break; - default: - aml_die("concat type mismatch %d != %d\n", a1->type, a2->type); - break; - } - /* Either deletes temp buffer, or decrease refcnt on original A2 */ - aml_xdelref(&a2, "xconcat"); - *res = c; -} - -/* Calculate length of Resource Template */ -int -aml_ccrlen(union acpi_resource *rs, void *arg) -{ - int *plen = arg; - - *plen += AML_CRSLEN(rs); - return 0; -} - -/* Concatenate resource templates, returning pointer to new object */ -void -aml_xconcatres(struct aml_value *a1, struct aml_value *a2, struct aml_value **res) -{ - struct aml_value *c; - int l1 = 0, l2 = 0; - - if (a1->type != AML_OBJTYPE_BUFFER || a2->type != AML_OBJTYPE_BUFFER) { - aml_die("concatres: not buffers\n"); - } - - /* Walk a1, a2, get length minus end tags, concatenate buffers, add end tag */ - aml_parse_resource(a1->length, a1->v_buffer, aml_ccrlen, &l1); - aml_parse_resource(a2->length, a2->v_buffer, aml_ccrlen, &l2); - - /* Concatenate buffers, add end tag */ - c = aml_allocvalue(AML_OBJTYPE_BUFFER, l1+l2+2, NULL); - memcpy(c->v_buffer, a1->v_buffer, l1); - memcpy(c->v_buffer+l1, a2->v_buffer, l2); - c->v_buffer[l1+l2+0] = 0x79; - c->v_buffer[l1+l2+1] = 0x00; - - *res = c; -} - -/* Extract substring from string or buffer */ -void -aml_xmid(struct aml_value *src, int index, int length, struct aml_value **res) -{ - int idx; - - for (idx=index; idx<index+length; idx++) { - if (idx >= src->length) - break; - if (src->v_buffer[idx] == 0) - break; - } - aml_die("mid\n"); -} - -/* - * Field I/O utility functions - */ -void aml_xresolve(struct aml_scope *, struct aml_value *); -void *aml_xgetptr(struct aml_value *, int); -void aml_xgasio(int, uint64_t, int, void *, int, int, const char *); -void aml_xfldio(struct aml_scope *, struct aml_value *, - struct aml_value *, int); -void aml_xcreatefield(struct aml_value *, int, struct aml_value *, int, int, - struct aml_value *, int); -void aml_xparsefieldlist(struct aml_scope *, int, int, - struct aml_value *, struct aml_value *, int); -int aml_evalhid(struct aml_node *, struct aml_value *); - -#define GAS_PCI_CFG_SPACE_UNEVAL 0xCC - -int -aml_evalhid(struct aml_node *node, struct aml_value *val) -{ - if (aml_evalname(dsdt_softc, node, "_HID", 0, NULL, val)) - return (-1); - - /* Integer _HID: convert to EISA ID */ - if (val->type == AML_OBJTYPE_INTEGER) - _aml_setvalue(val, AML_OBJTYPE_STRING, -1, aml_eisaid(val->v_integer)); - return (0); -} - -int -aml_xgetpci(struct aml_node *node, int64_t *base) -{ - struct aml_node *pci_root; - struct aml_value hid; - int64_t v; - - *base = 0; - dnprintf(10,"RESOLVE PCI: %s\n", aml_nodename(node)); - for (pci_root=node->parent; pci_root; pci_root=pci_root->parent) { - /* PCI Root object will have _HID value */ - if (aml_evalhid(pci_root, &hid) == 0) { - aml_freevalue(&hid); - break; - } - } - if (!aml_evalinteger(NULL, node->parent, "_ADR", 0, NULL, &v)) - *base += (v << 16L); - if (!aml_evalinteger(NULL, pci_root, "_BBN", 0, NULL, &v)) - *base += (v << 48L); - return 0; -} - -void -aml_xresolve(struct aml_scope *scope, struct aml_value *val) -{ - int64_t base; - - if (val->type != AML_OBJTYPE_OPREGION || val->v_opregion.flag) - return; - if (val->v_opregion.iospace != GAS_PCI_CFG_SPACE) - return; - - /* Evaluate PCI Address */ - aml_xgetpci(val->node, &base); - val->v_opregion.iobase += base; - val->v_opregion.flag = 1; -} - -/* Perform IO to address space - * type = GAS_XXXX - * base = base address - * rlen = length in bytes to read/write - * buf = buffer - * mode = ACPI_IOREAD/ACPI_IOWRITE - * sz = access_size (bits) - */ -void -aml_xgasio(int type, uint64_t base, int rlen, void *buf, int mode, int sz, - const char *lbl) -{ - sz >>= 3; - acpi_gasio(dsdt_softc, mode, type, base, sz, rlen, buf); -#ifdef ACPI_DEBUG - { - int idx; - printf("%sio: [%s] ty:%x bs=%.8llx sz=%.4x rlen=%.4x ", - mode == ACPI_IOREAD ? "rd" : "wr", lbl, - type, base, sz, rlen); - for (idx=0; idx<rlen; idx++) { - printf("%.2x ", ((uint8_t *)buf)[idx]); - } - } - printf("\n"); -#endif -} - -void * -aml_xgetptr(struct aml_value *tmp, int blen) -{ - if (blen > aml_intlen) { - _aml_setvalue(tmp, AML_OBJTYPE_BUFFER, aml_bytelen(blen), 0); - return tmp->v_buffer; - } - _aml_setvalue(tmp, AML_OBJTYPE_INTEGER, 0, NULL); - return &tmp->v_integer; -} - -/* Read and Write BufferField and FieldUnit objects */ -void -aml_xfldio(struct aml_scope *scope, struct aml_value *fld, - struct aml_value *buf, int mode) -{ - struct aml_value tmp, *data; - int bpos, blen, preserve=1, mask, aligned, rlen, slen; - void *sptr, *dptr; - - switch (AML_FIELD_ACCESS(fld->v_field.flags)) { - case AML_FIELD_WORDACC: - mask=15; - break; - case AML_FIELD_DWORDACC: - mask=31; - break; - case AML_FIELD_QWORDACC: - mask=63; - break; - default: - mask=7; - break; - } - data = fld->v_field.ref1; - bpos = fld->v_field.bitpos; - blen = fld->v_field.bitlen; - rlen = aml_bytelen((bpos & 7) + blen); - aligned = !((bpos|blen)&mask); - preserve = AML_FIELD_UPDATE(fld->v_field.flags); - - dnprintf(30,"\nquick: %s: [%s] %.4x-%.4x msk=%.2x algn=%d prsrv=%d [%s]\n", - mode == ACPI_IOREAD ? "read from" : "write to", - aml_nodename(fld->node), - bpos, blen, mask, aligned, preserve, - aml_mnem(fld->v_field.type, 0)); - - memset(&tmp, 0, sizeof(tmp)); - if (fld->v_field.ref2 != NULL) { - /* Write index */ - dnprintf(30,"writing index fldio: %d\n", fld->v_field.ref3); - _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, - fld->v_field.ref3, NULL); - aml_xfldio(scope, fld->v_field.ref2, &tmp, ACPI_IOWRITE); - } - - /* Get pointer to Data Object */ - switch (data->type) { - case AML_OBJTYPE_BUFFER: - dptr = data->v_buffer; - break; - case AML_OBJTYPE_STRING: - dptr = data->v_string; - break; - case AML_OBJTYPE_INTEGER: - dptr = &data->v_integer; - break; - case AML_OBJTYPE_OPREGION: - /* Depending on size, allocate buffer or integer */ - aml_xresolve(scope, data); - dptr = aml_xgetptr(&tmp, rlen << 3); - break; - case AML_OBJTYPE_FIELDUNIT: - case AML_OBJTYPE_BUFFERFIELD: - /* Set to integer for now.. */ - _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, 0x0, NULL); - dptr = &tmp.v_integer; - break; - default: - aml_die("jk XREAD/WRITE: unknown type: %x\n", data->type); - break; - } - - aml_lockfield(scope, fld); - if (mode == ACPI_IOREAD) { - sptr = aml_xgetptr(buf, blen); - switch (data->type) { - case AML_OBJTYPE_OPREGION: - /* Do GASIO into temp buffer, bitcopy into result */ - aml_xgasio(data->v_opregion.iospace, - data->v_opregion.iobase+(bpos>>3), - rlen, dptr, ACPI_IOREAD, mask+1, - aml_nodename(fld->node)); - aml_bufcpy(sptr, 0, dptr, bpos & 7, blen); - break; - case AML_OBJTYPE_FIELDUNIT: - case AML_OBJTYPE_BUFFERFIELD: - /* Do FieldIO into temp buffer, bitcopy into result */ - aml_xfldio(scope, data, &tmp, ACPI_IOREAD); - aml_bufcpy(sptr, 0, dptr, bpos & 7, blen); - break; - default: - /* bitcopy into result */ - aml_bufcpy(sptr, 0, dptr, bpos, blen); - break; - } - } - else { - switch (buf->type) { - case AML_OBJTYPE_INTEGER: - slen = aml_intlen; - break; - default: - slen = buf->length<<3; - break; - } - if (slen < blen) { -#ifndef SMALL_KERNEL - aml_showvalue(fld, 0); - aml_showvalue(buf, 0); -#endif - aml_die("BIG SOURCE %d %d %s", buf->length, blen>>3, ""); - } - if (buf->type != AML_OBJTYPE_INTEGER) - aml_die("writefield: not integer\n"); - sptr = &buf->v_integer; - - switch (data->type) { - case AML_OBJTYPE_OPREGION: - if (!aligned && preserve == AML_FIELD_PRESERVE) { - /* Preserve contents: read current value */ - aml_xgasio(data->v_opregion.iospace, - data->v_opregion.iobase+(bpos>>3), - rlen, dptr, ACPI_IOREAD, mask+1, - aml_nodename(fld->node)); - } - /* Bitcopy data into temp buffer, write GAS */ - if (preserve == AML_FIELD_WRITEASONES) - memset(dptr, 0xFF, tmp.length); - aml_bufcpy(dptr, bpos & 7, sptr, 0, blen); - aml_xgasio(data->v_opregion.iospace, - data->v_opregion.iobase+(bpos>>3), - rlen, dptr, ACPI_IOWRITE, mask+1, - aml_nodename(fld->node)); - break; - case AML_OBJTYPE_FIELDUNIT: - case AML_OBJTYPE_BUFFERFIELD: - if (!aligned && preserve == AML_FIELD_PRESERVE) { - /* Preserve contents: read current value */ - aml_xfldio(scope, data, &tmp, ACPI_IOREAD); - if (tmp.type != AML_OBJTYPE_INTEGER) - dptr = tmp.v_buffer; - } - else { - dptr = aml_xgetptr(&tmp, rlen<<3); - } - /* Bitcopy data into temp buffer, write field */ - if (preserve == AML_FIELD_WRITEASONES) - memset(dptr, 0xFF, tmp.length); - aml_bufcpy(dptr, bpos & 7, sptr, 0, blen); - aml_xfldio(scope, data, &tmp, ACPI_IOWRITE); - break; - default: - if (blen > aml_intlen) { - aml_die("jk Big Buffer other!\n"); - } - aml_bufcpy(dptr, bpos, sptr, 0, blen); - break; - } - } - aml_freevalue(&tmp); - aml_unlockfield(scope, fld); -} - -/* Create Field Object data index - * AMLOP_FIELD n:OpRegion NULL - * AMLOP_INDEXFIELD n:Field n:Field - * AMLOP_BANKFIELD n:OpRegion n:Field - * AMLOP_CREATEFIELD t:Buffer NULL - * AMLOP_CREATEBITFIELD t:Buffer NULL - * AMLOP_CREATEBYTEFIELD t:Buffer NULL - * AMLOP_CREATEWORDFIELD t:Buffer NULL - * AMLOP_CREATEDWORDFIELD t:Buffer NULL - * AMLOP_CREATEQWORDFIELD t:Buffer NULL - * AMLOP_INDEX t:Buffer NULL - */ -void -aml_xcreatefield(struct aml_value *field, int opcode, - struct aml_value *data, int bpos, int blen, - struct aml_value *index, int indexval) -{ - dnprintf(10, "## %s(%s): %s %.4x-%.4x\n", - aml_mnem(opcode, 0), - blen > aml_intlen ? "BUF" : "INT", - aml_nodename(field->node), bpos, blen); - if (index) { - dnprintf(10, " index:%s:%.2x\n", aml_nodename(index->node), - indexval); - } - dnprintf(10, " data:%s\n", aml_nodename(data->node)); - field->type = (opcode == AMLOP_FIELD || - opcode == AMLOP_INDEXFIELD || - opcode == AMLOP_BANKFIELD) ? - AML_OBJTYPE_FIELDUNIT : - AML_OBJTYPE_BUFFERFIELD; - field->v_field.type = opcode; - field->v_field.bitpos = bpos; - field->v_field.bitlen = blen; - field->v_field.ref3 = indexval; - field->v_field.ref2 = index; - field->v_field.ref1 = data; - - /* Increase reference count */ - aml_xaddref(data, "Field.Data"); - aml_xaddref(index, "Field.Index"); -} - -/* Parse Field/IndexField/BankField scope */ -void -aml_xparsefieldlist(struct aml_scope *mscope, int opcode, int flags, - struct aml_value *data, struct aml_value *index, int indexval) -{ - struct aml_value *rv; - int bpos, blen; - - if (mscope == NULL) - return; - bpos = 0; - while (mscope->pos < mscope->end) { - switch (*mscope->pos) { - case 0x00: // reserved, length - mscope->pos++; - blen = aml_parselength(mscope); - break; - case 0x01: // flags - mscope->pos += 3; - blen = 0; - break; - default: // 4-byte name, length - mscope->pos = aml_xparsename(mscope->pos, mscope->node, - ns_xcreate, &rv); - blen = aml_parselength(mscope); - rv->v_field.flags = flags; - switch (opcode) { - case AMLOP_FIELD: - /* nbF */ - aml_xcreatefield(rv, opcode, data, bpos, - blen, NULL, 0); - break; - case AMLOP_INDEXFIELD: - /* nnbF */ - aml_xcreatefield(rv, opcode, data, bpos & 7, - blen, index, bpos>>3); - break; - case AMLOP_BANKFIELD: - /* nnibF */ - aml_xcreatefield(rv, opcode, data, bpos, - blen, index, indexval); - break; - } - break; - } - bpos += blen; - } -} - -/* - * Mutex/Event utility functions - */ -int acpi_xmutex_acquire(struct aml_scope *, struct aml_value *, int); -void acpi_xmutex_release(struct aml_scope *, struct aml_value *); -int acpi_xevent_wait(struct aml_scope *, struct aml_value *, int); -void acpi_xevent_signal(struct aml_scope *, struct aml_value *); -void acpi_xevent_reset(struct aml_scope *, struct aml_value *); - -int -acpi_xmutex_acquire(struct aml_scope *scope, struct aml_value *mtx, - int timeout) -{ - int err; - - if (mtx->v_mtx.owner == NULL || scope == mtx->v_mtx.owner) { - /* We are now the owner */ - mtx->v_mtx.owner = scope; - if (mtx == aml_global_lock) { - dnprintf(10,"LOCKING GLOBAL\n"); - err = acpi_acquire_global_lock(&dsdt_softc->sc_facs->global_lock); - } - dnprintf(5,"%s acquires mutex %s\n", scope->node->name, - mtx->node->name); - return 0; - } - else if (timeout == 0) { - return 1; - } - /* Wait for mutex */ - return 0; -} - -void -acpi_xmutex_release(struct aml_scope *scope, struct aml_value *mtx) -{ - int err; - - if (mtx == aml_global_lock) { - dnprintf(10,"UNLOCKING GLOBAL\n"); - err=acpi_release_global_lock(&dsdt_softc->sc_facs->global_lock); - } - dnprintf(5, "%s releases mutex %s\n", scope->node->name, - mtx->node->name); - mtx->v_mtx.owner = NULL; - /* Wakeup waiters */ -} - -int -acpi_xevent_wait(struct aml_scope *scope, struct aml_value *evt, int timeout) -{ - if (evt->v_evt.state == 1) { - /* Object is signaled */ - return 0; - } - else if (timeout == 0) { - /* Zero timeout */ - return 1; - } - /* Wait for timeout or signal */ - return 0; -} - -void -acpi_xevent_signal(struct aml_scope *scope, struct aml_value *evt) -{ - evt->v_evt.state = 1; - /* Wakeup waiters */ -} - -void -acpi_xevent_reset(struct aml_scope *scope, struct aml_value *evt) -{ - evt->v_evt.state = 0; -} - -/* Store result value into an object */ -void -aml_xstore(struct aml_scope *scope, struct aml_value *lhs , int64_t ival, - struct aml_value *rhs) -{ - struct aml_value tmp; - int mlen; - - /* Already set */ - if (lhs == rhs || lhs == NULL || lhs->type == AML_OBJTYPE_NOTARGET) { - return; - } - memset(&tmp, 0, sizeof(tmp)); - tmp.refcnt=99; - if (rhs == NULL) { - rhs = _aml_setvalue(&tmp, AML_OBJTYPE_INTEGER, ival, NULL); - } - if (rhs->type == AML_OBJTYPE_BUFFERFIELD || - rhs->type == AML_OBJTYPE_FIELDUNIT) { - aml_xfldio(scope, rhs, &tmp, ACPI_IOREAD); - rhs = &tmp; - } - while (lhs->type == AML_OBJTYPE_OBJREF) { - lhs = lhs->v_objref.ref; - } - switch (lhs->type) { - case AML_OBJTYPE_UNINITIALIZED: - aml_copyvalue(lhs, rhs); - break; - case AML_OBJTYPE_BUFFERFIELD: - case AML_OBJTYPE_FIELDUNIT: - aml_xfldio(scope, lhs, rhs, ACPI_IOWRITE); - break; - case AML_OBJTYPE_DEBUGOBJ: - break; - case AML_OBJTYPE_INTEGER: - aml_xconvert(rhs, &rhs, lhs->type, 0); - lhs->v_integer = rhs->v_integer; - aml_xdelref(&rhs, "store.int"); - break; - case AML_OBJTYPE_BUFFER: - case AML_OBJTYPE_STRING: - aml_xconvert(rhs, &rhs, lhs->type, 0); - if (lhs->length < rhs->length) { - dnprintf(10,"Overrun! %d,%d\n", lhs->length, rhs->length); - aml_freevalue(lhs); - _aml_setvalue(lhs, rhs->type, rhs->length, NULL); - } - mlen = min(lhs->length, rhs->length); - memset(lhs->v_buffer, 0x00, lhs->length); - memcpy(lhs->v_buffer, rhs->v_buffer, mlen); - aml_xdelref(&rhs, "store.bufstr"); - break; - case AML_OBJTYPE_PACKAGE: - /* Convert to LHS type, copy into LHS */ - if (rhs->type != AML_OBJTYPE_PACKAGE) { - aml_die("Copy non-package into package?"); - } - aml_freevalue(lhs); - aml_copyvalue(lhs, rhs); - break; - default: - aml_die("Store to default type! %x\n", lhs->type); - break; - } - aml_freevalue(&tmp); -} - -/* Disassembler routines */ -void aml_disprintf(void *arg, const char *fmt, ...); - -void -aml_disprintf(void *arg, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); -} - -void -aml_disasm(struct aml_scope *scope, int lvl, - void (*dbprintf)(void *, const char *, ...), - void *arg) -{ - int pc, opcode; - struct aml_opcode *htab; - uint64_t ival; - struct aml_value *rv, tmp; - uint8_t *end; - struct aml_scope *ms; - char *ch; - char mch[64]; - - if (dbprintf == NULL) - dbprintf = aml_disprintf; - - pc = aml_pc(scope->pos); - opcode = aml_parseopcode(scope); - htab = aml_findopcode(opcode); - - /* Display address + indent */ - if (lvl <= 0x7FFF) { - dbprintf(arg, "%.4x ", pc); - for (pc=0; pc<lvl; pc++) { - dbprintf(arg, " "); - } - } - ch = NULL; - switch (opcode) { - case AMLOP_NAMECHAR: - scope->pos = aml_xparsename(scope->pos, scope->node, - ns_xsearch, &rv); - if (rv->type == AML_OBJTYPE_NAMEREF) { - ch = "@@@"; - aml_xdelref(&rv, "disasm"); - break; - } - /* if this is a method, get arguments */ - strlcpy(mch, aml_nodename(rv->node), sizeof(mch)); - if (rv->type == AML_OBJTYPE_METHOD) { - strlcat(mch, "(", sizeof(mch)); - for (ival=0; ival<AML_METHOD_ARGCOUNT(rv->v_method.flags); ival++) { - strlcat(mch, ival ? ", %z" : "%z", - sizeof(mch)); - } - strlcat(mch, ")", sizeof(mch)); - } - ch = mch; - break; - - case AMLOP_ZERO: - case AMLOP_ONE: - case AMLOP_ONES: - case AMLOP_LOCAL0: - case AMLOP_LOCAL1: - case AMLOP_LOCAL2: - case AMLOP_LOCAL3: - case AMLOP_LOCAL4: - case AMLOP_LOCAL5: - case AMLOP_LOCAL6: - case AMLOP_LOCAL7: - case AMLOP_ARG0: - case AMLOP_ARG1: - case AMLOP_ARG2: - case AMLOP_ARG3: - case AMLOP_ARG4: - case AMLOP_ARG5: - case AMLOP_ARG6: - case AMLOP_NOP: - case AMLOP_REVISION: - case AMLOP_DEBUG: - case AMLOP_CONTINUE: - case AMLOP_BREAKPOINT: - case AMLOP_BREAK: - ch="%m"; - break; - case AMLOP_BYTEPREFIX: - ch="%b"; - break; - case AMLOP_WORDPREFIX: - ch="%w"; - break; - case AMLOP_DWORDPREFIX: - ch="%d"; - break; - case AMLOP_QWORDPREFIX: - ch="%q"; - break; - case AMLOP_STRINGPREFIX: - ch="%a"; - break; - - case AMLOP_INCREMENT: - case AMLOP_DECREMENT: - case AMLOP_LNOT: - case AMLOP_SIZEOF: - case AMLOP_DEREFOF: - case AMLOP_REFOF: - case AMLOP_OBJECTTYPE: - case AMLOP_UNLOAD: - case AMLOP_RELEASE: - case AMLOP_SIGNAL: - case AMLOP_RESET: - case AMLOP_STALL: - case AMLOP_SLEEP: - case AMLOP_RETURN: - ch="%m(%n)"; - break; - case AMLOP_OR: - case AMLOP_ADD: - case AMLOP_AND: - case AMLOP_NAND: - case AMLOP_XOR: - case AMLOP_SHL: - case AMLOP_SHR: - case AMLOP_NOR: - case AMLOP_MOD: - case AMLOP_SUBTRACT: - case AMLOP_MULTIPLY: - case AMLOP_INDEX: - case AMLOP_CONCAT: - case AMLOP_CONCATRES: - case AMLOP_TOSTRING: - ch="%m(%n, %n, %n)"; - break; - case AMLOP_CREATEBYTEFIELD: - case AMLOP_CREATEWORDFIELD: - case AMLOP_CREATEDWORDFIELD: - case AMLOP_CREATEQWORDFIELD: - case AMLOP_CREATEBITFIELD: - ch="%m(%n, %n, %N)"; - break; - case AMLOP_CREATEFIELD: - ch="%m(%n, %n, %n, %N)"; - break; - case AMLOP_DIVIDE: - case AMLOP_MID: - ch="%m(%n, %n, %n, %n)"; - break; - case AMLOP_LAND: - case AMLOP_LOR: - case AMLOP_LNOTEQUAL: - case AMLOP_LLESSEQUAL: - case AMLOP_LLESS: - case AMLOP_LEQUAL: - case AMLOP_LGREATEREQUAL: - case AMLOP_LGREATER: - case AMLOP_NOT: - case AMLOP_FINDSETLEFTBIT: - case AMLOP_FINDSETRIGHTBIT: - case AMLOP_TOINTEGER: - case AMLOP_TOBUFFER: - case AMLOP_TOHEXSTRING: - case AMLOP_TODECSTRING: - case AMLOP_FROMBCD: - case AMLOP_TOBCD: - case AMLOP_WAIT: - case AMLOP_LOAD: - case AMLOP_STORE: - case AMLOP_NOTIFY: - case AMLOP_COPYOBJECT: - ch="%m(%n, %n)"; - break; - case AMLOP_ACQUIRE: - ch = "%m(%n, %w)"; - break; - case AMLOP_CONDREFOF: - ch="%m(%R, %n)"; - break; - case AMLOP_ALIAS: - ch="%m(%n, %N)"; - break; - case AMLOP_NAME: - ch="%m(%N, %n)"; - break; - case AMLOP_EVENT: - ch="%m(%N)"; - break; - case AMLOP_MUTEX: - ch = "%m(%N, %b)"; - break; - case AMLOP_OPREGION: - ch = "%m(%N, %b, %n, %n)"; - break; - case AMLOP_DATAREGION: - ch="%m(%N, %n, %n, %n)"; - break; - case AMLOP_FATAL: - ch = "%m(%b, %d, %n)"; - break; - case AMLOP_IF: - case AMLOP_WHILE: - case AMLOP_SCOPE: - case AMLOP_THERMALZONE: - case AMLOP_VARPACKAGE: - end = aml_parseend(scope); - ch = "%m(%n) {\n%T}"; - break; - case AMLOP_DEVICE: - end = aml_parseend(scope); - ch = "%m(%N) {\n%T}"; - break; - case AMLOP_POWERRSRC: - end = aml_parseend(scope); - ch = "%m(%N, %b, %w) {\n%T}"; - break; - case AMLOP_PROCESSOR: - end = aml_parseend(scope); - ch = "%m(%N, %b, %d, %b) {\n%T}"; - break; - case AMLOP_METHOD: - end = aml_parseend(scope); - ch = "%m(%N, %b) {\n%T}"; - break; - case AMLOP_PACKAGE: - end = aml_parseend(scope); - ch = "%m(%b) {\n%T}"; - break; - case AMLOP_ELSE: - end = aml_parseend(scope); - ch = "%m {\n%T}"; - break; - case AMLOP_BUFFER: - end = aml_parseend(scope); - ch = "%m(%n) { %B }"; - break; - case AMLOP_INDEXFIELD: - end = aml_parseend(scope); - ch = "%m(%n, %n, %b) {\n%F}"; - break; - case AMLOP_BANKFIELD: - end = aml_parseend(scope); - ch = "%m(%n, %n, %n, %b) {\n%F}"; - break; - case AMLOP_FIELD: - end = aml_parseend(scope); - ch = "%m(%n, %b) {\n%F}"; - break; - case AMLOP_MATCH: - ch = "%m(%n, %b, %n, %b, %n, %n)"; - break; - case AMLOP_LOADTABLE: - ch = "%m(%n, %n, %n, %n, %n, %n)"; - break; - default: - aml_die("opcode = %x\n", opcode); - break; - } - - /* Parse printable buffer args */ - while (ch && *ch) { - char c; - - if (*ch != '%') { - dbprintf(arg,"%c", *(ch++)); - continue; - } - c = *(++ch); - switch (c) { - case 'b': - case 'w': - case 'd': - case 'q': - /* Parse simple object: don't allocate */ - aml_xparsesimple(scope, c, &tmp); - dbprintf(arg,"0x%llx", tmp.v_integer); - break; - case 'a': - dbprintf(arg, "\'%s\'", scope->pos); - scope->pos += strlen(scope->pos)+1; - break; - case 'N': - /* Create Name */ - rv = aml_xparsesimple(scope, c, NULL); - dbprintf(arg,aml_nodename(rv->node)); - break; - case 'm': - /* display mnemonic */ - dbprintf(arg,htab->mnem); - break; - case 'R': - /* Search name */ - scope->pos = aml_xparsename(scope->pos, scope->node, - ns_xdis, &rv); - break; - case 'z': - case 'n': - /* generic arg: recurse */ - aml_disasm(scope, lvl | 0x8000, dbprintf, arg); - break; - case 'B': - /* Buffer */ - scope->pos = end; - break; - case 'F': - /* Field List */ - tmp.v_buffer = scope->pos; - tmp.length = end - scope->pos; - - ms = aml_xpushscope(scope, &tmp, scope->node, 0); - while (ms && ms->pos < ms->end) { - if (*ms->pos == 0x00) { - ms->pos++; - aml_parselength(ms); - } - else if (*ms->pos == 0x01) { - ms->pos+=3; - } - else { - ms->pos = aml_xparsename(ms->pos, - ms->node, ns_xcreate, &rv); - aml_parselength(ms); - dbprintf(arg," %s\n", - aml_nodename(rv->node)); - } - } - aml_xpopscope(ms); - - /* Display address and closing bracket */ - dbprintf(arg,"%.4x ", aml_pc(scope->pos)); - for (pc=0; pc<(lvl & 0x7FFF); pc++) { - dbprintf(arg," "); - } - scope->pos = end; - break; - case 'T': - /* Scope: Termlist */ - tmp.v_buffer = scope->pos; - tmp.length = end - scope->pos; - - ms = aml_xpushscope(scope, &tmp, scope->node, 0); - while (ms && ms->pos < ms->end) { - aml_disasm(ms, (lvl + 1) & 0x7FFF, - dbprintf, arg); - } - aml_xpopscope(ms); - - /* Display address and closing bracket */ - dbprintf(arg,"%.4x ", aml_pc(scope->pos)); - for (pc=0; pc<(lvl & 0x7FFF); pc++) { - dbprintf(arg," "); - } - scope->pos = end; - break; - } - ch++; - } - if (lvl <= 0x7FFF) { - dbprintf(arg,"\n"); - } -} - -int aml_busy; - -/* Evaluate method or buffervalue objects */ -struct aml_value * -aml_xeval(struct aml_scope *scope, struct aml_value *my_ret, int ret_type, - int argc, struct aml_value *argv) -{ - struct aml_value *tmp = my_ret; - struct aml_scope *ms; - int idx; - - switch (tmp->type) { - case AML_OBJTYPE_METHOD: - dnprintf(10,"\n--== Eval Method [%s, %d args] to %c ==--\n", - aml_nodename(tmp->node), - AML_METHOD_ARGCOUNT(tmp->v_method.flags), - ret_type); - ms = aml_xpushscope(scope, tmp, tmp->node, AMLOP_METHOD); - ms->args = acpi_os_malloc(7 * sizeof(struct aml_value)); - - /* Parse method arguments */ - for (idx=0; idx<AML_METHOD_ARGCOUNT(tmp->v_method.flags); idx++) { - ms->args[idx].type = AML_OBJTYPE_OBJREF; - ms->args[idx].v_objref.type = AMLOP_ARG0 + idx; - if (argv) { - ms->args[idx].v_objref.ref = &argv[idx]; - argv[idx].refcnt = 99; - } - else { - ms->args[idx].v_objref.ref = - aml_xparse(scope, 't', "ARGX"); - } - } -#ifdef ACPI_DEBUG - aml_showstack(ms); -#endif - - /* Evaluate method scope */ - if (tmp->v_method.fneval != NULL) { - my_ret = tmp->v_method.fneval(ms, NULL); - } - else { - aml_xparse(ms, 'T', "METHEVAL"); - my_ret = ms->retv; - } - dnprintf(10,"\n--==Finished evaluating method: %s %c\n", - aml_nodename(tmp->node), ret_type); -#ifdef ACPI_DEBUG - aml_showvalue(my_ret, 0); - aml_showstack(ms); -#endif - aml_xpopscope(ms); - break; - case AML_OBJTYPE_BUFFERFIELD: - case AML_OBJTYPE_FIELDUNIT: - my_ret = aml_allocvalue(0,0,NULL); - dnprintf(20,"quick: Convert Bufferfield to %c 0x%x\n", - ret_type, my_ret); - aml_xfldio(scope, tmp, my_ret, ACPI_IOREAD); - break; - } - if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { -#ifndef SMALL_KERNEL - aml_showvalue(my_ret, 8-100); -#endif - aml_die("Not Integer"); - } - return my_ret; -} - -/* - * The following opcodes produce return values - * TOSTRING -> Str - * TOHEXSTR -> Str - * TODECSTR -> Str - * STRINGPFX -> Str - * BUFFER -> Buf - * CONCATRES -> Buf - * TOBUFFER -> Buf - * MID -> Buf|Str - * CONCAT -> Buf|Str - * PACKAGE -> Pkg - * VARPACKAGE -> Pkg - * LOCALx -> Obj - * ARGx -> Obj - * NAMECHAR -> Obj - * REFOF -> ObjRef - * INDEX -> ObjRef - * DEREFOF -> DataRefObj - * COPYOBJECT -> DataRefObj - * STORE -> DataRefObj - - * ZERO -> Int - * ONE -> Int - * ONES -> Int - * REVISION -> Int - * B/W/D/Q -> Int - * OR -> Int - * AND -> Int - * ADD -> Int - * NAND -> Int - * XOR -> Int - * SHL -> Int - * SHR -> Int - * NOR -> Int - * MOD -> Int - * SUBTRACT -> Int - * MULTIPLY -> Int - * DIVIDE -> Int - * NOT -> Int - * TOBCD -> Int - * FROMBCD -> Int - * FSLEFTBIT -> Int - * FSRIGHTBIT -> Int - * INCREMENT -> Int - * DECREMENT -> Int - * TOINTEGER -> Int - * MATCH -> Int - * SIZEOF -> Int - * OBJECTTYPE -> Int - * TIMER -> Int - - * CONDREFOF -> Bool - * ACQUIRE -> Bool - * WAIT -> Bool - * LNOT -> Bool - * LAND -> Bool - * LOR -> Bool - * LLESS -> Bool - * LEQUAL -> Bool - * LGREATER -> Bool - * LNOTEQUAL -> Bool - * LLESSEQUAL -> Bool - * LGREATEREQ -> Bool - - * LOADTABLE -> DDB - * DEBUG -> Debug - - * The following opcodes do not generate a return value: - * NOP - * BREAKPOINT - * RELEASE - * RESET - * SIGNAL - * NAME - * ALIAS - * OPREGION - * DATAREGION - * EVENT - * MUTEX - * SCOPE - * DEVICE - * THERMALZONE - * POWERRSRC - * PROCESSOR - * METHOD - * CREATEFIELD - * CREATEBITFIELD - * CREATEBYTEFIELD - * CREATEWORDFIELD - * CREATEDWORDFIELD - * CREATEQWORDFIELD - * FIELD - * INDEXFIELD - * BANKFIELD - * STALL - * SLEEP - * NOTIFY - * FATAL - * LOAD - * UNLOAD - * IF - * ELSE - * WHILE - * BREAK - * CONTINUE - */ - -/* Parse a simple object from AML Bytestream */ -struct aml_value * -aml_xparsesimple(struct aml_scope *scope, char ch, struct aml_value *rv) -{ - if (ch == AML_ARG_CREATENAME) { - scope->pos = aml_xparsename(scope->pos, scope->node, - ns_xcreate, &rv); - return rv; - } - else if (ch == AML_ARG_SEARCHNAME) { - scope->pos = aml_xparsename(scope->pos, scope->node, - ns_xsearch, &rv); - return rv; - } - if (rv == NULL) - rv = aml_allocvalue(0,0,NULL); - switch (ch) { - case AML_ARG_REVISION: - _aml_setvalue(rv, AML_OBJTYPE_INTEGER, AML_REVISION, NULL); - break; - case AML_ARG_DEBUG: - _aml_setvalue(rv, AML_OBJTYPE_DEBUGOBJ, 0, NULL); - break; - case AML_ARG_BYTE: - _aml_setvalue(rv, AML_OBJTYPE_INTEGER, - aml_get8(scope->pos), NULL); - scope->pos += 1; - break; - case AML_ARG_WORD: - _aml_setvalue(rv, AML_OBJTYPE_INTEGER, - aml_get16(scope->pos), NULL); - scope->pos += 2; - break; - case AML_ARG_DWORD: - _aml_setvalue(rv, AML_OBJTYPE_INTEGER, - aml_get32(scope->pos), NULL); - scope->pos += 4; - break; - case AML_ARG_QWORD: - _aml_setvalue(rv, AML_OBJTYPE_INTEGER, - aml_get64(scope->pos), NULL); - scope->pos += 8; - break; - case AML_ARG_STRING: - _aml_setvalue(rv, AML_OBJTYPE_STRING, -1, scope->pos); - scope->pos += rv->length+1; - break; - } - return rv; -} - -/* - * Main Opcode Parser/Evaluator - * - * ret_type is expected type for return value - * 'o' = Data Object (Int/Str/Buf/Pkg/Name) - * 'i' = Integer - * 't' = TermArg (Int/Str/Buf/Pkg) - * 'r' = Target (NamedObj/Local/Arg/Null) - * 'S' = SuperName (NamedObj/Local/Arg) - * 'T' = TermList - */ -#define aml_debugger(x) - -struct aml_value * -aml_xparse(struct aml_scope *scope, int ret_type, const char *stype) -{ - int opcode, idx, pc, optype[8]; - struct aml_opcode *htab; - struct aml_value *opargs[8], *my_ret, *tmp, *cname; - struct aml_scope *mscope; - const char *ch; - int64_t ival; - - my_ret = NULL; - if (scope == NULL || scope->pos >= scope->end) { - return NULL; - } - start: - if (odp++ > 125) - panic("depth"); - - /* --== Stage 0: Get Opcode ==-- */ - pc = aml_pc(scope->pos); - aml_debugger(scope); - - opcode = aml_parseopcode(scope); - delay(amlop_delay); - - htab = aml_findopcode(opcode); - if (htab == NULL) { - /* No opcode handler */ - aml_die("Unknown opcode: %.4x @ %.4x", opcode, - aml_pc(scope->pos - opsize(opcode))); - } - dnprintf(18,"%.4x %s\n", pc, aml_mnem(opcode, scope->pos)); - - /* --== Stage 1: Process opcode arguments ==-- */ - cname = NULL; - memset(opargs, 0, sizeof(opargs)); - memset(optype, 0, sizeof(optype)); - idx = 0; - for (ch = htab->args; *ch; ch++) { - struct aml_value *rv; - uint8_t *end; - - rv = NULL; - switch (*ch) { - case AML_ARG_OBJLEN: - end = aml_parseend(scope); - break; - case AML_ARG_IFELSE: - /* Special Case: IF-ELSE:piTbpT or IF:piT */ - ch = (*end == AMLOP_ELSE && end < scope->end) ? - "-TbpT" : "-T"; - break; - - /* Complex arguments */ - case 's': - case 'S': - case AML_ARG_TARGET: - case AML_ARG_TERMOBJ: - case AML_ARG_INTEGER: - if (*ch == 'r' && *scope->pos == AMLOP_ZERO) { - /* Special case: NULL Target */ - rv = aml_allocvalue(AML_OBJTYPE_NOTARGET, 0, NULL); - scope->pos++; - } - else { - rv = aml_xparse(scope, *ch, htab->mnem); - if (rv == NULL) - aml_die("NULL RESULT"); - } - break; - - /* Simple arguments */ - case AML_ARG_WHILE: - case AML_ARG_BUFFER: - case AML_ARG_METHOD: - case AML_ARG_FIELDLIST: - case AML_ARG_TERMOBJLIST: - rv = aml_allocvalue(AML_OBJTYPE_SCOPE, 0, NULL); - rv->v_buffer = scope->pos; - rv->length = end - scope->pos; - scope->pos = end; - break; - case AML_ARG_CONST: - rv = aml_allocvalue(AML_OBJTYPE_INTEGER, - (char)opcode, NULL); - break; - case AML_ARG_CREATENAME: - rv = aml_xparsesimple(scope, *ch, NULL); - cname = rv; - if (cname->type != 0 && opcode != AMLOP_SCOPE) - dnprintf(10, "%s value already exists %s\n", - aml_nodename(cname->node), - htab->mnem); - break; - case AML_ARG_SEARCHNAME: - rv = aml_xparsesimple(scope, *ch, NULL); - if (rv->type != AML_OBJTYPE_NAMEREF) - aml_xaddref(rv, "Search Name"); - break; - case AML_ARG_BYTE: - case AML_ARG_WORD: - case AML_ARG_DWORD: - case AML_ARG_QWORD: - case AML_ARG_DEBUG: - case AML_ARG_STRING: - case AML_ARG_REVISION: - rv = aml_xparsesimple(scope, *ch, NULL); - break; - case AML_ARG_STKLOCAL: - mscope = aml_xfindscope(scope, AMLOP_METHOD, 0); - if (mscope->locals == NULL) { - mscope->locals = acpi_os_malloc(8 * sizeof(struct aml_value)); - } - rv = &mscope->locals[opcode - AMLOP_LOCAL0]; - if (rv->refcnt == 0) { - rv->refcnt++; - } - rv->stack = opcode; - rv->node = mscope->node; - break; - case AML_ARG_STKARG: - mscope = aml_xfindscope(scope, AMLOP_METHOD, 0); - rv = mscope->args[opcode - AMLOP_ARG0].v_objref.ref; - break; - default: - aml_die("Unknown arg type: %c\n", *ch); - break; - } - if (rv != NULL) { - optype[idx] = *ch; - opargs[idx++] = rv; - } - } - - /* Check for Op(Src1,Src2,Src1) type operations */ - for (idx=0; optype[idx]; idx++) { - int jdx; - for (jdx=idx+1; optype[jdx]; jdx++) { - if (opargs[idx] == opargs[jdx]) { - dnprintf(12,"STORE SAME %s %d,%d -> [%s] ", - htab->mnem, idx, jdx, - aml_nodename(scope->node)); - } - } - } - - /* --== Stage 2: Process opcode ==-- */ - ival = 0; - my_ret = NULL; - mscope = NULL; - switch (opcode) { - case AMLOP_NOP: - case AMLOP_BREAKPOINT: - break; - case AMLOP_LOCAL0: - case AMLOP_LOCAL1: - case AMLOP_LOCAL2: - case AMLOP_LOCAL3: - case AMLOP_LOCAL4: - case AMLOP_LOCAL5: - case AMLOP_LOCAL6: - case AMLOP_LOCAL7: - my_ret = opargs[0]; - aml_xaddref(my_ret, htab->mnem); - if (ret_type == AML_ARG_INTEGER) { - /* Return copy of integer value */ - aml_xconvert(my_ret, &my_ret, AML_OBJTYPE_INTEGER, 0); - ival = my_ret->v_integer; - aml_xdelref(&my_ret, "local.int"); - my_ret = NULL; - } - else if (ret_type == AML_ARG_TARGET) { - /* Store to LocalX: free object */ - aml_freevalue(my_ret); - } - break; - case AMLOP_ARG0: - case AMLOP_ARG1: - case AMLOP_ARG2: - case AMLOP_ARG3: - case AMLOP_ARG4: - case AMLOP_ARG5: - case AMLOP_ARG6: - /* These are not allocated dynamically but do not have node */ - my_ret = opargs[0]; - aml_xaddref(my_ret, htab->mnem); - break; - case AMLOP_NAMECHAR: - /* opargs[0] = named object (node != NULL), or nameref */ - my_ret = opargs[0]; - if (my_ret->type == AML_OBJTYPE_OBJREF) { - my_ret = my_ret->v_objref.ref; - aml_xaddref(my_ret, "de-alias"); - } - if (ret_type == 'i' || ret_type == 't' || ret_type == 'T') { - /* Return TermArg or Integer: Evaluate object */ - my_ret = aml_xeval(scope, my_ret, ret_type, 0, NULL); - } - else if (my_ret->type == AML_OBJTYPE_METHOD) { - /* This should only happen with CondRef */ - dnprintf(12,"non-termarg method : %s\n", stype); - aml_xaddref(my_ret, "zoom"); - } - break; - - case AMLOP_ZERO: - case AMLOP_ONE: - case AMLOP_ONES: - case AMLOP_DEBUG: - case AMLOP_REVISION: - case AMLOP_BYTEPREFIX: - case AMLOP_WORDPREFIX: - case AMLOP_DWORDPREFIX: - case AMLOP_QWORDPREFIX: - case AMLOP_STRINGPREFIX: - my_ret = opargs[0]; - break; - - case AMLOP_BUFFER: - /* Buffer: iB => Buffer */ - my_ret = aml_allocvalue(AML_OBJTYPE_BUFFER, - opargs[0]->v_integer, NULL); - memcpy(my_ret->v_buffer, opargs[1]->v_buffer, - opargs[1]->length); - break; - case AMLOP_PACKAGE: - case AMLOP_VARPACKAGE: - /* Package/VarPackage: bT/iT => Package */ - my_ret = aml_allocvalue(AML_OBJTYPE_PACKAGE, - opargs[0]->v_integer, 0); - mscope = aml_xpushscope(scope, opargs[1], scope->node, - AMLOP_PACKAGE); - - for (idx=0; idx<my_ret->length; idx++) { - tmp = aml_xparse(mscope, 'o', "Package"); - if (tmp == NULL) { - continue; - } - if (tmp->node) { - /* Object is a named node: store as string */ - const char *nn = aml_nodename(tmp->node); - aml_xdelref(&tmp, "pkg.node"); - tmp = aml_allocvalue(AML_OBJTYPE_STRING, - -1, nn); - } - else if (tmp->type == AML_OBJTYPE_NAMEREF) { - const char *nn = aml_getname(tmp->v_nameref); - aml_xdelref(&tmp, "pkg.node"); - tmp = aml_allocvalue(AML_OBJTYPE_STRING, - -1, nn); - } - /* Package value already allocated; delete it - * and replace with pointer to return value */ - aml_xdelref(&my_ret->v_package[idx], "pkg/init"); - my_ret->v_package[idx] = tmp; - } - aml_xpopscope(mscope); - mscope = NULL; - break; - - /* Math/Logical operations */ - case AMLOP_OR: - case AMLOP_ADD: - case AMLOP_AND: - case AMLOP_NAND: - case AMLOP_XOR: - case AMLOP_SHL: - case AMLOP_SHR: - case AMLOP_NOR: - case AMLOP_MOD: - case AMLOP_SUBTRACT: - case AMLOP_MULTIPLY: - /* XXX: iir => I */ - ival = aml_evalexpr(opargs[0]->v_integer, - opargs[1]->v_integer, opcode); - aml_xstore(scope, opargs[2], ival, NULL); - break; - case AMLOP_DIVIDE: - /* Divide: iirr => I */ - ival = aml_evalexpr(opargs[0]->v_integer, - opargs[1]->v_integer, AMLOP_MOD); - aml_xstore(scope, opargs[2], ival, NULL); - - ival = aml_evalexpr(opargs[0]->v_integer, - opargs[1]->v_integer, AMLOP_DIVIDE); - aml_xstore(scope, opargs[3], ival, NULL); - break; - case AMLOP_NOT: - case AMLOP_TOBCD: - case AMLOP_FROMBCD: - case AMLOP_FINDSETLEFTBIT: - case AMLOP_FINDSETRIGHTBIT: - /* XXX: ir => I */ - ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); - aml_xstore(scope, opargs[1], ival, NULL); - break; - case AMLOP_INCREMENT: - case AMLOP_DECREMENT: - /* Inc/Dec: S => I */ - my_ret = aml_xeval(scope, opargs[0], AML_ARG_INTEGER, 0, NULL); - ival = aml_evalexpr(my_ret->v_integer, 1, opcode); - aml_xstore(scope, opargs[0], ival, NULL); - break; - case AMLOP_LNOT: - /* LNot: i => Bool */ - ival = aml_evalexpr(opargs[0]->v_integer, 0, opcode); - break; - case AMLOP_LOR: - case AMLOP_LAND: - /* XXX: ii => Bool */ - ival = aml_evalexpr(opargs[0]->v_integer, - opargs[1]->v_integer, opcode); - break; - case AMLOP_LLESS: - case AMLOP_LEQUAL: - case AMLOP_LGREATER: - case AMLOP_LNOTEQUAL: - case AMLOP_LLESSEQUAL: - case AMLOP_LGREATEREQUAL: - /* XXX: tt => Bool */ - ival = aml_xcompare(opargs[0], opargs[1], opcode); - break; - - /* Reference/Store operations */ - case AMLOP_CONDREFOF: - /* CondRef: rr => I */ - ival = 0; - if (opargs[0]->node != NULL) { - aml_freevalue(opargs[1]); - - /* Create Object Reference */ - _aml_setvalue(opargs[1], AML_OBJTYPE_OBJREF, 0, opargs[0]); - opargs[1]->v_objref.type = AMLOP_REFOF; - aml_xaddref(opargs[1], "CondRef"); - - /* Mark that we found it */ - ival = -1; - } - break; - case AMLOP_REFOF: - /* RefOf: r => ObjRef */ - my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, 0, opargs[0]); - my_ret->v_objref.type = AMLOP_REFOF; - aml_xaddref(my_ret->v_objref.ref, "RefOf"); - break; - case AMLOP_INDEX: - /* Index: tir => ObjRef */ - idx = opargs[1]->v_integer; - if (idx >= opargs[0]->length || idx < 0) { -#ifndef SMALL_KERNEL - aml_showvalue(opargs[0], 0); -#endif - aml_die("Index out of bounds %d/%d\n", idx, - opargs[0]->length); - } - switch (opargs[0]->type) { - case AML_OBJTYPE_PACKAGE: - /* Don't set opargs[0] to NULL */ - if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { - my_ret = opargs[0]->v_package[idx]; - aml_xaddref(my_ret, "Index.Package"); - } - else { - my_ret = aml_allocvalue(AML_OBJTYPE_OBJREF, 0, - opargs[0]->v_package[idx]); - my_ret->v_objref.type = AMLOP_PACKAGE; - aml_xaddref(my_ret->v_objref.ref, - "Index.Package"); - } - break; - case AML_OBJTYPE_BUFFER: - case AML_OBJTYPE_STRING: - case AML_OBJTYPE_INTEGER: - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - if (ret_type == 't' || ret_type == 'i' || ret_type == 'T') { - dnprintf(12,"Index.Buf Term: %d = %x\n", - idx, tmp->v_buffer[idx]); - ival = tmp->v_buffer[idx]; - } - else { - dnprintf(12, "Index.Buf Targ\n"); - my_ret = aml_allocvalue(0,0,NULL); - aml_xcreatefield(my_ret, AMLOP_INDEX, tmp, - 8 * idx, 8, NULL, 0); - } - aml_xdelref(&tmp, "Index.BufStr"); - break; - default: - aml_die("Unknown index : %x\n", opargs[0]->type); - break; - } - aml_xstore(scope, opargs[2], ival, my_ret); - break; - case AMLOP_DEREFOF: - /* DerefOf: t:ObjRef => DataRefObj */ - if (opargs[0]->type == AML_OBJTYPE_OBJREF) { - my_ret = opargs[0]->v_objref.ref; - aml_xaddref(my_ret, "DerefOf"); - } - else { - my_ret = opargs[0]; - //aml_xaddref(my_ret, "DerefOf"); - } - break; - case AMLOP_COPYOBJECT: - /* CopyObject: t:DataRefObj, s:implename => DataRefObj */ - my_ret = opargs[0]; - aml_freevalue(opargs[1]); - aml_copyvalue(opargs[1], opargs[0]); - break; - case AMLOP_STORE: - /* Store: t:DataRefObj, S:upername => DataRefObj */ - my_ret = opargs[0]; - aml_xstore(scope, opargs[1], 0, opargs[0]); - break; - - /* Conversion */ - case AMLOP_TOINTEGER: - /* Source:CData, Result => Integer */ - aml_xconvert(opargs[0], &my_ret, AML_OBJTYPE_INTEGER, 0); - aml_xstore(scope, opargs[1], 0, my_ret); - break; - case AMLOP_TOBUFFER: - /* Source:CData, Result => Buffer */ - aml_xconvert(opargs[0], &my_ret, AML_OBJTYPE_BUFFER, 0); - aml_xstore(scope, opargs[1], 0, my_ret); - break; - case AMLOP_TOHEXSTRING: - /* Source:CData, Result => String */ - aml_xconvert(opargs[0], &my_ret, AML_OBJTYPE_STRING, 'x'); - aml_xstore(scope, opargs[1], 0, my_ret); - break; - case AMLOP_TODECSTRING: - /* Source:CData, Result => String */ - aml_xconvert(opargs[0], &my_ret, AML_OBJTYPE_STRING, 'd'); - aml_xstore(scope, opargs[1], 0, my_ret); - break; - case AMLOP_TOSTRING: - /* Source:B, Length:I, Result => String */ - aml_xconvert(opargs[0], &my_ret, AML_OBJTYPE_STRING, 0); - aml_die("tostring\n"); - break; - case AMLOP_CONCAT: - /* Source1:CData, Source2:CData, Result => CData */ - aml_xconcat(opargs[0], opargs[1], &my_ret); - aml_xstore(scope, opargs[2], 0, my_ret); - break; - case AMLOP_CONCATRES: - /* Concat two resource buffers: buf1, buf2, result => Buffer */ - aml_xconcatres(opargs[0], opargs[1], &my_ret); - aml_xstore(scope, opargs[2], 0, my_ret); - break; - case AMLOP_MID: - /* Source:BS, Index:I, Length:I, Result => BS */ - aml_xmid(opargs[0], opargs[1]->v_integer, - opargs[2]->v_integer, &my_ret); - aml_xstore(scope, opargs[3], 0, my_ret); - break; - case AMLOP_MATCH: - /* Match: Pkg, Op1, Val1, Op2, Val2, Index */ - ival = aml_xmatch(opargs[0], opargs[5]->v_integer, - opargs[1]->v_integer, opargs[2]->v_integer, - opargs[3]->v_integer, opargs[4]->v_integer); - break; - case AMLOP_SIZEOF: - /* Sizeof: S => i */ - ival = opargs[0]->length; - break; - case AMLOP_OBJECTTYPE: - /* ObjectType: S => i */ - ival = opargs[0]->type; - break; - - /* Mutex/Event handlers */ - case AMLOP_ACQUIRE: - /* Acquire: Sw => Bool */ - ival = acpi_xmutex_acquire(scope, opargs[0], - opargs[1]->v_integer); - break; - case AMLOP_RELEASE: - /* Release: S */ - acpi_xmutex_release(scope, opargs[0]); - break; - case AMLOP_WAIT: - /* Wait: Si => Bool */ - ival = acpi_xevent_wait(scope, opargs[0], - opargs[1]->v_integer); - break; - case AMLOP_RESET: - /* Reset: S */ - acpi_xevent_reset(scope, opargs[0]); - break; - case AMLOP_SIGNAL: - /* Signal: S */ - acpi_xevent_signal(scope, opargs[0]); - break; - - /* Named objects */ - case AMLOP_NAME: - /* Name: Nt */ - aml_freevalue(cname); - aml_copyvalue(cname, opargs[1]); - break; - case AMLOP_ALIAS: - /* Alias: nN */ - cname->type = AML_OBJTYPE_OBJREF; - cname->v_objref.type = AMLOP_ALIAS; - cname->v_objref.ref = opargs[0]; - while (cname->v_objref.ref->type == AML_OBJTYPE_OBJREF) { - /* Single indirection level */ - cname->v_objref.ref = cname->v_objref.ref->v_objref.ref; - } - aml_xaddref(cname->v_objref.ref, "Alias"); - break; - case AMLOP_OPREGION: - /* OpRegion: Nbii */ - cname->type = AML_OBJTYPE_OPREGION; - cname->v_opregion.iospace = opargs[1]->v_integer; - cname->v_opregion.iobase = opargs[2]->v_integer; - cname->v_opregion.iolen = opargs[3]->v_integer; - cname->v_opregion.flag = 0; - break; - case AMLOP_DATAREGION: - /* DataTableRegion: N,t:SigStr,t:OemIDStr,t:OemTableIDStr */ - cname->type = AML_OBJTYPE_OPREGION; - cname->v_opregion.iospace = GAS_SYSTEM_MEMORY; - cname->v_opregion.iobase = 0; - cname->v_opregion.iolen = 0; - aml_die("AML-DataTableRegion\n"); - break; - case AMLOP_EVENT: - /* Event: N */ - cname->type = AML_OBJTYPE_EVENT; - cname->v_integer = 0; - break; - case AMLOP_MUTEX: - /* Mutex: Nw */ - cname->type = AML_OBJTYPE_MUTEX; - cname->v_mtx.synclvl = opargs[1]->v_integer; - break; - case AMLOP_SCOPE: - /* Scope: NT */ - mscope = aml_xpushscope(scope, opargs[1], cname->node, opcode); - break; - case AMLOP_DEVICE: - /* Device: NT */ - cname->type = AML_OBJTYPE_DEVICE; - mscope = aml_xpushscope(scope, opargs[1], cname->node, opcode); - break; - case AMLOP_THERMALZONE: - /* ThermalZone: NT */ - cname->type = AML_OBJTYPE_THERMZONE; - mscope = aml_xpushscope(scope, opargs[1], cname->node, opcode); - break; - case AMLOP_POWERRSRC: - /* PowerRsrc: NbwT */ - cname->type = AML_OBJTYPE_POWERRSRC; - cname->v_powerrsrc.pwr_level = opargs[1]->v_integer; - cname->v_powerrsrc.pwr_order = opargs[2]->v_integer; - mscope = aml_xpushscope(scope, opargs[3], cname->node, opcode); - break; - case AMLOP_PROCESSOR: - /* Processor: NbdbT */ - cname->type = AML_OBJTYPE_PROCESSOR; - cname->v_processor.proc_id = opargs[1]->v_integer; - cname->v_processor.proc_addr = opargs[2]->v_integer; - cname->v_processor.proc_len = opargs[3]->v_integer; - mscope = aml_xpushscope(scope, opargs[4], cname->node, opcode); - break; - case AMLOP_METHOD: - /* Method: NbM */ - cname->type = AML_OBJTYPE_METHOD; - cname->v_method.flags = opargs[1]->v_integer; - cname->v_method.start = opargs[2]->v_buffer; - cname->v_method.end = cname->v_method.start + opargs[2]->length; - cname->v_method.base = aml_root.start; - break; - - /* Field objects */ - case AMLOP_CREATEFIELD: - /* Source:B, BitIndex:I, NumBits:I, FieldName */ - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - aml_xcreatefield(cname, opcode, tmp, opargs[1]->v_integer, - opargs[2]->v_integer, NULL, 0); - aml_xdelref(&tmp, htab->mnem); - break; - case AMLOP_CREATEBITFIELD: - /* Source:B, BitIndex:I, FieldName */ - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - aml_xcreatefield(cname, opcode, tmp, opargs[1]->v_integer, - 1, NULL, 0); - aml_xdelref(&tmp, htab->mnem); - break; - case AMLOP_CREATEBYTEFIELD: - /* Source:B, ByteIndex:I, FieldName */ - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - aml_xcreatefield(cname, opcode, tmp, opargs[1]->v_integer*8, - 8, NULL, 0); - aml_xdelref(&tmp, htab->mnem); - cname->v_field.flags = AML_FIELD_BYTEACC; - break; - case AMLOP_CREATEWORDFIELD: - /* Source:B, ByteIndex:I, FieldName */ - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - aml_xcreatefield(cname, opcode, tmp, opargs[1]->v_integer*8, - 16, NULL, 0); - aml_xdelref(&tmp, htab->mnem); - cname->v_field.flags = AML_FIELD_WORDACC; - break; - case AMLOP_CREATEDWORDFIELD: - /* Source:B, ByteIndex:I, FieldName */ - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - aml_xcreatefield(cname, opcode, tmp, opargs[1]->v_integer*8, - 32, NULL, 0); - aml_xdelref(&tmp, htab->mnem); - cname->v_field.flags = AML_FIELD_DWORDACC; - break; - case AMLOP_CREATEQWORDFIELD: - /* Source:B, ByteIndex:I, FieldName */ - aml_xconvert(opargs[0], &tmp, AML_OBJTYPE_BUFFER, 0); - aml_xcreatefield(cname, opcode, tmp, opargs[1]->v_integer*8, - 64, NULL, 0); - aml_xdelref(&tmp, htab->mnem); - cname->v_field.flags = AML_FIELD_QWORDACC; - break; - case AMLOP_FIELD: - /* Field: n:OpRegion, b:Flags, F:ieldlist */ - mscope = aml_xpushscope(scope, opargs[2], scope->node, opcode); - aml_xparsefieldlist(mscope, opcode, opargs[1]->v_integer, - opargs[0], NULL, 0); - break; - case AMLOP_INDEXFIELD: - /* IndexField: n:Index, n:Data, b:Flags, F:ieldlist */ - mscope = aml_xpushscope(scope, opargs[3], scope->node, opcode); - aml_xparsefieldlist(mscope, opcode, opargs[2]->v_integer, - opargs[1], opargs[0], 0); - break; - case AMLOP_BANKFIELD: - /* BankField: n:OpRegion, n:Field, i:Bank, b:Flags, F:ieldlist */ - mscope = aml_xpushscope(scope, opargs[4], scope->node, opcode); - aml_xparsefieldlist(mscope, opcode, opargs[3]->v_integer, - opargs[0], opargs[1], opargs[2]->v_integer); - break; - - /* Misc functions */ - case AMLOP_STALL: - /* Stall: i */ - acpi_stall(opargs[0]->v_integer); - break; - case AMLOP_SLEEP: - /* Sleep: i */ - acpi_sleep(opargs[0]->v_integer); - break; - case AMLOP_NOTIFY: - /* Notify: Si */ - dnprintf(50,"Notifying: %s %x\n", - aml_nodename(opargs[0]->node), - opargs[1]->v_integer); - aml_notify(opargs[0]->node, opargs[1]->v_integer); - break; - case AMLOP_TIMER: - /* Timer: => i */ - ival = 0xDEADBEEF; - break; - case AMLOP_FATAL: - /* Fatal: bdi */ - aml_die("AML FATAL ERROR: %x,%x,%x\n", - opargs[0]->v_integer, opargs[1]->v_integer, - opargs[2]->v_integer); - break; - case AMLOP_LOADTABLE: - /* LoadTable(Sig:Str, OEMID:Str, OEMTable:Str, [RootPath:Str], [ParmPath:Str], - [ParmData:DataRefObj]) => DDBHandle */ - aml_die("LoadTable"); - break; - case AMLOP_LOAD: - /* Load(Object:NameString, DDBHandle:SuperName) */ - tmp = opargs[0]; - if (tmp->type != AML_OBJTYPE_OPREGION || - tmp->v_opregion.iospace != GAS_SYSTEM_MEMORY) { - aml_die("LOAD: not a memory region!\n"); - } -#if 0 - /* Create buffer and read from memory */ - aml_xgasio(tmp->v_opregion.iospace, tmp->v_opregion.iobase, - tmp->v_opregion.iolen, - opargs[1], ACPI_IOREAD); - - /* Validate that this is a SSDT */ - if (!valid_acpihdr(opargs[1]->v_buffer, opargs[1]->length, - "SSDT")) { - aml_die("LOAD: Not a SSDT!\n"); - } - - /* Parse block */ - mscope = aml_xpushscope(scope, opargs[1], scope->node, - AMLOP_SCOPE); -#endif - break; - case AMLOP_UNLOAD: - /* DDBHandle */ - aml_die("Unload"); - break; - - /* Control Flow */ - case AMLOP_IF: - /* Arguments: iT or iTbT */ - if (opargs[0]->v_integer) { - dnprintf(10,"parse-if @ %.4x\n", pc); - mscope = aml_xpushscope(scope, opargs[1], scope->node, - AMLOP_IF); - } - else if (opargs[3] != NULL) { - dnprintf(10,"parse-else @ %.4x\n", pc); - mscope = aml_xpushscope(scope, opargs[3], scope->node, - AMLOP_ELSE); - } - break; - case AMLOP_WHILE: - mscope = aml_xpushscope(scope, opargs[0], scope->node, - AMLOP_WHILE); - while (mscope->pos != NULL) { - /* At beginning of scope.. reset and perform test */ - mscope->pos = mscope->start; - tmp = aml_xparse(mscope, AML_ARG_INTEGER, "While-Test"); - ival = tmp->v_integer; - aml_xdelref(&tmp, "while"); - - dnprintf(10,"@@@@@@ WHILE: %llx @ %x\n", ival, pc); - if (ival == 0) { - break; - } - aml_xparse(mscope, 'T', "While"); - } - aml_xpopscope(mscope); - mscope = NULL; - break; - case AMLOP_BREAK: - /* Break: Find While Scope parent, mark type as null */ - mscope = aml_xfindscope(scope, AMLOP_WHILE, 1); - mscope->pos = NULL; - mscope = NULL; - break; - case AMLOP_CONTINUE: - /* Find Scope.. mark all objects as invalid on way to root */ - mscope = aml_xfindscope(scope, AMLOP_WHILE, 1); - mscope->pos = mscope->start; - mscope = NULL; - break; - case AMLOP_RETURN: - mscope = aml_xfindscope(scope, AMLOP_METHOD, 1); - if (mscope->retv) { - aml_die("already allocated\n"); - } - mscope->retv = aml_allocvalue(0,0,NULL); - aml_copyvalue(mscope->retv, opargs[0]); - mscope = NULL; - break; - default: - /* may be set direct result */ - aml_die("Unknown opcode: %x:%s\n", opcode, htab->mnem); - break; - } - if (mscope != NULL) { - aml_xparse(mscope, 'T', htab->mnem); - aml_xpopscope(mscope); - } - if ((ret_type == 'i' || ret_type == 't') && my_ret == NULL) { - dnprintf(10,"quick: %.4x [%s] allocating return integer = 0x%llx\n", - pc, htab->mnem, ival); - my_ret = aml_allocvalue(AML_OBJTYPE_INTEGER, ival, NULL); - } - if (ret_type == 'i' && my_ret && my_ret->type != AML_OBJTYPE_INTEGER) { - dnprintf(10,"quick: %.4x convert to integer %s -> %s\n", - pc, htab->mnem, stype); - } - if (my_ret != NULL) { - /* Display result */ - my_ret->stack = opcode; - dnprintf(20,"quick: %.4x %18s %c %.4x\n", pc, stype, - ret_type, my_ret->stack); - } - - /* End opcode: display/free arguments */ - for (idx=0; optype[idx] != 0; idx++) { - if (opargs[idx] == my_ret || optype[idx] == 'N') - opargs[idx] = NULL; - aml_xdelref(&opargs[idx], "oparg"); - } - odp--; - - /* If parsing whole scope and not done, start again */ - if (ret_type == 'T') { - aml_xdelref(&my_ret, "scope.loop"); - if (scope->pos && scope->pos < scope->end) - goto start; - } - dnprintf(50, ">>return [%s] %s %c %p\n", aml_nodename(scope->node), - stype, ret_type, my_ret); - return my_ret; -} - -int -acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length) -{ - struct aml_scope *scope; - struct aml_value res; - - dsdt_softc = sc; - - aml_root.start = start; - memset(&res, 0, sizeof(res)); - res.type = AML_OBJTYPE_SCOPE; - res.length = length; - res.v_buffer = start; - - /* Push toplevel scope, parse AML */ - scope = aml_xpushscope(NULL, &res, &aml_root, AMLOP_SCOPE); - aml_busy++; - aml_xparse(scope, 'T', "TopLevel"); - aml_busy--; - aml_xpopscope(scope); - - return 0; -} - -/* - * @@@: External API - * - * evaluate an AML node - * Returns a copy of the value in res (must be freed by user) - */ -int -aml_evalnode(struct acpi_softc *sc, struct aml_node *node, - int argc, struct aml_value *argv, struct aml_value *res) -{ - struct aml_value *xres; - - if (node == NULL || node->value == NULL) - return (ACPI_E_BADVALUE); - if (res) - memset(res, 0, sizeof(*res)); - dnprintf(12,"EVALNODE: %s %d\n", aml_nodename(node), acpi_nalloc); - switch (node->value->type) { - case AML_OBJTYPE_INTEGER: - case AML_OBJTYPE_PACKAGE: - case AML_OBJTYPE_STRING: - case AML_OBJTYPE_BUFFER: - case AML_OBJTYPE_PROCESSOR: - case AML_OBJTYPE_THERMZONE: - case AML_OBJTYPE_POWERRSRC: - if (res) - aml_copyvalue(res, node->value); - break; - case AML_OBJTYPE_BUFFERFIELD: - case AML_OBJTYPE_FIELDUNIT: - case AML_OBJTYPE_METHOD: - aml_busy++; - xres = aml_xeval(NULL, node->value, 't', argc, argv); - aml_busy--; - if (res && xres) - aml_copyvalue(res, xres); - if (xres != node->value) - aml_xdelref(&xres, "EvalNode"); - break; - default: - return (-1); - } - return (0); -} - -/* - * evaluate an AML name - * Returns a copy of the value in res (must be freed by user) - */ -int -aml_evalname(struct acpi_softc *sc, struct aml_node *parent, const char *name, - int argc, struct aml_value *argv, struct aml_value *res) -{ - parent = aml_searchname(parent, name); - return aml_evalnode(sc, parent, argc, argv, res); -} - -/* - * evaluate an AML integer object - */ -int -aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent, - const char *name, int argc, struct aml_value *argv, int64_t *ival) -{ - struct aml_value res; - int rc; - - parent = aml_searchname(parent, name); - rc = aml_evalnode(sc, parent, argc, argv, &res); - *ival = aml_val2int(&res); - aml_freevalue(&res); - - return rc; -} - -/* - * Search for an AML name in namespace.. root only - */ -struct aml_node * -aml_searchname(struct aml_node *root, const void *vname) -{ - char *name = (char *)vname; - - dnprintf(25,"Searchname: %s:%s = ", aml_nodename(root), vname); - if (*name == AMLOP_ROOTCHAR) { - root = &aml_root; - name++; - } - while (*name != 0) { - root = __aml_search(root, name, 0); - name += (name[4] == '.') ? 5 : 4; - } - dnprintf(25,"%p %s\n", root, aml_nodename(root)); - return root; -} - -/* - * Search for relative name - */ -struct aml_node * -aml_searchrel(struct aml_node *root, const void *vname) -{ - struct aml_node *res; - - while (root) { - res = aml_searchname(root, vname); - if (res != NULL) - return res; - root = root->parent; - } - return NULL; -} diff --git a/sys/dev/acpi/dsdt.h b/sys/dev/acpi/dsdt.h index 4b2ca856c18..8149f5c7869 100644 --- a/sys/dev/acpi/dsdt.h +++ b/sys/dev/acpi/dsdt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dsdt.h,v 1.33 2008/05/14 05:24:36 jordan Exp $ */ +/* $OpenBSD: dsdt.h,v 1.34 2008/05/16 06:50:55 dlg Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -54,7 +54,6 @@ const char *aml_args(int); const char *aml_mnem(int, uint8_t *); int64_t aml_val2int(struct aml_value *); struct aml_node *aml_searchname(struct aml_node *, const void *); -struct aml_node *aml_searchrel(struct aml_node *, const void *); struct aml_node *aml_createname(struct aml_node *, const void *, struct aml_value *); |