|
From: Andy P. <at...@us...> - 2002-04-09 15:08:36
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/acpi/ospm/ec
In directory usw-pr-cvs1:/tmp/cvs-serv13840/acpi/ospm/ec
Added Files:
Makefile ec_osl.c ecgpe.c ecmain.c ecspace.c ectransx.c
Log Message:
synch 2.4.15 commit 17
--- NEW FILE ---
O_TARGET := ospm_$(notdir $(CURDIR)).o
obj-m := $(O_TARGET)
EXTRA_CFLAGS += $(ACPI_CFLAGS)
obj-y := $(patsubst %.c,%.o,$(wildcard *.c))
include $(TOPDIR)/Rules.make
--- NEW FILE ---
/*****************************************************************************
*
* Module Name: ec_osl.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* 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/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <acpi.h>
#include <bm.h>
#include "ec.h"
MODULE_AUTHOR("Andrew Grover");
MODULE_DESCRIPTION("ACPI Component Architecture (CA) - Embedded Controller Driver");
extern struct proc_dir_entry *bm_proc_root;
/****************************************************************************
*
* FUNCTION: ec_osl_init
*
* PARAMETERS: <none>
*
* RETURN: 0: Success
*
* DESCRIPTION: Module initialization.
*
****************************************************************************/
static int __init
ec_osl_init (void)
{
acpi_status status = AE_OK;
/* abort if no busmgr */
if (!bm_proc_root)
return -ENODEV;
status = ec_initialize();
return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
}
/****************************************************************************
*
* FUNCTION: ec_osl_cleanup
*
* PARAMETERS: <none>
*
* RETURN: <none>
*
* DESCRIPTION: Module cleanup.
*
****************************************************************************/
static void __exit
ec_osl_cleanup(void)
{
ec_terminate();
return;
}
module_init(ec_osl_init);
module_exit(ec_osl_cleanup);
--- NEW FILE ---
/*****************************************************************************
*
* Module Name: ecgpe.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* 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 <acpi.h>
#include "ec.h"
#define _COMPONENT ACPI_EC
MODULE_NAME ("ecgpe")
/****************************************************************************
*
* FUNCTION: ec_query_handler
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
void
ec_query_handler (
void *context)
{
EC_CONTEXT *ec = (EC_CONTEXT*)context;
static char object_name[5] = {'_','Q','0','0','\0'};
const char hex[] = {'0','1','2','3','4','5','6','7','8',
'9','A','B','C','D','E','F'};
FUNCTION_TRACE("ec_query_handler");
if (!ec) {
ACPI_DEBUG_PRINT ((ACPI_DB_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).
*/
object_name[2] = hex[((ec->query_data >> 4) & 0x0F)];
object_name[3] = hex[(ec->query_data & 0x0F)];
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Evaluating [%s] for ec [%02x].\n", object_name, ec->device_handle));
bm_evaluate_object(ec->acpi_handle, object_name, NULL, NULL);
return_VOID;
}
/****************************************************************************
*
* FUNCTION: ec_gpe_handler
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
void
ec_gpe_handler (
void *context)
{
acpi_status status = AE_OK;
EC_CONTEXT *ec = (EC_CONTEXT*)context;
EC_STATUS ec_status = 0;
FUNCTION_TRACE("ec_gpe_handler");
if (!ec) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
return_VOID;
}
/* TBD: synchronize w/ transaction (ectransx). */
/*
* EC_SCI?
* -------
* Check the EC_SCI bit to see if this is an EC_SCI event. If not (e.g.
* OBF/IBE) just return, as we already poll to detect these events.
*/
acpi_os_read_port(ec->status_port, &ec_status, 8);
if (!(ec_status & EC_FLAG_SCI)) {
return_VOID;
}
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "EC_SCI event detected on ec [%02x] - running query.\n", ec->device_handle));
/*
* Run Query:
* ----------
* Query the EC to find out which _Qxx method we need to evaluate.
* Note that successful completion of the query causes the EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
status = ec_io_write(ec, ec->command_port, EC_COMMAND_QUERY,
EC_EVENT_OUTPUT_BUFFER_FULL);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'query command' to EC.\n"));
return_VOID;
}
status = ec_io_read(ec, ec->data_port, &(ec->query_data),
EC_EVENT_NONE);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Error reading query data.\n"));
return_VOID;
}
/* TBD: un-synchronize w/ transaction (ectransx). */
/*
* Spurious EC_SCI?
* ----------------
*/
if (!ec->query_data) {
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Spurious EC SCI detected.\n"));
return_VOID;
}
/*
* Defer _Qxx Execution:
* ---------------------
* Can't evaluate this method now 'cause we're at interrupt-level.
*/
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
ec_query_handler, ec);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to defer _Qxx method evaluation.\n"));
return_VOID;
}
return_VOID;
}
/****************************************************************************
*
* FUNCTION: ec_install_gpe_handler
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_install_gpe_handler (
EC_CONTEXT *ec)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_install_gpe_handler");
if (!ec) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Evaluate _GPE:
* --------------
* Evaluate the "_GPE" object (required) to find out which GPE bit
* is used by this EC to signal events (SCIs).
*/
status = bm_evaluate_simple_integer(ec->acpi_handle,
"_GPE", &(ec->gpe_bit));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Install GPE Handler:
* --------------------
* Install a handler for this EC's GPE bit.
*/
status = acpi_install_gpe_handler(ec->gpe_bit, ACPI_EVENT_EDGE_TRIGGERED,
&ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "acpi_install_gpe_handler() failed for GPE bit [%02x] with status [%08x].\n", ec->gpe_bit, status));
ec->gpe_bit = EC_GPE_UNKNOWN;
return_ACPI_STATUS(status);
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_remove_gpe_handler
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_remove_gpe_handler (
EC_CONTEXT *ec)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_remove_gpe_handler");
if (!ec) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_remove_gpe_handler(ec->gpe_bit, &ec_gpe_handler);
return_ACPI_STATUS(status);
}
--- NEW FILE ---
/*****************************************************************************
*
* Module Name: ecmain.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* 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 <acpi.h>
#include "ec.h"
#define _COMPONENT ACPI_EC
MODULE_NAME ("ecmain")
/****************************************************************************
* Internal Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: ec_print
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION: Prints out information on a specific ec.
*
****************************************************************************/
void
ec_print (
EC_CONTEXT *ec)
{
#ifdef ACPI_DEBUG
acpi_buffer buffer;
#endif /*ACPI_DEBUG*/
PROC_NAME("ec_print");
if (!ec) {
return;
}
acpi_os_printf("EC: found, GPE %d\n", ec->gpe_bit);
#ifdef ACPI_DEBUG
buffer.length = 256;
buffer.pointer = acpi_os_callocate(buffer.length);
if (!buffer.pointer) {
return;
}
/*
* Get the full pathname for this ACPI object.
*/
acpi_get_name(ec->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
/*
* Print out basic thermal zone information.
*/
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n"));
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Embedded_controller[%02x]:[%p] %s\n", ec->device_handle, ec->acpi_handle, (char*)buffer.pointer));
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| gpe_bit[%02x] status/command_port[%02x] data_port[%02x]\n", ec->gpe_bit, ec->status_port, ec->data_port));
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n"));
acpi_os_free(buffer.pointer);
#endif /*ACPI_DEBUG*/
return;
}
/****************************************************************************
*
* FUNCTION: ec_get_port_values
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION: Evaluate _CRS to get the current resources (I/O port
* addresses) for this EC.
*
****************************************************************************/
acpi_status
ec_get_port_values(
EC_CONTEXT *ec)
{
acpi_status status = AE_OK;
acpi_buffer buffer;
acpi_resource *resource = NULL;
FUNCTION_TRACE("ec_get_port_values");
if (!ec) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
buffer.length = 0;
buffer.pointer = NULL;
status = acpi_get_current_resources(ec->acpi_handle, &buffer);
if (status != AE_BUFFER_OVERFLOW) {
return_ACPI_STATUS(status);
}
buffer.pointer = acpi_os_callocate(buffer.length);
if (!buffer.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
status = acpi_get_current_resources(ec->acpi_handle, &buffer);
if (ACPI_FAILURE(status)) {
goto end;
}
resource = (acpi_resource *) buffer.pointer;
ec->data_port = resource->data.io.min_base_address;
resource = NEXT_RESOURCE(resource);
ec->status_port = ec->command_port =
resource->data.io.min_base_address;
end:
acpi_os_free(buffer.pointer);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_add_device
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_add_device(
BM_HANDLE device_handle,
void **context)
{
acpi_status status = AE_OK;
BM_DEVICE *device = NULL;
EC_CONTEXT *ec = NULL;
u8 gpe_handler = FALSE;
u8 space_handler = FALSE;
FUNCTION_TRACE("ec_add_device");
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding EC device [%02x].\n", device_handle));
if (!context || *context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Get information on this device.
*/
status = bm_get_device_info(device_handle, &device);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Allocate a new EC_CONTEXT structure.
*/
ec = acpi_os_callocate(sizeof(EC_CONTEXT));
if (!ec) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
ec->device_handle = device->handle;
ec->acpi_handle = device->acpi_handle;
/*
* Get the I/O port addresses for the command/status and data ports.
*/
status = ec_get_port_values(ec);
if (ACPI_FAILURE(status)) {
goto end;
}
/*
* See if we need to obtain the global lock for EC transactions.
*/
status = bm_evaluate_simple_integer(ec->acpi_handle, "_GLK",
&ec->use_global_lock);
if (status == AE_NOT_FOUND) {
ec->use_global_lock = 0;
}
else if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "EC _GLK failed\n"));
goto end;
}
/*
* Install a handler for servicing this EC's GPE.
*/
status = ec_install_gpe_handler(ec);
if (ACPI_FAILURE(status)) {
goto end;
}
else {
gpe_handler = TRUE;
}
/*
* Install a handler for servicing this EC's address space.
*/
status = ec_install_space_handler(ec);
if (ACPI_FAILURE(status)) {
goto end;
}
else {
space_handler = TRUE;
}
/*
* Create a semaphore to serialize EC transactions.
*/
status = acpi_os_create_semaphore(1,1, &(ec->mutex));
if (ACPI_FAILURE(status)) {
goto end;
}
/*
* Context now contains information specific to this EC. Note
* that we'll get this pointer back on every ec_request() and
* ec_notify().
*/
*context = ec;
ec_print(ec);
end:
if (ACPI_FAILURE(status)) {
if (gpe_handler) {
ec_remove_gpe_handler(ec);
}
if (space_handler) {
ec_remove_space_handler(ec);
}
if (ec->mutex) {
acpi_os_delete_semaphore(ec->mutex);
}
acpi_os_free(ec);
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_remove_device
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_remove_device(
void **context)
{
acpi_status status = AE_OK;
EC_CONTEXT *ec = NULL;
FUNCTION_TRACE("ec_remove_device");
if (!context || !*context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
ec = (EC_CONTEXT*)*context;
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing EC device [%02x].\n", ec->device_handle));
ec_remove_space_handler(ec);
ec_remove_gpe_handler(ec);
if (ec->mutex) {
acpi_os_delete_semaphore(ec->mutex);
}
acpi_os_free(ec);
*context = NULL;
return_ACPI_STATUS(status);
}
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: ec_initialize
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_initialize (void)
{
acpi_status status = AE_OK;
BM_DEVICE_ID criteria;
BM_DRIVER driver;
FUNCTION_TRACE("ec_initialize");
MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
MEMSET(&driver, 0, sizeof(BM_DRIVER));
/*
* Register driver for AC Adapter devices.
*/
MEMCPY(criteria.hid, EC_HID_EC, sizeof(EC_HID_EC));
driver.notify = &ec_notify;
driver.request = &ec_request;
status = bm_register_driver(&criteria, &driver);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_terminate
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_terminate(void)
{
acpi_status status = AE_OK;
BM_DEVICE_ID criteria;
BM_DRIVER driver;
FUNCTION_TRACE("ec_terminate");
MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
MEMSET(&driver, 0, sizeof(BM_DRIVER));
/*
* Unregister driver for AC Adapter devices.
*/
MEMCPY(criteria.hid, EC_HID_EC, sizeof(EC_HID_EC));
driver.notify = &ec_notify;
driver.request = &ec_request;
status = bm_unregister_driver(&criteria, &driver);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_notify
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_notify (
BM_NOTIFY notify,
BM_HANDLE device_handle,
void **context)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_notify");
switch (notify) {
case BM_NOTIFY_DEVICE_ADDED:
status = ec_add_device(device_handle, context);
break;
case BM_NOTIFY_DEVICE_REMOVED:
status = ec_remove_device(context);
break;
default:
status = AE_SUPPORT;
break;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_request
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_request (
BM_REQUEST *request,
void *context)
{
acpi_status status = AE_OK;
EC_REQUEST *ec_request = NULL;
EC_CONTEXT *ec = NULL;
FUNCTION_TRACE("ec_request");
/*
* Must have a valid request structure and context.
*/
if (!request || !context)
return_ACPI_STATUS(AE_BAD_PARAMETER);
/*
* buffer must contain a valid EC_REQUEST structure.
*/
status = bm_cast_buffer(&(request->buffer), (void**)&ec_request,
sizeof(EC_REQUEST));
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
/*
* context contains information specific to this EC.
*/
ec = (EC_CONTEXT*)context;
/*
* Perform the Transaction.
*/
status = ec_transaction(ec, ec_request);
return_ACPI_STATUS(status);
}
--- NEW FILE ---
/*****************************************************************************
*
* Module Name: ecspace.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* 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 <acpi.h>
#include "ec.h"
#define _COMPONENT ACPI_EC
MODULE_NAME ("ecspace")
/****************************************************************************
*
* FUNCTION: ec_space_setup
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_space_setup (
acpi_handle region_handle,
u32 function,
void *handler_context,
void **return_context)
{
/*
* The EC object is in the handler context and is needed
* when calling the ec_space_handler.
*/
*return_context = handler_context;
return AE_OK;
}
/****************************************************************************
*
* FUNCTION: ec_space_handler
*
* PARAMETERS: function - Read or Write operation
* address - Where in the space to read or write
* bit_width - Field width in bits (should be 8)
* value - Pointer to in or out value
* context - context pointer
*
* RETURN:
*
* DESCRIPTION: Handler for the Embedded Controller (EC) address space
* (Op Region)
*
****************************************************************************/
acpi_status
ec_space_handler (
u32 function,
ACPI_PHYSICAL_ADDRESS address,
u32 bit_width,
u32 *value,
void *handler_context,
void *region_context)
{
acpi_status status = AE_OK;
EC_CONTEXT *ec = NULL;
EC_REQUEST ec_request;
FUNCTION_TRACE("ec_space_handler");
if (address > 0xFF || bit_width != 8 || !value || !handler_context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
ec = (EC_CONTEXT*)handler_context;
switch (function) {
case ACPI_READ_ADR_SPACE:
ec_request.command = EC_COMMAND_READ;
ec_request.address = address;
ec_request.data = 0;
break;
case ACPI_WRITE_ADR_SPACE:
ec_request.command = EC_COMMAND_WRITE;
ec_request.address = address;
ec_request.data = (u8)(*value);
break;
default:
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Received request with invalid function [%X].\n", function));
return_ACPI_STATUS(AE_BAD_PARAMETER);
break;
}
/*
* Perform the Transaction.
*/
status = ec_transaction(ec, &ec_request);
if (ACPI_SUCCESS(status)) {
(*value) = (u32)ec_request.data;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_install_space_handler
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_install_space_handler (
EC_CONTEXT *ec)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_install_space_handler");
if (!ec) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_install_address_space_handler (ec->acpi_handle,
ACPI_ADR_SPACE_EC, &ec_space_handler, &ec_space_setup, ec);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_remove_space_handler
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_remove_space_handler (
EC_CONTEXT *ec)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_remove_space_handler");
if (!ec) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_remove_address_space_handler(ec->acpi_handle,
ACPI_ADR_SPACE_EC, &ec_space_handler);
return_ACPI_STATUS(status);
}
--- NEW FILE ---
/*****************************************************************************
*
* Module Name: ectransx.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* 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 <acpi.h>
#include "ec.h"
#define _COMPONENT ACPI_EC
MODULE_NAME ("ectransx")
/****************************************************************************
*
* FUNCTION: ec_io_wait
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_io_wait (
EC_CONTEXT *ec,
EC_EVENT wait_event)
{
EC_STATUS ec_status = 0;
u32 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 {
acpi_os_read_port(ec->status_port, &ec_status, 8);
if (ec_status & EC_FLAG_OUTPUT_BUFFER) {
return(AE_OK);
}
acpi_os_stall(10);
} while (--i>0);
break;
case EC_EVENT_INPUT_BUFFER_EMPTY:
do {
acpi_os_read_port(ec->status_port, &ec_status, 8);
if (!(ec_status & EC_FLAG_INPUT_BUFFER)) {
return(AE_OK);
}
acpi_os_stall(10);
} while (--i>0);
break;
}
return(AE_TIME);
}
/****************************************************************************
*
* FUNCTION: ec_io_read
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_io_read (
EC_CONTEXT *ec,
ACPI_IO_ADDRESS io_port,
u8 *data,
EC_EVENT wait_event)
{
acpi_status status = AE_OK;
if (!ec || !data) {
return(AE_BAD_PARAMETER);
}
acpi_os_read_port(io_port, (u32*) data, 8);
if (wait_event) {
status = ec_io_wait(ec, wait_event);
}
return(status);
}
/****************************************************************************
*
* FUNCTION: ec_io_write
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_io_write (
EC_CONTEXT *ec,
ACPI_IO_ADDRESS io_port,
u8 data,
EC_EVENT wait_event)
{
acpi_status status = AE_OK;
if (!ec) {
return(AE_BAD_PARAMETER);
}
acpi_os_write_port(io_port, data, 8);
if (wait_event) {
status = ec_io_wait(ec, wait_event);
}
return(status);
}
/****************************************************************************
*
* FUNCTION: ec_read
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_read (
EC_CONTEXT *ec,
u8 address,
u8 *data)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_read");
if (!ec || !data) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (ec->use_global_lock) {
status = acpi_acquire_global_lock();
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not acquire Global Lock\n"));
return_ACPI_STATUS(status);
}
}
status = ec_io_write(ec, ec->command_port, EC_COMMAND_READ,
EC_EVENT_INPUT_BUFFER_EMPTY);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_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)) {
ACPI_DEBUG_PRINT ((ACPI_DB_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);
if (ec->use_global_lock) {
acpi_release_global_lock();
}
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Read data [%02x] from address [%02x] on ec [%02x].\n", (*data), address, ec->device_handle));
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_write
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_write (
EC_CONTEXT *ec,
u8 address,
u8 data)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_write");
if (!ec)
return_ACPI_STATUS(AE_BAD_PARAMETER);
if (ec->use_global_lock) {
status = acpi_acquire_global_lock();
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not acquire Global Lock\n"));
return_ACPI_STATUS(status);
}
}
status = ec_io_write(ec, ec->command_port, EC_COMMAND_WRITE,
EC_EVENT_INPUT_BUFFER_EMPTY);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_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)) {
ACPI_DEBUG_PRINT ((ACPI_DB_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)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'write data' to EC.\n"));
return_ACPI_STATUS(status);
}
if (ec->use_global_lock) {
acpi_release_global_lock();
}
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Wrote data [%02x] to address [%02x] on ec [%02x].\n", data, address, ec->device_handle));
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: ec_transaction
*
* PARAMETERS:
*
* RETURN:
*
* DESCRIPTION:
*
****************************************************************************/
acpi_status
ec_transaction (
EC_CONTEXT *ec,
EC_REQUEST *request)
{
acpi_status status = AE_OK;
FUNCTION_TRACE("ec_transaction");
if (!ec || !request) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Obtain mutex to serialize all EC transactions.
*/
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 mutex to indicate transaction completion.
*/
acpi_os_signal_semaphore(ec->mutex, 1);
return_ACPI_STATUS(status);
}
|