📄 ec.c
字号:
*/ object_name[2] = hex[((ec_q->data >> 4) & 0x0F)]; object_name[3] = hex[(ec_q->data & 0x0F)]; DEBUG_PRINT(ACPI_INFO, ("Read query data[0x%02x] from ec - evaluating [%s].\n", ec_q->data, object_name)); status = acpi_evaluate_object(ec_q->ec->acpi_handle, object_name, NULL, NULL); kfree(ec_q); return_VOID;}/* * handle GPE */static voidec_gpe_handler(void *context){ ACPI_STATUS status = AE_OK; ec_context_t *ec = (ec_context_t *) context; EC_QUERY_DATA *ec_q = NULL; EC_STATUS ec_status = 0; FUNCTION_TRACE("ec_gpe_handler"); if (!ec) { DEBUG_PRINT(ACPI_INFO, ("Invalid (NULL) context.\n")); return_VOID; } // GET SPINLOCK! /* * 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. */ ec_status = acpi_os_in8(ec->status_port); DEBUG_PRINT(ACPI_INFO, ("EC Status Register: [0x%02x]\n", ec_status)); if (!(ec_status & EC_FLAG_SCI)) return_VOID; DEBUG_PRINT(ACPI_INFO, ("EC_SCI detected - running QUERY.\n")); // TODO: Need GFP_ATOMIC 'switch' for OSL interface... ec_q = kmalloc(sizeof(EC_QUERY_DATA), GFP_ATOMIC); if (!ec_q) { DEBUG_PRINT(ACPI_INFO, ("Memory allocation failure.\n")); return_VOID; } ec_q->ec = ec; ec_q->data = 0; /* * 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->status_port, EC_COMMAND_QUERY, EC_EVENT_OUTPUT_BUFFER_FULL); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Unable to send 'query command' to EC.\n")); goto End; } status = ec_io_read(ec, ec->data_port, &(ec_q->data), EC_EVENT_NONE); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_WARN, ("Error reading query data.\n")); goto End; } // RELEASE SPINLOCK! if (!ec_q->data) { DEBUG_PRINT(ACPI_WARN, ("Spurious EC SCI detected.\n")); status = AE_ERROR; goto End; } /* * 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_q); if (ACPI_FAILURE(status)) { DEBUG_PRINT(ACPI_ERROR, ("Unable to defer _Qxx method evaluation.\n")); goto End; }End: if (ACPI_FAILURE(status)) kfree(ec_q); return_VOID;}static ACPI_STATUSec_region_setup ( ACPI_HANDLE handle, u32 function, void *handler_context, void **region_context){ FUNCTION_TRACE("acpi_ec_region_setup"); printk("acpi_ec_region_setup\n"); if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { acpi_cm_free (*region_context); *region_context = NULL; } return_ACPI_STATUS (AE_OK); } *region_context = NULL; return_ACPI_STATUS (AE_OK);}/***************************************************************************** * * FUNCTION: ec_region_handler * * PARAMETERS: function - Read or Write operation * address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) * value - Pointer to in or out value * context - context pointer * * RETURN: <TBD> * * DESCRIPTION: Handler for the Embedded Controller (EC) address space * (Op Region) * ****************************************************************************/static ACPI_STATUSec_region_handler ( UINT32 function, ACPI_PHYSICAL_ADDRESS address, UINT32 bit_width, UINT32 *value, void *handler_context, void *region_context){ ACPI_STATUS status = AE_OK; ec_context_t *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_t*)handler_context; switch (function) { case ADDRESS_SPACE_READ: ec_request.command = EC_COMMAND_READ; ec_request.address = address; ec_request.data = 0; break; case ADDRESS_SPACE_WRITE: ec_request.command = EC_COMMAND_WRITE; ec_request.address = address; ec_request.data = (UINT8)(*value); break; default: DEBUG_PRINT(ACPI_WARN, ("Received request with invalid function [0x%08X].\n", function)); return_ACPI_STATUS(AE_BAD_PARAMETER); break; } DEBUG_PRINT(ACPI_INFO, ("device[ec] command[0x%02X] address[0x%02X] data[0x%02X]\n", ec_request.command, ec_request.address, ec_request.data)); /* * Perform the Transaction. */ status = ec_transaction(ec, &ec_request); if (ACPI_SUCCESS(status)) (*value) = (UINT32)ec_request.data; return_ACPI_STATUS(status);}/* * Get Embedded Controller information */static ACPI_STATUSfound_ec( ACPI_HANDLE handle, u32 level, void *ctx, void **value){ ACPI_STATUS status; ACPI_OBJECT obj; ACPI_BUFFER buf; RESOURCE *res; ec_context_t *ec_cxt; buf.length = 0; buf.pointer = NULL; if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW) return AE_OK; buf.pointer = kmalloc(buf.length, GFP_KERNEL); if (!buf.pointer) return AE_NO_MEMORY; if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) { kfree(buf.pointer); return AE_OK; } ec_cxt = kmalloc(sizeof(ec_context_t), GFP_KERNEL); if (!ec_cxt) { kfree(buf.pointer); return AE_NO_MEMORY; } ec_cxt->acpi_handle = handle; res = (RESOURCE*) buf.pointer; ec_cxt->data_port = res->data.io.min_base_address; res = NEXT_RESOURCE(res); ec_cxt->status_port = (int) res->data.io.min_base_address; kfree(buf.pointer); /* determine GPE bit */ /* BUG: in acpi 2.0 this could return a package */ buf.length = sizeof(obj); buf.pointer = &obj; if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf)) || obj.type != ACPI_TYPE_NUMBER) return AE_OK; ec_cxt->gpe_bit = obj.number.value; /* determine if we need the Global Lock when accessing */ buf.length = sizeof(obj); buf.pointer = &obj; status = acpi_evaluate_object(handle, "_GLK", NULL, &buf); if (status == AE_NOT_FOUND) ec_cxt->need_global_lock = 0; else if (!ACPI_SUCCESS(status) || obj.type != ACPI_TYPE_NUMBER) { DEBUG_PRINT(ACPI_ERROR, ("_GLK failed\n")); return AE_OK; } ec_cxt->need_global_lock = obj.number.value; printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,gpe %d GL %d)\n", ec_cxt->data_port, ec_cxt->status_port, ec_cxt->gpe_bit, ec_cxt->need_global_lock); if (!ACPI_SUCCESS(acpi_install_gpe_handler( ec_cxt->gpe_bit, ACPI_EVENT_EDGE_TRIGGERED, ec_gpe_handler, ec_cxt))) { REPORT_ERROR(("Could not install GPE handler for EC.\n")); return AE_OK; } status = acpi_install_address_space_handler (handle, ADDRESS_SPACE_EC, ec_region_handler, ec_region_setup, ec_cxt); if (!ACPI_SUCCESS(status)) { REPORT_ERROR(("Could not install EC address " "space handler, error %s\n", acpi_cm_format_exception (status))); } return AE_OK;}intacpi_ec_init(void){ acpi_get_devices(ACPI_EC_HID, found_ec, NULL, NULL); return 0;}intacpi_ec_terminate(void){ /* TODO */ /* walk list of EC's */ /* free their context and release resources */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -