/*- * Copyright (c) 2009 Clemens Zeidler * Copyright (c) 2003-2007 Nate Lawson * Copyright (c) 2000 Michael Smith * Copyright (c) 2000 BSDi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef ACPI_EMBEDDED_CONTROLLER_H #define ACPI_EMBEDDED_CONTROLLER_H #include #include #include #include #include #include extern "C" { # include "acpi.h" # include "accommon.h" # include "acnamesp.h" # include "actypes.h" # include "ACPIPrivate.h" } // #define TRACE_EMBEDDED_CONTROLLER #ifdef TRACE_EMBEDDED_CONTROLLER # define TRACE(x...) dprintf("EC: " x) #else # define TRACE(x...) #endif #define ERROR(x...) dprintf("EC: " x) typedef uint8 EC_COMMAND; #define EC_COMMAND_UNKNOWN ((EC_COMMAND) 0x00) #define EC_COMMAND_READ ((EC_COMMAND) 0x80) #define EC_COMMAND_WRITE ((EC_COMMAND) 0x81) #define EC_COMMAND_BURST_ENABLE ((EC_COMMAND) 0x82) #define EC_COMMAND_BURST_DISABLE ((EC_COMMAND) 0x83) #define EC_COMMAND_QUERY ((EC_COMMAND) 0x84) /* * EC_STATUS: * ---------- * The encoding of the EC status register is illustrated below. * Note that a set bit (1) indicates the property is TRUE * (e.g. if bit 0 is set then the output buffer is full). * +-+-+-+-+-+-+-+-+ * |7|6|5|4|3|2|1|0| * +-+-+-+-+-+-+-+-+ * | | | | | | | | * | | | | | | | +- Output Buffer Full? * | | | | | | +--- Input Buffer Full? * | | | | | +----- * | | | | +------- Data Register is Command Byte? * | | | +--------- Burst Mode Enabled? * | | +----------- SCI Event? * | +------------- SMI Event? * +--------------- * */ typedef uint8 EC_STATUS; #define EC_FLAG_OUTPUT_BUFFER ((EC_STATUS) 0x01) #define EC_FLAG_INPUT_BUFFER ((EC_STATUS) 0x02) #define EC_FLAG_DATA_IS_CMD ((EC_STATUS) 0x08) #define EC_FLAG_BURST_MODE ((EC_STATUS) 0x10) /* * EC_EVENT: * --------- */ typedef uint8 EC_EVENT; #define EC_EVENT_UNKNOWN ((EC_EVENT) 0x00) #define EC_EVENT_OUTPUT_BUFFER_FULL ((EC_EVENT) 0x01) #define EC_EVENT_INPUT_BUFFER_EMPTY ((EC_EVENT) 0x02) #define EC_EVENT_SCI ((EC_EVENT) 0x20) #define EC_EVENT_SMI ((EC_EVENT) 0x40) /* Data byte returned after burst enable indicating it was successful. */ #define EC_BURST_ACK 0x90 /* * Register access primitives */ #define EC_GET_DATA(sc) \ bus_space_read_1((sc)->ec_data_pci_address) #define EC_SET_DATA(sc, v) \ bus_space_write_1((sc)->ec_data_pci_address, (v)) #define EC_GET_CSR(sc) \ bus_space_read_1((sc)->ec_csr_pci_address) #define EC_SET_CSR(sc, v) \ bus_space_write_1((sc)->ec_csr_pci_address, (v)) #define ACPI_PKG_VALID(pkg, size) \ ((pkg) != NULL && (pkg)->object_type == ACPI_TYPE_PACKAGE && \ (pkg)->package.count >= (size)) /* * Driver cookie. */ struct acpi_ec_cookie { device_node* ec_dev; acpi_module_info* ec_acpi_module; acpi_device_module_info* ec_acpi; acpi_device ec_handle; int ec_uid; acpi_handle ec_gpehandle; uint8 ec_gpebit; int ec_data_pci_address; int ec_csr_pci_address; int ec_glk; uint32 ec_glkhandle; mutex ec_lock; int ec_burstactive; int32 ec_sci_pending; int32 ec_gencount; ConditionVariable ec_condition_var; int ec_suspending; }; /* * XXX njl * I couldn't find it in the spec but other implementations also use a * value of 1 ms for the time to acquire global lock. */ #define EC_LOCK_TIMEOUT 1000 /* Default delay in microseconds between each run of the status polling loop. */ #define EC_POLL_DELAY 50 /* Total time in ms spent waiting for a response from EC. */ #define EC_TIMEOUT 750 #define EVENT_READY(event, status) \ (((event) == EC_EVENT_OUTPUT_BUFFER_FULL && \ ((status) & EC_FLAG_OUTPUT_BUFFER) != 0) || \ ((event) == EC_EVENT_INPUT_BUFFER_EMPTY && \ ((status) & EC_FLAG_INPUT_BUFFER) == 0)) static bool ec_burst_mode = true; static bool ec_polled_mode = false; static int ec_timeout = EC_TIMEOUT; static status_t EcLock(struct acpi_ec_cookie *sc) { /* If _GLK is non-zero, acquire the global lock. */ if (sc->ec_glk) { status_t status = sc->ec_acpi_module->acquire_global_lock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle); if (status != B_OK) return status; } return mutex_lock(&sc->ec_lock); } static void EcUnlock(struct acpi_ec_cookie *sc) { mutex_unlock(&sc->ec_lock); if (sc->ec_glk) sc->ec_acpi_module->release_global_lock(sc->ec_glkhandle); } static uint32 EcGpeHandler(acpi_handle gpeDevice, uint32 gpeNumber, void *context); static acpi_status EcSpaceSetup(acpi_handle region, uint32 function, void *context, void **return_Context); static acpi_status EcSpaceHandler(uint32 function, acpi_physical_address address, uint32 width, int *value, void *context, void *regionContext); static acpi_status EcWaitEvent(struct acpi_ec_cookie *sc, EC_EVENT event, int32 gen_count); static acpi_status EcCommand(struct acpi_ec_cookie *sc, EC_COMMAND cmd); static acpi_status EcRead(struct acpi_ec_cookie *sc, uint8 address, uint8 *readData); static acpi_status EcWrite(struct acpi_ec_cookie *sc, uint8 address, uint8 writeData); #endif // ACPI_EMBEDDED_CONTROLLER_H