Example #1
0
static ACPI_STATUS
EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
{
    ACPI_STATUS	Status;

    /*
     * Lock the EC
     */
    if (ACPI_FAILURE(Status = EcLock(sc)))
	return(Status);

    /*
     * Perform the transaction.
     */
    switch (EcRequest->Command) {
    case EC_COMMAND_READ:
	Status = EcRead(sc, EcRequest->Address, &(EcRequest->Data));
	break;

    case EC_COMMAND_WRITE:
	Status = EcWrite(sc, EcRequest->Address, &(EcRequest->Data));
	break;

    default:
	Status = AE_SUPPORT;
	break;
    }

    /*
     * Unlock the EC
     */
    EcUnlock(sc);
    
    /*
     * Clear & Re-Enable the EC GPE:
     * -----------------------------
     * 'Consume' any EC GPE events that we generated while performing
     * the transaction (e.g. IBF/OBF).	Clearing the GPE here shouldn't
     * have an adverse affect on outstanding EC-SCI's, as the source
     * (EC-SCI) will still be high and thus should trigger the GPE
     * immediately after we re-enabling it.
     */
    if (sc->ec_pendquery){
	if (ACPI_FAILURE(AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
						 EcGpeQueryHandler, sc)))
	    printf("Pend Query Queuing Failed\n");
	sc->ec_pendquery = 0;
    }

    if (ACPI_FAILURE(AcpiClearEvent(sc->ec_gpebit, ACPI_EVENT_GPE)))
	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
	    "EcRequest: Unable to clear the EC GPE.\n");
    if (ACPI_FAILURE(AcpiEnableEvent(sc->ec_gpebit, ACPI_EVENT_GPE, 0)))
	ACPI_VPRINT(sc->ec_dev, acpi_device_get_parent_softc(sc->ec_dev),
	    "EcRequest: Unable to re-enable the EC GPE.\n");

    return(Status);
}
Example #2
0
static ACPI_STATUS
EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
{
	ACPI_STATUS Status;

	if ((Status = EcLock(sc)) != AE_OK)
		return (Status);

	/*
	 * Perform the transaction.
	 */
	switch (EcRequest->Command) {
	case EC_COMMAND_READ:
		Status = EcRead(sc, EcRequest->Address, &(EcRequest->Data));
		break;

	case EC_COMMAND_WRITE:
		Status = EcWrite(sc, EcRequest->Address, &(EcRequest->Data));
		break;

	default:
		Status = AE_SUPPORT;
		break;
	}

	/*
	 * Clear & Re-Enable the EC GPE:
	 * -----------------------------
	 * 'Consume' any EC GPE events that we generated while performing
	 * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't
	 * have an adverse affect on outstanding EC-SCI's, as the source
	 * (EC-SCI) will still be high and thus should trigger the GPE
	 * immediately after we re-enabling it.
	 */
	if (sc->sc_flags & EC_F_PENDQUERY) {
		if (AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
		    EcGpeQueryHandler, sc) != AE_OK)
			printf("%s: unable to queue pending query\n",
			    sc->sc_dev.dv_xname);
		sc->sc_flags &= ~EC_F_PENDQUERY;
	}

	if (AcpiClearEvent(sc->sc_gpebit, ACPI_EVENT_GPE) != AE_OK)
		printf("%s: EcRequest: unable to clear EC GPE\n",
		    sc->sc_dev.dv_xname);
	if (AcpiEnableEvent(sc->sc_gpebit, ACPI_EVENT_GPE) != AE_OK)
		printf("%s: EcRequest: unable to reenable EC GPE\n",
		    sc->sc_dev.dv_xname);

	EcUnlock(sc);

	return(Status);
}
Example #3
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);
}
Example #4
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_STATUS			Status;
    UINT8			*EcData;
    UINT8			EcAddr;
    int				bytes, i;

    ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, (UINT32)Address);

    if (Width % 8 != 0 || Value == NULL || Context == NULL)
	return_ACPI_STATUS (AE_BAD_PARAMETER);
    bytes = Width / 8;
    if (Address + bytes - 1 > 0xFF)
	return_ACPI_STATUS (AE_BAD_ADDRESS);

    if (Function == ACPI_READ)
	*Value = 0;
    EcAddr = Address;
    EcData = (UINT8 *)Value;

    /*
     * 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)) {
	    CTR0(KTR_ACPI, "ec running gpe handler directly");
	    EcGpeQueryHandler(sc);
	}
    }

    /* Serialize with EcGpeQueryHandler() at transaction granularity. */
    Status = EcLock(sc);
    if (ACPI_FAILURE(Status))
	return_ACPI_STATUS (Status);

    /* Perform the transaction(s), based on Width. */
    for (i = 0; i < bytes; i++, EcAddr++, EcData++) {
	switch (Function) {
	case ACPI_READ:
	    Status = EcRead(sc, EcAddr, EcData);
	    break;
	case ACPI_WRITE:
	    Status = EcWrite(sc, EcAddr, *EcData);
	    break;
	default:
	    device_printf(sc->ec_dev, "invalid EcSpaceHandler function %d\n",
			  Function);
	    Status = AE_BAD_PARAMETER;
	    break;
	}
	if (ACPI_FAILURE(Status))
	    break;
    }

    EcUnlock(sc);
    return_ACPI_STATUS (Status);
}