moved acpi_thermal to new driver API

improved a bit the read output
published the acpi device module
minor cleanup in pci module


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19397 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2006-11-30 00:36:36 +00:00
parent 26417177e7
commit 66581f3731
6 changed files with 216 additions and 243 deletions

View File

@ -255,5 +255,6 @@ _EXPORT module_info *modules[] = {
(module_info *) &acpi_module,
(module_info *) &sACPIModule,
(module_info *) &acpi_ns_dump_module,
(module_info *) &gACPIDeviceModule,
NULL
};

View File

@ -63,6 +63,8 @@ extern struct acpi_module_info acpi_module;
extern pnp_devfs_driver_info acpi_ns_dump_module;
extern acpi_device_module_info gACPIDeviceModule;
void enable_fixed_event (uint32 event);
void disable_fixed_event (uint32 event);

View File

@ -121,7 +121,7 @@ pci_module_register_child_devices(void *cookie)
{ B_DRIVER_MAPPING, B_STRING_TYPE, { string: "%"PCI_DEVICE_VENDOR_ID_ITEM "%|_%" PCI_DEVICE_DEVICE_ID_ITEM "%" }},
// ToDo: this is a hack
{ B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: device.class_base == 1 ? "drivers/dev/disk" : "drivers/dev" }},
{ B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: device.class_base == PCI_mass_storage ? "drivers/dev/disk" : "drivers/dev" }},
{ NULL }
};
device_node_handle deviceNode;

View File

@ -3,167 +3,72 @@
Obtains general status of passive devices, monitors / sets critical temperatures
Controls active devices.
+++++ */
#include "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>
#include <pnp_devfs.h>
#include "acpi_thermal.h"
int32 api_version = B_CUR_DRIVER_API_VERSION;
acpi_module_info *acpi;
#define ACPI_THERMAL_MODULE_NAME "drivers/bin/acpi_thermal/acpi_device_v1"
static thermal_dev *device_list = NULL;
static sem_id dev_list_lock = -1;
static int device_count = 0;
/* Base Namespace devices are published to */
#define ACPI_THERMAL_BASENAME "acpi/thermal/%d"
static char **device_names = NULL;
// name of pnp generator of path ids
#define ACPI_THERMAL_PATHID_GENERATOR "acpi_thermal/path_id"
/* 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)
device_manager_info *gDeviceManager;
typedef struct acpi_ns_device_info {
device_node_handle node;
acpi_device_module_info *acpi;
acpi_device acpi_cookie;
} acpi_thermal_device_info;
status_t acpi_thermal_control(acpi_thermal_device_info* device, uint32 op, void* arg, size_t len);
static status_t
acpi_thermal_open(acpi_thermal_device_info *device, uint32 flags, void** cookie)
{
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("\\");
*cookie = device;
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)
acpi_thermal_read(acpi_thermal_device_info* device, off_t position, void *buf, size_t* num_bytes)
{
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)
{
int i;
acpi_thermal_type therm_info;
if (*num_bytes < 1)
return B_IO_ERROR;
if (position == 0) {
size_t max_len = *num_bytes;
char *str = (char *)buf;
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",
acpi_thermal_control(device, drvOpGetThermalType, &therm_info, 0);
snprintf(str, max_len, " 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",
max_len -= strlen(str);
str += strlen(str);
snprintf(str, max_len, " 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 + *num_bytes, " Hot Temperature: %lu.%lu K\n",
max_len -= strlen(str);
str += strlen(str);
snprintf(str, max_len, " Hot Temperature: %lu.%lu K\n",
(therm_info.hot_temp / 10), (therm_info.hot_temp % 10));
*num_bytes = strlen((char *)buf);
}
if (therm_info.passive_package) {
@ -183,6 +88,7 @@ acpi_thermal_read (void* cookie, off_t position, void *buf, size_t* num_bytes)
*/
free(therm_info.passive_package);
}
*num_bytes = strlen((char *)buf);
} else {
*num_bytes = 0;
}
@ -190,19 +96,19 @@ acpi_thermal_read (void* cookie, off_t position, void *buf, size_t* num_bytes)
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
acpi_thermal_control (acpi_thermal_device_info* device, uint32 op, void* arg, size_t len)
{
status_t err = B_ERROR;
thermal_dev *td = (thermal_dev *)cookie;
char objname[255];
acpi_thermal_type *att = NULL;
size_t bufsize = sizeof(acpi_object_type);
@ -214,12 +120,11 @@ acpi_thermal_control (void* cookie, uint32 op, void* arg, size_t len)
att = (acpi_thermal_type *)arg;
// Read basic temperature thresholds.
att->devnum = td->num;
err = acpi->evaluate_method(td->path, "_CRT", &buf, bufsize, NULL, 0);
err = device->acpi->evaluate_method(device->acpi_cookie, "_CRT", &buf, bufsize, NULL, 0);
att->critical_temp = buf.data.integer;
err = acpi->evaluate_method(td->path, "_TMP", &buf, bufsize, NULL, 0);
err = device->acpi->evaluate_method(device->acpi_cookie, "_TMP", &buf, bufsize, NULL, 0);
att->current_temp = buf.data.integer;
err = acpi->evaluate_method(td->path, "_HOT", &buf, bufsize, NULL, 0);
err = device->acpi->evaluate_method(device->acpi_cookie, "_HOT", &buf, bufsize, NULL, 0);
if (err == B_OK) {
att->hot_temp = buf.data.integer;
} else {
@ -229,8 +134,7 @@ acpi_thermal_control (void* cookie, uint32 op, void* arg, size_t len)
// Read Passive Cooling devices
att->passive_package = NULL;
sprintf(objname, "%s._PSL", td->path);
err = acpi->get_object(objname, &(att->passive_package));
err = device->acpi->get_object(device->acpi_cookie, "_PSL", &(att->passive_package));
att->active_count = 0;
att->active_devices = NULL;
@ -242,63 +146,176 @@ acpi_thermal_control (void* cookie, uint32 op, void* arg, size_t len)
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
static float
acpi_thermal_support(device_node_handle parent, bool *_noConnection)
{
char *bus;
uint32 device_type;
// make sure parent is really the ACPI bus manager
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false) != B_OK) {
dprintf("no bus\n");
return 0.0;
}
if (strcmp(bus, "acpi")) {
dprintf("bad bus\n");
goto err;
}
// check whether it's really a thermal Device
if (gDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM, &device_type, false) != B_OK
|| device_type != ACPI_TYPE_THERMAL) {
dprintf("bad type\n");
goto err;
}
// TODO check there are _CRT and _TMP ?
free(bus);
return 0.6;
err:
free(bus);
return 0.0;
}
static status_t
acpi_thermal_init_device(device_node_handle node, void *user_cookie, void **cookie)
{
acpi_thermal_device_info *device;
status_t res;
device = (acpi_thermal_device_info *)calloc(1, sizeof(*device));
if (device == NULL)
return B_NO_MEMORY;
device->node = node;
// register it everywhere
res = gDeviceManager->init_driver(gDeviceManager->get_parent(node), NULL,
(driver_module_info **)&device->acpi, (void**) &device->acpi_cookie);
if (res != B_OK)
goto err;
*cookie = device;
return B_OK;
err:
free(device);
return res;
}
static status_t
acpi_thermal_uninit_device(acpi_thermal_device_info *device)
{
gDeviceManager->uninit_driver(gDeviceManager->get_parent(device->node));
free(device);
return B_OK;
}
static status_t
acpi_thermal_added(device_node_handle node)
{
int path_id;
char name[128];
path_id = gDeviceManager->create_id(ACPI_THERMAL_PATHID_GENERATOR);
if (path_id < 0) {
return B_ERROR;
}
snprintf(name, sizeof(name), ACPI_THERMAL_BASENAME, path_id);
{
device_attr attrs[] = {
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: ACPI_THERMAL_MODULE_NAME }},
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: "acpi_thermal" }},
// we want devfs on top of us (who wouldn't?)
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: PNP_DEVFS_MODULE_NAME }},
{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, { string: ACPI_THERMAL_PATHID_GENERATOR }},
{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: path_id }},
// tell which name we want to have in devfs
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
{ NULL }
};
return gDeviceManager->register_device(node, attrs, NULL, &node);
}
}
static status_t
std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
{}
};
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;
}
pnp_devfs_driver_info acpi_thermal_dump_module = {
{
{
ACPI_THERMAL_MODULE_NAME,
0,
std_ops
},
acpi_thermal_support,
acpi_thermal_added,
acpi_thermal_init_device,
(status_t (*) (void *))acpi_thermal_uninit_device,
NULL
},
(pnp_device_open_hook) &acpi_thermal_open,
acpi_thermal_close,
acpi_thermal_free,
(device_control_hook) &acpi_thermal_control,
(device_read_hook) acpi_thermal_read,
acpi_thermal_write,
NULL,
NULL,
NULL,
NULL
};
module_info *modules[] = {
(module_info *)&acpi_thermal_dump_module,
NULL
};

View File

@ -16,9 +16,6 @@ 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;
@ -41,4 +38,4 @@ struct acpi_thermal_active_object {
acpi_object_type *active_package;
};
#endif /* _ACPI_THERMAL_H */
#endif /* _ACPI_THERMAL_H */

View File

@ -1,44 +0,0 @@
/* ++++++++++
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 */