acpi_status bm_get_status ( BM_DEVICE *device) { acpi_status status = AE_OK; if (!device) { return AE_BAD_PARAMETER; } device->status = BM_STATUS_UNKNOWN; /* * Dynamic Status? * --------------- * If _STA isn't present we just return the default status. */ if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) { device->status = BM_STATUS_DEFAULT; return AE_OK; } /* * Evaluate _STA: * -------------- */ status = bm_evaluate_simple_integer(device->acpi_handle, "_STA", &(device->status)); return status; }
acpi_status bm_get_power_state ( BM_NODE *node) { acpi_status status = AE_OK; BM_DEVICE *device = NULL; FUNCTION_TRACE("bm_get_power_state"); if (!node || !node->parent) { return_ACPI_STATUS(AE_BAD_PARAMETER); } device = &(node->device); device->power.state = ACPI_STATE_UNKNOWN; /* * Power Control? * -------------- * If this device isn't directly power manageable (e.g. doesn't * include _PR0/_PS0) then there's nothing to do (state is static). */ if (!BM_IS_POWER_CONTROL(device)) { return_ACPI_STATUS(AE_OK); } /* * Parent Present? * --------------- * Make sure the parent is present before mucking with the child. */ if (!BM_NODE_PRESENT(node->parent)) { return_ACPI_STATUS(AE_NOT_EXIST); } /* * Get Power State: * ---------------- * Either directly (via _PSC) or inferred (via power resource * dependencies). */ if (BM_IS_POWER_STATE(device)) { status = bm_evaluate_simple_integer(device->acpi_handle, "_PSC", &(device->power.state)); } else { status = bm_get_inferred_power_state(device); } if (ACPI_SUCCESS(status)) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Device [%02x] is at power state [D%d].\n", device->handle, device->power.state)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Error getting power state for device [%02x]\n", device->handle)); } return_ACPI_STATUS(status); }
static int ac_osl_proc_read_status ( char *page, char **start, off_t off, int count, int *eof, void *context) { acpi_status status = AE_OK; AC_CONTEXT *ac_adapter = NULL; char *p = page; int len; if (!context) { goto end; } ac_adapter = (AC_CONTEXT*)context; /* don't get status more than once for a single proc read */ if (off != 0) { goto end; } status = bm_evaluate_simple_integer(ac_adapter->acpi_handle, "_PSR", &(ac_adapter->is_online)); if (ACPI_FAILURE(status)) { p += sprintf(p, "Error reading AC Adapter status\n"); goto end; } if (ac_adapter->is_online) { p += sprintf(p, "Status: %s\n", AC_ON_LINE); } else { p += sprintf(p, "Status: %s\n", AC_OFF_LINE); } end: len = (p - page); if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len>count) len = count; if (len<0) len = 0; return(len); }
acpi_status ec_install_gpe_handler ( EC_CONTEXT *ec) { acpi_status status = AE_OK; FUNCTION_TRACE("ec_install_gpe_handler"); if (!ec) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Evaluate _GPE: * -------------- * Evaluate the "_GPE" object (required) to find out which GPE bit * is used by this EC to signal events (SCIs). */ status = bm_evaluate_simple_integer(ec->acpi_handle, "_GPE", &(ec->gpe_bit)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Install GPE Handler: * -------------------- * Install a handler for this EC's GPE bit. */ status = acpi_install_gpe_handler(ec->gpe_bit, ACPI_EVENT_EDGE_TRIGGERED, &ec_gpe_handler, ec); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "acpi_install_gpe_handler() failed for GPE bit [%02x] with status [%08x].\n", ec->gpe_bit, status)); ec->gpe_bit = EC_GPE_UNKNOWN; return_ACPI_STATUS(status); } return_ACPI_STATUS(status); }
acpi_status tz_get_temperature ( TZ_CONTEXT *tz) { acpi_status status = AE_OK; FUNCTION_TRACE("tz_get_temperature"); if (!tz) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Evaluate the _TMP method to get the current temperature. */ status = bm_evaluate_simple_integer(tz->acpi_handle, "_TMP", &(tz->policy.temperature)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %d d_k\n", tz->policy.temperature)); return_ACPI_STATUS(status); }
acpi_status ec_add_device( BM_HANDLE device_handle, void **context) { acpi_status status = AE_OK; BM_DEVICE *device = NULL; EC_CONTEXT *ec = NULL; u8 gpe_handler = FALSE; u8 space_handler = FALSE; FUNCTION_TRACE("ec_add_device"); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding EC device [%02x].\n", device_handle)); if (!context || *context) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Get information on this device. */ status = bm_get_device_info(device_handle, &device); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Allocate a new EC_CONTEXT structure. */ ec = acpi_os_callocate(sizeof(EC_CONTEXT)); if (!ec) { return_ACPI_STATUS(AE_NO_MEMORY); } ec->device_handle = device->handle; ec->acpi_handle = device->acpi_handle; /* * Get the I/O port addresses for the command/status and data ports. */ status = ec_get_port_values(ec); if (ACPI_FAILURE(status)) { goto end; } /* * See if we need to obtain the global lock for EC transactions. */ status = bm_evaluate_simple_integer(ec->acpi_handle, "_GLK", &ec->use_global_lock); if (status == AE_NOT_FOUND) { ec->use_global_lock = 0; } else if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "EC _GLK failed\n")); goto end; } /* * Install a handler for servicing this EC's GPE. */ status = ec_install_gpe_handler(ec); if (ACPI_FAILURE(status)) { goto end; } else { gpe_handler = TRUE; } /* * Install a handler for servicing this EC's address space. */ status = ec_install_space_handler(ec); if (ACPI_FAILURE(status)) { goto end; } else { space_handler = TRUE; } /* * Create a semaphore to serialize EC transactions. */ status = acpi_os_create_semaphore(1,1, &(ec->mutex)); if (ACPI_FAILURE(status)) { goto end; } /* * Context now contains information specific to this EC. Note * that we'll get this pointer back on every ec_request() and * ec_notify(). */ *context = ec; ec_print(ec); end: if (ACPI_FAILURE(status)) { if (gpe_handler) { ec_remove_gpe_handler(ec); } if (space_handler) { ec_remove_space_handler(ec); } if (ec->mutex) { acpi_os_delete_semaphore(ec->mutex); } acpi_os_free(ec); } return_ACPI_STATUS(status); }
acpi_status tz_add_device ( BM_HANDLE device_handle, void **context) { acpi_status status = AE_OK; TZ_CONTEXT *tz = NULL; BM_DEVICE *device = NULL; acpi_handle tmp_handle = NULL; static u32 zone_count = 0; FUNCTION_TRACE("tz_add_device"); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding thermal zone [%02x].\n", device_handle)); if (!context || *context) { ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Invalid context for device [%02x].\n", device_handle)); return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Get information on this device. */ status = bm_get_device_info(device_handle, &device); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Allocate a new Thermal Zone device. */ tz = acpi_os_callocate(sizeof(TZ_CONTEXT)); if (!tz) { return_ACPI_STATUS(AE_NO_MEMORY); } tz->device_handle = device->handle; tz->acpi_handle = device->acpi_handle; /* TBD: How to manage 'uid' when zones are Pn_p? */ sprintf(tz->uid, "%d", zone_count++); /* * Temperature: * ------------ * Make sure we can read the zone's current temperature (_TMP). * If we can't, there's no use in doing any policy (abort). */ status = tz_get_temperature(tz); if (ACPI_FAILURE(status)) goto end; /* * Polling Frequency: * ------------------ * If _TZP doesn't exist use the OS default polling frequency. */ status = bm_evaluate_simple_integer(tz->acpi_handle, "_TZP", &(tz->policy.polling_freq)); if (ACPI_FAILURE(status)) { tz->policy.polling_freq = TZP; } status = AE_OK; /* * Cooling Preference: * ------------------- * Default to ACTIVE (noisy) cooling until policy decides otherwise. * Note that _SCP is optional. */ tz_set_cooling_preference(tz, TZ_COOLING_MODE_ACTIVE); /* * Start Policy: * ------------- * Thermal policy is included in the kernel (this driver) because * of the critical role it plays in avoiding nuclear meltdown. =O */ status = tz_policy_add_device(tz); if (ACPI_FAILURE(status)) goto end; status = tz_osl_add_device(tz); if (ACPI_FAILURE(status)) goto end; *context = tz; tz_print(tz); end: if (ACPI_FAILURE(status)) acpi_os_free(tz); return_ACPI_STATUS(status); }
acpi_status tz_get_thresholds ( TZ_CONTEXT *tz) { acpi_status status = AE_OK; TZ_THRESHOLDS *thresholds = NULL; u32 value = 0; u32 i = 0; FUNCTION_TRACE("acpi_tz_get_thresholds"); if (!tz) { return_ACPI_STATUS(AE_BAD_PARAMETER); } thresholds = &(tz->policy.thresholds); /* Critical Shutdown (required) */ status = bm_evaluate_simple_integer(tz->acpi_handle, "_CRT", &value); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n")); return_ACPI_STATUS(status); } else { thresholds->critical.temperature = value; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%d]\n", thresholds->critical.temperature)); } /* Critical Sleep (optional) */ status = bm_evaluate_simple_integer(tz->acpi_handle, "_HOT", &value); if (ACPI_FAILURE(status)) { thresholds->hot.is_valid = 0; thresholds->hot.temperature = 0; } else { thresholds->hot.is_valid = 1; thresholds->hot.temperature = value; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%d]\n", thresholds->hot.temperature)); } /* Passive: Processors (optional) */ status = bm_evaluate_simple_integer(tz->acpi_handle, "_PSV", &value); if (ACPI_FAILURE(status)) { thresholds->passive.is_valid = 0; thresholds->passive.temperature = 0; } else { thresholds->passive.is_valid = 1; thresholds->passive.temperature = value; status = bm_evaluate_simple_integer(tz->acpi_handle, "_TC1", &value); if (ACPI_FAILURE(status)) { thresholds->passive.is_valid = 0; } thresholds->passive.tc1 = value; status = bm_evaluate_simple_integer(tz->acpi_handle, "_TC2", &value); if (ACPI_FAILURE(status)) { thresholds->passive.is_valid = 0; } thresholds->passive.tc2 = value; status = bm_evaluate_simple_integer(tz->acpi_handle, "_TSP", &value); if (ACPI_FAILURE(status)) { thresholds->passive.is_valid = 0; } thresholds->passive.tsp = value; status = bm_evaluate_reference_list(tz->acpi_handle, "_PSL", &(thresholds->passive.devices)); if (ACPI_FAILURE(status)) { thresholds->passive.is_valid = 0; } if (thresholds->passive.is_valid) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%d]\n", thresholds->passive.temperature)); } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid passive threshold\n")); } } /* Active: Fans, etc. (optional) */ for (i=0; i<TZ_MAX_ACTIVE_THRESHOLDS; i++) { char name[5] = {'_','A','C',('0'+i),'\0'}; status = bm_evaluate_simple_integer(tz->acpi_handle, name, &value); if (ACPI_FAILURE(status)) { thresholds->active[i].is_valid = 0; thresholds->active[i].temperature = 0; break; } thresholds->active[i].temperature = value; name[2] = 'L'; status = bm_evaluate_reference_list(tz->acpi_handle, name, &(thresholds->active[i].devices)); if (ACPI_SUCCESS(status)) { thresholds->active[i].is_valid = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%d]\n", i, thresholds->active[i].temperature)); } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i)); } } return_ACPI_STATUS(AE_OK); }
acpi_status bm_get_pm_capabilities ( BM_NODE *node) { acpi_status status = AE_OK; BM_DEVICE *device = NULL; BM_DEVICE *parent_device = NULL; acpi_handle acpi_handle = NULL; BM_POWER_STATE dx_supported = ACPI_STATE_UNKNOWN; char object_name[5] = {'_','S','0','D','\0'}; u32 i = 0; FUNCTION_TRACE("bm_get_pm_capabilities"); if (!node || !node->parent) { return_ACPI_STATUS(AE_BAD_PARAMETER); } device = &(node->device); parent_device = &(node->parent->device); /* * Power Management Flags: * ----------------------- */ if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PSC", &acpi_handle))) { device->power.flags |= BM_FLAGS_POWER_STATE; } if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_IRC", &acpi_handle))) { device->power.flags |= BM_FLAGS_INRUSH_CURRENT; } if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PRW", &acpi_handle))) { device->power.flags |= BM_FLAGS_WAKE_CAPABLE; } /* * Device Power State: * ------------------- * Note that we can't get the device's power state until we've * initialized all power resources, so for now we just set to * unknown. */ device->power.state = ACPI_STATE_UNKNOWN; /* * Dx Supported in S0: * ------------------- * Figure out which Dx states are supported by this device for the * S0 (working) state. Note that D0 and D3 are required (assumed). */ device->power.dx_supported[ACPI_STATE_S0] = BM_FLAGS_D0_SUPPORT | BM_FLAGS_D3_SUPPORT; if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR1", &acpi_handle))) || (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS1", &acpi_handle)))) { device->power.dx_supported[ACPI_STATE_S0] |= BM_FLAGS_D1_SUPPORT; } if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR2", &acpi_handle))) || (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS2", &acpi_handle)))) { device->power.dx_supported[ACPI_STATE_S0] |= BM_FLAGS_D2_SUPPORT; } /* * Dx Supported in S1-S5: * ---------------------- * Figure out which Dx states are supported by this device for * all other Sx states. */ for (i = ACPI_STATE_S1; i <= ACPI_STATE_S5; i++) { /* * D3 support is assumed (off is always possible!). */ device->power.dx_supported[i] = BM_FLAGS_D3_SUPPORT; /* * Evalute _Sx_d: * ------------- * Which returns the highest (power) Dx state supported in * this system (Sx) state. We convert this value to a bit * mask of supported states (conceptually simpler). */ status = bm_evaluate_simple_integer(device->acpi_handle, object_name, &dx_supported); if (ACPI_SUCCESS(status)) { switch (dx_supported) { case 0: device->power.dx_supported[i] |= BM_FLAGS_D0_SUPPORT; /* fall through */ case 1: device->power.dx_supported[i] |= BM_FLAGS_D1_SUPPORT; /* fall through */ case 2: device->power.dx_supported[i] |= BM_FLAGS_D2_SUPPORT; /* fall through */ case 3: device->power.dx_supported[i] |= BM_FLAGS_D3_SUPPORT; break; } /* * Validate: * --------- * Mask of any states that _Sx_d falsely advertises * (e.g.claims D1 support but neither _PR2 or _PS2 * exist). In other words, S1-S5 can't offer a Dx * state that isn't supported by S0. */ device->power.dx_supported[i] &= device->power.dx_supported[ACPI_STATE_S0]; } object_name[2]++; } return_ACPI_STATUS(AE_OK); }