summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/acpi/acpi.c180
-rw-r--r--sys/dev/acpi/acpiac.c8
-rw-r--r--sys/dev/acpi/acpiasus.c6
-rw-r--r--sys/dev/acpi/acpibat.c18
-rw-r--r--sys/dev/acpi/acpibtn.c10
-rw-r--r--sys/dev/acpi/acpidebug.c54
-rw-r--r--sys/dev/acpi/acpidock.c14
-rw-r--r--sys/dev/acpi/acpiec.c4
-rw-r--r--sys/dev/acpi/acpiprt.c56
-rw-r--r--sys/dev/acpi/acpithinkpad.c8
-rw-r--r--sys/dev/acpi/acpitz.c14
-rw-r--r--sys/dev/acpi/amltypes.h3
-rw-r--r--sys/dev/acpi/dsdt.c2723
-rw-r--r--sys/dev/acpi/dsdt.h3
14 files changed, 2969 insertions, 132 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index 604a06f3016..21a8b6c1060 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.116 2008/04/27 16:23:16 jcs Exp $ */
+/* $OpenBSD: acpi.c,v 1.117 2008/05/14 05:24:36 jordan Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -87,6 +87,8 @@ 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)
@@ -173,6 +175,9 @@ 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) {
@@ -192,6 +197,9 @@ 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;
}
}
@@ -266,7 +274,7 @@ acpi_inidev(struct aml_node *node, void *arg)
*/
/* Evaluate _STA to decide _INI fate and walk fate */
- if (!aml_evalname(sc, node, "_STA", 0, NULL, &res))
+ if (!aml_evalname(sc, node->parent, "_STA", 0, NULL, &res))
st = (int)aml_val2int(&res);
aml_freevalue(&res);
@@ -304,7 +312,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, "_STA", 0, NULL, &res))
+ if (!aml_evalname(sc, node->parent, "_STA", 0, NULL, &res))
st = (int)aml_val2int(&res);
aml_freevalue(&res);
@@ -612,22 +620,22 @@ acpi_attach(struct device *parent, struct device *self, void *aux)
acpi_softc = sc;
/* initialize runtime environment */
- aml_find_node(aml_root.child, "_INI", acpi_inidev, sc);
+ aml_find_node(&aml_root, "_INI", acpi_inidev, sc);
/* attach pci interrupt routing tables */
- aml_find_node(aml_root.child, "_PRT", acpi_foundprt, sc);
+ aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc);
#ifndef SMALL_KERNEL
/* XXX EC needs to be attached first on some systems */
- aml_find_node(aml_root.child, "_HID", acpi_foundec, sc);
+ aml_find_node(&aml_root, "_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.child, "_HID", acpi_foundhid, sc);
+ aml_find_node(&aml_root, "_HID", acpi_foundhid, sc);
/* attach docks */
- aml_find_node(aml_root.child, "_DCK", acpi_founddock, sc);
+ aml_find_node(&aml_root, "_DCK", acpi_founddock, sc);
/* create list of devices we want to query when APM come in */
SLIST_INIT(&sc->sc_ac);
@@ -1138,6 +1146,9 @@ 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)
{
@@ -1146,6 +1157,12 @@ 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);
@@ -1244,19 +1261,18 @@ int
acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler)
(struct acpi_softc *, int, void *), void *arg, const char *label)
{
- if (gpe >= sc->sc_lastgpe || handler == NULL)
- return -EINVAL;
+ struct gpe_block *ptbl;
- if (sc->gpe_table[gpe].handler != NULL) {
+ ptbl = acpi_find_gpe(sc, gpe);
+ if (ptbl == NULL || handler == NULL)
+ return -EINVAL;
+ if (ptbl->handler != NULL) {
dnprintf(10, "error: GPE %.2x already enabled\n", gpe);
return -EBUSY;
}
-
dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, label);
- sc->gpe_table[gpe].handler = handler;
- sc->gpe_table[gpe].arg = arg;
-
- /* Defer enabling GPEs */
+ ptbl->handler = handler;
+ ptbl->arg = arg;
return (0);
}
@@ -1341,6 +1357,112 @@ 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)
{
@@ -1348,6 +1470,12 @@ 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) {
}
@@ -1380,7 +1508,7 @@ acpi_init_gpes(struct acpi_softc *sc)
"edge");
}
}
- aml_find_node(aml_root.child, "_PRW", acpi_foundprw, sc);
+ aml_find_node(&aml_root, "_PRW", acpi_foundprw, sc);
sc->sc_maxgpe = ngpe;
}
@@ -1395,7 +1523,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.child, name, 0, NULL, &res) == 0) {
+ if (aml_evalname(sc, &aml_root, 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]);
@@ -1408,11 +1536,11 @@ acpi_init_states(struct acpi_softc *sc)
void
acpi_init_pm(struct acpi_softc *sc)
{
- 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");
+ 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");
}
void
@@ -1431,6 +1559,7 @@ 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) */
@@ -1508,6 +1637,7 @@ 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;
@@ -1541,6 +1671,8 @@ acpi_powerdown(void)
acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
}
+extern int aml_busy;
+
void
acpi_isr_thread(void *arg)
{
@@ -1585,6 +1717,8 @@ 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 4d9bcda0b49..bd349ede386 100644
--- a/sys/dev/acpi/acpiac.c
+++ b/sys/dev/acpi/acpiac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpiac.c,v 1.19 2007/11/03 22:51:21 canacar Exp $ */
+/* $OpenBSD: acpiac.c,v 1.20 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
- aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev,
+ aml_register_notify(sc->sc_devnode, 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->parent->name);
+ sc->sc_devnode->name);
switch (notify_type) {
case 0x00:
diff --git a/sys/dev/acpi/acpiasus.c b/sys/dev/acpi/acpiasus.c
index 78e23f2bc02..2d1a83d1c03 100644
--- a/sys/dev/acpi/acpiasus.c
+++ b/sys/dev/acpi/acpiasus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpiasus.c,v 1.1 2008/04/24 13:57:49 jsing Exp $ */
+/* $OpenBSD: acpiasus.c,v 1.2 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
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->parent, aa->aaa_dev,
+ aml_register_notify(sc->sc_devnode, aa->aaa_dev,
acpiasus_notify, sc, ACPIDEV_NOPOLL);
}
diff --git a/sys/dev/acpi/acpibat.c b/sys/dev/acpi/acpibat.c
index 90d01e3608d..9ba4516ab09 100644
--- a/sys/dev/acpi/acpibat.c
+++ b/sys/dev/acpi/acpibat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibat.c,v 1.46 2007/11/16 13:58:18 deraadt Exp $ */
+/* $OpenBSD: acpibat.c,v 1.47 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
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->parent->name);
+ printf(": %s", sc->sc_devnode->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->parent->name);
+ printf(": %s not present\n", sc->sc_devnode->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->parent, aa->aaa_dev,
+ aml_register_notify(sc->sc_devnode, 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->parent->name);
+ sc->sc_devnode->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->parent->name);
+ sc->sc_devnode->name);
switch (notify_type) {
case 0x80: /* _BST changed */
if (!sc->sc_bat_present) {
printf("%s: %s: inserted\n", DEVNAME(sc),
- sc->sc_devnode->parent->name);
+ sc->sc_devnode->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->parent->name);
+ sc->sc_devnode->name);
sc->sc_bat_present = 0;
}
break;
diff --git a/sys/dev/acpi/acpibtn.c b/sys/dev/acpi/acpibtn.c
index 8d7ae2fdd42..cc1e70853f3 100644
--- a/sys/dev/acpi/acpibtn.c
+++ b/sys/dev/acpi/acpibtn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibtn.c,v 1.16 2008/04/12 12:49:28 kettenis Exp $ */
+/* $OpenBSD: acpibtn.c,v 1.17 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
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->parent->name);
+ printf(": %s\n", sc->sc_devnode->name);
- aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev, acpibtn_notify,
+ aml_register_notify(sc->sc_devnode, 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->parent->name);
+ sc->sc_devnode->name);
switch (sc->sc_btn_type) {
case ACPIBTN_LID:
diff --git a/sys/dev/acpi/acpidebug.c b/sys/dev/acpi/acpidebug.c
index 0a80d43b0cd..5bcb8b86535 100644
--- a/sys/dev/acpi/acpidebug.c
+++ b/sys/dev/acpi/acpidebug.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpidebug.c,v 1.16 2007/11/12 21:58:14 deraadt Exp $ */
+/* $OpenBSD: acpidebug.c,v 1.17 2008/05/14 05:24:36 jordan 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);
-
- db_aml_showvalue(value->v_field.ref1);
- db_aml_showvalue(value->v_field.ref2);
+ 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));
break;
case AML_OBJTYPE_BUFFERFIELD:
- db_printf("%s: pos=%.4x len=%.4x ",
+ db_printf("%s: pos=%.4x len=%.4x\n",
aml_mnem(value->v_field.type, NULL),
value->v_field.bitpos,
value->v_field.bitlen);
-
- 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);
+ db_printf(" buffer: %s\n",
+ aml_nodename(value->v_field.ref1->node));
break;
case AML_OBJTYPE_OPREGION:
db_printf("opregion: %s,0x%llx,0x%x\n",
@@ -306,6 +306,24 @@ 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;
@@ -315,10 +333,24 @@ 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 4103e40fbc0..397de321206 100644
--- a/sys/dev/acpi/acpidock.c
+++ b/sys/dev/acpi/acpidock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpidock.c,v 1.27 2007/11/12 21:58:14 deraadt Exp $ */
+/* $OpenBSD: acpidock.c,v 1.28 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
- printf(": %s", sc->sc_devnode->parent->name);
+ printf(": %s", sc->sc_devnode->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->parent, aa->aaa_dev,
+ aml_register_notify(sc->sc_devnode, 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->parent->name);
+ dnprintf(15, "%s: %s", DEVNAME(sc), node->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->parent->name, res.v_string);
+ node->name, res.v_string);
/* XXX more than one dock? */
n = malloc(sizeof(struct aml_nodelist), M_DEVBUF, M_WAITOK);
- n->node = node->parent;
+ n->node = node;
TAILQ_INSERT_TAIL(&sc->sc_deps_h, n, entries);
}
diff --git a/sys/dev/acpi/acpiec.c b/sys/dev/acpi/acpiec.c
index 8f342914aa7..e505f552919 100644
--- a/sys/dev/acpi/acpiec.c
+++ b/sys/dev/acpi/acpiec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpiec.c,v 1.21 2007/12/07 19:06:02 fgsch Exp $ */
+/* $OpenBSD: acpiec.c,v 1.22 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
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 187475bb603..a6a980f6798 100644
--- a/sys/dev/acpi/acpiprt.c
+++ b/sys/dev/acpi/acpiprt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpiprt.c,v 1.20 2007/11/12 21:58:14 deraadt Exp $ */
+/* $OpenBSD: acpiprt.c,v 1.21 2008/05/14 05:24:36 jordan Exp $ */
/*
* Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org>
*
@@ -45,6 +45,7 @@ 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 {
@@ -119,6 +120,37 @@ 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;
@@ -166,8 +198,17 @@ acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v)
}
pp = v->v_package[2];
+ if (pp->type == AML_OBJTYPE_STRING) {
+ printf("STRING: %s\n", pp->v_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_searchname(sc->sc_devnode, pp->v_nameref);
+ node = aml_searchrel(sc->sc_devnode, pp->v_nameref);
if (node == NULL) {
printf("Invalid device\n");
return;
@@ -198,6 +239,16 @@ 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 (!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);
+ }
} else {
irq = aml_val2int(v->v_package[3]);
}
@@ -340,6 +391,5 @@ 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 a434bcff06b..a956d774127 100644
--- a/sys/dev/acpi/acpithinkpad.c
+++ b/sys/dev/acpi/acpithinkpad.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpithinkpad.c,v 1.2 2008/05/14 02:02:05 jcs Exp $ */
+/* $OpenBSD: acpithinkpad.c,v 1.3 2008/05/14 05:24:36 jordan Exp $ */
/*
* Copyright (c) 2008 joshua stein <jcs@openbsd.org>
@@ -112,7 +112,7 @@ 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->child,
+ if (aml_evalname((struct acpi_softc *)parent, aa->aaa_node,
"MHKV", 0, NULL, &res))
goto fail;
@@ -134,7 +134,7 @@ thinkpad_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->child;
+ sc->sc_devnode = aa->aaa_node;
printf("\n");
@@ -142,7 +142,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->parent, aa->aaa_dev,
+ aml_register_notify(sc->sc_devnode, aa->aaa_dev,
thinkpad_hotkey, sc, ACPIDEV_NOPOLL);
return;
diff --git a/sys/dev/acpi/acpitz.c b/sys/dev/acpi/acpitz.c
index 725cf65db1a..be6d35bbe41 100644
--- a/sys/dev/acpi/acpitz.c
+++ b/sys/dev/acpi/acpitz.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpitz.c,v 1.23 2008/04/12 12:49:28 kettenis Exp $ */
+/* $OpenBSD: acpitz.c,v 1.24 2008/05/14 05:24:36 jordan 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->child;
+ sc->sc_devnode = aa->aaa_node;
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->parent, NULL,
+ aml_register_notify(sc->sc_devnode, 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->parent->name);
+ sc->sc_devnode->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->parent->name);
+ sc->sc_devnode->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->parent->name, name);
+ sc->sc_devnode->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->parent->name);
+ sc->sc_devnode->name);
switch (notify_type) {
case 0x80: /* hardware notifications */
diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h
index 54fd887a99d..daa7d03fe30 100644
--- a/sys/dev/acpi/amltypes.h
+++ b/sys/dev/acpi/amltypes.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amltypes.h,v 1.26 2008/05/13 09:05:06 jordan Exp $ */
+/* $OpenBSD: amltypes.h,v 1.27 2008/05/14 05:24:36 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -275,6 +275,7 @@ 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 be6e3916367..90cd6e1524f 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: dsdt.c,v 1.109 2008/02/07 17:48:59 henning Exp $ */
+/* $OpenBSD: dsdt.c,v 1.110 2008/05/14 05:24:36 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -184,9 +184,9 @@ struct aml_opcode aml_table[] = {
{ AMLOP_ARG6, "Arg6", "A", aml_parseref },
/* Control flow */
- { AMLOP_IF, "If", "pI", aml_parseif },
+ { AMLOP_IF, "If", "piI", aml_parseif },
{ AMLOP_ELSE, "Else", "pT" },
- { AMLOP_WHILE, "While", "piT", aml_parsewhile },
+ { AMLOP_WHILE, "While", "pW", aml_parsewhile },
{ AMLOP_BREAK, "Break", "" },
{ AMLOP_CONTINUE, "Continue", "" },
{ AMLOP_RETURN, "Return", "t", aml_parseref },
@@ -234,20 +234,20 @@ struct aml_opcode aml_table[] = {
{ 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_POWERRSRC, "Power Resource", "pNbwT",aml_parsenamedscope },
{ AMLOP_THERMALZONE, "ThermalZone", "pNT", aml_parsenamedscope },
{ AMLOP_PROCESSOR, "Processor", "pNbdbT", aml_parsenamedscope },
- { AMLOP_METHOD, "Method", "pNfM", aml_parsemethod },
+ { AMLOP_METHOD, "Method", "pNbM", aml_parsemethod },
/* Field operations */
- { AMLOP_FIELD, "Field", "pnfF", aml_parsefieldunit },
- { AMLOP_INDEXFIELD, "IndexField", "pntfF", aml_parsefieldunit },
- { AMLOP_BANKFIELD, "BankField", "pnnifF", aml_parsefieldunit },
+ { AMLOP_FIELD, "Field", "pnbF", aml_parsefieldunit },
+ { AMLOP_INDEXFIELD, "IndexField", "pnnbF",aml_parsefieldunit },
+ { AMLOP_BANKFIELD, "BankField", "pnnibF",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_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 */
@@ -255,36 +255,36 @@ struct aml_opcode aml_table[] = {
{ AMLOP_TOBUFFER, "ToBuffer", "tr", },
{ AMLOP_TODECSTRING, "ToDecString", "ir", aml_parsestring },
{ AMLOP_TOHEXSTRING, "ToHexString", "ir", aml_parsestring },
- { AMLOP_TOSTRING, "ToString", "t", aml_parsestring },
+ { AMLOP_TOSTRING, "ToString", "tir", 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", "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_ACQUIRE, "Acquire", "Sw", aml_parsemuxaction },
+ { AMLOP_RELEASE, "Release", "S", aml_parsemuxaction },
+ { AMLOP_SIGNAL, "Signal", "S", aml_parsemuxaction },
+ { AMLOP_WAIT, "Wait", "Si", aml_parsemuxaction },
+ { AMLOP_RESET, "Reset", "S", aml_parsemuxaction },
{ 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_REFOF, "RefOf", "S", aml_parseref },
+ { AMLOP_CONDREFOF, "CondRef", "SS", aml_parseref },
{ AMLOP_LOADTABLE, "LoadTable", "tttttt" },
{ AMLOP_STALL, "Stall", "i", aml_parsemisc2 },
{ AMLOP_SLEEP, "Sleep", "i", aml_parsemisc2 },
- { AMLOP_LOAD, "Load", "nt", aml_parseref },
+ { AMLOP_LOAD, "Load", "nS", aml_parseref },
{ AMLOP_UNLOAD, "Unload", "t" },
- { AMLOP_STORE, "Store", "tr", aml_parseref },
+ { AMLOP_STORE, "Store", "tS", aml_parseref },
{ AMLOP_CONCAT, "Concat", "ttr", aml_parsestring },
{ AMLOP_CONCATRES, "ConcatRes", "ttt" },
- { AMLOP_NOTIFY, "Notify", "ti", aml_parsemisc2 },
- { AMLOP_SIZEOF, "Sizeof", "t", aml_parsemisc3 },
+ { AMLOP_NOTIFY, "Notify", "Si", aml_parsemisc2 },
+ { AMLOP_SIZEOF, "Sizeof", "S", aml_parsemisc3 },
{ AMLOP_MATCH, "Match", "tbibii", aml_parsematch },
- { AMLOP_OBJECTTYPE, "ObjectType", "t", aml_parsemisc3 },
- { AMLOP_COPYOBJECT, "CopyObject", "tr", aml_parseref },
+ { AMLOP_OBJECTTYPE, "ObjectType", "S", aml_parsemisc3 },
+ { AMLOP_COPYOBJECT, "CopyObject", "tS", aml_parseref },
};
int aml_pc(uint8_t *src)
@@ -668,21 +668,40 @@ void acpi_poll_notify(void)
* @@@: Namespace functions
*/
-struct aml_node *__aml_search(struct aml_node *, uint8_t *);
+struct aml_node *__aml_search(struct aml_node *, uint8_t *, int);
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)
+__aml_search(struct aml_node *root, uint8_t *nameseg, int create)
{
+ struct aml_node **sp, *node;
+
+ /* XXX: Replace with SLIST/SIMPLEQ routines */
if (root == NULL)
return NULL;
- for (root = root->child; root; root = root->sibling) {
- if (!memcmp(root->name, nameseg, AML_NAMESEG_LEN))
- return root;
+ //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;
}
- return NULL;
+ }
+ //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;
}
/* Get absolute pathname of AML node */
@@ -772,7 +791,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)) == NULL) {
+ if ((node = __aml_search(root, name, 0)) == NULL) {
node = acpi_os_malloc(sizeof(struct aml_node));
memcpy((void *)node->name, name, AML_NAMESEG_LEN);
@@ -794,6 +813,7 @@ aml_createname(struct aml_node *root, const void *vname, struct aml_value *value
}
/* Search namespace for a named node */
+#if 0
struct aml_node *
aml_searchname(struct aml_node *root, const void *vname)
{
@@ -826,23 +846,24 @@ aml_searchname(struct aml_node *root, const void *vname)
default:
if (name[4] == '.') {
/* Called from user code */
- while (*name && (root = __aml_search(root, name)) != NULL) {
+ while (*name && (root = __aml_search(root, name, 0)) != NULL) {
name += AML_NAMESEG_LEN+1;
}
return root;
}
/* Special case.. search relative for name */
- while (root && (node = __aml_search(root, name)) == NULL) {
+ while (root && (node = __aml_search(root, name, 0)) == NULL) {
root = root->parent;
}
return node;
}
/* Search absolute for name*/
- while (count-- && (root = __aml_search(root, name)) != NULL) {
+ while (count-- && (root = __aml_search(root, name, 0)) != NULL) {
name += AML_NAMESEG_LEN;
}
return root;
}
+#endif
/* Free all children nodes/values */
void
@@ -1034,7 +1055,8 @@ aml_getbufint(struct aml_value *src, int bitpos, int bitlen,
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)
{
@@ -1963,7 +1985,7 @@ aml_evalexpr(int64_t lhs, int64_t rhs, int opcode)
break;
}
- dnprintf(50,"aml_evalexpr: %s %llx %llx = %llx\n",
+ dnprintf(15,"aml_evalexpr: %s %llx %llx = %llx\n",
aml_mnem(opcode, NULL), lhs, rhs, res);
return res;
@@ -2082,6 +2104,7 @@ aml_evalmethod(struct aml_scope *parent, struct aml_node *node,
* evaluate an AML node
* Returns a copy of the value in res (must be freed by user)
*/
+#if 0
int
aml_evalnode(struct acpi_softc *sc, struct aml_node *node,
int argc, struct aml_value *argv, struct aml_value *res)
@@ -2160,6 +2183,7 @@ aml_evalinteger(struct acpi_softc *sc, struct aml_node *parent,
}
return 1;
}
+#endif
void
aml_walknodes(struct aml_node *node, int mode,
@@ -3401,23 +3425,16 @@ char *aml_valid_osi[] = {
struct aml_value *
aml_callosi(struct aml_scope *scope, struct aml_value *val)
{
- 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);
+ int idx, result=0;
+ struct aml_value *fa;
+ fa = scope->args[0].v_objref.ref;
for (idx=0; !result && aml_valid_osi[idx] != NULL; idx++) {
- tmpstr.v_string = aml_valid_osi[idx];
- tmpstr.length = strlen(tmpstr.v_string);
-
- result = aml_cmpvalue(arg, &tmpstr, AMLOP_LEQUAL);
+ dnprintf(10,"osi: %s,%s\n", fa->v_string, aml_valid_osi[idx]);
+ result = !strcmp(fa->v_string, aml_valid_osi[idx]);
}
- aml_setvalue(scope, val, NULL, result);
- return val;
+ dnprintf(10,"@@ OSI found: %x\n", result);
+ return aml_allocvalue(AML_OBJTYPE_INTEGER, result, NULL);
}
void
@@ -3431,6 +3448,10 @@ 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);
@@ -3554,6 +3575,7 @@ 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)
{
@@ -3572,6 +3594,7 @@ 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
@@ -3644,3 +3667,2599 @@ 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;
+}
+
+/* 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);
+ }
+ }
+}
+
+/* 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) {
+ aml_showvalue(a, 0);
+ 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) {
+ aml_showvalue(fld, 0);
+ aml_showvalue(buf, 0);
+ 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) {
+ aml_showvalue(my_ret, 8-100);
+ 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 (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) {
+ aml_showvalue(opargs[0], 0);
+ 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);
+ 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);
+
+ /* Pass object off to Eval Function */
+ xres = aml_xeval(NULL, node->value, 't', argc, argv);
+ aml_copyvalue(res, xres);
+ if (xres != node->value)
+ aml_xdelref(&xres, "EvalNode");
+
+ 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 5ec041f0d8f..4b2ca856c18 100644
--- a/sys/dev/acpi/dsdt.h
+++ b/sys/dev/acpi/dsdt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.h,v 1.32 2008/05/13 09:05:06 jordan Exp $ */
+/* $OpenBSD: dsdt.h,v 1.33 2008/05/14 05:24:36 jordan Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -54,6 +54,7 @@ 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 *);