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:
parent
857fd445c3
commit
c369b3b021
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=66090
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user