xref: /dragonfly/sys/dev/acpica/acpi_ec.c (revision 2d8a3be7)
1 /*-
2  * Copyright (c) 2000 Michael Smith
3  * Copyright (c) 2000 BSDi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *	$FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.38.2.1 2003/08/22 20:49:20 jhb Exp $
28  *      $DragonFly: src/sys/dev/acpica/Attic/acpi_ec.c,v 1.1 2003/09/24 03:32:16 drhodus Exp $
29  */
30 /******************************************************************************
31  *
32  * 1. Copyright Notice
33  *
34  * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
35  * reserved.
36  *
37  * 2. License
38  *
39  * 2.1. This is your license from Intel Corp. under its intellectual property
40  * rights.  You may have additional license terms from the party that provided
41  * you this software, covering your right to use that party's intellectual
42  * property rights.
43  *
44  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
45  * copy of the source code appearing in this file ("Covered Code") an
46  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
47  * base code distributed originally by Intel ("Original Intel Code") to copy,
48  * make derivatives, distribute, use and display any portion of the Covered
49  * Code in any form, with the right to sublicense such rights; and
50  *
51  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
52  * license (with the right to sublicense), under only those claims of Intel
53  * patents that are infringed by the Original Intel Code, to make, use, sell,
54  * offer to sell, and import the Covered Code and derivative works thereof
55  * solely to the minimum extent necessary to exercise the above copyright
56  * license, and in no event shall the patent license extend to any additions
57  * to or modifications of the Original Intel Code.  No other license or right
58  * is granted directly or by implication, estoppel or otherwise;
59  *
60  * The above copyright and patent license is granted only if the following
61  * conditions are met:
62  *
63  * 3. Conditions
64  *
65  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
66  * Redistribution of source code of any substantial portion of the Covered
67  * Code or modification with rights to further distribute source must include
68  * the above Copyright Notice, the above License, this list of Conditions,
69  * and the following Disclaimer and Export Compliance provision.  In addition,
70  * Licensee must cause all Covered Code to which Licensee contributes to
71  * contain a file documenting the changes Licensee made to create that Covered
72  * Code and the date of any change.  Licensee must include in that file the
73  * documentation of any changes made by any predecessor Licensee.  Licensee
74  * must include a prominent statement that the modification is derived,
75  * directly or indirectly, from Original Intel Code.
76  *
77  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
78  * Redistribution of source code of any substantial portion of the Covered
79  * Code or modification without rights to further distribute source must
80  * include the following Disclaimer and Export Compliance provision in the
81  * documentation and/or other materials provided with distribution.  In
82  * addition, Licensee may not authorize further sublicense of source of any
83  * portion of the Covered Code, and must include terms to the effect that the
84  * license from Licensee to its licensee is limited to the intellectual
85  * property embodied in the software Licensee provides to its licensee, and
86  * not to intellectual property embodied in modifications its licensee may
87  * make.
88  *
89  * 3.3. Redistribution of Executable. Redistribution in executable form of any
90  * substantial portion of the Covered Code or modification must reproduce the
91  * above Copyright Notice, and the following Disclaimer and Export Compliance
92  * provision in the documentation and/or other materials provided with the
93  * distribution.
94  *
95  * 3.4. Intel retains all right, title, and interest in and to the Original
96  * Intel Code.
97  *
98  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
99  * Intel shall be used in advertising or otherwise to promote the sale, use or
100  * other dealings in products derived from or relating to the Covered Code
101  * without prior written authorization from Intel.
102  *
103  * 4. Disclaimer and Export Compliance
104  *
105  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
106  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
107  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
108  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
109  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
110  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
111  * PARTICULAR PURPOSE.
112  *
113  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
114  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
115  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
116  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
117  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
118  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
119  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
120  * LIMITED REMEDY.
121  *
122  * 4.3. Licensee shall not export, either directly or indirectly, any of this
123  * software or system incorporating such software without first obtaining any
124  * required license or other approval from the U. S. Department of Commerce or
125  * any other agency or department of the United States Government.  In the
126  * event Licensee exports any such software from the United States or
127  * re-exports any such software from a foreign destination, Licensee shall
128  * ensure that the distribution and export/re-export of the software is in
129  * compliance with all laws, regulations, orders, or other restrictions of the
130  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
131  * any of its subsidiaries will export/re-export any technical data, process,
132  * software, or service, directly or indirectly, to any country for which the
133  * United States government or any agency thereof requires an export license,
134  * other governmental approval, or letter of assurance, without first obtaining
135  * such license, approval or letter.
136  *
137  *****************************************************************************/
138 
139 #include "opt_acpi.h"
140 #include <sys/param.h>
141 #include <sys/kernel.h>
142 #include <sys/bus.h>
143 
144 #include <machine/bus.h>
145 #include <machine/resource.h>
146 #include <sys/rman.h>
147 
148 #include "acpi.h"
149 
150 #include <dev/acpica/acpivar.h>
151 
152 /*
153  * Hooks for the ACPI CA debugging infrastructure
154  */
155 #define _COMPONENT	ACPI_EC
156 ACPI_MODULE_NAME("EC")
157 
158 /*
159  * EC_COMMAND:
160  * -----------
161  */
162 typedef UINT8				EC_COMMAND;
163 
164 #define EC_COMMAND_UNKNOWN		((EC_COMMAND) 0x00)
165 #define EC_COMMAND_READ			((EC_COMMAND) 0x80)
166 #define EC_COMMAND_WRITE		((EC_COMMAND) 0x81)
167 #define EC_COMMAND_BURST_ENABLE		((EC_COMMAND) 0x82)
168 #define EC_COMMAND_BURST_DISABLE	((EC_COMMAND) 0x83)
169 #define EC_COMMAND_QUERY		((EC_COMMAND) 0x84)
170 
171 /*
172  * EC_STATUS:
173  * ----------
174  * The encoding of the EC status register is illustrated below.
175  * Note that a set bit (1) indicates the property is TRUE
176  * (e.g. if bit 0 is set then the output buffer is full).
177  * +-+-+-+-+-+-+-+-+
178  * |7|6|5|4|3|2|1|0|
179  * +-+-+-+-+-+-+-+-+
180  *  | | | | | | | |
181  *  | | | | | | | +- Output Buffer Full?
182  *  | | | | | | +--- Input Buffer Full?
183  *  | | | | | +----- <reserved>
184  *  | | | | +------- Data Register is Command Byte?
185  *  | | | +--------- Burst Mode Enabled?
186  *  | | +----------- SCI Event?
187  *  | +------------- SMI Event?
188  *  +--------------- <Reserved>
189  *
190  */
191 typedef UINT8				EC_STATUS;
192 
193 #define EC_FLAG_OUTPUT_BUFFER		((EC_STATUS) 0x01)
194 #define EC_FLAG_INPUT_BUFFER		((EC_STATUS) 0x02)
195 #define EC_FLAG_BURST_MODE		((EC_STATUS) 0x10)
196 #define EC_FLAG_SCI			((EC_STATUS) 0x20)
197 
198 /*
199  * EC_EVENT:
200  * ---------
201  */
202 typedef UINT8				EC_EVENT;
203 
204 #define EC_EVENT_UNKNOWN		((EC_EVENT) 0x00)
205 #define EC_EVENT_OUTPUT_BUFFER_FULL	((EC_EVENT) 0x01)
206 #define EC_EVENT_INPUT_BUFFER_EMPTY	((EC_EVENT) 0x02)
207 #define EC_EVENT_SCI			((EC_EVENT) 0x20)
208 
209 /*
210  * Register access primitives
211  */
212 #define EC_GET_DATA(sc)							\
213 	bus_space_read_1((sc)->ec_data_tag, (sc)->ec_data_handle, 0)
214 
215 #define EC_SET_DATA(sc, v)						\
216 	bus_space_write_1((sc)->ec_data_tag, (sc)->ec_data_handle, 0, (v))
217 
218 #define EC_GET_CSR(sc)							\
219 	bus_space_read_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0)
220 
221 #define EC_SET_CSR(sc, v)						\
222 	bus_space_write_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0, (v))
223 
224 /*
225  * Driver softc.
226  */
227 struct acpi_ec_softc {
228     device_t		ec_dev;
229     ACPI_HANDLE		ec_handle;
230     UINT32		ec_gpebit;
231 
232     int			ec_data_rid;
233     struct resource	*ec_data_res;
234     bus_space_tag_t	ec_data_tag;
235     bus_space_handle_t	ec_data_handle;
236 
237     int			ec_csr_rid;
238     struct resource	*ec_csr_res;
239     bus_space_tag_t	ec_csr_tag;
240     bus_space_handle_t	ec_csr_handle;
241 
242     int			ec_locked;
243     int			ec_lockhandle;
244     int			ec_pendquery;
245     int			ec_csrvalue;
246 };
247 
248 static int		acpi_ec_event_driven = 0;
249 TUNABLE_INT("hw.acpi.ec.event_driven", &acpi_ec_event_driven);
250 
251 #define EC_LOCK_TIMEOUT	1000	/* 1ms */
252 
253 static __inline ACPI_STATUS
254 EcLock(struct acpi_ec_softc *sc)
255 {
256     ACPI_STATUS	status;
257 
258     /* XXX ACPI_WAIT_FOREVER is probably a bad idea, what is a better time? */
259     status = AcpiAcquireGlobalLock(ACPI_WAIT_FOREVER, &sc->ec_lockhandle);
260     if (ACPI_SUCCESS(status))
261 	sc->ec_locked = 1;
262 
263     return (status);
264 }
265 
266 static __inline void
267 EcUnlock(struct acpi_ec_softc *sc)
268 {
269     sc->ec_locked = 0;
270     AcpiReleaseGlobalLock(sc->ec_lockhandle);
271 }
272 
273 static __inline int
274 EcIsLocked(struct acpi_ec_softc *sc)
275 {
276     return (sc->ec_locked != 0);
277 }
278 
279 typedef struct
280 {
281     EC_COMMAND		Command;
282     UINT8		Address;
283     UINT8		Data;
284 } EC_REQUEST;
285 
286 static void		EcGpeHandler(void *Context);
287 static ACPI_STATUS	EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
288 				void *Context, void **return_Context);
289 static ACPI_STATUS	EcSpaceHandler(UINT32 Function,
290 				ACPI_PHYSICAL_ADDRESS Address,
291 				UINT32 width, ACPI_INTEGER *Value,
292 				void *Context, void *RegionContext);
293 static ACPI_STATUS	EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
294 static ACPI_STATUS	EcQuery(struct acpi_ec_softc *sc, UINT8 *Data);
295 static ACPI_STATUS	EcTransaction(struct acpi_ec_softc *sc,
296 				EC_REQUEST *EcRequest);
297 static ACPI_STATUS	EcRead(struct acpi_ec_softc *sc, UINT8 Address,
298 				UINT8 *Data);
299 static ACPI_STATUS	EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
300 				UINT8 *Data);
301 static void		acpi_ec_identify(driver_t driver, device_t bus);
302 static int		acpi_ec_probe(device_t dev);
303 static int		acpi_ec_attach(device_t dev);
304 
305 static device_method_t acpi_ec_methods[] = {
306     /* Device interface */
307     DEVMETHOD(device_identify,	acpi_ec_identify),
308     DEVMETHOD(device_probe,	acpi_ec_probe),
309     DEVMETHOD(device_attach,	acpi_ec_attach),
310 
311     {0, 0}
312 };
313 
314 static driver_t acpi_ec_driver = {
315     "acpi_ec",
316     acpi_ec_methods,
317     sizeof(struct acpi_ec_softc),
318 };
319 
320 static devclass_t acpi_ec_devclass;
321 DRIVER_MODULE(acpi_ec, acpi, acpi_ec_driver, acpi_ec_devclass, 0, 0);
322 
323 /*
324  * Look for an ECDT table and if we find one, set up a default EC
325  * space handler to catch possible attempts to access EC space before
326  * we have a real driver instance in place.
327  * We're not really an identify routine, but because we get called
328  * before most other things, this works out OK.
329  */
330 static void
331 acpi_ec_identify(driver_t driver, device_t bus)
332 {
333     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
334 
335     /* XXX implement - need an ACPI 2.0 system to test this */
336 }
337 
338 /*
339  * We could setup resources in the probe routine in order to have them printed
340  * when the device is attached.
341  */
342 static int
343 acpi_ec_probe(device_t dev)
344 {
345 
346     if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("ec") &&
347 	acpi_MatchHid(dev, "PNP0C09")) {
348 
349 	/*
350 	 * Set device description
351 	 */
352 	device_set_desc(dev, "embedded controller");
353 	return (0);
354     }
355     return (ENXIO);
356 }
357 
358 static int
359 acpi_ec_attach(device_t dev)
360 {
361     struct acpi_ec_softc	*sc;
362     ACPI_STATUS			Status;
363     int				errval = 0;
364 
365     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
366 
367     /*
368      * Fetch/initialise softc
369      */
370     sc = device_get_softc(dev);
371     bzero(sc, sizeof(*sc));
372     sc->ec_dev = dev;
373     sc->ec_handle = acpi_get_handle(dev);
374 
375     /*
376      * Attach bus resources
377      */
378     sc->ec_data_rid = 0;
379     sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
380 			&sc->ec_data_rid, 0, ~0, 1, RF_ACTIVE);
381     if (sc->ec_data_res == NULL) {
382 	device_printf(dev, "can't allocate data port\n");
383 	errval = ENXIO;
384 	goto out;
385     }
386     sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
387     sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);
388 
389     sc->ec_csr_rid = 1;
390     sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
391 			&sc->ec_csr_rid, 0, ~0, 1, RF_ACTIVE);
392     if (sc->ec_csr_res == NULL) {
393 	device_printf(dev, "can't allocate command/status port\n");
394 	errval = ENXIO;
395 	goto out;
396     }
397     sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
398     sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
399 
400     /*
401      * Install GPE handler
402      *
403      * Evaluate the _GPE method to find the GPE bit used by the EC to signal
404      * status (SCI).
405      */
406     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE\n"));
407     Status = acpi_EvaluateInteger(sc->ec_handle, "_GPE", &sc->ec_gpebit);
408     if (ACPI_FAILURE(Status)) {
409 	device_printf(dev, "can't evaluate _GPE - %s\n",
410 		      AcpiFormatException(Status));
411 	errval = ENXIO;
412 	goto out;
413     }
414 
415     /*
416      * Install a handler for this EC's GPE bit.  Note that EC SCIs are
417      * treated as both edge- and level-triggered interrupts; in other words
418      * we clear the status bit immediately after getting an EC-SCI, then
419      * again after we're done processing the event.  This guarantees that
420      * events we cause while performing a transaction (e.g. IBE/OBF) get
421      * cleared before re-enabling the GPE.
422      */
423     Status = AcpiInstallGpeHandler(sc->ec_gpebit,
424 		ACPI_EVENT_LEVEL_TRIGGERED | ACPI_EVENT_EDGE_TRIGGERED,
425 		EcGpeHandler, sc);
426     if (ACPI_FAILURE(Status)) {
427 	device_printf(dev, "can't install GPE handler for %s - %s\n",
428 		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
429 	errval = ENXIO;
430 	goto out;
431     }
432 
433     /*
434      * Install address space handler
435      */
436     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
437     Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
438 		EcSpaceHandler, EcSpaceSetup, sc);
439     if (ACPI_FAILURE(Status)) {
440 	device_printf(dev, "can't install address space handler for %s - %s\n",
441 		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
442 	panic("very suck");
443 	errval = ENXIO;
444 	goto out;
445     }
446     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attach complete\n"));
447     return_VALUE (0);
448 
449  out:
450     if (sc->ec_csr_res)
451 	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
452 			     sc->ec_csr_res);
453     if (sc->ec_data_res)
454         bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
455 			     sc->ec_data_res);
456     return_VALUE (errval);
457 }
458 
459 static void
460 EcGpeQueryHandler(void *Context)
461 {
462     struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
463     UINT8			Data;
464     ACPI_STATUS			Status;
465     char			qxx[5];
466 
467     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
468 
469     for (;;) {
470 
471 	/*
472 	 * Check EC_SCI.
473 	 *
474 	 * Bail out if the EC_SCI bit of the status register is not set.
475 	 * Note that this function should only be called when
476 	 * this bit is set (polling is used to detect IBE/OBF events).
477 	 *
478 	 * It is safe to do this without locking the controller, as it's
479 	 * OK to call EcQuery when there's no data ready; in the worst
480 	 * case we should just find nothing waiting for us and bail.
481 	 */
482 	if ((EC_GET_CSR(sc) & EC_EVENT_SCI) == 0)
483 	    break;
484 
485 	/*
486 	 * Find out why the EC is signalling us
487 	 */
488 	Status = EcQuery(sc, &Data);
489 
490 	/*
491 	 * If we failed to get anything from the EC, give up
492 	 */
493 	if (ACPI_FAILURE(Status)) {
494 	    ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
495 		"GPE query failed - %s\n", AcpiFormatException(Status));
496 	    break;
497 	}
498 
499 	/*
500 	 * Evaluate _Qxx to respond to the controller.
501 	 */
502 	sprintf(qxx, "_Q%02x", Data);
503 	strupr(qxx);
504 	Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
505 	/*
506 	 * Ignore spurious query requests.
507 	 */
508 	if (ACPI_FAILURE(Status) && (Data != 0 || Status != AE_NOT_FOUND)) {
509 	    ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
510 	    	"evaluation of GPE query method %s failed - %s\n",
511 		qxx, AcpiFormatException(Status));
512 	}
513     }
514         /* I know I request Level trigger cleanup */
515     if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE)))
516 	printf("EcGpeQueryHandler:ClearEvent Failed\n");
517     if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0)))
518 	printf("EcGpeQueryHandler:EnableEvent Failed\n");
519 }
520 
521 /*
522  * Handle a GPE sent to us.
523  */
524 static void
525 EcGpeHandler(void *Context)
526 {
527     struct acpi_ec_softc *sc = Context;
528     int csrvalue;
529 
530     /*
531      * If EC is locked, the intr must process EcRead/Write wait only.
532      * Query request must be pending.
533      */
534     if (EcIsLocked(sc)) {
535 	csrvalue = EC_GET_CSR(sc);
536 	if (csrvalue & EC_EVENT_SCI)
537 	    sc->ec_pendquery = 1;
538 	if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 ||
539 	    (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) {
540 	    sc->ec_csrvalue = csrvalue;
541 	    wakeup(&sc->ec_csrvalue);
542 	}
543     } else {
544 	/* Queue GpeQuery Handler */
545 	if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
546 				    EcGpeQueryHandler,Context))) {
547 	    printf("QueryHandler Queuing Failed\n");
548 	}
549     }
550 }
551 
552 static ACPI_STATUS
553 EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
554 	     void **RegionContext)
555 {
556 
557     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
558 
559     /*
560      * Just pass the context through, there's nothing to do here.
561      */
562     *RegionContext = Context;
563 
564     return_ACPI_STATUS (AE_OK);
565 }
566 
567 static ACPI_STATUS
568 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
569 	       ACPI_INTEGER *Value, void *Context, void *RegionContext)
570 {
571     struct acpi_ec_softc	*sc = (struct acpi_ec_softc *)Context;
572     ACPI_STATUS			Status = AE_OK;
573     EC_REQUEST			EcRequest;
574     int				i;
575 
576     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
577 
578     if (Address > 0xFF || width % 8 != 0 || Value == NULL || Context == NULL)
579         return_ACPI_STATUS (AE_BAD_PARAMETER);
580 
581     switch (Function) {
582     case ACPI_READ:
583         EcRequest.Command = EC_COMMAND_READ;
584         EcRequest.Address = Address;
585 	(*Value) = 0;
586         break;
587     case ACPI_WRITE:
588         EcRequest.Command = EC_COMMAND_WRITE;
589         EcRequest.Address = Address;
590         break;
591     default:
592 	device_printf(sc->ec_dev, "invalid Address Space function %d\n",
593 		      Function);
594         return_ACPI_STATUS (AE_BAD_PARAMETER);
595     }
596 
597     /*
598      * Perform the transaction.
599      */
600     for (i = 0; i < width; i += 8) {
601 	if (Function == ACPI_READ)
602 	    EcRequest.Data = 0;
603 	else
604 	    EcRequest.Data = (UINT8)((*Value) >> i);
605 	Status = EcTransaction(sc, &EcRequest);
606 	if (ACPI_FAILURE(Status))
607 	    break;
608         *Value |= (ACPI_INTEGER)EcRequest.Data << i;
609 	if (++EcRequest.Address == 0)
610             return_ACPI_STATUS (AE_BAD_PARAMETER);
611     }
612     return_ACPI_STATUS (Status);
613 }
614 
615 /*
616  * Wait for an event interrupt for a specific condition.
617  */
618 static ACPI_STATUS
619 EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event)
620 {
621     EC_STATUS	EcStatus;
622     int		i;
623 
624     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Event);
625 
626     /* XXX this should test whether interrupts are available some other way */
627     if (cold || acpi_ec_event_driven)
628 	return_ACPI_STATUS (EcWaitEvent(sc, Event));
629 
630     if (!EcIsLocked(sc)) {
631 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
632 	    "EcWaitEventIntr called without EC lock!\n");
633     }
634 
635     EcStatus = EC_GET_CSR(sc);
636 
637     /* XXX waiting too long? */
638     for (i = 0; i < 10; i++) {
639 	/*
640 	 * Check EC status against the desired event.
641 	 */
642     	if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
643 	    (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
644 	    return_ACPI_STATUS (AE_OK);
645 
646 	if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) &&
647 	    (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
648 	    return_ACPI_STATUS (AE_OK);
649 
650 	sc->ec_csrvalue = 0;
651 	/* XXX sleeping with Acpi Global Lock held */
652 	if (tsleep(&sc->ec_csrvalue, 0, "EcWait", 1) != EWOULDBLOCK) {
653 	    EcStatus = sc->ec_csrvalue;
654 	} else {
655 	    EcStatus = EC_GET_CSR(sc);
656 	}
657     }
658     return_ACPI_STATUS (AE_ERROR);
659 }
660 
661 static ACPI_STATUS
662 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
663 {
664     EC_STATUS	EcStatus;
665     UINT32	i = 0;
666 
667     if (!EcIsLocked(sc)) {
668 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
669 	    "EcWaitEvent called without EC lock!\n");
670     }
671 
672     /*
673      * Stall 1us:
674      * ----------
675      * Stall for 1 microsecond before reading the status register
676      * for the first time.  This allows the EC to set the IBF/OBF
677      * bit to its proper state.
678      *
679      * XXX it is not clear why we read the CSR twice.
680      */
681     AcpiOsStall(1);
682     EcStatus = EC_GET_CSR(sc);
683 
684     /*
685      * Wait For Event:
686      * ---------------
687      * Poll the EC status register to detect completion of the last
688      * command.  Wait up to 10ms (in 10us chunks) for this to occur.
689      */
690     for (i = 0; i < 1000; i++) {
691 	EcStatus = EC_GET_CSR(sc);
692 
693         if (Event == EC_EVENT_OUTPUT_BUFFER_FULL &&
694             (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
695 	    return (AE_OK);
696 
697 	if (Event == EC_EVENT_INPUT_BUFFER_EMPTY &&
698             (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
699 	    return(AE_OK);
700 
701 	AcpiOsStall(10);
702     }
703 
704     return (AE_ERROR);
705 }
706 
707 static ACPI_STATUS
708 EcQuery(struct acpi_ec_softc *sc, UINT8 *Data)
709 {
710     ACPI_STATUS	Status;
711 
712     Status = EcLock(sc);
713     if (ACPI_FAILURE(Status))
714 	return (Status);
715 
716     EC_SET_CSR(sc, EC_COMMAND_QUERY);
717     Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
718     if (ACPI_SUCCESS(Status))
719 	*Data = EC_GET_DATA(sc);
720 
721     EcUnlock(sc);
722 
723     if (ACPI_FAILURE(Status)) {
724 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
725 	    "timeout waiting for EC to respond to EC_COMMAND_QUERY\n");
726     }
727     return (Status);
728 }
729 
730 static ACPI_STATUS
731 EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
732 {
733     ACPI_STATUS	Status;
734 
735     Status = EcLock(sc);
736     if (ACPI_FAILURE(Status))
737 	return (Status);
738 
739     /*
740      * Perform the transaction.
741      */
742     switch (EcRequest->Command) {
743     case EC_COMMAND_READ:
744 	Status = EcRead(sc, EcRequest->Address, &EcRequest->Data);
745 	break;
746     case EC_COMMAND_WRITE:
747 	Status = EcWrite(sc, EcRequest->Address, &EcRequest->Data);
748 	break;
749     default:
750 	Status = AE_SUPPORT;
751 	break;
752     }
753 
754     EcUnlock(sc);
755 
756     /*
757      * Clear & Re-Enable the EC GPE:
758      * -----------------------------
759      * 'Consume' any EC GPE events that we generated while performing
760      * the transaction (e.g. IBF/OBF).	Clearing the GPE here shouldn't
761      * have an adverse affect on outstanding EC-SCI's, as the source
762      * (EC-SCI) will still be high and thus should trigger the GPE
763      * immediately after we re-enabling it.
764      */
765     if (sc->ec_pendquery) {
766 	if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
767 						 EcGpeQueryHandler, sc)))
768 	    printf("Pend Query Queuing Failed\n");
769 	sc->ec_pendquery = 0;
770     }
771 
772     if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE))) {
773 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
774 	    "EcRequest: Unable to clear the EC GPE.\n");
775     }
776     if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0))) {
777 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
778 	    "EcRequest: Unable to re-enable the EC GPE.\n");
779     }
780 
781     return (Status);
782 }
783 
784 
785 static ACPI_STATUS
786 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
787 {
788     ACPI_STATUS	Status;
789 
790     if (!EcIsLocked(sc)) {
791 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
792 	    "EcRead called without EC lock!\n");
793     }
794 
795     /*EcBurstEnable(EmbeddedController);*/
796 
797     EC_SET_CSR(sc, EC_COMMAND_READ);
798     Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
799     if (ACPI_FAILURE(Status)) {
800 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
801 	    "EcRead: Failed waiting for EC to process read command.\n");
802 	return (Status);
803     }
804 
805     EC_SET_DATA(sc, Address);
806     Status = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
807     if (ACPI_FAILURE(Status)) {
808 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
809 	    "EcRead: Failed waiting for EC to send data.\n");
810 	return (Status);
811     }
812 
813     *Data = EC_GET_DATA(sc);
814 
815     /*EcBurstDisable(EmbeddedController);*/
816 
817     return (AE_OK);
818 }
819 
820 static ACPI_STATUS
821 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
822 {
823     ACPI_STATUS	Status;
824 
825     if (!EcIsLocked(sc)) {
826 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
827 	    "EcWrite called without EC lock!\n");
828     }
829 
830     /*EcBurstEnable(EmbeddedController);*/
831 
832     EC_SET_CSR(sc, EC_COMMAND_WRITE);
833     Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
834     if (ACPI_FAILURE(Status)) {
835 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
836 	    "EcWrite: Failed waiting for EC to process write command.\n");
837 	return (Status);
838     }
839 
840     EC_SET_DATA(sc, Address);
841     Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
842     if (ACPI_FAILURE(Status)) {
843 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
844 	    "EcRead: Failed waiting for EC to process address.\n");
845 	return (Status);
846     }
847 
848     EC_SET_DATA(sc, *Data);
849     Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
850     if (ACPI_FAILURE(Status)) {
851 	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
852 	    "EcWrite: Failed waiting for EC to process data.\n");
853 	return (Status);
854     }
855 
856     /*EcBurstDisable(EmbeddedController);*/
857 
858     return (AE_OK);
859 }
860