Commit 40c05507 authored by Andy Grover's avatar Andy Grover Committed by Linus Torvalds

[PATCH] ACPI patch 2/9

This patch adds in the new drivers.

- Support for driverfs
- File/code layout more in the Linux style
- improvements to battery, processor, and thermal support
parent 62c7aea9
/*
* acpi_ac.c - ACPI AC Adapter Driver ($Revision: 22 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include "acpi_bus.h"
#include "acpi_drivers.h"
#define _COMPONENT ACPI_AC_COMPONENT
ACPI_MODULE_NAME ("acpi_ac")
MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
MODULE_LICENSE("GPL");
#define PREFIX "ACPI: "
int acpi_ac_add (struct acpi_device *device);
int acpi_ac_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_ac_driver = {
name: ACPI_AC_DRIVER_NAME,
class: ACPI_AC_CLASS,
ids: ACPI_AC_HID,
ops: {
add: acpi_ac_add,
remove: acpi_ac_remove,
},
};
struct acpi_ac {
acpi_handle handle;
unsigned long state;
};
/* --------------------------------------------------------------------------
AC Adapter Management
-------------------------------------------------------------------------- */
static int
acpi_ac_get_state (
struct acpi_ac *ac)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE("acpi_ac_get_state");
if (!ac)
return_VALUE(-EINVAL);
status = acpi_evaluate_integer(ac->handle, "_PSR", NULL, &ac->state);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error reading AC Adapter state\n"));
ac->state = ACPI_AC_STATUS_UNKNOWN;
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
#include <linux/compatmac.h>
#include <linux/proc_fs.h>
struct proc_dir_entry *acpi_ac_dir = NULL;
static int
acpi_ac_read_state (
char *page,
char **start,
off_t off,
int count,
int *eof,
void *data)
{
struct acpi_ac *ac = (struct acpi_ac *) data;
char *p = page;
int len = 0;
ACPI_FUNCTION_TRACE("acpi_ac_read_state");
if (!ac || (off != 0))
goto end;
if (0 != acpi_ac_get_state(ac)) {
p += sprintf(p, "ERROR: Unable to read AC Adapter state\n");
goto end;
}
p += sprintf(p, "state: ");
switch (ac->state) {
case ACPI_AC_STATUS_OFFLINE:
p += sprintf(p, "off-line\n");
break;
case ACPI_AC_STATUS_ONLINE:
p += sprintf(p, "on-line\n");
break;
default:
p += sprintf(p, "unknown\n");
break;
}
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_VALUE(len);
}
static int
acpi_ac_add_fs (
struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_add_fs");
if (!acpi_ac_dir) {
acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
if (!acpi_ac_dir)
return_VALUE(-ENODEV);
}
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_ac_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
/* 'state' [R] */
entry = create_proc_entry(ACPI_AC_FILE_STATE,
S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create '%s' fs entry\n",
ACPI_AC_FILE_STATE));
else {
entry->read_proc = acpi_ac_read_state;
entry->data = acpi_driver_data(device);
}
return_VALUE(0);
}
static int
acpi_ac_remove_fs (
struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
if (!acpi_ac_dir)
return_VALUE(-ENODEV);
if (acpi_device_dir(device))
remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
return_VALUE(0);
}
/* --------------------------------------------------------------------------
Driver Model
-------------------------------------------------------------------------- */
void
acpi_ac_notify (
acpi_handle handle,
u32 event,
void *data)
{
struct acpi_ac *ac = (struct acpi_ac *) data;
struct acpi_device *device = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_notify");
if (!ac)
return;
if (0 != acpi_bus_get_device(ac->handle, &device))
return_VOID;
switch (event) {
case ACPI_AC_NOTIFY_STATUS:
acpi_ac_get_state(ac);
acpi_bus_generate_event(device, event, (u32) ac->state);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
int
acpi_ac_add (
struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_add");
if (!device)
return_VALUE(-EINVAL);
ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL);
if (!ac)
return_VALUE(-ENOMEM);
memset(ac, 0, sizeof(struct acpi_ac));
ac->handle = device->handle;
sprintf(acpi_device_name(device), "%s", ACPI_AC_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_AC_CLASS);
acpi_driver_data(device) = ac;
result = acpi_ac_get_state(ac);
if (0 != result)
goto end;
result = acpi_ac_add_fs(device);
if (0 != result)
goto end;
status = acpi_install_notify_handler(ac->handle,
ACPI_DEVICE_NOTIFY, acpi_ac_notify, ac);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
ac->state?"on-line":"off-line");
end:
if (0 != result) {
acpi_ac_remove_fs(device);
kfree(ac);
}
return_VALUE(result);
}
int
acpi_ac_remove (
struct acpi_device *device,
int type)
{
acpi_status status = AE_OK;
struct acpi_ac *ac = NULL;
ACPI_FUNCTION_TRACE("acpi_ac_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
ac = (struct acpi_ac *) acpi_driver_data(device);
status = acpi_remove_notify_handler(ac->handle,
ACPI_DEVICE_NOTIFY, acpi_ac_notify);
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error removing notify handler\n"));
acpi_ac_remove_fs(device);
kfree(ac);
return_VALUE(0);
}
int __init
acpi_ac_init (void)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_ac_init");
result = acpi_bus_register_driver(&acpi_ac_driver);
if (0 > result) {
remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
return_VALUE(-ENODEV);
}
return_VALUE(0);
}
void __exit
acpi_ac_exit (void)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_ac_exit");
result = acpi_bus_unregister_driver(&acpi_ac_driver);
if (0 == result)
remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
return_VOID;
}
module_init(acpi_ac_init);
module_exit(acpi_ac_exit);
This diff is collapsed.
This diff is collapsed.
/*
* acpi_bus.h - ACPI Bus Driver ($Revision: 17 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef __ACPI_BUS_H__
#define __ACPI_BUS_H__
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,4))
#include <linux/device.h>
#define CONFIG_LDM
#endif
#include "include/acpi.h"
/* TBD: Make dynamic */
#define ACPI_MAX_HANDLES 10
struct acpi_handle_list {
u32 count;
acpi_handle handles[ACPI_MAX_HANDLES];
};
/* acpi_utils.h */
acpi_status acpi_extract_package (acpi_object *, acpi_buffer *, acpi_buffer *);
acpi_status acpi_evaluate (acpi_handle, acpi_string, acpi_object_list *, acpi_buffer *);
acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *, unsigned long *);
acpi_status acpi_evaluate_reference (acpi_handle, acpi_string, acpi_object_list *, struct acpi_handle_list *);
#ifdef CONFIG_ACPI_BUS
#include <linux/proc_fs.h>
#define ACPI_BUS_FILE_ROOT "acpi"
extern struct proc_dir_entry *acpi_root_dir;
extern FADT_DESCRIPTOR acpi_fadt;
enum acpi_bus_removal_type {
ACPI_BUS_REMOVAL_NORMAL = 0,
ACPI_BUS_REMOVAL_EJECT,
ACPI_BUS_REMOVAL_SUPRISE,
ACPI_BUS_REMOVAL_TYPE_COUNT
};
enum acpi_bus_device_type {
ACPI_BUS_TYPE_DEVICE = 0,
ACPI_BUS_TYPE_POWER,
ACPI_BUS_TYPE_PROCESSOR,
ACPI_BUS_TYPE_THERMAL,
ACPI_BUS_TYPE_SYSTEM,
ACPI_BUS_TYPE_POWER_BUTTON,
ACPI_BUS_TYPE_SLEEP_BUTTON,
ACPI_BUS_DEVICE_TYPE_COUNT
};
struct acpi_driver;
struct acpi_device;
/*
* ACPI Driver
* -----------
*/
typedef int (*acpi_op_add) (struct acpi_device *device);
typedef int (*acpi_op_remove) (struct acpi_device *device, int type);
typedef int (*acpi_op_lock) (struct acpi_device *device, int type);
typedef int (*acpi_op_start) (struct acpi_device *device);
typedef int (*acpi_op_stop) (struct acpi_device *device, int type);
typedef int (*acpi_op_suspend) (struct acpi_device *device, int state);
typedef int (*acpi_op_resume) (struct acpi_device *device, int state);
typedef int (*acpi_op_scan) (struct acpi_device *device);
struct acpi_driver_ops {
acpi_op_add add;
acpi_op_remove remove;
acpi_op_lock lock;
acpi_op_start start;
acpi_op_stop stop;
acpi_op_suspend suspend;
acpi_op_resume resume;
acpi_op_scan scan;
};
struct acpi_driver {
struct list_head node;
char name[80];
char class[80];
int references;
char *ids; /* Supported Hardware IDs */
struct acpi_driver_ops ops;
};
enum acpi_blacklist_predicates
{
all_versions,
less_than_or_equal,
equal,
greater_than_or_equal,
};
struct acpi_blacklist_item
{
char oem_id[7];
char oem_table_id[9];
u32 oem_revision;
acpi_table_type table;
enum acpi_blacklist_predicates oem_revision_predicate;
char *reason;
u32 is_critical_error;
};
/*
* ACPI Device
* -----------
*/
/* Status (_STA) */
struct acpi_device_status {
u32 present:1;
u32 enabled:1;
u32 show_in_ui:1;
u32 functional:1;
u32 battery_present:1;
u32 reserved:27;
};
/* Flags */
struct acpi_device_flags {
u8 dynamic_status:1;
u8 compatible_ids:1;
u8 removable:1;
u8 ejectable:1;
u8 lockable:1;
u8 suprise_removal_ok:1;
u8 power_manageable:1;
u8 performance_manageable:1;
};
/* File System */
struct acpi_device_dir {
struct proc_dir_entry *entry;
};
#define acpi_device_dir(d) ((d)->dir.entry)
/* Plug and Play */
typedef char acpi_bus_id[5];
typedef unsigned long acpi_bus_address;
typedef char acpi_hardware_id[9];
typedef char acpi_unique_id[9];
typedef char acpi_device_name[40];
typedef char acpi_device_class[20];
struct acpi_device_pnp {
acpi_bus_id bus_id; /* Object name */
acpi_bus_address bus_address; /* _ADR */
acpi_hardware_id hardware_id; /* _HID */
acpi_unique_id unique_id; /* _UID */
acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */
};
#define acpi_device_bid(d) ((d)->pnp.bus_id)
#define acpi_device_adr(d) ((d)->pnp.bus_address)
#define acpi_device_hid(d) ((d)->pnp.hardware_id)
#define acpi_device_uid(d) ((d)->pnp.unique_id)
#define acpi_device_name(d) ((d)->pnp.device_name)
#define acpi_device_class(d) ((d)->pnp.device_class)
/* Power Management */
struct acpi_device_power_flags {
u8 explicit_get:1; /* _PSC present? */
u8 power_resources:1; /* Power resources */
u8 inrush_current:1; /* Serialize Dx->D0 */
u8 wake_capable:1; /* Wakeup supported? */
u8 wake_enabled:1; /* Enabled for wakeup */
u8 power_removed:1; /* Optimize Dx->D0 */
u8 reserved:2;
};
struct acpi_device_power_state {
struct {
u8 valid:1;
u8 explicit_set:1; /* _PSx present? */
u8 reserved:6;
} flags;
int power; /* % Power (compared to D0) */
int latency; /* Dx->D0 time (microseconds) */
struct acpi_handle_list resources; /* Power resources referenced */
};
struct acpi_device_power {
int state; /* Current state */
struct acpi_device_power_flags flags;
struct acpi_device_power_state states[4]; /* Power states (D0-D3) */
};
/* Performance Management */
struct acpi_device_perf_flags {
u8 reserved:8;
};
struct acpi_device_perf_state {
struct {
u8 valid:1;
u8 reserved:7;
} flags;
u8 power; /* % Power (compared to P0) */
u8 performance; /* % Performance ( " ) */
int latency; /* Px->P0 time (microseconds) */
};
struct acpi_device_perf {
int state;
struct acpi_device_perf_flags flags;
int state_count;
struct acpi_device_perf_state *states;
};
/* Device */
struct acpi_device {
acpi_handle handle;
struct acpi_device *parent;
struct list_head children;
struct list_head node;
struct acpi_device_status status;
struct acpi_device_flags flags;
struct acpi_device_pnp pnp;
struct acpi_device_power power;
struct acpi_device_perf performance;
struct acpi_device_dir dir;
struct acpi_driver *driver;
void *driver_data;
#ifdef CONFIG_LDM
struct device dev;
#endif
};
#define acpi_driver_data(d) ((d)->driver_data)
/*
* Events
* ------
*/
struct acpi_bus_event {
struct list_head node;
acpi_device_class device_class;
acpi_bus_id bus_id;
u32 type;
u32 data;
};
/*
* External Functions
*/
int acpi_bus_get_device(acpi_handle, struct acpi_device **device);
int acpi_bus_get_status (struct acpi_device *device);
int acpi_bus_get_power (acpi_handle handle, int *state);
int acpi_bus_set_power (acpi_handle handle, int state);
int acpi_bus_generate_event (struct acpi_device *device, u8 type, int data);
int acpi_bus_receive_event (struct acpi_bus_event *event);
int acpi_bus_register_driver (struct acpi_driver *driver);
int acpi_bus_unregister_driver (struct acpi_driver *driver);
int acpi_bus_scan (struct acpi_device *device);
int acpi_init (void);
void acpi_exit (void);
#endif /*CONFIG_ACPI_BUS*/
#endif /*__ACPI_BUS_H__*/
/*
* acpi_button.c - ACPI Button Driver ($Revision: 22 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include "acpi_bus.h"
#include "acpi_drivers.h"
#define _COMPONENT ACPI_BUTTON_COMPONENT
ACPI_MODULE_NAME ("acpi_button")
MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
MODULE_LICENSE("GPL");
#define PREFIX "ACPI: "
int acpi_button_add (struct acpi_device *device);
int acpi_button_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_button_driver = {
name: ACPI_BUTTON_DRIVER_NAME,
class: ACPI_BUTTON_CLASS,
ids: "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E",
ops: {
add: acpi_button_add,
remove: acpi_button_remove,
},
};
struct acpi_button {
acpi_handle handle;
struct acpi_device *device; /* Fixed button kludge */
u8 type;
unsigned long pushed;
};
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
#include <linux/compatmac.h>
#include <linux/proc_fs.h>
struct proc_dir_entry *acpi_button_dir = NULL;
static int
acpi_button_read_info (
char *page,
char **start,
off_t off,
int count,
int *eof,
void *data)
{
int result = 0;
struct acpi_button *button = (struct acpi_button *) data;
char *p = page;
int len = 0;
ACPI_FUNCTION_TRACE("acpi_button_read_info");
if (!button || !button->device)
goto end;
p += sprintf(p, "type: %s\n",
acpi_device_name(button->device));
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_VALUE(len);
}
static int
acpi_button_add_fs (
struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add_fs");
if (!acpi_button_dir) {
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
if (!acpi_button_dir)
return_VALUE(-ENODEV);
}
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_button_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
/* 'info' [R] */
entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
S_IRUGO, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create '%s' fs entry\n",
ACPI_BUTTON_FILE_INFO));
else {
entry->read_proc = acpi_button_read_info;
entry->data = acpi_driver_data(device);
}
return_VALUE(0);
}
static int
acpi_button_remove_fs (
struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
if (!acpi_button_dir)
return_VALUE(-ENODEV);
if (acpi_device_dir(device))
remove_proc_entry(acpi_device_bid(device), acpi_button_dir);
return_VALUE(0);
}
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
void
acpi_button_notify (
acpi_handle handle,
u32 event,
void *data)
{
struct acpi_button *button = (struct acpi_button *) data;
ACPI_FUNCTION_TRACE("acpi_button_notify");
if (!button || !button->device)
return_VOID;
switch (event) {
case ACPI_BUTTON_NOTIFY_STATUS:
acpi_bus_generate_event(button->device, event, ++button->pushed);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
break;
}
return_VOID;
}
acpi_status
acpi_button_notify_fixed (
void *data)
{
struct acpi_button *button = (struct acpi_button *) data;
ACPI_FUNCTION_TRACE("acpi_button_notify_fixed");
if (!button)
return_ACPI_STATUS(AE_BAD_PARAMETER);
acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button);
return_ACPI_STATUS(AE_OK);
}
int
acpi_button_add (
struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_add");
if (!device)
return_VALUE(-EINVAL);
button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL);
if (!button)
return_VALUE(-ENOMEM);
memset(button, 0, sizeof(struct acpi_button));
button->device = device;
button->handle = device->handle;
sprintf(acpi_device_class(device), "%s", ACPI_BUTTON_CLASS);
acpi_driver_data(device) = button;
/*
* Determine the button type (via hid), as fixed-feature buttons
* need to be handled a bit differently than generic-space.
*/
if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
button->type = ACPI_BUTTON_TYPE_POWERF;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_POWERF);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
button->type = ACPI_BUTTON_TYPE_SLEEPF;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_SLEEPF);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
button->type = ACPI_BUTTON_TYPE_POWER;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_POWER);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
button->type = ACPI_BUTTON_TYPE_SLEEP;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_SLEEP);
}
else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
button->type = ACPI_BUTTON_TYPE_LID;
sprintf(acpi_device_name(device), "%s",
ACPI_BUTTON_DEVICE_NAME_LID);
}
else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n",
acpi_device_hid(device)));
result = -ENODEV;
goto end;
}
result = acpi_button_add_fs(device);
if (0 != result)
goto end;
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
status = acpi_install_fixed_event_handler (
ACPI_EVENT_POWER_BUTTON,
acpi_button_notify_fixed,
button);
break;
case ACPI_BUTTON_TYPE_SLEEPF:
status = acpi_install_fixed_event_handler (
ACPI_EVENT_SLEEP_BUTTON,
acpi_button_notify_fixed,
button);
break;
default:
status = acpi_install_notify_handler (
button->handle,
ACPI_DEVICE_NOTIFY,
acpi_button_notify,
button);
break;
}
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing notify handler\n"));
result = -ENODEV;
goto end;
}
printk(KERN_INFO PREFIX "%s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
end:
if (0 != result) {
acpi_button_remove_fs(device);
kfree(button);
}
return_VALUE(result);
}
int
acpi_button_remove (struct acpi_device *device, int type)
{
acpi_status status = 0;
struct acpi_button *button = NULL;
ACPI_FUNCTION_TRACE("acpi_button_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
button = acpi_driver_data(device);
/* Unregister for device notifications. */
switch (button->type) {
case ACPI_BUTTON_TYPE_POWERF:
status = acpi_remove_fixed_event_handler(
ACPI_EVENT_POWER_BUTTON, acpi_button_notify_fixed);
break;
case ACPI_BUTTON_TYPE_SLEEPF:
status = acpi_remove_fixed_event_handler(
ACPI_EVENT_SLEEP_BUTTON, acpi_button_notify_fixed);
break;
default:
status = acpi_remove_notify_handler(button->handle,
ACPI_DEVICE_NOTIFY, acpi_button_notify);
break;
}
if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error removing notify handler\n"));
acpi_button_remove_fs(device);
kfree(button);
return_VALUE(0);
}
static int __init
acpi_button_init (void)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_button_init");
result = acpi_bus_register_driver(&acpi_button_driver);
if (0 > result)
return_VALUE(-ENODEV);
return_VALUE(0);
}
static void __exit
acpi_button_exit (void)
{
ACPI_FUNCTION_TRACE("acpi_button_exit");
acpi_bus_unregister_driver(&acpi_button_driver);
return_VOID;
}
module_init(acpi_button_init);
module_exit(acpi_button_exit);
This diff is collapsed.
This diff is collapsed.
/*
* acpi_fan.c - ACPI Fan Driver ($Revision: 25 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include "acpi_bus.h"
#include "acpi_drivers.h"
#define _COMPONENT ACPI_FAN_COMPONENT
ACPI_MODULE_NAME ("acpi_fan")
MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
MODULE_LICENSE("GPL");
#define PREFIX "ACPI: "
int acpi_fan_add (struct acpi_device *device);
int acpi_fan_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_fan_driver = {
name: ACPI_FAN_DRIVER_NAME,
class: ACPI_FAN_CLASS,
ids: ACPI_FAN_HID,
ops: {
add: acpi_fan_add,
remove: acpi_fan_remove,
},
};
struct acpi_fan {
acpi_handle handle;
};
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
#include <linux/compatmac.h>
#include <linux/proc_fs.h>
struct proc_dir_entry *acpi_fan_dir = NULL;
static int
acpi_fan_read_state (
char *page,
char **start,
off_t off,
int count,
int *eof,
void *data)
{
struct acpi_fan *fan = (struct acpi_fan *) data;
char *p = page;
int len = 0;
int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_read_state");
if (!fan || (off != 0))
goto end;
if (0 != acpi_bus_get_power(fan->handle, &state))
goto end;
p += sprintf(p, "status: %s\n",
!state?"on":"off");
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_VALUE(len);
}
static int
acpi_fan_write_state (
struct file *file,
const char *buffer,
unsigned long count,
void *data)
{
int result = 0;
struct acpi_fan *fan = (struct acpi_fan *) data;
char state_string[12] = {'\0'};
ACPI_FUNCTION_TRACE("acpi_fan_write_state");
if (!fan || (count > sizeof(state_string) - 1))
return_VALUE(-EINVAL);
if (copy_from_user(state_string, buffer, count))
return_VALUE(-EFAULT);
state_string[count] = '\0';
result = acpi_bus_set_power(fan->handle,
simple_strtoul(state_string, NULL, 0));
if (0 != result)
return_VALUE(result);
return_VALUE(count);
}
static int
acpi_fan_add_fs (
struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
ACPI_FUNCTION_TRACE("acpi_fan_add_fs");
if (!device)
return_VALUE(-EINVAL);
if (!acpi_fan_dir) {
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
return_VALUE(-ENODEV);
}
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_fan_dir);
if (!acpi_device_dir(device))
return_VALUE(-ENODEV);
}
/* 'status' [R/W] */
entry = create_proc_entry(ACPI_FAN_FILE_STATE,
S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
if (!entry)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create '%s' fs entry\n",
ACPI_FAN_FILE_STATE));
else {
entry->read_proc = acpi_fan_read_state;
entry->write_proc = acpi_fan_write_state;
entry->data = acpi_driver_data(device);
}
return_VALUE(0);
}
static int
acpi_fan_remove_fs (
struct acpi_device *device)
{
ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
if (!acpi_fan_dir)
return_VALUE(-ENODEV);
if (acpi_device_dir(device))
remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
return_VALUE(0);
}
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
int
acpi_fan_add (
struct acpi_device *device)
{
int result = 0;
struct acpi_fan *fan = NULL;
int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_add");
if (!device)
return_VALUE(-EINVAL);
fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL);
if (!fan)
return_VALUE(-ENOMEM);
memset(fan, 0, sizeof(struct acpi_fan));
fan->handle = device->handle;
sprintf(acpi_device_name(device), "%s", ACPI_FAN_DEVICE_NAME);
sprintf(acpi_device_class(device), "%s", ACPI_FAN_CLASS);
acpi_driver_data(device) = fan;
result = acpi_bus_get_power(fan->handle, &state);
if (0 != result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error reading power state\n"));
goto end;
}
result = acpi_fan_add_fs(device);
if (0 != result)
goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
!device->power.state?"on":"off");
end:
if (0 != result)
kfree(fan);
return_VALUE(result);
}
int
acpi_fan_remove (
struct acpi_device *device,
int type)
{
struct acpi_fan *fan = NULL;
ACPI_FUNCTION_TRACE("acpi_fan_remove");
if (!device || !acpi_driver_data(device))
return_VALUE(-EINVAL);
fan = (struct acpi_fan *) acpi_driver_data(device);
acpi_fan_remove_fs(device);
kfree(fan);
return_VALUE(0);
}
int __init
acpi_fan_init (void)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_fan_init");
result = acpi_bus_register_driver(&acpi_fan_driver);
if (0 > result)
return_VALUE(-ENODEV);
return_VALUE(0);
}
void __exit
acpi_fan_exit (void)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_fan_exit");
result = acpi_bus_unregister_driver(&acpi_fan_driver);
if (0 == result)
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
return_VOID;
}
module_init(acpi_fan_init);
module_exit(acpi_fan_exit);
/* /*
* ksyms.c - ACPI exported symbols * acpi_ksyms.c - ACPI Kernel Symbols ($Revision: 13 $)
* *
* Copyright (C) 2000 Andrew Grover * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or (at
* (at your option) any later version. * your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* *
* This program is distributed in the hope that it will be useful, * You should have received a copy of the GNU General Public License along
* but WITHOUT ANY WARRANTY; without even the implied warranty of * with this program; if not, write to the Free Software Foundation, Inc.,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include "include/acpi.h"
#include <linux/kernel.h> #include "acpi_bus.h"
#include <linux/types.h>
#include <linux/acpi.h>
#include "acpi.h"
#include "acdebug.h"
extern int acpi_in_debugger; #ifdef CONFIG_ACPI_INTERPRETER
extern FADT_DESCRIPTOR acpi_fadt;
#define _COMPONENT OS_DEPENDENT /* ACPI Debugger */
MODULE_NAME ("symbols")
#ifdef ENABLE_DEBUGGER #ifdef ENABLE_DEBUGGER
extern int acpi_in_debugger;
EXPORT_SYMBOL(acpi_in_debugger); EXPORT_SYMBOL(acpi_in_debugger);
EXPORT_SYMBOL(acpi_db_user_commands); EXPORT_SYMBOL(acpi_db_user_commands);
#endif
#endif /* ENABLE_DEBUGGER */
/* ACPI Core Subsystem */
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
EXPORT_SYMBOL(acpi_dbg_layer);
EXPORT_SYMBOL(acpi_dbg_level);
EXPORT_SYMBOL(acpi_ut_debug_print_raw); EXPORT_SYMBOL(acpi_ut_debug_print_raw);
EXPORT_SYMBOL(acpi_ut_debug_print); EXPORT_SYMBOL(acpi_ut_debug_print);
EXPORT_SYMBOL(acpi_ut_status_exit); EXPORT_SYMBOL(acpi_ut_status_exit);
EXPORT_SYMBOL(acpi_ut_value_exit);
EXPORT_SYMBOL(acpi_ut_exit); EXPORT_SYMBOL(acpi_ut_exit);
EXPORT_SYMBOL(acpi_ut_trace); EXPORT_SYMBOL(acpi_ut_trace);
#endif #endif /*ACPI_DEBUG*/
EXPORT_SYMBOL(acpi_gbl_FADT);
EXPORT_SYMBOL(acpi_os_free);
EXPORT_SYMBOL(acpi_os_printf);
EXPORT_SYMBOL(acpi_os_callocate);
EXPORT_SYMBOL(acpi_os_sleep);
EXPORT_SYMBOL(acpi_os_stall);
EXPORT_SYMBOL(acpi_os_queue_for_execution);
EXPORT_SYMBOL(acpi_dbg_layer);
EXPORT_SYMBOL(acpi_dbg_level);
EXPORT_SYMBOL(acpi_format_exception);
EXPORT_SYMBOL(acpi_get_handle); EXPORT_SYMBOL(acpi_get_handle);
EXPORT_SYMBOL(acpi_get_parent); EXPORT_SYMBOL(acpi_get_parent);
...@@ -68,7 +62,6 @@ EXPORT_SYMBOL(acpi_get_object_info); ...@@ -68,7 +62,6 @@ EXPORT_SYMBOL(acpi_get_object_info);
EXPORT_SYMBOL(acpi_get_next_object); EXPORT_SYMBOL(acpi_get_next_object);
EXPORT_SYMBOL(acpi_evaluate_object); EXPORT_SYMBOL(acpi_evaluate_object);
EXPORT_SYMBOL(acpi_get_table); EXPORT_SYMBOL(acpi_get_table);
EXPORT_SYMBOL(acpi_install_notify_handler); EXPORT_SYMBOL(acpi_install_notify_handler);
EXPORT_SYMBOL(acpi_remove_notify_handler); EXPORT_SYMBOL(acpi_remove_notify_handler);
EXPORT_SYMBOL(acpi_install_gpe_handler); EXPORT_SYMBOL(acpi_install_gpe_handler);
...@@ -77,39 +70,61 @@ EXPORT_SYMBOL(acpi_install_address_space_handler); ...@@ -77,39 +70,61 @@ EXPORT_SYMBOL(acpi_install_address_space_handler);
EXPORT_SYMBOL(acpi_remove_address_space_handler); EXPORT_SYMBOL(acpi_remove_address_space_handler);
EXPORT_SYMBOL(acpi_install_fixed_event_handler); EXPORT_SYMBOL(acpi_install_fixed_event_handler);
EXPORT_SYMBOL(acpi_remove_fixed_event_handler); EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
EXPORT_SYMBOL(acpi_acquire_global_lock); EXPORT_SYMBOL(acpi_acquire_global_lock);
EXPORT_SYMBOL(acpi_release_global_lock); EXPORT_SYMBOL(acpi_release_global_lock);
EXPORT_SYMBOL(acpi_get_current_resources); EXPORT_SYMBOL(acpi_get_current_resources);
EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_get_possible_resources);
EXPORT_SYMBOL(acpi_set_current_resources); EXPORT_SYMBOL(acpi_set_current_resources);
EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_enable_event);
EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_disable_event);
EXPORT_SYMBOL(acpi_clear_event); EXPORT_SYMBOL(acpi_clear_event);
EXPORT_SYMBOL(acpi_get_timer_duration); EXPORT_SYMBOL(acpi_get_timer_duration);
EXPORT_SYMBOL(acpi_get_timer); EXPORT_SYMBOL(acpi_get_timer);
EXPORT_SYMBOL(acpi_hw_get_sleep_type_data);
EXPORT_SYMBOL(acpi_hw_bit_register_read);
EXPORT_SYMBOL(acpi_hw_bit_register_write);
EXPORT_SYMBOL(acpi_enter_sleep_state);
EXPORT_SYMBOL(acpi_get_system_info);
/* ACPI OS Services Layer (acpi_osl.c) */
EXPORT_SYMBOL(acpi_os_free);
EXPORT_SYMBOL(acpi_os_printf);
EXPORT_SYMBOL(acpi_os_sleep);
EXPORT_SYMBOL(acpi_os_stall);
EXPORT_SYMBOL(acpi_os_signal);
EXPORT_SYMBOL(acpi_os_queue_for_execution);
EXPORT_SYMBOL(acpi_os_signal_semaphore); EXPORT_SYMBOL(acpi_os_signal_semaphore);
EXPORT_SYMBOL(acpi_os_create_semaphore); EXPORT_SYMBOL(acpi_os_create_semaphore);
EXPORT_SYMBOL(acpi_os_delete_semaphore); EXPORT_SYMBOL(acpi_os_delete_semaphore);
EXPORT_SYMBOL(acpi_os_wait_semaphore); EXPORT_SYMBOL(acpi_os_wait_semaphore);
EXPORT_SYMBOL(acpi_os_read_port); /* ACPI Utilities (acpi_utils.c) */
EXPORT_SYMBOL(acpi_os_write_port);
EXPORT_SYMBOL(acpi_extract_package);
EXPORT_SYMBOL(acpi_evaluate);
EXPORT_SYMBOL(acpi_evaluate_integer);
EXPORT_SYMBOL(acpi_evaluate_reference);
#endif /*CONFIG_ACPI_INTERPRETER*/
/* ACPI Bus Driver (acpi_bus.c) */
#ifdef CONFIG_ACPI_BUS
EXPORT_SYMBOL(acpi_fadt); EXPORT_SYMBOL(acpi_fadt);
EXPORT_SYMBOL(acpi_hw_register_bit_access); EXPORT_SYMBOL(acpi_root_dir);
EXPORT_SYMBOL(acpi_hw_obtain_sleep_type_register_data); EXPORT_SYMBOL(acpi_bus_get_device);
EXPORT_SYMBOL(acpi_enter_sleep_state); EXPORT_SYMBOL(acpi_bus_get_status);
EXPORT_SYMBOL(acpi_get_system_info); EXPORT_SYMBOL(acpi_bus_get_power);
EXPORT_SYMBOL(acpi_leave_sleep_state); EXPORT_SYMBOL(acpi_bus_set_power);
/*EXPORT_SYMBOL(acpi_save_state_mem);*/ EXPORT_SYMBOL(acpi_bus_generate_event);
/*EXPORT_SYMBOL(acpi_save_state_disk);*/ EXPORT_SYMBOL(acpi_bus_receive_event);
EXPORT_SYMBOL(acpi_hw_register_read); EXPORT_SYMBOL(acpi_bus_register_driver);
EXPORT_SYMBOL(acpi_set_firmware_waking_vector); EXPORT_SYMBOL(acpi_bus_unregister_driver);
EXPORT_SYMBOL(acpi_subsystem_status); EXPORT_SYMBOL(acpi_bus_scan);
EXPORT_SYMBOL(acpi_init);
#endif /*CONFIG_ACPI_BUS*/
EXPORT_SYMBOL(acpi_os_signal);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment