Пример #1
0
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);
}    
Пример #2
0
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);
}
Пример #3
0
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));
    }
}
Пример #4
0
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);
}
Пример #5
0
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);
}    
Пример #6
0
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);
}
Пример #7
0
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));
    }
}