summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2000-09-20 01:01:32 +0000
committeriwasaki <iwasaki@FreeBSD.org>2000-09-20 01:01:32 +0000
commit25e47ad7a2fc03462f2f9b79c003eb3042e0bed5 (patch)
treeecb0a0decbebc69a6adc8e5319ae5de550247398 /sys/dev/acpi
parent1794dd585719ba2b3eabff1b40720ff5ccb7649c (diff)
downloadFreeBSD-src-25e47ad7a2fc03462f2f9b79c003eb3042e0bed5.zip
FreeBSD-src-25e47ad7a2fc03462f2f9b79c003eb3042e0bed5.tar.gz
Improve region I/O sub-routines by re-writing most of low level part
of AML interpreter. - Delete and cleanup a lot of almost duplicated code in kernel/userland. - Add new common functions for kernel/userland code. aml_adjust_readvalue(), aml_adjust_updatevalue(), aml_region_handle_alloc(), aml_region_handle_free() and aml_region_io(). - Add primitive functions for both versions of kernel/userland in order to have shared code as much as possible. aml_region_read_simple(), aml_region_write_simple(), aml_region_prompt_read(), aml_region_prompt_write() and aml_region_prompt_update_value(). - Consider update rule and access type in field flags. Also add a lot of definitions for the flags. - Fix bugs on bit manipulation for read/write operations. - Fix bugs on IndexField I/O part. Also add workaround for temporary object corruption during StoreOp interpretation.
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/aml/aml_common.c327
-rw-r--r--sys/dev/acpi/aml/aml_common.h80
-rw-r--r--sys/dev/acpi/aml/aml_evalobj.c7
-rw-r--r--sys/dev/acpi/aml/aml_parse.c10
-rw-r--r--sys/dev/acpi/aml/aml_region.c432
-rw-r--r--sys/dev/acpi/aml/aml_region.h34
-rw-r--r--sys/dev/acpi/aml/aml_store.c25
7 files changed, 615 insertions, 300 deletions
diff --git a/sys/dev/acpi/aml/aml_common.c b/sys/dev/acpi/aml/aml_common.c
index c4d3e1e..fe98e1e 100644
--- a/sys/dev/acpi/aml/aml_common.c
+++ b/sys/dev/acpi/aml/aml_common.c
@@ -42,6 +42,7 @@
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <machine/acpica_osd.h>
#endif /* !_KERNEL */
#include <dev/acpi/aml/aml_common.h>
@@ -276,6 +277,97 @@ aml_showtree(struct aml_name * aname, int lev)
}
/*
+ * Common Region I/O Stuff
+ */
+
+static __inline u_int64_t
+aml_adjust_bitmask(u_int32_t flags, u_int32_t bitlen)
+{
+ u_int64_t bitmask;
+
+ switch (AML_FIELDFLAGS_ACCESSTYPE(flags)) {
+ case AML_FIELDFLAGS_ACCESS_ANYACC:
+ if (bitlen <= 8) {
+ bitmask = 0x000000ff;
+ break;
+ }
+ if (bitlen <= 16) {
+ bitmask = 0x0000ffff;
+ break;
+ }
+ bitmask = 0xffffffff;
+ break;
+ case AML_FIELDFLAGS_ACCESS_BYTEACC:
+ bitmask = 0x000000ff;
+ break;
+ case AML_FIELDFLAGS_ACCESS_WORDACC:
+ bitmask = 0x0000ffff;
+ break;
+ case AML_FIELDFLAGS_ACCESS_DWORDACC:
+ default:
+ bitmask = 0xffffffff;
+ break;
+ }
+
+ switch (bitlen) {
+ case 16:
+ bitmask |= 0x0000ffff;
+ break;
+ case 32:
+ bitmask |= 0xffffffff;
+ break;
+ }
+
+ return (bitmask);
+}
+
+u_int32_t
+aml_adjust_readvalue(u_int32_t flags, u_int32_t bitoffset, u_int32_t bitlen,
+ u_int32_t orgval)
+{
+ u_int32_t offset, retval;
+ u_int64_t bitmask;
+
+ offset = bitoffset; /* XXX bitoffset may change in this function! */
+ bitmask = aml_adjust_bitmask(flags, bitlen);
+ retval = (orgval >> offset) & (~(bitmask << bitlen)) & bitmask;
+
+ return (retval);
+}
+
+u_int32_t
+aml_adjust_updatevalue(u_int32_t flags, u_int32_t bitoffset, u_int32_t bitlen,
+ u_int32_t orgval, u_int32_t value)
+{
+ u_int32_t offset, retval;
+ u_int64_t bitmask;
+
+ offset = bitoffset; /* XXX bitoffset may change in this function! */
+ bitmask = aml_adjust_bitmask(flags, bitlen);
+ retval = orgval;
+ switch (AML_FIELDFLAGS_UPDATERULE(flags)) {
+ case AML_FIELDFLAGS_UPDATE_PRESERVE:
+ retval &= (~(((u_int64_t)1 << bitlen) - 1) << offset) |
+ (~(bitmask << offset));
+ break;
+ case AML_FIELDFLAGS_UPDATE_WRITEASONES:
+ retval = (~(((u_int64_t)1 << bitlen) - 1) << offset) |
+ (~(bitmask << offset));
+ retval &= bitmask; /* trim the upper bits */
+ break;
+ case AML_FIELDFLAGS_UPDATE_WRITEASZEROS:
+ retval = 0;
+ break;
+ default:
+ printf("illegal update rule: %d\n", flags);
+ return (orgval);
+ }
+
+ retval |= (value << (offset & bitmask));
+ return (retval);
+}
+
+/*
* BufferField I/O
*/
@@ -293,8 +385,8 @@ aml_bufferfield_io(int io, u_int32_t *valuep, u_int8_t *origin,
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 value, readval;
u_int32_t byteoffset, bytelen;
masklow = maskhigh = 0xff;
@@ -304,6 +396,31 @@ aml_bufferfield_io(int io, u_int32_t *valuep, u_int8_t *origin,
byteoffset = bitoffset / 8;
bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
addr = origin + byteoffset;
+
+ /* simple I/O ? */
+ if (bitlen <= 8 || bitlen == 16 || bitlen == 32) {
+ bcopy(addr, &readval, bytelen);
+ AML_DEBUGPRINT("\n\t[bufferfield:0x%x@%p:%d,%d]",
+ readval, addr, bitoffset % 8, bitlen);
+ switch (io) {
+ case AML_BUFFER_INPUT:
+ value = aml_adjust_readvalue(AML_FIELDFLAGS_ACCESS_BYTEACC,
+ bitoffset % 8, bitlen, readval);
+ *valuep = value;
+ AML_DEBUGPRINT("\n[read(bufferfield, %p)&mask:0x%x]\n",
+ addr, value);
+ break;
+ case AML_BUFFER_OUTPUT:
+ value = aml_adjust_updatevalue(AML_FIELDFLAGS_ACCESS_BYTEACC,
+ bitoffset % 8, bitlen, readval, value);
+ bcopy(&value, addr, bytelen);
+ AML_DEBUGPRINT("->[bufferfield:0x%x@%p:%d,%d]",
+ value, addr, bitoffset % 8, bitlen);
+ break;
+ }
+ goto out;
+ }
+
offsetlow = bitoffset % 8;
if (bytelen > 1) {
offsethigh = (bitlen - (8 - offsetlow)) % 8;
@@ -378,7 +495,7 @@ aml_bufferfield_io(int io, u_int32_t *valuep, u_int8_t *origin,
*addr = tmp;
}
}
-
+out:
return (0);
}
@@ -404,3 +521,209 @@ aml_bufferfield_write(u_int32_t value, u_int8_t *origin,
origin, bitoffset, bitlen);
return (status);
}
+
+int
+aml_region_handle_alloc(struct aml_environ *env, int regtype, u_int32_t flags,
+ u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen,
+ struct aml_region_handle *h)
+{
+ int state;
+ struct aml_name *pci_info;
+
+ state = 0;
+ pci_info = NULL;
+ bzero(h, sizeof(struct aml_region_handle));
+
+ h->env = env;
+ h->regtype = regtype;
+ h->flags = flags;
+ h->baseaddr = baseaddr;
+ h->bitoffset = bitoffset;
+ h->bitlen = bitlen;
+
+ switch (AML_FIELDFLAGS_ACCESSTYPE(flags)) {
+ case AML_FIELDFLAGS_ACCESS_ANYACC:
+ if (bitlen <= 8) {
+ h->unit = 1;
+ break;
+ }
+ if (bitlen <= 16) {
+ h->unit = 2;
+ break;
+ }
+ h->unit = 4;
+ break;
+ case AML_FIELDFLAGS_ACCESS_BYTEACC:
+ h->unit = 1;
+ break;
+ case AML_FIELDFLAGS_ACCESS_WORDACC:
+ h->unit = 2;
+ break;
+ case AML_FIELDFLAGS_ACCESS_DWORDACC:
+ h->unit = 4;
+ break;
+ default:
+ h->unit = 1;
+ break;
+ }
+
+ h->addr = baseaddr + h->unit * ((bitoffset / 8) / h->unit);
+ h->bytelen = baseaddr + ((bitoffset + bitlen) / 8) - h->addr +
+ ((bitlen % 8) ? 1 : 0);
+
+#ifdef _KERNEL
+ switch (h->regtype) {
+ case AML_REGION_SYSMEM:
+ OsdMapMemory((void *)h->addr, h->bytelen, (void **)&h->vaddr);
+ break;
+
+ case AML_REGION_PCICFG:
+ /* Obtain PCI bus number */
+ pci_info = aml_search_name(env, "_BBN");
+ if (pci_info == NULL || pci_info->property->type != aml_t_num) {
+ AML_DEBUGPRINT("Cannot locate _BBN. Using default 0\n");
+ h->pci_bus = 0;
+ } else {
+ AML_DEBUGPRINT("found _BBN: %d\n",
+ pci_info->property->num.number);
+ h->pci_bus = pci_info->property->num.number & 0xff;
+ }
+
+ /* Obtain device & function number */
+ pci_info = aml_search_name(env, "_ADR");
+ if (pci_info == NULL || pci_info->property->type != aml_t_num) {
+ printf("Cannot locate: _ADR\n");
+ state = -1;
+ goto out;
+ }
+ h->pci_devfunc = pci_info->property->num.number;
+
+ AML_DEBUGPRINT("[pci%d.%d]", h->pci_bus, h->pci_devfunc);
+ break;
+
+ default:
+ break;
+ }
+
+out:
+#endif /* _KERNEL */
+ return (state);
+}
+
+void
+aml_region_handle_free(struct aml_region_handle *h)
+{
+#ifdef _KERNEL
+ switch (h->regtype) {
+ case AML_REGION_SYSMEM:
+ OsdUnMapMemory((void *)h->vaddr, h->bytelen);
+ break;
+
+ default:
+ break;
+ }
+#endif /* _KERNEL */
+}
+
+static int
+aml_region_io_simple(struct aml_environ *env, int io, int regtype,
+ u_int32_t flags, u_int32_t *valuep, u_int32_t baseaddr,
+ u_int32_t bitoffset, u_int32_t bitlen)
+{
+ int i, state;
+ u_int32_t readval, value, offset, bytelen;
+ struct aml_region_handle handle;
+
+ state = aml_region_handle_alloc(env, regtype, flags,
+ baseaddr, bitoffset, bitlen, &handle);
+ if (state == -1) {
+ goto out;
+ }
+
+ readval = 0;
+ offset = bitoffset % (handle.unit * 8);
+ /* limitation of 32 bits alignment */
+ bytelen = (handle.bytelen > 4) ? 4 : handle.bytelen;
+
+ if (io == AML_REGION_INPUT ||
+ AML_FIELDFLAGS_UPDATERULE(flags) == AML_FIELDFLAGS_UPDATE_PRESERVE) {
+ for (i = 0; i < bytelen; i += handle.unit) {
+ state = aml_region_read_simple(&handle, i, &value);
+ if (state == -1) {
+ goto out;
+ }
+ readval |= (value << (i * 8));
+ }
+ AML_DEBUGPRINT("\t[%d:0x%x@0x%x:%d,%d]",
+ regtype, readval, handle.addr, offset, bitlen);
+ }
+
+ switch (io) {
+ case AML_REGION_INPUT:
+ AML_DEBUGPRINT("\n");
+ readval = aml_adjust_readvalue(flags, offset, bitlen, readval);
+ value = readval;
+ value = aml_region_prompt_read(&handle, value);
+ state = aml_region_prompt_update_value(readval, value, &handle);
+ if (state == -1) {
+ goto out;
+ }
+
+ *valuep = value;
+ break;
+ case AML_REGION_OUTPUT:
+ value = *valuep;
+ value = aml_adjust_updatevalue(flags, offset,
+ bitlen, readval, value);
+ value = aml_region_prompt_write(&handle, value);
+ AML_DEBUGPRINT("\t->[%d:0x%x@0x%x:%d,%d]\n", regtype, value,
+ handle.addr, offset, bitlen);
+ for (i = 0; i < bytelen; i += handle.unit) {
+ state = aml_region_write_simple(&handle, i, value);
+ if (state == -1) {
+ goto out;
+ }
+ value = value >> (handle.unit * 8);
+ }
+ break;
+ }
+
+ aml_region_handle_free(&handle);
+out:
+ return (state);
+}
+
+int
+aml_region_io(struct aml_environ *env, int io, int regtype,
+ u_int32_t flags, u_int32_t *valuep, u_int32_t baseaddr,
+ u_int32_t bitoffset, u_int32_t bitlen)
+{
+ u_int32_t unit, offset;
+ u_int32_t offadj, bitadj;
+ u_int32_t value, readval;
+ int state, i;
+
+ readval = 0;
+ state = 0;
+ unit = 4; /* limitation of 32 bits alignment */
+ offset = bitoffset % (unit * 8);
+ offadj = 0;
+ bitadj = 0;
+ if (offset + bitlen > unit * 8) {
+ bitadj = bitlen - (unit * 8 - offset);
+ }
+ for (i = 0; i < offset + bitlen; i += unit * 8) {
+ value = (*valuep) >> offadj;
+ state = aml_region_io_simple(env, io, regtype, flags,
+ &value, baseaddr, bitoffset + offadj, bitlen - bitadj);
+ if (state == -1) {
+ goto out;
+ }
+ readval |= value << offadj;
+ bitadj = offadj = bitlen - bitadj;
+ }
+ *valuep = readval;
+
+out:
+ return (state);
+}
diff --git a/sys/dev/acpi/aml/aml_common.h b/sys/dev/acpi/aml/aml_common.h
index ed253af..4988385 100644
--- a/sys/dev/acpi/aml/aml_common.h
+++ b/sys/dev/acpi/aml/aml_common.h
@@ -30,6 +30,9 @@
#ifndef _AML_COMMON_H_
#define _AML_COMMON_H_
+/*
+ * General Stuff
+ */
#ifdef _KERNEL
#define AML_SYSABORT() do { \
printf("aml: fatal errer at %s:%d\n", __FILE__, __LINE__); \
@@ -68,8 +71,85 @@ int aml_print_curname(struct aml_name *);
void aml_print_namestring(u_int8_t *);
void aml_print_indent(int);
+/*
+ * Reigion I/O Stuff for both kernel/userland.
+ */
+
+/*
+ * Field Flags
+ */
+/* bit 0 -3: AccessType */
+#define AML_FIELDFLAGS_ACCESS_ANYACC 0x00
+#define AML_FIELDFLAGS_ACCESS_BYTEACC 0x01
+#define AML_FIELDFLAGS_ACCESS_WORDACC 0x02
+#define AML_FIELDFLAGS_ACCESS_DWORDACC 0x03
+#define AML_FIELDFLAGS_ACCESS_BLOCKACC 0x04
+#define AML_FIELDFLAGS_ACCESS_SMBSENDRECVACC 0x05
+#define AML_FIELDFLAGS_ACCESS_SMBQUICKACC 0x06
+#define AML_FIELDFLAGS_ACCESSTYPE(flags) (flags & 0x0f)
+/* bit 4: LockRule */
+#define AML_FIELDFLAGS_LOCK_NOLOCK 0x00
+#define AML_FIELDFLAGS_LOCK_LOCK 0x10
+#define AML_FIELDFLAGS_LOCKRULE(flags) (flags & 0x10)
+/* bit 5 - 6: UpdateRule */
+#define AML_FIELDFLAGS_UPDATE_PRESERVE 0x00
+#define AML_FIELDFLAGS_UPDATE_WRITEASONES 0x20
+#define AML_FIELDFLAGS_UPDATE_WRITEASZEROS 0x40
+#define AML_FIELDFLAGS_UPDATERULE(flags) (flags & 0x60)
+/* bit 7: reserved (must be 0) */
+
+#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
+
+struct aml_region_handle {
+ /* These are copies of values used on initialization */
+ struct aml_environ *env;
+ int regtype;
+ u_int32_t flags;
+ u_int32_t baseaddr;
+ u_int32_t bitoffset;
+ u_int32_t bitlen;
+
+ /* following is determined on initialization */
+ vm_offset_t addr, bytelen;
+ u_int32_t unit; /* access unit in bytes */
+
+ /* region type dependant */
+ vm_offset_t vaddr; /* SystemMemory */
+ u_int32_t pci_bus, pci_devfunc; /* PCI_Config */
+};
+
+u_int32_t aml_adjust_readvalue(u_int32_t, u_int32_t, u_int32_t,
+ u_int32_t);
+u_int32_t aml_adjust_updatevalue(u_int32_t, u_int32_t, u_int32_t,
+ u_int32_t, u_int32_t);
+
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);
+int aml_region_handle_alloc(struct aml_environ *, int, u_int32_t,
+ u_int32_t, u_int32_t, u_int32_t,
+ struct aml_region_handle *);
+void aml_region_handle_free(struct aml_region_handle *);
+
+int aml_region_io(struct aml_environ *, int, int,
+ u_int32_t, u_int32_t *, u_int32_t,
+ u_int32_t, u_int32_t);
+extern int aml_region_read_simple(struct aml_region_handle *, vm_offset_t,
+ u_int32_t *);
+extern int aml_region_write_simple(struct aml_region_handle *, vm_offset_t,
+ u_int32_t);
+extern u_int32_t aml_region_prompt_read(struct aml_region_handle *,
+ u_int32_t);
+extern u_int32_t aml_region_prompt_write(struct aml_region_handle *,
+ u_int32_t);
+extern int aml_region_prompt_update_value(u_int32_t, u_int32_t,
+ struct aml_region_handle *);
#endif /* !_AML_COMMON_H_ */
diff --git a/sys/dev/acpi/aml/aml_evalobj.c b/sys/dev/acpi/aml/aml_evalobj.c
index 573ae26..41916f6 100644
--- a/sys/dev/acpi/aml/aml_evalobj.c
+++ b/sys/dev/acpi/aml/aml_evalobj.c
@@ -65,11 +65,13 @@ static union aml_object *aml_eval_fieldobject(struct aml_environ *env,
static union aml_object *
aml_eval_fieldobject(struct aml_environ *env, struct aml_name *name)
{
+ int num;
struct aml_name *oname,*wname;
struct aml_field *field;
struct aml_opregion *or;
union aml_object tobj;
+ num = 0;
/* CANNOT OCCUR! */
if (name == NULL || name->property == NULL ||
name->property->type != aml_t_field) {
@@ -116,7 +118,10 @@ aml_eval_fieldobject(struct aml_environ *env, struct aml_name *name)
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);
+ num = aml_objtonum(env, aml_eval_name(env, wname));
+ env->tempobject.type = aml_t_num;
+ env->tempobject.num.number = (num >> (field->bitoffset & 7)) &
+ ((1 << field->bitlen) - 1);
}
env->curname = oname;
return (&env->tempobject);
diff --git a/sys/dev/acpi/aml/aml_parse.c b/sys/dev/acpi/aml/aml_parse.c
index 344eb6c..560c910 100644
--- a/sys/dev/acpi/aml/aml_parse.c
+++ b/sys/dev/acpi/aml/aml_parse.c
@@ -1613,6 +1613,16 @@ aml_parse_termobj(struct aml_environ *env, int indent)
AML_DEBUGPRINT(", ");
destname1 = aml_parse_termobj(env, indent);
AML_DEBUGPRINT(")");
+ /* XXX
+ * temporary object may change during aml_store_to_name()
+ * operation, so we make a copy of it on stack.
+ */
+ if (destname1 == &env->tempname &&
+ destname1->property == &env->tempobject) {
+ destname1 = aml_create_local_object();
+ AML_COPY_OBJECT(destname1->property, env,
+ &env->tempobject, NULL);
+ }
aml_store_to_name(env, tmpobj, destname1);
if (env->stat == aml_stat_panic) {
AML_DEBUGPRINT("StoreOp failed");
diff --git a/sys/dev/acpi/aml/aml_region.c b/sys/dev/acpi/aml/aml_region.c
index 5f318a5..e50091a 100644
--- a/sys/dev/acpi/aml/aml_region.c
+++ b/sys/dev/acpi/aml/aml_region.c
@@ -44,316 +44,157 @@
#include <machine/acpica_osd.h>
#endif
-#define AML_REGION_INPUT 0
-#define AML_REGION_OUTPUT 1
+/*
+ * Dummy functions for aml_region_io_simple()
+ */
+u_int32_t
+aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
+{
-#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
+ return (value);
+}
-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_int32_t
+aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
{
- 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);
- }
+ return (value);
+}
- 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;
- }
+int
+aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
+ struct aml_region_handle *h)
+{
+ return (0);
+}
- /* 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;
+/*
+ * Primitive functions for aml_region_io_simple()
+ */
+int
+aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t *valuep)
+{
+ u_int32_t value;
+
+ switch (h->regtype) {
+ case AML_REGION_SYSMEM:
+ /* XXX should be MI */
+ switch (h->unit) {
+ case 1:
+ value = *(volatile u_int8_t *)(h->vaddr + offset);
+ value &= 0xff;
+ break;
+ case 2:
+ value = *(volatile u_int16_t *)(h->vaddr + offset);
+ value &= 0xffff;
+ break;
+ case 4:
+ value = *(volatile u_int32_t *)(h->vaddr + offset);
+ break;
}
- 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_SYSIO:
+ switch (h->unit) {
+ case 1:
+ value = OsdIn8(h->addr + offset);
+ value &= 0xff;
+ break;
+ case 2:
+ value = OsdIn16(h->addr + offset);
+ value &= 0xffff;
+ break;
+ case 4:
+ value = OsdIn32(h->addr + offset);
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;
+ case AML_REGION_PCICFG:
+ switch (h->unit) {
+ case 1:
+ OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc,
+ h->addr + offset, (UINT8 *)&value);
+ value &= 0xff;
+ break;
+ case 2:
+ OsdReadPciCfgWord(h->pci_bus, h->pci_devfunc,
+ h->addr + offset, (UINT16 *)&value);
+ value &= 0xffff;
+ break;
+ case 4:
+ OsdReadPciCfgDword(h->pci_bus, h->pci_devfunc,
+ h->addr + offset, &value);
break;
}
- goto io_done;
+ break;
+ default:
+ printf("aml_region_read_simple: not supported yet (%d)\n",
+ h->regtype);
+ value = 0;
+ break;
}
+ *valuep = value;
+ return (0);
+}
- for (i = 0; i < bytelen; i++) {
- /* XXX */
- switch (regtype) {
- case AML_REGION_SYSMEM:
- val = *(volatile u_int8_t *)(vaddr + i);
+int
+aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t value)
+{
+
+ switch (h->regtype) {
+ case AML_REGION_SYSMEM:
+ /* XXX should be MI */
+ switch (h->unit) {
+ case 1:
+ value &= 0xff;
+ *(volatile u_int8_t *)(h->vaddr + offset) = value;
+ break;
+ case 2:
+ value &= 0xffff;
+ *(volatile u_int16_t *)(h->vaddr + offset) = value;
break;
- case AML_REGION_SYSIO:
- val = OsdIn8(addr + i);
+ case 4:
+ *(volatile u_int32_t *)(h->vaddr + offset) = value;
+ break;
+ }
+ break;
+ case AML_REGION_SYSIO:
+ switch (h->unit) {
+ case 1:
+ value &= 0xff;
+ OsdOut8(h->addr + offset, value);
break;
- case AML_REGION_PCICFG:
- OsdReadPciCfgByte(pci_bus, pci_devfunc, addr + i, &val);
+ case 2:
+ value &= 0xffff;
+ OsdOut16(h->addr + offset, value);
break;
- default:
- printf("aml_region_io_system: not supported yet (%d)\n",
- regtype);
- val = 0;
+ case 4:
+ OsdOut32(h->addr + offset, value);
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_PCICFG:
+ switch (h->unit) {
+ case 1:
+ OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc,
+ h->addr + offset, 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;
- }
-
+ case 2:
+ OsdWritePciCfgWord(h->pci_bus, h->pci_devfunc,
+ h->addr + offset, value);
+ break;
+ case 4:
+ OsdWritePciCfgDword(h->pci_bus, h->pci_devfunc,
+ h->addr + offset, value);
break;
}
+ break;
+ default:
+ printf("aml_region_write_simple: not supported yet (%d)\n",
+ h->regtype);
+ break;
}
-io_done:
- if (regtype == AML_REGION_SYSMEM) {
- OsdUnMapMemory((void *)vaddr, bytelen);
- }
-
- aml_debug = debug; /* restore debug devel */
-
- return (state);
+ return (0);
}
static int
@@ -405,7 +246,9 @@ aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
int value;
int state;
- state = aml_region_io_system(env, AML_REGION_INPUT, regtype,
+ AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen);
+
+ state = aml_region_io(env, AML_REGION_INPUT, regtype,
flags, &value, addr, bitoffset, bitlen);
AML_SYSASSERT(state != -1);
@@ -419,6 +262,7 @@ aml_region_read_into_buffer(struct aml_environ *env, int regtype,
{
int state;
+ AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen);
state = aml_region_io_buffer(AML_REGION_INPUT, regtype, flags,
buffer, addr, bitoffset, bitlen);
@@ -431,7 +275,9 @@ aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
{
int state;
- state = aml_region_io_system(env, AML_REGION_OUTPUT, regtype,
+ AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen);
+
+ state = aml_region_io(env, AML_REGION_OUTPUT, regtype,
flags, &value, addr, bitoffset, bitlen);
AML_SYSASSERT(state != -1);
@@ -445,6 +291,9 @@ aml_region_write_from_buffer(struct aml_environ *env, int regtype,
{
int state;
+ AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags,
+ addr, bitoffset, bitlen);
+
state = aml_region_io_buffer(AML_REGION_OUTPUT, regtype, flags,
buffer, addr, bitoffset, bitlen);
@@ -460,6 +309,9 @@ aml_region_bcopy(struct aml_environ *env, int regtype,
vm_offset_t to_addr, to_vaddr;
size_t len;
+ AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen,
+ dflags, daddr, dbitoffset, dbitlen);
+
if (regtype != AML_REGION_SYSMEM) {
printf("aml_region_bcopy: region type isn't system memory!\n");
return (-1);
diff --git a/sys/dev/acpi/aml/aml_region.h b/sys/dev/acpi/aml/aml_region.h
index 599e6a5..caa3f6c 100644
--- a/sys/dev/acpi/aml/aml_region.h
+++ b/sys/dev/acpi/aml/aml_region.h
@@ -31,8 +31,42 @@
#define _AML_REGION_H_
/*
+ * Note that common part of region I/O is implemented in aml_common.c.
+ */
+
+/*
+ * Debug macros for region I/O
+ */
+
+#define AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen) \
+ AML_DEBUGPRINT("\n[aml_region_read(%d, %d, 0x%x, 0x%x, 0x%x)]\n",\
+ regtype, flags, addr, bitoffset, bitlen)
+
+#define AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, \
+ addr, bitoffset, bitlen) \
+ AML_DEBUGPRINT("\n[aml_region_read_into_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",\
+ regtype, flags, addr, bitoffset, bitlen)
+
+#define AML_REGION_WRITE_DEBUG(regtype, flags, value, \
+ addr, bitoffset, bitlen) \
+ AML_DEBUGPRINT("\n[aml_region_write(%d, %d, 0x%x, 0x%x, 0x%x, 0x%x)]\n",\
+ regtype, flags, value, addr, bitoffset, bitlen)
+
+#define AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags, \
+ addr, bitoffset, bitlen) \
+ AML_DEBUGPRINT("\n[aml_region_write_from_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",\
+ regtype, flags, addr, bitoffset, bitlen)
+
+#define AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen, \
+ dflags, daddr, dbitoffset, dbitlen) \
+ AML_DEBUGPRINT("\n[aml_region_bcopy(%d, %d, 0x%x, 0x%x, 0x%x, %d, 0x%x, 0x%x, 0x%x)]\n",\
+ regtype, flags, addr, bitoffset, bitlen, \
+ dflags, daddr, dbitoffset, dbitlen)
+
+/*
* Region I/O subroutine
*/
+
struct aml_environ;
u_int32_t aml_region_read(struct aml_environ *, int, u_int32_t,
diff --git a/sys/dev/acpi/aml/aml_store.c b/sys/dev/acpi/aml/aml_store.c
index ce9439d..20040b7 100644
--- a/sys/dev/acpi/aml/aml_store.c
+++ b/sys/dev/acpi/aml/aml_store.c
@@ -55,13 +55,14 @@ 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_name *wname, *oname, *iname;
struct aml_field *field;
struct aml_opregion *or;
- union aml_object tobj;
+ union aml_object tobj, iobj, *tmpobj;
field = &name->property->field;
oname = env->curname;
+ iname = NULL;
env->curname = name->parent;
if (field->f.ftype == f_t_field) {
wname = aml_search_name(env, field->f.fld.regname);
@@ -113,13 +114,23 @@ aml_store_to_fieldname(struct aml_environ *env, union aml_object *obj,
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);
+ iname = aml_search_name(env, field->f.ifld.indexname);
wname = aml_search_name(env, field->f.ifld.dataname);
+ iobj.type = aml_t_num;
+ iobj.num.number = field->bitoffset / 8; /* AccessType Boundary */
+
+ /* read whole values of IndexField */
+ aml_store_to_name(env, &iobj, iname);
+ tmpobj = aml_eval_name(env, wname);
+
+ /* make the values to be written */
tobj.num = obj->num;
- tobj.num.number = tobj.num.number << (field->bitoffset & 7);
+ tobj.num.number = aml_adjust_updatevalue(field->flags,
+ field->bitoffset & 7, field->bitlen,
+ tmpobj->num.number, obj->num.number);
+
+ /* write the values to IndexField */
+ aml_store_to_name(env, &iobj, iname);
aml_store_to_name(env, &tobj, wname);
}
env->curname = oname;
OpenPOWER on IntegriCloud