1 /* $NetBSD: aml_common.c,v 1.1 2007/01/14 04:36:13 christos Exp $ */
4 * Copyright (c) 1999 Takanori Watanabe
5 * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
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 $
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: aml_common.c,v 1.1 2007/01/14 04:36:13 christos Exp $");
35 #include <sys/param.h>
46 #include <sys/kernel.h>
47 #include <sys/sysctl.h>
48 #include <sys/systm.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 */
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>
71 #else /* !AML_DEBUG */
73 #endif /* AML_DEBUG */
75 SYSCTL_INT(_debug
, OID_AUTO
, aml_debug
, CTLFLAG_RW
, &aml_debug
, 1, "");
78 static void aml_print_nameseg(u_int8_t
*dp
);
81 aml_print_nameseg(u_int8_t
*dp
)
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]);
96 aml_print_namestring(u_int8_t
*dp
)
102 AML_DEBUGPRINT("%c", dp
[0]);
104 } else if (dp
[0] == '^') {
105 while (dp
[0] == '^') {
106 AML_DEBUGPRINT("%c", dp
[0]);
110 if (dp
[0] == 0x00) { /* NullName */
111 /* AML_DEBUGPRINT("<null>"); */
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 */
119 for (i
= 0, dp
+= 2; i
< segcount
; i
++, dp
+= 4) {
121 AML_DEBUGPRINT("%c", '.');
123 aml_print_nameseg(dp
);
126 aml_print_nameseg(dp
);
130 aml_print_curname(struct aml_name
*name
)
132 struct aml_name
*root
;
134 root
= aml_get_rootname();
136 AML_DEBUGPRINT("\\");
139 aml_print_curname(name
->parent
);
141 aml_print_nameseg((unsigned char *)name
->name
);
147 aml_print_indent(int indent
)
151 for (i
= 0; i
< indent
; i
++)
156 aml_showobject(union aml_object
* obj
)
162 printf("NO object\n");
169 printf("Num:0x%x\n", obj
->num
.number
);
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
);
176 printf("Mutex:Level %d\n", obj
->mutex
.level
);
179 printf("PowerResource:Level %d Order %d\n",
180 obj
->pres
.level
, obj
->pres
.order
);
183 printf("OprationRegion:Busspace%d, Offset 0x%x Length 0x%x\n",
184 obj
->opregion
.space
, obj
->opregion
.offset
,
185 obj
->opregion
.length
);
188 printf("Fieldelement:flag 0x%x offset 0x%x len 0x%x {",
189 obj
->field
.flags
, obj
->field
.bitoffset
,
191 switch (obj
->field
.f
.ftype
) {
193 aml_print_namestring(obj
->field
.f
.fld
.regname
);
196 aml_print_namestring(obj
->field
.f
.ifld
.indexname
);
198 aml_print_namestring(obj
->field
.f
.ifld
.dataname
);
201 aml_print_namestring(obj
->field
.f
.bfld
.regname
);
203 aml_print_namestring(obj
->field
.f
.bfld
.bankname
);
204 printf("0x%x", obj
->field
.f
.bfld
.bankvalue
);
210 printf("Method: Arg %d From %p To %p\n", obj
->meth
.argnum
,
211 obj
->meth
.from
, obj
->meth
.to
);
214 printf("Buffer: size:0x%x Data %p\n", obj
->buffer
.size
,
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
);
225 printf("String:%s\n", obj
->str
.string
);
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
) {
233 if (obj
->package
.objects
[i
]->type
< 0) {
237 aml_showobject(obj
->package
.objects
[i
]);
241 printf("Thermalzone\n");
246 case aml_t_ddbhandle
:
247 printf("DDBHANDLE\n");
250 if (obj
->objref
.alias
== 1) {
253 printf("Object reference");
254 if (obj
->objref
.offset
>= 0) {
255 printf(" (offset 0x%x)", obj
->objref
.offset
);
259 aml_showobject(obj
->objref
.ref
);
262 printf("UNK ID=%d\n", obj
->type
);
269 aml_showtree(struct aml_name
* aname
, int lev
)
272 struct aml_name
*ptr
;
275 for (i
= 0; i
< lev
; i
++) {
278 strncpy(name
, aname
->name
, 4);
281 if (aname
->property
!= NULL
) {
282 aml_showobject(aname
->property
);
286 for (ptr
= aname
->child
; ptr
; ptr
= ptr
->brother
)
287 aml_showtree(ptr
, lev
+ 1);
291 * Common Region I/O Stuff
294 static __inline u_int64_t
295 aml_adjust_bitmask(u_int32_t flags
, u_int32_t bitlen
)
299 switch (AML_FIELDFLAGS_ACCESSTYPE(flags
)) {
300 case AML_FIELDFLAGS_ACCESS_ANYACC
:
302 bitmask
= 0x000000ff;
306 bitmask
= 0x0000ffff;
309 bitmask
= 0xffffffff;
311 case AML_FIELDFLAGS_ACCESS_BYTEACC
:
312 bitmask
= 0x000000ff;
314 case AML_FIELDFLAGS_ACCESS_WORDACC
:
315 bitmask
= 0x0000ffff;
317 case AML_FIELDFLAGS_ACCESS_DWORDACC
:
319 bitmask
= 0xffffffff;
325 bitmask
|= 0x0000ffff;
328 bitmask
|= 0xffffffff;
336 aml_adjust_readvalue(u_int32_t flags
, u_int32_t bitoffset
, u_int32_t bitlen
,
339 u_int32_t offset
, retval
;
342 offset
= bitoffset
; /* XXX bitoffset may change in this function! */
343 bitmask
= aml_adjust_bitmask(flags
, bitlen
);
344 retval
= (orgval
>> offset
) & (~(bitmask
<< bitlen
)) & bitmask
;
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
)
353 u_int32_t offset
, retval
;
356 offset
= bitoffset
; /* XXX bitoffset may change in this function! */
357 bitmask
= aml_adjust_bitmask(flags
, bitlen
);
359 switch (AML_FIELDFLAGS_UPDATERULE(flags
)) {
360 case AML_FIELDFLAGS_UPDATE_PRESERVE
:
361 retval
&= (~(((u_int64_t
)1 << bitlen
) - 1) << offset
) |
362 (~(bitmask
<< offset
));
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 */
369 case AML_FIELDFLAGS_UPDATE_WRITEASZEROS
:
373 printf("illegal update rule: %d\n", flags
);
377 retval
|= (value
<< (offset
& bitmask
));
385 #define AML_BUFFER_INPUT 0
386 #define AML_BUFFER_OUTPUT 1
388 static int aml_bufferfield_io(int io
, u_int32_t
*valuep
,
389 u_int8_t
*origin
, u_int32_t bitoffset
,
393 aml_bufferfield_io(int io
, u_int32_t
*valuep
, u_int8_t
*origin
,
394 u_int32_t bitoffset
, u_int32_t bitlen
)
396 u_int8_t val
, tmp
, masklow
, maskhigh
;
397 u_int8_t offsetlow
, offsethigh
;
399 u_int32_t value
, readval
;
400 u_int32_t byteoffset
, bytelen
, i
;
402 masklow
= maskhigh
= 0xff;
406 byteoffset
= bitoffset
/ 8;
407 bytelen
= bitlen
/ 8 + ((bitlen
% 8) ? 1 : 0);
408 addr
= origin
+ byteoffset
;
411 if (bitlen
<= 8 || bitlen
== 16 || bitlen
== 32) {
412 bcopy(addr
, &readval
, bytelen
);
413 AML_DEBUGPRINT("\n\t[bufferfield:0x%x@%p:%d,%d]",
414 readval
, addr
, bitoffset
% 8, bitlen
);
416 case AML_BUFFER_INPUT
:
417 value
= aml_adjust_readvalue(AML_FIELDFLAGS_ACCESS_BYTEACC
,
418 bitoffset
% 8, bitlen
, readval
);
420 AML_DEBUGPRINT("\n[read(bufferfield, %p)&mask:0x%x]\n",
423 case AML_BUFFER_OUTPUT
:
424 value
= aml_adjust_updatevalue(AML_FIELDFLAGS_ACCESS_BYTEACC
,
425 bitoffset
% 8, bitlen
, readval
, value
);
426 bcopy(&value
, addr
, bytelen
);
427 AML_DEBUGPRINT("->[bufferfield:0x%x@%p:%d,%d]",
428 value
, addr
, bitoffset
% 8, bitlen
);
434 offsetlow
= bitoffset
% 8;
436 offsethigh
= (bitlen
- (8 - offsetlow
)) % 8;
442 masklow
= (~((1 << bitlen
) - 1) << offsetlow
) | ~(0xff << offsetlow
);
443 AML_DEBUGPRINT("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n",
444 offsetlow
, masklow
, ~masklow
& 0xff);
447 maskhigh
= 0xff << offsethigh
;
448 AML_DEBUGPRINT("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n",
449 offsethigh
, maskhigh
, ~maskhigh
& 0xff);
451 for (i
= bytelen
; i
> 0; i
--, addr
++) {
454 AML_DEBUGPRINT("\t[bufferfield:0x%02x@%p]", val
, addr
);
457 case AML_BUFFER_INPUT
:
459 /* the lowest byte? */
462 readval
= tmp
& ~masklow
;
467 if (i
== 1 && offsethigh
) {
468 tmp
= tmp
& ~maskhigh
;
470 readval
= (tmp
<< (8 * (bytelen
- i
))) | readval
;
473 AML_DEBUGPRINT("\n");
474 /* goto to next byte... */
478 /* final adjustment before finishing region access */
480 readval
= readval
>> offsetlow
;
482 AML_DEBUGPRINT("[read(bufferfield, %p)&mask:0x%x]\n",
488 case AML_BUFFER_OUTPUT
:
490 /* the lowest byte? */
493 tmp
= (val
& masklow
) | tmp
<< offsetlow
;
495 value
= value
>> (8 - offsetlow
);
497 if (i
== 1 && offsethigh
) {
498 tmp
= (val
& maskhigh
) | tmp
;
503 AML_DEBUGPRINT("->[bufferfield:0x%02x@%p]\n",
513 aml_bufferfield_read(u_int8_t
*origin
, u_int32_t bitoffset
,
519 aml_bufferfield_io(AML_BUFFER_INPUT
, (u_int32_t
*)&value
, origin
,
525 aml_bufferfield_write(u_int32_t value
, u_int8_t
*origin
,
526 u_int32_t bitoffset
, u_int32_t bitlen
)
530 status
= aml_bufferfield_io(AML_BUFFER_OUTPUT
, &value
,
531 origin
, bitoffset
, bitlen
);
536 aml_region_handle_alloc(struct aml_environ
*env
, int regtype
, u_int32_t flags
,
537 u_int32_t baseaddr
, u_int32_t bitoffset
, u_int32_t bitlen
,
538 struct aml_region_handle
*h
)
541 struct aml_name
*pci_info
;
545 bzero(h
, sizeof(struct aml_region_handle
));
548 h
->regtype
= regtype
;
550 h
->baseaddr
= baseaddr
;
551 h
->bitoffset
= bitoffset
;
554 switch (AML_FIELDFLAGS_ACCESSTYPE(flags
)) {
555 case AML_FIELDFLAGS_ACCESS_ANYACC
:
566 case AML_FIELDFLAGS_ACCESS_BYTEACC
:
569 case AML_FIELDFLAGS_ACCESS_WORDACC
:
572 case AML_FIELDFLAGS_ACCESS_DWORDACC
:
580 h
->addr
= baseaddr
+ h
->unit
* ((bitoffset
/ 8) / h
->unit
);
581 h
->bytelen
= baseaddr
+ ((bitoffset
+ bitlen
) / 8) - h
->addr
+
582 ((bitlen
% 8) ? 1 : 0);
585 switch (h
->regtype
) {
586 case AML_REGION_SYSMEM
:
587 OsdMapMemory((void *)h
->addr
, h
->bytelen
, (void **)&h
->vaddr
);
590 case AML_REGION_PCICFG
:
591 /* Obtain PCI bus number */
592 pci_info
= aml_search_name(env
, "_BBN");
593 if (pci_info
== NULL
|| pci_info
->property
->type
!= aml_t_num
) {
594 AML_DEBUGPRINT("Cannot locate _BBN. Using default 0\n");
597 AML_DEBUGPRINT("found _BBN: %d\n",
598 pci_info
->property
->num
.number
);
599 h
->pci_bus
= pci_info
->property
->num
.number
& 0xff;
602 /* Obtain device & function number */
603 pci_info
= aml_search_name(env
, "_ADR");
604 if (pci_info
== NULL
|| pci_info
->property
->type
!= aml_t_num
) {
605 printf("Cannot locate: _ADR\n");
609 h
->pci_devfunc
= pci_info
->property
->num
.number
;
611 AML_DEBUGPRINT("[pci%d.%d]", h
->pci_bus
, h
->pci_devfunc
);
624 aml_region_handle_free(struct aml_region_handle
*h
)
627 switch (h
->regtype
) {
628 case AML_REGION_SYSMEM
:
629 OsdUnMapMemory((void *)h
->vaddr
, h
->bytelen
);
639 aml_region_io_simple(struct aml_environ
*env
, int io
, int regtype
,
640 u_int32_t flags
, u_int32_t
*valuep
, u_int32_t baseaddr
,
641 u_int32_t bitoffset
, u_int32_t bitlen
)
644 u_int32_t readval
, value
, offset
, bytelen
, i
;
645 struct aml_region_handle handle
;
647 state
= aml_region_handle_alloc(env
, regtype
, flags
,
648 baseaddr
, bitoffset
, bitlen
, &handle
);
654 offset
= bitoffset
% (handle
.unit
* 8);
655 /* limitation of 32 bits alignment */
656 bytelen
= (handle
.bytelen
> 4) ? 4 : handle
.bytelen
;
658 if (io
== AML_REGION_INPUT
||
659 AML_FIELDFLAGS_UPDATERULE(flags
) == AML_FIELDFLAGS_UPDATE_PRESERVE
) {
660 for (i
= 0; i
< bytelen
; i
+= handle
.unit
) {
661 state
= aml_region_read_simple(&handle
, i
, &value
);
665 readval
|= (value
<< (i
* 8));
667 AML_DEBUGPRINT("\t[%d:0x%x@0x%lx:%d,%d]",
668 regtype
, readval
, handle
.addr
, offset
, bitlen
);
672 case AML_REGION_INPUT
:
673 AML_DEBUGPRINT("\n");
674 readval
= aml_adjust_readvalue(flags
, offset
, bitlen
, readval
);
676 value
= aml_region_prompt_read(&handle
, value
);
677 state
= aml_region_prompt_update_value(readval
, value
, &handle
);
684 case AML_REGION_OUTPUT
:
686 value
= aml_adjust_updatevalue(flags
, offset
,
687 bitlen
, readval
, value
);
688 value
= aml_region_prompt_write(&handle
, value
);
689 AML_DEBUGPRINT("\t->[%d:0x%x@0x%lx:%d,%d]\n", regtype
, value
,
690 handle
.addr
, offset
, bitlen
);
691 for (i
= 0; i
< bytelen
; i
+= handle
.unit
) {
692 state
= aml_region_write_simple(&handle
, i
, value
);
696 value
= value
>> (handle
.unit
* 8);
701 aml_region_handle_free(&handle
);
707 aml_region_io(struct aml_environ
*env
, int io
, int regtype
,
708 u_int32_t flags
, u_int32_t
*valuep
, u_int32_t baseaddr
,
709 u_int32_t bitoffset
, u_int32_t bitlen
)
711 u_int32_t unit
, offset
;
712 u_int32_t offadj
, bitadj
;
713 u_int32_t value
, readval
, i
;
718 unit
= 4; /* limitation of 32 bits alignment */
719 offset
= bitoffset
% (unit
* 8);
722 if (offset
+ bitlen
> unit
* 8) {
723 bitadj
= bitlen
- (unit
* 8 - offset
);
725 for (i
= 0; i
< offset
+ bitlen
; i
+= unit
* 8) {
726 value
= (*valuep
) >> offadj
;
727 state
= aml_region_io_simple(env
, io
, regtype
, flags
,
728 &value
, baseaddr
, bitoffset
+ offadj
, bitlen
- bitadj
);
732 readval
|= value
<< offadj
;
733 bitadj
= offadj
= bitlen
- bitadj
;