linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] filling in ACPI files in sysfs
@ 2004-04-06 15:56 Alex Williamson
  2004-04-06 16:18 ` [ACPI] " Matthew Wilcox
  0 siblings, 1 reply; 2+ messages in thread
From: Alex Williamson @ 2004-04-06 15:56 UTC (permalink / raw)
  To: linux-kernel, acpi-devel


   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;
 }
	


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [ACPI] [RFC] filling in ACPI files in sysfs
  2004-04-06 15:56 [RFC] filling in ACPI files in sysfs Alex Williamson
@ 2004-04-06 16:18 ` Matthew Wilcox
  0 siblings, 0 replies; 2+ messages in thread
From: Matthew Wilcox @ 2004-04-06 16:18 UTC (permalink / raw)
  To: Alex Williamson; +Cc: linux-kernel, acpi-devel

On Tue, Apr 06, 2004 at 09:56:30AM -0600, Alex Williamson wrote:
>    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,

This is something I've wanted for a long time!  Thanks for doing the
work, Alex.  I'll give it a try on my x86 crash-n-bash box.

-- 
"Next the statesmen will invent cheap lies, putting the blame upon 
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince 
himself that the war is just, and will thank God for the better sleep 
he enjoys after this process of grotesque self-deception." -- Mark Twain

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-04-06 16:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-06 15:56 [RFC] filling in ACPI files in sysfs Alex Williamson
2004-04-06 16:18 ` [ACPI] " Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).