1 /* $NetBSD: acpi_ec.c,v 1.57 2009/09/16 10:47:54 mlelstv Exp $ */
4 * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
7 * Redistribution and use in source and binary forms, with or without
8 * 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
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * The ACPI Embedded Controller (EC) driver serves two different purposes:
34 * - read and write access from ASL, e.g. to read battery state
35 * - notification of ASL of System Control Interrupts.
37 * Access to the EC is serialised by sc_access_mtx and optionally the
38 * ACPI global mutex. Both locks are held until the request is fulfilled.
39 * All access to the softc has to hold sc_mtx to serialise against the GPE
40 * handler and the callout. sc_mtx is also used for wakeup conditions.
42 * SCIs are processed in a kernel thread. Handling gets a bit complicated
43 * by the lock order (sc_mtx must be acquired after sc_access_mtx and the
46 * Read and write requests spin around for a short time as many requests
47 * can be handled instantly by the EC. During normal processing interrupt
48 * mode is used exclusively. At boot and resume time interrupts are not
49 * working and the handlers just busy loop.
51 * A callout is scheduled to compensate for missing interrupts on some
52 * hardware. If the EC doesn't process a request for 5s, it is most likely
53 * in a wedged state. No method to reset the EC is currently known.
55 * Special care has to be taken to not poll the EC in a busy loop without
56 * delay. This can prevent processing of Power Button events. At least some
57 * Lenovo Thinkpads seem to be implement the Power Button Override in the EC
58 * and the only option to recover on those models is to cut off all power.
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.57 2009/09/16 10:47:54 mlelstv Exp $");
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/condvar.h>
67 #include <sys/device.h>
68 #include <sys/kernel.h>
69 #include <sys/kthread.h>
70 #include <sys/mutex.h>
74 #include <dev/acpi/acpireg.h>
75 #include <dev/acpi/acpivar.h>
76 #include <dev/acpi/acpi_ecvar.h>
78 #define _COMPONENT ACPI_EC_COMPONENT
79 ACPI_MODULE_NAME ("acpi_ec")
81 /* Maximum time to wait for global ACPI lock in ms */
82 #define EC_LOCK_TIMEOUT 5
84 /* Maximum time to poll for completion of a command in ms */
85 #define EC_POLL_TIMEOUT 5
87 /* Maximum time to give a single EC command in s */
88 #define EC_CMD_TIMEOUT 10
90 /* From ACPI 3.0b, chapter 12.3 */
91 #define EC_COMMAND_READ 0x80
92 #define EC_COMMAND_WRITE 0x81
93 #define EC_COMMAND_BURST_EN 0x82
94 #define EC_COMMAND_BURST_DIS 0x83
95 #define EC_COMMAND_QUERY 0x84
97 /* From ACPI 3.0b, chapter 12.2.1 */
98 #define EC_STATUS_OBF 0x01
99 #define EC_STATUS_IBF 0x02
100 #define EC_STATUS_CMD 0x08
101 #define EC_STATUS_BURST 0x10
102 #define EC_STATUS_SCI 0x20
103 #define EC_STATUS_SMI 0x40
105 static const char *ec_hid
[] = {
122 struct acpiec_softc
{
128 bus_space_tag_t sc_data_st
;
129 bus_space_handle_t sc_data_sh
;
131 bus_space_tag_t sc_csr_st
;
132 bus_space_handle_t sc_csr_sh
;
134 bool sc_need_global_lock
;
135 UINT32 sc_global_lock
;
137 kmutex_t sc_mtx
, sc_access_mtx
;
138 kcondvar_t sc_cv
, sc_cv_sci
;
139 enum ec_state_t sc_state
;
141 callout_t sc_pseudo_intr
;
143 uint8_t sc_cur_addr
, sc_cur_val
;
146 static int acpiecdt_match(device_t
, cfdata_t
, void *);
147 static void acpiecdt_attach(device_t
, device_t
, void *);
149 static int acpiec_match(device_t
, cfdata_t
, void *);
150 static void acpiec_attach(device_t
, device_t
, void *);
152 static void acpiec_common_attach(device_t
, device_t
, ACPI_HANDLE
,
153 bus_addr_t
, bus_addr_t
, ACPI_HANDLE
, uint8_t);
155 static bool acpiec_suspend(device_t
, pmf_qual_t
);
156 static bool acpiec_resume(device_t
, pmf_qual_t
);
157 static bool acpiec_shutdown(device_t
, int);
159 static bool acpiec_parse_gpe_package(device_t
, ACPI_HANDLE
,
160 ACPI_HANDLE
*, uint8_t *);
162 static void acpiec_callout(void *);
163 static void acpiec_gpe_query(void *);
164 static UINT32
acpiec_gpe_handler(void *);
165 static ACPI_STATUS
acpiec_space_setup(ACPI_HANDLE
, UINT32
, void *, void **);
166 static ACPI_STATUS
acpiec_space_handler(UINT32
, ACPI_PHYSICAL_ADDRESS
,
167 UINT32
, ACPI_INTEGER
*, void *, void *);
169 static void acpiec_gpe_state_machine(device_t
);
171 CFATTACH_DECL_NEW(acpiec
, sizeof(struct acpiec_softc
),
172 acpiec_match
, acpiec_attach
, NULL
, NULL
);
174 CFATTACH_DECL_NEW(acpiecdt
, sizeof(struct acpiec_softc
),
175 acpiecdt_match
, acpiecdt_attach
, NULL
, NULL
);
177 static device_t ec_singleton
= NULL
;
178 static bool acpiec_cold
= false;
181 acpiecdt_find(device_t parent
, ACPI_HANDLE
*ec_handle
,
182 bus_addr_t
*cmd_reg
, bus_addr_t
*data_reg
, uint8_t *gpebit
)
184 ACPI_TABLE_ECDT
*ecdt
;
187 rv
= AcpiGetTable(ACPI_SIG_ECDT
, 1, (ACPI_TABLE_HEADER
**)&ecdt
);
188 if (ACPI_FAILURE(rv
))
191 if (ecdt
->Control
.BitWidth
!= 8 || ecdt
->Data
.BitWidth
!= 8) {
192 aprint_error_dev(parent
,
193 "ECDT register width invalid (%d/%d)\n",
194 ecdt
->Control
.BitWidth
, ecdt
->Data
.BitWidth
);
198 rv
= AcpiGetHandle(ACPI_ROOT_OBJECT
, ecdt
->Id
, ec_handle
);
199 if (ACPI_FAILURE(rv
)) {
200 aprint_error_dev(parent
,
201 "failed to look up EC object %s: %s\n",
202 ecdt
->Id
, AcpiFormatException(rv
));
206 *cmd_reg
= ecdt
->Control
.Address
;
207 *data_reg
= ecdt
->Data
.Address
;
214 acpiecdt_match(device_t parent
, cfdata_t match
, void *aux
)
216 ACPI_HANDLE ec_handle
;
217 bus_addr_t cmd_reg
, data_reg
;
220 if (acpiecdt_find(parent
, &ec_handle
, &cmd_reg
, &data_reg
, &gpebit
))
227 acpiecdt_attach(device_t parent
, device_t self
, void *aux
)
229 ACPI_HANDLE ec_handle
;
230 bus_addr_t cmd_reg
, data_reg
;
233 if (!acpiecdt_find(parent
, &ec_handle
, &cmd_reg
, &data_reg
, &gpebit
))
234 panic("ECDT disappeared");
237 aprint_normal(": ACPI Embedded Controller via ECDT\n");
239 acpiec_common_attach(parent
, self
, ec_handle
, cmd_reg
, data_reg
,
244 acpiec_match(device_t parent
, cfdata_t match
, void *aux
)
246 struct acpi_attach_args
*aa
= aux
;
248 if (aa
->aa_node
->ad_type
!= ACPI_TYPE_DEVICE
)
251 return acpi_match_hid(aa
->aa_node
->ad_devinfo
, ec_hid
);
255 acpiec_attach(device_t parent
, device_t self
, void *aux
)
257 struct acpi_attach_args
*aa
= aux
;
258 struct acpi_resources ec_res
;
259 struct acpi_io
*io0
, *io1
;
260 ACPI_HANDLE gpe_handle
;
264 if (ec_singleton
!= NULL
) {
265 aprint_naive(": using %s\n", device_xname(ec_singleton
));
266 aprint_normal(": using %s\n", device_xname(ec_singleton
));
267 if (!pmf_device_register(self
, NULL
, NULL
))
268 aprint_error_dev(self
, "couldn't establish power handler\n");
272 if (!acpiec_parse_gpe_package(self
, aa
->aa_node
->ad_handle
,
273 &gpe_handle
, &gpebit
))
276 rv
= acpi_resource_parse(self
, aa
->aa_node
->ad_handle
, "_CRS",
277 &ec_res
, &acpi_resource_parse_ops_default
);
279 aprint_error_dev(self
, "resource parsing failed: %s\n",
280 AcpiFormatException(rv
));
284 if ((io0
= acpi_res_io(&ec_res
, 0)) == NULL
) {
285 aprint_error_dev(self
, "no data register resource\n");
288 if ((io1
= acpi_res_io(&ec_res
, 1)) == NULL
) {
289 aprint_error_dev(self
, "no CSR register resource\n");
293 acpiec_common_attach(parent
, self
, aa
->aa_node
->ad_handle
,
294 io1
->ar_base
, io0
->ar_base
, gpe_handle
, gpebit
);
297 acpi_resource_cleanup(&ec_res
);
301 acpiec_common_attach(device_t parent
, device_t self
,
302 ACPI_HANDLE ec_handle
, bus_addr_t cmd_reg
, bus_addr_t data_reg
,
303 ACPI_HANDLE gpe_handle
, uint8_t gpebit
)
305 struct acpiec_softc
*sc
= device_private(self
);
309 sc
->sc_ech
= ec_handle
;
310 sc
->sc_gpeh
= gpe_handle
;
311 sc
->sc_gpebit
= gpebit
;
313 sc
->sc_state
= EC_STATE_FREE
;
314 mutex_init(&sc
->sc_mtx
, MUTEX_DRIVER
, IPL_TTY
);
315 mutex_init(&sc
->sc_access_mtx
, MUTEX_DEFAULT
, IPL_NONE
);
316 cv_init(&sc
->sc_cv
, "eccv");
317 cv_init(&sc
->sc_cv_sci
, "ecsci");
319 if (bus_space_map(sc
->sc_data_st
, data_reg
, 1, 0,
320 &sc
->sc_data_sh
) != 0) {
321 aprint_error_dev(self
, "unable to map data register\n");
325 if (bus_space_map(sc
->sc_csr_st
, cmd_reg
, 1, 0, &sc
->sc_csr_sh
) != 0) {
326 aprint_error_dev(self
, "unable to map CSR register\n");
330 rv
= acpi_eval_integer(sc
->sc_ech
, "_GLK", &val
);
332 sc
->sc_need_global_lock
= val
!= 0;
333 } else if (rv
!= AE_NOT_FOUND
) {
334 aprint_error_dev(self
, "unable to evaluate _GLK: %s\n",
335 AcpiFormatException(rv
));
338 sc
->sc_need_global_lock
= false;
340 if (sc
->sc_need_global_lock
)
341 aprint_normal_dev(self
, "using global ACPI lock\n");
343 callout_init(&sc
->sc_pseudo_intr
, CALLOUT_MPSAFE
);
344 callout_setfunc(&sc
->sc_pseudo_intr
, acpiec_callout
, self
);
346 rv
= AcpiInstallAddressSpaceHandler(sc
->sc_ech
, ACPI_ADR_SPACE_EC
,
347 acpiec_space_handler
, acpiec_space_setup
, self
);
349 aprint_error_dev(self
,
350 "unable to install address space handler: %s\n",
351 AcpiFormatException(rv
));
355 rv
= AcpiInstallGpeHandler(sc
->sc_gpeh
, sc
->sc_gpebit
,
356 ACPI_GPE_EDGE_TRIGGERED
, acpiec_gpe_handler
, self
);
358 aprint_error_dev(self
, "unable to install GPE handler: %s\n",
359 AcpiFormatException(rv
));
363 rv
= AcpiSetGpeType(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_GPE_TYPE_RUNTIME
);
365 aprint_error_dev(self
, "unable to set GPE type: %s\n",
366 AcpiFormatException(rv
));
370 rv
= AcpiEnableGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_ISR
);
372 aprint_error_dev(self
, "unable to enable GPE: %s\n",
373 AcpiFormatException(rv
));
377 if (kthread_create(PRI_NONE
, KTHREAD_MPSAFE
, NULL
, acpiec_gpe_query
,
378 self
, NULL
, "acpiec sci thread")) {
379 aprint_error_dev(self
, "unable to create query kthread\n");
385 if (!pmf_device_register1(self
, acpiec_suspend
, acpiec_resume
,
387 aprint_error_dev(self
, "couldn't establish power handler\n");
392 (void)AcpiRemoveGpeHandler(sc
->sc_gpeh
, sc
->sc_gpebit
,
394 (void)AcpiRemoveAddressSpaceHandler(sc
->sc_ech
,
395 ACPI_ADR_SPACE_EC
, acpiec_space_handler
);
396 bus_space_unmap(sc
->sc_csr_st
, sc
->sc_csr_sh
, 1);
398 bus_space_unmap(sc
->sc_data_st
, sc
->sc_data_sh
, 1);
402 acpiec_suspend(device_t dv
, pmf_qual_t qual
)
410 acpiec_resume(device_t dv
, pmf_qual_t qual
)
418 acpiec_shutdown(device_t dv
, int how
)
426 acpiec_parse_gpe_package(device_t self
, ACPI_HANDLE ec_handle
,
427 ACPI_HANDLE
*gpe_handle
, uint8_t *gpebit
)
433 rv
= acpi_eval_struct(ec_handle
, "_GPE", &buf
);
435 aprint_error_dev(self
, "unable to evaluate _GPE: %s\n",
436 AcpiFormatException(rv
));
442 if (p
->Type
== ACPI_TYPE_INTEGER
) {
444 *gpebit
= p
->Integer
.Value
;
449 if (p
->Type
!= ACPI_TYPE_PACKAGE
) {
450 aprint_error_dev(self
, "_GPE is neither integer nor package\n");
455 if (p
->Package
.Count
!= 2) {
456 aprint_error_dev(self
, "_GPE package does not contain 2 elements\n");
461 c
= &p
->Package
.Elements
[0];
463 case ACPI_TYPE_LOCAL_REFERENCE
:
465 *gpe_handle
= c
->Reference
.Handle
;
467 case ACPI_TYPE_STRING
:
468 /* XXX should be using real scope here */
469 rv
= AcpiGetHandle(NULL
, p
->String
.Pointer
, gpe_handle
);
471 aprint_error_dev(self
,
472 "_GPE device reference unresolvable\n");
478 aprint_error_dev(self
, "_GPE device reference incorrect\n");
482 c
= &p
->Package
.Elements
[1];
483 if (c
->Type
!= ACPI_TYPE_INTEGER
) {
484 aprint_error_dev(self
,
485 "_GPE package needs integer as 2nd field\n");
489 *gpebit
= c
->Integer
.Value
;
495 acpiec_read_data(struct acpiec_softc
*sc
)
497 return bus_space_read_1(sc
->sc_data_st
, sc
->sc_data_sh
, 0);
501 acpiec_write_data(struct acpiec_softc
*sc
, uint8_t val
)
503 bus_space_write_1(sc
->sc_data_st
, sc
->sc_data_sh
, 0, val
);
507 acpiec_read_status(struct acpiec_softc
*sc
)
509 return bus_space_read_1(sc
->sc_csr_st
, sc
->sc_csr_sh
, 0);
513 acpiec_write_command(struct acpiec_softc
*sc
, uint8_t cmd
)
515 bus_space_write_1(sc
->sc_csr_st
, sc
->sc_csr_sh
, 0, cmd
);
519 acpiec_space_setup(ACPI_HANDLE region
, UINT32 func
, void *arg
,
522 if (func
== ACPI_REGION_DEACTIVATE
)
531 acpiec_lock(device_t dv
)
533 struct acpiec_softc
*sc
= device_private(dv
);
536 mutex_enter(&sc
->sc_access_mtx
);
538 if (sc
->sc_need_global_lock
) {
539 rv
= AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT
, &sc
->sc_global_lock
);
541 aprint_error_dev(dv
, "failed to acquire global lock: %s\n",
542 AcpiFormatException(rv
));
549 acpiec_unlock(device_t dv
)
551 struct acpiec_softc
*sc
= device_private(dv
);
554 if (sc
->sc_need_global_lock
) {
555 rv
= AcpiReleaseGlobalLock(sc
->sc_global_lock
);
557 aprint_error_dev(dv
, "failed to release global lock: %s\n",
558 AcpiFormatException(rv
));
561 mutex_exit(&sc
->sc_access_mtx
);
565 acpiec_read(device_t dv
, uint8_t addr
, uint8_t *val
)
567 struct acpiec_softc
*sc
= device_private(dv
);
568 int i
, timeo
= 1000 * EC_CMD_TIMEOUT
;
571 mutex_enter(&sc
->sc_mtx
);
573 sc
->sc_cur_addr
= addr
;
574 sc
->sc_state
= EC_STATE_READ
;
576 for (i
= 0; i
< EC_POLL_TIMEOUT
; ++i
) {
577 acpiec_gpe_state_machine(dv
);
578 if (sc
->sc_state
== EC_STATE_FREE
)
583 if (cold
|| acpiec_cold
) {
584 while (sc
->sc_state
!= EC_STATE_FREE
&& timeo
-- > 0) {
586 acpiec_gpe_state_machine(dv
);
588 if (sc
->sc_state
!= EC_STATE_FREE
) {
589 mutex_exit(&sc
->sc_mtx
);
590 AcpiClearGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_NOT_ISR
);
592 aprint_error_dev(dv
, "command timed out, state %d\n",
596 } else if (cv_timedwait(&sc
->sc_cv
, &sc
->sc_mtx
, EC_CMD_TIMEOUT
* hz
)) {
597 mutex_exit(&sc
->sc_mtx
);
598 AcpiClearGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_NOT_ISR
);
600 aprint_error_dev(dv
, "command takes over %d sec...\n", EC_CMD_TIMEOUT
);
605 *val
= sc
->sc_cur_val
;
607 mutex_exit(&sc
->sc_mtx
);
613 acpiec_write(device_t dv
, uint8_t addr
, uint8_t val
)
615 struct acpiec_softc
*sc
= device_private(dv
);
616 int i
, timeo
= 1000 * EC_CMD_TIMEOUT
;
619 mutex_enter(&sc
->sc_mtx
);
621 sc
->sc_cur_addr
= addr
;
622 sc
->sc_cur_val
= val
;
623 sc
->sc_state
= EC_STATE_WRITE
;
625 for (i
= 0; i
< EC_POLL_TIMEOUT
; ++i
) {
626 acpiec_gpe_state_machine(dv
);
627 if (sc
->sc_state
== EC_STATE_FREE
)
632 if (cold
|| acpiec_cold
) {
633 while (sc
->sc_state
!= EC_STATE_FREE
&& timeo
-- > 0) {
635 acpiec_gpe_state_machine(dv
);
637 if (sc
->sc_state
!= EC_STATE_FREE
) {
638 mutex_exit(&sc
->sc_mtx
);
639 AcpiClearGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_NOT_ISR
);
641 aprint_error_dev(dv
, "command timed out, state %d\n",
645 } else if (cv_timedwait(&sc
->sc_cv
, &sc
->sc_mtx
, EC_CMD_TIMEOUT
* hz
)) {
646 mutex_exit(&sc
->sc_mtx
);
647 AcpiClearGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_NOT_ISR
);
649 aprint_error_dev(dv
, "command takes over %d sec...\n", EC_CMD_TIMEOUT
);
654 mutex_exit(&sc
->sc_mtx
);
660 acpiec_space_handler(UINT32 func
, ACPI_PHYSICAL_ADDRESS paddr
,
661 UINT32 width
, ACPI_INTEGER
*value
, void *arg
, void *region_arg
)
664 struct acpiec_softc
*sc
;
669 if (paddr
> 0xff || width
% 8 != 0 || value
== NULL
|| arg
== NULL
||
670 paddr
+ width
/ 8 > 0xff)
671 return AE_BAD_PARAMETER
;
675 sc
= device_private(dv
);
682 for (i
= 0; i
< width
; i
+= 8, ++addr
) {
683 rv
= acpiec_read(dv
, addr
, ®
);
686 *value
|= (ACPI_INTEGER
)reg
<< i
;
690 for (i
= 0; i
< width
; i
+= 8, ++addr
) {
691 reg
= (*value
>>i
) & 0xff;
692 rv
= acpiec_write(dv
, addr
, reg
);
698 aprint_error("%s: invalid Address Space function called: %x\n",
699 device_xname(dv
), (unsigned int)func
);
700 return AE_BAD_PARAMETER
;
707 acpiec_gpe_query(void *arg
)
710 struct acpiec_softc
*sc
= device_private(dv
);
717 mutex_enter(&sc
->sc_mtx
);
719 if (sc
->sc_got_sci
== false)
720 cv_wait(&sc
->sc_cv_sci
, &sc
->sc_mtx
);
721 mutex_exit(&sc
->sc_mtx
);
724 mutex_enter(&sc
->sc_mtx
);
726 /* The Query command can always be issued, so be defensive here. */
727 sc
->sc_got_sci
= false;
728 sc
->sc_state
= EC_STATE_QUERY
;
730 for (i
= 0; i
< EC_POLL_TIMEOUT
; ++i
) {
731 acpiec_gpe_state_machine(dv
);
732 if (sc
->sc_state
== EC_STATE_FREE
)
737 cv_wait(&sc
->sc_cv
, &sc
->sc_mtx
);
740 reg
= sc
->sc_cur_val
;
742 mutex_exit(&sc
->sc_mtx
);
746 goto loop
; /* Spurious query result */
749 * Evaluate _Qxx to respond to the controller.
751 snprintf(qxx
, sizeof(qxx
), "_Q%02X", (unsigned int)reg
);
752 rv
= AcpiEvaluateObject(sc
->sc_ech
, qxx
, NULL
, NULL
);
753 if (rv
!= AE_OK
&& rv
!= AE_NOT_FOUND
) {
754 aprint_error("%s: GPE query method %s failed: %s",
755 device_xname(dv
), qxx
, AcpiFormatException(rv
));
762 acpiec_gpe_state_machine(device_t dv
)
764 struct acpiec_softc
*sc
= device_private(dv
);
767 reg
= acpiec_read_status(sc
);
769 if (reg
& EC_STATUS_SCI
)
770 sc
->sc_got_sci
= true;
772 switch (sc
->sc_state
) {
774 if ((reg
& EC_STATUS_IBF
) != 0)
775 break; /* Nothing of interest here. */
776 acpiec_write_command(sc
, EC_COMMAND_QUERY
);
777 sc
->sc_state
= EC_STATE_QUERY_VAL
;
780 case EC_STATE_QUERY_VAL
:
781 if ((reg
& EC_STATUS_OBF
) == 0)
782 break; /* Nothing of interest here. */
784 sc
->sc_cur_val
= acpiec_read_data(sc
);
785 sc
->sc_state
= EC_STATE_FREE
;
787 cv_signal(&sc
->sc_cv
);
791 if ((reg
& EC_STATUS_IBF
) != 0)
792 break; /* Nothing of interest here. */
794 acpiec_write_command(sc
, EC_COMMAND_READ
);
795 sc
->sc_state
= EC_STATE_READ_ADDR
;
798 case EC_STATE_READ_ADDR
:
799 if ((reg
& EC_STATUS_IBF
) != 0)
800 break; /* Nothing of interest here. */
802 acpiec_write_data(sc
, sc
->sc_cur_addr
);
803 sc
->sc_state
= EC_STATE_READ_VAL
;
806 case EC_STATE_READ_VAL
:
807 if ((reg
& EC_STATUS_OBF
) == 0)
808 break; /* Nothing of interest here. */
809 sc
->sc_cur_val
= acpiec_read_data(sc
);
810 sc
->sc_state
= EC_STATE_FREE
;
812 cv_signal(&sc
->sc_cv
);
816 if ((reg
& EC_STATUS_IBF
) != 0)
817 break; /* Nothing of interest here. */
819 acpiec_write_command(sc
, EC_COMMAND_WRITE
);
820 sc
->sc_state
= EC_STATE_WRITE_ADDR
;
823 case EC_STATE_WRITE_ADDR
:
824 if ((reg
& EC_STATUS_IBF
) != 0)
825 break; /* Nothing of interest here. */
826 acpiec_write_data(sc
, sc
->sc_cur_addr
);
827 sc
->sc_state
= EC_STATE_WRITE_VAL
;
830 case EC_STATE_WRITE_VAL
:
831 if ((reg
& EC_STATUS_IBF
) != 0)
832 break; /* Nothing of interest here. */
833 sc
->sc_state
= EC_STATE_FREE
;
834 cv_signal(&sc
->sc_cv
);
836 acpiec_write_data(sc
, sc
->sc_cur_val
);
841 cv_signal(&sc
->sc_cv_sci
);
844 panic("invalid state");
847 if (sc
->sc_state
!= EC_STATE_FREE
)
848 callout_schedule(&sc
->sc_pseudo_intr
, 1);
852 acpiec_callout(void *arg
)
855 struct acpiec_softc
*sc
= device_private(dv
);
857 AcpiClearGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_NOT_ISR
);
859 mutex_enter(&sc
->sc_mtx
);
860 acpiec_gpe_state_machine(dv
);
861 mutex_exit(&sc
->sc_mtx
);
865 acpiec_gpe_handler(void *arg
)
868 struct acpiec_softc
*sc
= device_private(dv
);
870 AcpiClearGpe(sc
->sc_gpeh
, sc
->sc_gpebit
, ACPI_ISR
);
872 mutex_enter(&sc
->sc_mtx
);
873 acpiec_gpe_state_machine(dv
);
874 mutex_exit(&sc
->sc_mtx
);
880 acpiec_bus_read(device_t dv
, u_int addr
, ACPI_INTEGER
*val
, int width
)
882 return acpiec_space_handler(ACPI_READ
, addr
, width
* 8, val
, dv
, NULL
);
886 acpiec_bus_write(device_t dv
, u_int addr
, ACPI_INTEGER val
, int width
)
888 return acpiec_space_handler(ACPI_WRITE
, addr
, width
* 8, &val
, dv
, NULL
);
892 acpiec_get_handle(device_t dv
)
894 struct acpiec_softc
*sc
= device_private(dv
);