/* * Given an object, verify that it's a reference to a device of some sort, * and try to switch it on. * * XXX replication of off/on function code is bad. */ static void acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg) { struct acpi_tz_softc *sc = (struct acpi_tz_softc *)arg; ACPI_HANDLE cooler; ACPI_STATUS status; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); cooler = acpi_GetReference(NULL, obj); if (cooler == NULL) { ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get handle\n")); return_VOID; } ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n", acpi_name(cooler))); status = acpi_pwr_switch_consumer(cooler, ACPI_STATE_D0); if (ACPI_FAILURE(status)) { ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), "failed to activate %s - %s\n", acpi_name(cooler), AcpiFormatException(status)); } return_VOID; }
/* Find dependent devices. When their parent is removed, so are they. */ static int acpi_dock_is_ejd_device(ACPI_HANDLE dock_handle, ACPI_HANDLE handle) { int ret; ACPI_STATUS ret_status; ACPI_BUFFER ejd_buffer; ACPI_OBJECT *obj; ret = 0; ejd_buffer.Pointer = NULL; ejd_buffer.Length = ACPI_ALLOCATE_BUFFER; ret_status = AcpiEvaluateObject(handle, "_EJD", NULL, &ejd_buffer); if (ACPI_FAILURE(ret_status)) goto out; obj = (ACPI_OBJECT *)ejd_buffer.Pointer; if (dock_handle == acpi_GetReference(NULL, obj)) ret = 1; out: if (ejd_buffer.Pointer != NULL) AcpiOsFree(ejd_buffer.Pointer); return (ret); }
/* * Given an object, verify that it's a reference to a device of some sort, * and try to switch it off. */ static void acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg) { ACPI_HANDLE cooler; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); cooler = acpi_GetReference(NULL, obj); if (cooler == NULL) { ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get handle\n")); return_VOID; } ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n", acpi_name(cooler))); acpi_pwr_switch_consumer(cooler, ACPI_STATE_D3); return_VOID; }
static int acpi_ec_probe(device_t dev) { ACPI_BUFFER buf; ACPI_HANDLE h; ACPI_OBJECT *obj; ACPI_STATUS status; device_t peer; char desc[64]; int ecdt; int ret; struct acpi_ec_params *params; static char *ec_ids[] = { "PNP0C09", NULL }; /* Check that this is a device and that EC is not disabled. */ if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec")) return (ENXIO); /* * If probed via ECDT, set description and continue. Otherwise, * we can access the namespace and make sure this is not a * duplicate probe. */ ret = ENXIO; ecdt = 0; buf.Pointer = NULL; buf.Length = ACPI_ALLOCATE_BUFFER; params = acpi_get_private(dev); if (params != NULL) { ecdt = 1; ret = 0; } else if (ACPI_ID_PROBE(device_get_parent(dev), dev, ec_ids)) { params = kmalloc(sizeof(struct acpi_ec_params), M_TEMP, M_WAITOK | M_ZERO); h = acpi_get_handle(dev); /* * Read the unit ID to check for duplicate attach and the * global lock value to see if we should acquire it when * accessing the EC. */ status = acpi_GetInteger(h, "_UID", ¶ms->uid); if (ACPI_FAILURE(status)) params->uid = 0; status = acpi_GetInteger(h, "_GLK", ¶ms->glk); if (ACPI_FAILURE(status)) params->glk = 0; /* * Evaluate the _GPE method to find the GPE bit used by the EC to * signal status (SCI). If it's a package, it contains a reference * and GPE bit, similar to _PRW. */ status = AcpiEvaluateObject(h, "_GPE", NULL, &buf); if (ACPI_FAILURE(status)) { device_printf(dev, "can't evaluate _GPE - %s\n", AcpiFormatException(status)); goto out; } obj = (ACPI_OBJECT *)buf.Pointer; if (obj == NULL) goto out; switch (obj->Type) { case ACPI_TYPE_INTEGER: params->gpe_handle = NULL; params->gpe_bit = obj->Integer.Value; break; case ACPI_TYPE_PACKAGE: if (!ACPI_PKG_VALID(obj, 2)) goto out; params->gpe_handle = acpi_GetReference(NULL, &obj->Package.Elements[0]); if (params->gpe_handle == NULL || acpi_PkgInt32(obj, 1, ¶ms->gpe_bit) != 0) goto out; break; default: device_printf(dev, "_GPE has invalid type %d\n", obj->Type); goto out; } /* Store the values we got from the namespace for attach. */ acpi_set_private(dev, params); /* * Check for a duplicate probe. This can happen when a probe * via ECDT succeeded already. If this is a duplicate, disable * this device. */ peer = devclass_get_device(acpi_ec_devclass, params->uid); if (peer == NULL || !device_is_alive(peer)) ret = 0; else device_disable(dev); } out: if (ret == 0) { ksnprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s", params->gpe_bit, (params->glk) ? ", GLK" : "", ecdt ? ", ECDT" : ""); device_set_desc_copy(dev, desc); } if (ret > 0 && params) kfree(params, M_TEMP); if (buf.Pointer) AcpiOsFree(buf.Pointer); return (ret); }