6fd40966e8e27fb9e9860610b5a36b998d5f970b
[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.52 2004/06/13 22:52:30 njl Exp $
29  * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.14 2008/08/27 16:35:19 hasso 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.52 2004/06/13 22:52:30 njl Exp $
141   * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.14 2008/08/27 16:35:19 hasso 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 #include <sys/malloc.h>
151 #include <sys/module.h>
152 #include <sys/lock.h>
153 #include <sys/rman.h>
154
155 #include "acpi.h"
156 #include "accommon.h"
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 /* Additional params to pass from the probe routine */
232 struct acpi_ec_params {
233     int         glk;
234     int         gpe_bit;
235     ACPI_HANDLE gpe_handle;
236     int         uid;
237 };
238
239 /* Indicate that this device has already been probed via ECDT. */
240 #define DEV_ECDT(x)             (acpi_get_magic(x) == (int)&acpi_ec_devclass)
241
242 /*
243  * Driver softc.
244  */
245 struct acpi_ec_softc {
246     device_t            ec_dev;
247     ACPI_HANDLE         ec_handle;
248     int                 ec_uid;
249     ACPI_HANDLE         ec_gpehandle;
250     UINT8               ec_gpebit;
251     UINT8               ec_csrvalue;
252     
253     int                 ec_data_rid;
254     struct resource     *ec_data_res;
255     bus_space_tag_t     ec_data_tag;
256     bus_space_handle_t  ec_data_handle;
257
258     int                 ec_csr_rid;
259     struct resource     *ec_csr_res;
260     bus_space_tag_t     ec_csr_tag;
261     bus_space_handle_t  ec_csr_handle;
262
263     int                 ec_glk;
264     int                 ec_glkhandle;
265     struct lock         ec_lock;
266 };
267
268 /*
269  * XXX
270  * I couldn't find it in the spec but other implementations also use a
271  * value of 1 ms for the time to acquire global lock.
272  */
273 #define EC_LOCK_TIMEOUT 1000
274
275 /* Default interval in microseconds for the status polling loop. */
276 #define EC_POLL_DELAY   10
277
278 /* Total time in ms spent in the poll loop waiting for a response. */
279 #define EC_POLL_TIMEOUT 100
280
281 #define EVENT_READY(event, status)                      \
282         (((event) == EC_EVENT_OUTPUT_BUFFER_FULL &&     \
283          ((status) & EC_FLAG_OUTPUT_BUFFER) != 0) ||    \
284          ((event) == EC_EVENT_INPUT_BUFFER_EMPTY &&     \
285          ((status) & EC_FLAG_INPUT_BUFFER) == 0))
286
287 static int      ec_poll_timeout = EC_POLL_TIMEOUT;
288 TUNABLE_INT("hw.acpi.ec.poll_timeout", &ec_poll_timeout);
289
290 static __inline ACPI_STATUS
291 EcLock(struct acpi_ec_softc *sc)
292 {
293     ACPI_STATUS status = AE_OK;
294
295     /* Always acquire this EC's mutex. */
296     lockmgr(&sc->ec_lock, LK_EXCLUSIVE|LK_RETRY);
297
298     /* If _GLK is non-zero, also acquire the global lock. */
299     if (sc->ec_glk) {
300         status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
301         if (ACPI_FAILURE(status))
302             lockmgr(&sc->ec_lock, LK_RELEASE);
303     }
304
305     return (status);
306 }
307
308 static __inline void
309 EcUnlock(struct acpi_ec_softc *sc)
310 {
311     if (sc->ec_glk)
312         AcpiReleaseGlobalLock(sc->ec_glkhandle);
313     lockmgr(&sc->ec_lock, LK_RELEASE);
314 }
315
316 static uint32_t         EcGpeHandler(void *Context);
317 static ACPI_STATUS      EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, 
318                                 void *Context, void **return_Context);
319 static ACPI_STATUS      EcSpaceHandler(UINT32 Function,
320                                 ACPI_PHYSICAL_ADDRESS Address,
321                                 UINT32 width, ACPI_INTEGER *Value,
322                                 void *Context, void *RegionContext);
323 static ACPI_STATUS      EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
324 static ACPI_STATUS      EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd);
325 static ACPI_STATUS      EcRead(struct acpi_ec_softc *sc, UINT8 Address,
326                                 UINT8 *Data);
327 static ACPI_STATUS      EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
328                                 UINT8 *Data);
329 static int              acpi_ec_probe(device_t dev);
330 static int              acpi_ec_attach(device_t dev);
331 static int              acpi_ec_read_method(device_t dev, u_int addr,
332                                 ACPI_INTEGER *val, int width);
333 static int              acpi_ec_write_method(device_t dev, u_int addr,
334                                 ACPI_INTEGER val, int width);
335
336 static device_method_t acpi_ec_methods[] = {
337     /* Device interface */
338     DEVMETHOD(device_probe,     acpi_ec_probe),
339     DEVMETHOD(device_attach,    acpi_ec_attach),
340
341     /* Embedded controller interface */
342     DEVMETHOD(acpi_ec_read,     acpi_ec_read_method),
343     DEVMETHOD(acpi_ec_write,    acpi_ec_write_method),
344
345     {0, 0}
346 };
347
348 static driver_t acpi_ec_driver = {
349     "acpi_ec",
350     acpi_ec_methods,
351     sizeof(struct acpi_ec_softc),
352 };
353
354 static devclass_t acpi_ec_devclass;
355 DRIVER_MODULE(acpi_ec, acpi, acpi_ec_driver, acpi_ec_devclass, 0, 0);
356 MODULE_DEPEND(acpi_ec, acpi, 1, 1, 1);
357
358 /*
359  * Look for an ECDT and if we find one, set up default GPE and 
360  * space handlers to catch attempts to access EC space before
361  * we have a real driver instance in place.
362  * TODO: if people report invalid ECDTs, add a tunable to disable them.
363  */
364 void
365 acpi_ec_ecdt_probe(device_t parent)
366 {
367     ACPI_TABLE_ECDT *ecdt;
368     ACPI_STATUS      status;
369     device_t         child;
370     ACPI_HANDLE      h;
371     struct acpi_ec_params *params;
372
373     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
374
375     /* Find and validate the ECDT. */
376     status = AcpiGetTable(ACPI_SIG_ECDT, 1, (ACPI_TABLE_HEADER **)&ecdt);
377     if (ACPI_FAILURE(status) ||
378         ecdt->Control.BitWidth != 8 || ecdt->Data.BitWidth != 8) {
379         return;
380     }
381
382     /* Create the child device with the given unit number. */
383     child = BUS_ADD_CHILD(parent, parent, 0, "acpi_ec", ecdt->Uid);
384     if (child == NULL) {
385         kprintf("%s: can't add child\n", __func__);
386         return;
387     }
388
389     /* Find and save the ACPI handle for this device. */
390     status = AcpiGetHandle(NULL, ecdt->Id, &h);
391     if (ACPI_FAILURE(status)) {
392         device_delete_child(parent, child);
393         kprintf("%s: can't get handle\n", __func__);
394         return;
395     }
396     acpi_set_handle(child, h);
397
398     /* Set the data and CSR register addresses. */
399     bus_set_resource(child, SYS_RES_IOPORT, 0, ecdt->Data.Address,
400         /*count*/1);
401     bus_set_resource(child, SYS_RES_IOPORT, 1, ecdt->Control.Address,
402         /*count*/1);
403
404     /*
405      * Store values for the probe/attach routines to use.  Store the
406      * ECDT GPE bit and set the global lock flag according to _GLK.
407      * Note that it is not perfectly correct to be evaluating a method
408      * before initializing devices, but in practice this function
409      * should be safe to call at this point.
410      */
411     params = kmalloc(sizeof(struct acpi_ec_params), M_TEMP, M_WAITOK | M_ZERO);
412     params->gpe_handle = NULL;
413     params->gpe_bit = ecdt->Gpe;
414     params->uid = ecdt->Uid;
415     acpi_GetInteger(h, "_GLK", &params->glk);
416     acpi_set_private(child, params);
417     acpi_set_magic(child, (int)&acpi_ec_devclass);
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_BUFFER buf;
428     ACPI_HANDLE h;
429     ACPI_OBJECT *obj;
430     ACPI_STATUS status;
431     device_t    peer;
432     char        desc[64];
433     int         ret;
434     struct acpi_ec_params *params;
435
436     /* Check that this is a device and that EC is not disabled. */
437     if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec"))
438         return (ENXIO);
439
440     /*
441      * If probed via ECDT, set description and continue.  Otherwise,
442      * we can access the namespace and make sure this is not a
443      * duplicate probe.
444      */
445     ret = ENXIO;
446     params = NULL;
447     buf.Pointer = NULL;
448     buf.Length = ACPI_ALLOCATE_BUFFER;
449     if (DEV_ECDT(dev)) {
450         params = acpi_get_private(dev);
451         ret = 0;
452     } else if (acpi_MatchHid(acpi_get_handle(dev), "PNP0C09")) {
453         params = kmalloc(sizeof(struct acpi_ec_params), M_TEMP,
454                         M_WAITOK | M_ZERO);
455         h = acpi_get_handle(dev);
456
457         /*
458          * Read the unit ID to check for duplicate attach and the
459          * global lock value to see if we should acquire it when
460          * accessing the EC.
461          */
462         status = acpi_GetInteger(h, "_UID", &params->uid);
463         if (ACPI_FAILURE(status))
464             params->uid = 0;
465         status = acpi_GetInteger(h, "_GLK", &params->glk);
466         if (ACPI_FAILURE(status))
467             params->glk = 0;
468
469         /*
470          * Evaluate the _GPE method to find the GPE bit used by the EC to
471          * signal status (SCI).  If it's a package, it contains a reference
472          * and GPE bit, similar to _PRW.
473          */
474         status = AcpiEvaluateObject(h, "_GPE", NULL, &buf);
475         if (ACPI_FAILURE(status)) {
476             device_printf(dev, "can't evaluate _GPE - %s\n",
477                           AcpiFormatException(status));
478             return (ENXIO);
479         }
480         obj = (ACPI_OBJECT *)buf.Pointer;
481         if (obj == NULL)
482             return (ENXIO);
483
484         switch (obj->Type) {
485         case ACPI_TYPE_INTEGER:
486             params->gpe_handle = NULL;
487             params->gpe_bit = obj->Integer.Value;
488             break;
489         case ACPI_TYPE_PACKAGE:
490             if (!ACPI_PKG_VALID(obj, 2))
491                 goto out;
492             params->gpe_handle =
493                 acpi_GetReference(NULL, &obj->Package.Elements[0]);
494             if (params->gpe_handle == NULL ||
495                 acpi_PkgInt32(obj, 1, &params->gpe_bit) != 0)
496                 goto out;
497             break;
498         default:
499             device_printf(dev, "_GPE has invalid type %d\n", obj->Type);
500             goto out;
501         }
502
503         /* Store the values we got from the namespace for attach. */
504         acpi_set_private(dev, params);
505
506         /*
507          * Check for a duplicate probe.  This can happen when a probe
508          * via ECDT succeeded already.  If this is a duplicate, disable
509          * this device.
510          */
511         peer = devclass_get_device(acpi_ec_devclass, params->uid);
512         if (peer == NULL || !device_is_alive(peer))
513             ret = 0;
514         else
515             device_disable(dev);
516     }
517
518 out:
519     if (ret == 0) {
520         ksnprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s",
521                  params->gpe_bit, (params->glk) ? ", GLK" : "",
522                  DEV_ECDT(dev) ? ", ECDT" : "");
523         device_set_desc_copy(dev, desc);
524     }
525
526     if (ret > 0 && params)
527         kfree(params, M_TEMP);
528     if (buf.Pointer)
529         AcpiOsFree(buf.Pointer);
530     return (ret);
531 }
532
533 static int
534 acpi_ec_attach(device_t dev)
535 {
536     struct acpi_ec_softc        *sc;
537     struct acpi_ec_params       *params;
538     ACPI_STATUS                 Status;
539
540     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
541
542     /* Fetch/initialize softc (assumes softc is pre-zeroed). */
543     sc = device_get_softc(dev);
544     params = acpi_get_private(dev);
545     sc->ec_dev = dev;
546     sc->ec_handle = acpi_get_handle(dev);
547     lockinit(&sc->ec_lock, "eclock", 0, 0);
548
549     /* Retrieve previously probed values via device ivars. */
550     sc->ec_glk = params->glk;
551     sc->ec_gpebit = params->gpe_bit;
552     sc->ec_gpehandle = params->gpe_handle;
553     sc->ec_uid = params->uid;
554     kfree(params, M_TEMP);
555
556     /* Attach bus resources for data and command/status ports. */
557     sc->ec_data_rid = 0;
558     sc->ec_data_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
559                         &sc->ec_data_rid, RF_ACTIVE);
560     if (sc->ec_data_res == NULL) {
561         device_printf(dev, "can't allocate data port\n");
562         goto error;
563     }
564     sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
565     sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);
566
567     sc->ec_csr_rid = 1;
568     sc->ec_csr_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
569                         &sc->ec_csr_rid, RF_ACTIVE);
570     if (sc->ec_csr_res == NULL) {
571         device_printf(dev, "can't allocate command/status port\n");
572         goto error;
573     }
574     sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
575     sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
576
577     /*
578      * Install a handler for this EC's GPE bit.  We want edge-triggered
579      * behavior.
580      */
581     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
582     Status = AcpiInstallGpeHandler(sc->ec_gpehandle, sc->ec_gpebit,
583                 ACPI_GPE_EDGE_TRIGGERED, &EcGpeHandler, sc);
584     if (ACPI_FAILURE(Status)) {
585         device_printf(dev, "can't install GPE handler for %s - %s\n",
586                       acpi_name(sc->ec_handle), AcpiFormatException(Status));
587         goto error;
588     }
589
590     /* 
591      * Install address space handler
592      */
593     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
594     Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
595                 &EcSpaceHandler, &EcSpaceSetup, sc);
596     if (ACPI_FAILURE(Status)) {
597         device_printf(dev, "can't install address space handler for %s - %s\n",
598                       acpi_name(sc->ec_handle), AcpiFormatException(Status));
599         goto error;
600     }
601
602     /* Enable runtime GPEs for the handler. */
603     Status = AcpiSetGpeType(sc->ec_gpehandle, sc->ec_gpebit,
604                             ACPI_GPE_TYPE_RUNTIME);
605     if (ACPI_FAILURE(Status)) {
606         device_printf(dev, "AcpiSetGpeType failed: %s\n",
607                       AcpiFormatException(Status));
608         goto error;
609     }
610     Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_NOT_ISR);
611     if (ACPI_FAILURE(Status)) {
612         device_printf(dev, "AcpiEnableGpe failed: %s\n",
613                       AcpiFormatException(Status));
614         goto error;
615     }
616
617     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
618     return (0);
619
620 error:
621     AcpiRemoveGpeHandler(sc->ec_gpehandle, sc->ec_gpebit, &EcGpeHandler);
622     AcpiRemoveAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
623         EcSpaceHandler);
624     if (sc->ec_csr_res)
625         bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid, 
626                              sc->ec_csr_res);
627     if (sc->ec_data_res)
628         bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
629                              sc->ec_data_res);
630     /* mtx_destroy(&sc->ec_mtx); */
631     return (ENXIO);
632 }
633
634 /* Methods to allow other devices (e.g., smbat) to read/write EC space. */
635 static int
636 acpi_ec_read_method(device_t dev, u_int addr, ACPI_INTEGER *val, int width)
637 {
638     struct acpi_ec_softc *sc;
639     ACPI_STATUS status;
640
641     sc = device_get_softc(dev);
642     status = EcSpaceHandler(ACPI_READ, addr, width * 8, val, sc, NULL);
643     if (ACPI_FAILURE(status))
644         return (ENXIO);
645     return (0);
646 }
647
648 static int
649 acpi_ec_write_method(device_t dev, u_int addr, ACPI_INTEGER val, int width)
650 {
651     struct acpi_ec_softc *sc;
652     ACPI_STATUS status;
653
654     sc = device_get_softc(dev);
655     status = EcSpaceHandler(ACPI_WRITE, addr, width * 8, &val, sc, NULL);
656     if (ACPI_FAILURE(status))
657         return (ENXIO);
658     return (0);
659 }
660
661 static void
662 EcGpeQueryHandler(void *Context)
663 {
664     struct acpi_ec_softc        *sc = (struct acpi_ec_softc *)Context;
665     UINT8                       Data;
666     ACPI_STATUS                 Status;
667     EC_STATUS                   EcStatus;
668     char                        qxx[5];
669
670     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
671     KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL"));
672
673     Status = EcLock(sc);
674     if (ACPI_FAILURE(Status)) {
675         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
676                     "GpeQuery lock error: %s\n", AcpiFormatException(Status));
677         return;
678     }
679
680     /*
681      * If the EC_SCI bit of the status register is not set, then pass
682      * it along to any potential waiters as it may be an IBE/OBF event.
683      */
684     EcStatus = EC_GET_CSR(sc);
685     if ((EcStatus & EC_EVENT_SCI) == 0) {
686         sc->ec_csrvalue = EcStatus;
687         wakeup(&sc->ec_csrvalue);
688         EcUnlock(sc);
689         goto re_enable;
690     }
691
692     /*
693      * Send a query command to the EC to find out which _Qxx call it
694      * wants to make.  This command clears the SCI bit and also the
695      * interrupt source since we are edge-triggered.
696      */
697     Status = EcCommand(sc, EC_COMMAND_QUERY);
698     if (ACPI_FAILURE(Status)) {
699         EcUnlock(sc);
700         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
701                     "GPE query failed - %s\n", AcpiFormatException(Status));
702         goto re_enable;
703     }
704     Data = EC_GET_DATA(sc);
705     EcUnlock(sc);
706
707     /* Ignore the value for "no outstanding event". (13.3.5) */
708     if (Data == 0)
709         goto re_enable;
710
711     /* Evaluate _Qxx to respond to the controller. */
712     ksprintf(qxx, "_Q%02x", Data);
713     strupr(qxx);
714     Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
715     if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) {
716         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
717                     "evaluation of GPE query method %s failed - %s\n", 
718                     qxx, AcpiFormatException(Status));
719     }
720
721 re_enable:
722     /* Re-enable the GPE event so we'll get future requests. */
723     Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_NOT_ISR);
724     if (ACPI_FAILURE(Status))
725         kprintf("EcGpeQueryHandler: AcpiEnableEvent failed\n");
726 }
727
728 /*
729  * Handle a GPE.  Currently we only handle SCI events as others must
730  * be handled by polling in EcWaitEvent().  This is because some ECs
731  * treat events as level when they should be edge-triggered.
732  */
733 static uint32_t
734 EcGpeHandler(void *Context)
735 {
736     struct acpi_ec_softc *sc = Context;
737     ACPI_STATUS                Status;
738
739     KASSERT(Context != NULL, ("EcGpeHandler called with NULL"));
740
741     /* Disable further GPEs while we handle this one. */
742     AcpiDisableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_ISR);
743
744     /* Schedule the GPE query handler. */
745     Status = AcpiOsExecute(OSL_GPE_HANDLER, EcGpeQueryHandler,
746                 Context);
747     if (ACPI_FAILURE(Status)) {
748         kprintf("Queuing GPE query handler failed.\n");
749         Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit, ACPI_ISR);
750         if (ACPI_FAILURE(Status))
751             kprintf("EcGpeHandler: AcpiEnableEvent failed\n");
752     }
753
754     return (0);
755 }
756
757 static ACPI_STATUS
758 EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
759              void **RegionContext)
760 {
761
762     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
763
764     /*
765      * If deactivating a region, always set the output to NULL.  Otherwise,
766      * just pass the context through.
767      */
768     if (Function == ACPI_REGION_DEACTIVATE)
769         *RegionContext = NULL;
770     else
771         *RegionContext = Context;
772
773     return_ACPI_STATUS (AE_OK);
774 }
775
776 static ACPI_STATUS
777 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
778                ACPI_INTEGER *Value, void *Context, void *RegionContext)
779 {
780     struct acpi_ec_softc        *sc = (struct acpi_ec_softc *)Context;
781     ACPI_STATUS                 Status;
782     UINT8                       EcAddr, EcData;
783     int                         i;
784
785     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
786
787     if (width % 8 != 0 || Value == NULL || Context == NULL)
788         return_ACPI_STATUS (AE_BAD_PARAMETER);
789     if (Address + (width / 8) - 1 > 0xFF)
790         return_ACPI_STATUS (AE_BAD_ADDRESS);
791
792     if (Function == ACPI_READ)
793         *Value = 0;
794     EcAddr = Address;
795     Status = AE_ERROR;
796
797     /* Perform the transaction(s), based on width. */
798     for (i = 0; i < width; i += 8, EcAddr++) {
799         Status = EcLock(sc);
800         if (ACPI_FAILURE(Status))
801             break;
802
803         switch (Function) {
804         case ACPI_READ:
805             Status = EcRead(sc, EcAddr, &EcData);
806             if (ACPI_SUCCESS(Status))
807                 *Value |= ((ACPI_INTEGER)EcData) << i;
808             break;
809         case ACPI_WRITE:
810             EcData = (UINT8)((*Value) >> i);
811             Status = EcWrite(sc, EcAddr, &EcData);
812             break;
813         default:
814             device_printf(sc->ec_dev, "invalid EcSpaceHandler function %d\n",
815                           Function);
816             Status = AE_BAD_PARAMETER;
817             break;
818         }
819         EcUnlock(sc);
820         if (ACPI_FAILURE(Status))
821             break;
822     }
823
824     return_ACPI_STATUS (Status);
825 }
826
827 static ACPI_STATUS
828 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
829 {
830     EC_STATUS   EcStatus;
831     ACPI_STATUS Status;
832     int         count, i, period, retval, slp_ival;
833     static int  EcDbgMaxDelay;
834
835     /* mtx_assert(&sc->ec_mtx, MA_OWNED); */
836     Status = AE_NO_HARDWARE_RESPONSE;
837
838     /* 
839      * Wait for 1 us before checking the CSR.  Testing shows about
840      * 50% of requests complete in 1 us and 90% of them complete
841      * in 5 us or less.
842      */
843     AcpiOsStall(1);
844
845     /*
846      * Poll the EC status register for up to 1 ms in chunks of 10 us
847      * to detect completion of the last command.
848      */
849     for (i = 0; i < 1000 / EC_POLL_DELAY; i++) {
850         EcStatus = EC_GET_CSR(sc);
851         if (EVENT_READY(Event, EcStatus)) {
852             Status = AE_OK;
853             break;
854         }
855         AcpiOsStall(EC_POLL_DELAY);
856     }
857     period = i * EC_POLL_DELAY;
858
859     /*
860      * If we still don't have a response and we're up and running, wait up
861      * to ec_poll_timeout ms for completion, sleeping for chunks of 10 ms.
862      */
863     slp_ival = 0;
864     if (Status != AE_OK) {
865         retval = ENXIO;
866         count = ec_poll_timeout / 10;
867         if (count == 0)
868             count = 1;
869         slp_ival = hz / 100;
870         if (slp_ival == 0)
871             slp_ival = 1;
872         for (i = 0; i < count; i++) {
873             if (retval != 0)
874                 EcStatus = EC_GET_CSR(sc);
875             else
876                 EcStatus = sc->ec_csrvalue;
877             if (EVENT_READY(Event, EcStatus)) {
878                 Status = AE_OK;
879                 break;
880             }
881             if (!cold)
882                 retval = tsleep(&sc->ec_csrvalue, 0, "ecpoll", slp_ival);
883             else
884                 AcpiOsStall(10000);
885         }
886     }
887
888     /* Calculate new delay and print it if it exceeds the max. */
889     if (slp_ival > 0)
890         period += i * 10000;
891     if (period > EcDbgMaxDelay) {
892         EcDbgMaxDelay = period;
893         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
894                     "info: new max delay is %d us\n", period);
895     }
896
897     return (Status);
898 }    
899
900 static ACPI_STATUS
901 EcCommand(struct acpi_ec_softc *sc, EC_COMMAND cmd)
902 {
903     ACPI_STATUS Status;
904     EC_EVENT    Event;
905
906     /*mtx_assert(&sc->ec_mtx, MA_OWNED);*/
907
908     /* Decide what to wait for based on command type. */
909     switch (cmd) {
910     case EC_COMMAND_READ:
911     case EC_COMMAND_WRITE:
912     case EC_COMMAND_BURST_DISABLE:
913         Event = EC_EVENT_INPUT_BUFFER_EMPTY;
914         break;
915     case EC_COMMAND_QUERY:
916     case EC_COMMAND_BURST_ENABLE:
917         Event = EC_EVENT_OUTPUT_BUFFER_FULL;
918         break;
919     default:
920         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
921                     "EcCommand: Invalid command %#x\n", cmd);
922         return (AE_BAD_PARAMETER);
923     }
924
925     /* Run the command and wait for the chosen event. */
926     EC_SET_CSR(sc, cmd);
927     Status = EcWaitEvent(sc, Event);
928     if (ACPI_FAILURE(Status)) {
929         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
930                     "EcCommand: no response to %#x\n", cmd);
931     }
932
933     return (Status);
934 }
935
936 static ACPI_STATUS
937 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
938 {
939     ACPI_STATUS Status;
940
941     /*mtx_assert(&sc->ec_mtx, MA_OWNED);*/
942
943 #ifdef notyet
944     /* If we can't start burst mode, continue anyway. */
945     EcCommand(sc, EC_COMMAND_BURST_ENABLE);
946 #endif
947
948     Status = EcCommand(sc, EC_COMMAND_READ);
949     if (ACPI_FAILURE(Status))
950         return (Status);
951
952     EC_SET_DATA(sc, Address);
953     Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
954     if (ACPI_FAILURE(Status)) {
955         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
956                     "EcRead: Failed waiting for EC to send data.\n");
957         return (Status);
958     }
959
960     *Data = EC_GET_DATA(sc);
961
962 #ifdef notyet
963     if (sc->ec_burstactive) {
964         Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
965         if (ACPI_FAILURE(Status))
966             return (Status);
967     }
968 #endif
969
970     return (AE_OK);
971 }    
972
973 static ACPI_STATUS
974 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
975 {
976     ACPI_STATUS Status;
977
978     /*mtx_assert(&sc->ec_mtx, MA_OWNED);*/
979
980 #ifdef notyet
981     /* If we can't start burst mode, continue anyway. */
982     EcCommand(sc, EC_COMMAND_BURST_ENABLE);
983 #endif
984
985     Status = EcCommand(sc, EC_COMMAND_WRITE);
986     if (ACPI_FAILURE(Status))
987         return (Status);
988
989     EC_SET_DATA(sc, Address);
990     Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
991     if (ACPI_FAILURE(Status)) {
992         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
993                     "EcRead: Failed waiting for EC to process address\n");
994         return (Status);
995     }
996
997     EC_SET_DATA(sc, *Data);
998     Status = EcWaitEvent(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
999     if (ACPI_FAILURE(Status)) {
1000         ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
1001                     "EcWrite: Failed waiting for EC to process data\n");
1002         return (Status);
1003     }
1004
1005 #ifdef notyet
1006     if (sc->ec_burstactive) {
1007         Status = EcCommand(sc, EC_COMMAND_BURST_DISABLE);
1008         if (ACPI_FAILURE(Status))
1009             return (Status);
1010     }
1011 #endif
1012
1013     return (AE_OK);
1014 }