1/***************************************************************************** 2 * 3 * Module Name: ectransx.c 4 * $Revision: 1.1.1.1 $ 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000, 2001 Andrew Grover 10 * 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. 15 * 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. 20 * 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 24 */ 25 26 27#include <acpi.h> 28#include "ec.h" 29 30#define _COMPONENT ACPI_EC 31 MODULE_NAME ("ectransx") 32 33 34/**************************************************************************** 35 * 36 * FUNCTION: ec_io_wait 37 * 38 * PARAMETERS: 39 * 40 * RETURN: 41 * 42 * DESCRIPTION: 43 * 44 ****************************************************************************/ 45 46acpi_status 47ec_io_wait ( 48 EC_CONTEXT *ec, 49 EC_EVENT wait_event) 50{ 51 EC_STATUS ec_status = 0; 52 u32 i = 100; 53 54 if (!ec || ((wait_event != EC_EVENT_OUTPUT_BUFFER_FULL) 55 && (wait_event != EC_EVENT_INPUT_BUFFER_EMPTY))) { 56 return(AE_BAD_PARAMETER); 57 } 58 59 /* 60 * Wait for Event: 61 * --------------- 62 * Poll the EC status register waiting for the event to occur. 63 * Note that we'll wait a maximum of 1ms in 10us chunks. 64 */ 65 switch (wait_event) { 66 67 case EC_EVENT_OUTPUT_BUFFER_FULL: 68 do { 69 acpi_os_read_port(ec->status_port, &ec_status, 8); 70 if (ec_status & EC_FLAG_OUTPUT_BUFFER) { 71 return(AE_OK); 72 } 73 acpi_os_stall(10); 74 } while (--i>0); 75 break; 76 77 case EC_EVENT_INPUT_BUFFER_EMPTY: 78 do { 79 acpi_os_read_port(ec->status_port, &ec_status, 8); 80 if (!(ec_status & EC_FLAG_INPUT_BUFFER)) { 81 return(AE_OK); 82 } 83 acpi_os_stall(10); 84 } while (--i>0); 85 break; 86 } 87 88 return(AE_TIME); 89} 90 91 92/**************************************************************************** 93 * 94 * FUNCTION: ec_io_read 95 * 96 * PARAMETERS: 97 * 98 * RETURN: 99 * 100 * DESCRIPTION: 101 * 102 ****************************************************************************/ 103 104acpi_status 105ec_io_read ( 106 EC_CONTEXT *ec, 107 u32 io_port, 108 u8 *data, 109 EC_EVENT wait_event) 110{ 111 acpi_status status = AE_OK; 112 113 if (!ec || !data) { 114 return(AE_BAD_PARAMETER); 115 } 116 117 acpi_os_read_port(io_port, (u32*) data, 8); 118 119 if (wait_event) { 120 status = ec_io_wait(ec, wait_event); 121 } 122 123 return(status); 124} 125 126 127/**************************************************************************** 128 * 129 * FUNCTION: ec_io_write 130 * 131 * PARAMETERS: 132 * 133 * RETURN: 134 * 135 * DESCRIPTION: 136 * 137 ****************************************************************************/ 138 139acpi_status 140ec_io_write ( 141 EC_CONTEXT *ec, 142 u32 io_port, 143 u8 data, 144 EC_EVENT wait_event) 145{ 146 acpi_status status = AE_OK; 147 148 if (!ec) { 149 return(AE_BAD_PARAMETER); 150 } 151 152 acpi_os_write_port(io_port, data, 8); 153 154 if (wait_event) { 155 status = ec_io_wait(ec, wait_event); 156 } 157 158 return(status); 159} 160 161 162/**************************************************************************** 163 * 164 * FUNCTION: ec_read 165 * 166 * PARAMETERS: 167 * 168 * RETURN: 169 * 170 * DESCRIPTION: 171 * 172 ****************************************************************************/ 173 174acpi_status 175ec_read ( 176 EC_CONTEXT *ec, 177 u8 address, 178 u8 *data) 179{ 180 acpi_status status = AE_OK; 181 182 FUNCTION_TRACE("ec_read"); 183 184 if (!ec || !data) { 185 return_ACPI_STATUS(AE_BAD_PARAMETER); 186 } 187 188 if (ec->use_global_lock) { 189 status = acpi_acquire_global_lock(); 190 if (ACPI_FAILURE(status)) { 191 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not acquire Global Lock\n")); 192 return_ACPI_STATUS(status); 193 } 194 } 195 196 status = ec_io_write(ec, ec->command_port, EC_COMMAND_READ, 197 EC_EVENT_INPUT_BUFFER_EMPTY); 198 if (ACPI_FAILURE(status)) { 199 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'read command' to EC.\n")); 200 return_ACPI_STATUS(status); 201 } 202 203 status = ec_io_write(ec, ec->data_port, address, 204 EC_EVENT_OUTPUT_BUFFER_FULL); 205 if (ACPI_FAILURE(status)) { 206 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'read address' to EC.\n")); 207 return_ACPI_STATUS(status); 208 } 209 210 status = ec_io_read(ec, ec->data_port, data, EC_EVENT_NONE); 211 212 if (ec->use_global_lock) { 213 acpi_release_global_lock(); 214 } 215 216 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Read data [%02x] from address [%02x] on ec [%02x].\n", (*data), address, ec->device_handle)); 217 218 return_ACPI_STATUS(status); 219} 220 221 222/**************************************************************************** 223 * 224 * FUNCTION: ec_write 225 * 226 * PARAMETERS: 227 * 228 * RETURN: 229 * 230 * DESCRIPTION: 231 * 232 ****************************************************************************/ 233 234acpi_status 235ec_write ( 236 EC_CONTEXT *ec, 237 u8 address, 238 u8 data) 239{ 240 acpi_status status = AE_OK; 241 242 FUNCTION_TRACE("ec_write"); 243 244 if (!ec) 245 return_ACPI_STATUS(AE_BAD_PARAMETER); 246 247 if (ec->use_global_lock) { 248 status = acpi_acquire_global_lock(); 249 if (ACPI_FAILURE(status)) { 250 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not acquire Global Lock\n")); 251 return_ACPI_STATUS(status); 252 } 253 } 254 255 status = ec_io_write(ec, ec->command_port, EC_COMMAND_WRITE, 256 EC_EVENT_INPUT_BUFFER_EMPTY); 257 if (ACPI_FAILURE(status)) { 258 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'write command' to EC.\n")); 259 return_ACPI_STATUS(status); 260 } 261 262 status = ec_io_write(ec, ec->data_port, address, 263 EC_EVENT_INPUT_BUFFER_EMPTY); 264 if (ACPI_FAILURE(status)) { 265 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'write address' to EC.\n")); 266 return_ACPI_STATUS(status); 267 } 268 269 status = ec_io_write(ec, ec->data_port, data, 270 EC_EVENT_INPUT_BUFFER_EMPTY); 271 if (ACPI_FAILURE(status)) { 272 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to send 'write data' to EC.\n")); 273 return_ACPI_STATUS(status); 274 } 275 276 if (ec->use_global_lock) { 277 acpi_release_global_lock(); 278 } 279 280 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Wrote data [%02x] to address [%02x] on ec [%02x].\n", data, address, ec->device_handle)); 281 282 return_ACPI_STATUS(status); 283} 284 285 286/**************************************************************************** 287 * 288 * FUNCTION: ec_transaction 289 * 290 * PARAMETERS: 291 * 292 * RETURN: 293 * 294 * DESCRIPTION: 295 * 296 ****************************************************************************/ 297 298acpi_status 299ec_transaction ( 300 EC_CONTEXT *ec, 301 EC_REQUEST *request) 302{ 303 acpi_status status = AE_OK; 304 305 FUNCTION_TRACE("ec_transaction"); 306 307 if (!ec || !request) { 308 return_ACPI_STATUS(AE_BAD_PARAMETER); 309 } 310 311 /* 312 * Obtain mutex to serialize all EC transactions. 313 */ 314 status = acpi_os_wait_semaphore(ec->mutex, 1, EC_DEFAULT_TIMEOUT); 315 if (ACPI_FAILURE(status)) { 316 return_ACPI_STATUS(status); 317 } 318 319 /* 320 * Perform the transaction. 321 */ 322 switch (request->command) { 323 324 case EC_COMMAND_READ: 325 status = ec_read(ec, request->address, &(request->data)); 326 break; 327 328 case EC_COMMAND_WRITE: 329 status = ec_write(ec, request->address, request->data); 330 break; 331 332 default: 333 status = AE_SUPPORT; 334 break; 335 } 336 337 /* 338 * Signal the mutex to indicate transaction completion. 339 */ 340 acpi_os_signal_semaphore(ec->mutex, 1); 341 342 return_ACPI_STATUS(status); 343} 344