From: Alex Williamson <alex.williamson@hp.com>
To: linux-kernel@vger.kernel.org, acpi-devel@lists.sourceforge.net
Subject: [RFC] filling in ACPI files in sysfs
Date: Tue, 06 Apr 2004 09:56:30 -0600 [thread overview]
Message-ID: <1081266989.2375.35.camel@patsy.fc.hp.com> (raw)
Seems like it's about time the ACPI sysfs namespace started doing
more than looking pretty. Here's a stab at adding in some basic
functionality. I'd like to get some feedback before I start filling in
the more complicated features. This has been lightly tested on a
sampling of HP ia64 boxes. Does this seem like a reasonable start?
Comments and reports from other platforms welcome. Thanks,
Alex
--
Alex Williamson HP Linux & Open Source Lab
===== drivers/acpi/scan.c 1.22 vs edited =====
--- 1.22/drivers/acpi/scan.c Tue Feb 3 22:29:19 2004
+++ edited/drivers/acpi/scan.c Tue Apr 6 09:15:29 2004
@@ -7,6 +7,7 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
+#include <acpi/actypes.h>
#define _COMPONENT ACPI_BUS_COMPONENT
@@ -22,9 +23,184 @@
#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver"
#define ACPI_BUS_DEVICE_NAME "System Bus"
+#define METHOD_NAME__DDN "_DDN"
+#define METHOD_NAME__SUN "_SUN"
+#define METHOD_NAME__STR "_STR"
+
static LIST_HEAD(acpi_device_list);
static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
+struct acpi_handle_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct acpi_device *, char *, char *);
+ ssize_t (*store)(struct acpi_device *, char *, const char *, size_t);
+};
+
+#define EISA_ID_TYPE (1<<0)
+#define UNICODE_TYPE (1<<1)
+
+static ssize_t
+parse_integer(char *buf, u32 value, unsigned int flags) {
+ if (flags & EISA_ID_TYPE) {
+ acpi_ex_eisa_id_to_string(value, buf);
+ buf[8] = '\n';
+ return 9;
+ }
+ return sprintf(buf, "%08x\n", value);
+}
+
+static ssize_t
+parse_string(char *buf, u32 length, char *pointer, unsigned int flags) {
+ snprintf(buf, length, "%s", pointer);
+ buf[length] = '\n';
+ return length + 1;
+}
+
+static ssize_t
+parse_buffer(char *buf, u32 length, u8 *pointer, unsigned int flags) {
+ ssize_t offset = 0;
+
+ if (flags & UNICODE_TYPE) {
+ for (; length > 0 ; length -= 2) {
+ sprintf(buf + offset, "%c", *pointer);
+ offset++;
+ pointer += 2;
+ }
+ } else {
+ for (; length > 0 ; length--) {
+ sprintf(buf + offset, "%02x", *pointer);
+ offset += 2;
+ pointer++;
+ }
+ }
+ sprintf(buf + offset++, "\n");
+ return offset;
+}
+
+static ssize_t parse_package(char *, union acpi_object *, unsigned int);
+
+static ssize_t
+parse_element(
+ char *buf,
+ union acpi_object *element,
+ unsigned int flags)
+{
+
+ switch (element->type) {
+ case ACPI_TYPE_INTEGER:
+ return parse_integer(buf, element->integer.value, flags);
+ case ACPI_TYPE_STRING:
+ return parse_string(buf, element->string.length,
+ element->string.pointer, flags);
+ case ACPI_TYPE_BUFFER:
+ return parse_buffer(buf, element->buffer.length,
+ element->buffer.pointer, flags);
+ case ACPI_TYPE_PACKAGE:
+ return parse_package(buf, element, flags);
+ default:
+ return sprintf(buf, "Unknown Type: %d\n", element->type);
+ }
+}
+
+static ssize_t
+parse_package(char *buf, union acpi_object *element, unsigned int flags) {
+ int count = element->package.count;
+ ssize_t tmp, retval = 0;
+
+ element = element->package.elements;
+
+ for (; count > 0 ; count--, element++) {
+ tmp = parse_element(buf, element, flags);
+ buf += tmp;
+ retval += tmp;
+ }
+ return retval;
+}
+
+static ssize_t
+acpi_device_read_file (
+ struct acpi_device *device,
+ char *method,
+ char *buf)
+{
+ acpi_status status;
+ union acpi_object *element;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ ssize_t retval = 0;
+ unsigned int flags = 0;
+
+ status = acpi_evaluate_object(device->handle, method, NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ if (!strcmp(method, METHOD_NAME__HID)
+ || !strcmp(method, METHOD_NAME__CID))
+ flags |= EISA_ID_TYPE;
+
+ if (!strcmp(method, METHOD_NAME__STR))
+ flags |= UNICODE_TYPE;
+
+ element = (union acpi_object *) buffer.pointer;
+ retval = parse_element(buf, element, flags);
+ acpi_os_free(element);
+ return retval;
+}
+
+#define acpi_handle_attr(method, show_func, store_func) \
+static struct acpi_handle_attribute acpi_handle_attr##method = { \
+ .attr = {.name = METHOD_NAME_##method, .mode = S_IFREG | S_IRUGO}, \
+ .show = show_func, \
+ .store = store_func, \
+};
+
+acpi_handle_attr(_ADR, acpi_device_read_file, NULL)
+acpi_handle_attr(_BBN, acpi_device_read_file, NULL)
+acpi_handle_attr(_CID, acpi_device_read_file, NULL)
+acpi_handle_attr(_DDN, acpi_device_read_file, NULL)
+acpi_handle_attr(_HID, acpi_device_read_file, NULL)
+acpi_handle_attr(_SEG, acpi_device_read_file, NULL)
+acpi_handle_attr(_STA, acpi_device_read_file, NULL)
+acpi_handle_attr(_STR, acpi_device_read_file, NULL)
+acpi_handle_attr(_SUN, acpi_device_read_file, NULL)
+acpi_handle_attr(_UID, acpi_device_read_file, NULL)
+
+typedef void acpi_device_sysfs_files(struct kobject *,
+ const struct attribute *);
+
+static void
+setup_sys_fs_files (
+ struct acpi_device *dev,
+ acpi_device_sysfs_files *func)
+{
+ acpi_handle tmp = NULL;
+
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__ADR, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_ADR.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__BBN, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_BBN.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__CID, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_CID.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__DDN, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_DDN.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__HID, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_HID.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__SEG, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_SEG.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__STA, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_STA.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__STR, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_STR.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__SUN, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_SUN.attr);
+ if (ACPI_SUCCESS(acpi_get_handle(dev->handle, METHOD_NAME__UID, &tmp)))
+ (*(func))(&dev->kobj, &acpi_handle_attr_UID.attr);
+}
+
+#define create_sysfs_files(dev) \
+ setup_sys_fs_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file)
+#define remove_sysfs_files(dev) \
+ setup_sys_fs_files(dev, &sysfs_remove_file)
+
static void acpi_device_release(struct kobject * kobj)
{
struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
@@ -33,7 +209,32 @@
kfree(dev);
}
+#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
+#define to_handle_attr(n) container_of(n, struct acpi_handle_attribute, attr);
+
+static ssize_t acpi_device_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct acpi_device *device = to_acpi_device(kobj);
+ struct acpi_handle_attribute *attribute = to_handle_attr(attr);
+ return attribute->show ? attribute->show(device, attribute->attr.name, buf) : 0;
+}
+
+static ssize_t acpi_device_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ struct acpi_device *device = to_acpi_device(kobj);
+ struct acpi_handle_attribute *attribute = to_handle_attr(attr);
+ return attribute->store ? attribute->store(device, attribute->attr.name, buf, len) : 0;
+}
+
+static struct sysfs_ops acpi_device_sysfs_ops = {
+ .show = acpi_device_attr_show,
+ .store = acpi_device_attr_store,
+};
+
static struct kobj_type ktype_acpi_ns = {
+ .sysfs_ops = &acpi_device_sysfs_ops,
.release = acpi_device_release,
};
@@ -72,6 +273,7 @@
device->kobj.ktype = &ktype_acpi_ns;
device->kobj.kset = &acpi_namespace_kset;
kobject_add(&device->kobj);
+ create_sysfs_files(device);
}
static int
@@ -79,6 +281,7 @@
struct acpi_device *device,
int type)
{
+ remove_sysfs_files(device);
kobject_unregister(&device->kobj);
return 0;
}
next reply other threads:[~2004-04-06 15:56 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-04-06 15:56 Alex Williamson [this message]
2004-04-06 16:18 ` [ACPI] [RFC] filling in ACPI files in sysfs Matthew Wilcox
-- strict thread matches above, loose matches on Subject: below --
2004-04-07 21:36 Paul Ionescu
[not found] ` <1081373781.23176.30.camel-LjAuIDrFwz0@public.gmane.org>
2004-04-07 22:13 ` Alex Williamson
[not found] ` <1081376023.2748.15.camel-Wmjt7DDUnIVxnVILBQAtiA@public.gmane.org>
2004-04-08 5:56 ` Paul Ionescu
2004-04-08 15:46 ` Paul Ionescu
[not found] ` <1081439217.23176.70.camel-LjAuIDrFwz0@public.gmane.org>
2004-04-08 16:41 ` Alex Williamson
2004-04-08 16:53 ` Paul Ionescu
2004-04-08 17:25 ` Matthew Wilcox
[not found] ` <20040408172548.GH18329-+pPCBgu9SkPzIGdyhVEDUDl5KyyQGfY2kSSpQ9I8OhVaa/9Udqfwiw@public.gmane.org>
2004-04-08 17:33 ` Alex Williamson
[not found] ` <1081536801.26073.120.camel@t40>
[not found] ` <1081537175.2694.11.camel@patsy.fc.hp.com>
[not found] ` <1081537175.2694.11.camel-Wmjt7DDUnIVxnVILBQAtiA@public.gmane.org>
2004-04-10 10:03 ` Paul Ionescu
[not found] ` <1081536489.23178.113.camel@t40>
[not found] ` <1081537087.2694.8.camel@patsy.fc.hp.com>
[not found] ` <1081537087.2694.8.camel-Wmjt7DDUnIVxnVILBQAtiA@public.gmane.org>
2004-04-10 11:36 ` Paul Ionescu
2004-04-08 8:14 Paul Ionescu
[not found] ` <20040408081455.52935.qmail-BuYeCebq3BaA/QwVtaZbd3CJp6faPEW9@public.gmane.org>
2004-04-08 14:36 ` Alex Williamson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1081266989.2375.35.camel@patsy.fc.hp.com \
--to=alex.williamson@hp.com \
--cc=acpi-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.