static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) { ACPI_STATUS Status; if (!EcIsLocked(sc)) ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev), "EcRead called without EC lock!\n"); /*EcBurstEnable(EmbeddedController);*/ EC_SET_CSR(sc, EC_COMMAND_READ); if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY))) { ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev), "EcRead: Failed waiting for EC to process read command.\n"); return(Status); } EC_SET_DATA(sc, Address); if (ACPI_FAILURE(Status = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL))) { ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev), "EcRead: Failed waiting for EC to send data.\n"); return(Status); } (*Data) = EC_GET_DATA(sc); /*EcBurstDisable(EmbeddedController);*/ return(AE_OK); }
static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) { ACPI_STATUS status; u_int gen_count; int retry; ACPI_SERIAL_ASSERT(ec); for (retry = 0; retry < 2; retry++) { status = EcCommand(sc, EC_COMMAND_READ); if (ACPI_FAILURE(status)) return (status); gen_count = sc->ec_gencount; EC_SET_DATA(sc, Address); status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL, gen_count); if (ACPI_FAILURE(status)) { if (EcCheckStatus(sc, "retr_check", EC_EVENT_INPUT_BUFFER_EMPTY) == AE_OK) continue; else break; } *Data = EC_GET_DATA(sc); return (AE_OK); } device_printf(sc->ec_dev, "EcRead: failed waiting to get data\n"); return (status); }
static void EcGpeQueryHandler(void *Context) { struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context; UINT8 Data; ACPI_STATUS Status; char qxx[5]; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL")); /* Serialize user access with EcSpaceHandler(). */ Status = EcLock(sc); if (ACPI_FAILURE(Status)) { device_printf(sc->ec_dev, "GpeQuery lock error: %s\n", AcpiFormatException(Status)); return; } /* * Send a query command to the EC to find out which _Qxx call it * wants to make. This command clears the SCI bit and also the * interrupt source since we are edge-triggered. To prevent the GPE * that may arise from running the query from causing another query * to be queued, we clear the pending flag only after running it. */ Status = EcCommand(sc, EC_COMMAND_QUERY); sc->ec_sci_pend = FALSE; if (ACPI_FAILURE(Status)) { EcUnlock(sc); device_printf(sc->ec_dev, "GPE query failed: %s\n", AcpiFormatException(Status)); return; } Data = EC_GET_DATA(sc); /* * We have to unlock before running the _Qxx method below since that * method may attempt to read/write from EC address space, causing * recursive acquisition of the lock. */ EcUnlock(sc); /* Ignore the value for "no outstanding event". (13.3.5) */ CTR2(KTR_ACPI, "ec query ok,%s running _Q%02X", Data ? "" : " not", Data); if (Data == 0) return; /* Evaluate _Qxx to respond to the controller. */ snprintf(qxx, sizeof(qxx), "_Q%02X", Data); AcpiUtStrupr(qxx); Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL); if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) { device_printf(sc->ec_dev, "evaluation of query method %s failed: %s\n", qxx, AcpiFormatException(Status)); } }
static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) { ACPI_STATUS status; UINT8 data; u_int gen_count; ACPI_SERIAL_ASSERT(ec); CTR1(KTR_ACPI, "ec read from %#x", Address); /* If we can't start burst mode, continue anyway. */ status = EcCommand(sc, EC_COMMAND_BURST_ENABLE); if (status == AE_OK) { data = EC_GET_DATA(sc); if (data == EC_BURST_ACK) { CTR0(KTR_ACPI, "ec burst enabled"); sc->ec_burstactive = TRUE; } } status = EcCommand(sc, EC_COMMAND_READ); if (ACPI_FAILURE(status)) return (status); gen_count = sc->ec_gencount; EC_SET_DATA(sc, Address); status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL, gen_count); if (ACPI_FAILURE(status)) { device_printf(sc->ec_dev, "EcRead: failed waiting to get data\n"); return (status); } *Data = EC_GET_DATA(sc); if (sc->ec_burstactive) { sc->ec_burstactive = FALSE; status = EcCommand(sc, EC_COMMAND_BURST_DISABLE); if (ACPI_FAILURE(status)) return (status); CTR0(KTR_ACPI, "ec disabled burst ok"); } return (AE_OK); }
static ACPI_STATUS EcQuery(struct acpi_ec_softc *sc, UINT8 *Data) { ACPI_STATUS Status; if (ACPI_FAILURE(Status = EcLock(sc))) return(Status); EC_SET_CSR(sc, EC_COMMAND_QUERY); if (ACPI_SUCCESS(Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL))) *Data = EC_GET_DATA(sc); EcUnlock(sc); if (ACPI_FAILURE(Status)) ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev), "timeout waiting for EC to respond to EC_COMMAND_QUERY\n"); return(Status); }
static ACPI_STATUS EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 Width, UINT64 *Value, void *Context, void *RegionContext) { struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context; ACPI_PHYSICAL_ADDRESS EcAddr; UINT8 *EcData; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address); if (Function != ACPI_READ && Function != ACPI_WRITE) return_ACPI_STATUS (AE_BAD_PARAMETER); if (Width % 8 != 0 || Value == NULL || Context == NULL) return_ACPI_STATUS (AE_BAD_PARAMETER); if (Address + Width / 8 > 256) return_ACPI_STATUS (AE_BAD_ADDRESS); /* * If booting, check if we need to run the query handler. If so, we * we call it directly here since our thread taskq is not active yet. */ if (cold || rebooting || sc->ec_suspending) { if ((EC_GET_CSR(sc) & EC_EVENT_SCI)) { EcGpeQueryHandler(sc); } } /* Serialize with EcGpeQueryHandler() at transaction granularity. */ Status = EcLock(sc); if (ACPI_FAILURE(Status)) return_ACPI_STATUS (Status); /* If we can't start burst mode, continue anyway. */ Status = EcCommand(sc, EC_COMMAND_BURST_ENABLE); if (ACPI_SUCCESS(Status)) { if (EC_GET_DATA(sc) == EC_BURST_ACK) { sc->ec_burstactive = TRUE; } } /* Perform the transaction(s), based on Width. */ EcAddr = Address; EcData = (UINT8 *)Value; if (Function == ACPI_READ) *Value = 0; do { switch (Function) { case ACPI_READ: Status = EcRead(sc, EcAddr, EcData); break; case ACPI_WRITE: Status = EcWrite(sc, EcAddr, *EcData); break; } if (ACPI_FAILURE(Status)) break; EcAddr++; EcData++; } while (EcAddr < Address + Width / 8); if (sc->ec_burstactive) { sc->ec_burstactive = FALSE; if (ACPI_SUCCESS(EcCommand(sc, EC_COMMAND_BURST_DISABLE))) { } } EcUnlock(sc); return_ACPI_STATUS (Status); }
static void EcGpeQueryHandler(void *Context) { struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context; UINT8 Data; ACPI_STATUS Status; int retry, sci_enqueued; char qxx[5]; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); KASSERT(Context != NULL, ("EcGpeQueryHandler called with NULL")); /* Serialize user access with EcSpaceHandler(). */ Status = EcLock(sc); if (ACPI_FAILURE(Status)) { device_printf(sc->ec_dev, "GpeQuery lock error: %s\n", AcpiFormatException(Status)); return; } /* * Send a query command to the EC to find out which _Qxx call it * wants to make. This command clears the SCI bit and also the * interrupt source since we are edge-triggered. To prevent the GPE * that may arise from running the query from causing another query * to be queued, we clear the pending flag only after running it. */ sci_enqueued = sc->ec_sci_pend; for (retry = 0; retry < 2; retry++) { Status = EcCommand(sc, EC_COMMAND_QUERY); if (ACPI_SUCCESS(Status)) break; if (EcCheckStatus(sc, "retr_check", EC_EVENT_INPUT_BUFFER_EMPTY) == AE_OK) continue; else break; } sc->ec_sci_pend = FALSE; if (ACPI_FAILURE(Status)) { EcUnlock(sc); device_printf(sc->ec_dev, "GPE query failed: %s\n", AcpiFormatException(Status)); return; } Data = EC_GET_DATA(sc); /* * We have to unlock before running the _Qxx method below since that * method may attempt to read/write from EC address space, causing * recursive acquisition of the lock. */ EcUnlock(sc); /* Ignore the value for "no outstanding event". (13.3.5) */ if (Data == 0) return; /* Evaluate _Qxx to respond to the controller. */ ksnprintf(qxx, sizeof(qxx), "_Q%02X", Data); AcpiUtStrupr(qxx); Status = AcpiEvaluateObject(sc->ec_handle, qxx, NULL, NULL); if (ACPI_FAILURE(Status) && Status != AE_NOT_FOUND) { device_printf(sc->ec_dev, "evaluation of query method %s failed: %s\n", qxx, AcpiFormatException(Status)); } /* Reenable runtime GPE if its execution was deferred. */ if (sci_enqueued) { Status = AcpiFinishGpe(sc->ec_gpehandle, sc->ec_gpebit); if (ACPI_FAILURE(Status)) device_printf(sc->ec_dev, "reenabling runtime GPE failed: %s\n", AcpiFormatException(Status)); } }