Deleted Added
full compact
acpi_ec.c (107328) acpi_ec.c (116927)
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:

--- 10 unchanged lines hidden (view full) ---

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 *
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:

--- 10 unchanged lines hidden (view full) ---

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: head/sys/dev/acpica/acpi_ec.c 107328 2002-11-27 18:09:20Z iwasaki $
27 * $FreeBSD: head/sys/dev/acpica/acpi_ec.c 116927 2003-06-27 21:57:42Z njl $
28 */
29/******************************************************************************
30 *
31 * 1. Copyright Notice
32 *
33 * Some or all of this work - Copyright (c) 1999, Intel Corp. All rights
34 * reserved.
35 *

--- 203 unchanged lines hidden (view full) ---

239 bus_space_handle_t ec_csr_handle;
240
241 int ec_locked;
242 int ec_lockhandle;
243 int ec_pendquery;
244 int ec_csrvalue;
245};
246
28 */
29/******************************************************************************
30 *
31 * 1. Copyright Notice
32 *
33 * Some or all of this work - Copyright (c) 1999, Intel Corp. All rights
34 * reserved.
35 *

--- 203 unchanged lines hidden (view full) ---

239 bus_space_handle_t ec_csr_handle;
240
241 int ec_locked;
242 int ec_lockhandle;
243 int ec_pendquery;
244 int ec_csrvalue;
245};
246
247static int acpi_ec_event_driven = 0;
247static int acpi_ec_event_driven = 0;
248TUNABLE_INT("hw.acpi.ec.event_driven", &acpi_ec_event_driven);
249
250#define EC_LOCK_TIMEOUT 1000 /* 1ms */
251
252static __inline ACPI_STATUS
253EcLock(struct acpi_ec_softc *sc)
254{
255 ACPI_STATUS status;
256
257 /* XXX ACPI_WAIT_FOREVER is probably a bad idea, what is a better time? */
248TUNABLE_INT("hw.acpi.ec.event_driven", &acpi_ec_event_driven);
249
250#define EC_LOCK_TIMEOUT 1000 /* 1ms */
251
252static __inline ACPI_STATUS
253EcLock(struct acpi_ec_softc *sc)
254{
255 ACPI_STATUS status;
256
257 /* XXX ACPI_WAIT_FOREVER is probably a bad idea, what is a better time? */
258 if (ACPI_SUCCESS(status = AcpiAcquireGlobalLock(ACPI_WAIT_FOREVER, &sc->ec_lockhandle)))
259 (sc)->ec_locked = 1;
258 status = AcpiAcquireGlobalLock(ACPI_WAIT_FOREVER, &sc->ec_lockhandle);
259 if (ACPI_SUCCESS(status))
260 sc->ec_locked = 1;
260
261
261 return(status);
262 return (status);
262}
263
264static __inline void
265EcUnlock(struct acpi_ec_softc *sc)
266{
263}
264
265static __inline void
266EcUnlock(struct acpi_ec_softc *sc)
267{
267 (sc)->ec_locked = 0;
268 sc->ec_locked = 0;
268 AcpiReleaseGlobalLock(sc->ec_lockhandle);
269}
270
271static __inline int
272EcIsLocked(struct acpi_ec_softc *sc)
273{
269 AcpiReleaseGlobalLock(sc->ec_lockhandle);
270}
271
272static __inline int
273EcIsLocked(struct acpi_ec_softc *sc)
274{
274 return((sc)->ec_locked != 0);
275 return (sc->ec_locked != 0);
275}
276
277typedef struct
278{
276}
277
278typedef struct
279{
279 EC_COMMAND Command;
280 UINT8 Address;
281 UINT8 Data;
280 EC_COMMAND Command;
281 UINT8 Address;
282 UINT8 Data;
282} EC_REQUEST;
283
284static void EcGpeHandler(void *Context);
285static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
283} EC_REQUEST;
284
285static void EcGpeHandler(void *Context);
286static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
286 void *Context, void **return_Context);
287static ACPI_STATUS EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width, ACPI_INTEGER *Value,
288 void *Context, void *RegionContext);
289
287 void *Context, void **return_Context);
288static ACPI_STATUS EcSpaceHandler(UINT32 Function,
289 ACPI_PHYSICAL_ADDRESS Address,
290 UINT32 width, ACPI_INTEGER *Value,
291 void *Context, void *RegionContext);
290static ACPI_STATUS EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
291static ACPI_STATUS EcQuery(struct acpi_ec_softc *sc, UINT8 *Data);
292static ACPI_STATUS EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
293static ACPI_STATUS EcQuery(struct acpi_ec_softc *sc, UINT8 *Data);
292static ACPI_STATUS EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest);
293static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data);
294static ACPI_STATUS EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data);
295
294static ACPI_STATUS EcTransaction(struct acpi_ec_softc *sc,
295 EC_REQUEST *EcRequest);
296static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address,
297 UINT8 *Data);
298static ACPI_STATUS EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
299 UINT8 *Data);
296static void acpi_ec_identify(driver_t driver, device_t bus);
297static int acpi_ec_probe(device_t dev);
298static int acpi_ec_attach(device_t dev);
299
300static device_method_t acpi_ec_methods[] = {
301 /* Device interface */
302 DEVMETHOD(device_identify, acpi_ec_identify),
303 DEVMETHOD(device_probe, acpi_ec_probe),

--- 19 unchanged lines hidden (view full) ---

323 * before most other things, this works out OK.
324 */
325static void
326acpi_ec_identify(driver_t driver, device_t bus)
327{
328 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
329
330 /* XXX implement - need an ACPI 2.0 system to test this */
300static void acpi_ec_identify(driver_t driver, device_t bus);
301static int acpi_ec_probe(device_t dev);
302static int acpi_ec_attach(device_t dev);
303
304static device_method_t acpi_ec_methods[] = {
305 /* Device interface */
306 DEVMETHOD(device_identify, acpi_ec_identify),
307 DEVMETHOD(device_probe, acpi_ec_probe),

--- 19 unchanged lines hidden (view full) ---

327 * before most other things, this works out OK.
328 */
329static void
330acpi_ec_identify(driver_t driver, device_t bus)
331{
332 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
333
334 /* XXX implement - need an ACPI 2.0 system to test this */
331
332 return_VOID;
333}
334
335/*
336 * We could setup resources in the probe routine in order to have them printed
337 * when the device is attached.
338 */
339static int
340acpi_ec_probe(device_t dev)
341{
342
335}
336
337/*
338 * We could setup resources in the probe routine in order to have them printed
339 * when the device is attached.
340 */
341static int
342acpi_ec_probe(device_t dev)
343{
344
343 if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) &&
344 !acpi_disabled("ec") &&
345 if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("ec") &&
345 acpi_MatchHid(dev, "PNP0C09")) {
346
347 /*
348 * Set device description
349 */
350 device_set_desc(dev, "embedded controller");
346 acpi_MatchHid(dev, "PNP0C09")) {
347
348 /*
349 * Set device description
350 */
351 device_set_desc(dev, "embedded controller");
351
352 return(0);
352 return (0);
353 }
353 }
354 return(ENXIO);
354 return (ENXIO);
355}
356
357static int
358acpi_ec_attach(device_t dev)
359{
360 struct acpi_ec_softc *sc;
361 ACPI_STATUS Status;
355}
356
357static int
358acpi_ec_attach(device_t dev)
359{
360 struct acpi_ec_softc *sc;
361 ACPI_STATUS Status;
362 int errval = 0;
362 int errval = 0;
363
364 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
365
366 /*
367 * Fetch/initialise softc
368 */
369 sc = device_get_softc(dev);
370 bzero(sc, sizeof(*sc));
371 sc->ec_dev = dev;
372 sc->ec_handle = acpi_get_handle(dev);
373
374 /*
375 * Attach bus resources
376 */
377 sc->ec_data_rid = 0;
363
364 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
365
366 /*
367 * Fetch/initialise softc
368 */
369 sc = device_get_softc(dev);
370 bzero(sc, sizeof(*sc));
371 sc->ec_dev = dev;
372 sc->ec_handle = acpi_get_handle(dev);
373
374 /*
375 * Attach bus resources
376 */
377 sc->ec_data_rid = 0;
378 if ((sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT, &sc->ec_data_rid,
379 0, ~0, 1, RF_ACTIVE)) == NULL) {
378 sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
379 &sc->ec_data_rid, 0, ~0, 1, RF_ACTIVE);
380 if (sc->ec_data_res == NULL) {
380 device_printf(dev, "can't allocate data port\n");
381 errval = ENXIO;
382 goto out;
383 }
384 sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
385 sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);
386
387 sc->ec_csr_rid = 1;
381 device_printf(dev, "can't allocate data port\n");
382 errval = ENXIO;
383 goto out;
384 }
385 sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
386 sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);
387
388 sc->ec_csr_rid = 1;
388 if ((sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT, &sc->ec_csr_rid,
389 0, ~0, 1, RF_ACTIVE)) == NULL) {
389 sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT,
390 &sc->ec_csr_rid, 0, ~0, 1, RF_ACTIVE);
391 if (sc->ec_csr_res == NULL) {
390 device_printf(dev, "can't allocate command/status port\n");
391 errval = ENXIO;
392 goto out;
393 }
394 sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
395 sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
396
397 /*
398 * Install GPE handler
399 *
400 * Evaluate the _GPE method to find the GPE bit used by the EC to signal
401 * status (SCI).
402 */
403 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE\n"));
392 device_printf(dev, "can't allocate command/status port\n");
393 errval = ENXIO;
394 goto out;
395 }
396 sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
397 sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);
398
399 /*
400 * Install GPE handler
401 *
402 * Evaluate the _GPE method to find the GPE bit used by the EC to signal
403 * status (SCI).
404 */
405 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE\n"));
404 if (ACPI_FAILURE(Status = acpi_EvaluateInteger(sc->ec_handle, "_GPE", &sc->ec_gpebit))) {
405 device_printf(dev, "can't evaluate _GPE - %s\n", AcpiFormatException(Status));
406 errval =ENXIO;
406 Status = acpi_EvaluateInteger(sc->ec_handle, "_GPE", &sc->ec_gpebit);
407 if (ACPI_FAILURE(Status)) {
408 device_printf(dev, "can't evaluate _GPE - %s\n",
409 AcpiFormatException(Status));
410 errval = ENXIO;
407 goto out;
408 }
409
410 /*
411 * Install a handler for this EC's GPE bit. Note that EC SCIs are
412 * treated as both edge- and level-triggered interrupts; in other words
413 * we clear the status bit immediately after getting an EC-SCI, then
414 * again after we're done processing the event. This guarantees that
415 * events we cause while performing a transaction (e.g. IBE/OBF) get
416 * cleared before re-enabling the GPE.
417 */
411 goto out;
412 }
413
414 /*
415 * Install a handler for this EC's GPE bit. Note that EC SCIs are
416 * treated as both edge- and level-triggered interrupts; in other words
417 * we clear the status bit immediately after getting an EC-SCI, then
418 * again after we're done processing the event. This guarantees that
419 * events we cause while performing a transaction (e.g. IBE/OBF) get
420 * cleared before re-enabling the GPE.
421 */
418 if (ACPI_FAILURE(Status = AcpiInstallGpeHandler(sc->ec_gpebit,
419 ACPI_EVENT_LEVEL_TRIGGERED |
420 ACPI_EVENT_EDGE_TRIGGERED,
421 EcGpeHandler, sc))) {
422 Status = AcpiInstallGpeHandler(sc->ec_gpebit,
423 ACPI_EVENT_LEVEL_TRIGGERED | ACPI_EVENT_EDGE_TRIGGERED,
424 EcGpeHandler, sc);
425 if (ACPI_FAILURE(Status)) {
422 device_printf(dev, "can't install GPE handler for %s - %s\n",
423 acpi_name(sc->ec_handle), AcpiFormatException(Status));
424 errval = ENXIO;
425 goto out;
426 }
427
428 /*
429 * Install address space handler
430 */
431 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
426 device_printf(dev, "can't install GPE handler for %s - %s\n",
427 acpi_name(sc->ec_handle), AcpiFormatException(Status));
428 errval = ENXIO;
429 goto out;
430 }
431
432 /*
433 * Install address space handler
434 */
435 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
432 if (ACPI_FAILURE(Status = AcpiInstallAddressSpaceHandler(sc->ec_handle,
433 ACPI_ADR_SPACE_EC,
434 EcSpaceHandler,
435 EcSpaceSetup,
436 sc))) {
436 Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
437 EcSpaceHandler, EcSpaceSetup, sc);
438 if (ACPI_FAILURE(Status)) {
437 device_printf(dev, "can't install address space handler for %s - %s\n",
438 acpi_name(sc->ec_handle), AcpiFormatException(Status));
439 panic("very suck");
440 errval = ENXIO;
441 goto out;
442 }
443 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attach complete\n"));
439 device_printf(dev, "can't install address space handler for %s - %s\n",
440 acpi_name(sc->ec_handle), AcpiFormatException(Status));
441 panic("very suck");
442 errval = ENXIO;
443 goto out;
444 }
445 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attach complete\n"));
444 return_VALUE(0);
446 return_VALUE (0);
447
445 out:
448 out:
446 if(sc->ec_csr_res)
449 if (sc->ec_csr_res)
447 bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
448 sc->ec_csr_res);
450 bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
451 sc->ec_csr_res);
449 if(sc->ec_data_res)
452 if (sc->ec_data_res)
450 bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
451 sc->ec_data_res);
453 bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
454 sc->ec_data_res);
452 return_VALUE(errval);
455 return_VALUE (errval);
453}
454
455static void
456EcGpeQueryHandler(void *Context)
457{
458 struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context;
459 UINT8 Data;
460 ACPI_STATUS Status;

--- 9 unchanged lines hidden (view full) ---

470 * Bail out if the EC_SCI bit of the status register is not set.
471 * Note that this function should only be called when
472 * this bit is set (polling is used to detect IBE/OBF events).
473 *
474 * It is safe to do this without locking the controller, as it's
475 * OK to call EcQuery when there's no data ready; in the worst
476 * case we should just find nothing waiting for us and bail.
477 */
456}
457
458static void
459EcGpeQueryHandler(void *Context)
460{
461 struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context;
462 UINT8 Data;
463 ACPI_STATUS Status;

--- 9 unchanged lines hidden (view full) ---

473 * Bail out if the EC_SCI bit of the status register is not set.
474 * Note that this function should only be called when
475 * this bit is set (polling is used to detect IBE/OBF events).
476 *
477 * It is safe to do this without locking the controller, as it's
478 * OK to call EcQuery when there's no data ready; in the worst
479 * case we should just find nothing waiting for us and bail.
480 */
478 if (!(EC_GET_CSR(sc) & EC_EVENT_SCI))
481 if ((EC_GET_CSR(sc) & EC_EVENT_SCI) == 0)
479 break;
480
481 /*
482 * Find out why the EC is signalling us
483 */
484 Status = EcQuery(sc, &Data);
485
486 /*

--- 12 unchanged lines hidden (view full) ---

499 strupr(qxx);
500 Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
501 /*
502 * Ignore spurious query requests.
503 */
504 if (ACPI_FAILURE(Status) && (Data != 0 || Status != AE_NOT_FOUND)) {
505 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
506 "evaluation of GPE query method %s failed - %s\n",
482 break;
483
484 /*
485 * Find out why the EC is signalling us
486 */
487 Status = EcQuery(sc, &Data);
488
489 /*

--- 12 unchanged lines hidden (view full) ---

502 strupr(qxx);
503 Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL);
504 /*
505 * Ignore spurious query requests.
506 */
507 if (ACPI_FAILURE(Status) && (Data != 0 || Status != AE_NOT_FOUND)) {
508 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
509 "evaluation of GPE query method %s failed - %s\n",
507 qxx, AcpiFormatException(Status));
510 qxx, AcpiFormatException(Status));
508 }
509 }
510 /* I know I request Level trigger cleanup */
511 if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE)))
511 }
512 }
513 /* I know I request Level trigger cleanup */
514 if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE)))
512 printf("EcGpeQueryHandler:ClearEvent Failed\n");
515 printf("EcGpeQueryHandler:ClearEvent Failed\n");
513 if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0)))
516 if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0)))
514 printf("EcGpeQueryHandler:EnableEvent Failed\n");
515 return_VOID;
517 printf("EcGpeQueryHandler:EnableEvent Failed\n");
516}
517
518/*
519 * Handle a GPE sent to us.
520 */
521static void
522EcGpeHandler(void *Context)
523{
524 struct acpi_ec_softc *sc = Context;
525 int csrvalue;
526
527 /*
528 * If EC is locked, the intr must process EcRead/Write wait only.
529 * Query request must be pending.
530 */
518}
519
520/*
521 * Handle a GPE sent to us.
522 */
523static void
524EcGpeHandler(void *Context)
525{
526 struct acpi_ec_softc *sc = Context;
527 int csrvalue;
528
529 /*
530 * If EC is locked, the intr must process EcRead/Write wait only.
531 * Query request must be pending.
532 */
531 if (EcIsLocked(sc)){
533 if (EcIsLocked(sc)) {
532 csrvalue = EC_GET_CSR(sc);
533 if (csrvalue & EC_EVENT_SCI)
534 sc->ec_pendquery = 1;
534 csrvalue = EC_GET_CSR(sc);
535 if (csrvalue & EC_EVENT_SCI)
536 sc->ec_pendquery = 1;
535 if ((csrvalue & EC_FLAG_OUTPUT_BUFFER)
536 || !(csrvalue & EC_FLAG_INPUT_BUFFER)) {
537 if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 ||
538 (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) {
537 sc->ec_csrvalue = csrvalue;
539 sc->ec_csrvalue = csrvalue;
538 wakeup((void *)&sc->ec_csrvalue);
540 wakeup(&sc->ec_csrvalue);
539 }
541 }
540 }else{
542 } else {
541 /* Queue GpeQuery Handler */
542 if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
543 EcGpeQueryHandler,Context))) {
544 printf("QueryHandler Queuing Failed\n");
545 }
546 }
543 /* Queue GpeQuery Handler */
544 if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
545 EcGpeQueryHandler,Context))) {
546 printf("QueryHandler Queuing Failed\n");
547 }
548 }
547 return;
548}
549
550static ACPI_STATUS
549}
550
551static ACPI_STATUS
551EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context, void **RegionContext)
552EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
553 void **RegionContext)
552{
553
554 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
555
556 /*
557 * Just pass the context through, there's nothing to do here.
558 */
559 *RegionContext = Context;
560
554{
555
556 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
557
558 /*
559 * Just pass the context through, there's nothing to do here.
560 */
561 *RegionContext = Context;
562
561 return_ACPI_STATUS(AE_OK);
563 return_ACPI_STATUS (AE_OK);
562}
563
564static ACPI_STATUS
564}
565
566static ACPI_STATUS
565EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width, ACPI_INTEGER *Value,
566 void *Context, void *RegionContext)
567EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
568 ACPI_INTEGER *Value, void *Context, void *RegionContext)
567{
568 struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context;
569 ACPI_STATUS Status = AE_OK;
570 EC_REQUEST EcRequest;
571 int i;
572
573 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
574
569{
570 struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context;
571 ACPI_STATUS Status = AE_OK;
572 EC_REQUEST EcRequest;
573 int i;
574
575 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);
576
575 if ((Address > 0xFF) || (width % 8 != 0) || (Value == NULL) || (Context == NULL))
576 return_ACPI_STATUS(AE_BAD_PARAMETER);
577 if (Address > 0xFF || width % 8 != 0 || Value == NULL || Context == NULL)
578 return_ACPI_STATUS (AE_BAD_PARAMETER);
577
578 switch (Function) {
579 case ACPI_READ:
580 EcRequest.Command = EC_COMMAND_READ;
581 EcRequest.Address = Address;
582 (*Value) = 0;
583 break;
579
580 switch (Function) {
581 case ACPI_READ:
582 EcRequest.Command = EC_COMMAND_READ;
583 EcRequest.Address = Address;
584 (*Value) = 0;
585 break;
584
585 case ACPI_WRITE:
586 EcRequest.Command = EC_COMMAND_WRITE;
587 EcRequest.Address = Address;
588 break;
586 case ACPI_WRITE:
587 EcRequest.Command = EC_COMMAND_WRITE;
588 EcRequest.Address = Address;
589 break;
589
590 default:
590 default:
591 device_printf(sc->ec_dev, "invalid Address Space function %d\n", Function);
592 return_ACPI_STATUS(AE_BAD_PARAMETER);
591 device_printf(sc->ec_dev, "invalid Address Space function %d\n",
592 Function);
593 return_ACPI_STATUS (AE_BAD_PARAMETER);
593 }
594
595 /*
596 * Perform the transaction.
597 */
598 for (i = 0; i < width; i += 8) {
599 if (Function == ACPI_READ)
600 EcRequest.Data = 0;
601 else
602 EcRequest.Data = (UINT8)((*Value) >> i);
594 }
595
596 /*
597 * Perform the transaction.
598 */
599 for (i = 0; i < width; i += 8) {
600 if (Function == ACPI_READ)
601 EcRequest.Data = 0;
602 else
603 EcRequest.Data = (UINT8)((*Value) >> i);
603 if (ACPI_FAILURE(Status = EcTransaction(sc, &EcRequest)))
604 Status = EcTransaction(sc, &EcRequest);
605 if (ACPI_FAILURE(Status))
604 break;
606 break;
605 (*Value) |= (ACPI_INTEGER)EcRequest.Data << i;
607 *Value |= (ACPI_INTEGER)EcRequest.Data << i;
606 if (++EcRequest.Address == 0)
608 if (++EcRequest.Address == 0)
607 return_ACPI_STATUS(AE_BAD_PARAMETER);
609 return_ACPI_STATUS (AE_BAD_PARAMETER);
608 }
610 }
609 return_ACPI_STATUS(Status);
611 return_ACPI_STATUS (Status);
610}
611
612/*
613 * Wait for an event interrupt for a specific condition.
614 */
615static ACPI_STATUS
616EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event)
617{
618 EC_STATUS EcStatus;
619 int i;
620
621 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Event);
622
623 /* XXX this should test whether interrupts are available some other way */
624 if (cold || acpi_ec_event_driven)
612}
613
614/*
615 * Wait for an event interrupt for a specific condition.
616 */
617static ACPI_STATUS
618EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event)
619{
620 EC_STATUS EcStatus;
621 int i;
622
623 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Event);
624
625 /* XXX this should test whether interrupts are available some other way */
626 if (cold || acpi_ec_event_driven)
625 return_ACPI_STATUS(EcWaitEvent(sc, Event));
627 return_ACPI_STATUS (EcWaitEvent(sc, Event));
626
628
627 if (!EcIsLocked(sc))
629 if (!EcIsLocked(sc)) {
628 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
629 "EcWaitEventIntr called without EC lock!\n");
630 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
631 "EcWaitEventIntr called without EC lock!\n");
632 }
630
631 EcStatus = EC_GET_CSR(sc);
632
633 /* XXX waiting too long? */
633
634 EcStatus = EC_GET_CSR(sc);
635
636 /* XXX waiting too long? */
634 for(i = 0; i < 10; i++){
637 for (i = 0; i < 10; i++) {
635 /*
636 * Check EC status against the desired event.
637 */
638 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
638 /*
639 * Check EC status against the desired event.
640 */
641 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
639 (EcStatus & EC_FLAG_OUTPUT_BUFFER))
640 return_ACPI_STATUS(AE_OK);
642 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
643 return_ACPI_STATUS (AE_OK);
641
642 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) &&
644
645 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) &&
643 !(EcStatus & EC_FLAG_INPUT_BUFFER))
644 return_ACPI_STATUS(AE_OK);
646 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
647 return_ACPI_STATUS (AE_OK);
645
646 sc->ec_csrvalue = 0;
648
649 sc->ec_csrvalue = 0;
647 if (ACPI_MSLEEP(&sc->ec_csrvalue, &acpi_mutex, PZERO, "EcWait", 1) != EWOULDBLOCK){
650 /* XXX sleeping with Acpi Global Lock held */
651 if (tsleep(&sc->ec_csrvalue, PZERO, "EcWait", 1) != EWOULDBLOCK) {
648 EcStatus = sc->ec_csrvalue;
652 EcStatus = sc->ec_csrvalue;
649 }else{
653 } else {
650 EcStatus = EC_GET_CSR(sc);
651 }
652 }
654 EcStatus = EC_GET_CSR(sc);
655 }
656 }
653 return_ACPI_STATUS(AE_ERROR);
657 return_ACPI_STATUS (AE_ERROR);
654}
655
656static ACPI_STATUS
657EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
658{
659 EC_STATUS EcStatus;
660 UINT32 i = 0;
661
658}
659
660static ACPI_STATUS
661EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
662{
663 EC_STATUS EcStatus;
664 UINT32 i = 0;
665
662 if (!EcIsLocked(sc))
666 if (!EcIsLocked(sc)) {
663 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
664 "EcWaitEvent called without EC lock!\n");
667 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
668 "EcWaitEvent called without EC lock!\n");
669 }
665
666 /*
667 * Stall 1us:
668 * ----------
669 * Stall for 1 microsecond before reading the status register
670 * for the first time. This allows the EC to set the IBF/OBF
671 * bit to its proper state.
672 *

--- 6 unchanged lines hidden (view full) ---

679 * Wait For Event:
680 * ---------------
681 * Poll the EC status register to detect completion of the last
682 * command. Wait up to 10ms (in 10us chunks) for this to occur.
683 */
684 for (i = 0; i < 1000; i++) {
685 EcStatus = EC_GET_CSR(sc);
686
670
671 /*
672 * Stall 1us:
673 * ----------
674 * Stall for 1 microsecond before reading the status register
675 * for the first time. This allows the EC to set the IBF/OBF
676 * bit to its proper state.
677 *

--- 6 unchanged lines hidden (view full) ---

684 * Wait For Event:
685 * ---------------
686 * Poll the EC status register to detect completion of the last
687 * command. Wait up to 10ms (in 10us chunks) for this to occur.
688 */
689 for (i = 0; i < 1000; i++) {
690 EcStatus = EC_GET_CSR(sc);
691
687 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
688 (EcStatus & EC_FLAG_OUTPUT_BUFFER))
689 return(AE_OK);
692 if (Event == EC_EVENT_OUTPUT_BUFFER_FULL &&
693 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
694 return (AE_OK);
690
695
691 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) &&
692 !(EcStatus & EC_FLAG_INPUT_BUFFER))
696 if (Event == EC_EVENT_INPUT_BUFFER_EMPTY &&
697 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
693 return(AE_OK);
694
695 AcpiOsStall(10);
696 }
697
698 return(AE_OK);
699
700 AcpiOsStall(10);
701 }
702
698 return(AE_ERROR);
703 return (AE_ERROR);
699}
700
701static ACPI_STATUS
702EcQuery(struct acpi_ec_softc *sc, UINT8 *Data)
703{
704 ACPI_STATUS Status;
705
704}
705
706static ACPI_STATUS
707EcQuery(struct acpi_ec_softc *sc, UINT8 *Data)
708{
709 ACPI_STATUS Status;
710
706 if (ACPI_FAILURE(Status = EcLock(sc)))
707 return(Status);
711 Status = EcLock(sc);
712 if (ACPI_FAILURE(Status))
713 return (Status);
708
709 EC_SET_CSR(sc, EC_COMMAND_QUERY);
714
715 EC_SET_CSR(sc, EC_COMMAND_QUERY);
710 if (ACPI_SUCCESS(Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL)))
716 Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
717 if (ACPI_SUCCESS(Status))
711 *Data = EC_GET_DATA(sc);
712
713 EcUnlock(sc);
714
718 *Data = EC_GET_DATA(sc);
719
720 EcUnlock(sc);
721
715 if (ACPI_FAILURE(Status))
722 if (ACPI_FAILURE(Status)) {
716 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
717 "timeout waiting for EC to respond to EC_COMMAND_QUERY\n");
723 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
724 "timeout waiting for EC to respond to EC_COMMAND_QUERY\n");
718 return(Status);
725 }
726 return (Status);
719}
720
721static ACPI_STATUS
722EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
723{
724 ACPI_STATUS Status;
725
727}
728
729static ACPI_STATUS
730EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
731{
732 ACPI_STATUS Status;
733
726 /*
727 * Lock the EC
728 */
729 if (ACPI_FAILURE(Status = EcLock(sc)))
730 return(Status);
734 Status = EcLock(sc);
735 if (ACPI_FAILURE(Status))
736 return (Status);
731
732 /*
733 * Perform the transaction.
734 */
735 switch (EcRequest->Command) {
736 case EC_COMMAND_READ:
737
738 /*
739 * Perform the transaction.
740 */
741 switch (EcRequest->Command) {
742 case EC_COMMAND_READ:
737 Status = EcRead(sc, EcRequest->Address, &(EcRequest->Data));
743 Status = EcRead(sc, EcRequest->Address, &EcRequest->Data);
738 break;
744 break;
739
740 case EC_COMMAND_WRITE:
745 case EC_COMMAND_WRITE:
741 Status = EcWrite(sc, EcRequest->Address, &(EcRequest->Data));
746 Status = EcWrite(sc, EcRequest->Address, &EcRequest->Data);
742 break;
747 break;
743
744 default:
745 Status = AE_SUPPORT;
746 break;
747 }
748
748 default:
749 Status = AE_SUPPORT;
750 break;
751 }
752
749 /*
750 * Unlock the EC
751 */
752 EcUnlock(sc);
753
754 /*
755 * Clear & Re-Enable the EC GPE:
756 * -----------------------------
757 * 'Consume' any EC GPE events that we generated while performing
758 * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't
759 * have an adverse affect on outstanding EC-SCI's, as the source
760 * (EC-SCI) will still be high and thus should trigger the GPE
761 * immediately after we re-enabling it.
762 */
753 EcUnlock(sc);
754
755 /*
756 * Clear & Re-Enable the EC GPE:
757 * -----------------------------
758 * 'Consume' any EC GPE events that we generated while performing
759 * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't
760 * have an adverse affect on outstanding EC-SCI's, as the source
761 * (EC-SCI) will still be high and thus should trigger the GPE
762 * immediately after we re-enabling it.
763 */
763 if (sc->ec_pendquery){
764 if (sc->ec_pendquery) {
764 if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
765 EcGpeQueryHandler, sc)))
766 printf("Pend Query Queuing Failed\n");
767 sc->ec_pendquery = 0;
768 }
769
765 if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
766 EcGpeQueryHandler, sc)))
767 printf("Pend Query Queuing Failed\n");
768 sc->ec_pendquery = 0;
769 }
770
770 if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE)))
771 if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE))) {
771 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
772 "EcRequest: Unable to clear the EC GPE.\n");
772 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
773 "EcRequest: Unable to clear the EC GPE.\n");
773 if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0)))
774 }
775 if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0))) {
774 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
775 "EcRequest: Unable to re-enable the EC GPE.\n");
776 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
777 "EcRequest: Unable to re-enable the EC GPE.\n");
778 }
776
779
777 return(Status);
780 return (Status);
778}
779
780
781static ACPI_STATUS
782EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
783{
784 ACPI_STATUS Status;
785
781}
782
783
784static ACPI_STATUS
785EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
786{
787 ACPI_STATUS Status;
788
786 if (!EcIsLocked(sc))
789 if (!EcIsLocked(sc)) {
787 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
788 "EcRead called without EC lock!\n");
790 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
791 "EcRead called without EC lock!\n");
792 }
789
790 /*EcBurstEnable(EmbeddedController);*/
791
792 EC_SET_CSR(sc, EC_COMMAND_READ);
793
794 /*EcBurstEnable(EmbeddedController);*/
795
796 EC_SET_CSR(sc, EC_COMMAND_READ);
793 if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY))) {
797 Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
798 if (ACPI_FAILURE(Status)) {
794 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
795 "EcRead: Failed waiting for EC to process read command.\n");
799 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
800 "EcRead: Failed waiting for EC to process read command.\n");
796 return(Status);
801 return (Status);
797 }
798
799 EC_SET_DATA(sc, Address);
802 }
803
804 EC_SET_DATA(sc, Address);
800 if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL))) {
805 Status = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
806 if (ACPI_FAILURE(Status)) {
801 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
802 "EcRead: Failed waiting for EC to send data.\n");
807 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
808 "EcRead: Failed waiting for EC to send data.\n");
803 return(Status);
809 return (Status);
804 }
805
810 }
811
806 (*Data) = EC_GET_DATA(sc);
812 *Data = EC_GET_DATA(sc);
807
808 /*EcBurstDisable(EmbeddedController);*/
809
813
814 /*EcBurstDisable(EmbeddedController);*/
815
810 return(AE_OK);
816 return (AE_OK);
811}
812
813static ACPI_STATUS
814EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
815{
816 ACPI_STATUS Status;
817
817}
818
819static ACPI_STATUS
820EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
821{
822 ACPI_STATUS Status;
823
818 if (!EcIsLocked(sc))
824 if (!EcIsLocked(sc)) {
819 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
820 "EcWrite called without EC lock!\n");
825 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
826 "EcWrite called without EC lock!\n");
827 }
821
822 /*EcBurstEnable(EmbeddedController);*/
823
824 EC_SET_CSR(sc, EC_COMMAND_WRITE);
828
829 /*EcBurstEnable(EmbeddedController);*/
830
831 EC_SET_CSR(sc, EC_COMMAND_WRITE);
825 if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY))) {
832 Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
833 if (ACPI_FAILURE(Status)) {
826 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
827 "EcWrite: Failed waiting for EC to process write command.\n");
834 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
835 "EcWrite: Failed waiting for EC to process write command.\n");
828 return(Status);
836 return (Status);
829 }
830
831 EC_SET_DATA(sc, Address);
837 }
838
839 EC_SET_DATA(sc, Address);
832 if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY))) {
840 Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
841 if (ACPI_FAILURE(Status)) {
833 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
834 "EcRead: Failed waiting for EC to process address.\n");
842 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
843 "EcRead: Failed waiting for EC to process address.\n");
835 return(Status);
844 return (Status);
836 }
837
838 EC_SET_DATA(sc, *Data);
845 }
846
847 EC_SET_DATA(sc, *Data);
839 if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY))) {
848 Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY);
849 if (ACPI_FAILURE(Status)) {
840 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
841 "EcWrite: Failed waiting for EC to process data.\n");
850 ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
851 "EcWrite: Failed waiting for EC to process data.\n");
842 return(Status);
852 return (Status);
843 }
844
845 /*EcBurstDisable(EmbeddedController);*/
846
853 }
854
855 /*EcBurstDisable(EmbeddedController);*/
856
847 return(AE_OK);
857 return (AE_OK);
848}
858}