acpi: use walk_resources to find embedded controller I/O ports.

* export walk_resources and use it
* removed SmallResourceData
* added embedded controller module for x86_64
This commit is contained in:
Jérôme Duval
2013-10-21 22:14:17 +02:00
parent 6c6668ae9e
commit ce2d7d5ac8
9 changed files with 72 additions and 200 deletions
+12
View File
@@ -142,6 +142,8 @@ enum {
*/ */
typedef uint32 acpi_status; typedef uint32 acpi_status;
typedef struct acpi_resource acpi_resource;
#endif // __ACTYPES_H__ #endif // __ACTYPES_H__
@@ -159,6 +161,9 @@ typedef acpi_status (*acpi_adr_space_setup)(acpi_handle regionHandle,
typedef void (*acpi_notify_handler)(acpi_handle device, uint32 value, typedef void (*acpi_notify_handler)(acpi_handle device, uint32 value,
void *context); void *context);
typedef acpi_status (*acpi_walk_resources_callback)(acpi_resource* resource,
void* context);
struct acpi_module_info { struct acpi_module_info {
module_info info; module_info info;
@@ -251,6 +256,9 @@ struct acpi_module_info {
acpi_data *retBuffer); acpi_data *retBuffer);
status_t (*set_current_resources)(acpi_handle busDeviceHandle, status_t (*set_current_resources)(acpi_handle busDeviceHandle,
acpi_data *buffer); acpi_data *buffer);
status_t (*walk_resources)(acpi_handle busDeviceHandle,
char *method, acpi_walk_resources_callback callback,
void* context);
/* Power state setting */ /* Power state setting */
@@ -317,6 +325,10 @@ typedef struct acpi_device_module_info {
/* Control method execution and data acquisition */ /* Control method execution and data acquisition */
status_t (*evaluate_method)(acpi_device device, const char *method, status_t (*evaluate_method)(acpi_device device, const char *method,
acpi_objects *args, acpi_data *returnValue); acpi_objects *args, acpi_data *returnValue);
/* Resource Management */
status_t (*walk_resources)(acpi_device device, char *method,
acpi_walk_resources_callback callback, void* context);
} acpi_device_module_info; } acpi_device_module_info;
@@ -39,6 +39,11 @@ typedef struct acpi_device_cookie {
} acpi_device_cookie; } acpi_device_cookie;
typedef struct acpi_resource acpi_resource;
typedef acpi_status (*acpi_walk_resources_callback)(acpi_resource* resource,
void* context);
// ACPI root. // ACPI root.
typedef struct acpi_root_info { typedef struct acpi_root_info {
driver_module_info info; driver_module_info info;
@@ -131,6 +136,9 @@ typedef struct acpi_root_info {
acpi_data *retBuffer); acpi_data *retBuffer);
status_t (*set_current_resources)(acpi_handle busDeviceHandle, status_t (*set_current_resources)(acpi_handle busDeviceHandle,
acpi_data *buffer); acpi_data *buffer);
status_t (*walk_resources)(acpi_handle busDeviceHandle,
char *method, acpi_walk_resources_callback callback,
void* context);
/* Power state setting */ /* Power state setting */
@@ -217,6 +225,8 @@ status_t get_possible_resources(acpi_handle busDeviceHandle,
acpi_data* returnValue); acpi_data* returnValue);
status_t set_current_resources(acpi_handle busDeviceHandle, status_t set_current_resources(acpi_handle busDeviceHandle,
acpi_data* buffer); acpi_data* buffer);
status_t walk_resources(acpi_handle busDeviceHandle, char* method,
acpi_walk_resources_callback callback, void* context);
status_t prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size); status_t prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size);
status_t enter_sleep_state(uint8 state); status_t enter_sleep_state(uint8 state);
@@ -624,6 +624,15 @@ set_current_resources(acpi_handle busDeviceHandle, acpi_data *buffer)
} }
status_t
walk_resources(acpi_handle busDeviceHandle, char* method,
acpi_walk_resources_callback callback, void* context)
{
return AcpiWalkResources(busDeviceHandle, method,
(ACPI_WALK_RESOURCE_CALLBACK)callback, context);
}
status_t status_t
prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size) prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size)
{ {
@@ -770,6 +779,7 @@ struct acpi_module_info gACPIModule = {
get_current_resources, get_current_resources,
get_possible_resources, get_possible_resources,
set_current_resources, set_current_resources,
walk_resources,
prepare_sleep_state, prepare_sleep_state,
enter_sleep_state, enter_sleep_state,
reboot, reboot,
@@ -74,6 +74,14 @@ acpi_evaluate_method(acpi_device device, const char *method,
} }
static status_t
acpi_walk_resources(acpi_device device, char *method,
acpi_walk_resources_callback callback, void* context)
{
return walk_resources(device->handle, method, callback, context);
}
static status_t static status_t
acpi_device_init_driver(device_node *node, void **cookie) acpi_device_init_driver(device_node *node, void **cookie)
{ {
@@ -154,4 +162,5 @@ acpi_device_module_info gACPIDeviceModule = {
acpi_get_object_type, acpi_get_object_type,
acpi_get_object, acpi_get_object,
acpi_evaluate_method, acpi_evaluate_method,
acpi_walk_resources
}; };
@@ -1,4 +1,5 @@
/* /*
* Copyright 2013, Jérôme Duval, [email protected].
* Copyright (c) 2009 Clemens Zeidler * Copyright (c) 2009 Clemens Zeidler
* Copyright (c) 2003-2007 Nate Lawson * Copyright (c) 2003-2007 Nate Lawson
* Copyright (c) 2000 Michael Smith * Copyright (c) 2000 Michael Smith
@@ -40,8 +41,6 @@
#include <KernelExport.h> #include <KernelExport.h>
#include <drivers/PCI.h> #include <drivers/PCI.h>
#include "SmallResourceData.h"
#define ACPI_EC_DRIVER_NAME "drivers/power/acpi_embedded_controller/driver_v1" #define ACPI_EC_DRIVER_NAME "drivers/power/acpi_embedded_controller/driver_v1"
@@ -143,6 +142,25 @@ acpi_PkgInt32(acpi_object_type* res, int idx, uint32* dst)
} }
acpi_status
embedded_controller_io_ports_parse_callback(ACPI_RESOURCE* resource,
void* _context)
{
acpi_ec_cookie* sc = (acpi_ec_cookie*)_context;
if (resource->Type != ACPI_RESOURCE_TYPE_IO)
return AE_OK;
if (sc->ec_data_pci_address == 0) {
sc->ec_data_pci_address = resource->Data.Io.Minimum;
} else if (sc->ec_csr_pci_address == 0) {
sc->ec_csr_pci_address = resource->Data.Io.Minimum;
} else {
return AE_CTRL_TERMINATE;
}
return AE_OK;
}
// #pragma mark - // #pragma mark -
@@ -282,13 +300,6 @@ embedded_controller_init_driver(device_node* dev, void** _driverCookie)
(void**)&sc->ec_handle); (void**)&sc->ec_handle);
gDeviceManager->put_node(parent); gDeviceManager->put_node(parent);
SmallResourceData resourceData(sc->ec_acpi, sc->ec_handle, "_CRS");
if (resourceData.InitCheck() != B_OK) {
TRACE("failed to read _CRS resource\n") ;
return B_ERROR;
}
io_port portData;
if (get_module(B_ACPI_MODULE_NAME, (module_info**)&sc->ec_acpi_module) if (get_module(B_ACPI_MODULE_NAME, (module_info**)&sc->ec_acpi_module)
!= B_OK) != B_OK)
return B_ERROR; return B_ERROR;
@@ -313,7 +324,7 @@ embedded_controller_init_driver(device_node* dev, void** _driverCookie)
// and GPE bit, similar to _PRW. // and GPE bit, similar to _PRW.
status = sc->ec_acpi->evaluate_method(sc->ec_handle, "_GPE", NULL, &buf); status = sc->ec_acpi->evaluate_method(sc->ec_handle, "_GPE", NULL, &buf);
if (status != B_OK) { if (status != B_OK) {
TRACE("can't evaluate _GPE\n"); ERROR("can't evaluate _GPE\n");
goto error; goto error;
} }
@@ -337,22 +348,19 @@ embedded_controller_init_driver(device_node* dev, void** _driverCookie)
goto error; goto error;
break; break;
default: default:
TRACE("_GPE has invalid type %i\n", int(obj->object_type)); ERROR("_GPE has invalid type %i\n", int(obj->object_type));
goto error; goto error;
} }
sc->ec_suspending = FALSE; sc->ec_suspending = FALSE;
// Attach bus resources for data and command/status ports. // Attach bus resources for data and command/status ports.
if (resourceData.ReadIOPort(&portData) != B_OK) status = sc->ec_acpi->walk_resources(sc->ec_handle, "_CRS",
embedded_controller_io_ports_parse_callback, sc);
if (status != B_OK) {
ERROR("Error while getting IO ports addresses\n");
goto error; goto error;
}
sc->ec_data_pci_address = portData.minimumBase;
if (resourceData.ReadIOPort(&portData) != B_OK)
goto error;
sc->ec_csr_pci_address = portData.minimumBase;
// Install a handler for this EC's GPE bit. We want edge-triggered // Install a handler for this EC's GPE bit. We want edge-triggered
// behavior. // behavior.
@@ -369,14 +377,14 @@ embedded_controller_init_driver(device_node* dev, void** _driverCookie)
status = sc->ec_acpi->install_address_space_handler(sc->ec_handle, status = sc->ec_acpi->install_address_space_handler(sc->ec_handle,
ACPI_ADR_SPACE_EC, &EcSpaceHandler, &EcSpaceSetup, sc); ACPI_ADR_SPACE_EC, &EcSpaceHandler, &EcSpaceSetup, sc);
if (status != B_OK) { if (status != B_OK) {
TRACE("can't install address space handler\n"); ERROR("can't install address space handler\n");
goto error; goto error;
} }
// Enable runtime GPEs for the handler. // Enable runtime GPEs for the handler.
status = sc->ec_acpi_module->enable_gpe(sc->ec_gpehandle, sc->ec_gpebit); status = sc->ec_acpi_module->enable_gpe(sc->ec_gpehandle, sc->ec_gpebit);
if (status != B_OK) { if (status != B_OK) {
TRACE("AcpiEnableGpe failed.\n"); ERROR("AcpiEnableGpe failed.\n");
goto error; goto error;
} }
@@ -519,7 +527,7 @@ EcGpeQueryHandler(void* context)
// that may arise from running the query from causing another query // that may arise from running the query from causing another query
// to be queued, we clear the pending flag only after running it. // to be queued, we clear the pending flag only after running it.
int sci_enqueued = sc->ec_sci_pending; int sci_enqueued = sc->ec_sci_pending;
acpi_status acpi_status; acpi_status acpi_status = AE_ERROR;
for (uint8 retry = 0; retry < 2; retry++) { for (uint8 retry = 0; retry < 2; retry++) {
acpi_status = EcCommand(sc, EC_COMMAND_QUERY); acpi_status = EcCommand(sc, EC_COMMAND_QUERY);
if (acpi_status == AE_OK) if (acpi_status == AE_OK)
@@ -207,7 +207,6 @@ KernelAddon acpi :
Device.cpp Device.cpp
NamespaceDump.cpp NamespaceDump.cpp
EmbeddedController.cpp EmbeddedController.cpp
SmallResourceData.cpp
: :
libacpi_ca.a libacpi_ca.a
; ;
@@ -221,6 +221,7 @@ static struct acpi_root_info sACPIRootModule = {
get_current_resources, get_current_resources,
get_possible_resources, get_possible_resources,
set_current_resources, set_current_resources,
walk_resources,
prepare_sleep_state, prepare_sleep_state,
enter_sleep_state, enter_sleep_state,
reboot, reboot,
@@ -233,9 +234,7 @@ module_info* modules[] = {
(module_info*)&sACPIRootModule, (module_info*)&sACPIRootModule,
(module_info*)&acpi_ns_dump_module, (module_info*)&acpi_ns_dump_module,
(module_info*)&gACPIDeviceModule, (module_info*)&gACPIDeviceModule,
#ifndef __x86_64__
(module_info*)&embedded_controller_driver_module, (module_info*)&embedded_controller_driver_module,
(module_info*)&embedded_controller_device_module, (module_info*)&embedded_controller_device_module,
#endif
NULL NULL
}; };
@@ -1,114 +0,0 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, [email protected]
*/
#include "SmallResourceData.h"
#include <stdlib.h>
//#define TRACE_SMALLRESOURCEDATA
#ifdef TRACE_SMALLRESOURCEDATA
# define TRACE(x...) dprintf("Small Resource Data: "x)
#else
# define TRACE(x...)
#endif
void
io_port::Print()
{
dprintf("io_port:\n");
int i = (deviceAddresses16Bit ? 1 : 0);
dprintf("deviceAddresses16Bit %i\n", i);
dprintf("minimumBase %i\n", minimumBase);
dprintf("maximumBase %i\n", maximumBase);
dprintf("minimumBaseAlignment %i\n", minimumBaseAlignment);
dprintf("contigiuousIOPorts %i\n", contigiuousIOPorts);
}
SmallResourceData::SmallResourceData(acpi_device_module_info* acpi,
acpi_device acpiCookie, const char* method)
{
acpi_data buffer;
buffer.pointer = NULL;
buffer.length = ACPI_ALLOCATE_BUFFER;
fStatus = acpi->evaluate_method(acpiCookie, method, NULL, &buffer);
if (fStatus != B_OK)
return;
fBuffer = (acpi_object_type*)buffer.pointer;
if (fBuffer[0].object_type != ACPI_TYPE_BUFFER) {
fStatus = B_ERROR;
return;
}
fResourcePointer = (int8*)fBuffer[0].data.buffer.buffer;
fBufferSize = fBuffer[0].data.buffer.length;
fRemainingBufferSize = fBufferSize;
// ToDo: Check checksum of the endtag. The sum of all databytes + checksum
// is zero. See section 6.4.2.8.
}
SmallResourceData::~SmallResourceData()
{
if (InitCheck() == B_OK)
free(fBuffer);
}
status_t
SmallResourceData::InitCheck()
{
return fStatus;
}
int8
SmallResourceData::GetType()
{
return *fResourcePointer;
}
status_t
SmallResourceData::ReadIOPort(io_port* ioPort)
{
const size_t packageSize = 8;
if (fRemainingBufferSize < packageSize)
return B_ERROR;
if (fResourcePointer[0] != kIOPort)
return B_ERROR;
ioPort->deviceAddresses16Bit = (fResourcePointer[1] == 1);
int16 tmp;
tmp = fResourcePointer[3];
tmp = tmp << 8;
tmp |= fResourcePointer[2];
ioPort->minimumBase = tmp;
tmp = fResourcePointer[5];
tmp = tmp << 8;
tmp |= fResourcePointer[4];
ioPort->maximumBase = tmp;
ioPort->minimumBaseAlignment = fResourcePointer[6];
ioPort->contigiuousIOPorts = fResourcePointer[7];
fResourcePointer += packageSize;
fRemainingBufferSize -= packageSize;
TRACE("SmallResourceData: remaining buffer size %i\n",
int(fRemainingBufferSize));
return B_OK;
}
@@ -1,61 +0,0 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Clemens Zeidler, [email protected]
*/
#ifndef SMALLRESOURCEDATA_H
#define SMALLRESOURCEDATA_H
#include <ACPI.h>
#include <Errors.h>
enum resource_type
{
kIOPort = 0x47,
kEndTag = 0x78
};
struct io_port
{
void Print();
//! The logical device decodes 16-bit addresses.
bool deviceAddresses16Bit;
uint16 minimumBase;
uint16 maximumBase;
uint8 minimumBaseAlignment;
uint8 contigiuousIOPorts;
};
/*! ToDo: implement also the other resource data, see acpi section 6.2.4 */
class SmallResourceData
{
public:
SmallResourceData(acpi_device_module_info* acpi,
acpi_device acpiCookie, const char* method);
~SmallResourceData();
status_t InitCheck();
int8 GetType();
/*! Get resource data and jump to the next resource. */
status_t ReadIOPort(io_port* ioPort);
private:
acpi_object_type* fBuffer;
size_t fBufferSize;
size_t fRemainingBufferSize;
int8* fResourcePointer;
status_t fStatus;
};
#endif