Home | History | Annotate | Line # | Download | only in aml
aml_common.c revision 1.1
      1 /*	$NetBSD: aml_common.c,v 1.1 2007/01/14 04:36:13 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999 Takanori Watanabe
      5  * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki (at) FreeBSD.org>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  *
     29  *	Id: aml_common.c,v 1.9 2000/08/09 14:47:43 iwasaki Exp
     30  *	$FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_common.c,v 1.6 2000/11/09 06:24:45 iwasaki Exp $
     31  */
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: aml_common.c,v 1.1 2007/01/14 04:36:13 christos Exp $");
     34 
     35 #include <sys/param.h>
     36 
     37 #ifndef _KERNEL
     38 #include <assert.h>
     39 #include <err.h>
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <unistd.h>
     44 #else /* _KERNEL */
     45 #include "opt_acpi.h"
     46 #include <sys/kernel.h>
     47 #include <sys/sysctl.h>
     48 #include <sys/systm.h>
     49 #include <sys/bus.h>
     50 #include <machine/bus.h>
     51 #include <dev/acpi/acpireg.h>
     52 #include <dev/acpi/acpivar.h>
     53 #ifndef ACPI_NO_OSDFUNC_INLINE
     54 #include <machine/acpica_osd.h>
     55 #endif /* !ACPI_NO_OSDFUNC_INLINE */
     56 #endif /* !_KERNEL */
     57 
     58 #include <acpi_common.h>
     59 #include <aml/aml_common.h>
     60 #include <aml/aml_env.h>
     61 #include <aml/aml_evalobj.h>
     62 #include <aml/aml_name.h>
     63 #include <aml/aml_obj.h>
     64 #include <aml/aml_parse.h>
     65 #include <aml/aml_status.h>
     66 #include <aml/aml_store.h>
     67 
     68 /* for debugging */
     69 #ifdef AML_DEBUG
     70 int	aml_debug = 1;
     71 #else	/* !AML_DEBUG */
     72 int	aml_debug = 0;
     73 #endif	/* AML_DEBUG */
     74 #ifdef _KERNEL
     75 SYSCTL_INT(_debug, OID_AUTO, aml_debug, CTLFLAG_RW, &aml_debug, 1, "");
     76 #endif /* _KERNEL */
     77 
     78 static void	 aml_print_nameseg(u_int8_t *dp);
     79 
     80 static void
     81 aml_print_nameseg(u_int8_t *dp)
     82 {
     83 
     84 	if (dp[3] != '_') {
     85 		AML_DEBUGPRINT("%c%c%c%c", dp[0], dp[1], dp[2], dp[3]);
     86 	} else if (dp[2] != '_') {
     87 		AML_DEBUGPRINT("%c%c%c_", dp[0], dp[1], dp[2]);
     88 	} else if (dp[1] != '_') {
     89 		AML_DEBUGPRINT("%c%c__", dp[0], dp[1]);
     90 	} else if (dp[0] != '_') {
     91 		AML_DEBUGPRINT("%c___", dp[0]);
     92 	}
     93 }
     94 
     95 void
     96 aml_print_namestring(u_int8_t *dp)
     97 {
     98 	int	segcount;
     99 	int	i;
    100 
    101 	if (dp[0] == '\\') {
    102 		AML_DEBUGPRINT("%c", dp[0]);
    103 		dp++;
    104 	} else if (dp[0] == '^') {
    105 		while (dp[0] == '^') {
    106 			AML_DEBUGPRINT("%c", dp[0]);
    107 			dp++;
    108 		}
    109 	}
    110 	if (dp[0] == 0x00) {	/* NullName */
    111 		/* AML_DEBUGPRINT("<null>"); */
    112 		dp++;
    113 	} else if (dp[0] == 0x2e) {	/* DualNamePrefix */
    114 		aml_print_nameseg(dp + 1);
    115 		AML_DEBUGPRINT("%c", '.');
    116 		aml_print_nameseg(dp + 5);
    117 	} else if (dp[0] == 0x2f) {	/* MultiNamePrefix */
    118 		segcount = dp[1];
    119 		for (i = 0, dp += 2; i < segcount; i++, dp += 4) {
    120 			if (i > 0) {
    121 				AML_DEBUGPRINT("%c", '.');
    122 			}
    123 			aml_print_nameseg(dp);
    124 		}
    125 	} else			/* NameSeg */
    126 		aml_print_nameseg(dp);
    127 }
    128 
    129 int
    130 aml_print_curname(struct aml_name *name)
    131 {
    132 	struct	aml_name *root;
    133 
    134 	root = aml_get_rootname();
    135 	if (name == root) {
    136 		AML_DEBUGPRINT("\\");
    137 		return (0);
    138 	} else {
    139 		aml_print_curname(name->parent);
    140 	}
    141 	aml_print_nameseg((unsigned char *)name->name);
    142 	AML_DEBUGPRINT(".");
    143 	return (0);
    144 }
    145 
    146 void
    147 aml_print_indent(int indent)
    148 {
    149 	int	i;
    150 
    151 	for (i = 0; i < indent; i++)
    152 		AML_DEBUGPRINT("    ");
    153 }
    154 
    155 void
    156 aml_showobject(union aml_object * obj)
    157 {
    158 	int	debug;
    159 	int	i;
    160 
    161 	if (obj == NULL) {
    162 		printf("NO object\n");
    163 		return;
    164 	}
    165 	debug = aml_debug;
    166 	aml_debug = 1;
    167 	switch (obj->type) {
    168 	case aml_t_num:
    169 		printf("Num:0x%x\n", obj->num.number);
    170 		break;
    171 	case aml_t_processor:
    172 		printf("Processor:No %d,Port 0x%x length 0x%x\n",
    173 		    obj->proc.id, obj->proc.addr, obj->proc.len);
    174 		break;
    175 	case aml_t_mutex:
    176 		printf("Mutex:Level %d\n", obj->mutex.level);
    177 		break;
    178 	case aml_t_powerres:
    179 		printf("PowerResource:Level %d Order %d\n",
    180 		    obj->pres.level, obj->pres.order);
    181 		break;
    182 	case aml_t_opregion:
    183 		printf("OprationRegion:Busspace%d, Offset 0x%x Length 0x%x\n",
    184 		    obj->opregion.space, obj->opregion.offset,
    185 		    obj->opregion.length);
    186 		break;
    187 	case aml_t_field:
    188 		printf("Fieldelement:flag 0x%x offset 0x%x len 0x%x {",
    189 		    obj->field.flags, obj->field.bitoffset,
    190 		    obj->field.bitlen);
    191 		switch (obj->field.f.ftype) {
    192 		case f_t_field:
    193 			aml_print_namestring(obj->field.f.fld.regname);
    194 			break;
    195 		case f_t_index:
    196 			aml_print_namestring(obj->field.f.ifld.indexname);
    197 			printf(" ");
    198 			aml_print_namestring(obj->field.f.ifld.dataname);
    199 			break;
    200 		case f_t_bank:
    201 			aml_print_namestring(obj->field.f.bfld.regname);
    202 			printf(" ");
    203 			aml_print_namestring(obj->field.f.bfld.bankname);
    204 			printf("0x%x", obj->field.f.bfld.bankvalue);
    205 			break;
    206 		}
    207 		printf("}\n");
    208 		break;
    209 	case aml_t_method:
    210 		printf("Method: Arg %d From %p To %p\n", obj->meth.argnum,
    211 		    obj->meth.from, obj->meth.to);
    212 		break;
    213 	case aml_t_buffer:
    214 		printf("Buffer: size:0x%x Data %p\n", obj->buffer.size,
    215 		    obj->buffer.data);
    216 		break;
    217 	case aml_t_device:
    218 		printf("Device\n");
    219 		break;
    220 	case aml_t_bufferfield:
    221 		printf("Bufferfield:offset 0x%x len 0x%x Origin %p\n",
    222 		    obj->bfld.bitoffset, obj->bfld.bitlen, obj->bfld.origin);
    223 		break;
    224 	case aml_t_string:
    225 		printf("String:%s\n", obj->str.string);
    226 		break;
    227 	case aml_t_package:
    228 		printf("Package:elements %d \n", obj->package.elements);
    229 		for (i = 0; i < obj->package.elements; i++) {
    230 			if (obj->package.objects[i] == NULL) {
    231 				break;
    232 			}
    233 			if (obj->package.objects[i]->type < 0) {
    234 				continue;
    235 			}
    236 			printf("        ");
    237 			aml_showobject(obj->package.objects[i]);
    238 		}
    239 		break;
    240 	case aml_t_therm:
    241 		printf("Thermalzone\n");
    242 		break;
    243 	case aml_t_event:
    244 		printf("Event\n");
    245 		break;
    246 	case aml_t_ddbhandle:
    247 		printf("DDBHANDLE\n");
    248 		break;
    249 	case aml_t_objref:
    250 		if (obj->objref.alias == 1) {
    251 			printf("Alias");
    252 		} else {
    253 			printf("Object reference");
    254 			if (obj->objref.offset >= 0) {
    255 				printf(" (offset 0x%x)", obj->objref.offset);
    256 			}
    257 		}
    258 		printf(" of ");
    259 		aml_showobject(obj->objref.ref);
    260 		break;
    261 	default:
    262 		printf("UNK ID=%d\n", obj->type);
    263 	}
    264 
    265 	aml_debug = debug;
    266 }
    267 
    268 void
    269 aml_showtree(struct aml_name * aname, int lev)
    270 {
    271 	int	i;
    272 	struct	aml_name *ptr;
    273 	char	name[5];
    274 
    275 	for (i = 0; i < lev; i++) {
    276 		printf("  ");
    277 	}
    278 	strncpy(name, aname->name, 4);
    279 	name[4] = 0;
    280 	printf("%s  ", name);
    281 	if (aname->property != NULL) {
    282 		aml_showobject(aname->property);
    283 	} else {
    284 		printf("\n");
    285 	}
    286 	for (ptr = aname->child; ptr; ptr = ptr->brother)
    287 		aml_showtree(ptr, lev + 1);
    288 }
    289 
    290 /*
    291  * Common Region I/O Stuff
    292  */
    293 
    294 static __inline u_int64_t
    295 aml_adjust_bitmask(u_int32_t flags, u_int32_t bitlen)
    296 {
    297 	u_int64_t	bitmask;
    298 
    299 	switch (AML_FIELDFLAGS_ACCESSTYPE(flags)) {
    300 	case AML_FIELDFLAGS_ACCESS_ANYACC:
    301 		if (bitlen <= 8) {
    302 			bitmask = 0x000000ff;
    303 			break;
    304 		}
    305 		if (bitlen <= 16) {
    306 			bitmask = 0x0000ffff;
    307 			break;
    308 		}
    309 		bitmask = 0xffffffff;
    310 		break;
    311 	case AML_FIELDFLAGS_ACCESS_BYTEACC:
    312 		bitmask = 0x000000ff;
    313 		break;
    314 	case AML_FIELDFLAGS_ACCESS_WORDACC:
    315 		bitmask = 0x0000ffff;
    316 		break;
    317 	case AML_FIELDFLAGS_ACCESS_DWORDACC:
    318 	default:
    319 		bitmask = 0xffffffff;
    320 		break;
    321 	}
    322 
    323 	switch (bitlen) {
    324 	case 16:
    325 		bitmask |= 0x0000ffff;
    326 		break;
    327 	case 32:
    328 		bitmask |= 0xffffffff;
    329 		break;
    330 	}
    331 
    332 	return (bitmask);
    333 }
    334 
    335 u_int32_t
    336 aml_adjust_readvalue(u_int32_t flags, u_int32_t bitoffset, u_int32_t bitlen,
    337     u_int32_t orgval)
    338 {
    339 	u_int32_t	offset, retval;
    340 	u_int64_t	bitmask;
    341 
    342 	offset = bitoffset;	/* XXX bitoffset may change in this function! */
    343 	bitmask = aml_adjust_bitmask(flags, bitlen);
    344 	retval = (orgval >> offset) & (~(bitmask << bitlen)) & bitmask;
    345 
    346 	return (retval);
    347 }
    348 
    349 u_int32_t
    350 aml_adjust_updatevalue(u_int32_t flags, u_int32_t bitoffset, u_int32_t bitlen,
    351     u_int32_t orgval, u_int32_t value)
    352 {
    353 	u_int32_t	offset, retval;
    354 	u_int64_t	bitmask;
    355 
    356 	offset = bitoffset;	/* XXX bitoffset may change in this function! */
    357 	bitmask = aml_adjust_bitmask(flags, bitlen);
    358 	retval = orgval;
    359 	switch (AML_FIELDFLAGS_UPDATERULE(flags)) {
    360 	case AML_FIELDFLAGS_UPDATE_PRESERVE:
    361 		retval &= (~(((u_int64_t)1 << bitlen) - 1) << offset) |
    362 			  (~(bitmask << offset));
    363 		break;
    364 	case AML_FIELDFLAGS_UPDATE_WRITEASONES:
    365 		retval =  (~(((u_int64_t)1 << bitlen) - 1) << offset) |
    366 			  (~(bitmask << offset));
    367 		retval &= bitmask;	/* trim the upper bits */
    368 		break;
    369 	case AML_FIELDFLAGS_UPDATE_WRITEASZEROS:
    370 		retval = 0;
    371 		break;
    372 	default:
    373 		printf("illegal update rule: %d\n", flags);
    374 		return (orgval);
    375 	}
    376 
    377 	retval |= (value << (offset & bitmask));
    378 	return (retval);
    379 }
    380 
    381 /*
    382  * BufferField I/O
    383  */
    384 
    385 #define AML_BUFFER_INPUT	0
    386 #define AML_BUFFER_OUTPUT	1
    387 
    388 static int	 aml_bufferfield_io(int io, u_int32_t *valuep,
    389 				    u_int8_t *origin, u_int32_t bitoffset,
    390 				    u_int32_t bitlen);
    391 
    392 static int
    393 aml_bufferfield_io(int io, u_int32_t *valuep, u_int8_t *origin,
    394     u_int32_t bitoffset, u_int32_t bitlen)
    395 {
    396 	u_int8_t	val, tmp, masklow, maskhigh;
    397 	u_int8_t	offsetlow, offsethigh;
    398 	u_int8_t	*addr;
    399 	int		i;
    400 	u_int32_t	value, readval;
    401 	u_int32_t	byteoffset, bytelen;
    402 
    403 	masklow = maskhigh = 0xff;
    404 	val = readval = 0;
    405 	value = *valuep;
    406 
    407 	byteoffset = bitoffset / 8;
    408 	bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
    409 	addr = origin + byteoffset;
    410 
    411 	/* simple I/O ? */
    412 	if (bitlen <= 8 || bitlen == 16 || bitlen == 32) {
    413 		bcopy(addr, &readval, bytelen);
    414 		AML_DEBUGPRINT("\n\t[bufferfield:0x%x@%p:%d,%d]",
    415 		    readval, addr, bitoffset % 8, bitlen);
    416 		switch (io) {
    417 		case AML_BUFFER_INPUT:
    418 			value = aml_adjust_readvalue(AML_FIELDFLAGS_ACCESS_BYTEACC,
    419 			    bitoffset % 8, bitlen, readval);
    420 			*valuep = value;
    421 			AML_DEBUGPRINT("\n[read(bufferfield, %p)&mask:0x%x]\n",
    422 			    addr, value);
    423 			break;
    424 		case AML_BUFFER_OUTPUT:
    425 			value = aml_adjust_updatevalue(AML_FIELDFLAGS_ACCESS_BYTEACC,
    426 			    bitoffset % 8, bitlen, readval, value);
    427 			bcopy(&value, addr, bytelen);
    428 			AML_DEBUGPRINT("->[bufferfield:0x%x@%p:%d,%d]",
    429 			    value, addr, bitoffset % 8, bitlen);
    430 			break;
    431 		}
    432 		goto out;
    433 	}
    434 
    435 	offsetlow = bitoffset % 8;
    436 	if (bytelen > 1) {
    437 		offsethigh = (bitlen - (8 - offsetlow)) % 8;
    438 	} else {
    439 		offsethigh = 0;
    440 	}
    441 
    442 	if (offsetlow) {
    443 		masklow = (~((1 << bitlen) - 1) << offsetlow) | ~(0xff << offsetlow);
    444 		AML_DEBUGPRINT("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n",
    445 		    offsetlow, masklow, ~masklow & 0xff);
    446 	}
    447 	if (offsethigh) {
    448 		maskhigh = 0xff << offsethigh;
    449 		AML_DEBUGPRINT("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n",
    450 		    offsethigh, maskhigh, ~maskhigh & 0xff);
    451 	}
    452 	for (i = bytelen; i > 0; i--, addr++) {
    453 		val = *addr;
    454 
    455 		AML_DEBUGPRINT("\t[bufferfield:0x%02x@%p]", val, addr);
    456 
    457 		switch (io) {
    458 		case AML_BUFFER_INPUT:
    459 			tmp = val;
    460 			/* the lowest byte? */
    461 			if (i == bytelen) {
    462 				if (offsetlow) {
    463 					readval = tmp & ~masklow;
    464 				} else {
    465 					readval = tmp;
    466 				}
    467 			} else {
    468 				if (i == 1 && offsethigh) {
    469 					tmp = tmp & ~maskhigh;
    470 				}
    471 				readval = (tmp << (8 * (bytelen - i))) | readval;
    472 			}
    473 
    474 			AML_DEBUGPRINT("\n");
    475 			/* goto to next byte... */
    476 			if (i > 1) {
    477 				continue;
    478 			}
    479 			/* final adjustment before finishing region access */
    480 			if (offsetlow) {
    481 				readval = readval >> offsetlow;
    482 			}
    483 			AML_DEBUGPRINT("[read(bufferfield, %p)&mask:0x%x]\n",
    484 			    addr, readval);
    485 			*valuep = readval;
    486 
    487 			break;
    488 
    489 		case AML_BUFFER_OUTPUT:
    490 			tmp = value & 0xff;
    491 			/* the lowest byte? */
    492 			if (i == bytelen) {
    493 				if (offsetlow) {
    494 					tmp = (val & masklow) | tmp << offsetlow;
    495 				}
    496 				value = value >> (8 - offsetlow);
    497 			} else {
    498 				if (i == 1 && offsethigh) {
    499 					tmp = (val & maskhigh) | tmp;
    500 				}
    501 				value = value >> 8;
    502 			}
    503 
    504 			AML_DEBUGPRINT("->[bufferfield:0x%02x@%p]\n",
    505 			    tmp, addr);
    506 			*addr = tmp;
    507 		}
    508 	}
    509 out:
    510 	return (0);
    511 }
    512 
    513 u_int32_t
    514 aml_bufferfield_read(u_int8_t *origin, u_int32_t bitoffset,
    515     u_int32_t bitlen)
    516 {
    517 	int	value;
    518 
    519 	value = 0;
    520 	aml_bufferfield_io(AML_BUFFER_INPUT, (u_int32_t *)&value, origin,
    521 	    bitoffset, bitlen);
    522 	return (value);
    523 }
    524 
    525 int
    526 aml_bufferfield_write(u_int32_t value, u_int8_t *origin,
    527     u_int32_t bitoffset, u_int32_t bitlen)
    528 {
    529 	int	status;
    530 
    531 	status = aml_bufferfield_io(AML_BUFFER_OUTPUT, &value,
    532 	    origin, bitoffset, bitlen);
    533 	return (status);
    534 }
    535 
    536 int
    537 aml_region_handle_alloc(struct aml_environ *env, int regtype, u_int32_t flags,
    538     u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen,
    539     struct aml_region_handle *h)
    540 {
    541 	int	state;
    542 	struct	aml_name *pci_info;
    543 
    544 	state = 0;
    545 	pci_info = NULL;
    546 	bzero(h, sizeof(struct aml_region_handle));
    547 
    548 	h->env = env;
    549 	h->regtype = regtype;
    550 	h->flags = flags;
    551 	h->baseaddr = baseaddr;
    552 	h->bitoffset = bitoffset;
    553 	h->bitlen = bitlen;
    554 
    555 	switch (AML_FIELDFLAGS_ACCESSTYPE(flags)) {
    556 	case AML_FIELDFLAGS_ACCESS_ANYACC:
    557 		if (bitlen <= 8) {
    558 			h->unit = 1;
    559 			break;
    560 		}
    561 		if (bitlen <= 16) {
    562 			h->unit = 2;
    563 			break;
    564 		}
    565 		h->unit = 4;
    566 		break;
    567 	case AML_FIELDFLAGS_ACCESS_BYTEACC:
    568 		h->unit = 1;
    569 		break;
    570 	case AML_FIELDFLAGS_ACCESS_WORDACC:
    571 		h->unit = 2;
    572 		break;
    573 	case AML_FIELDFLAGS_ACCESS_DWORDACC:
    574 		h->unit = 4;
    575 		break;
    576 	default:
    577 		h->unit = 1;
    578 		break;
    579 	}
    580 
    581 	h->addr = baseaddr + h->unit * ((bitoffset / 8) / h->unit);
    582 	h->bytelen = baseaddr + ((bitoffset + bitlen) / 8) - h->addr +
    583 		     ((bitlen % 8) ? 1 : 0);
    584 
    585 #ifdef _KERNEL
    586 	switch (h->regtype) {
    587 	case AML_REGION_SYSMEM:
    588 		OsdMapMemory((void *)h->addr, h->bytelen, (void **)&h->vaddr);
    589 		break;
    590 
    591 	case AML_REGION_PCICFG:
    592 		/* Obtain PCI bus number */
    593 		pci_info = aml_search_name(env, "_BBN");
    594 		if (pci_info == NULL || pci_info->property->type != aml_t_num) {
    595 			AML_DEBUGPRINT("Cannot locate _BBN. Using default 0\n");
    596 			h->pci_bus = 0;
    597 		} else {
    598 			AML_DEBUGPRINT("found _BBN: %d\n",
    599 			    pci_info->property->num.number);
    600 			h->pci_bus = pci_info->property->num.number & 0xff;
    601 		}
    602 
    603 		/* Obtain device & function number */
    604 		pci_info = aml_search_name(env, "_ADR");
    605 		if (pci_info == NULL || pci_info->property->type != aml_t_num) {
    606 			printf("Cannot locate: _ADR\n");
    607 			state = -1;
    608 			goto out;
    609 		}
    610 		h->pci_devfunc = pci_info->property->num.number;
    611 
    612 		AML_DEBUGPRINT("[pci%d.%d]", h->pci_bus, h->pci_devfunc);
    613 		break;
    614 
    615 	default:
    616 		break;
    617 	}
    618 
    619 out:
    620 #endif	/* _KERNEL */
    621 	return (state);
    622 }
    623 
    624 void
    625 aml_region_handle_free(struct aml_region_handle *h)
    626 {
    627 #ifdef _KERNEL
    628 	switch (h->regtype) {
    629 	case AML_REGION_SYSMEM:
    630 		OsdUnMapMemory((void *)h->vaddr, h->bytelen);
    631 		break;
    632 
    633 	default:
    634 		break;
    635 	}
    636 #endif	/* _KERNEL */
    637 }
    638 
    639 static int
    640 aml_region_io_simple(struct aml_environ *env, int io, int regtype,
    641     u_int32_t flags, u_int32_t *valuep, u_int32_t baseaddr,
    642     u_int32_t bitoffset, u_int32_t bitlen)
    643 {
    644 	int		i, state;
    645 	u_int32_t	readval, value, offset, bytelen;
    646 	struct		aml_region_handle handle;
    647 
    648 	state = aml_region_handle_alloc(env, regtype, flags,
    649             baseaddr, bitoffset, bitlen, &handle);
    650 	if (state == -1) {
    651 		goto out;
    652 	}
    653 
    654 	readval = 0;
    655 	offset = bitoffset % (handle.unit * 8);
    656 	/* limitation of 32 bits alignment */
    657 	bytelen = (handle.bytelen > 4) ? 4 : handle.bytelen;
    658 
    659 	if (io == AML_REGION_INPUT ||
    660 	    AML_FIELDFLAGS_UPDATERULE(flags) == AML_FIELDFLAGS_UPDATE_PRESERVE) {
    661 		for (i = 0; i < bytelen; i += handle.unit) {
    662 			state = aml_region_read_simple(&handle, i, &value);
    663 			if (state == -1) {
    664 				goto out;
    665 			}
    666 			readval |= (value << (i * 8));
    667 		}
    668 		AML_DEBUGPRINT("\t[%d:0x%x@0x%lx:%d,%d]",
    669 		    regtype, readval, handle.addr, offset, bitlen);
    670 	}
    671 
    672 	switch (io) {
    673 	case AML_REGION_INPUT:
    674 		AML_DEBUGPRINT("\n");
    675 		readval = aml_adjust_readvalue(flags, offset, bitlen, readval);
    676 		value = readval;
    677 		value = aml_region_prompt_read(&handle, value);
    678 		state = aml_region_prompt_update_value(readval, value, &handle);
    679 		if (state == -1) {
    680 			goto out;
    681 		}
    682 
    683 		*valuep = value;
    684 		break;
    685 	case AML_REGION_OUTPUT:
    686 		value = *valuep;
    687 		value = aml_adjust_updatevalue(flags, offset,
    688 		    bitlen, readval, value);
    689 		value = aml_region_prompt_write(&handle, value);
    690 		AML_DEBUGPRINT("\t->[%d:0x%x@0x%lx:%d,%d]\n", regtype, value,
    691 		    handle.addr, offset, bitlen);
    692 		for (i = 0; i < bytelen; i += handle.unit) {
    693 			state = aml_region_write_simple(&handle, i, value);
    694 			if (state == -1) {
    695 				goto out;
    696 			}
    697 			value = value >> (handle.unit * 8);
    698 		}
    699 		break;
    700 	}
    701 
    702 	aml_region_handle_free(&handle);
    703 out:
    704 	return (state);
    705 }
    706 
    707 int
    708 aml_region_io(struct aml_environ *env, int io, int regtype,
    709     u_int32_t flags, u_int32_t *valuep, u_int32_t baseaddr,
    710     u_int32_t bitoffset, u_int32_t bitlen)
    711 {
    712 	u_int32_t	unit, offset;
    713 	u_int32_t	offadj, bitadj;
    714 	u_int32_t	value, readval;
    715 	int		state, i;
    716 
    717 	readval = 0;
    718 	state = 0;
    719 	unit = 4;	/* limitation of 32 bits alignment */
    720 	offset = bitoffset % (unit * 8);
    721 	offadj = 0;
    722 	bitadj = 0;
    723 	if (offset + bitlen > unit * 8) {
    724 		bitadj = bitlen  - (unit * 8 - offset);
    725 	}
    726 	for (i = 0; i < offset + bitlen; i += unit * 8) {
    727 		value = (*valuep) >> offadj;
    728 		state = aml_region_io_simple(env, io, regtype, flags,
    729 		    &value, baseaddr, bitoffset + offadj, bitlen - bitadj);
    730 		if (state == -1) {
    731 			goto out;
    732 		}
    733 		readval |= value << offadj;
    734 		bitadj = offadj = bitlen - bitadj;
    735 	}
    736 	*valuep = readval;
    737 
    738 out:
    739 	return (state);
    740 }
    741