Merge from vendor branch LIBPCAP:
[dragonfly.git] / sys / dev / acpica5 / acpi_ec.c
1 /*-
2  * Copyright (c) 2003 Nate Lawson
3  * Copyright (c) 2000 Michael Smith
4  * Copyright (c) 2000 BSDi
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.42 2004/01/03 02:01:39 njl Exp $
29  * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.2 2004/03/01 06:33:13 dillon Exp $
30  */
31 /******************************************************************************
32  *
33  * 1. Copyright Notice
34  *
35  * Some or all of this work - Copyright (c) 1999, Intel Corp.  All rights
36  * reserved.
37  *
38  * 2. License
39  *
40  * 2.1. This is your license from Intel Corp. under its intellectual property
41  * rights.  You may have additional license terms from the party that provided
42  * you this software, covering your right to use that party's intellectual
43  * property rights.
44  *
45  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
46  * copy of the source code appearing in this file ("Covered Code") an
47  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
48  * base code distributed originally by Intel ("Original Intel Code") to copy,
49  * make derivatives, distribute, use and display any portion of the Covered
50  * Code in any form, with the right to sublicense such rights; and
51  *
52  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
53  * license (with the right to sublicense), under only those claims of Intel
54  * patents that are infringed by the Original Intel Code, to make, use, sell,
55  * offer to sell, and import the Covered Code and derivative works thereof
56  * solely to the minimum extent necessary to exercise the above copyright
57  * license, and in no event shall the patent license extend to any additions
58  * to or modifications of the Original Intel Code.  No other license or right
59  * is granted directly or by implication, estoppel or otherwise;
60  *
61  * The above copyright and patent license is granted only if the following
62  * conditions are met:
63  *
64  * 3. Conditions 
65  *
66  * 3.1. Redistribution of Source with Rights to Further Distribute Source.  
67  * Redistribution of source code of any substantial portion of the Covered
68  * Code or modification with rights to further distribute source must include
69  * the above Copyright Notice, the above License, this list of Conditions,
70  * and the following Disclaimer and Export Compliance provision.  In addition,
71  * Licensee must cause all Covered Code to which Licensee contributes to
72  * contain a file documenting the changes Licensee made to create that Covered
73  * Code and the date of any change.  Licensee must include in that file the
74  * documentation of any changes made by any predecessor Licensee.  Licensee 
75  * must include a prominent statement that the modification is derived,
76  * directly or indirectly, from Original Intel Code.
77  *
78  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.  
79  * Redistribution of source code of any substantial portion of the Covered
80  * Code or modification without rights to further distribute source must
81  * include the following Disclaimer and Export Compliance provision in the
82  * documentation and/or other materials provided with distribution.  In
83  * addition, Licensee may not authorize further sublicense of source of any
84  * portion of the Covered Code, and must include terms to the effect that the
85  * license from Licensee to its licensee is limited to the intellectual
86  * property embodied in the software Licensee provides to its licensee, and
87  * not to intellectual property embodied in modifications its licensee may
88  * make.
89  *
90  * 3.3. Redistribution of Executable. Redistribution in executable form of any
91  * substantial portion of the Covered Code or modification must reproduce the
92  * above Copyright Notice, and the following Disclaimer and Export Compliance
93  * provision in the documentation and/or other materials provided with the
94  * distribution.
95  *
96  * 3.4. Intel retains all right, title, and interest in and to the Original
97  * Intel Code.
98  *
99  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
100  * Intel shall be used in advertising or otherwise to promote the sale, use or
101  * other dealings in products derived from or relating to the Covered Code
102  * without prior written authorization from Intel.
103  *
104  * 4. Disclaimer and Export Compliance
105  *
106  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
107  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
108  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
109  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
110  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
111  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
112  * PARTICULAR PURPOSE. 
113  *
114  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
115  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
116  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
117  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
118  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
119  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
120  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
121  * LIMITED REMEDY.
122  *
123  * 4.3. Licensee shall not export, either directly or indirectly, any of this
124  * software or system incorporating such software without first obtaining any
125  * required license or other approval from the U. S. Department of Commerce or
126  * any other agency or department of the United States Government.  In the
127  * event Licensee exports any such software from the United States or
128  * re-exports any such software from a foreign destination, Licensee shall
129  * ensure that the distribution and export/re-export of the software is in
130  * compliance with all laws, regulations, orders, or other restrictions of the
131  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
132  * any of its subsidiaries will export/re-export any technical data, process,
133  * software, or service, directly or indirectly, to any country for which the
134  * United States government or any agency thereof requires an export license,
135  * other governmental approval, or letter of assurance, without first obtaining
136  * such license, approval or letter.
137  *
138  *****************************************************************************/
139  /*
140   * $FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.42 2004/01/03 02:01:39 njl Exp $
141   * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.2 2004/03/01 06:33:13 dillon Exp $
142   *
143   */
144
145 #include "opt_acpi.h"
146 #include <sys/param.h>
147 #include <sys/kernel.h>
148 #include <sys/bus.h>
149 #include <sys/thread.h>
150
151 #include <machine/bus.h>
152 #include <machine/resource.h>
153 #include <sys/rman.h>
154
155 #include "acpi.h"
156
157 #include <dev/acpica5/acpivar.h>
158
159 /*
160  * Hooks for the ACPI CA debugging infrastructure
161  */
162 #define _COMPONENT      ACPI_EC
163 ACPI_MODULE_NAME("EC")
164
165 /*
166  * EC_COMMAND:
167  * -----------
168  */
169 typedef UINT8                           EC_COMMAND;
170
171 #define EC_COMMAND_UNKNOWN              ((EC_COMMAND) 0x00)
172 #define EC_COMMAND_READ                 ((EC_COMMAND) 0x80)
173 #define EC_COMMAND_WRITE                ((EC_COMMAND) 0x81)
174 #define EC_COMMAND_BURST_ENABLE         ((EC_COMMAND) 0x82)
175 #define EC_COMMAND_BURST_DISABLE        ((EC_COMMAND) 0x83)
176 #define EC_COMMAND_QUERY                ((EC_COMMAND) 0x84)
177
178 /* 
179  * EC_STATUS:
180  * ----------
181  * The encoding of the EC status register is illustrated below.
182  * Note that a set bit (1) indicates the property is TRUE
183  * (e.g. if bit 0 is set then the output buffer is full).
184  * +-+-+-+-+-+-+-+-+
185  * |7|6|5|4|3|2|1|0|    
186  * +-+-+-+-+-+-+-+-+
187  *  | | | | | | | |
188  *  | | | | | | | +- Output Buffer Full?
189  *  | | | | | | +--- Input Buffer Full?
190  *  | | | | | +----- <reserved>
191  *  | | | | +------- Data Register is Command Byte?
192  *  | | | +--------- Burst Mode Enabled?
193  *  | | +----------- SCI Event?
194  *  | +------------- SMI Event?
195  *  +--------------- <Reserved>
196  *
197  */
198 typedef UINT8                           EC_STATUS;
199
200 #define EC_FLAG_OUTPUT_BUFFER           ((EC_STATUS) 0x01)
201 #define EC_FLAG_INPUT_BUFFER            ((EC_STATUS) 0x02)
202 #define EC_FLAG_BURST_MODE              ((EC_STATUS) 0x10)
203 #define EC_FLAG_SCI                     ((EC_STATUS) 0x20)
204
205 /*
206  * EC_EVENT:
207  * ---------
208  */
209 typedef UINT8                           EC_EVENT;
210
211 #define EC_EVENT_UNKNOWN                ((EC_EVENT) 0x00)
212 #define EC_EVENT_OUTPUT_BUFFER_FULL     ((EC_EVENT) 0x01)
213 #define EC_EVENT_INPUT_BUFFER_EMPTY     ((EC_EVENT) 0x02)
214 #define EC_EVENT_SCI                    ((EC_EVENT) 0x20)
215
216 /*
217  * Register access primitives
218  */
219 #define EC_GET_DATA(sc)                                                 \
220         bus_space_read_1((sc)->ec_data_tag, (sc)->ec_data_handle, 0)
221
222 #define EC_SET_DATA(sc, v)                                              \
223         bus_space_write_1((sc)->ec_data_tag, (sc)->ec_data_handle, 0, (v))
224
225 #define EC_GET_CSR(sc)                                                  \
226         bus_space_read_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0)
227
228 #define EC_SET_CSR(sc, v)                                               \
229         bus_space_write_1((sc)->ec_csr_tag, (sc)->ec_csr_handle, 0, (v))
230
231 /* Embedded Controller Boot Resources Table (ECDT) */
232 typedef struct {
233     ACPI_TABLE_HEADER           header;
234     ACPI_GENERIC_ADDRESS        control;
235     ACPI_GENERIC_ADDRESS        data;
236     UINT32                      uid;
237     UINT8                       gpe_bit;
238     char                        ec_id[0];
239 } ACPI_TABLE_ECDT;
240
241 /* Indicate that this device has already been probed via ECDT. */
242 #define DEV_ECDT(x)             (acpi_get_private(x) == &acpi_ec_devclass)
243
244 /* Indicate that this device should use the global lock. */
245 #define DEV_GLK_FLAG            0x40000000
246
247 /* Get/set GPE bit value in the magic ivar. */
248 #define DEV_GET_GPEBIT(x)       ((x) & 0xff)
249 #define DEV_SET_GPEBIT(x, y)    ((x) = ((x) & ~0xff) | ((y) & 0xff))
250
251 /*
252  * Driver softc.
253  */
254 struct acpi_ec_softc {
255     device_t            ec_dev;
256     ACPI_HANDLE         ec_handle;
257     UINT8               ec_gpebit;
258     UINT8               ec_csrvalue;
259     
260     int                 ec_data_rid;
261     struct resource     *ec_data_res;
262     bus_space_tag_t     ec_data_tag;
263     bus_space_handle_t  ec_data_handle;
264
265     int                 ec_csr_rid;
266     struct resource     *ec_csr_res;
267     bus_space_tag_t     ec_csr_tag;
268     bus_space_handle_t  ec_csr_handle;
269
270     int                 ec_glk;
271     int                 ec_glkhandle;
272     struct lwkt_rwlock  ec_rwlock;
273     int                 ec_polldelay;
274 };
275
276 /*
277  * XXX
278  * I couldn't find it in the spec but other implementations also use a
279  * value of 1 ms for the time to acquire global lock.
280  */
281 #define EC_LOCK_TIMEOUT 1000
282
283 /*
284  * Start with an interval of 1 us for status poll loop.  This delay
285  * will be dynamically adjusted based on the actual time waited.
286  */
287 #define EC_POLL_DELAY   1
288
289 /* Total time in ms spent in the poll loop waiting for a response. */
290 #define EC_POLL_TIMEOUT 100
291
292 #define EVENT_READY(event, status)                      \
293         (((event) == EC_EVENT_OUTPUT_BUFFER_FULL &&     \
294          ((status) & EC_FLAG_OUTPUT_BUFFER) != 0) ||    \
295          ((event) == EC_EVENT_INPUT_BUFFER_EMPTY &&     \
296          ((status) & EC_FLAG_INPUT_BUFFER) == 0))
297
298 static int      ec_poll_timeout = EC_POLL_TIMEOUT;
299 TUNABLE_INT("hw.acpi.ec.poll_timeout", &ec_poll_timeout);
300
301 static __inline ACPI_STATUS
302 EcLock(struct acpi_ec_softc *sc)
303 {
304     ACPI_STATUS status = AE_OK;
305
306     /* Always acquire this EC's mutex. */
307     lwkt_exlock(&sc->ec_rwlock, "acpi2");
308
309     /* If _GLK is non-zero, also acquire the global lock. */
310     if (sc->ec_glk) {
311         status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
312         if (ACPI_FAILURE(status))
313             lwkt_exunlock(&sc->ec_rwlock);
314     }
315
316     return (status);
317 }
318
319 static __inline void
320 EcUnlock(struct acpi_ec_softc *sc)
321 {
322     if (sc->ec_glk)
323         AcpiReleaseGlobalLock(sc->ec_glkhandle);
324     lwkt_exunlock(&sc->ec_rwlock);
325 }
326
327 static void             EcGpeHandler(void *Context);
328 static ACPI_STATUS      EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, 
329                                 void *Context, void **return_Context);
330 static ACPI_STATUS      EcSpaceHandler(UINT32 Function,
331                                 ACPI_PHYSICAL_ADDRESS Address,
332                                 UINT32 width, ACPI_INTEGER *Value,
333                                 void *Context, void *RegionContext);
334 static ACPI_STATUS      EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
335 static ACPI_STATUS      EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd);
336 static ACPI_STATUS      EcRead(struct acpi_ec_softc *sc, UINT8 Address,
337                                 UINT8 *Data);
338 static ACPI_STATUS      EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
339                                 UINT8 *Data);
340 static int              acpi_ec_probe(device_t dev);
341 static int              acpi_ec_attach(device_t dev);
342
343 static device_method_t acpi_ec_methods[] = {
344     /* Device interface */
345     DEVMETHOD(device_probe,     acpi_ec_probe),
346     DEVMETHOD(device_attach,    acpi_ec_attach),
347
348     {0, 0}
349 };
350
351 static driver_t acpi_ec_driver = {
352     "acpi_ec",
353     acpi_ec_methods,
354     sizeof(struct acpi_ec_softc),
355 };
356
357 static devclass_t acpi_ec_devclass;
358 DRIVER_MODULE(acpi_ec, acpi, acpi_ec_driver, acpi_ec_devclass, 0, 0);
359
360 /*
361  * Look for an ECDT and if we find one, set up default GPE and 
362  * space handlers to catch attempts to access EC space before
363  * we have a real driver instance in place.
364  * TODO: if people report invalid ECDTs, add a tunable to disable them.
365  */
366 void
367 acpi_ec_ecdt_probe(device_t parent)
368 {
369     ACPI_TABLE_ECDT *ecdt;
370     ACPI_STATUS      status;
371     device_t         child;
372     ACPI_HANDLE      h;
373     int              magic;
374
375     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
376
377     /* Find and validate the ECDT. */
378     status = AcpiGetFirmwareTable("ECDT", 1, ACPI_LOGICAL_ADDRESSING, 
379                 (ACPI_TABLE_HEADER **)&ecdt);
380     if (ACPI_FAILURE(status) ||
381         ecdt->control.RegisterBitWidth != 8 ||
382         ecdt->data.RegisterBitWidth != 8) {
383         return;
384     }
385
386     /* Create the child device with the given unit number. */
387     child = BUS_ADD_CHILD(parent, 0, "acpi_ec", ecdt->uid);
388     if (child == NULL) {
389         printf("acpi_ec_ecdt_probe: can't add child\n");
390         return;
391     }
392
393     /* Find and save the ACPI handle for this device. */
394     status = AcpiGetHandle(NULL, ecdt->ec_id, &h);
395     if (ACPI_FAILURE(status)) {
396         device_delete_child(parent, child);
397         printf("acpi_ec_ecdt_probe: can't get handle\n");
398         return;
399     }
400     acpi_set_handle(child, h);
401
402     /* Set the data and CSR register addresses. */
403     bus_set_resource(child, SYS_RES_IOPORT, 0, ecdt->data.Address,
404         /*count*/1);
405     bus_set_resource(child, SYS_RES_IOPORT, 1, ecdt->control.Address,
406         /*count*/1);
407
408     /*
409      * Store values for the probe/attach routines to use.  Store the
410      * ECDT GPE bit and set the global lock flag (just to be safe).
411      * We'll determine whether we really want to use the global lock
412      * in a later call to attach.
413      */
414     acpi_set_private(child, &acpi_ec_devclass);
415     magic = DEV_GLK_FLAG;
416     DEV_SET_GPEBIT(magic, ecdt->gpe_bit);
417     acpi_set_magic(child, magic);
418
419     /* Finish the attach process. */
420     if (device_probe_and_attach(child) != 0)
421         device_delete_child(parent, child);
422 }
423
424 static int
425 acpi_ec_probe(device_t dev)
426 {
427     ACPI_HANDLE h;
428     ACPI_STATUS status;
429     device_t    peer;
430     char        desc[64];
431     int         magic, uid, glk, gpebit, ret = ENXIO;
432
433     /* Check that this is a device and that EC is not disabled. */
434     if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec"))
435         return (ENXIO);
436
437     /*
438      * If probed via ECDT, set description and continue.  Otherwise,
439      * we can access the namespace and make sure this is not a
440      * duplicate probe.
441      */
442     magic = acpi_get_magic(dev);
443     if (DEV_ECDT(dev)) {
444         snprintf(desc, sizeof(desc), "Embedded Controller: ECDT, GPE %#x, GLK",
445                  DEV_GET_GPEBIT(magic));
446         device_set_desc_copy(dev, desc);
447         ret = 0;
448     } else if (acpi_MatchHid(dev, "PNP0C09")) {
449         h = acpi_get_handle(dev);
450
451         /*
452          * Read the unit ID to check for duplicate attach and the
453          * global lock value to see if we should acquire it when
454          * accessing the EC.
455          */
456         status = acpi_EvaluateInteger(h, "_UID", &uid);
457         if (ACPI_FAILURE(status))
458             uid = 0;
459         status = acpi_EvaluateInteger(h, "_GLK", &glk);
460         if (ACPI_FAILURE(status))
461             glk = 0;
462
463         /*
464          * Evaluate the _GPE method to find the GPE bit used by the EC to
465          * signal status (SCI).  Note that we don't handle the case where
466          * it can return a package instead of an int.
467          */
468         status = acpi_EvaluateInteger(h, "_GPE", &gpebit);
469         if (ACPI_FAILURE(status)) {
470             device_printf(dev, "can't evaluate _GPE - %s\n",
471                           AcpiFormatException(status));
472             return (ENXIO);
473         }
474
475         /* Store the values we got from the namespace for attach. */
476         magic = glk != 0 ? DEV_GLK_FLAG : 0;
477         DEV_SET_GPEBIT(magic, gpebit);
478         acpi_set_magic(dev, magic);
479
480         /*
481          * Check for a duplicate probe.  This can happen when a probe
482          * via ECDT succeeded already.  If there is a duplicate, override
483          * its value for GLK in the peer's softc since the ECDT case
484          * always enables the global lock to be safe.  Otherwise, just
485          * continue on to attach.
486          */
487         peer = devclass_get_device(acpi_ec_devclass, uid);
488         if (peer == NULL || !device_is_alive(peer)) {
489             snprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s",
490                      gpebit, glk != 0 ? ", GLK" : "");
491             device_set_desc_copy(dev, desc);
492             ret = 0;
493         } else {
494             struct acpi_ec_softc *sc;
495
496             /*
497              * Set the peer's sc->ec_glk with locks held so we won't
498              * override it between another thread's lock/unlock calls.
499              */
500             sc = device_get_softc(peer);
501             if (sc->ec_glk != glk) {
502                 ACPI_VPRINT(peer, acpi_device_get_parent_softc(peer),
503                     "Changing GLK from %d to %d\n", sc->ec_glk, glk);
504                 lwkt_exlock(&sc->ec_rwlock, "acpi2");
505                 sc->ec_glk = glk != 0 ? 1 : 0;
506                 lwkt_exunlock(&sc->ec_rwlock);
507             }
508         }
509     }
510
511     return (ret);
512 }
513
514 static int
515 acpi_ec_attach(device_t dev)
516 {
517     struct acpi_ec_softc        *sc;
518     ACPI_STATUS                 Status;
519     int                         magic, errval = 0;
520
521     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
522
523     /* Fetch/initialize softc (assumes softc is pre-zeroed). */
524     sc = device_get_softc(dev);
525     sc->ec_dev = dev;
526     sc->ec_handle = acpi_get_handle(dev);
527     sc->ec_polldelay = EC_POLL_DELAY;
528     lwkt_rwlock_init(&sc->ec_rwlock);
529
530     /* Retrieve previously probed values via device ivars. */
531     magic = acpi_get_magic(dev);
532     sc->ec_glk = (magic & DEV_GLK_FLAG) != 0 ? 1 : 0;
533     sc->ec_gpebit = DEV_GET_GPEBIT(magic);
534
535     /* Attach bus resources for data and command/status ports. */
536     sc->ec_data_rid = 0;
537     sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
538                         &sc->ec_data_rid, 0, ~0, 1, RF_ACTIVE);
539     if (sc->ec_data_res == NULL) {
540         device_printf(dev, "can't allocate data port\n");
541         errval = ENXIO;
542         goto out;
543     }
544     sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
545     sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);
546
547     sc->ec_csr_rid = 1;
548     sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
549                         &sc->ec_csr_rid, 0, ~0, 1, RF_ACTIVE);
550     if (sc->ec_csr_res == NULL) {
551         device_printf(dev, "can't allocate command/status port\n");
552         errval = ENXIO;
553         goto out;
554     }
555     sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
556     sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
557
558     /*
559      * Install a handler for this EC's GPE bit.  We want edge-triggered
560      * behavior.
561      */
562     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
563     Status = AcpiInstallGpeHandler(NULL, sc->ec_gpebit,
564                 ACPI_EVENT_EDGE_TRIGGERED, &EcGpeHandler, sc);
565     if (ACPI_FAILURE(Status)) {
566         device_printf(dev, "can't install GPE handler for %s - %s\n",
567                       acpi_name(sc->ec_handle), AcpiFormatException(Status));
568         errval = ENXIO;
569         goto out;
570     }
571
572     /* 
573      * Install address space handler
574      */
575     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
576     Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
577                 &EcSpaceHandler, &EcSpaceSetup, sc);
578     if (ACPI_FAILURE(Status)) {
579         device_printf(dev, "can't install address space handler for %s - %s\n",
580                       acpi_name(sc->ec_handle), AcpiFormatException(Status));
581         Status = AcpiRemoveGpeHandler(NULL, sc->ec_gpebit, &EcGpeHandler);
582         if (ACPI_FAILURE(Status))
583             panic("Added GPE handler but can't remove it");
584         errval = ENXIO;
585         goto out;
586     }
587
588     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
589     return (0);
590
591  out:
592     if (sc->ec_csr_res)
593         bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid, 
594                              sc->ec_csr_res);
595     if (sc->ec_data_res)
596         bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
597                              sc->ec_data_res);
598     /* mtx_destroy(&sc->ec_mtx); */
599     return (errval);
600 }
601
602 static void
603 EcGpeQueryHandler(void *Context)
604 {
605     struct acpi_ec_softc        *sc = (struct acpi_ec_softc *)Context;
606     UINT8                       Data;
607     ACPI_STATUS                 Status;
608     EC_STATUS                   EcStatus;
609     char                        qxx[5];
610
611     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
612     KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL"));
613
614     Status = EcLock(sc);
615     if (ACPI_FAILURE(Status)) {
616         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
617                     "GpeQuery lock error: %s\n", AcpiFormatException(Status));
618         return;
619     }
620
621     /*
622      * If the EC_SCI bit of the status register is not set, then pass
623      * it along to any potential waiters as it may be an IBE/OBF event.
624      */
625     EcStatus = EC_GET_CSR(sc);
626     if ((EcStatus & EC_EVENT_SCI) == 0) {
627         sc->ec_csrvalue = EcStatus;
628         wakeup(&sc->ec_csrvalue);
629         EcUnlock(sc);
630         goto re_enable;
631     }
632
633     /*
634      * Send a query command to the EC to find out which _Qxx call it
635      * wants to make.  This command clears the SCI bit and also the
636      * interrupt source since we are edge-triggered.
637      */
638     Status = EcCommand(sc, EC_COMMAND_QUERY);
639     if (ACPI_FAILURE(Status)) {
640         EcUnlock(sc);
641         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
642                     "GPE query failed - %s\n", AcpiFormatException(Status));
643         goto re_enable;
644     }
645     Data = EC_GET_DATA(sc);
646     EcUnlock(sc);
647
648     /* Ignore the value for "no outstanding event". (13.3.5) */
649     if (Data == 0)
650         goto re_enable;
651
652     /* Evaluate _Qxx to respond to the controller. */
653     sprintf(qxx, "_Q%02x", Data);
654     strupr(qxx);
655     Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
656     if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) {
657         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
658                     "evaluation of GPE query method %s failed - %s\n", 
659                     qxx, AcpiFormatException(Status));
660     }
661
662 re_enable:
663     /* Re-enable the GPE event so we'll get future requests. */
664     Status = AcpiEnableGpe(NULL, sc->ec_gpebit, ACPI_NOT_ISR);
665     if (ACPI_FAILURE(Status))
666         printf("EcGpeQueryHandler: AcpiEnableEvent failed\n");
667 }
668
669 /*
670  * Handle a GPE.  Currently we only handle SCI events as others must
671  * be handled by polling in EcWaitEvent().  This is because some ECs
672  * treat events as level when they should be edge-triggered.
673  */
674 static void
675 EcGpeHandler(void *Context)
676 {
677     struct acpi_ec_softc *sc = Context;
678     ACPI_STATUS                Status;
679
680     KASSERT(Context != NULL, ("EcGpeHandler called with NULL"));
681
682     /* Disable further GPEs while we handle this one. */
683     AcpiDisableGpe(NULL, sc->ec_gpebit, ACPI_ISR);
684
685     /* Schedule the GPE query handler. */
686     Status = AcpiOsQueueForExecution(OSD_PRIORITY_GPE, EcGpeQueryHandler,
687                 Context);
688     if (ACPI_FAILURE(Status)) {
689         printf("Queuing GPE query handler failed.\n");
690         Status = AcpiEnableGpe(NULL, sc->ec_gpebit, ACPI_ISR);
691         if (ACPI_FAILURE(Status))
692             printf("EcGpeHandler: AcpiEnableEvent failed\n");
693     }
694 }
695
696 static ACPI_STATUS
697 EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
698              void **RegionContext)
699 {
700
701     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
702
703     /*
704      * If deactivating a region, always set the output to NULL.  Otherwise,
705      * just pass the context through.
706      */
707     if (Function == ACPI_REGION_DEACTIVATE)
708         *RegionContext = NULL;
709     else
710         *RegionContext = Context;
711
712     return_ACPI_STATUS (AE_OK);
713 }
714
715 static ACPI_STATUS
716 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
717                ACPI_INTEGER *Value, void *Context, void *RegionContext)
718 {
719     struct acpi_ec_softc        *sc = (struct acpi_ec_softc *)Context;
720     ACPI_STATUS                 Status = AE_OK;
721     UINT8                       EcAddr, EcData;
722     int                         i;
723
724     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
725
726     if (Address > 0xFF || width % 8 != 0 || Value == NULL || Context == NULL)
727         return_ACPI_STATUS (AE_BAD_PARAMETER);
728
729     /*
730      * Perform the transaction.
731      */
732     EcAddr = Address;
733     for (i = 0; i < width; i += 8) {
734         Status = EcLock(sc);
735         if (ACPI_FAILURE(Status))
736             return (Status);
737
738         switch (Function) {
739         case ACPI_READ:
740             EcData = 0;
741             Status = EcRead(sc, EcAddr, &EcData);
742             break;
743         case ACPI_WRITE:
744             EcData = (UINT8)((*Value) >> i);
745             Status = EcWrite(sc, EcAddr, &EcData);
746             break;
747         default:
748             device_printf(sc->ec_dev, "invalid EcSpaceHandler function %d\n",
749                           Function);
750             Status = AE_BAD_PARAMETER;
751             break;
752         }
753
754         EcUnlock(sc);
755         if (ACPI_FAILURE(Status))
756             return (Status);
757
758         *Value |= (ACPI_INTEGER)EcData << i;
759         if (++EcAddr == 0)
760             return_ACPI_STATUS (AE_BAD_PARAMETER);
761     }
762     return_ACPI_STATUS (Status);
763 }
764
765 static ACPI_STATUS
766 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
767 {
768     EC_STATUS   EcStatus;
769     ACPI_STATUS Status;
770     int         i, period, retval;
771     static int  EcDbgMaxDelay;
772
773     /* mtx_assert(&sc->ec_mtx, MA_OWNED); */
774     Status = AE_NO_HARDWARE_RESPONSE;
775
776     /* 
777      * Wait for 1 us before checking the CSR.  Testing shows about
778      * 50% of requests complete in 1 us and 90% of them complete
779      * in 5 us or less.
780      */
781     AcpiOsStall(1);
782
783     /*
784      * Poll the EC status register to detect completion of the last
785      * command.  First, wait up to 1 ms in chunks of sc->ec_polldelay
786      * microseconds.
787      */
788     for (i = 0; i < 1000 / sc->ec_polldelay; i++) {
789         EcStatus = EC_GET_CSR(sc);
790         if (EVENT_READY(Event, EcStatus)) {
791             Status = AE_OK;
792             break;
793         }
794         AcpiOsStall(sc->ec_polldelay);
795     }
796
797     /* Scale poll delay by the amount of time actually waited. */
798     period = i * sc->ec_polldelay;
799     if (period <= 5)
800         sc->ec_polldelay = 1;
801     else if (period <= 20)
802         sc->ec_polldelay = 5;
803     else if (period <= 100)
804         sc->ec_polldelay = 10;
805     else
806         sc->ec_polldelay = 100;
807
808     /*
809      * If we still don't have a response, wait up to ec_poll_timeout ms
810      * for completion, sleeping for chunks of ~10 ms.
811      */
812     if (Status != AE_OK) {
813         retval = -1;
814         for (i = 0; i < ec_poll_timeout / 10; i++) {
815             if (retval != 0)
816                 EcStatus = EC_GET_CSR(sc);
817             else
818                 EcStatus = sc->ec_csrvalue;
819             if (EVENT_READY(Event, EcStatus)) {
820                 Status = AE_OK;
821                 break;
822             }
823             retval = tsleep(&sc->ec_csrvalue, 0, "ecpoll", 1 + hz / 100);
824         }
825     }
826
827     /* Calculate new delay and print it if it exceeds the max. */
828     if (period == 1000)
829         period += i * 10000;
830     if (period > EcDbgMaxDelay) {
831         EcDbgMaxDelay = period;
832         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
833                     "info: new max delay is %d us\n", period);
834     }
835
836     return (Status);
837 }    
838
839 static ACPI_STATUS
840 EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd)
841 {
842     ACPI_STATUS Status;
843     EC_EVENT    Event;
844
845     /*mtx_assert(&sc->ec_mtx, MA_OWNED);*/
846
847     /* Decide what to wait for based on command type. */
848     switch (cmd) {
849     case EC_COMMAND_READ:
850     case EC_COMMAND_WRITE:
851     case EC_COMMAND_BURST_DISABLE:
852         Event = EC_EVENT_INPUT_BUFFER_EMPTY;
853         break;
854     case EC_COMMAND_QUERY:
855     case EC_COMMAND_BURST_ENABLE:
856         Event = EC_EVENT_OUTPUT_BUFFER_FULL;
857         break;
858     default:
859         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
860                     "EcCommand: Invalid command %#x\n", cmd);
861         return (AE_BAD_PARAMETER);
862     }
863
864     /* Run the command and wait for the chosen event. */
865     EC_SET_CSR(sc, cmd);
866     Status = EcWaitEvent(sc, Event);
867     if (ACPI_FAILURE(Status)) {
868         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
869                     "EcCommand: no response to %#x\n", cmd);
870     }
871
872     return (Status);
873 }
874
875 static ACPI_STATUS
876 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
877 {
878     ACPI_STATUS Status;
879
880     /*mtx_assert(&sc->ec_mtx, MA_OWNED);*/
881
882 #ifdef notyet
883     /* If we can't start burst mode, continue anyway. */
884     EcCommand(sc, EC_COMMAND_BURST_ENABLE);
885 #endif
886
887     Status = EcCommand(sc, EC_COMMAND_READ);
888     if (ACPI_FAILURE(Status))
889         return (Status);
890
891     EC_SET_DATA(sc, Address);
892     Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
893     if (ACPI_FAILURE(Status)) {
894         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
895                     "EcRead: Failed waiting for EC to send data.\n");
896         return (Status);
897     }
898
899     *Data = EC_GET_DATA(sc);
900
901 #ifdef notyet
902     if (sc->ec_burstactive) {
903         Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
904         if (ACPI_FAILURE(Status))
905             return (Status);
906     }
907 #endif
908
909     return (AE_OK);
910 }    
911
912 static ACPI_STATUS
913 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
914 {
915     ACPI_STATUS Status;
916
917     /*mtx_assert(&sc->ec_mtx, MA_OWNED);*/
918
919 #ifdef notyet
920     /* If we can't start burst mode, continue anyway. */
921     EcCommand(sc, EC_COMMAND_BURST_ENABLE);
922 #endif
923
924     Status = EcCommand(sc, EC_COMMAND_WRITE);
925     if (ACPI_FAILURE(Status))
926         return (Status);
927
928     EC_SET_DATA(sc, Address);
929     Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
930     if (ACPI_FAILURE(Status)) {
931         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
932                     "EcRead: Failed waiting for EC to process address\n");
933         return (Status);
934     }
935
936     EC_SET_DATA(sc, *Data);
937     Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
938     if (ACPI_FAILURE(Status)) {
939         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
940                     "EcWrite: Failed waiting for EC to process data\n");
941         return (Status);
942     }
943
944 #ifdef notyet
945     if (sc->ec_burstactive) {
946         Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
947         if (ACPI_FAILURE(Status))
948             return (Status);
949     }
950 #endif
951
952     return (AE_OK);
953 }