Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/acpica/acpi_ec.c
Show First 20 Lines • Show All 339 Lines • ▼ Show 20 Lines | acpi_ec_probe(device_t dev) | ||||
ACPI_STATUS status; | ACPI_STATUS status; | ||||
device_t peer; | device_t peer; | ||||
char desc[64]; | char desc[64]; | ||||
int ecdt; | int ecdt; | ||||
int ret; | int ret; | ||||
struct acpi_ec_params *params; | struct acpi_ec_params *params; | ||||
static char *ec_ids[] = { "PNP0C09", NULL }; | static char *ec_ids[] = { "PNP0C09", NULL }; | ||||
ret = ENXIO; | |||||
/* Check that this is a device and that EC is not disabled. */ | /* Check that this is a device and that EC is not disabled. */ | ||||
if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec")) | if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec")) | ||||
return (ENXIO); | return (ret); | ||||
if (device_is_devclass_fixed(dev)) { | |||||
/* | /* | ||||
* If probed via ECDT, set description and continue. Otherwise, | * If probed via ECDT, set description and continue. Otherwise, we can | ||||
* we can access the namespace and make sure this is not a | * access the namespace and make sure this is not a duplicate probe. | ||||
* duplicate probe. | |||||
*/ | */ | ||||
ret = ENXIO; | |||||
ecdt = 0; | |||||
buf.Pointer = NULL; | |||||
buf.Length = ACPI_ALLOCATE_BUFFER; | |||||
params = acpi_get_private(dev); | |||||
if (params != NULL) { | |||||
ecdt = 1; | ecdt = 1; | ||||
params = acpi_get_private(dev); | |||||
if (params != NULL) | |||||
ret = 0; | ret = 0; | ||||
} else { | |||||
goto out; | |||||
} | |||||
ret = ACPI_ID_PROBE(device_get_parent(dev), dev, ec_ids, NULL); | ret = ACPI_ID_PROBE(device_get_parent(dev), dev, ec_ids, NULL); | ||||
if (ret > 0) | if (ret > 0) | ||||
goto out; | return (ret); | ||||
params = malloc(sizeof(struct acpi_ec_params), M_TEMP, | |||||
M_WAITOK | M_ZERO); | params = malloc(sizeof(struct acpi_ec_params), M_TEMP, M_WAITOK | M_ZERO); | ||||
buf.Pointer = NULL; | |||||
buf.Length = ACPI_ALLOCATE_BUFFER; | |||||
h = acpi_get_handle(dev); | h = acpi_get_handle(dev); | ||||
/* | /* | ||||
* Read the unit ID to check for duplicate attach and the | * Read the unit ID to check for duplicate attach and the global lock value | ||||
* global lock value to see if we should acquire it when | * to see if we should acquire it when accessing the EC. | ||||
* accessing the EC. | |||||
*/ | */ | ||||
status = acpi_GetInteger(h, "_UID", ¶ms->uid); | status = acpi_GetInteger(h, "_UID", ¶ms->uid); | ||||
if (ACPI_FAILURE(status)) | if (ACPI_FAILURE(status)) | ||||
params->uid = 0; | params->uid = 0; | ||||
status = acpi_GetInteger(h, "_GLK", ¶ms->glk); | status = acpi_GetInteger(h, "_GLK", ¶ms->glk); | ||||
if (ACPI_FAILURE(status)) | if (ACPI_FAILURE(status)) | ||||
params->glk = 0; | params->glk = 0; | ||||
/* | /* | ||||
* Evaluate the _GPE method to find the GPE bit used by the EC to | * Evaluate the _GPE method to find the GPE bit used by the EC to signal | ||||
* signal status (SCI). If it's a package, it contains a reference | * status (SCI). If it's a package, it contains a reference and GPE bit, | ||||
* and GPE bit, similar to _PRW. | * similar to _PRW. | ||||
*/ | */ | ||||
status = AcpiEvaluateObject(h, "_GPE", NULL, &buf); | status = AcpiEvaluateObject(h, "_GPE", NULL, &buf); | ||||
if (ACPI_FAILURE(status)) { | if (ACPI_FAILURE(status)) { | ||||
device_printf(dev, "can't evaluate _GPE - %s\n", | device_printf(dev, "can't evaluate _GPE - %s\n", AcpiFormatException(status)); | ||||
AcpiFormatException(status)); | |||||
goto out; | goto out; | ||||
} | } | ||||
obj = (ACPI_OBJECT *)buf.Pointer; | obj = (ACPI_OBJECT *)buf.Pointer; | ||||
if (obj == NULL) | if (obj == NULL) | ||||
goto out; | goto out; | ||||
switch (obj->Type) { | switch (obj->Type) { | ||||
case ACPI_TYPE_INTEGER: | case ACPI_TYPE_INTEGER: | ||||
params->gpe_handle = NULL; | params->gpe_handle = NULL; | ||||
params->gpe_bit = obj->Integer.Value; | params->gpe_bit = obj->Integer.Value; | ||||
break; | break; | ||||
case ACPI_TYPE_PACKAGE: | case ACPI_TYPE_PACKAGE: | ||||
if (!ACPI_PKG_VALID(obj, 2)) | if (!ACPI_PKG_VALID(obj, 2)) | ||||
goto out; | goto out; | ||||
params->gpe_handle = | params->gpe_handle = acpi_GetReference(NULL, &obj->Package.Elements[0]); | ||||
acpi_GetReference(NULL, &obj->Package.Elements[0]); | |||||
if (params->gpe_handle == NULL || | if (params->gpe_handle == NULL || | ||||
acpi_PkgInt32(obj, 1, ¶ms->gpe_bit) != 0) | acpi_PkgInt32(obj, 1, ¶ms->gpe_bit) != 0) | ||||
goto out; | goto out; | ||||
break; | break; | ||||
default: | default: | ||||
device_printf(dev, "_GPE has invalid type %d\n", obj->Type); | device_printf(dev, "_GPE has invalid type %d\n", obj->Type); | ||||
goto out; | goto out; | ||||
} | } | ||||
/* Store the values we got from the namespace for attach. */ | /* Store the values we got from the namespace for attach. */ | ||||
acpi_set_private(dev, params); | acpi_set_private(dev, params); | ||||
/* | /* | ||||
* Check for a duplicate probe. This can happen when a probe | * Check for a duplicate probe. This can happen when a probe via ECDT | ||||
* via ECDT succeeded already. If this is a duplicate, disable | * succeeded already. If this is a duplicate, disable this device. | ||||
* this device. | |||||
*/ | */ | ||||
peer = devclass_get_device(acpi_ec_devclass, params->uid); | peer = devclass_get_device(acpi_ec_devclass, params->uid); | ||||
if (peer != NULL && device_is_alive(peer)){ | if (peer == NULL || !device_is_alive(peer)) | ||||
ret = ENXIO; | ret = 0; | ||||
else | |||||
device_disable(dev); | device_disable(dev); | ||||
} | |||||
} | |||||
if (buf.Pointer) | |||||
AcpiOsFree(buf.Pointer); | |||||
out: | out: | ||||
if (ret <= 0) { | if (ret <= 0) { | ||||
snprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s", | snprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s", | ||||
params->gpe_bit, (params->glk) ? ", GLK" : "", | params->gpe_bit, (params->glk) ? ", GLK" : "", | ||||
ecdt ? ", ECDT" : ""); | ecdt ? ", ECDT" : ""); | ||||
device_set_desc_copy(dev, desc); | device_set_desc_copy(dev, desc); | ||||
} else | } else | ||||
free(params, M_TEMP); | free(params, M_TEMP); | ||||
if (buf.Pointer) | |||||
AcpiOsFree(buf.Pointer); | |||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
acpi_ec_attach(device_t dev) | acpi_ec_attach(device_t dev) | ||||
{ | { | ||||
struct acpi_ec_softc *sc; | struct acpi_ec_softc *sc; | ||||
struct acpi_ec_params *params; | struct acpi_ec_params *params; | ||||
▲ Show 20 Lines • Show All 578 Lines • Show Last 20 Lines |