1 /*****************************************************************************
3 * Module Name: ecmain.c
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 Andrew Grover
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #define _COMPONENT ACPI_EC
31 MODULE_NAME ("ecmain")
34 /****************************************************************************
36 ****************************************************************************/
38 /****************************************************************************
46 * DESCRIPTION: Prints out information on a specific ec.
48 ****************************************************************************/
58 PROC_NAME("ec_print");
64 acpi_os_printf("EC: found, GPE %d\n", ec->gpe_bit);
68 buffer.pointer = acpi_os_callocate(buffer.length);
69 if (!buffer.pointer) {
74 * Get the full pathname for this ACPI object.
76 acpi_get_name(ec->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
79 * Print out basic thermal zone information.
81 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n"));
82 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Embedded_controller[%02x]:[%p] %s\n", ec->device_handle, ec->acpi_handle, (char*)buffer.pointer));
83 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));
84 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n"));
86 acpi_os_free(buffer.pointer);
93 /****************************************************************************
95 * FUNCTION: ec_get_port_values
101 * DESCRIPTION: Evaluate _CRS to get the current resources (I/O port
102 * addresses) for this EC.
104 ****************************************************************************/
110 acpi_status status = AE_OK;
112 acpi_resource *resource = NULL;
114 FUNCTION_TRACE("ec_get_port_values");
117 return_ACPI_STATUS(AE_BAD_PARAMETER);
121 buffer.pointer = NULL;
123 status = acpi_get_current_resources(ec->acpi_handle, &buffer);
124 if (status != AE_BUFFER_OVERFLOW) {
125 return_ACPI_STATUS(status);
128 buffer.pointer = acpi_os_callocate(buffer.length);
129 if (!buffer.pointer) {
130 return_ACPI_STATUS(AE_NO_MEMORY);
133 status = acpi_get_current_resources(ec->acpi_handle, &buffer);
134 if (ACPI_FAILURE(status)) {
138 resource = (acpi_resource *) buffer.pointer;
139 ec->data_port = resource->data.io.min_base_address;
141 resource = NEXT_RESOURCE(resource);
143 ec->status_port = ec->command_port =
144 resource->data.io.min_base_address;
146 acpi_os_free(buffer.pointer);
148 return_ACPI_STATUS(status);
152 /****************************************************************************
154 * FUNCTION: ec_add_device
162 ****************************************************************************/
166 BM_HANDLE device_handle,
169 acpi_status status = AE_OK;
170 BM_DEVICE *device = NULL;
171 EC_CONTEXT *ec = NULL;
172 u8 gpe_handler = FALSE;
173 u8 space_handler = FALSE;
175 FUNCTION_TRACE("ec_add_device");
177 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding EC device [%02x].\n", device_handle));
179 if (!context || *context) {
180 return_ACPI_STATUS(AE_BAD_PARAMETER);
184 * Get information on this device.
186 status = bm_get_device_info(device_handle, &device);
187 if (ACPI_FAILURE(status)) {
188 return_ACPI_STATUS(status);
192 * Allocate a new EC_CONTEXT structure.
194 ec = acpi_os_callocate(sizeof(EC_CONTEXT));
196 return_ACPI_STATUS(AE_NO_MEMORY);
199 ec->device_handle = device->handle;
200 ec->acpi_handle = device->acpi_handle;
203 * Get the I/O port addresses for the command/status and data ports.
205 status = ec_get_port_values(ec);
206 if (ACPI_FAILURE(status)) {
211 * See if we need to obtain the global lock for EC transactions.
213 status = bm_evaluate_simple_integer(ec->acpi_handle, "_GLK",
214 &ec->use_global_lock);
215 if (status == AE_NOT_FOUND) {
216 ec->use_global_lock = 0;
218 else if (ACPI_FAILURE(status)) {
219 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "EC _GLK failed\n"));
224 * Install a handler for servicing this EC's GPE.
226 status = ec_install_gpe_handler(ec);
227 if (ACPI_FAILURE(status)) {
235 * Install a handler for servicing this EC's address space.
237 status = ec_install_space_handler(ec);
238 if (ACPI_FAILURE(status)) {
242 space_handler = TRUE;
246 * Create a semaphore to serialize EC transactions.
248 status = acpi_os_create_semaphore(1,1, &(ec->mutex));
249 if (ACPI_FAILURE(status)) {
254 * Context now contains information specific to this EC. Note
255 * that we'll get this pointer back on every ec_request() and
263 if (ACPI_FAILURE(status)) {
266 ec_remove_gpe_handler(ec);
270 ec_remove_space_handler(ec);
274 acpi_os_delete_semaphore(ec->mutex);
280 return_ACPI_STATUS(status);
284 /****************************************************************************
286 * FUNCTION: ec_remove_device
294 ****************************************************************************/
300 acpi_status status = AE_OK;
301 EC_CONTEXT *ec = NULL;
303 FUNCTION_TRACE("ec_remove_device");
305 if (!context || !*context) {
306 return_ACPI_STATUS(AE_BAD_PARAMETER);
309 ec = (EC_CONTEXT*)*context;
311 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing EC device [%02x].\n", ec->device_handle));
313 ec_remove_space_handler(ec);
315 ec_remove_gpe_handler(ec);
318 acpi_os_delete_semaphore(ec->mutex);
325 return_ACPI_STATUS(status);
329 /****************************************************************************
331 ****************************************************************************/
333 /****************************************************************************
335 * FUNCTION: ec_initialize
343 ****************************************************************************/
348 acpi_status status = AE_OK;
349 BM_DEVICE_ID criteria;
352 FUNCTION_TRACE("ec_initialize");
354 MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
355 MEMSET(&driver, 0, sizeof(BM_DRIVER));
358 * Register driver for AC Adapter devices.
360 MEMCPY(criteria.hid, EC_HID_EC, sizeof(EC_HID_EC));
362 driver.notify = &ec_notify;
363 driver.request = &ec_request;
365 status = bm_register_driver(&criteria, &driver);
367 return_ACPI_STATUS(status);
371 /****************************************************************************
373 * FUNCTION: ec_terminate
381 ****************************************************************************/
386 acpi_status status = AE_OK;
387 BM_DEVICE_ID criteria;
390 FUNCTION_TRACE("ec_terminate");
392 MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
393 MEMSET(&driver, 0, sizeof(BM_DRIVER));
396 * Unregister driver for AC Adapter devices.
398 MEMCPY(criteria.hid, EC_HID_EC, sizeof(EC_HID_EC));
400 driver.notify = &ec_notify;
401 driver.request = &ec_request;
403 status = bm_unregister_driver(&criteria, &driver);
405 return_ACPI_STATUS(status);
409 /****************************************************************************
411 * FUNCTION: ec_notify
419 ****************************************************************************/
424 BM_HANDLE device_handle,
427 acpi_status status = AE_OK;
429 FUNCTION_TRACE("ec_notify");
433 case BM_NOTIFY_DEVICE_ADDED:
434 status = ec_add_device(device_handle, context);
437 case BM_NOTIFY_DEVICE_REMOVED:
438 status = ec_remove_device(context);
446 return_ACPI_STATUS(status);
450 /****************************************************************************
452 * FUNCTION: ec_request
460 ****************************************************************************/
467 acpi_status status = AE_OK;
468 EC_REQUEST *ec_request = NULL;
469 EC_CONTEXT *ec = NULL;
471 FUNCTION_TRACE("ec_request");
474 * Must have a valid request structure and context.
476 if (!request || !context)
477 return_ACPI_STATUS(AE_BAD_PARAMETER);
480 * buffer must contain a valid EC_REQUEST structure.
482 status = bm_cast_buffer(&(request->buffer), (void**)&ec_request,
484 if (ACPI_FAILURE(status))
485 return_ACPI_STATUS(status);
488 * context contains information specific to this EC.
490 ec = (EC_CONTEXT*)context;
493 * Perform the Transaction.
495 status = ec_transaction(ec, ec_request);
497 return_ACPI_STATUS(status);