diff options
author | takawata <takawata@FreeBSD.org> | 2000-08-24 09:33:30 +0000 |
---|---|---|
committer | takawata <takawata@FreeBSD.org> | 2000-08-24 09:33:30 +0000 |
commit | 3135216f2b96c5fbf4376f70255fc04ccfa4a3ab (patch) | |
tree | 2148c1c3b096be89000f930f9c014ba73d196c73 /usr.sbin/acpi/amldb | |
parent | 84083e097dd32caf80b017c7007aba2ecfe7f9a6 (diff) | |
download | FreeBSD-src-3135216f2b96c5fbf4376f70255fc04ccfa4a3ab.zip FreeBSD-src-3135216f2b96c5fbf4376f70255fc04ccfa4a3ab.tar.gz |
Add orthogonal part of ACPI support code.
This does not come effect until non-orthogonal part is commited.
Approved by: jkh
Obtained from: ACPI for FreeBSD CVS repository.
Diffstat (limited to 'usr.sbin/acpi/amldb')
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_amlmem.c | 92 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_amlmem.h | 65 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_common.c | 406 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_common.h | 75 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_env.h | 46 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_evalobj.c | 421 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_evalobj.h | 46 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_memman.c | 476 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_memman.h | 172 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_name.c | 477 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_name.h | 88 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_obj.c | 265 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_obj.h | 227 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_parse.c | 1998 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_parse.h | 36 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_region.c | 490 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_region.h | 58 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_status.h | 41 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_store.c | 338 | ||||
-rw-r--r-- | usr.sbin/acpi/amldb/aml/aml_store.h | 39 |
20 files changed, 5856 insertions, 0 deletions
diff --git a/usr.sbin/acpi/amldb/aml/aml_amlmem.c b/usr.sbin/acpi/amldb/aml/aml_amlmem.c new file mode 100644 index 0000000..6498f63 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_amlmem.c @@ -0,0 +1,92 @@ +/*- + * 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: aml_amlmem.c,v 1.15 2000/08/09 14:47:43 iwasaki Exp $ + * $FreeBSD$ + */ + +/* + * AML Namespace Memory Management + */ + +#include <sys/param.h> + +#include <dev/acpi/aml/aml_env.h> +#include <dev/acpi/aml/aml_memman.h> +#include <dev/acpi/aml/aml_name.h> + +MEMMAN_INITIALSTORAGE_DESC(struct aml_namestr, _aml_namestr_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_num, _aml_num_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_string, _aml_string_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_buffer, _aml_buffer_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_package, _aml_package_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_field, _aml_field_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_method, _aml_method_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_mutex, _aml_mutex_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_opregion, _aml_opregion_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_powerres, _aml_powerres_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_processor, _aml_processor_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_bufferfield, _aml_bufferfield_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_event, _aml_event_storage); +MEMMAN_INITIALSTORAGE_DESC(enum aml_objtype, _aml_objtype_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_name, _aml_name_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_name_group, _aml_name_group_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_objref, _aml_objref_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_regfield, _aml_regfield_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_environ, _aml_environ_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_local_stack, _aml_local_stack_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_mutex_queue, _aml_mutex_queue_storage); + +struct memman_blockman aml_blockman[] = { + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_namestr), _aml_namestr_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_num), _aml_num_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_string), _aml_string_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_buffer), _aml_buffer_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_package), _aml_package_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_field), _aml_field_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_method), _aml_method_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_mutex), _aml_mutex_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_opregion), _aml_opregion_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_powerres), _aml_powerres_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_processor), _aml_processor_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_bufferfield), _aml_bufferfield_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_event), _aml_event_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(enum aml_objtype), _aml_objtype_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_name), _aml_name_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_name_group), _aml_name_group_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_objref), _aml_objref_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_regfield), _aml_regfield_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_environ), _aml_environ_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_local_stack), _aml_local_stack_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_mutex_queue), _aml_mutex_queue_storage), +}; + +struct memman_histogram aml_histogram[MEMMAN_HISTOGRAM_SIZE]; + +static struct memman _aml_memman = MEMMAN_MEMMANAGER_DESC(aml_blockman, 21, + aml_histogram, 1); + +struct memman *aml_memman = &_aml_memman; + diff --git a/usr.sbin/acpi/amldb/aml/aml_amlmem.h b/usr.sbin/acpi/amldb/aml/aml_amlmem.h new file mode 100644 index 0000000..ed76565 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_amlmem.h @@ -0,0 +1,65 @@ +/*- + * 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: aml_amlmem.h,v 1.12 2000/08/08 14:12:05 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_AMLMEM_H_ +#define _AML_AMLMEM_H_ + +/* + * AML Namespace Memory Management + */ + +#include <dev/acpi/aml/aml_memman.h> + +enum { + memid_aml_namestr = 0, + memid_aml_num, + memid_aml_string, + memid_aml_buffer, + memid_aml_package, + memid_aml_field, + memid_aml_method, + memid_aml_mutex, + memid_aml_opregion, + memid_aml_powerres, + memid_aml_processor, + memid_aml_bufferfield, + memid_aml_event, + memid_aml_objtype, + memid_aml_name, + memid_aml_name_group, + memid_aml_objref, + memid_aml_regfield, + memid_aml_environ, + memid_aml_local_stack, + memid_aml_mutex_queue, +}; + +extern struct memman *aml_memman; + +#endif /* !_AML_AMLMEM_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_common.c b/usr.sbin/acpi/amldb/aml/aml_common.c new file mode 100644 index 0000000..c4d3e1e --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_common.c @@ -0,0 +1,406 @@ +/*- + * 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: aml_common.c,v 1.9 2000/08/09 14:47:43 iwasaki Exp $ + * $FreeBSD$ + */ + +#include <sys/param.h> + +#ifndef _KERNEL +#include <assert.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#else /* _KERNEL */ +#include "opt_acpi.h" +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#endif /* !_KERNEL */ + +#include <dev/acpi/aml/aml_common.h> +#include <dev/acpi/aml/aml_env.h> +#include <dev/acpi/aml/aml_evalobj.h> +#include <dev/acpi/aml/aml_name.h> +#include <dev/acpi/aml/aml_obj.h> +#include <dev/acpi/aml/aml_parse.h> +#include <dev/acpi/aml/aml_status.h> +#include <dev/acpi/aml/aml_store.h> + +/* for debugging */ +#ifdef AML_DEBUG +int aml_debug = 1; +#else /* !AML_DEBUG */ +int aml_debug = 0; +#endif /* AML_DEBUG */ +#ifdef _KERNEL +SYSCTL_INT(_debug, OID_AUTO, aml_debug, CTLFLAG_RW, &aml_debug, 1, ""); +#endif /* _KERNEL */ + +static void aml_print_nameseg(u_int8_t *dp); + +static void +aml_print_nameseg(u_int8_t *dp) +{ + + if (dp[3] != '_') { + AML_DEBUGPRINT("%c%c%c%c", dp[0], dp[1], dp[2], dp[3]); + } else if (dp[2] != '_') { + AML_DEBUGPRINT("%c%c%c_", dp[0], dp[1], dp[2]); + } else if (dp[1] != '_') { + AML_DEBUGPRINT("%c%c__", dp[0], dp[1]); + } else if (dp[0] != '_') { + AML_DEBUGPRINT("%c___", dp[0]); + } +} + +void +aml_print_namestring(u_int8_t *dp) +{ + int segcount; + int i; + + if (dp[0] == '\\') { + AML_DEBUGPRINT("%c", dp[0]); + dp++; + } else if (dp[0] == '^') { + while (dp[0] == '^') { + AML_DEBUGPRINT("%c", dp[0]); + dp++; + } + } + if (dp[0] == 0x00) { /* NullName */ + /* AML_DEBUGPRINT("<null>"); */ + dp++; + } else if (dp[0] == 0x2e) { /* DualNamePrefix */ + aml_print_nameseg(dp + 1); + AML_DEBUGPRINT("%c", '.'); + aml_print_nameseg(dp + 5); + } else if (dp[0] == 0x2f) { /* MultiNamePrefix */ + segcount = dp[1]; + for (i = 0, dp += 2; i < segcount; i++, dp += 4) { + if (i > 0) { + AML_DEBUGPRINT("%c", '.'); + } + aml_print_nameseg(dp); + } + } else /* NameSeg */ + aml_print_nameseg(dp); +} + +int +aml_print_curname(struct aml_name *name) +{ + struct aml_name *root; + + root = aml_get_rootname(); + if (name == root) { + AML_DEBUGPRINT("\\"); + return (0); + } else { + aml_print_curname(name->parent); + } + aml_print_nameseg(name->name); + AML_DEBUGPRINT("."); + return (0); +} + +void +aml_print_indent(int indent) +{ + int i; + + for (i = 0; i < indent; i++) + AML_DEBUGPRINT(" "); +} + +void +aml_showobject(union aml_object * obj) +{ + int debug; + int i; + + if (obj == NULL) { + printf("NO object\n"); + return; + } + debug = aml_debug; + aml_debug = 1; + switch (obj->type) { + case aml_t_num: + printf("Num:0x%x\n", obj->num.number); + break; + case aml_t_processor: + printf("Processor:No %d,Port 0x%x length 0x%x\n", + obj->proc.id, obj->proc.addr, obj->proc.len); + break; + case aml_t_mutex: + printf("Mutex:Level %d\n", obj->mutex.level); + break; + case aml_t_powerres: + printf("PowerResource:Level %d Order %d\n", + obj->pres.level, obj->pres.order); + break; + case aml_t_opregion: + printf("OprationRegion:Busspace%d, Offset 0x%x Length 0x%x\n", + obj->opregion.space, obj->opregion.offset, + obj->opregion.length); + break; + case aml_t_field: + printf("Fieldelement:flag 0x%x offset 0x%x len 0x%x {", + obj->field.flags, obj->field.bitoffset, + obj->field.bitlen); + switch (obj->field.f.ftype) { + case f_t_field: + aml_print_namestring(obj->field.f.fld.regname); + break; + case f_t_index: + aml_print_namestring(obj->field.f.ifld.indexname); + printf(" "); + aml_print_namestring(obj->field.f.ifld.dataname); + break; + case f_t_bank: + aml_print_namestring(obj->field.f.bfld.regname); + printf(" "); + aml_print_namestring(obj->field.f.bfld.bankname); + printf("0x%x", obj->field.f.bfld.bankvalue); + break; + } + printf("}\n"); + break; + case aml_t_method: + printf("Method: Arg %d From %p To %p\n", obj->meth.argnum, + obj->meth.from, obj->meth.to); + break; + case aml_t_buffer: + printf("Buffer: size:0x%x Data %p\n", obj->buffer.size, + obj->buffer.data); + break; + case aml_t_device: + printf("Device\n"); + break; + case aml_t_bufferfield: + printf("Bufferfield:offset 0x%x len 0x%x Origin %p\n", + obj->bfld.bitoffset, obj->bfld.bitlen, obj->bfld.origin); + break; + case aml_t_string: + printf("String:%s\n", obj->str.string); + break; + case aml_t_package: + printf("Package:elements %d \n", obj->package.elements); + for (i = 0; i < obj->package.elements; i++) { + if (obj->package.objects[i] == NULL) { + break; + } + if (obj->package.objects[i]->type < 0) { + continue; + } + printf(" "); + aml_showobject(obj->package.objects[i]); + } + break; + case aml_t_therm: + printf("Thermalzone\n"); + break; + case aml_t_event: + printf("Event\n"); + break; + case aml_t_ddbhandle: + printf("DDBHANDLE\n"); + break; + case aml_t_objref: + if (obj->objref.alias == 1) { + printf("Alias"); + } else { + printf("Object reference"); + if (obj->objref.offset >= 0) { + printf(" (offset 0x%x)", obj->objref.offset); + } + } + printf(" of "); + aml_showobject(obj->objref.ref); + break; + default: + printf("UNK ID=%d\n", obj->type); + } + + aml_debug = debug; +} + +void +aml_showtree(struct aml_name * aname, int lev) +{ + int i; + struct aml_name *ptr; + char name[5]; + + for (i = 0; i < lev; i++) { + printf(" "); + } + strncpy(name, aname->name, 4); + name[4] = 0; + printf("%s ", name); + if (aname->property != NULL) { + aml_showobject(aname->property); + } else { + printf("\n"); + } + for (ptr = aname->child; ptr; ptr = ptr->brother) + aml_showtree(ptr, lev + 1); +} + +/* + * BufferField I/O + */ + +#define AML_BUFFER_INPUT 0 +#define AML_BUFFER_OUTPUT 1 + +static int aml_bufferfield_io(int io, u_int32_t *valuep, + u_int8_t *origin, u_int32_t bitoffset, + u_int32_t bitlen); + +static int +aml_bufferfield_io(int io, u_int32_t *valuep, u_int8_t *origin, + u_int32_t bitoffset, u_int32_t bitlen) +{ + u_int8_t val, tmp, masklow, maskhigh; + u_int8_t offsetlow, offsethigh; + u_int8_t *addr; + int value = *valuep, readval; + int i; + u_int32_t byteoffset, bytelen; + + masklow = maskhigh = 0xff; + val = readval = 0; + value = *valuep; + + byteoffset = bitoffset / 8; + bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0); + addr = origin + byteoffset; + offsetlow = bitoffset % 8; + if (bytelen > 1) { + offsethigh = (bitlen - (8 - offsetlow)) % 8; + } else { + offsethigh = 0; + } + + if (offsetlow) { + masklow = (~((1 << bitlen) - 1) << offsetlow) | ~(0xff << offsetlow); + AML_DEBUGPRINT("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n", + offsetlow, masklow, ~masklow & 0xff); + } + if (offsethigh) { + maskhigh = 0xff << offsethigh; + AML_DEBUGPRINT("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n", + offsethigh, maskhigh, ~maskhigh & 0xff); + } + for (i = bytelen; i > 0; i--, addr++) { + val = *addr; + + AML_DEBUGPRINT("\t[bufferfield:0x%02x@%p]", val, addr); + + switch (io) { + case AML_BUFFER_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; + } + + AML_DEBUGPRINT("\n"); + /* goto to next byte... */ + if (i > 1) { + continue; + } + /* final adjustment before finishing region access */ + if (offsetlow) { + readval = readval >> offsetlow; + } + AML_DEBUGPRINT("[read(bufferfield, %p)&mask:0x%x]\n", + addr, readval); + *valuep = readval; + + break; + + case AML_BUFFER_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; + } + + AML_DEBUGPRINT("->[bufferfield:0x%02x@%p]\n", + tmp, addr); + *addr = tmp; + } + } + + return (0); +} + +u_int32_t +aml_bufferfield_read(u_int8_t *origin, u_int32_t bitoffset, + u_int32_t bitlen) +{ + int value; + + value = 0; + aml_bufferfield_io(AML_BUFFER_INPUT, &value, origin, + bitoffset, bitlen); + return (value); +} + +int +aml_bufferfield_write(u_int32_t value, u_int8_t *origin, + u_int32_t bitoffset, u_int32_t bitlen) +{ + int status; + + status = aml_bufferfield_io(AML_BUFFER_OUTPUT, &value, + origin, bitoffset, bitlen); + return (status); +} diff --git a/usr.sbin/acpi/amldb/aml/aml_common.h b/usr.sbin/acpi/amldb/aml/aml_common.h new file mode 100644 index 0000000..ed253af --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_common.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 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: aml_common.h,v 1.4 2000/08/08 14:12:05 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_COMMON_H_ +#define _AML_COMMON_H_ + +#ifdef _KERNEL +#define AML_SYSABORT() do { \ + printf("aml: fatal errer at %s:%d\n", __FILE__, __LINE__); \ + panic("panic in AML interpreter!"); \ +} while(0) +#define AML_SYSASSERT(x) do { \ + if (!(x)) { \ + AML_SYSABORT(); \ + } \ +} while(0) +#define AML_SYSERRX(eval, fmt, args...) do { \ + printf(fmt, args); \ +} while(0) +#define AML_DEBUGGER(x, y) /* no debugger in kernel */ +#else /* !_KERNEL */ +#define AML_SYSASSERT(x) assert(x) +#define AML_SYSABORT() abort() +#define AML_SYSERRX(eval, fmt, args...) errx(eval, fmt, args) +#define AML_DEBUGGER(x, y) aml_dbgr(x, y) +#endif /* _KERNEL */ + +union aml_object; +struct aml_name; + +extern int aml_debug; + +#define AML_DEBUGPRINT(args...) do { \ + if (aml_debug) { \ + printf(args); \ + } \ +} while(0) + +void aml_showobject(union aml_object *); +void aml_showtree(struct aml_name *, int); +int aml_print_curname(struct aml_name *); +void aml_print_namestring(u_int8_t *); +void aml_print_indent(int); + +u_int32_t aml_bufferfield_read(u_int8_t *, u_int32_t, u_int32_t); +int aml_bufferfield_write(u_int32_t, u_int8_t *, + u_int32_t, u_int32_t); + +#endif /* !_AML_COMMON_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_env.h b/usr.sbin/acpi/amldb/aml/aml_env.h new file mode 100644 index 0000000..e78330d --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_env.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * 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: aml_env.h,v 1.11 2000/08/08 14:12:05 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_ENV_H_ +#define _AML_ENV_H_ + +#include <dev/acpi/aml/aml_name.h> +#include <dev/acpi/aml/aml_obj.h> +#include <dev/acpi/aml/aml_status.h> + +struct aml_environ { + u_int8_t *dp; + u_int8_t *end; + enum aml_status stat; + struct aml_name *curname; + struct aml_name tempname; + union aml_object tempobject; +}; + +#endif /* !_AML_ENV_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_evalobj.c b/usr.sbin/acpi/amldb/aml/aml_evalobj.c new file mode 100644 index 0000000..573ae26 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_evalobj.c @@ -0,0 +1,421 @@ +/*- + * 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: aml_evalobj.c,v 1.27 2000/08/16 18:14:53 iwasaki Exp $ + * $FreeBSD$ + */ + +#include <sys/param.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_evalobj.h> +#include <dev/acpi/aml/aml_name.h> +#include <dev/acpi/aml/aml_obj.h> +#include <dev/acpi/aml/aml_parse.h> +#include <dev/acpi/aml/aml_region.h> +#include <dev/acpi/aml/aml_status.h> +#include <dev/acpi/aml/aml_store.h> + +#ifndef _KERNEL +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/bus.h> +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static union aml_object *aml_eval_fieldobject(struct aml_environ *env, + struct aml_name *name); + +static union aml_object * +aml_eval_fieldobject(struct aml_environ *env, struct aml_name *name) +{ + struct aml_name *oname,*wname; + struct aml_field *field; + struct aml_opregion *or; + union aml_object tobj; + + /* CANNOT OCCUR! */ + if (name == NULL || name->property == NULL || + name->property->type != aml_t_field) { + printf("????\n"); + env->stat = aml_stat_panic; + return (NULL); + } + field = &name->property->field; + oname = env->curname; + if (field->bitlen > 32) { + env->tempobject.type = aml_t_regfield; + } else { + env->tempobject.type = aml_t_num; + } + env->curname = name; + if (field->f.ftype == f_t_field) { + wname = aml_search_name(env, field->f.fld.regname); + if (wname == NULL || wname->property == NULL || + wname->property->type != aml_t_opregion) { + AML_DEBUGPRINT("Inappropreate Type\n"); + env->stat = aml_stat_panic; + env->curname = oname; + return (NULL); + } + or = &wname->property->opregion; + if (env->tempobject.type == aml_t_regfield) { + env->tempobject.regfield.space = or->space; + env->tempobject.regfield.flags = field->flags; + env->tempobject.regfield.offset = or->offset; + env->tempobject.regfield.bitoffset = field->bitoffset; + env->tempobject.regfield.bitlen = field->bitlen; + } else { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = aml_region_read(env, + or->space, field->flags, or->offset, + field->bitoffset, field->bitlen); + AML_DEBUGPRINT("[read(%d, 0x%x)->0x%x]", + or->space, or->offset + field->bitoffset / 8, + env->tempobject.num.number); + } + } else if (field->f.ftype == f_t_index) { + wname = aml_search_name(env, field->f.ifld.indexname); + tobj.type = aml_t_num; + tobj.num.number = field->bitoffset / 8;/* AccessType Boundary */ + aml_store_to_name(env, &tobj, wname); + wname = aml_search_name(env, field->f.ifld.dataname); + aml_eval_name(env, wname); + } + env->curname = oname; + return (&env->tempobject); +} + +union aml_object * +aml_eval_objref(struct aml_environ *env, union aml_object *obj) +{ + int offset; + union aml_object num1; + union aml_object *ref, *ret; + + ret = obj; + if (obj->objref.deref == 1) { + num1.type = aml_t_num; + offset = obj->objref.offset; + ref = obj->objref.ref; + if (ref == NULL) { + goto out; + } + switch (ref->type) { + case aml_t_package: + if (ref->package.elements > offset) { + ret = ref->package.objects[offset]; + } else { + num1.num.number = 0; + env->tempobject = num1; + ret = &env->tempobject; + } + break; + case aml_t_buffer: + if (ref->buffer.size > offset) { + num1.num.number = ref->buffer.data[offset] & 0xff; + } else { + num1.num.number = 0; + } + env->tempobject = num1; + ret = &env->tempobject; + break; + default: + break; + } + } + if (obj->objref.alias == 1) { + ret = aml_eval_name(env, obj->objref.nameref); + goto out; + } +out: + return (ret); +} + +/* + * Eval named object. + */ +union aml_object * +aml_eval_name(struct aml_environ *env, struct aml_name *aname) +{ + int argnum, i; + int num; + struct aml_name *tmp; + struct aml_environ *copy; + struct aml_local_stack *stack; + union aml_object *obj, *ret; + union aml_object *src; + + ret = NULL; + if (aname == NULL || aname->property == NULL) { + return (NULL); + } + if (env->stat == aml_stat_panic) { + return (NULL); + } + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + return (NULL); + } + ret = aname->property; + i = 0; +reevaluate: + if (i > 10) { + env->stat = aml_stat_panic; + printf("TOO MANY LOOP\n"); + ret = NULL; + goto out; + } + switch (aname->property->type) { + case aml_t_namestr: + tmp = aname; + aname = aml_search_name(env, aname->property->nstr.dp); + if (aname == NULL) { + aname = tmp; + } + i++; + goto reevaluate; + case aml_t_objref: + ret = aml_eval_objref(env, aname->property); + goto out; + case aml_t_num: + case aml_t_string: + case aml_t_buffer: + case aml_t_package: + case aml_t_debug: + ret = aname->property; + goto out; + case aml_t_field: + aml_free_objectcontent(&env->tempobject); + ret = aml_eval_fieldobject(env, aname); + goto out; + case aml_t_method: + aml_free_objectcontent(&env->tempobject); + argnum = aname->property->meth.argnum & 7; + *copy = *env; + copy->curname = aname; + copy->dp = aname->property->meth.from; + copy->end = aname->property->meth.to; + copy->stat = aml_stat_none; + stack = aml_local_stack_create(); + AML_DEBUGPRINT("("); + for (i = 0; i < argnum; i++) { + aml_local_stack_getArgX(stack, i)->property = + aml_copy_object(env, + aml_eval_name(env, + aml_parse_termobj(env, 0))); + if (i < argnum - 1) + AML_DEBUGPRINT(", "); + } + AML_DEBUGPRINT(")\n"); + aml_local_stack_push(stack); + if (env->stat == aml_stat_step) { + AML_DEBUGGER(env, copy); + } + tmp = aml_execute_method(copy); + obj = aml_eval_name(env, tmp); + if (copy->stat == aml_stat_panic) { + AML_DEBUGPRINT("PANIC OCCURED IN METHOD"); + env->stat = aml_stat_panic; + ret = NULL; + aml_local_stack_delete(aml_local_stack_pop()); + goto out; + } + if (aml_debug) { + aml_showobject(obj); + } + + if (tmp) + tmp->property = NULL; + aml_local_stack_delete(aml_local_stack_pop()); + if (obj) { + aml_create_local_object()->property = obj; + ret = obj; + } else { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = 0; + } + + goto out; + case aml_t_bufferfield: + aml_free_objectcontent(&env->tempobject); + if (aname->property->bfld.bitlen > 32) { + ret = aname->property; + } else { + src = aname->property; + num = aml_bufferfield_read(src->bfld.origin, + src->bfld.bitoffset, src->bfld.bitlen); + env->tempobject.type = aml_t_num; + env->tempobject.num.number = num; + ret = &env->tempobject; + } + goto out; + default: + AML_DEBUGPRINT("I eval the object that I should not eval, %s%d", + aname->name, aname->property->type); + AML_SYSABORT(); + ret = NULL; + goto out; + } +out: + memman_free(aml_memman, memid_aml_environ, copy); + return (ret); +} + +/* + * Eval named object but env variable is not required and return + * status of evaluation (success is zero). This function is assumed + * to be called by aml_apply_foreach_found_objects(). + * Note that no arguments are passed if object is a method. + */ + +int +aml_eval_name_simple(struct aml_name *name, va_list ap) +{ + struct aml_environ *env; + union aml_object *ret; + + if (name == NULL || name->property == NULL) { + return (1); + } + + env = memman_alloc(aml_memman, memid_aml_environ); + if (env == NULL) { + return (1); + } + bzero(env, sizeof(struct aml_environ)); + + aml_local_stack_push(aml_local_stack_create()); + + AML_DEBUGPRINT("Evaluating "); + aml_print_curname(name); + ret = aml_eval_name(env, name); + if (name->property->type != aml_t_method) { + AML_DEBUGPRINT("\n"); + if (aml_debug) { + aml_showobject(ret); + } + } + + aml_local_stack_delete(aml_local_stack_pop()); + + memman_free(aml_memman, memid_aml_environ, env); + return (0); +} + +int +aml_objtonum(struct aml_environ *env, union aml_object *obj) +{ + + if (obj != NULL && obj->type == aml_t_num) { + return (obj->num.number); + } else { + env->stat = aml_stat_panic; + return (-1); + } +} + +struct aml_name * +aml_execute_method(struct aml_environ *env) +{ + struct aml_name *name; + struct aml_name_group *newgrp; + + newgrp = aml_new_name_group(AML_NAME_GROUP_IN_METHOD); + + AML_DEBUGPRINT("["); + aml_print_curname(env->curname); + AML_DEBUGPRINT(" START]\n"); + + name = aml_parse_objectlist(env, 0); + AML_DEBUGPRINT("["); + aml_print_curname(env->curname); + AML_DEBUGPRINT(" END]\n"); + + aml_delete_name_group(newgrp); + return (name); +} + +union aml_object * +aml_invoke_method_by_name(char *method, int argc, union aml_object *argv) +{ + int i; + struct aml_name *name; + struct aml_name *tmp; + struct aml_environ *env; + struct aml_local_stack *stack; + union aml_object *retval; + union aml_object *obj; + + retval = NULL; + env = memman_alloc(aml_memman, memid_aml_environ); + if (env == NULL) { + return (NULL); + } + bzero(env, sizeof(struct aml_environ)); + name = aml_find_from_namespace(aml_get_rootname(), method); + + if (name != NULL && name->property != NULL && + name->property->type == aml_t_method) { + env->curname = name; + env->dp = name->property->meth.from; + env->end = name->property->meth.to; + AML_DEBUGGER(env, env); + stack = aml_local_stack_create(); + for (i = 0; i < argc; i++) { + aml_local_stack_getArgX(stack, i)->property = + aml_alloc_object(argv[i].type, &argv[i]); + } + aml_local_stack_push(stack); + obj = aml_eval_name(env, tmp = aml_execute_method(env)); + if (aml_debug) { + aml_showtree(name, 0); + } + + if (tmp) + tmp->property = NULL; + aml_local_stack_delete(aml_local_stack_pop()); + if (obj) { + aml_create_local_object()->property = obj; + retval = obj; + } + } + memman_free(aml_memman, memid_aml_environ, env); + return (retval); +} diff --git a/usr.sbin/acpi/amldb/aml/aml_evalobj.h b/usr.sbin/acpi/amldb/aml/aml_evalobj.h new file mode 100644 index 0000000..884f301 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_evalobj.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * 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: aml_evalobj.h,v 1.11 2000/08/16 18:14:53 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_EVALOBJ_H_ +#define _AML_EVALOBJ_H_ + +#include <machine/stdarg.h> + +union aml_object *aml_eval_objref(struct aml_environ *, + union aml_object *); +union aml_object *aml_eval_name(struct aml_environ *, + struct aml_name *); +int aml_eval_name_simple(struct aml_name *, va_list); +int aml_objtonum(struct aml_environ *, + union aml_object *); +struct aml_name *aml_execute_method(struct aml_environ *); +union aml_object *aml_invoke_method_by_name(char *, + int, union aml_object *); + +#endif /* !_AML_EVALOBJ_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_memman.c b/usr.sbin/acpi/amldb/aml/aml_memman.c new file mode 100644 index 0000000..7fe8c55 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_memman.c @@ -0,0 +1,476 @@ +/*- + * 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: aml_memman.c,v 1.10 2000/08/09 14:47:43 iwasaki Exp $ + * $FreeBSD$ + */ + +/* + * Generic Memory Management + */ + +#include <sys/param.h> + +#include <dev/acpi/aml/aml_memman.h> + +#ifndef _KERNEL +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#else /* _KERNEL */ +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/malloc.h> +MALLOC_DEFINE(M_MEMMAN, "memman", "Generic and Simple Memory Management"); +#endif /* !_KERNEL */ + +unsigned int memid_unkown = 255; + +static int manage_block(struct memman *memman, unsigned int id, + void *block, unsigned static_mem, + unsigned entries); +static int blockman_init(struct memman *memman, unsigned int id); +static void memman_flexsize_add_histogram(struct memman *memman, + size_t size, + int tolerance); +static int memman_comp_histogram_size(const void *a, + const void *b); +static void memman_sort_histogram_by_size(struct memman *memman); +static unsigned int memman_guess_memid(struct memman *memman, void *chunk); +static void memman_statistics_fixedsize(struct memman *memman); +static void memman_statistics_flexsize(struct memman *memman); + +static int +manage_block(struct memman *memman, unsigned int id, void *block, + unsigned static_mem, unsigned entries) +{ + unsigned int i; + size_t alloc_size; + void *tmp, *realblock; + struct memman_blockman *bmp; + struct memman_block *memblock; + struct memman_node *memnodes; + + bmp = &memman->blockman[id]; + alloc_size = MEMMAN_BLOCKNODE_SIZE(entries); + + if (static_mem) { + tmp = (void *)block; + realblock = (char *)block + alloc_size; + } else { + tmp = MEMMAN_SYSMALLOC(alloc_size); + if (!tmp) { + return (-1); + } + realblock = block; + + memman->allocated_mem += alloc_size; + memman->salloc_called++; + } + + memblock = (struct memman_block *)tmp; + memnodes = (struct memman_node *)((char *)tmp + sizeof(struct memman_block)); + + memblock->block = realblock; + memblock->static_mem = static_mem; + memblock->allocated = entries; + memblock->available = entries; + if (!static_mem) { + alloc_size += roundup(bmp->size * entries, ROUNDUP_UNIT); + } + memblock->allocated_mem = alloc_size; + LIST_INSERT_HEAD(&bmp->block_list, memblock, links); + + for (i = 0; i < entries; ++i) { + memnodes[i].node = ((char *)realblock + (i * (bmp->size))); + memnodes[i].memblock = memblock; + LIST_INSERT_HEAD(&bmp->free_node_list, &memnodes[i], links); + } + bmp->available = entries; + + return (0); +} + +static int +blockman_init(struct memman *memman, unsigned int id) +{ + int status; + struct memman_blockman *bmp; + + bmp = &memman->blockman[id]; + bmp->initialized = 1; + LIST_INIT(&bmp->block_list); + LIST_INIT(&bmp->free_node_list); + LIST_INIT(&bmp->occupied_node_list); + status = manage_block(memman, id, bmp->initial_block, + 1, MEMMAN_INITIAL_SIZE); + return (status); +} + +void * +memman_alloc(struct memman *memman, unsigned int id) +{ + size_t alloc_size; + void *chunk, *block; + struct memman_blockman *bmp; + struct memman_node *memnode; + + if (memman->max_memid <= id) { + printf("memman_alloc: invalid memory type id\n"); + return (NULL); + } + bmp = &memman->blockman[id]; + if (!bmp->initialized) { + if (blockman_init(memman, id)) { + goto malloc_fail; + } + } + memman->alloc_called++; + + if (bmp->available == 0) { + alloc_size = roundup(bmp->size * MEMMAN_INCR_SIZE, + ROUNDUP_UNIT); + block = MEMMAN_SYSMALLOC(alloc_size); + if (!block) { + goto malloc_fail; + } + memman->required_mem += bmp->size * MEMMAN_INCR_SIZE; + memman->allocated_mem += alloc_size; + memman->salloc_called++; + + if (manage_block(memman, id, block, 0, MEMMAN_INCR_SIZE)) { + goto malloc_fail; + } + } + memnode = LIST_FIRST(&bmp->free_node_list); + LIST_REMOVE(memnode, links); + chunk = memnode->node; + LIST_INSERT_HEAD(&bmp->occupied_node_list, memnode, links); + memnode->memblock->available--; + bmp->available--; + + return (chunk); + +malloc_fail: + printf("memman_alloc: could not allocate memory\n"); + return (NULL); +} + +static void +memman_flexsize_add_histogram(struct memman *memman, size_t size, + int tolerance) +{ + int i; + int gap; + + if (size == 0) { + return; + } + for (i = 0; i < memman->flex_mem_histogram_ptr; i++) { + gap = memman->flex_mem_histogram[i].mem_size - size; + if (gap >= (tolerance * -1) && gap <= tolerance) { + memman->flex_mem_histogram[i].count++; + if (memman->flex_mem_histogram[i].mem_size < size) { + memman->flex_mem_histogram[i].mem_size = size; + } + return; + } + } + + if (memman->flex_mem_histogram_ptr == MEMMAN_HISTOGRAM_SIZE) { + memman_flexsize_add_histogram(memman, size, tolerance + 1); + return; + } + i = memman->flex_mem_histogram_ptr; + memman->flex_mem_histogram[i].mem_size = size; + memman->flex_mem_histogram[i].count = 1; + memman->flex_mem_histogram_ptr++; +} + +static int +memman_comp_histogram_size(const void *a, const void *b) +{ + int delta; + + delta = ((const struct memman_histogram *)a)->mem_size - + ((const struct memman_histogram *)b)->mem_size; + return (delta); +} + +static void +memman_sort_histogram_by_size(struct memman *memman) +{ + qsort(memman->flex_mem_histogram, memman->flex_mem_histogram_ptr, + sizeof(struct memman_histogram), memman_comp_histogram_size); +} + +void * +memman_alloc_flexsize(struct memman *memman, size_t size) +{ + void *mem; + struct memman_flexmem_info *info; + + if (size == 0) { + return (NULL); + } + if ((mem = MEMMAN_SYSMALLOC(size)) != NULL) { /* XXX */ + + info = MEMMAN_SYSMALLOC(sizeof(struct memman_flexmem_info)); + if (info) { + if (!memman->flex_mem_initialized) { + LIST_INIT(&memman->flexmem_info_list); + bzero(memman->flex_mem_histogram, + sizeof(struct memman_histogram)); + memman->flex_mem_initialized = 1; + } + info->addr = mem; + info->mem_size = size; + LIST_INSERT_HEAD(&memman->flexmem_info_list, info, links); + } + memman->flex_alloc_called++; + memman->flex_salloc_called++; + memman->flex_required_mem += size; + memman->flex_allocated_mem += size; + if (memman->flex_mem_size_min == 0 || + memman->flex_mem_size_min > size) { + memman->flex_mem_size_min = size; + } + if (memman->flex_mem_size_max < size) { + memman->flex_mem_size_max = size; + } + if (memman->flex_peak_mem_usage < + (memman->flex_allocated_mem - memman->flex_reclaimed_mem)) { + memman->flex_peak_mem_usage = + (memman->flex_allocated_mem - memman->flex_reclaimed_mem); + } + memman_flexsize_add_histogram(memman, size, + memman->flex_mem_histogram_initial_tolerance); + } + return (mem); +} + +static unsigned int +memman_guess_memid(struct memman *memman, void *chunk) +{ + unsigned int id; + struct memman_blockman *bmp; + struct memman_node *memnode; + + for (id = 0; id < memman->max_memid; id++) { + bmp = &memman->blockman[id]; + if (!bmp->initialized) { + if (blockman_init(memman, id)) { + printf("memman_free: could not initialized\n"); + } + } + LIST_FOREACH(memnode, &bmp->occupied_node_list, links) { + if (memnode->node == chunk) { + return (id); /* got it! */ + } + } + } + return (memid_unkown); /* gave up */ +} + +void +memman_free(struct memman *memman, unsigned int memid, void *chunk) +{ + unsigned int id; + unsigned found; + void *block; + struct memman_blockman *bmp; + struct memman_block *memblock; + struct memman_node *memnode; + + id = memid; + if (memid == memid_unkown) { + id = memman_guess_memid(memman, chunk); + } + if (memman->max_memid <= id) { + printf("memman_free: invalid memory type id\n"); + MEMMAN_SYSABORT(); + return; + } + bmp = &memman->blockman[id]; + if (!bmp->initialized) { + if (blockman_init(memman, id)) { + printf("memman_free: could not initialized\n"); + } + } + found = 0; + LIST_FOREACH(memnode, &bmp->occupied_node_list, links) { + if (memnode->node == chunk) { + found = 1; + break; + } + } + if (!found) { + printf("memman_free: invalid address\n"); + return; + } + memman->free_called++; + + LIST_REMOVE(memnode, links); + memblock = memnode->memblock; + memblock->available++; + LIST_INSERT_HEAD(&bmp->free_node_list, memnode, links); + bmp->available++; + + if (!memblock->static_mem && + memblock->available == memblock->allocated) { + LIST_FOREACH(memnode, &bmp->free_node_list, links) { + if (memnode->memblock != memblock) { + continue; + } + LIST_REMOVE(memnode, links); + bmp->available--; + } + block = memblock->block; + MEMMAN_SYSFREE(block); + memman->sfree_called++; + + LIST_REMOVE(memblock, links); + memman->sfree_called++; + memman->reclaimed_mem += memblock->allocated_mem; + MEMMAN_SYSFREE(memblock); + } +} + +void +memman_free_flexsize(struct memman *memman, void *chunk) +{ + struct memman_flexmem_info *info; + + LIST_FOREACH(info, &memman->flexmem_info_list, links) { + if (info->addr == chunk) { + memman->flex_reclaimed_mem += info->mem_size; + LIST_REMOVE(info, links); + MEMMAN_SYSFREE(info); + break; + } + } + /* XXX */ + memman->flex_free_called++; + memman->flex_sfree_called++; + MEMMAN_SYSFREE(chunk); +} + +void +memman_freeall(struct memman *memman) +{ + int id; + void *chunk; + struct memman_blockman *bmp; + struct memman_node *memnode; + struct memman_block *memblock; + struct memman_flexmem_info *info; + + for (id = 0; id < memman->max_memid; id++) { + bmp = &memman->blockman[id]; + + while ((memnode = LIST_FIRST(&bmp->occupied_node_list))) { + chunk = memnode->node; + printf("memman_freeall: fixed size (id = %d)\n", id); + memman_free(memman, id, chunk); + } + while ((memblock = LIST_FIRST(&bmp->block_list))) { + LIST_REMOVE(memblock, links); + if (!memblock->static_mem) { + memman->sfree_called++; + memman->reclaimed_mem += memblock->allocated_mem; + MEMMAN_SYSFREE(memblock); + } + } + bmp->initialized = 0; + } + + LIST_FOREACH(info, &memman->flexmem_info_list, links) { + printf("memman_freeall: flex size (size = %d, addr = %p)\n", + info->mem_size, info->addr); + memman_free_flexsize(memman, info->addr); + } +} + +static void +memman_statistics_fixedsize(struct memman *memman) +{ + printf(" fixed size memory blocks\n"); + printf(" alloc(): %d times\n", memman->alloc_called); + printf(" system malloc(): %d times\n", memman->salloc_called); + printf(" free(): %d times\n", memman->free_called); + printf(" system free(): %d times\n", memman->sfree_called); + printf(" required memory: %d bytes\n", memman->required_mem); + printf(" allocated memory: %d bytes\n", memman->allocated_mem); + printf(" reclaimed memory: %d bytes\n", memman->reclaimed_mem); +} + +static void +memman_statistics_flexsize(struct memman *memman) +{ + int i; + + printf(" flexible size memory blocks\n"); + printf(" alloc(): %d times\n", memman->flex_alloc_called); + printf(" system malloc(): %d times\n", memman->flex_salloc_called); + printf(" free(): %d times\n", memman->flex_free_called); + printf(" system free(): %d times\n", memman->flex_sfree_called); + printf(" required memory: %d bytes\n", memman->flex_required_mem); + printf(" allocated memory: %d bytes\n", memman->flex_allocated_mem); + printf(" reclaimed memory: %d bytes\n", memman->flex_reclaimed_mem); + printf(" peak memory usage: %d bytes\n", memman->flex_peak_mem_usage); + printf(" min memory size: %d bytes\n", memman->flex_mem_size_min); + printf(" max memory size: %d bytes\n", memman->flex_mem_size_max); + printf(" avg memory size: %d bytes\n", + (memman->flex_alloc_called) ? + memman->flex_allocated_mem / memman->flex_alloc_called : 0); + + printf(" memory size histogram (%d entries):\n", + memman->flex_mem_histogram_ptr); + printf(" size count\n"); + memman_sort_histogram_by_size(memman); + for (i = 0; i < memman->flex_mem_histogram_ptr; i++) { + printf(" %d %d\n", + memman->flex_mem_histogram[i].mem_size, + memman->flex_mem_histogram[i].count); + } +} + +void +memman_statistics(struct memman *memman) +{ + printf("memman: reporting statistics\n"); + memman_statistics_fixedsize(memman); + memman_statistics_flexsize(memman); +} + +size_t +memman_memid2size(struct memman *memman, unsigned int id) +{ + if (memman->max_memid <= id) { + printf("memman_alloc: invalid memory type id\n"); + return (0); + } + return (memman->blockman[id].size); +} diff --git a/usr.sbin/acpi/amldb/aml/aml_memman.h b/usr.sbin/acpi/amldb/aml/aml_memman.h new file mode 100644 index 0000000..f6806c5 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_memman.h @@ -0,0 +1,172 @@ +/*- + * 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: aml_memman.h,v 1.9 2000/08/09 14:47:43 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _MEMMAN_H_ +#define _MEMMAN_H_ + +/* + * Generic Memory Management + */ + +#include <sys/param.h> +#include <sys/queue.h> + +/* memory block */ +struct memman_block { + LIST_ENTRY(memman_block) links; + void *block; + unsigned static_mem; /* static memory or not */ + unsigned int allocated; /* number of allocated chunks */ + unsigned int available; /* number of available chunks */ + unsigned int allocated_mem; /* block + misc (in bytes) */ + +}__attribute__((packed)); + +LIST_HEAD(memman_block_list, memman_block); + +/* memory node in block */ +struct memman_node { + LIST_ENTRY(memman_node) links; + void *node; + struct memman_block *memblock; +}__attribute__((packed)); + +LIST_HEAD(memman_node_list, memman_node); + +/* memory type id */ +extern unsigned int memid_unkown; + +/* memory block manager */ +struct memman_blockman { + unsigned int size; /* size of chunk */ + unsigned int available; /* total # of available chunks */ + void *initial_block; /* initial memory storage */ + unsigned initialized; /* initialized or not */ + + struct memman_block_list block_list; + struct memman_node_list free_node_list; + struct memman_node_list occupied_node_list; +}; + +/* memory size histogram */ +#define MEMMAN_HISTOGRAM_SIZE 20 +struct memman_histogram { + int mem_size; + int count; +}; + +/* flex size memory allocation info */ +struct memman_flexmem_info { + LIST_ENTRY(memman_flexmem_info) links; + void *addr; + size_t mem_size; +}__attribute__((packed)); + +LIST_HEAD(memman_flexmem_info_list, memman_flexmem_info); + +/* memory manager */ +struct memman { + struct memman_blockman *blockman; + unsigned int max_memid; /* max number of valid memid */ + + /* fixed size memory blocks */ + unsigned int alloc_called; /* memman_alloc() calling */ + unsigned int free_called; /* memman_free() calling */ + unsigned int salloc_called; /* malloc() calling */ + unsigned int sfree_called; /* free() calling */ + size_t required_mem; /* total required memory (in bytes) */ + size_t allocated_mem; /* total malloc()ed memory */ + size_t reclaimed_mem; /* total free()ed memory */ + /* flex size memory blocks */ + unsigned int flex_alloc_called; /* memman_alloc_flexsize() calling */ + unsigned int flex_free_called; /* memman_free_flexsize() calling */ + unsigned int flex_salloc_called;/* malloc() calling */ + unsigned int flex_sfree_called; /* free() calling */ + size_t flex_required_mem; /* total required memory (in bytes) */ + size_t flex_allocated_mem;/* total malloc()ed memory */ + size_t flex_reclaimed_mem;/* total free()ed memory */ + size_t flex_mem_size_min; /* min size of allocated memory */ + size_t flex_mem_size_max; /* max size of allocated memory */ + size_t flex_peak_mem_usage;/* memory usage at a peak period */ + + /* stuff for more detailed statistical information */ + struct memman_histogram *flex_mem_histogram; + unsigned int flex_mem_histogram_ptr; + int flex_mem_histogram_initial_tolerance; + unsigned flex_mem_initialized; + struct memman_flexmem_info_list flexmem_info_list; +}; + +#define MEMMAN_BLOCKNODE_SIZE(entries) sizeof(struct memman_block) + \ + sizeof(struct memman_node) * entries + +#ifndef ROUNDUP_UNIT +#define ROUNDUP_UNIT 4 +#endif + +#if !defined(MEMMAN_INITIAL_SIZE) || MEMMAN_INITIAL_SIZE < 2048 +#define MEMMAN_INITIAL_SIZE 2048 +#endif + +#if !defined(MEMMAN_INCR_SIZE) || MEMMAN_INCR_SIZE < 512 +#define MEMMAN_INCR_SIZE 512 +#endif + +#define MEMMAN_INITIALSTORAGE_DESC(type, name) \ +static struct { \ + char blocknodes[MEMMAN_BLOCKNODE_SIZE(MEMMAN_INITIAL_SIZE)]; \ + type realblock[MEMMAN_INITIAL_SIZE]; \ +} name + +#define MEMMAN_MEMBLOCK_DESC(size, initial_storage) \ + { size, MEMMAN_INITIAL_SIZE, &initial_storage, 0 } + +#define MEMMAN_MEMMANAGER_DESC(blockman, max_memid, histogram, tolerance) \ + { blockman, max_memid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, histogram, 0, tolerance, 0} + +void *memman_alloc(struct memman *, unsigned int); +void *memman_alloc_flexsize(struct memman *, size_t); +void memman_free(struct memman *, unsigned int, void *); +void memman_free_flexsize(struct memman *, void *); +void memman_freeall(struct memman *); +void memman_statistics(struct memman *); +size_t memman_memid2size(struct memman *, unsigned int); + +#ifdef _KERNEL +#define MEMMAN_SYSMALLOC(size) malloc(size, M_MEMMAN, M_WAITOK) +#define MEMMAN_SYSFREE(ptr) free(ptr, M_MEMMAN) +#define MEMMAN_SYSABORT() /* no abort in kernel */ +#else /* !_KERNEL */ +#define MEMMAN_SYSMALLOC(size) malloc(size) +#define MEMMAN_SYSFREE(ptr) free(ptr) +#define MEMMAN_SYSABORT() abort() +#endif /* _KERNEL */ + +#endif /* !_MEMMAN_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_name.c b/usr.sbin/acpi/amldb/aml/aml_name.c new file mode 100644 index 0000000..6cc0f6c --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_name.c @@ -0,0 +1,477 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * Copyright (c) 1999, 2000 Yasuo Yokoyama + * 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: aml_name.c,v 1.15 2000/08/16 18:14:53 iwasaki Exp $ + * $FreeBSD$ + */ + +#include <sys/param.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_name.h> + +#ifndef _KERNEL +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static struct aml_name *aml_find_name(struct aml_name *, char *); +static struct aml_name *aml_new_name(struct aml_name *, char *); +static void aml_delete_name(struct aml_name *); + +static struct aml_name rootname = {"\\", NULL, NULL, NULL, NULL, NULL}; + +static struct aml_name_group root_group = { + AML_NAME_GROUP_ROOT, + &rootname, + NULL +}; + +struct aml_name_group *name_group_list = &root_group; +struct aml_local_stack *stack_top = NULL; + +struct aml_name * +aml_get_rootname() +{ + + return (&rootname); +} + +static struct aml_name * +aml_find_name(struct aml_name *parent, char *name) +{ + struct aml_name *result; + + if (!parent) + parent = &rootname; + for (result = parent->child; result; result = result->brother) + if (!strncmp(result->name, name, 4)) + break; + return (result); +} + +/* + * Parse given namesppace expression and find a first matched object + * under given level of the tree by depth first search. + */ + +struct aml_name * +aml_find_from_namespace(struct aml_name *parent, char *name) +{ + char *ptr; + int len; + struct aml_name *result; + + ptr = name; + if (!parent) + parent = &rootname; + + if (ptr[0] == '\\') { + ptr++; + parent = &rootname; + } + for (len = 0; ptr[len] != '.' && ptr[len] != '\0'; len++) + ; + + for (result = parent->child; result; result = result->brother) { + if (!strncmp(result->name, ptr, len)) { + if (ptr[len] == '\0' || ptr[len + 1] == '\0') { + return (result); + } + ptr += len; + if (ptr[0] != '.') { + return (NULL); + } + ptr++; + return (aml_find_from_namespace(result, ptr)); + } + } + + return (NULL); +} + +static void +_aml_apply_foreach_found_objects(struct aml_name *parent, char *name, + int len, int shallow, int (*func)(struct aml_name *, va_list), va_list ap) +{ + struct aml_name *child, *ptr; + + child = ptr = NULL; + + /* function to apply must be specified */ + if (func == NULL) { + return; + } + + for (child = parent->child; child; child = child->brother) { + if (!strncmp(child->name, name, len)) { + /* if function call was failed, stop searching */ + if (func(child, ap) != 0) { + return; + } + } + } + + if (shallow == 1) { + return; + } + + for (ptr = parent->child; ptr; ptr = ptr->brother) { + /* do more searching */ + _aml_apply_foreach_found_objects(ptr, name, len, 0, func, ap); + } +} + +/* + * Find named objects as many as possible under given level of + * namespace, and apply given callback function for each + * named objects found. If the callback function returns non-zero + * value, then the search terminates immediately. + * Note that object name expression is used as forward substring match, + * not exact match. The name expression "_L" will match for objects + * which have name starting with "_L" such as "\_SB_.LID_._LID" and + * "\_GPE._L00" and so on. The name expression can include parent object + * name in it like "\_GPE._L". In this case, GPE X level wake handlers + * will be found under "\_GPE" in shallow level. + */ + +void +aml_apply_foreach_found_objects(struct aml_name *start, char *name, + int (*func)(struct aml_name *, va_list), ...) +{ + int i, len, has_dot, last_is_dot, shallow; + struct aml_name *child, *parent; + va_list ap; + + shallow = 0; + parent = start; + if (name[0] == '\\') { + name++; + parent = &rootname; + shallow = 1; + } + + len = strlen(name); + last_is_dot = 0; + /* the last dot should be ignored */ + if (len > 0 && name[len - 1] == '.') { + len--; + last_is_dot = 1; + } + + has_dot = 0; + for (i = 0; i < len - 1; i++) { + if (name[i] == '.') { + has_dot = 1; + break; + } + } + + /* try to parse expression and find any matched object. */ + if (has_dot == 1) { + child = aml_find_from_namespace(parent, name); + if (child == NULL) { + return; + } + + /* + * we have at least one object matched, search all objects + * under upper level of the found object. + */ + parent = child->parent; + + /* find the last `.' */ + for (name = name + len - 1; *name != '.'; name--) + ; + name++; + len = strlen(name) - last_is_dot; + shallow = 1; + } + + if (len > 4) { + return; + } + + va_start(ap, func); + _aml_apply_foreach_found_objects(parent, name, len, shallow, func, ap); + va_end(ap); +} + +struct aml_name_group * +aml_new_name_group(int id) +{ + struct aml_name_group *result; + + result = memman_alloc(aml_memman, memid_aml_name_group); + result->id = id; + result->head = NULL; + result->next = name_group_list; + name_group_list = result; + return (result); +} + +void +aml_delete_name_group(struct aml_name_group *target) +{ + struct aml_name_group *previous; + + previous = name_group_list; + if (previous == target) + name_group_list = target->next; + else { + while (previous && previous->next != target) + previous = previous->next; + if (previous) + previous->next = target->next; + } + target->next = NULL; + if (target->head) + aml_delete_name(target->head); + memman_free(aml_memman, memid_aml_name_group, target); +} + +static struct aml_name * +aml_new_name(struct aml_name *parent, char *name) +{ + struct aml_name *newname; + + if ((newname = aml_find_name(parent, name)) != NULL) + return (newname); + + newname = memman_alloc(aml_memman, memid_aml_name); + strncpy(newname->name, name, 4); + newname->parent = parent; + newname->child = NULL; + newname->property = NULL; + if (parent->child) + newname->brother = parent->child; + else + newname->brother = NULL; + parent->child = newname; + + newname->chain = name_group_list->head; + name_group_list->head = newname; + + return (newname); +} + +/* + * NOTE: + * aml_delete_name() doesn't maintain aml_name_group::{head,tail}. + */ +static void +aml_delete_name(struct aml_name *target) +{ + struct aml_name *next; + struct aml_name *ptr; + + for (; target; target = next) { + next = target->chain; + if (target->child) { + target->chain = NULL; + continue; + } + if (target->brother) { + if (target->parent) { + if (target->parent->child == target) { + target->parent->child = target->brother; + } else { + ptr = target->parent->child; + while (ptr && ptr->brother != target) + ptr = ptr->brother; + if (ptr) + ptr->brother = target->brother; + } + target->brother = NULL; + } + } else if (target->parent) { + target->parent->child = NULL; + } + aml_free_object(&target->property); + memman_free(aml_memman, memid_aml_name, target); + } +} + +#define AML_SEARCH_NAME 0 +#define AML_CREATE_NAME 1 +static struct aml_name *aml_nameman(struct aml_environ *, u_int8_t *, int); + +struct aml_name * +aml_search_name(struct aml_environ *env, u_int8_t *dp) +{ + + return (aml_nameman(env, dp, AML_SEARCH_NAME)); +} + +struct aml_name * +aml_create_name(struct aml_environ *env, u_int8_t *dp) +{ + + return (aml_nameman(env, dp, AML_CREATE_NAME)); +} + +static struct aml_name * +aml_nameman(struct aml_environ *env, u_int8_t *dp, int flag) +{ + int segcount; + int i; + struct aml_name *newname, *curname; + struct aml_name *(*searchfunc) (struct aml_name *, char *); + +#define CREATECHECK() do { \ + if (newname == NULL) { \ + AML_DEBUGPRINT("ERROR CANNOT FIND NAME\n"); \ + env->stat = aml_stat_panic; \ + return (NULL); \ + } \ +} while(0) + + searchfunc = (flag == AML_CREATE_NAME) ? aml_new_name : aml_find_name; + newname = env->curname; + if (dp[0] == '\\') { + newname = &rootname; + dp++; + } else if (dp[0] == '^') { + while (dp[0] == '^') { + newname = newname->parent; + CREATECHECK(); + dp++; + } + } + if (dp[0] == 0x00) { /* NullName */ + dp++; + } else if (dp[0] == 0x2e) { /* DualNamePrefix */ + newname = (*searchfunc) (newname, dp + 1); + CREATECHECK(); + newname = (*searchfunc) (newname, dp + 5); + CREATECHECK(); + } else if (dp[0] == 0x2f) { /* MultiNamePrefix */ + segcount = dp[1]; + for (i = 0, dp += 2; i < segcount; i++, dp += 4) { + newname = (*searchfunc) (newname, dp); + CREATECHECK(); + } + } else if (flag == AML_CREATE_NAME) { /* NameSeg */ + newname = aml_new_name(newname, dp); + CREATECHECK(); + } else { + curname = newname; + for (;;) { + newname = aml_find_name(curname, dp); + if (newname != NULL) + break; + if (curname == &rootname) + break; + curname = curname->parent; + } + } + return (newname); +} + +#undef CREATECHECK + +struct aml_local_stack * +aml_local_stack_create() +{ + struct aml_local_stack *result; + + result = memman_alloc(aml_memman, memid_aml_local_stack); + memset(result, 0, sizeof(struct aml_local_stack)); + return (result); +} + +void +aml_local_stack_push(struct aml_local_stack *stack) +{ + + stack->next = stack_top; + stack_top = stack; +} + +struct aml_local_stack * +aml_local_stack_pop() +{ + struct aml_local_stack *result; + + result = stack_top; + stack_top = result->next; + result->next = NULL; + return (result); +} + +void +aml_local_stack_delete(struct aml_local_stack *stack) +{ + int i; + + for (i = 0; i < 8; i++) + aml_free_object(&stack->localvalue[i].property); + for (i = 0; i < 7; i++) + aml_free_object(&stack->argumentvalue[i].property); + aml_delete_name(stack->temporary); + memman_free(aml_memman, memid_aml_local_stack, stack); +} + +struct aml_name * +aml_local_stack_getLocalX(int index) +{ + + if (stack_top == NULL) + return (NULL); + return (&stack_top->localvalue[index]); +} + +struct aml_name * +aml_local_stack_getArgX(struct aml_local_stack *stack, int index) +{ + + if (!stack) + stack = stack_top; + if (stack == NULL) + return (NULL); + return (&stack->argumentvalue[index]); +} + +struct aml_name * +aml_create_local_object() +{ + struct aml_name *result; + + result = memman_alloc(aml_memman, memid_aml_name); + result->child = result->brother = result->parent = NULL; + result->property = NULL; + result->chain = stack_top->temporary; + stack_top->temporary = result; + return (result); +} diff --git a/usr.sbin/acpi/amldb/aml/aml_name.h b/usr.sbin/acpi/amldb/aml/aml_name.h new file mode 100644 index 0000000..ab203ce --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_name.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * Copyright (c) 1999, 2000 Yasuo Yokoyama + * 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: aml_name.h,v 1.17 2000/08/16 18:14:54 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_NAME_H_ +#define _AML_NAME_H_ + +#include <machine/stdarg.h> + +#include <dev/acpi/aml/aml_obj.h> + +struct aml_name { + char name[4]; + union aml_object *property; + struct aml_name *parent; + struct aml_name *brother; + struct aml_name *child; + struct aml_name *chain; +}; + +#define AML_NAME_GROUP_ROOT 0 +#define AML_NAME_GROUP_OS_DEFINED 1 +#define AML_NAME_GROUP_IN_METHOD 2 + +struct aml_name_group { + int id; /* DSDT address or DBHANDLE */ + struct aml_name *head; + struct aml_name_group *next; +}; + +struct aml_local_stack { + struct aml_name localvalue[8]; + struct aml_name argumentvalue[7]; + struct aml_name *temporary; + struct aml_local_stack *next; +}; + +/* forward declarement */ +struct aml_envrion; + +struct aml_name *aml_get_rootname(void); +struct aml_name_group *aml_new_name_group(int); +void aml_delete_name_group(struct aml_name_group *); + +struct aml_name *aml_find_from_namespace(struct aml_name *, char *); +void aml_apply_foreach_found_objects(struct aml_name *, + char *, int (*)(struct aml_name *, va_list), ...); +struct aml_name *aml_search_name(struct aml_environ *, u_int8_t *); +struct aml_name *aml_create_name(struct aml_environ *, u_int8_t *); + +struct aml_local_stack *aml_local_stack_create(void); +void aml_local_stack_push(struct aml_local_stack *); +struct aml_local_stack *aml_local_stack_pop(void); +void aml_local_stack_delete(struct aml_local_stack *); +struct aml_name *aml_local_stack_getLocalX(int); +struct aml_name *aml_local_stack_getArgX(struct aml_local_stack *, int); +struct aml_name *aml_create_local_object(void); + +extern struct aml_name_group *name_group_list; + +#endif /* !_AML_NAME_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_obj.c b/usr.sbin/acpi/amldb/aml/aml_obj.c new file mode 100644 index 0000000..6634d43 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_obj.c @@ -0,0 +1,265 @@ +/*- + * 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: aml_obj.c,v 1.17 2000/08/12 15:20:45 iwasaki Exp $ + * $FreeBSD$ + */ + +#include <sys/param.h> + +#include <dev/acpi/aml/aml_amlmem.h> +#include <dev/acpi/aml/aml_env.h> +#include <dev/acpi/aml/aml_name.h> +#include <dev/acpi/aml/aml_obj.h> +#include <dev/acpi/aml/aml_status.h> +#include <dev/acpi/aml/aml_store.h> + +#ifndef _KERNEL +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#else /* _KERNEL */ +#include <sys/bus.h> +#include <sys/systm.h> +#endif /* !_KERNEL */ + +union aml_object * +aml_copy_object(struct aml_environ *env, union aml_object *orig) +{ + int i; + union aml_object *ret; + + if (orig == NULL) + return (NULL); + switch (orig->type) { + case aml_t_regfield: + ret = aml_alloc_object(aml_t_buffer, 0); + ret->buffer.size = (orig->regfield.bitlen / 8) + + ((orig->regfield.bitlen % 8) ? 1 : 0); + if (ret->buffer.size == 0) { + goto out; + } + ret->buffer.data = memman_alloc_flexsize(aml_memman, ret->buffer.size); + aml_store_to_object(env, orig, ret); + break; + + default: + ret = aml_alloc_object(0, orig); + break; + } + + if (1 || orig != &env->tempobject) { /* XXX */ + if (orig->type == aml_t_buffer) { + if (orig->buffer.size == 0) { + goto out; + } + ret->buffer.data = memman_alloc_flexsize(aml_memman, + orig->buffer.size); + bcopy(orig->buffer.data, ret->buffer.data, orig->buffer.size); + } else if (orig->type == aml_t_package) { + if (ret->package.elements == 0) { + goto out; + } + ret->package.objects = memman_alloc_flexsize(aml_memman, + ret->package.elements * sizeof(union aml_object *)); + for (i = 0; i < ret->package.elements; i++) { + ret->package.objects[i] = aml_copy_object(env, orig->package.objects[i]); + } + } else if (orig->type == aml_t_string && orig->str.needfree != 0) { + ret->str.string = memman_alloc_flexsize(aml_memman, + strlen(orig->str.string) + 1); + strcpy(orig->str.string, ret->str.string); + } else if (orig->type == aml_t_num) { + ret->num.constant = 0; + } + } else { + printf("%s:%d\n", __FILE__, __LINE__); + env->tempobject.type = aml_t_null; + } +out: + return ret; +} + +/* + * This function have two function: copy or allocate. if orig != NULL, + * orig is duplicated. + */ + +union aml_object * +aml_alloc_object(enum aml_objtype type, union aml_object *orig) +{ + unsigned int memid; + union aml_object *ret; + + if (orig != NULL) { + type = orig->type; + } + switch (type) { + case aml_t_namestr: + memid = memid_aml_namestr; + break; + case aml_t_buffer: + memid = memid_aml_buffer; + break; + case aml_t_string: + memid = memid_aml_string; + break; + case aml_t_bufferfield: + memid = memid_aml_bufferfield; + break; + case aml_t_package: + memid = memid_aml_package; + break; + case aml_t_num: + memid = memid_aml_num; + break; + case aml_t_powerres: + memid = memid_aml_powerres; + break; + case aml_t_opregion: + memid = memid_aml_opregion; + break; + case aml_t_method: + memid = memid_aml_method; + break; + case aml_t_processor: + memid = memid_aml_processor; + break; + case aml_t_field: + memid = memid_aml_field; + break; + case aml_t_mutex: + memid = memid_aml_mutex; + break; + case aml_t_device: + memid = memid_aml_objtype; + break; + case aml_t_objref: + memid = memid_aml_objref; + break; + default: + memid = memid_aml_objtype; + break; + } + ret = memman_alloc(aml_memman, memid); + ret->type = type; + + if (orig != NULL) { + bcopy(orig, ret, memman_memid2size(aml_memman, memid)); + } + return (ret); +} + +void +aml_free_objectcontent(union aml_object *obj) +{ + int i; + + if (obj->type == aml_t_buffer && obj->buffer.data != NULL) { + memman_free_flexsize(aml_memman, obj->buffer.data); + obj->buffer.data = NULL; + } + if (obj->type == aml_t_string && obj->str.string != NULL) { + if (obj->str.needfree != 0) { + memman_free_flexsize(aml_memman, obj->str.string); + obj->str.string = NULL; + } + } + if (obj->type == aml_t_package && obj->package.objects != NULL) { + for (i = 0; i < obj->package.elements; i++) { + aml_free_object(&obj->package.objects[i]); + } + memman_free_flexsize(aml_memman, obj->package.objects); + obj->package.objects = NULL; + } +} + +void +aml_free_object(union aml_object **obj) +{ + union aml_object *body; + + body = *obj; + if (body == NULL) { + return; + } + aml_free_objectcontent(*obj); + memman_free(aml_memman, memid_unkown, *obj); + *obj = NULL; +} + +void +aml_realloc_object(union aml_object *obj, int size) +{ + int i; + enum aml_objtype type; + union aml_object tmp; + + type = obj->type; + switch (type) { + case aml_t_buffer: + if (obj->buffer.size >= size) { + return; + } + tmp.buffer.size = size; + tmp.buffer.data = memman_alloc_flexsize(aml_memman, size); + bzero(tmp.buffer.data, size); + bcopy(obj->buffer.data, tmp.buffer.data, obj->buffer.size); + aml_free_objectcontent(obj); + *obj = tmp; + break; + case aml_t_string: + if (strlen(obj->str.string) >= size) { + return; + } + tmp.str.string = memman_alloc_flexsize(aml_memman, size + 1); + strcpy(tmp.str.string, obj->str.string); + aml_free_objectcontent(obj); + *obj = tmp; + break; + case aml_t_package: + if (obj->package.elements >= size) { + return; + } + tmp.package.objects = memman_alloc_flexsize(aml_memman, + size * sizeof(union aml_object *)); + bzero(tmp.package.objects, size * sizeof(union aml_object *)); + for (i = 0; i < obj->package.elements; i++) { + tmp.package.objects[i] = obj->package.objects[i]; + } + memman_free_flexsize(aml_memman, obj->package.objects); + obj->package.objects = tmp.package.objects; + break; + default: + break; + } +} diff --git a/usr.sbin/acpi/amldb/aml/aml_obj.h b/usr.sbin/acpi/amldb/aml/aml_obj.h new file mode 100644 index 0000000..45546e7 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_obj.h @@ -0,0 +1,227 @@ +/*- + * 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: aml_obj.h,v 1.15 2000/08/09 14:47:43 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_OBJ_H_ +#define _AML_OBJ_H_ + +#include <sys/queue.h> + +struct aml_environ; +enum aml_objtype { + aml_t_namestr = -3, + aml_t_regfield, + aml_t_objref, + aml_t_null = 0, + aml_t_num, + aml_t_string, + aml_t_buffer, + aml_t_package, + aml_t_device, + aml_t_field, + aml_t_event, + aml_t_method, + aml_t_mutex, + aml_t_opregion, + aml_t_powerres, + aml_t_processor, + aml_t_therm, + aml_t_bufferfield, + aml_t_ddbhandle, + aml_t_debug +}; + +struct aml_namestr { + enum aml_objtype type; /* =aml_t_namestr */ + u_int8_t *dp; +}; + +struct aml_opregion { + enum aml_objtype type; + int space; + int offset; + int length; +}; + +struct aml_num { + enum aml_objtype type; /* =aml_t_num */ + int number; + int constant; +}; + +struct aml_package { + enum aml_objtype type; + int elements; + union aml_object **objects; +}; + +struct aml_string { + enum aml_objtype type; /* =aml_t_string */ + int needfree; + u_int8_t *string; +}; + +struct aml_buffer { + enum aml_objtype type; /* =aml_t_buffer */ + int size; + u_int8_t *data; /* This should be free when + * this object is free. + */ +}; + +enum fieldtype { + f_t_field, + f_t_index, + f_t_bank +}; + +struct nfieldd { + enum fieldtype ftype; /* f_t_field */ + u_int8_t *regname; /* Namestring */ +}; + +struct ifieldd { + enum fieldtype ftype; /* f_t_index */ + u_int8_t *indexname; + u_int8_t *dataname; +}; + +struct bfieldd { + enum fieldtype ftype; /* f_t_bank */ + u_int8_t *regname; + u_int8_t *bankname; + u_int32_t bankvalue; +}; + +struct aml_field { + enum aml_objtype type; + u_int32_t flags; + int bitoffset; /* Not Byte offset but bitoffset */ + int bitlen; + union { + enum fieldtype ftype; + struct nfieldd fld; + struct ifieldd ifld; + struct bfieldd bfld; + } f; +}; + +struct aml_bufferfield { + enum aml_objtype type; /* aml_t_bufferfield */ + int bitoffset; + int bitlen; + u_int8_t *origin; /* This should not be free + * when this object is free + * (Within Buffer object) + */ +}; + +struct aml_method { + enum aml_objtype type; + int argnum; /* Not argnum but argnum|frag */ + u_int8_t *from; + u_int8_t *to; +}; + +struct aml_powerres { + enum aml_objtype type; + int level; + int order; +}; + +struct aml_processor { + enum aml_objtype type; + int id; + int addr; + int len; +}; + +struct aml_mutex_queue { + STAILQ_ENTRY(aml_mutex_queue) entry; +}; + +struct aml_mutex { + enum aml_objtype type; + int level; + volatile void *cookie; /* In kernel, struct proc? */ + STAILQ_HEAD(, aml_mutex_queue) queue; +}; + +struct aml_objref { + enum aml_objtype type; + struct aml_name *nameref; + union aml_object *ref; + int offset; /* of aml_buffer.data or aml_package.objects. */ + /* if negative value, not ready to dereference for element access. */ + unsigned deref; /* indicates whether dereffenced or not */ + unsigned alias; /* true if this is an alias object reference */ +}; + +struct aml_regfield { + enum aml_objtype type; + int space; + u_int32_t flags; + int offset; + int bitoffset; + int bitlen; +}; + +struct aml_event { + enum aml_objtype type; /* aml_t_event */ + int inuse; +}; + +union aml_object { + enum aml_objtype type; + struct aml_num num; + struct aml_processor proc; + struct aml_powerres pres; + struct aml_opregion opregion; + struct aml_method meth; + struct aml_field field; + struct aml_mutex mutex; + struct aml_namestr nstr; + struct aml_buffer buffer; + struct aml_bufferfield bfld; + struct aml_package package; + struct aml_string str; + struct aml_objref objref; + struct aml_event event; + struct aml_regfield regfield; +}; + +union aml_object *aml_copy_object(struct aml_environ *, + union aml_object *); +union aml_object *aml_alloc_object(enum aml_objtype, + union aml_object *); +void aml_free_objectcontent(union aml_object *); +void aml_free_object(union aml_object **); +void aml_realloc_object(union aml_object *, int); + +#endif /* !_AML_OBJ_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_parse.c b/usr.sbin/acpi/amldb/aml/aml_parse.c new file mode 100644 index 0000000..344eb6c --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_parse.c @@ -0,0 +1,1998 @@ +/*- + * Copyright (c) 1999 Doug Rabson + * 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: aml_parse.c,v 1.32 2000/08/12 15:20:45 iwasaki Exp $ + * $FreeBSD$ + */ + +#include <sys/param.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_evalobj.h> +#include <dev/acpi/aml/aml_name.h> +#include <dev/acpi/aml/aml_obj.h> +#include <dev/acpi/aml/aml_parse.h> +#include <dev/acpi/aml/aml_status.h> +#include <dev/acpi/aml/aml_store.h> + +#ifndef _KERNEL +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/bus.h> +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static int findsetleftbit(int num); +static int findsetrightbit(int num); +static int frombcd(int num); +static int tobcd(int num); + +static u_int32_t aml_parse_pkglength(struct aml_environ *env); +static u_int8_t aml_parse_bytedata(struct aml_environ *env); +static u_int16_t aml_parse_worddata(struct aml_environ *env); +static u_int32_t aml_parse_dworddata(struct aml_environ *env); +static u_int8_t *aml_parse_namestring(struct aml_environ *env); +static void aml_parse_defscope(struct aml_environ *env, + int indent); +static union aml_object *aml_parse_defbuffer(struct aml_environ *env, + int indent); +static struct aml_name *aml_parse_concat_number(struct aml_environ *env, + int num1, int indent); +static struct aml_name *aml_parse_concat_buffer(struct aml_environ *env, + union aml_object *obj, + int indent); +static struct aml_name *aml_parse_concat_string(struct aml_environ *env, + union aml_object *obj, + int indent); +static struct aml_name *aml_parse_concatop(struct aml_environ *env, + int indent); +static union aml_object *aml_parse_defpackage(struct aml_environ *env, + int indent); +static void aml_parse_defmethod(struct aml_environ *env, + int indent); +static void aml_parse_defopregion(struct aml_environ *env, + int indent); +static int aml_parse_field(struct aml_environ *env, + struct aml_field *template); +static void aml_parse_fieldlist(struct aml_environ *env, + struct aml_field *template, + int indent); +static void aml_parse_deffield(struct aml_environ *env, + int indent); +static void aml_parse_defindexfield(struct aml_environ *env, + int indent); +static void aml_parse_defbankfield(struct aml_environ *env, + int indent); +static void aml_parse_defdevice(struct aml_environ *env, + int indent); +static void aml_parse_defprocessor(struct aml_environ *env, + int indent); +static void aml_parse_defpowerres(struct aml_environ *env, + int indent); +static void aml_parse_defthermalzone(struct aml_environ *env, + int indent); +static struct aml_name *aml_parse_defelse(struct aml_environ *env, + int indent, int num); +static struct aml_name *aml_parse_defif(struct aml_environ *env, + int indent); +static struct aml_name *aml_parse_defwhile(struct aml_environ *env, + int indent); +static void aml_parse_defmutex(struct aml_environ *env, + int indent); +static void aml_createfield_generic(struct aml_environ *env, + union aml_object *srcbuf, + int index, int len, + char *newname); +static void aml_parse_defcreatefield(struct aml_environ *env, + int indent); + +static int +findsetleftbit(int num) +{ + int i, filter; + + filter = 0; + for (i = 0; i < 32; i++) { + filter = filter >> 1; + filter |= 1 << 31; + if (filter & num) { + break; + } + } + i = (i == 32) ? 0 : i + 1; + return (i); +} + +static int +findsetrightbit(int num) +{ + int i, filter; + + filter = 0; + for (i = 0; i < 32; i++) { + filter = filter << 1; + filter |= 1; + if (filter & num) { + break; + } + } + i = (i == 32) ? 0 : i + 1; + return (i); +} + +static int +frombcd(int num) +{ + int res, factor; + + res = 0; + factor = 1; + while (num != 0) { + res += ((num & 0xf) * factor); + num = num / 16; + factor *= 10; + } + return (res); +} + +static int +tobcd(int num) +{ + int res, factor; + + res = 0; + factor = 1; + while (num != 0) { + res += ((num % 10) * factor); + num = num / 10; + factor *= 16; + } + return (res); +} + +static u_int32_t +aml_parse_pkglength(struct aml_environ *env) +{ + u_int8_t *dp; + u_int32_t pkglength; + + dp = env->dp; + pkglength = *dp++; + switch (pkglength >> 6) { + case 0: + break; + case 1: + pkglength = (pkglength & 0xf) + (dp[0] << 4); + dp += 1; + break; + case 2: + pkglength = (pkglength & 0xf) + (dp[0] << 4) + (dp[1] << 12); + dp += 2; + break; + case 3: + pkglength = (pkglength & 0xf) + + (dp[0] << 4) + (dp[1] << 12) + (dp[2] << 20); + dp += 3; + break; + } + + env->dp = dp; + return (pkglength); +} + +static u_int8_t +aml_parse_bytedata(struct aml_environ *env) +{ + u_int8_t data; + + data = env->dp[0]; + env->dp++; + return (data); +} + +static u_int16_t +aml_parse_worddata(struct aml_environ *env) +{ + u_int16_t data; + + data = env->dp[0] + (env->dp[1] << 8); + env->dp += 2; + return (data); +} + +static u_int32_t +aml_parse_dworddata(struct aml_environ *env) +{ + u_int32_t data; + + data = env->dp[0] + (env->dp[1] << 8) + + (env->dp[2] << 16) + (env->dp[3] << 24); + env->dp += 4; + return (data); +} + +static u_int8_t * +aml_parse_namestring(struct aml_environ *env) +{ + u_int8_t *name; + int segcount; + + name = env->dp; + if (env->dp[0] == '\\') + env->dp++; + else if (env->dp[0] == '^') + while (env->dp[0] == '^') + env->dp++; + if (env->dp[0] == 0x00) /* NullName */ + env->dp++; + else if (env->dp[0] == 0x2e) /* DualNamePrefix */ + env->dp += 1 + 4 + 4; /* NameSeg, NameSeg */ + else if (env->dp[0] == 0x2f) { /* MultiNamePrefix */ + segcount = env->dp[1]; + env->dp += 1 + 1 + segcount * 4; /* segcount * NameSeg */ + } else + env->dp += 4; /* NameSeg */ + + return (name); +} + +struct aml_name * +aml_parse_objectlist(struct aml_environ *env, int indent) +{ + union aml_object *obj; + + obj = NULL; + while (env->dp < env->end) { + aml_print_indent(indent); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT("\n"); + if (env->stat == aml_stat_step) { + AML_DEBUGGER(env, env); + continue; + } + if (env->stat != aml_stat_none) { + env->tempname.property = obj; + return (&env->tempname); + } + } + return (NULL); +} + +#define AML_CREATE_NAME(amlname, env, namestr, ret) do { \ + amlname = aml_create_name(env, namestr); \ + if (env->stat == aml_stat_panic) \ + return ret; \ +} while(0) + +#define AML_COPY_OBJECT(dest, env, src, ret) do { \ + dest = aml_copy_object(env, src); \ + if (dest == NULL) { \ + env->stat = aml_stat_panic; \ + return ret; \ + } \ +} while(0) + +#define AML_ALLOC_OBJECT(dest, env, type, ret) do { \ + dest = aml_alloc_object(type, NULL); \ + if (dest == NULL) { \ + env->stat= aml_stat_panic; \ + return ret; \ + } \ +} while(0) + +static void +aml_parse_defscope(struct aml_environ *env, int indent) +{ + u_int8_t *start, *end, *oend; + u_int8_t *name; + u_int32_t pkglength; + struct aml_name *oname; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + + AML_DEBUGPRINT("Scope("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_DEBUGPRINT(") {\n"); + oname = env->curname; + AML_CREATE_NAME(env->curname, env, name,); + oend = env->end; + env->end = end = start + pkglength; + aml_parse_objectlist(env, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + AML_SYSASSERT(env->dp == env->end); + env->dp = end; + env->end = oend; + env->curname = oname; + env->stat = aml_stat_none; +} + +static union aml_object * +aml_parse_defbuffer(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *end; + u_int8_t *buffer; + u_int32_t pkglength; + int size1, size2, size; + union aml_object *obj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + end = start + pkglength; + + AML_DEBUGPRINT("Buffer("); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + size1 = aml_objtonum(env, obj); + size2 = end - env->dp; + size = (size1 < size2) ? size1 : size2; + if (size1 > 0) { + buffer = memman_alloc_flexsize(aml_memman, size1); + if (buffer == NULL) { + AML_DEBUGPRINT("NO MEMORY\n"); + env->stat = aml_stat_panic; + return (NULL); + } + bzero(buffer, size1); + bcopy(env->dp, buffer, size); + } else { + buffer = NULL; + } + + obj = &env->tempobject; + obj->type = aml_t_buffer; + obj->buffer.size = size1; + obj->buffer.data = buffer; + AML_DEBUGPRINT(") "); + env->dp = end; + + return (obj); +} + +static struct aml_name * +aml_parse_concat_number(struct aml_environ *env, int num1, int indent) +{ + int num2; + struct aml_name *destname; + union aml_object *obj; + + num2 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + destname = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + obj = &env->tempobject; + obj->type = aml_t_buffer; + obj->buffer.size = 2; + obj->buffer.data = memman_alloc_flexsize(aml_memman, 2); + if (obj->buffer.data == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + obj->buffer.data[0] = num1 & 0xff; + obj->buffer.data[1] = num2 & 0xff; + aml_store_to_name(env, obj, destname); + return (&env->tempname); +} + +static struct aml_name * +aml_parse_concat_buffer(struct aml_environ *env, union aml_object *obj, + int indent) +{ + union aml_object *tmpobj, *tmpobj2, *resobj; + struct aml_name *destname; + + tmpobj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + if (tmpobj->type != aml_t_buffer) { + env->stat = aml_stat_panic; + return (NULL); + } + AML_COPY_OBJECT(tmpobj2, env, tmpobj, NULL); + destname = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + resobj = &env->tempobject; + env->tempname.property = resobj; + resobj->buffer.type = aml_t_buffer; + resobj->buffer.size = tmpobj2->buffer.size + obj->buffer.size; + if (resobj->buffer.size > 0) { + resobj->buffer.data = memman_alloc_flexsize(aml_memman, + resobj->buffer.size); + if (resobj->buffer.data == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + bcopy(obj->buffer.data, resobj->buffer.data, obj->buffer.size); + bcopy(tmpobj2->buffer.data, + resobj->buffer.data + obj->buffer.size, + tmpobj2->buffer.size); + } else { + resobj->buffer.data = NULL; + } + aml_free_object(&tmpobj2); + aml_store_to_name(env, resobj, destname); + return (&env->tempname); +} + +static struct aml_name * +aml_parse_concat_string(struct aml_environ *env, union aml_object *obj, + int indent) +{ + int len; + union aml_object *tmpobj, *tmpobj2, *resobj; + struct aml_name *destname; + + tmpobj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + if (tmpobj->type != aml_t_string) { + env->stat = aml_stat_panic; + return (NULL); + } + AML_COPY_OBJECT(tmpobj2, env, tmpobj, NULL); + destname = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + resobj = &env->tempobject; + env->tempname.property = resobj; + resobj->type = aml_t_buffer; + resobj->str.needfree = 1; + len = strlen(obj->str.string) + strlen(tmpobj2->str.string) + 1; + if (len > 0) { + resobj->str.string = memman_alloc_flexsize(aml_memman, len); + if (resobj->str.string == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + strncpy(resobj->str.string, obj->str.string, len); + strcat(resobj->str.string, tmpobj->str.string); + } else { + resobj->str.string = NULL; + } + aml_free_object(&tmpobj2); + aml_store_to_name(env, resobj, destname); + return (&env->tempname); +} + +static struct aml_name * +aml_parse_concatop(struct aml_environ *env, int indent) +{ + union aml_object *obj, *tmpobj; + struct aml_name *aname; + + AML_DEBUGPRINT("Concat("); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + switch (obj->type) { + case aml_t_num: + aname = aml_parse_concat_number(env, aml_objtonum(env, obj), indent); + break; + + case aml_t_buffer: + /* obj may be temporal object */ + AML_COPY_OBJECT(tmpobj, env, obj, NULL); + aname = aml_parse_concat_buffer(env, obj, indent); + aml_free_object(&tmpobj); + break; + + case aml_t_string: + /* obj may be temporal object */ + AML_COPY_OBJECT(tmpobj, env, obj, NULL); + aname = aml_parse_concat_string(env, obj, indent); + aml_free_object(&tmpobj); + break; + + default: + env->stat = aml_stat_panic; + aname = NULL; + break; + } + + AML_DEBUGPRINT("\n"); + return (aname); +} + +static union aml_object * +aml_parse_defpackage(struct aml_environ *env, int indent) +{ + u_int8_t numelements; + u_int8_t *start; + u_int32_t pkglength; + int i; + struct aml_environ *copy; + struct aml_name *tmpname; + union aml_object *obj, **objects; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + numelements = aml_parse_bytedata(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + if (numelements > 0) { + objects = memman_alloc_flexsize(aml_memman, + numelements * sizeof(union aml_object *)); + if (objects == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } else { + bzero(objects, numelements * sizeof(union aml_object *)); + } + } else { + objects = NULL; + } + + *copy = *env; + env->dp = copy->end = start + pkglength; + AML_DEBUGPRINT("Package() {\n"); + i = 0; + while ((copy->dp < copy->end) && (i < numelements)) { + aml_print_indent(indent + 1); + tmpname = aml_parse_termobj(copy, indent + 1); + + if (tmpname != NULL) { + objects[i] = aml_copy_object(copy, tmpname->property); + } + AML_DEBUGPRINT(",\n"); + i++; + } + aml_free_objectcontent(©->tempobject); + + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + obj = &env->tempobject; + obj->type = aml_t_package; + obj->package.elements = numelements; + obj->package.objects = objects; + + memman_free(aml_memman, memid_aml_environ, copy); + return (obj); +} + +static void +aml_parse_defmethod(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start; + u_int32_t pkglength; + char *name; + struct aml_environ *copy; + struct aml_method *meth; + struct aml_name *aname; + union aml_object *aobj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("Method("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + AML_ALLOC_OBJECT(aobj, env, aml_t_method,); + meth = &aobj->meth; + aname->property = aobj; + flags = *env->dp++; + + if (flags) { + AML_DEBUGPRINT(", %d", flags); + } + AML_DEBUGPRINT(") {\n"); + *copy = *env; + meth->argnum = flags; + meth->from = env->dp; + meth->to = env->dp = copy->end = start + pkglength; + aml_print_indent(indent); + AML_DEBUGPRINT("}"); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defopregion(struct aml_environ *env, int indent) +{ + u_int8_t *name; + struct aml_name *aname; + struct aml_opregion *opregion; + union aml_object *obj; + const char *regions[] = { + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + }; + + AML_DEBUGPRINT("OperationRegion("); + /* Name */ + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return; + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_opregion,); + opregion = &aname->property->opregion; + opregion->space = *env->dp; + AML_DEBUGPRINT(", %s, ", regions[*env->dp]); /* Space */ + env->dp++; + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); /* Offset */ + opregion->offset = aml_objtonum(env, obj); + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); /* Length */ + opregion->length = aml_objtonum(env, obj); + AML_DEBUGPRINT(")"); +} + +static const char *accessnames[] = { + "AnyAcc", + "ByteAcc", + "WordAcc", + "DWordAcc", + "BlockAcc", + "SMBSendRecvAcc", + "SMBQuickAcc" +}; + +static int +aml_parse_field(struct aml_environ *env, struct aml_field *template) +{ + u_int8_t *name; + u_int8_t access, attribute; + u_int32_t width; + struct aml_name *aname; + struct aml_field *prop; + + switch (*env->dp) { + case '\\': + case '^': + case 'A'...'Z': + case '_': + case '.': + name = aml_parse_namestring(env); + width = aml_parse_pkglength(env); + template->bitlen = width; + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + /* Allignment */ + if (width == 16) { + template->bitoffset += 15; + template->bitoffset &= (~15); + } + if (width == 32) { + template->bitoffset += 31; + template->bitoffset &= (~31); + } else if ((width & 7) == 0) { + template->bitoffset += 7; + template->bitoffset &= (~7); + } else if ((width > 32) && (width & 7) != 0) { + AML_DEBUGPRINT("??? Can I treat it?\n"); + } + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return (NULL); + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_field, NULL); + prop = &aname->property->field; + *prop = *template; + template->bitoffset += width; + AML_DEBUGPRINT(",\t%d", width); + break; + case 0x00: + env->dp++; + width = aml_parse_pkglength(env); + template->bitoffset += width; + AML_DEBUGPRINT("Offset(0x%x)", template->bitoffset); + break; + case 0x01: + access = env->dp[1]; + attribute = env->dp[2]; + env->dp += 3; + AML_DEBUGPRINT("AccessAs(%s, %d)", accessnames[access], attribute); + template->bitoffset = attribute; + template->flags = (template->flags | 0xf0) | access; + break; + } + return (template->bitoffset); +} + +static void +aml_parse_fieldlist(struct aml_environ *env, struct aml_field *template, + int indent) +{ + u_int32_t offset; + + offset = 0; + while (env->dp < env->end) { + aml_print_indent(indent); + offset = aml_parse_field(env, template); + if (env->dp < env->end) { + AML_DEBUGPRINT(",\n"); + } else { + AML_DEBUGPRINT("\n"); + } + } +} + +static void +aml_parse_deffield(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start, *name; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_field fieldtemplate; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("Field("); + aml_print_namestring(name = aml_parse_namestring(env)); + fieldtemplate.type = aml_t_field; + flags = aml_parse_bytedata(env); + fieldtemplate.flags = fieldtemplate.flags = flags; + + *copy = *env; + env->dp = copy->end = start + pkglength; + fieldtemplate.bitoffset = 0; + fieldtemplate.bitlen = 0; + fieldtemplate.f.ftype = f_t_field; + fieldtemplate.f.fld.regname = name; + AML_DEBUGPRINT(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + aml_parse_fieldlist(copy, &fieldtemplate, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defindexfield(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start, *iname, *dname; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_field template; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("IndexField("); + aml_print_namestring(iname = aml_parse_namestring(env)); /* Name1 */ + AML_DEBUGPRINT(", "); + aml_print_namestring(dname = aml_parse_namestring(env)); /* Name2 */ + template.type = aml_t_field; + template.flags = flags = aml_parse_bytedata(env); + template.bitoffset = 0; + template.bitlen = 0; + template.f.ftype = f_t_index; + template.f.ifld.indexname = iname; + template.f.ifld.dataname = dname; + AML_DEBUGPRINT(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + *copy = *env; + env->dp = copy->end = start + pkglength; + aml_parse_fieldlist(copy, &template, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defbankfield(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start, *rname, *bname; + u_int32_t pkglength, bankvalue; + struct aml_environ *copy; + struct aml_field template; + union aml_object *obj; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("BankField("); + aml_print_namestring(rname = aml_parse_namestring(env)); /* Name1 */ + AML_DEBUGPRINT(", "); + aml_print_namestring(bname = aml_parse_namestring(env)); /* Name2 */ + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); /* BankValue */ + bankvalue = aml_objtonum(env, obj); + template.type = aml_t_field; + template.flags = flags = aml_parse_bytedata(env); + template.bitoffset = 0; + template.bitlen = 0; + template.f.ftype = f_t_bank; + template.f.bfld.regname = rname; + template.f.bfld.bankname = bname; + template.f.bfld.bankvalue = bankvalue; + *copy = *env; + env->dp = copy->end = start + pkglength; + AML_DEBUGPRINT(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + aml_parse_fieldlist(copy, &template, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + + aml_free_objectcontent(©->tempobject); + AML_SYSASSERT(copy->dp == copy->end); + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defdevice(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("Device("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_DEBUGPRINT(") {\n"); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + AML_ALLOC_OBJECT(copy->curname->property, env, aml_t_device,); + env->dp = copy->end = start + pkglength; + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defprocessor(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_processor *proc; + union aml_object *obj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_ALLOC_OBJECT(obj, env, aml_t_processor,); + proc = &obj->proc; + AML_DEBUGPRINT("Processor("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + proc->id = aml_parse_bytedata(env); + proc->addr = aml_parse_dworddata(env); + proc->len = aml_parse_bytedata(env); + AML_DEBUGPRINT(", %d, 0x%x, 0x%x) {\n", proc->id, proc->addr, proc->len); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + copy->curname->property = obj; + env->dp = copy->end = start + pkglength; + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defpowerres(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_powerres *pres; + union aml_object *obj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("PowerResource("); + AML_ALLOC_OBJECT(obj, env, aml_t_powerres,); + name = aml_parse_namestring(env); + aml_print_namestring(name); + pres = &obj->pres; + pres->level = aml_parse_bytedata(env); + pres->order = aml_parse_worddata(env); + AML_DEBUGPRINT(", %d, %d) {\n", pres->level, pres->order); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + copy->curname->property = obj; + env->dp = copy->end = start + pkglength; + + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defthermalzone(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("ThermalZone("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_DEBUGPRINT(") {\n"); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + AML_ALLOC_OBJECT(copy->curname->property, env, aml_t_therm,); + env->dp = copy->end = start + pkglength; + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static struct aml_name * +aml_parse_defelse(struct aml_environ *env, int indent, int num) +{ + u_int8_t *start, *end, *oend; + u_int32_t pkglength; + struct aml_name *aname; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + oend = env->end; + env->end = end = start + pkglength; + aname = NULL; + + AML_DEBUGPRINT("Else {\n"); + if (num == 0) { + aname = aml_parse_objectlist(env, indent + 1); + aml_print_indent(indent); + } + AML_DEBUGPRINT("}"); + + env->dp = end; + env->end = oend; + return (aname); +} + +static struct aml_name * +aml_parse_defif(struct aml_environ *env, int indent) +{ + u_int8_t *start, *end, *oend; + u_int32_t pkglength; + int num; + struct aml_name *aname, *aname1; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + aname = NULL; + + AML_DEBUGPRINT("If("); + num = aml_objtonum(env, aml_eval_name + (env, aml_parse_termobj(env, indent))); + oend = env->end; + end = start + pkglength; + AML_DEBUGPRINT(")"); + if (num) { + AML_DEBUGPRINT("{\n"); + env->end = end; + aname = aml_parse_objectlist(env, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + } + env->dp = end; + env->end = oend; + if ((end < oend) && *(env->dp) == 0xa1) { + env->dp++; + aname1 = aml_parse_defelse(env, indent, num); + aname = (num == 0) ? aname1 : aname; + } + return (aname); +} + +static struct aml_name * +aml_parse_defwhile(struct aml_environ *env, int indent) +{ + u_int8_t *start, *end, *oend; + u_int32_t pkglength; + int num; + struct aml_name *aname; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + oend = env->end; + end = start + pkglength; + aname = NULL; + for (;;) { + env->dp = start; + aml_parse_pkglength(env); + AML_DEBUGPRINT("While("); + num = aml_objtonum(env, aml_eval_name + (env, aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(")"); + if (num == 0) { + break; + } + AML_DEBUGPRINT(" {\n"); + env->end = end; + aname = aml_parse_objectlist(env, indent + 1); + if (env->stat == aml_stat_step) { + AML_DEBUGGER(env, env); + continue; + } + if (env->stat != aml_stat_none) + break; + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + } + AML_DEBUGPRINT("\n"); + env->dp = end; + env->end = oend; + if (env->stat == aml_stat_break) { + env->stat = aml_stat_none; + aname = NULL; + } + return (aname); +} + +static void +aml_parse_defmutex(struct aml_environ *env, int indent) +{ + char *name; + struct aml_name *aname; + struct aml_mutex *mut; + + /* MutexOp */ + AML_DEBUGPRINT("Mutex("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return; + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_mutex,); + mut = &aname->property->mutex; + mut->level = *env->dp++; + STAILQ_INIT(&mut->queue); + AML_DEBUGPRINT(", %d)", mut->level); +} + +static void +aml_createfield_generic(struct aml_environ *env, + union aml_object *srcbuf, int index, + int len, char *newname) +{ + struct aml_bufferfield *field; + struct aml_name *aname; + + if (srcbuf == NULL || srcbuf->type != aml_t_buffer) { + AML_DEBUGPRINT("Not Buffer assigned,"); + env->stat = aml_stat_panic; + return; + } + AML_CREATE_NAME(aname, env, newname,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return; + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_bufferfield,); + field = &aname->property->bfld; + field->bitoffset = index; + field->bitlen = len; + field->origin = srcbuf->buffer.data; +} + +static void +aml_parse_defcreatefield(struct aml_environ *env, int indent) +{ + int index, len; + char *newname; + union aml_object *obj, *srcbuf; + + /* CreateFieldOp */ + AML_DEBUGPRINT("CreateField("); + srcbuf = aml_eval_name(env, aml_parse_termobj(env, indent)); + if (srcbuf == &env->tempobject) { + AML_DEBUGPRINT("NONAMED BUFFER\n"); + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + index = aml_objtonum(env, obj); + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + len = aml_objtonum(env, obj); + AML_DEBUGPRINT(", "); + newname = aml_parse_namestring(env); + aml_print_namestring(newname); + aml_createfield_generic(env, srcbuf, index, len, newname); + AML_DEBUGPRINT(") "); +} + +/* + * Returns Named object or parser buffer. The object need not be free because + * it returns preallocated buffer in env or Contain of named object. If You + * need to preserve object, create a copy and then store. And The object + * returned from this function is not valid after another call is + * shared, tempolary buffer may be shared. + */ +struct aml_name * +aml_parse_termobj(struct aml_environ *env, int indent) +{ + u_int8_t opcode; + u_int8_t *name; + int value; + int num1, num2; + int len; + int match1, match2, i, pkgval, start; + int widthindex, index; + char *newname; + struct aml_name *aname; + struct aml_name *destname1, *destname2; + struct aml_name *tmpname, *srcname; + struct aml_name *src; + union aml_object *ret; + union aml_object *tmpobj; + union aml_object anum; + union aml_object *objref; + union aml_object *srcobj; + union aml_object *obj; + union aml_object *srcbuf; + static int widthtbl[4] = {32, 16, 8, 1}; + const char *opname[4] = {"CreateDWordField", "CreateWordField", + "CreateByteField", "CreateBitField"}; + + aname = &env->tempname; + ret = &env->tempobject; + anum.type = aml_t_num; + aname->property = ret; + aml_free_objectcontent(ret); + if (env->stat == aml_stat_panic) { + /* + * If previosuly parser panic , parsing next instruction is + * prohibited. + */ + return (NULL); + } + aname = NULL; + opcode = *env->dp++; + switch (opcode) { + case '\\': + case '^': + case 'A' ... 'Z': + case '_': + case '.': + env->dp--; + ret->type = aml_t_namestr; + ret->nstr.dp = aml_parse_namestring(env); + aml_print_namestring(ret->nstr.dp); + aname = &env->tempname; + break; + case 0x0a: /* BytePrefix */ + ret->type = aml_t_num; + value = aml_parse_bytedata(env); + ret->num.number = value; + AML_DEBUGPRINT("0x%x", value); + aname = &env->tempname; + break; + case 0x0b: /* WordPrefix */ + ret->type = aml_t_num; + value = aml_parse_worddata(env); + ret->num.number = value; + AML_DEBUGPRINT("0x%x", value); + aname = &env->tempname; + break; + case 0x0c: /* DWordPrefix */ + ret->type = aml_t_num; + value = aml_parse_dworddata(env); + ret->num.number = value; + AML_DEBUGPRINT("0x%x", value); + aname = &env->tempname; + break; + case 0x0d: /* StringPrefix */ + ret->type = aml_t_string; + ret->str.string = env->dp; + len = strlen(env->dp); + ret->str.needfree = 0; + AML_DEBUGPRINT("\"%s\"", (const char *)ret->str.string); + env->dp += (len + 1); + aname = &env->tempname; + break; + case 0x00: /* ZeroOp */ + ret->type = aml_t_num; + ret->num.number = 0; + ret->num.constant = 1; + AML_DEBUGPRINT("Zero"); + aname = &env->tempname; + break; + case 0x01: /* OneOp */ + ret->type = aml_t_num; + ret->num.number = 1; + ret->num.constant = 1; + AML_DEBUGPRINT("One"); + aname = &env->tempname; + break; + case 0xff: /* OnesOp */ + ret->type = aml_t_num; + ret->num.number = 0xffffffff; + ret->num.constant = 1; + AML_DEBUGPRINT("Ones"); + aname = &env->tempname; + break; + case 0x06: /* AliasOp */ + AML_DEBUGPRINT("Alias("); + tmpname = aml_parse_termobj(env, indent); + if (env->stat == aml_stat_panic) { + return (NULL); + } + if (tmpname->property == NULL || + tmpname->property->type != aml_t_namestr) { + env->stat = aml_stat_panic; + return (NULL); + } + /* + * XXX if srcname is deleted after this object, what + * shall I do? + */ + srcname = aml_search_name(env, tmpname->property->nstr.dp); + AML_DEBUGPRINT(", "); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + aml_print_curname(aname); + return (NULL); + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_objref, NULL); + objref = aname->property; + objref->objref.nameref = srcname; + objref->objref.ref = srcname->property; + objref->objref.offset = -1; + objref->objref.alias = 1; /* Yes, this is an alias */ + AML_DEBUGPRINT(")"); + /* shut the interpreter up during the namespace initializing */ + return (NULL); + case 0x08: /* NameOp */ + AML_DEBUGPRINT("Name("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + if (env->stat == aml_stat_panic) { + AML_DEBUGPRINT("Already Defined \n"); + aml_print_curname(aname); + return (NULL); + } + AML_DEBUGPRINT(", "); + AML_COPY_OBJECT(aname->property, env, + aml_eval_name(env, + aml_parse_termobj(env, indent)), + NULL); + AML_DEBUGPRINT(")"); + break; + case 0x10: /* ScopeOp */ + aml_parse_defscope(env, indent); + break; + case 0x11: /* BufferOp */ + aname = &env->tempname; + aname->property = aml_parse_defbuffer(env, indent); + break; + case 0x12: /* PackageOp */ + aname = &env->tempname; + aname->property = aml_parse_defpackage(env, indent); + break; + case 0x14: /* MethodOp */ + aml_parse_defmethod(env, indent); + break; + case 0x5b: /* ExtOpPrefix */ + opcode = *env->dp++; + switch (opcode) { + case 0x01: + aml_parse_defmutex(env, indent); + break; + case 0x02: /* EventOp */ + AML_DEBUGPRINT("Event("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return (NULL); + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_event, NULL); + AML_DEBUGPRINT(")"); + return (NULL); + break; + case 0x12: /* CondRefOfOp */ + AML_DEBUGPRINT("CondRefOf("); + src = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + if (src == &env->tempname || src == NULL) { + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + anum.num.number = 0xffffffff; + env->tempobject.num = anum.num; + aname = &env->tempname; + break; + } + AML_ALLOC_OBJECT(objref, env, aml_t_objref, NULL); + if (src->property == NULL || + src->property->type != aml_t_namestr) { + objref->objref.nameref = src; + } else { + objref->objref.nameref = aml_create_local_object(); + } + objref->objref.ref = src->property; + objref->objref.offset = -1; /* different from IndexOp */ + + destname1 = aml_parse_termobj(env, indent); + aml_store_to_name(env, objref, destname1); + anum.num.number = 0; + env->tempobject.num = anum.num; + aname = &env->tempname; + AML_DEBUGPRINT(")"); + break; + case 0x13: + aml_parse_defcreatefield(env, indent); + break; + case 0x20: /* LoadOp *//* XXX Not Impremented */ + AML_DEBUGPRINT("Load("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x21: /* StallOp *//* XXX Not yet */ + AML_DEBUGPRINT("Stall("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x22: /* SleepOp *//* XXX Not yet */ + AML_DEBUGPRINT("Sleep("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x23: /* AcquireOp *//* XXX Not yet */ + AML_DEBUGPRINT("Acquire("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", 0x%x)", aml_parse_worddata(env)); + break; + case 0x24: /* SignalOp *//* XXX Not yet */ + AML_DEBUGPRINT("Signal("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x25: /* WaitOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Wait("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x26: /* ResetOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Reset("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x27: /* ReleaseOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Release("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; +#define NUMOP2(opname, operation) do { \ + AML_DEBUGPRINT(opname); \ + AML_DEBUGPRINT("("); \ + num1 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + anum.num.number = operation (num1); \ + destname1 = aml_parse_termobj(env, indent); \ + AML_DEBUGPRINT(")"); \ + aml_store_to_name(env, &anum, destname1); \ + env->tempobject.num = anum.num; \ + env->tempname.property = &env->tempobject; \ + aname = &env->tempname; \ +} while(0) + + case 0x28: /* FromBCDOp */ + NUMOP2("FromBCD", frombcd); + break; + case 0x29: /* ToBCDOp */ + NUMOP2("ToBCD", tobcd); + break; + case 0x2a: /* UnloadOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Unload("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x30: + env->tempobject.type = aml_t_num; + env->tempobject.num.number = 0; + env->tempobject.num.constant = 1; + AML_DEBUGPRINT("Revision"); + break; + case 0x31: + env->tempobject.type = aml_t_debug; + aname = &env->tempname; + AML_DEBUGPRINT("Debug"); + break; + case 0x32: /* FatalOp */ + AML_DEBUGPRINT("Fatal("); + AML_DEBUGPRINT("0x%x, ", aml_parse_bytedata(env)); + AML_DEBUGPRINT("0x%x, ", aml_parse_dworddata(env)); + aml_parse_termobj(env, indent); + env->stat = aml_stat_panic; + AML_DEBUGPRINT(")"); + break; + case 0x80: /* OpRegionOp */ + aml_parse_defopregion(env, indent); + break; + case 0x81: /* FieldOp */ + aml_parse_deffield(env, indent); + break; + case 0x82: /* DeviceOp */ + aml_parse_defdevice(env, indent); + break; + case 0x83: /* ProcessorOp */ + aml_parse_defprocessor(env, indent); + break; + case 0x84: /* PowerResOp */ + aml_parse_defpowerres(env, indent); + break; + case 0x85: /* ThermalZoneOp */ + aml_parse_defthermalzone(env, indent); + break; + case 0x86: /* IndexFieldOp */ + aml_parse_defindexfield(env, indent); + break; + case 0x87: /* BankFieldOp */ + aml_parse_defbankfield(env, indent); + break; + default: + AML_SYSERRX(1, "strange opcode 0x5b, 0x%x\n", opcode); + AML_SYSABORT(); + } + break; + case 0x68 ... 0x6e: /* ArgN */ + AML_DEBUGPRINT("Arg%d", opcode - 0x68); + return (aml_local_stack_getArgX(NULL, opcode - 0x68)); + break; + case 0x60 ... 0x67: + AML_DEBUGPRINT("Local%d", opcode - 0x60); + return (aml_local_stack_getLocalX(opcode - 0x60)); + break; + case 0x70: /* StoreOp */ + AML_DEBUGPRINT("Store("); + aname = aml_create_local_object(); + AML_COPY_OBJECT(tmpobj, env, + aml_eval_name(env, aml_parse_termobj(env, indent)), NULL); + aname->property = tmpobj; + AML_DEBUGPRINT(", "); + destname1 = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + aml_store_to_name(env, tmpobj, destname1); + if (env->stat == aml_stat_panic) { + AML_DEBUGPRINT("StoreOp failed"); + return (NULL); + } + aname = aml_create_local_object(); + AML_COPY_OBJECT(tmpobj, env, destname1->property, NULL); + aname->property = tmpobj; + if (tmpobj == NULL) { + printf("???"); + break; + } + break; + case 0x71: /* RefOfOp */ + AML_DEBUGPRINT("RefOf("); + src = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + + aname = aml_create_local_object(); + AML_ALLOC_OBJECT(aname->property, env, aml_t_objref, NULL); + objref = aname->property; + if (src->property == NULL || + src->property->type != aml_t_namestr) { + objref->objref.nameref = src; + } else { + objref->objref.nameref = aml_create_local_object(); + } + objref->objref.ref = src->property; + objref->objref.offset = -1; /* different from IndexOp */ + break; + +#define NUMOP3_2(opname, oparation, ope2) do { \ + AML_DEBUGPRINT(opname); \ + AML_DEBUGPRINT("("); \ + num1 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + num2 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + anum.num.number = ope2(num1 oparation num2); \ + destname1 = aml_parse_termobj(env, indent); \ + AML_DEBUGPRINT(")"); \ + aml_store_to_name(env, &anum, destname1); \ + env->tempobject.num = anum.num; \ + env->tempname.property = &env->tempobject; \ + aname = &env->tempname; \ +} while(0) + +#define NUMOP3(opname, operation) NUMOP3_2(opname, operation, ) +#define NUMOPN3(opname, operation) NUMOP3_2(opname, operation, ~) + + case 0x72: /* AddOp */ + NUMOP3("Add", +); + break; + case 0x73: /* ConcatOp */ + aname = aml_parse_concatop(env, indent); + break; + case 0x74: /* SubtractOp */ + NUMOP3("Subtract", -); + break; + case 0x75: /* IncrementOp */ + AML_DEBUGPRINT("Increment("); + aname = aml_parse_termobj(env, indent); + num1 = aml_objtonum(env, aml_eval_name(env, aname)); + num1++; + anum.num.number = num1; + AML_DEBUGPRINT(")"); + aml_store_to_name(env, &anum, aname); + aname = &env->tempname; + env->tempobject.num = anum.num; + break; + case 0x76: /* DecrementOp */ + AML_DEBUGPRINT("Decrement("); + aname = aml_parse_termobj(env, indent); + num1 = aml_objtonum(env, aml_eval_name(env, aname)); + num1--; + anum.num.number = num1; + AML_DEBUGPRINT(")"); + aml_store_to_name(env, &anum, aname); + aname = &env->tempname; + env->tempobject.num = anum.num; + break; + case 0x77: /* MultiplyOp */ + NUMOP3("Multiply", *); + break; + case 0x78: /* DivideOp */ + AML_DEBUGPRINT("Divide("); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + num2 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + anum.num.number = num1 % num2; + destname1 = aml_parse_termobj(env, indent); + aml_store_to_name(env, &anum, destname1); + AML_DEBUGPRINT(", "); + anum.num.number = num1 / num2; + destname2 = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + aml_store_to_name(env, &anum, destname2); + env->tempobject.num = anum.num; + aname = &env->tempname; + break; + case 0x79: /* ShiftLeftOp */ + NUMOP3("ShiftLeft", <<); + break; + case 0x7a: /* ShiftRightOp */ + NUMOP3("ShiftRight", >>); + break; + case 0x7b: /* AndOp */ + NUMOP3("And", &); + break; + case 0x7c: /* NAndOp */ + NUMOPN3("NAnd", &); + break; + case 0x7d: /* OrOp */ + NUMOP3("Or", |); + break; + case 0x7e: /* NOrOp */ + NUMOPN3("NOr", |); + break; + case 0x7f: /* XOrOp */ + NUMOP3("XOr", ^); + break; + case 0x80: /* NotOp */ + NUMOP2("Not", ~); + break; + case 0x81: /* FindSetLeftBitOp */ + NUMOP2("FindSetLeftBit", findsetleftbit); + break; + case 0x82: /* FindSetRightBitOp */ + NUMOP2("FindSetRightBit", findsetrightbit); + break; + case 0x83: /* DerefOp */ + AML_DEBUGPRINT("DerefOf("); + objref = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(")"); + + if (objref->objref.ref == NULL) { + env->tempname.property = objref->objref.ref; + aname = &env->tempname; + break; + } + switch (objref->objref.ref->type) { + case aml_t_package: + case aml_t_buffer: + if (objref->objref.offset < 0) { + env->tempname.property = objref->objref.ref; + } else { + objref->objref.deref = 1; + env->tempname.property = objref; + } + break; + default: + env->tempname.property = objref->objref.ref; + break; + } + + aname = &env->tempname; + break; + case 0x86: /* NotifyOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Notify("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x87: /* SizeOfOp */ + AML_DEBUGPRINT("SizeOf("); + aname = aml_parse_termobj(env, indent); + tmpobj = aml_eval_name(env, aname); + + AML_DEBUGPRINT(")"); + num1 = 0; + switch (tmpobj->type) { + case aml_t_buffer: + num1 = tmpobj->buffer.size; + break; + case aml_t_string: + num1 = strlen(tmpobj->str.string); + break; + case aml_t_package: + num1 = tmpobj->package.elements; + break; + default: + AML_DEBUGPRINT("Args of SizeOf should be " + "buffer/string/package only\n"); + break; + } + + anum.num.number = num1; + env->tempobject.num = anum.num; + aname = &env->tempname; + break; + case 0x88: /* IndexOp */ + AML_DEBUGPRINT("Index("); + srcobj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + destname1 = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + aname = aml_create_local_object(); + switch (srcobj->type) { + case aml_t_package: + case aml_t_buffer: + AML_ALLOC_OBJECT(objref, env, aml_t_objref, NULL); + aname->property = objref; + objref->objref.ref = srcobj; + objref->objref.offset = num1; + objref->objref.deref = 0; + break; + default: + AML_DEBUGPRINT("Arg0 of Index should be either " + "buffer or package\n"); + return (aname); + } + + aml_store_to_name(env, objref, destname1); + break; + case 0x89: /* MatchOp *//* XXX Not yet Impremented */ + AML_DEBUGPRINT("Match("); + AML_COPY_OBJECT(obj, env, aml_eval_name(env, + aml_parse_termobj(env, indent)), NULL); + if (obj->type != aml_t_package) { + env->stat = aml_stat_panic; + return (NULL); + } + anum.num.number = 0xffffffff; + match1 = *env->dp; + AML_DEBUGPRINT(", %d", *env->dp); + env->dp++; + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + match2 = *env->dp; + AML_DEBUGPRINT(", %d", *env->dp); + env->dp++; + num2 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + start = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + +#define MATCHOP(opnum, arg1, arg2) ((opnum == 0) ? (1) : \ + (opnum == 1) ? ((arg1) == (arg2)) : \ + (opnum == 2) ? ((arg1) <= (arg2)) : \ + (opnum == 3) ? ((arg1) < (arg2)) : \ + (opnum == 4) ? ((arg1) >= (arg2)) : \ + (opnum == 5) ? ((arg1) > (arg2)) : 0 ) + + for (i = start; i < obj->package.elements; i++) { + pkgval = aml_objtonum(env, obj->package.objects[i]); + if (MATCHOP(match1, pkgval, num1) && + MATCHOP(match2, pkgval, num2)) { + anum.num.number = i; + break; + } + } + AML_DEBUGPRINT(")"); + aml_free_object(&obj); + aname = &env->tempname; + env->tempname.property = &env->tempobject; + env->tempobject.num = anum.num; + break; +#undef MATCHOP + case 0x8a ... 0x8d: /* CreateDWordFieldOp */ + widthindex = *(env->dp - 1) - 0x8a; + AML_DEBUGPRINT("%s(", opname[widthindex]); + srcbuf = aml_eval_name(env, aml_parse_termobj(env, indent)); + if (srcbuf == &env->tempobject) { + AML_DEBUGPRINT("NOT NAMEDBUF\n"); + env->stat = aml_stat_panic; + return (NULL); + } + AML_DEBUGPRINT(", "); + index = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + if (widthindex != 3) { + index *= 8; + } + AML_DEBUGPRINT(", "); + newname = aml_parse_namestring(env); + aml_print_namestring(newname); + aml_createfield_generic(env, srcbuf, index, + widthtbl[widthindex], newname); + AML_DEBUGPRINT(")"); + break; + case 0x8e: /* ObjectTypeOp */ + AML_DEBUGPRINT("ObjectType("); + aname = aml_parse_termobj(env, indent); + if (aname == NULL) { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = aml_t_null; + } else { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = aname->property->type; + } + aname = &env->tempname; + AML_DEBUGPRINT(")"); + break; + +#define CMPOP(opname,operation) do { \ + AML_DEBUGPRINT(opname); \ + AML_DEBUGPRINT("("); \ + num1 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + num2 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + aname = &env->tempname; \ + env->tempobject.type = aml_t_num; \ + env->tempobject.num.number = (num1 operation num2) ? 0xffffffff : 0; \ + aname->property = &env->tempobject; \ + AML_DEBUGPRINT(")"); \ +} while(0) + + case 0x90: + CMPOP("LAnd", &&); + break; + case 0x91: + CMPOP("LOr", ||); + break; + case 0x92: + AML_DEBUGPRINT("LNot("); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + aname = &env->tempname; + env->tempobject.type = aml_t_num; + env->tempobject.num.number = (!num1) ? 0xffffffff : 0; + aname->property = &env->tempobject; + AML_DEBUGPRINT(")"); + break; + case 0x93: + CMPOP("LEqual", ==); + break; + case 0x94: + CMPOP("LGreater", >); + break; + case 0x95: + CMPOP("LLess", <); + break; + case 0xa0: /* IfOp */ + aname = aml_parse_defif(env, indent); + break; +#if 0 + + case 0xa1: /* ElseOp should not be treated in Main parser + * But If Op */ + aml_parse_defelse(env, indent); + break; +#endif + case 0xa2: /* WhileOp */ + aname = aml_parse_defwhile(env, indent); + break; + case 0xa3: /* NoopOp */ + AML_DEBUGPRINT("Noop"); + break; + case 0xa5: /* BreakOp */ + AML_DEBUGPRINT("Break"); + env->stat = aml_stat_break; + break; + case 0xa4: /* ReturnOp */ + AML_DEBUGPRINT("Return("); + AML_COPY_OBJECT(env->tempname.property, env, aml_eval_name(env, + aml_parse_termobj(env, indent)), NULL); + aname = &env->tempname; + env->stat = aml_stat_return; + AML_DEBUGPRINT(")"); + break; + case 0xcc: /* BreakPointOp */ + /* XXX Not Yet Impremented (Not need?) */ + AML_DEBUGPRINT("BreakPoint"); + break; + default: + AML_SYSERRX(1, "strange opcode 0x%x\n", opcode); + AML_SYSABORT(); + } + + return (aname); +} diff --git a/usr.sbin/acpi/amldb/aml/aml_parse.h b/usr.sbin/acpi/amldb/aml/aml_parse.h new file mode 100644 index 0000000..96ab22c --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_parse.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 1999 Doug Rabson + * 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: aml_parse.h,v 1.9 2000/08/08 14:12:05 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_PARSE_H_ +#define _AML_PARSE_H_ + +struct aml_name *aml_parse_objectlist(struct aml_environ *, int); +struct aml_name *aml_parse_termobj(struct aml_environ *, int); + +#endif /* !_AML_PARSE_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_region.c b/usr.sbin/acpi/amldb/aml/aml_region.c new file mode 100644 index 0000000..5f318a5 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_region.c @@ -0,0 +1,490 @@ +/*- + * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> + * Copyright (c) 2000 Munehiro Matsuda <haro@tk.kubota.co.jp> + * 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: aml_region.c,v 1.10 2000/08/09 14:47:44 iwasaki Exp $ + * $FreeBSD$ + */ + +/* + * Region I/O subroutine + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/acpi.h> + +#include <dev/acpi/aml/aml_common.h> +#include <dev/acpi/aml/aml_region.h> +#include <dev/acpi/aml/aml_name.h> + +#ifndef ACPI_NO_OSDFUNC_INLINE +#include <machine/acpica_osd.h> +#endif + +#define AML_REGION_INPUT 0 +#define AML_REGION_OUTPUT 1 + +#define AML_REGION_SYSMEM 0 +#define AML_REGION_SYSIO 1 +#define AML_REGION_PCICFG 2 +#define AML_REGION_EMBCTL 3 +#define AML_REGION_SMBUS 4 + +static int +aml_region_io_system(struct aml_environ *env, boolean_t io, int regtype, + u_int32_t flags, u_int32_t *valuep, u_int32_t baseaddr, + u_int32_t bitoffset, u_int32_t bitlen) +{ + u_int8_t val, tmp, masklow, maskhigh; + u_int8_t offsetlow, offsethigh; + vm_offset_t addr, vaddr, byteoffset, bytelen; + u_int32_t pci_bus; + u_int32_t pci_devfunc; + int value, readval; + int state, i; + int debug; + + /* save debug level and shut it up */ + debug = aml_debug; + aml_debug = 0; + + value = *valuep; + val = readval = 0; + masklow = maskhigh = 0xff; + state = 0; + vaddr = 0; + pci_bus = pci_devfunc = 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); + AML_DEBUGPRINT("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n", + offsetlow, masklow, ~masklow & 0xff); + } + if (offsethigh) { + maskhigh = 0xff << offsethigh; + AML_DEBUGPRINT("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n", + offsethigh, maskhigh, ~maskhigh & 0xff); + } + + if (regtype == AML_REGION_SYSMEM) { + OsdMapMemory((void *)addr, bytelen, (void **)&vaddr); + } + if (regtype == AML_REGION_PCICFG) { + /* Access to PCI Config space */ + struct aml_name *pci_info; + + /* Obtain PCI bus number */ + pci_info = aml_search_name(env, "_BBN"); + if (!pci_info || pci_info->property->type != aml_t_num) { + AML_DEBUGPRINT("Cannot locate _BBN. Using default 0\n"); + pci_bus = 0; + } else { + AML_DEBUGPRINT("found _BBN: %d\n", + pci_info->property->num.number); + pci_bus = pci_info->property->num.number & 0xff; + } + + /* Obtain device & function number */ + pci_info = aml_search_name(env, "_ADR"); + if (!pci_info || pci_info->property->type != aml_t_num) { + printf("Cannot locate: _ADR\n"); + state = -1; + goto io_done; + } + pci_devfunc = pci_info->property->num.number; + + AML_DEBUGPRINT("[pci%d.%d]", pci_bus, pci_devfunc); + } + + /* simple I/O ? */ + if (offsetlow == 0 && offsethigh == 0 && + (bitlen == 8 || bitlen == 16 || bitlen == 32)) { + switch (io) { + case AML_REGION_INPUT: + switch (regtype) { + case AML_REGION_SYSMEM: + /* XXX should be MI */ + switch (bitlen) { + case 8: + value = *(volatile u_int8_t *)(vaddr); + value &= 0xff; + break; + case 16: + value = *(volatile u_int16_t *)(vaddr); + value &= 0xffff; + break; + case 32: + value = *(volatile u_int32_t *)(vaddr); + break; + } + break; + case AML_REGION_SYSIO: + switch (bitlen) { + case 8: + value = OsdIn8(addr); + value &= 0xff; + break; + case 16: + value = OsdIn16(addr); + value &= 0xffff; + break; + case 32: + value = OsdIn32(addr); + break; + } + break; + case AML_REGION_PCICFG: + switch (bitlen) { + case 8: + OsdReadPciCfgByte(pci_bus, pci_devfunc, + addr, (UINT8 *)&value); + value &= 0xff; + break; + case 16: + OsdReadPciCfgWord(pci_bus, pci_devfunc, + addr, (UINT16 *)&value); + value &= 0xffff; + break; + case 32: + OsdReadPciCfgDword(pci_bus, pci_devfunc, + addr, &value); + break; + } + break; + default: + printf("aml_region_io_system: not supported yet (%d)\n", + regtype); + value = 0; + break; + } + *valuep = value; + break; + case AML_REGION_OUTPUT: + switch (regtype) { + case AML_REGION_SYSMEM: + /* XXX should be MI */ + switch (bitlen) { + case 8: + value &= 0xff; + *(volatile u_int8_t *)(vaddr) = value; + break; + case 16: + value &= 0xffff; + *(volatile u_int16_t *)(vaddr) = value; + break; + case 32: + *(volatile u_int32_t *)(vaddr) = value; + break; + } + break; + case AML_REGION_SYSIO: + switch (bitlen) { + case 8: + value &= 0xff; + OsdOut8(addr, value); + break; + case 16: + value &= 0xffff; + OsdOut16(addr, value); + break; + case 32: + OsdOut32(addr, value); + break; + } + break; + case AML_REGION_PCICFG: + switch (bitlen) { + case 8: + OsdWritePciCfgByte(pci_bus, pci_devfunc, + addr, value); + break; + case 16: + OsdWritePciCfgWord(pci_bus, pci_devfunc, + addr, value); + break; + case 32: + OsdWritePciCfgDword(pci_bus, pci_devfunc, + addr, value); + break; + } + break; + default: + printf("aml_region_io_system: not supported yet (%d)\n", + regtype); + break; + } + break; + } + goto io_done; + } + + for (i = 0; i < bytelen; i++) { + /* XXX */ + switch (regtype) { + case AML_REGION_SYSMEM: + val = *(volatile u_int8_t *)(vaddr + i); + break; + case AML_REGION_SYSIO: + val = OsdIn8(addr + i); + break; + case AML_REGION_PCICFG: + OsdReadPciCfgByte(pci_bus, pci_devfunc, addr + i, &val); + break; + default: + printf("aml_region_io_system: not supported yet (%d)\n", + regtype); + val = 0; + break; + } + + AML_DEBUGPRINT("\t[%d:0x%02x@0x%x]", regtype, val, addr + i); + + switch (io) { + case AML_REGION_INPUT: + tmp = val; + /* the lowest byte? */ + if (i == 0) { + if (offsetlow) { + readval = tmp & ~masklow; + } else { + readval = tmp; + } + } else { + if (i == bytelen - 1 && offsethigh) { + tmp = tmp & ~maskhigh; + } + readval = (tmp << (8 * i)) | readval; + } + + AML_DEBUGPRINT("\n"); + /* goto to next byte... */ + if (i < bytelen - 1) { + continue; + } + /* final adjustment before finishing region access */ + if (offsetlow) { + readval = readval >> offsetlow; + } + AML_DEBUGPRINT("\t[read(%d, 0x%x)&mask:0x%x]\n", + regtype, addr + i, readval); + value = readval; + *valuep = value; + + break; + case AML_REGION_OUTPUT: + tmp = value & 0xff; + /* the lowest byte? */ + if (i == 0) { + if (offsetlow) { + tmp = (val & masklow) | tmp << offsetlow; + } + value = value >> (8 - offsetlow); + } else { + if (i == bytelen - 1 && offsethigh) { + tmp = (val & maskhigh) | tmp; + } + value = value >> 8; + } + + AML_DEBUGPRINT("->[%d:0x%02x@0x%x]\n", + regtype, tmp, addr + i); + val = tmp; + + /* XXX */ + switch (regtype) { + case AML_REGION_SYSMEM: + *(volatile u_int8_t *)(vaddr + i) = val; + break; + case AML_REGION_SYSIO: + OsdOut8(addr + i, val); + break; + case AML_REGION_PCICFG: + OsdWritePciCfgByte(pci_bus, pci_devfunc, + addr + i, val); + break; + default: + printf("aml_region_io_system: not supported yet (%d)\n", + regtype); + break; + } + + break; + } + } + +io_done: + if (regtype == AML_REGION_SYSMEM) { + OsdUnMapMemory((void *)vaddr, bytelen); + } + + aml_debug = debug; /* restore debug devel */ + + return (state); +} + +static int +aml_region_io_buffer(boolean_t io, int regtype, u_int32_t flags, + u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen) +{ + vm_offset_t addr, vaddr; + size_t len; + const char *funcname[] = { + "aml_region_read_into_buffer", + "aml_region_write_from_buffer" + }; + + if (regtype != AML_REGION_SYSMEM) { + printf("%s: region type isn't system memory!\n", funcname[io]); + return (-1); + } + + if (bitlen % 8) { + printf("%s: bit length isn't a multiple of 8!\n", funcname[io]); + } + if (bitoffset % 8) { + printf("%s: bit offset isn't a multiple of 8!\n", funcname[io]); + } + + addr = baseaddr + bitoffset / 8; + len = bitlen / 8 + ((bitlen % 8) ? 1 : 0); + + OsdMapMemory((void *)addr, len, (void **)&vaddr); + + switch (io) { + case AML_REGION_INPUT: + bcopy((void *)vaddr, (void *)buffer, len); + break; + case AML_REGION_OUTPUT: + bcopy((void *)buffer, (void *)vaddr, len); + break; + } + + OsdUnMapMemory((void *)vaddr, len); + + 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) +{ + int value; + int state; + + state = aml_region_io_system(env, AML_REGION_INPUT, regtype, + flags, &value, addr, bitoffset, bitlen); + AML_SYSASSERT(state != -1); + + return (value); +} + +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) +{ + int state; + + state = aml_region_io_buffer(AML_REGION_INPUT, regtype, flags, + buffer, addr, bitoffset, bitlen); + + return (state); +} + +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) +{ + int state; + + state = aml_region_io_system(env, AML_REGION_OUTPUT, regtype, + flags, &value, addr, bitoffset, bitlen); + AML_SYSASSERT(state != -1); + + return (state); +} + +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) +{ + int state; + + state = aml_region_io_buffer(AML_REGION_OUTPUT, regtype, flags, + buffer, addr, bitoffset, bitlen); + + return (state); +} + +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) +{ + vm_offset_t from_addr, from_vaddr; + vm_offset_t to_addr, to_vaddr; + size_t len; + + if (regtype != AML_REGION_SYSMEM) { + printf("aml_region_bcopy: region type isn't system memory!\n"); + return (-1); + } + + if ((bitlen % 8) || (dbitlen % 8)) { + printf("aml_region_bcopy: bit length isn't a multiple of 8!\n"); + } + if ((bitoffset % 8) || (dbitoffset % 8)) { + printf("aml_region_bcopy: bit offset isn't a multiple of 8!\n"); + } + + from_addr = addr + bitoffset / 8; + to_addr = daddr + dbitoffset / 8; + + len = (bitlen > dbitlen) ? dbitlen : bitlen; + len = len / 8 + ((len % 8) ? 1 : 0); + + OsdMapMemory((void *)from_addr, len, (void **)&from_vaddr); + OsdMapMemory((void *)to_addr, len, (void **)&to_vaddr); + + bcopy((void *)from_vaddr, (void *)to_vaddr, len); + + OsdUnMapMemory((void *)from_vaddr, len); + OsdUnMapMemory((void *)to_vaddr, len); + + return (0); +} diff --git a/usr.sbin/acpi/amldb/aml/aml_region.h b/usr.sbin/acpi/amldb/aml/aml_region.h new file mode 100644 index 0000000..599e6a5 --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_region.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 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: aml_region.h,v 1.5 2000/08/08 14:12:05 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_REGION_H_ +#define _AML_REGION_H_ + +/* + * Region I/O subroutine + */ +struct aml_environ; + +u_int32_t aml_region_read(struct aml_environ *, int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t); +int aml_region_write(struct aml_environ *, int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t, u_int32_t); +int aml_region_read_into_buffer(struct aml_environ *, int, + u_int32_t, u_int32_t, u_int32_t, + u_int32_t, u_int8_t *); +int aml_region_write_from_buffer(struct aml_environ *, int, + u_int32_t, u_int8_t *, u_int32_t, + u_int32_t, u_int32_t); +int aml_region_bcopy(struct aml_environ *, int, + u_int32_t, u_int32_t, u_int32_t, u_int32_t, + u_int32_t, u_int32_t, u_int32_t, u_int32_t); + +#ifndef _KERNEL +void aml_simulation_regdump(const char *); +extern int aml_debug_prompt_regoutput; +extern int aml_debug_prompt_reginput; +#endif /* !_KERNEL */ + +#endif /* !_AML_REGION_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_status.h b/usr.sbin/acpi/amldb/aml/aml_status.h new file mode 100644 index 0000000..cbb601c --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_status.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * 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: aml_status.h,v 1.6 2000/08/08 14:12:05 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_STATUS_H_ +#define _AML_STATUS_H_ + +enum aml_status { + aml_stat_none = 0, + aml_stat_return, + aml_stat_break, + aml_stat_panic, + aml_stat_step +}; + +#endif /* !_AML_STATUS_H_ */ diff --git a/usr.sbin/acpi/amldb/aml/aml_store.c b/usr.sbin/acpi/amldb/aml/aml_store.c new file mode 100644 index 0000000..ce9439d --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_store.c @@ -0,0 +1,338 @@ +/*- + * 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: aml_store.c,v 1.22 2000/08/09 14:47:44 iwasaki Exp $ + * $FreeBSD$ + */ + +#include <sys/param.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_evalobj.h> +#include <dev/acpi/aml/aml_name.h> +#include <dev/acpi/aml/aml_obj.h> +#include <dev/acpi/aml/aml_region.h> +#include <dev/acpi/aml/aml_status.h> +#include <dev/acpi/aml/aml_store.h> + +#ifndef _KERNEL +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static void +aml_store_to_fieldname(struct aml_environ *env, union aml_object *obj, + struct aml_name *name) +{ + char *buffer; + struct aml_name *wname, *oname; + struct aml_field *field; + struct aml_opregion *or; + union aml_object tobj; + + field = &name->property->field; + oname = env->curname; + env->curname = name->parent; + if (field->f.ftype == f_t_field) { + wname = aml_search_name(env, field->f.fld.regname); + if (wname == NULL || + wname->property == NULL || + wname->property->type != aml_t_opregion) { + AML_DEBUGPRINT("Inappropreate Type\n"); + env->stat = aml_stat_panic; + env->curname = oname; + return; + } + or = &wname->property->opregion; + switch (obj->type) { + case aml_t_num: + aml_region_write(env, or->space, field->flags, + obj->num.number, or->offset, + field->bitoffset, field->bitlen); + AML_DEBUGPRINT("[write(%d, 0x%x, 0x%x)]", + or->space, obj->num.number, + or->offset + field->bitoffset / 8); + break; + case aml_t_buffer: + case aml_t_bufferfield: + if (obj->type == aml_t_buffer) { + buffer = obj->buffer.data; + } else { + buffer = obj->bfld.origin; + buffer += obj->bfld.bitoffset / 8; + } + aml_region_write_from_buffer(env, or->space, + field->flags, buffer, or->offset, field->bitoffset, + field->bitlen); + break; + case aml_t_regfield: + if (or->space != obj->regfield.space) { + AML_DEBUGPRINT("aml_store_to_fieldname: " + "Different type of space\n"); + break; + } + aml_region_bcopy(env, obj->regfield.space, + obj->regfield.flags, obj->regfield.offset, + obj->regfield.bitoffset, obj->regfield.bitlen, + field->flags, or->offset, field->bitoffset, + field->bitlen); + break; + default: + AML_DEBUGPRINT("aml_store_to_fieldname: " + "Inappropreate Type of src object\n"); + break; + } + } else if (field->f.ftype == f_t_index) { + wname = aml_search_name(env, field->f.ifld.indexname); + tobj.type = aml_t_num; + tobj.num.number = field->bitoffset / 8; /* AccessType Boundary */ + aml_store_to_name(env, &tobj, wname); + wname = aml_search_name(env, field->f.ifld.dataname); + tobj.num = obj->num; + tobj.num.number = tobj.num.number << (field->bitoffset & 7); + aml_store_to_name(env, &tobj, wname); + } + env->curname = oname; +} + +static void +aml_store_to_buffer(struct aml_environ *env, union aml_object *obj, + union aml_object *buf, int offset) +{ + int size; + int bitlen; + + switch (obj->type) { + case aml_t_num: + if (offset > buf->buffer.size) { + aml_realloc_object(buf, offset); + } + buf->buffer.data[offset] = obj->num.number & 0xff; + AML_DEBUGPRINT("[Store number 0x%x to buffer]", + obj->num.number & 0xff); + break; + case aml_t_string: + size = strlen(obj->str.string); + if (buf->buffer.size - offset < size) { + aml_realloc_object(buf, offset + size + 1); + } + strcpy(&buf->buffer.data[offset], obj->str.string); + AML_DEBUGPRINT("[Store string to buffer]"); + break; + case aml_t_buffer: + bzero(buf->buffer.data, buf->buffer.size); + if (obj->buffer.size > buf->buffer.size) { + size = buf->buffer.size; + } else { + size = obj->buffer.size; + } + bcopy(obj->buffer.data, buf->buffer.data, size); + break; + case aml_t_regfield: + bitlen = (buf->buffer.size - offset) * 8; + if (bitlen > obj->regfield.bitlen) { + bitlen = obj->regfield.bitlen; + } + aml_region_read_into_buffer(env, obj->regfield.space, + obj->regfield.flags, obj->regfield.offset, + obj->regfield.bitoffset, bitlen, + buf->buffer.data + offset); + break; + default: + goto not_yet; + } + return; +not_yet: + AML_DEBUGPRINT("[XXX not supported yet]"); +} + + +void +aml_store_to_object(struct aml_environ *env, union aml_object *src, + union aml_object * dest) +{ + char *buffer, *srcbuf; + int offset, bitlen; + + switch (dest->type) { + case aml_t_num: + if (src->type == aml_t_num) { + dest->num = src->num; + AML_DEBUGPRINT("[Store number 0x%x]", src->num.number); + } else { + env->stat = aml_stat_panic; + } + break; + case aml_t_string: + case aml_t_package: + break; + case aml_t_buffer: + aml_store_to_buffer(env, src, dest, 0); + break; + case aml_t_bufferfield: + buffer = dest->bfld.origin; + offset = dest->bfld.bitoffset; + bitlen = dest->bfld.bitlen; + + switch (src->type) { + case aml_t_num: + if (aml_bufferfield_write(src->num.number, buffer, offset, bitlen)) { + AML_DEBUGPRINT("aml_bufferfield_write() failed\n"); + } + break; + case aml_t_buffer: + case aml_t_bufferfield: + if (src->type == aml_t_buffer) { + srcbuf = src->buffer.data; + } else { + srcbuf = src->bfld.origin; + srcbuf += src->bfld.bitoffset / 8; + } + bcopy(srcbuf, buffer, bitlen / 8); + break; + case aml_t_regfield: + aml_region_read_into_buffer(env, src->regfield.space, + src->regfield.flags, src->regfield.offset, + src->regfield.bitoffset, src->regfield.bitlen, + buffer); + break; + default: + AML_DEBUGPRINT("not implemented yet"); + break; + } + break; + case aml_t_debug: + aml_showobject(src); + break; + default: + AML_DEBUGPRINT("[Unimplemented %d]", dest->type); + break; + } +} + +static void +aml_store_to_objref(struct aml_environ *env, union aml_object *obj, + union aml_object *r) +{ + int offset; + union aml_object *ref; + + if (r->objref.ref == NULL) { + r->objref.ref = aml_alloc_object(obj->type, NULL); /* XXX */ + r->objref.nameref->property = r->objref.ref; + } + ref = r->objref.ref; + + switch (ref->type) { + case aml_t_buffer: + offset = r->objref.offset; + aml_store_to_buffer(env, obj, ref, r->objref.offset); + break; + case aml_t_package: + offset = r->objref.offset; + if (r->objref.ref->package.elements < offset) { + aml_realloc_object(ref, offset); + } + if (ref->package.objects[offset] == NULL) { + ref->package.objects[offset] = aml_copy_object(env, obj); + } else { + aml_store_to_object(env, obj, ref->package.objects[offset]); + } + break; + default: + aml_store_to_object(env, obj, ref); + break; + } +} + +/* + * Store to Named object + */ +void +aml_store_to_name(struct aml_environ *env, union aml_object *obj, + struct aml_name *name) +{ + struct aml_name *wname; + + if (env->stat == aml_stat_panic) { + return; + } + if (name == NULL || obj == NULL) { + AML_DEBUGPRINT("[Try to store no existant name ]"); + return; + } + if (name->property == NULL) { + name->property = aml_copy_object(env, obj); + AML_DEBUGPRINT("[Copy number 0x%x]", obj->num.number); + return; + } + if (name->property->type == aml_t_namestr) { + wname = aml_search_name(env, name->property->nstr.dp); + name = wname; + } + if (name == NULL) { + env->stat = aml_stat_panic; + return; + } + if (name->property == NULL || name->property->type == aml_t_null) { + name->property = aml_copy_object(env, obj); + AML_DEBUGPRINT("[Copy number 0x%x]", obj->num.number); + return; + } + /* Writes to constant object are not allowed */ + if (name->property != NULL && name->property->type == aml_t_num && + name->property->num.constant == 1) { + return; + } + /* try to dereference */ + if (obj->type == aml_t_objref && obj->objref.deref == 0) { + AML_DEBUGPRINT("Source object isn't dereferenced yet, " + "try to dereference anyway\n"); + obj->objref.deref = 1; + obj = aml_eval_objref(env, obj); + } + switch (name->property->type) { + case aml_t_field: + aml_store_to_fieldname(env, obj, name); + break; + case aml_t_objref: + aml_store_to_objref(env, obj, name->property); + break; + case aml_t_num: + if (name == &env->tempname) + break; + default: + aml_store_to_object(env, obj, name->property); + break; + } +} diff --git a/usr.sbin/acpi/amldb/aml/aml_store.h b/usr.sbin/acpi/amldb/aml/aml_store.h new file mode 100644 index 0000000..c41fb8c --- /dev/null +++ b/usr.sbin/acpi/amldb/aml/aml_store.h @@ -0,0 +1,39 @@ +/*- + * 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: aml_store.h,v 1.8 2000/08/09 14:47:44 iwasaki Exp $ + * $FreeBSD$ + */ + +#ifndef _AML_STORE_H_ +#define _AML_STORE_H_ + +void aml_store_to_name(struct aml_environ *, union aml_object *, + struct aml_name *); +void aml_store_to_object(struct aml_environ *, union aml_object *, + union aml_object *); + +#endif /* _AML_STORE_H_ */ |