summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2000-08-31 14:45:00 +0000
committeriwasaki <iwasaki@FreeBSD.org>2000-08-31 14:45:00 +0000
commitd15e4891fc346c4a9751e132de24131b232866c5 (patch)
tree6c3a121b0e0ac7e29335c6f9d29a0ec38f388f9b /usr.sbin
parent960c7c47e2358093ca0eb7f3a30bb6e0599d0b74 (diff)
parent53d00480b62ab9201d60e57cc253edf29995e51b (diff)
downloadFreeBSD-src-d15e4891fc346c4a9751e132de24131b232866c5.zip
FreeBSD-src-d15e4891fc346c4a9751e132de24131b232866c5.tar.gz
This commit was generated by cvs2svn to compensate for changes in r65287,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/acpi/amldb/Makefile13
-rw-r--r--usr.sbin/acpi/amldb/amldb.c188
-rw-r--r--usr.sbin/acpi/amldb/debug.c311
-rw-r--r--usr.sbin/acpi/amldb/debug.h36
-rw-r--r--usr.sbin/acpi/amldb/region.c538
5 files changed, 1086 insertions, 0 deletions
diff --git a/usr.sbin/acpi/amldb/Makefile b/usr.sbin/acpi/amldb/Makefile
new file mode 100644
index 0000000..e683e1c
--- /dev/null
+++ b/usr.sbin/acpi/amldb/Makefile
@@ -0,0 +1,13 @@
+# $Id: Makefile,v 1.5 2000/07/14 18:16:30 iwasaki Exp $
+# $FreeBSD$
+
+PROG= amldb
+SRCS= amldb.c debug.c region.c
+SRCS+= aml_parse.c aml_name.c aml_amlmem.c aml_memman.c aml_store.c aml_obj.c aml_evalobj.c aml_common.c
+NOMAN= yes
+#MAN8= amldb.8
+#DEBUG_FLAGS= -g
+CFLAGS+= -I${.CURDIR}/../../../sys -I${.CURDIR}
+
+.include <bsd.prog.mk>
+.PATH: ${.CURDIR}/../../../sys/dev/acpi/aml
diff --git a/usr.sbin/acpi/amldb/amldb.c b/usr.sbin/acpi/amldb/amldb.c
new file mode 100644
index 0000000..007a1ab
--- /dev/null
+++ b/usr.sbin/acpi/amldb/amldb.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 1999 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: amldb.c,v 1.8 2000/08/08 14:12:24 iwasaki Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <dev/acpi/aml/aml_amlmem.h>
+#include <dev/acpi/aml/aml_common.h>
+#include <dev/acpi/aml/aml_env.h>
+#include <dev/acpi/aml/aml_parse.h>
+#include <dev/acpi/aml/aml_region.h>
+
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+int regdump_enabled = 0;
+int memstat_enabled = 0;
+int showtree_enabled = 0;
+
+static void aml_init_namespace();
+
+void
+aml_init_namespace()
+{
+ struct aml_environ env;
+ struct aml_name *newname;
+
+ aml_new_name_group(AML_NAME_GROUP_OS_DEFINED);
+ env.curname = aml_get_rootname();
+ newname = aml_create_name(&env, "\\_OS_");
+ newname->property = aml_alloc_object(aml_t_string, NULL);
+ newname->property->str.needfree = 0;
+ newname->property->str.string = "Microsoft Windows NT";
+}
+
+static int
+load_dsdt(const char *dsdtfile)
+{
+ struct aml_environ env;
+ u_int8_t *code;
+ struct stat sb;
+ int fd;
+
+ printf("Loading %s...", dsdtfile);
+
+ fd = open(dsdtfile, O_RDONLY, 0);
+ if (fd == -1) {
+ perror("open");
+ exit(-1);
+ }
+ if (fstat(fd, &sb) == -1) {
+ perror("fstat");
+ exit(-1);
+ }
+ if ((code = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == NULL) {
+ perror("mmap");
+ exit(-1);
+ }
+ aml_init_namespace();
+
+ aml_new_name_group((int)code);
+ bzero(&env, sizeof(env));
+
+ /*
+ * Microsoft asl.exe generates 0x23 byte additional info.
+ * at the begining of the file, so just ignore it.
+ */
+ if (strncmp(code, "DSDT", 4) == 0) {
+ env.dp = code + 0x23;
+ } else {
+ env.dp = code;
+ }
+ env.end = code + sb.st_size;
+ env.curname = aml_get_rootname();
+
+ aml_local_stack_push(aml_local_stack_create());
+ aml_parse_objectlist(&env, 0);
+ aml_local_stack_delete(aml_local_stack_pop());
+
+ assert(env.dp == env.end);
+ env.dp = code;
+ env.end = code + sb.st_size;
+
+ printf("done\n");
+
+ aml_debug = 1; /* debug print enabled */
+
+ if (showtree_enabled == 1) {
+ aml_showtree(env.curname, 0);
+ }
+ do {
+ aml_dbgr(&env, &env);
+ } while (env.stat != aml_stat_panic);
+
+ aml_debug = 0; /* debug print disabled */
+
+ if (regdump_enabled == 1) {
+ aml_simulation_regdump("region.dmp");
+ }
+ while (name_group_list->id != AML_NAME_GROUP_ROOT) {
+ aml_delete_name_group(name_group_list);
+ }
+
+ if (memstat_enabled == 1) {
+ memman_statistics(aml_memman);
+ }
+ memman_freeall(aml_memman);
+
+ return (0);
+}
+
+static void
+usage(const char *progname)
+{
+
+ printf("usage: %s [-d] [-s] [-t] [-h] dsdt_files...\n", progname);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char c, *progname;
+ int i;
+
+ progname = argv[0];
+ while ((c = getopt(argc, argv, "dsth")) != -1) {
+ switch (c) {
+ case 'd':
+ regdump_enabled = 1;
+ break;
+ case 's':
+ memstat_enabled = 1;
+ break;
+ case 't':
+ showtree_enabled = 1;
+ break;
+ case 'h':
+ default:
+ usage(progname);
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ usage(progname);
+ }
+ for (i = 0; i < argc; i++) {
+ load_dsdt(argv[i]);
+ }
+
+ return (0);
+}
diff --git a/usr.sbin/acpi/amldb/debug.c b/usr.sbin/acpi/amldb/debug.c
new file mode 100644
index 0000000..794c3d6
--- /dev/null
+++ b/usr.sbin/acpi/amldb/debug.c
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 1999 Takanori Watanabe
+ * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: debug.c,v 1.19 2000/08/16 18:15:00 iwasaki Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/acpi.h>
+
+#include <dev/acpi/aml/aml_name.h>
+#include <dev/acpi/aml/aml_amlmem.h>
+#include <dev/acpi/aml/aml_status.h>
+#include <dev/acpi/aml/aml_env.h>
+#include <dev/acpi/aml/aml_obj.h>
+#include <dev/acpi/aml/aml_evalobj.h>
+#include <dev/acpi/aml/aml_parse.h>
+#include <dev/acpi/aml/aml_region.h>
+#include <dev/acpi/aml/aml_store.h>
+#include <dev/acpi/aml/aml_common.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+static int
+print_named_object(struct aml_name *name, va_list ap)
+{
+
+ aml_print_curname(name);
+ printf("\n");
+
+ return (0); /* always return success to continue the search */
+}
+
+void
+aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
+{
+#define CMDBUFLEN 512
+#define ARGBUFLEN 512
+ static char lastcommand[CMDBUFLEN];
+ char commandline[CMDBUFLEN];
+ char argbuf[7][ARGBUFLEN];
+ char *ptr, *method;
+ char *np, *ep;
+ int i;
+ int argnum;
+ struct aml_name *name;
+ union aml_object argv[7], *retval;
+
+ while (1) {
+ fputs("AML>", stderr);
+ fgets(commandline, 512, stdin);
+ commandline[512 - 1] = '\n'; /* safety */
+ if (feof(stdin)) {
+ commandline[0] = 'q';
+ }
+ if (commandline[0] == '\n') {
+ memcpy(commandline, lastcommand, sizeof commandline);
+ }
+ memcpy(lastcommand, commandline, sizeof commandline);
+ switch (commandline[0]) {
+ case 's':
+ if (env2 != NULL) {
+ env2->stat = aml_stat_step;
+ }
+ /* FALLTHROUGH */
+ case 'n':
+ env1->stat = aml_stat_step;
+ return;
+ case 'c':
+ env1->stat = aml_stat_none;
+ return;
+ case 'q':
+ env1->stat = aml_stat_panic;
+ return;
+ case 't':
+ /* NULL terminate */
+ ptr = &commandline[1];
+ while (ptr[0] != '\n')
+ ptr++;
+ ptr[0] = '\0';
+
+ /* move pointer to object name */
+ ptr = &commandline[1];
+ while (ptr[0] == ' ')
+ ptr++;
+
+ /* show current tree if no argument */
+ if (ptr[0] == '\0') {
+ aml_showtree(env1->curname, 0);
+ goto show_variables;
+ }
+ /* start from root? */
+ if (ptr[0] == '\\') {
+ if (ptr[1] == '\0') {
+ aml_showtree(aml_get_rootname(), 0);
+ goto show_variables;
+ }
+ if ((name = aml_find_from_namespace(aml_get_rootname(), ptr))) {
+ aml_showtree(name, 0);
+ goto show_variables;
+ }
+ }
+ if ((name = aml_find_from_namespace(env1->curname, ptr))) {
+ aml_showtree(name, 0);
+ }
+show_variables:
+ for (i = 0; i < 7; i++) {
+ struct aml_name *tmp =
+ aml_local_stack_getArgX(NULL, i);
+
+ if (tmp == NULL || tmp->property == NULL) {
+ break;
+ }
+ printf(" Arg%d ", i);
+ aml_showobject(tmp->property);
+ }
+ for (i = 0; i < 8; i++) {
+ struct aml_name *tmp =
+ aml_local_stack_getLocalX(i);
+
+ if (tmp == NULL || tmp->property == NULL) {
+ continue;
+ }
+ printf(" Local%d ", i);
+ aml_showobject(tmp->property);
+ }
+ break;
+ case 'i':
+ aml_debug_prompt_reginput =
+ (aml_debug_prompt_reginput == 0) ? 1 : 0;
+ if (aml_debug_prompt_reginput)
+ fputs("REGION INPUT ON\n", stderr);
+ else
+ fputs("REGION INPUT OFF\n", stderr);
+ break;
+ case 'o':
+ aml_debug_prompt_regoutput =
+ (aml_debug_prompt_regoutput == 0) ? 1 : 0;
+ if (aml_debug_prompt_regoutput)
+ fputs("REGION OUTPUT ON\n", stderr);
+ else
+ fputs("REGION OUTPUT OFF\n", stderr);
+ break;
+ case 'm':
+ memman_statistics(aml_memman);
+ break;
+ case 'r':
+ /* NULL terminate */
+ ptr = &commandline[1];
+ while (ptr[0] != '\n')
+ ptr++;
+ ptr[0] = '\0';
+
+ /* move pointer to method name */
+ ptr = &commandline[1];
+ while (ptr[0] == ' ')
+ ptr++;
+
+ if (ptr[0] == '\0') {
+ break;
+ }
+ name = aml_find_from_namespace(aml_get_rootname(), ptr);
+ if (name == NULL) {
+ printf("%s:%d:aml_dbgr: not found name %s\n",
+ __FILE__, __LINE__, ptr);
+ break;
+ }
+ if (name->property == NULL ||
+ name->property->type != aml_t_method) {
+ printf("%s:%d:aml_dbgr: not method %s\n",
+ __FILE__, __LINE__, ptr);
+ break;
+ }
+ aml_showobject(name->property);
+ method = ptr;
+
+ argnum = name->property->meth.argnum & 0x07;
+ if (argnum) {
+ fputs(" Enter argument values "
+ "(ex. number 1 / string foo). "
+ "'q' to quit.\n", stderr);
+ }
+ /* get and parse argument values */
+ for (i = 0; i < argnum; i++) {
+retry:
+ fprintf(stderr, " Arg%d ? ", i);
+ if (read(0, argbuf[i], ARGBUFLEN) == 0) {
+ fputs("\n", stderr);
+ goto retry;
+ }
+ argbuf[i][ARGBUFLEN - 1] = '\n';
+ if (argbuf[i][0] == 'q') {
+ goto finish_execution;
+ }
+ if (argbuf[i][0] == '\n') {
+ goto retry;
+ }
+ /* move pointer to the value */
+ ptr = &argbuf[i][0];
+ while (ptr[0] != ' ' && ptr[0] != '\n') {
+ ptr++;
+ }
+ while (ptr[0] == ' ') {
+ ptr++;
+ }
+ if (ptr[0] == '\n') {
+ goto retry;
+ }
+ switch (argbuf[i][0]) {
+ case 'n':
+ argv[i].type = aml_t_num;
+ np = ptr;
+ if (ptr[0] == '0' &&
+ ptr[1] == 'x') {
+ argv[i].num.number = strtoq(ptr, &ep, 16);
+ } else {
+ argv[i].num.number = strtoq(ptr, &ep, 10);
+ }
+ if (np == ep) {
+ fputs("Wrong value for number.\n",
+ stderr);
+ goto retry;
+ }
+ break;
+ case 's':
+ argv[i].type = aml_t_string;
+ argv[i].str.needfree = 0;
+ argv[i].str.string = ptr;
+ /* NULL ternimate */
+ while (ptr[0] != '\n') {
+ ptr++;
+ }
+ ptr[0] = '\0';
+ break;
+ default:
+ fputs("Invalid data type "
+ "(supports number or string only)\n",
+ stderr);
+ goto retry;
+ }
+ }
+ bzero(lastcommand, sizeof lastcommand);
+ fprintf(stderr, "==== Running %s. ====\n", method);
+ aml_local_stack_push(aml_local_stack_create());
+ retval = aml_invoke_method_by_name(method, argnum, argv);
+ aml_showobject(retval);
+ aml_local_stack_delete(aml_local_stack_pop());
+ fprintf(stderr, "==== %s finished. ====\n", method);
+finish_execution:
+ break;
+ case 'f':
+ /* NULL terminate */
+ ptr = &commandline[1];
+ while (ptr[0] != '\n')
+ ptr++;
+ ptr[0] = '\0';
+
+ /* move pointer to object name */
+ ptr = &commandline[1];
+ while (ptr[0] == ' ')
+ ptr++;
+
+ aml_apply_foreach_found_objects(aml_get_rootname(),
+ ptr, print_named_object);
+ break;
+ case 'h':
+ fputs("s Single step\n"
+ "n Step program\n"
+ "c Continue program being debugged\n"
+ "q Quit method execution\n"
+ "t Show local name space tree and variables\n"
+ "i Toggle region input prompt\n"
+ "o Toggle region output prompt\n"
+ "m Show memory management statistics\n"
+ "r Run specified method\n"
+ "f Find named objects from namespace.\n"
+ "h Show this messsage\n", stderr);
+ break;
+ }
+ }
+}
diff --git a/usr.sbin/acpi/amldb/debug.h b/usr.sbin/acpi/amldb/debug.h
new file mode 100644
index 0000000..3e84efa
--- /dev/null
+++ b/usr.sbin/acpi/amldb/debug.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1999 Takanori Watanabe
+ * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: debug.h,v 1.8 2000/08/09 14:47:57 iwasaki Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+void aml_dbgr(struct aml_environ *, struct aml_environ *);
+
+#endif /* !_DEBUG_H_ */
diff --git a/usr.sbin/acpi/amldb/region.c b/usr.sbin/acpi/amldb/region.c
new file mode 100644
index 0000000..94a5d79
--- /dev/null
+++ b/usr.sbin/acpi/amldb/region.c
@@ -0,0 +1,538 @@
+/*-
+ * Copyright (c) 1999 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: region.c,v 1.14 2000/08/08 14:12:25 iwasaki Exp $
+ * $FreeBSD$
+ */
+
+/*
+ * Region I/O subroutine
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <dev/acpi/aml/aml_amlmem.h>
+#include <dev/acpi/aml/aml_name.h>
+#include <dev/acpi/aml/aml_common.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+int aml_debug_prompt_regoutput = 0;
+int aml_debug_prompt_reginput = 1;
+
+static void aml_simulation_regload(const char *dumpfile);
+
+struct ACPIRegionContent {
+ TAILQ_ENTRY(ACPIRegionContent) links;
+ int regtype;
+ u_int32_t addr;
+ u_int8_t value;
+};
+
+TAILQ_HEAD(ACPIRegionContentList, ACPIRegionContent);
+struct ACPIRegionContentList RegionContentList;
+
+static int aml_simulation_initialized = 0;
+
+static void
+aml_simulation_init()
+{
+
+ aml_simulation_initialized = 1;
+ TAILQ_INIT(&RegionContentList);
+ aml_simulation_regload("region.ini");
+}
+
+static int
+aml_simulate_regcontent_add(int regtype, u_int32_t addr, u_int8_t value)
+{
+ struct ACPIRegionContent *rc;
+
+ rc = malloc(sizeof(struct ACPIRegionContent));
+ if (rc == NULL) {
+ return (-1); /* malloc fail */
+ }
+ rc->regtype = regtype;
+ rc->addr = addr;
+ rc->value = value;
+
+ TAILQ_INSERT_TAIL(&RegionContentList, rc, links);
+ return (0);
+}
+
+static int
+aml_simulate_regcontent_read(int regtype, u_int32_t addr, u_int8_t *valuep)
+{
+ struct ACPIRegionContent *rc;
+
+ if (!aml_simulation_initialized) {
+ aml_simulation_init();
+ }
+ TAILQ_FOREACH(rc, &RegionContentList, links) {
+ if (rc->regtype == regtype && rc->addr == addr) {
+ *valuep = rc->value;
+ return (1); /* found */
+ }
+ }
+
+ return (aml_simulate_regcontent_add(regtype, addr, 0));
+}
+
+static int
+aml_simulate_regcontent_write(int regtype, u_int32_t addr, u_int8_t *valuep)
+{
+ struct ACPIRegionContent *rc;
+
+ if (!aml_simulation_initialized) {
+ aml_simulation_init();
+ }
+ TAILQ_FOREACH(rc, &RegionContentList, links) {
+ if (rc->regtype == regtype && rc->addr == addr) {
+ rc->value = *valuep;
+ return (1); /* exists */
+ }
+ }
+
+ return (aml_simulate_regcontent_add(regtype, addr, *valuep));
+}
+
+static u_int32_t
+aml_simulate_prompt(char *msg, u_int32_t def_val)
+{
+ char buf[16], *ep;
+ u_int32_t val;
+
+ val = def_val;
+ printf("DEBUG");
+ if (msg != NULL) {
+ printf("%s", msg);
+ }
+ printf("(default: 0x%x / %u) >>", val, val);
+ fflush(stdout);
+
+ bzero(buf, sizeof buf);
+ while (1) {
+ if (read(0, buf, sizeof buf) == 0) {
+ continue;
+ }
+ if (buf[0] == '\n') {
+ break; /* use default value */
+ }
+ if (buf[0] == '0' && buf[1] == 'x') {
+ val = strtoq(buf, &ep, 16);
+ } else {
+ val = strtoq(buf, &ep, 10);
+ }
+ break;
+ }
+ return (val);
+}
+
+static void
+aml_simulation_regload(const char *dumpfile)
+{
+ char buf[256], *np, *ep;
+ struct ACPIRegionContent rc;
+ FILE *fp;
+
+ if (!aml_simulation_initialized) {
+ return;
+ }
+ if ((fp = fopen(dumpfile, "r")) == NULL) {
+ warn(dumpfile);
+ return;
+ }
+ while (fgets(buf, sizeof buf, fp) != NULL) {
+ np = buf;
+ /* reading region type */
+ rc.regtype = strtoq(np, &ep, 10);
+ if (np == ep) {
+ continue;
+ }
+ np = ep;
+
+ /* reading address */
+ rc.addr = strtoq(np, &ep, 16);
+ if (np == ep) {
+ continue;
+ }
+ np = ep;
+
+ /* reading value */
+ rc.value = strtoq(np, &ep, 16);
+ if (np == ep) {
+ continue;
+ }
+ aml_simulate_regcontent_write(rc.regtype, rc.addr, &rc.value);
+ }
+
+ fclose(fp);
+}
+
+#define ACPI_REGION_INPUT 0
+#define ACPI_REGION_OUTPUT 1
+
+static int
+aml_simulate_region_io(int io, int regtype, u_int32_t flags, u_int32_t *valuep,
+ u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen, int prompt)
+{
+ char buf[64];
+ u_int8_t val, tmp, masklow, maskhigh;
+ u_int8_t offsetlow, offsethigh;
+ u_int32_t addr, byteoffset, bytelen;
+ int value, readval;
+ int state, i;
+
+ value = *valuep;
+ val = readval = 0;
+ masklow = maskhigh = 0xff;
+ state = 0;
+
+ byteoffset = bitoffset / 8;
+ bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
+ addr = baseaddr + byteoffset;
+ offsetlow = bitoffset % 8;
+ if (bytelen > 1) {
+ offsethigh = (bitlen - (8 - offsetlow)) % 8;
+ } else {
+ offsethigh = 0;
+ }
+
+ if (offsetlow) {
+ masklow = (~((1 << bitlen) - 1) << offsetlow) | \
+ ~(0xff << offsetlow);
+ printf("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n",
+ offsetlow, masklow, ~masklow & 0xff);
+ }
+ if (offsethigh) {
+ maskhigh = 0xff << offsethigh;
+ printf("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n",
+ offsethigh, maskhigh, ~maskhigh & 0xff);
+ }
+ for (i = bytelen; i > 0; i--, addr++) {
+ val = 0;
+ state = aml_simulate_regcontent_read(regtype, addr, &val);
+ if (state == -1) {
+ goto finish;
+ }
+ printf("\t[%d:0x%02x@0x%x]", regtype, val, addr);
+
+ switch (io) {
+ case ACPI_REGION_INPUT:
+ tmp = val;
+ /* the lowest byte? */
+ if (i == bytelen) {
+ if (offsetlow) {
+ readval = tmp & ~masklow;
+ } else {
+ readval = tmp;
+ }
+ } else {
+ if (i == 1 && offsethigh) {
+ tmp = tmp & ~maskhigh;
+ }
+ readval = (tmp << (8 * (bytelen - i))) | readval;
+ }
+
+ printf("\n");
+ /* goto to next byte... */
+ if (i > 1) {
+ continue;
+ }
+ /* final adjustment before finishing region access */
+ if (offsetlow) {
+ readval = readval >> offsetlow;
+ }
+ sprintf(buf, "[read(%d, 0x%x)&mask:0x%x]",
+ regtype, addr, readval);
+ if (prompt) {
+ value = aml_simulate_prompt(buf, readval);
+ if (readval != value) {
+ state = aml_simulate_region_io(ACPI_REGION_OUTPUT,
+ regtype, flags, &value, baseaddr,
+ bitoffset, bitlen, 0);
+ if (state == -1) {
+ goto finish;
+ }
+ }
+ } else {
+ printf("\t%s\n", buf);
+ value = readval;
+ }
+ *valuep = value;
+
+ break;
+ case ACPI_REGION_OUTPUT:
+ tmp = value & 0xff;
+ /* the lowest byte? */
+ if (i == bytelen) {
+ if (offsetlow) {
+ tmp = (val & masklow) | tmp << offsetlow;
+ }
+ value = value >> (8 - offsetlow);
+ } else {
+ if (i == 1 && offsethigh) {
+ tmp = (val & maskhigh) | tmp;
+ }
+ value = value >> 8;
+ }
+
+ if (prompt) {
+ printf("\n");
+ sprintf(buf, "[write(%d, 0x%02x, 0x%x)]",
+ regtype, tmp, addr);
+ val = aml_simulate_prompt(buf, tmp);
+ } else {
+ printf("->[%d:0x%02x@0x%x]\n",
+ regtype, tmp, addr);
+ val = tmp;
+ }
+ state = aml_simulate_regcontent_write(regtype,
+ addr, &val);
+ if (state == -1) {
+ goto finish;
+ }
+ break;
+ }
+ }
+finish:
+ return (state);
+}
+
+static int
+aml_simulate_region_io_buffer(int io, int regtype, u_int32_t flags,
+ u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen)
+{
+ u_int8_t val;
+ u_int8_t offsetlow, offsethigh;
+ u_int32_t addr, byteoffset, bytelen;
+ int state, i;
+
+ val = 0;
+ offsetlow = offsethigh = 0;
+ state = 0;
+
+ byteoffset = bitoffset / 8;
+ bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
+ addr = baseaddr + byteoffset;
+ offsetlow = bitoffset % 8;
+ assert(offsetlow == 0);
+
+ if (bytelen > 1) {
+ offsethigh = (bitlen - (8 - offsetlow)) % 8;
+ }
+ assert(offsethigh == 0);
+
+ for (i = bytelen; i > 0; i--, addr++) {
+ switch (io) {
+ case ACPI_REGION_INPUT:
+ val = 0;
+ state = aml_simulate_regcontent_read(regtype, addr, &val);
+ if (state == -1) {
+ goto finish;
+ }
+ buffer[bytelen - i] = val;
+ break;
+ case ACPI_REGION_OUTPUT:
+ val = buffer[bytelen - i];
+ state = aml_simulate_regcontent_write(regtype,
+ addr, &val);
+ if (state == -1) {
+ goto finish;
+ }
+ break;
+ }
+ }
+finish:
+ return (state);
+}
+
+static u_int32_t
+aml_simulate_region_read(int regtype, u_int32_t flags, u_int32_t addr,
+ u_int32_t bitoffset, u_int32_t bitlen)
+{
+ int value;
+ int state;
+
+ AML_DEBUGPRINT("\n[aml_region_read(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
+ regtype, flags, addr, bitoffset, bitlen);
+ state = aml_simulate_region_io(ACPI_REGION_INPUT, regtype, flags, &value,
+ addr, bitoffset, bitlen, aml_debug_prompt_reginput);
+ assert(state != -1);
+ return (value);
+}
+
+int
+aml_simulate_region_read_into_buffer(int regtype, u_int32_t flags,
+ u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen, u_int8_t *buffer)
+{
+ int state;
+
+ AML_DEBUGPRINT("\n[aml_region_read_into_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
+ regtype, flags, addr, bitoffset, bitlen);
+ state = aml_simulate_region_io_buffer(ACPI_REGION_INPUT, regtype, flags,
+ buffer, addr, bitoffset, bitlen);
+ assert(state != -1);
+ return (state);
+}
+
+int
+aml_simulate_region_write(int regtype, u_int32_t flags, u_int32_t value,
+ u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
+{
+ int state;
+
+ AML_DEBUGPRINT("\n[aml_region_write(%d, %d, 0x%x, 0x%x, 0x%x, 0x%x)]\n",
+ regtype, flags, value, addr, bitoffset, bitlen);
+ state = aml_simulate_region_io(ACPI_REGION_OUTPUT, regtype, flags,
+ &value, addr, bitoffset, bitlen, aml_debug_prompt_regoutput);
+ assert(state != -1);
+ return (state);
+}
+
+int
+aml_simulate_region_write_from_buffer(int regtype, u_int32_t flags,
+ u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
+{
+ int state;
+
+ AML_DEBUGPRINT("\n[aml_region_write_from_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
+ regtype, flags, addr, bitoffset, bitlen);
+ state = aml_simulate_region_io_buffer(ACPI_REGION_OUTPUT, regtype,
+ flags, buffer, addr, bitoffset, bitlen);
+ assert(state != -1);
+ return (state);
+}
+
+int
+aml_simulate_region_bcopy(int regtype, u_int32_t flags, u_int32_t addr,
+ u_int32_t bitoffset, u_int32_t bitlen,
+ u_int32_t dflags, u_int32_t daddr,
+ u_int32_t dbitoffset, u_int32_t dbitlen)
+{
+ u_int32_t len, i;
+ u_int32_t value;
+ int state;
+
+ AML_DEBUGPRINT("\n[aml_region_bcopy(%d, %d, 0x%x, 0x%x, 0x%x, %d, 0x%x, 0x%x, 0x%x)]\n",
+ regtype, flags, addr, bitoffset, bitlen,
+ dflags, daddr, dbitoffset, dbitlen);
+
+ len = (bitlen > dbitlen) ? dbitlen : bitlen;
+ len = len / 8 + ((len % 8) ? 1 : 0);
+
+ for (i = 0; i < len; i++) {
+ state = aml_simulate_region_io(ACPI_REGION_INPUT, regtype,
+ flags, &value, addr, bitoffset + i * 8, 8, 0);
+ assert(state != -1);
+ state = aml_simulate_region_io(ACPI_REGION_OUTPUT, regtype,
+ dflags, &value, daddr, dbitoffset + i * 8, 8, 0);
+ assert(state != -1);
+ }
+
+ return (0);
+}
+
+u_int32_t
+aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
+ u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
+{
+
+ return (aml_simulate_region_read(regtype, flags, addr,
+ bitoffset, bitlen));
+}
+
+int
+aml_region_read_into_buffer(struct aml_environ *env, int regtype,
+ u_int32_t flags, u_int32_t addr, u_int32_t bitoffset,
+ u_int32_t bitlen, u_int8_t *buffer)
+{
+
+ return (aml_simulate_region_read_into_buffer(regtype, flags, addr,
+ bitoffset, bitlen, buffer));
+}
+
+int
+aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
+ u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
+{
+
+ return (aml_simulate_region_write(regtype, flags, value, addr,
+ bitoffset, bitlen));
+}
+
+int
+aml_region_write_from_buffer(struct aml_environ *env, int regtype,
+ u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
+ u_int32_t bitlen)
+{
+
+ return (aml_simulate_region_write_from_buffer(regtype, flags, buffer,
+ addr, bitoffset, bitlen));
+}
+
+int
+aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
+ u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
+ u_int32_t dflags, u_int32_t daddr,
+ u_int32_t dbitoffset, u_int32_t dbitlen)
+{
+
+ return (aml_simulate_region_bcopy(regtype, flags, addr, bitoffset,
+ bitlen, dflags, daddr, dbitoffset, dbitlen));
+}
+
+void
+aml_simulation_regdump(const char *dumpfile)
+{
+ struct ACPIRegionContent *rc;
+ FILE *fp;
+
+ if (!aml_simulation_initialized) {
+ return;
+ }
+ if ((fp = fopen(dumpfile, "w")) == NULL) {
+ warn(dumpfile);
+ return;
+ }
+ while (!TAILQ_EMPTY(&RegionContentList)) {
+ rc = TAILQ_FIRST(&RegionContentList);
+ fprintf(fp, "%d 0x%x 0x%x\n",
+ rc->regtype, rc->addr, rc->value);
+ TAILQ_REMOVE(&RegionContentList, rc, links);
+ free(rc);
+ }
+
+ fclose(fp);
+ TAILQ_INIT(&RegionContentList);
+}
OpenPOWER on IntegriCloud