📄 ec.c
字号:
/* * ec.c - Embedded controller support * * Copyright (C) 2000 Andrew Henroid * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <linux/kernel.h>#include <linux/acpi.h>#include <linux/slab.h>#include "acpi.h"#include "driver.h"#include "ec.h"#define _COMPONENT OS_DEPENDENT MODULE_NAME ("ec")#define ACPI_EC_HID "PNP0C09"enum{ ACPI_EC_SMI = 0x40, ACPI_EC_SCI = 0x20, ACPI_EC_BURST = 0x10, ACPI_EC_CMD = 0x08, ACPI_EC_IBF = 0x02, ACPI_EC_OBF = 0x01};enum{ ACPI_EC_READ = 0x80, ACPI_EC_WRITE = 0x81, ACPI_EC_BURST_ENABLE = 0x82, ACPI_EC_BURST_DISABLE = 0x83, ACPI_EC_QUERY = 0x84,};typedef struct{ ACPI_HANDLE acpi_handle; u32 gpe_bit; ACPI_IO_ADDRESS status_port; ACPI_IO_ADDRESS data_port; u32 need_global_lock;} ec_context_t;typedef struct { ec_context_t *ec; u8 data;} EC_QUERY_DATA;static char object_name[] = {'_', 'Q', '0', '0', '\0'};static char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};static ACPI_STATUSec_io_wait ( ec_context_t *ec, EC_EVENT wait_event){ EC_STATUS ec_status = 0; UINT32 i = 100; if (!ec || ((wait_event != EC_EVENT_OUTPUT_BUFFER_FULL) && (wait_event != EC_EVENT_INPUT_BUFFER_EMPTY))) return(AE_BAD_PARAMETER); /* * Wait for Event: * --------------- * Poll the EC status register waiting for the event to occur. * Note that we'll wait a maximum of 1ms in 10us chunks. */ switch (wait_event) { case EC_EVENT_OUTPUT_BUFFER_FULL: do { ec_status = acpi_os_in8(ec->status_port); if (ec_status & EC_FLAG_OUTPUT_BUFFER) return(AE_OK); acpi_os_sleep_usec(10); } while (--i>0); break; case EC_EVENT_INPUT_BUFFER_EMPTY: do { ec_status = acpi_os_in8(ec->status_port); if (!(ec_status & EC_FLAG_INPUT_BUFFER)) return(AE_OK); acpi_os_sleep_usec(10); } while (--i>0); break; } return(AE_TIME);}static ACPI_STATUSec_io_read ( ec_context_t *ec, ACPI_IO_ADDRESS io_port, UINT8 *data, EC_EVENT wait_event){ ACPI_STATUS status = AE_OK; if (!ec || !data) return(AE_BAD_PARAMETER); *data = acpi_os_in8(io_port); if (wait_event) status = ec_io_wait(ec, wait_event); return(status);}static ACPI_STATUSec_io_write ( ec_context_t *ec, ACPI_IO_ADDRESS io_port, UINT8 data, EC_EVENT wait_event){ ACPI_STATUS status = AE_OK; if (!ec) return(AE_BAD_PARAMETER); acpi_os_out8(io_port, data); if (wait_event) status = ec_io_wait(ec, wait_event); return(status);}static ACPI_STATUSec_read ( ec_context_t *ec, UINT8 address, UINT8 *data){ ACPI_STATUS status = AE_OK; FUNCTION_TRACE("ec_read"); if (!ec || !data) return_ACPI_STATUS(AE_BAD_PARAMETER); status = ec_io_write(ec, ec->status_port, EC_COMMAND_READ, EC_EVENT_INPUT_BUFFER_EMPTY); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Unable to send 'read command' to EC.\n")); return_ACPI_STATUS(status); } status = ec_io_write(ec, ec->data_port, address, EC_EVENT_OUTPUT_BUFFER_FULL); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Unable to send 'read address' to EC.\n")); return_ACPI_STATUS(status); } status = ec_io_read(ec, ec->data_port, data, EC_EVENT_NONE); DEBUG_PRINT(ACPI_INFO, ("Read data[0x%02x] from address[0x%02x] on ec.\n", (*data), address)); return_ACPI_STATUS(status);}static ACPI_STATUSec_write ( ec_context_t *ec, UINT8 address, UINT8 data){ ACPI_STATUS status = AE_OK; FUNCTION_TRACE("ec_write"); if (!ec) return_ACPI_STATUS(AE_BAD_PARAMETER); status = ec_io_write(ec, ec->status_port, EC_COMMAND_WRITE, EC_EVENT_INPUT_BUFFER_EMPTY); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write command' to EC.\n")); return_ACPI_STATUS(status); } status = ec_io_write(ec, ec->data_port, address, EC_EVENT_INPUT_BUFFER_EMPTY); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write address' to EC.\n")); return_ACPI_STATUS(status); } status = ec_io_write(ec, ec->data_port, data, EC_EVENT_INPUT_BUFFER_EMPTY); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Unable to send 'write data' to EC.\n")); return_ACPI_STATUS(status); } DEBUG_PRINT(ACPI_INFO, ("Wrote data[0x%02x] to address[0x%02x] on ec.\n", data, address)); return_ACPI_STATUS(status);}static ACPI_STATUSec_transaction ( ec_context_t *ec, EC_REQUEST *request){ ACPI_STATUS status = AE_OK; FUNCTION_TRACE("ec_transaction"); if (!ec || !request) return_ACPI_STATUS(AE_BAD_PARAMETER); /* * Obtaining semaphore (mutex) to serialize all EC transactions. */ /* DEBUG_PRINT(ACPI_INFO, ("Calling acpi_os_wait_semaphore(%p, 1, %d)\n", ec->mutex, EC_DEFAULT_TIMEOUT)); status = acpi_os_wait_semaphore(ec->mutex, 1, EC_DEFAULT_TIMEOUT); if (ACPI_FAILURE(status)) return_ACPI_STATUS(status); */ /* * Perform the transaction. */ switch (request->command) { case EC_COMMAND_READ: status = ec_read(ec, request->address, &(request->data)); break; case EC_COMMAND_WRITE: status = ec_write(ec, request->address, request->data); break; default: status = AE_SUPPORT; break; } /* * Signal the semaphore (mutex) to indicate transaction completion. */ /* DEBUG_PRINT(ACPI_INFO, ("Calling acpi_os_signal_semaphore(%p, 1)\n", ec->mutex)); acpi_os_signal_semaphore(ec->mutex, 1); */ return_ACPI_STATUS(status);}static ACPI_STATUS ec_space_setup ( ACPI_HANDLE region_handle, UINT32 function, void *handler_context, void **return_context){ // TODO: What is this function for? /* * The ec object is in the handler context and is needed * when calling the ec_space_handler. */ *return_context = handler_context; return AE_OK;}static voidec_query_handler ( void *context){ ACPI_STATUS status = AE_OK; EC_QUERY_DATA *ec_q = (EC_QUERY_DATA*)context; FUNCTION_TRACE("ec_query_handler"); if (!ec_q || !ec_q->ec) { DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) context.\n")); return_VOID; } /* * Evaluate _Qxx: * -------------- * Evaluate corresponding _Qxx method. Note that a zero query * value indicates a spurious EC_SCI (no such thing as _Q00).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -