* added the beginnings of an acpi_thermal driver.
* currently should detect thermal zones and allow interrogation of their current and critical (possibly HOT) temps. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16562 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
f19839c230
commit
90200dfec1
@ -1,4 +1,5 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers power ;
|
SubDir HAIKU_TOP src add-ons kernel drivers power ;
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_button ;
|
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_button ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_thermal ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_ns_dump ;
|
SubInclude HAIKU_TOP src add-ons kernel drivers power acpi_ns_dump ;
|
@ -66,6 +66,7 @@ void dump_acpi_namespace(char *root, void *buf, size_t* num_bytes, int indenting
|
|||||||
sprintf(tabs, "%s|--- ", tabs);
|
sprintf(tabs, "%s|--- ", tabs);
|
||||||
depth = sizeof(char) * 5 * indenting + sizeof(char); // index into result where the device name will be.
|
depth = sizeof(char) * 5 * indenting + sizeof(char); // index into result where the device name will be.
|
||||||
|
|
||||||
|
dprintf("acpi_ns_dump: recursing from %s\n", root);
|
||||||
while (acpi->get_next_entry(ACPI_TYPE_ANY, root, result, 255, &counter) == B_OK) {
|
while (acpi->get_next_entry(ACPI_TYPE_ANY, root, result, 255, &counter) == B_OK) {
|
||||||
type = acpi->get_object_type(result);
|
type = acpi->get_object_type(result);
|
||||||
sprintf(output, "%s%s", tabs, result + depth);
|
sprintf(output, "%s%s", tabs, result + depth);
|
||||||
|
15
src/add-ons/kernel/drivers/power/acpi_thermal/Jamfile
Normal file
15
src/add-ons/kernel/drivers/power/acpi_thermal/Jamfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel drivers power acpi_thermal ;
|
||||||
|
|
||||||
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
|
if $(TARGET_PLATFORM) != haiku {
|
||||||
|
# Needed for <ACPI.h>. Unfortunately we also get the other headers there,
|
||||||
|
# that we don't really want.
|
||||||
|
UsePublicHeaders drivers ;
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelAddon acpi_thermal : kernel drivers bin :
|
||||||
|
acpi_thermal.c
|
||||||
|
;
|
||||||
|
|
||||||
|
Depends acpi_thermal : acpi ;
|
277
src/add-ons/kernel/drivers/power/acpi_thermal/acpi_thermal.c
Normal file
277
src/add-ons/kernel/drivers/power/acpi_thermal/acpi_thermal.c
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/* ++++++++++
|
||||||
|
ACPI Generic Thermal Zone Driver.
|
||||||
|
Obtains general status of passive devices, monitors / sets critical temperatures
|
||||||
|
Controls active devices.
|
||||||
|
+++++ */
|
||||||
|
#include "acpi_thermal_dev.h"
|
||||||
|
#include "acpi_thermal.h"
|
||||||
|
|
||||||
|
acpi_module_info *acpi;
|
||||||
|
|
||||||
|
static thermal_dev *device_list = NULL;
|
||||||
|
static sem_id dev_list_lock = -1;
|
||||||
|
static int device_count = 0;
|
||||||
|
|
||||||
|
static char **device_names = NULL;
|
||||||
|
|
||||||
|
/* Enumerates the devices of ACPI_THERMAL_TYPE
|
||||||
|
* looking for devices with _CRT and _TMP methods.
|
||||||
|
* Those devices, be they passive or active
|
||||||
|
* are usefull things to monitor / control.
|
||||||
|
*/
|
||||||
|
void enumerate_devices (char* parent)
|
||||||
|
{
|
||||||
|
char result[255];
|
||||||
|
void *counter = NULL;
|
||||||
|
thermal_dev *td = NULL;
|
||||||
|
|
||||||
|
acpi_object_type buf;
|
||||||
|
size_t bufsize = sizeof(buf);
|
||||||
|
|
||||||
|
while (acpi->get_next_entry(ACPI_TYPE_THERMAL, parent, result, 255, &counter) == B_OK) {
|
||||||
|
if ((acpi->evaluate_method(result, "_TMP", &buf, bufsize, NULL, 0) == B_OK) &&
|
||||||
|
(acpi->evaluate_method(result, "_CRT", &buf, bufsize, NULL, 0) == B_OK))
|
||||||
|
{
|
||||||
|
td = (thermal_dev *) malloc(sizeof(thermal_dev));
|
||||||
|
if (td != NULL) {
|
||||||
|
td->open = 0;
|
||||||
|
td->num = device_count;
|
||||||
|
dprintf("acpi_thermal: Adding thermal device from: %s\n", result);
|
||||||
|
td->path = malloc(sizeof(char) * strlen(result) + 1);
|
||||||
|
strcpy(td->path, result);
|
||||||
|
|
||||||
|
acquire_sem(dev_list_lock);
|
||||||
|
td->next = device_list;
|
||||||
|
device_list = td;
|
||||||
|
device_count++;
|
||||||
|
release_sem(dev_list_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerate_devices(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup_published_names(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dprintf("acpi_thermal: cleanup_published_names()\n");
|
||||||
|
if (device_names) {
|
||||||
|
for (i = 0; device_names[i]; i++){
|
||||||
|
free(device_names[i]);
|
||||||
|
}
|
||||||
|
free(device_names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
init_hardware (void)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
init_driver (void)
|
||||||
|
{
|
||||||
|
if (get_module(B_ACPI_MODULE_NAME, (module_info **)&acpi) < 0) {
|
||||||
|
dprintf("Failed to get ACPI module\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dev_list_lock = create_sem(1, "dev_list_lock")) < 0) {
|
||||||
|
put_module(B_ACPI_MODULE_NAME);
|
||||||
|
return dev_list_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
enumerate_devices("\\");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
uninit_driver (void)
|
||||||
|
{
|
||||||
|
thermal_dev *td;
|
||||||
|
acquire_sem(dev_list_lock);
|
||||||
|
td = device_list;
|
||||||
|
|
||||||
|
while (td != NULL) {
|
||||||
|
device_list = td->next;
|
||||||
|
device_count--;
|
||||||
|
|
||||||
|
free(td->path);
|
||||||
|
free(td);
|
||||||
|
td = device_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_sem(dev_list_lock);
|
||||||
|
|
||||||
|
put_module(B_ACPI_MODULE_NAME);
|
||||||
|
|
||||||
|
cleanup_published_names();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
acpi_thermal_open (const char *name, uint32 flags, void** cookie)
|
||||||
|
{
|
||||||
|
thermal_dev *td;
|
||||||
|
int devnum = atoi(name + strlen(basename));
|
||||||
|
|
||||||
|
acquire_sem(dev_list_lock);
|
||||||
|
for (td = device_list; td; td = td->next) {
|
||||||
|
if (td->num == devnum) {
|
||||||
|
dprintf("acpi_thermal: opening ACPI path %s\n", td->path);
|
||||||
|
td->open++;
|
||||||
|
*cookie = td;
|
||||||
|
|
||||||
|
release_sem(dev_list_lock);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_sem(dev_list_lock);
|
||||||
|
|
||||||
|
*cookie = NULL;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
acpi_thermal_read (void* cookie, off_t position, void *buf, size_t* num_bytes)
|
||||||
|
{
|
||||||
|
acpi_thermal_type therm_info;
|
||||||
|
if (*num_bytes < 1)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
if (position == 0) {
|
||||||
|
dprintf("acpi_thermal: read()\n");
|
||||||
|
acpi_thermal_control(cookie, drvOpGetThermalType, &therm_info, 0);
|
||||||
|
sprintf((char *)buf, "ACPI Thermal Device %u\n", therm_info.devnum);
|
||||||
|
*num_bytes = strlen((char *)buf);
|
||||||
|
|
||||||
|
sprintf((char *)buf + *num_bytes, " Critical Temperature: %lu.%lu K\n", (therm_info.critical_temp / 10), (therm_info.critical_temp % 10));
|
||||||
|
*num_bytes = strlen((char *)buf);
|
||||||
|
|
||||||
|
sprintf((char *)buf + *num_bytes, " Current Temperature: %lu.%lu K\n", (therm_info.current_temp / 10), (therm_info.current_temp % 10));
|
||||||
|
*num_bytes = strlen((char *)buf);
|
||||||
|
|
||||||
|
if (therm_info.hot_temp > 0) {
|
||||||
|
sprintf((char *)buf, "Hot Temperature: %lu.%lu K\n", (therm_info.hot_temp / 10), (therm_info.hot_temp % 10));
|
||||||
|
*num_bytes = strlen((char *)buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*num_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
acpi_thermal_write (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
acpi_thermal_control (void* cookie, uint32 op, void* arg, size_t len)
|
||||||
|
{
|
||||||
|
status_t err = B_ERROR;
|
||||||
|
|
||||||
|
thermal_dev *td = (thermal_dev *)cookie;
|
||||||
|
acpi_thermal_type *att = NULL;
|
||||||
|
|
||||||
|
acpi_object_type buf;
|
||||||
|
size_t bufsize = sizeof(buf);
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case drvOpGetThermalType: {
|
||||||
|
dprintf("acpi_thermal: GetThermalType()\n");
|
||||||
|
att = (acpi_thermal_type *)arg;
|
||||||
|
|
||||||
|
att->devnum = td->num;
|
||||||
|
err = acpi->evaluate_method(td->path, "_CRT", &buf, bufsize, NULL, 0);
|
||||||
|
att->critical_temp = buf.data.integer;
|
||||||
|
err = acpi->evaluate_method(td->path, "_TMP", &buf, bufsize, NULL, 0);
|
||||||
|
att->current_temp = buf.data.integer;
|
||||||
|
err = acpi->evaluate_method(td->path, "_HOT", &buf, bufsize, NULL, 0);
|
||||||
|
if (err == B_OK) {
|
||||||
|
att->hot_temp = buf.data.integer;
|
||||||
|
} else {
|
||||||
|
att->hot_temp = 0;
|
||||||
|
}
|
||||||
|
dprintf("acpi_thermal: GotBasicTemperatures()\n");
|
||||||
|
|
||||||
|
// TODO: Fill this out
|
||||||
|
att->passive_count = 0;
|
||||||
|
att->passive_package = NULL;
|
||||||
|
|
||||||
|
att->active_count = 0;
|
||||||
|
att->active_devices = NULL;
|
||||||
|
|
||||||
|
err = B_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
acpi_thermal_close (void* cookie)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
acpi_thermal_free (void* cookie)
|
||||||
|
{
|
||||||
|
thermal_dev *td = (thermal_dev *)cookie;
|
||||||
|
|
||||||
|
acquire_sem(dev_list_lock);
|
||||||
|
td->open--;
|
||||||
|
release_sem(dev_list_lock);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_hooks acpi_thermal_hooks = {
|
||||||
|
acpi_thermal_open, /* -> open entry point */
|
||||||
|
acpi_thermal_close, /* -> close entry point */
|
||||||
|
acpi_thermal_free, /* -> free cookie */
|
||||||
|
acpi_thermal_control, /* -> control entry point */
|
||||||
|
acpi_thermal_read, /* -> read entry point */
|
||||||
|
acpi_thermal_write, /* -> write entry point */
|
||||||
|
NULL, NULL, NULL, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
const char**
|
||||||
|
publish_devices()
|
||||||
|
{
|
||||||
|
thermal_dev *td;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dprintf("acpi_thermal: publish_devices()\n");
|
||||||
|
|
||||||
|
cleanup_published_names();
|
||||||
|
|
||||||
|
acquire_sem(dev_list_lock);
|
||||||
|
device_names = (char **) malloc(sizeof(char*) * (device_count + 1));
|
||||||
|
if (device_names) {
|
||||||
|
for (i = 0, td = device_list; td; td = td->next) {
|
||||||
|
if ((device_names[i] = (char *) malloc(strlen(basename) + 4))) {
|
||||||
|
sprintf(device_names[i], "%s%d", basename, td->num);
|
||||||
|
dprintf("acpi_thermal: Publishing \"/dev/%s\"\n", device_names[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
device_names[i] = NULL;
|
||||||
|
}
|
||||||
|
release_sem(dev_list_lock);
|
||||||
|
|
||||||
|
return (const char**) device_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_hooks*
|
||||||
|
find_device(const char* name)
|
||||||
|
{
|
||||||
|
return &acpi_thermal_hooks;
|
||||||
|
}
|
43
src/add-ons/kernel/drivers/power/acpi_thermal/acpi_thermal.h
Normal file
43
src/add-ons/kernel/drivers/power/acpi_thermal/acpi_thermal.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* ++++++++++
|
||||||
|
Public interface to the ACPI thermal device driver.
|
||||||
|
+++++ */
|
||||||
|
#ifndef _ACPI_THERMAL_H
|
||||||
|
#define _ACPI_THERMAL_H
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <ACPI.h>
|
||||||
|
|
||||||
|
enum { /* ioctl op-codes */
|
||||||
|
drvOpGetThermalType = B_DEVICE_OP_CODES_END + 10001,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct acpi_thermal_active_object acpi_thermal_active_object;
|
||||||
|
typedef struct acpi_thermal_type acpi_thermal_type;
|
||||||
|
|
||||||
|
struct acpi_thermal_type {
|
||||||
|
/* Published thermal device number */
|
||||||
|
int devnum;
|
||||||
|
|
||||||
|
/* Required fields for thermal devices */
|
||||||
|
uint32 critical_temp;
|
||||||
|
uint32 current_temp;
|
||||||
|
|
||||||
|
/* Optional HOT temp, S4 sleep threshold */
|
||||||
|
uint32 hot_temp;
|
||||||
|
|
||||||
|
/* List of acpi_objects_types assigned to the passive device list */
|
||||||
|
uint32 passive_count;
|
||||||
|
acpi_object_type *passive_package;
|
||||||
|
|
||||||
|
/* List of acpi_thermal_active_objects that can actively manage this thermal device */
|
||||||
|
uint32 active_count;
|
||||||
|
acpi_thermal_active_object *active_devices;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct acpi_thermal_active_object {
|
||||||
|
uint32 threshold_temp;
|
||||||
|
acpi_object_type *active_package;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _ACPI_THERMAL_H */
|
@ -0,0 +1,44 @@
|
|||||||
|
/* ++++++++++
|
||||||
|
ACPI Generic Thermal Zone Driver.
|
||||||
|
Obtains general status of passive devices, monitors / sets critical temperatures
|
||||||
|
Controls active devices.
|
||||||
|
+++++ */
|
||||||
|
#ifndef _ACPI_THERMAL_DEV_H
|
||||||
|
#define _ACPI_THERMAL_DEV_H
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <Errors.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <ACPI.h>
|
||||||
|
|
||||||
|
/* Base Namespace devices are published to */
|
||||||
|
static const char *basename = "power/thermal/";
|
||||||
|
|
||||||
|
typedef struct thermal_dev thermal_dev;
|
||||||
|
struct thermal_dev
|
||||||
|
{
|
||||||
|
thermal_dev *next;
|
||||||
|
|
||||||
|
int num;
|
||||||
|
int open;
|
||||||
|
char* path;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* builds the device lsit
|
||||||
|
*/
|
||||||
|
void enumerate_devices (char* base);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frees allocated memory to device list entries
|
||||||
|
*/
|
||||||
|
void cleanup_published_names (void);
|
||||||
|
|
||||||
|
static status_t acpi_thermal_control (void* cookie, uint32 op, void* arg, size_t len);
|
||||||
|
|
||||||
|
#endif /* _ACPI_THERMAL_DEV_H */
|
Loading…
Reference in New Issue
Block a user