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.
This commit is contained in:
Mitsuru IWASAKI 2000-09-20 01:01:32 +00:00
parent 857fd445c3
commit c369b3b021
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=66090
15 changed files with 1356 additions and 754 deletions

View File

@ -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>
@ -275,6 +276,97 @@ aml_showtree(struct aml_name * aname, int lev)
aml_showtree(ptr, lev + 1);
}
/*
* 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);
}

View File

@ -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_ */

View File

@ -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);

View File

@ -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");

View File

@ -44,316 +44,157 @@
#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)
/*
* Dummy functions for aml_region_io_simple()
*/
u_int32_t
aml_region_prompt_read(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;
return (value);
}
value = *valuep;
val = readval = 0;
masklow = maskhigh = 0xff;
state = 0;
vaddr = 0;
pci_bus = pci_devfunc = 0;
u_int32_t
aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
{
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;
}
return (value);
}
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);
}
int
aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
struct aml_region_handle *h)
{
return (0);
}
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;
/*
* 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;
/* 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;
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 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;
}
case 2:
value = *(volatile u_int16_t *)(h->vaddr + offset);
value &= 0xffff;
break;
case 4:
value = *(volatile u_int32_t *)(h->vaddr + offset);
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:
switch (h->unit) {
case 1:
value = OsdIn8(h->addr + offset);
value &= 0xff;
break;
case AML_REGION_SYSIO:
val = OsdIn8(addr + i);
case 2:
value = OsdIn16(h->addr + offset);
value &= 0xffff;
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;
case 4:
value = OsdIn32(h->addr + offset);
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:
OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc,
h->addr + offset, (UINT8 *)&value);
value &= 0xff;
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:
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;
}
break;
default:
printf("aml_region_read_simple: not supported yet (%d)\n",
h->regtype);
value = 0;
break;
}
*valuep = value;
return (0);
}
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 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 2:
value &= 0xffff;
OsdOut16(h->addr + offset, value);
break;
case 4:
OsdOut32(h->addr + offset, value);
break;
}
break;
case AML_REGION_PCICFG:
switch (h->unit) {
case 1:
OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc,
h->addr + offset, value);
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);

View File

@ -30,9 +30,43 @@
#ifndef _AML_REGION_H_
#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,

View File

@ -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;

View File

@ -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>
@ -275,6 +276,97 @@ aml_showtree(struct aml_name * aname, int lev)
aml_showtree(ptr, lev + 1);
}
/*
* 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);
}

View File

@ -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_ */

View File

@ -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);

View File

@ -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");

View File

@ -44,316 +44,157 @@
#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)
/*
* Dummy functions for aml_region_io_simple()
*/
u_int32_t
aml_region_prompt_read(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;
return (value);
}
value = *valuep;
val = readval = 0;
masklow = maskhigh = 0xff;
state = 0;
vaddr = 0;
pci_bus = pci_devfunc = 0;
u_int32_t
aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
{
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;
}
return (value);
}
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);
}
int
aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
struct aml_region_handle *h)
{
return (0);
}
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;
/*
* 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;
/* 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;
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 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;
}
case 2:
value = *(volatile u_int16_t *)(h->vaddr + offset);
value &= 0xffff;
break;
case 4:
value = *(volatile u_int32_t *)(h->vaddr + offset);
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:
switch (h->unit) {
case 1:
value = OsdIn8(h->addr + offset);
value &= 0xff;
break;
case AML_REGION_SYSIO:
val = OsdIn8(addr + i);
case 2:
value = OsdIn16(h->addr + offset);
value &= 0xffff;
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;
case 4:
value = OsdIn32(h->addr + offset);
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:
OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc,
h->addr + offset, (UINT8 *)&value);
value &= 0xff;
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:
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;
}
break;
default:
printf("aml_region_read_simple: not supported yet (%d)\n",
h->regtype);
value = 0;
break;
}
*valuep = value;
return (0);
}
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 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 2:
value &= 0xffff;
OsdOut16(h->addr + offset, value);
break;
case 4:
OsdOut32(h->addr + offset, value);
break;
}
break;
case AML_REGION_PCICFG:
switch (h->unit) {
case 1:
OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc,
h->addr + offset, value);
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);

View File

@ -30,9 +30,43 @@
#ifndef _AML_REGION_H_
#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,

View File

@ -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;

View File

@ -36,6 +36,7 @@
#include <dev/acpi/aml/aml_amlmem.h>
#include <dev/acpi/aml/aml_name.h>
#include <dev/acpi/aml/aml_region.h>
#include <dev/acpi/aml/aml_common.h>
#include <assert.h>
@ -199,133 +200,102 @@ aml_simulation_regload(const char *dumpfile)
fclose(fp);
}
#define ACPI_REGION_INPUT 0
#define ACPI_REGION_OUTPUT 1
static int
aml_simulate_region_io(int io, int regtype, u_int32_t flags, u_int32_t *valuep,
u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen, int prompt)
int
aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset,
u_int32_t *valuep)
{
char buf[64];
u_int8_t val, tmp, masklow, maskhigh;
u_int8_t offsetlow, offsethigh;
u_int32_t addr, byteoffset, bytelen;
int value, readval;
int state, i;
int i, state;
u_int8_t val;
u_int32_t value;
value = *valuep;
val = readval = 0;
masklow = maskhigh = 0xff;
state = 0;
byteoffset = bitoffset / 8;
bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
addr = baseaddr + byteoffset;
offsetlow = bitoffset % 8;
if (bytelen > 1) {
offsethigh = (bitlen - (8 - offsetlow)) % 8;
} else {
offsethigh = 0;
}
if (offsetlow) {
masklow = (~((1 << bitlen) - 1) << offsetlow) | \
~(0xff << offsetlow);
printf("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n",
offsetlow, masklow, ~masklow & 0xff);
}
if (offsethigh) {
maskhigh = 0xff << offsethigh;
printf("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n",
offsethigh, maskhigh, ~maskhigh & 0xff);
}
for (i = bytelen; i > 0; i--, addr++) {
val = 0;
state = aml_simulate_regcontent_read(regtype, addr, &val);
value = val = 0;
for (i = 0; i < h->unit; i++) {
state = aml_simulate_regcontent_read(h->regtype,
h->addr + offset + i, &val);
if (state == -1) {
goto finish;
goto out;
}
printf("\t[%d:0x%02x@0x%x]", regtype, val, addr);
value |= val << (i * 8);
}
*valuep = value;
out:
return (state);
}
switch (io) {
case ACPI_REGION_INPUT:
tmp = val;
/* the lowest byte? */
if (i == bytelen) {
if (offsetlow) {
readval = tmp & ~masklow;
} else {
readval = tmp;
}
} else {
if (i == 1 && offsethigh) {
tmp = tmp & ~maskhigh;
}
readval = (tmp << (8 * (bytelen - i))) | readval;
}
int
aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset,
u_int32_t value)
{
int i, state;
u_int8_t val;
printf("\n");
/* goto to next byte... */
if (i > 1) {
continue;
}
/* final adjustment before finishing region access */
if (offsetlow) {
readval = readval >> offsetlow;
}
sprintf(buf, "[read(%d, 0x%x)&mask:0x%x]",
regtype, addr, readval);
if (prompt) {
value = aml_simulate_prompt(buf, readval);
if (readval != value) {
state = aml_simulate_region_io(ACPI_REGION_OUTPUT,
regtype, flags, &value, baseaddr,
bitoffset, bitlen, 0);
if (state == -1) {
goto finish;
}
}
} else {
printf("\t%s\n", buf);
value = readval;
}
*valuep = value;
state = 0;
val = 0;
for (i = 0; i < h->unit; i++) {
val = value & 0xff;
state = aml_simulate_regcontent_write(h->regtype,
h->addr + offset + i, &val);
if (state == -1) {
goto out;
}
value = value >> 8;
}
out:
return (state);
}
break;
case ACPI_REGION_OUTPUT:
tmp = value & 0xff;
/* the lowest byte? */
if (i == bytelen) {
if (offsetlow) {
tmp = (val & masklow) | tmp << offsetlow;
}
value = value >> (8 - offsetlow);
} else {
if (i == 1 && offsethigh) {
tmp = (val & maskhigh) | tmp;
}
value = value >> 8;
}
u_int32_t
aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
{
u_int32_t retval;
char buf[64];
if (prompt) {
printf("\n");
sprintf(buf, "[write(%d, 0x%02x, 0x%x)]",
regtype, tmp, addr);
val = aml_simulate_prompt(buf, tmp);
} else {
printf("->[%d:0x%02x@0x%x]\n",
regtype, tmp, addr);
val = tmp;
}
state = aml_simulate_regcontent_write(regtype,
addr, &val);
if (state == -1) {
goto finish;
}
break;
retval = value;
sprintf(buf, "[read(%d, 0x%x)&mask:0x%x]",
h->regtype, h->addr, value);
if (aml_debug_prompt_reginput) {
retval = aml_simulate_prompt(buf, value);
} else {
printf("\t%s\n", buf);
}
return (retval);
}
u_int32_t
aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
{
u_int32_t retval;
char buf[64];
retval = value;
if (aml_debug_prompt_regoutput) {
printf("\n");
sprintf(buf, "[write(%d, 0x%x, 0x%x)]",
h->regtype, value, h->addr);
retval = aml_simulate_prompt(buf, value);
}
return (retval);
}
int
aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
struct aml_region_handle *h)
{
int state;
state = 0;
if (orgval != value) {
state = aml_region_io(h->env, AML_REGION_OUTPUT, h->regtype,
h->flags, &value, h->baseaddr, h->bitoffset, h->bitlen);
if (state == -1) {
goto out;
}
}
finish:
out:
return (state);
}
@ -355,7 +325,7 @@ aml_simulate_region_io_buffer(int io, int regtype, u_int32_t flags,
for (i = bytelen; i > 0; i--, addr++) {
switch (io) {
case ACPI_REGION_INPUT:
case AML_REGION_INPUT:
val = 0;
state = aml_simulate_regcontent_read(regtype, addr, &val);
if (state == -1) {
@ -363,7 +333,7 @@ aml_simulate_region_io_buffer(int io, int regtype, u_int32_t flags,
}
buffer[bytelen - i] = val;
break;
case ACPI_REGION_OUTPUT:
case AML_REGION_OUTPUT:
val = buffer[bytelen - i];
state = aml_simulate_regcontent_write(regtype,
addr, &val);
@ -378,16 +348,14 @@ aml_simulate_region_io_buffer(int io, int regtype, u_int32_t flags,
}
static u_int32_t
aml_simulate_region_read(int regtype, u_int32_t flags, u_int32_t addr,
u_int32_t bitoffset, u_int32_t bitlen)
aml_simulate_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;
AML_DEBUGPRINT("\n[aml_region_read(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
regtype, flags, addr, bitoffset, bitlen);
state = aml_simulate_region_io(ACPI_REGION_INPUT, regtype, flags, &value,
addr, bitoffset, bitlen, aml_debug_prompt_reginput);
state = aml_region_io(env, AML_REGION_INPUT, regtype, flags, &value,
addr, bitoffset, bitlen);
assert(state != -1);
return (value);
}
@ -398,24 +366,21 @@ aml_simulate_region_read_into_buffer(int regtype, u_int32_t flags,
{
int state;
AML_DEBUGPRINT("\n[aml_region_read_into_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
regtype, flags, addr, bitoffset, bitlen);
state = aml_simulate_region_io_buffer(ACPI_REGION_INPUT, regtype, flags,
state = aml_simulate_region_io_buffer(AML_REGION_INPUT, regtype, flags,
buffer, addr, bitoffset, bitlen);
assert(state != -1);
return (state);
}
int
aml_simulate_region_write(int regtype, u_int32_t flags, u_int32_t value,
u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
aml_simulate_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;
AML_DEBUGPRINT("\n[aml_region_write(%d, %d, 0x%x, 0x%x, 0x%x, 0x%x)]\n",
regtype, flags, value, addr, bitoffset, bitlen);
state = aml_simulate_region_io(ACPI_REGION_OUTPUT, regtype, flags,
&value, addr, bitoffset, bitlen, aml_debug_prompt_regoutput);
state = aml_region_io(env, AML_REGION_OUTPUT, regtype, flags,
&value, addr, bitoffset, bitlen);
assert(state != -1);
return (state);
}
@ -426,16 +391,15 @@ aml_simulate_region_write_from_buffer(int regtype, u_int32_t flags,
{
int state;
AML_DEBUGPRINT("\n[aml_region_write_from_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
regtype, flags, addr, bitoffset, bitlen);
state = aml_simulate_region_io_buffer(ACPI_REGION_OUTPUT, regtype,
state = aml_simulate_region_io_buffer(AML_REGION_OUTPUT, regtype,
flags, buffer, addr, bitoffset, bitlen);
assert(state != -1);
return (state);
}
int
aml_simulate_region_bcopy(int regtype, u_int32_t flags, u_int32_t addr,
aml_simulate_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)
@ -444,19 +408,15 @@ aml_simulate_region_bcopy(int regtype, u_int32_t flags, u_int32_t addr,
u_int32_t value;
int state;
AML_DEBUGPRINT("\n[aml_region_bcopy(%d, %d, 0x%x, 0x%x, 0x%x, %d, 0x%x, 0x%x, 0x%x)]\n",
regtype, flags, addr, bitoffset, bitlen,
dflags, daddr, dbitoffset, dbitlen);
len = (bitlen > dbitlen) ? dbitlen : bitlen;
len = len / 8 + ((len % 8) ? 1 : 0);
for (i = 0; i < len; i++) {
state = aml_simulate_region_io(ACPI_REGION_INPUT, regtype,
flags, &value, addr, bitoffset + i * 8, 8, 0);
state = aml_region_io(env, AML_REGION_INPUT, regtype,
flags, &value, addr, bitoffset + i * 8, 8);
assert(state != -1);
state = aml_simulate_region_io(ACPI_REGION_OUTPUT, regtype,
dflags, &value, daddr, dbitoffset + i * 8, 8, 0);
state = aml_region_io(env, AML_REGION_OUTPUT, regtype,
dflags, &value, daddr, dbitoffset + i * 8, 8);
assert(state != -1);
}
@ -468,7 +428,9 @@ aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
{
return (aml_simulate_region_read(regtype, flags, addr,
AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen);
return (aml_simulate_region_read(env, regtype, flags, addr,
bitoffset, bitlen));
}
@ -478,6 +440,8 @@ aml_region_read_into_buffer(struct aml_environ *env, int regtype,
u_int32_t bitlen, u_int8_t *buffer)
{
AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen);
return (aml_simulate_region_read_into_buffer(regtype, flags, addr,
bitoffset, bitlen, buffer));
}
@ -487,7 +451,9 @@ aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
{
return (aml_simulate_region_write(regtype, flags, value, addr,
AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen);
return (aml_simulate_region_write(env, regtype, flags, value, addr,
bitoffset, bitlen));
}
@ -497,6 +463,9 @@ aml_region_write_from_buffer(struct aml_environ *env, int regtype,
u_int32_t bitlen)
{
AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags,
addr, bitoffset, bitlen);
return (aml_simulate_region_write_from_buffer(regtype, flags, buffer,
addr, bitoffset, bitlen));
}
@ -508,7 +477,10 @@ aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
u_int32_t dbitoffset, u_int32_t dbitlen)
{
return (aml_simulate_region_bcopy(regtype, flags, addr, bitoffset,
AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen,
dflags, daddr, dbitoffset, dbitlen);
return (aml_simulate_region_bcopy(env, regtype, flags, addr, bitoffset,
bitlen, dflags, daddr, dbitoffset, dbitlen));
}