Hi, Andy!

> > > I would think that it would make sense to keep shutdown 
> > with all the other
> > > power management events. Perhaps it will makes more sense 
> > to handle UPS's
> > > through the power management code.
> > 
> > Yes, that would be another acceptable solution. Situation where half
> > of power managment (UPS) is done with init and half with acpid is not
> > acceptable. [I doubt UPS users will want to switch. Why invent new
> > daemon when init is doing perfect job?]
> 
> I think init is doing a perfect job WRT UPSs because this is a trivial
> application of power management. init wasn't really meant for this.
> According to its man page:
> 
> "init...it's primary role is to create processes from a script in the file
> /etc/inittab...It also controls autonomous processes required by any
> particular system"
> 
> We are going to need some software that handles button events, as well as
> thermal events, battery events, polling the battery, AC adapter status
> changes, sleeping the system, and more.

I do not want to put battery/thermal/AC adapter status through
init. On *many* machines, button is only usefull device from ACPI (for
example all desktop machines). On desktop machine, you probably will
not want to configure/run acpid. Init should be able to do its job.

I agree that for notebooks where you want to handle thermal events
etc., acpid will be neccessary. I just do not want desktop people to
be forced to run acpid.

> We need WAY more flexibility than init provides. I find the argument that
> init is already handling one minor power-related thing an unconvincing
> reason why we should cram all power management through it.

It is doing UPS and c-a-d handling, which is *very* similar to what
you want to do on power button press 99% of time.
                                                                Pavel
PS: About thermal events -- do I need to do something special in order
for temperature to be measured?

I can send _TMP, and get temperature reading, but it does not change
with time -- I get the same value from boot on.

BTW here are hacks I use for easy control of ACPI. That way, I can
just for A in device_*; do echo -n '_TMP' > $A; done and get
temperature reading in syslog ;-).

Do you think some way to reflect acpi structure in proc would be good
idea?

diff -ur -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x 
*.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x 
version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x 
bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x 
*.flags -x *.bak clean/drivers/acpi/common/cmeval.c linux/drivers/acpi/common/cmeval.c
--- clean/drivers/acpi/common/cmeval.c  Wed Jan 31 16:14:27 2001
+++ linux/drivers/acpi/common/cmeval.c  Fri Apr  6 08:45:21 2001
@@ -262,9 +262,10 @@
  ***************************************************************************/
 
 ACPI_STATUS
-acpi_cm_execute_STA (
+acpi_cm_execute_rint (
        ACPI_NAMESPACE_NODE     *device_node,
-       u32                     *flags)
+       u32                     *flags,
+       char                    *name)
 {
        ACPI_OPERAND_OBJECT     *obj_desc;
        ACPI_STATUS             status;
@@ -273,14 +274,12 @@
        /* Execute the method */
 
        status = acpi_ns_evaluate_relative (device_node,
-                        METHOD_NAME__STA, NULL, &obj_desc);
-       if (AE_NOT_FOUND == status) {
-               *flags = 0x0F;
-               status = AE_OK;
-       }
-
+                        name, NULL, &obj_desc);
+       if (ACPI_FAILURE (status))
+               return (status);
 
-       else /* success */ {
+       /* I guess it used to be subtle bug here, on AE_NOT_FOUND, it did 
+cm_remove_reference, anyway */
+       {
                /* Did we get a return object? */
 
                if (!obj_desc) {
@@ -306,3 +305,71 @@
 
        return (status);
 }
+
+
+ACPI_STATUS
+acpi_cm_execute_STA (
+       ACPI_NAMESPACE_NODE     *device_node,
+       u32                     *flags)
+{
+       ACPI_STATUS             status;
+
+       status = acpi_cm_execute_rint(device_node, flags, "_STA");
+       if (status == AE_NOT_FOUND) {
+               *flags = 0x0F;
+               return AE_OK;
+       }
+       return status;
+}
+
+
+ACPI_STATUS
+acpi_cm_execute_any (
+       ACPI_NAMESPACE_NODE     *device_node,
+       char                    *res,
+       char                    *name)
+{
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_STATUS             status;
+
+
+       /* Execute the method */
+
+       status = acpi_ns_evaluate_relative (device_node,
+                        name, NULL, &obj_desc);
+       sprintf(res, "error");
+       if (ACPI_FAILURE (status))
+               return (status);
+
+       /* I guess it used to be subtle bug here, on AE_NOT_FOUND, it did 
+cm_remove_reference, anyway */
+       {
+               /* Did we get a return object? */
+
+               if (!obj_desc) {
+                       sprintf(res, "no return");
+                       return (AE_OK);
+               }
+
+               /* Is the return object of the correct type? */
+
+               switch (obj_desc->common.type) {
+               case ACPI_TYPE_INTEGER:
+                       sprintf(res, "int: %d", obj_desc->integer.value);
+                       break;
+               case ACPI_TYPE_STRING:
+                       sprintf(res, "string: %20s", obj_desc->string.pointer);
+                       break;
+               deafult:
+                       sprintf(res, "unknown", obj_desc->string.pointer);
+                       break;
+               }
+
+               /* On exit, we must delete the return object */
+
+               acpi_cm_remove_reference (obj_desc);
+       }
+
+       return (status);
+}
+
+
diff -ur -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x 
*.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x 
version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x 
bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x 
*.flags -x *.bak clean/drivers/acpi/events/evevent.c 
linux/drivers/acpi/events/evevent.c
--- clean/drivers/acpi/events/evevent.c Sun Apr  1 00:22:57 2001
+++ linux/drivers/acpi/events/evevent.c Wed Apr  4 01:08:11 2001
@@ -30,6 +30,8 @@
 #include "acnamesp.h"
 #include "accommon.h"
 
+#include <linux/signal.h>
+
 #define _COMPONENT          EVENT_HANDLING
         MODULE_NAME         ("evevent")
 
@@ -49,25 +51,15 @@
  *************************************************************************/
 
 ACPI_STATUS
-acpi_ev_initialize (
-       void)
+acpi_ev_initialize (void)
 {
        ACPI_STATUS             status;
 
-
-       /* Make sure we have ACPI tables */
-
-       if (!acpi_gbl_DSDT) {
+       if (!acpi_gbl_DSDT)                     /* Make sure we have ACPI tables */
                return (AE_NO_ACPI_TABLES);
-       }
-
-
-       /* Make sure the BIOS supports ACPI mode */
 
-       if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) {
+       if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) /* Make sure the BIOS 
+supports ACPI mode */
                return (AE_ERROR);
-       }
-
 
        acpi_gbl_original_mode = acpi_hw_get_mode();
 
@@ -77,38 +69,18 @@
         * before handers are installed.
         */
 
-       status = acpi_ev_fixed_event_initialize ();
-       if (ACPI_FAILURE (status)) {
+       if (ACPI_FAILURE (status = acpi_ev_fixed_event_initialize ()))
                return (status);
-       }
-
-       status = acpi_ev_gpe_initialize ();
-       if (ACPI_FAILURE (status)) {
+       if (ACPI_FAILURE (status = acpi_ev_gpe_initialize ()))
                return (status);
-       }
-
-       /* Install the SCI handler */
-
-       status = acpi_ev_install_sci_handler ();
-       if (ACPI_FAILURE (status)) {
+       if (ACPI_FAILURE (status = acpi_ev_install_sci_handler ()))
                return (status);
-       }
-
-
        /* Install handlers for control method GPE handlers (_Lxx, _Exx) */
-
-       status = acpi_ev_init_gpe_control_methods ();
-       if (ACPI_FAILURE (status)) {
+       if (ACPI_FAILURE (status = acpi_ev_init_gpe_control_methods ()))
                return (status);
-       }
-
        /* Install the handler for the Global Lock */
-
-       status = acpi_ev_init_global_lock_handler ();
-       if (ACPI_FAILURE (status)) {
+       if (ACPI_FAILURE (status = acpi_ev_init_global_lock_handler ()))
                return (status);
-       }
-
 
        return (status);
 }
@@ -131,6 +103,7 @@
 {
        int                     i = 0;
 
+       printk("acpi: Initializing fixed events\n");
        /* Initialize the structure that keeps track of fixed event handlers */
 
        for (i = 0; i < NUM_FIXED_EVENTS; i++) {
@@ -181,6 +154,7 @@
        if ((status_register & ACPI_STATUS_PMTIMER) &&
                (enable_register & ACPI_ENABLE_PMTIMER))
        {
+               printk ("acpi: PM timer!\n");
                int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER);
        }
 
@@ -189,22 +163,27 @@
        if ((status_register & ACPI_STATUS_GLOBAL) &&
                (enable_register & ACPI_ENABLE_GLOBAL))
        {
+               printk ("acpi: BIOS wants to play!\n");
                int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL);
        }
 
        /* power button event */
 
        if ((status_register & ACPI_STATUS_POWER_BUTTON) &&
-               (enable_register & ACPI_ENABLE_POWER_BUTTON))
+           (enable_register & ACPI_ENABLE_POWER_BUTTON))
        {
+               printk ("acpi: Power button pressed!\n");
+               kill_proc (1, SIGTERM, 1);
                int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON);
        }
 
+
        /* sleep button event */
 
        if ((status_register & ACPI_STATUS_SLEEP_BUTTON) &&
                (enable_register & ACPI_ENABLE_SLEEP_BUTTON))
        {
+               printk("acpi: Sleep button pressed!\n");
                int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON);
        }
 
diff -ur -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x 
*.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x 
version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x 
bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x 
*.flags -x *.bak clean/drivers/acpi/hardware/hwsleep.c 
linux/drivers/acpi/hardware/hwsleep.c
--- clean/drivers/acpi/hardware/hwsleep.c       Sun Apr  1 00:22:57 2001
+++ linux/drivers/acpi/hardware/hwsleep.c       Wed Apr  4 00:11:19 2001
@@ -27,6 +27,7 @@
 #include "acpi.h"
 #include "acnamesp.h"
 #include "achware.h"
+#include <linux/delay.h>
 
 #define _COMPONENT          HARDWARE
         MODULE_NAME         ("hwsleep")
@@ -50,7 +51,6 @@
        ACPI_PHYSICAL_ADDRESS physical_address)
 {
 
-
        /* Make sure that we have an FACS */
 
        if (!acpi_gbl_FACS) {
@@ -59,6 +59,8 @@
 
        /* Set the vector */
 
+       printk("Setting waking_vector to %lx\n", physical_address);
+
        if (acpi_gbl_FACS->vector_width == 32) {
                * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) 
physical_address;
        }
@@ -112,6 +114,12 @@
        return (AE_OK);
 }
 
+void
+while1(void)
+{
+       while(1);
+}
+
 /******************************************************************************
  *
  * FUNCTION:    Acpi_enter_sleep_state
@@ -136,6 +144,13 @@
        u16 PM1_acontrol;
        u16 PM1_bcontrol;
 
+/*
+       acpi_set_firmware_waking_vector(0xffff0);
+*/
+       acpi_set_firmware_waking_vector(&while1 - 0xc0000000);
+
+       printk("Entering power state %d\n", sleep_state);
+
        /*
         * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
         */
@@ -175,14 +190,23 @@
        PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
        PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
 
-       disable();
+       /*disable();*/
 
+       printk("hwsleep: Writing registers\n");
        acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol);
        acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol);
+       printk("hwsleep: enabling sleep!\n");
        acpi_hw_register_write(ACPI_MTX_LOCK, PM1_CONTROL,
                (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)));
+       printk("hwsleep: before enable\n");
 
-       enable();
+       /*enable();*/
+       printk("hwsleep: after enable\n");
 
+       arg_list.count = 1;
+       arg_list.pointer = &arg;
+       acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
+       printk("hwsleep: Waked up?\n");
+       mdelay(1000);
        return (AE_OK);
 }
diff -ur -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x 
*.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x 
version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x 
bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x 
*.flags -x *.bak clean/drivers/acpi/namespace/nsxfobj.c 
linux/drivers/acpi/namespace/nsxfobj.c
--- clean/drivers/acpi/namespace/nsxfobj.c      Sun Apr  1 00:23:00 2001
+++ linux/drivers/acpi/namespace/nsxfobj.c      Tue Apr 10 00:19:01 2001
@@ -30,6 +30,10 @@
 #include "acnamesp.h"
 #include "acdispat.h"
 
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
 
 #define _COMPONENT          NAMESPACE
         MODULE_NAME         ("nsxfobj")
@@ -592,7 +596,7 @@
 
        status = acpi_cm_execute_STA (node, &flags);
        if (ACPI_FAILURE (status)) {
-               return (status);
+               return AE_OK;
        }
 
        if (!(flags & 0x01)) {
@@ -694,3 +698,203 @@
 
        return (status);
 }
+
+static int
+proc_read_device_info(char *page, char **start, off_t off,
+                       int count, int *eof, void *data)
+{
+       ACPI_HANDLE             obj_handle = (u32) data;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_STATUS             status;
+       char *p = page;
+       int len;
+       u32 flags;
+       DEVICE_ID               device_id;
+
+       /* don't get info more than once for a single proc read */
+       if (off != 0)
+               goto end;
+
+       acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+       node = acpi_ns_convert_handle_to_entry (obj_handle);
+
+       acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+       status = acpi_cm_execute_STA (node, &flags);
+       if (ACPI_FAILURE (status))
+               p += sprintf(p, "Present:       No (%lx)\n", status);
+       else    p += sprintf(p, "Present:       Yes (flags %lx)\n", flags);
+
+       status = acpi_cm_execute_HID (node, &device_id);
+       if (!ACPI_FAILURE (status))
+               p += sprintf(p, "HID ident:     %s\n", &device_id.buffer );
+
+       status = acpi_cm_execute_UID (node, &device_id);
+       if (!ACPI_FAILURE (status))
+               p += sprintf(p, "UID ident:     %s\n", &device_id.buffer );
+
+       flags = 0xdeadbeef;
+       status = acpi_cm_execute_rint (node, &flags, "_PSC");
+       if (!ACPI_FAILURE (status))
+               p += sprintf(p, "Power status:  %d\n", flags);
+
+       p += sprintf(p, "This is some random information\n");
+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 len;
+}
+
+int
+proc_write_device_info(struct file *file, const char *buffer,
+                      unsigned long count, void *data)
+{
+       ACPI_HANDLE             obj_handle = (u32) data;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_STATUS             status;
+       int len;
+       u32 flags;
+       char buf[256], buf2[256];
+       DEVICE_ID               device_id;
+
+       acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+       node = acpi_ns_convert_handle_to_entry (obj_handle);
+
+       acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+       if (count > 250)
+               return -EPERM;
+       if (copy_from_user(buf, buffer, count))
+               return -EFAULT;
+       buf[count] = 0;
+       printk("acpi_write_device_info: %s...", buf);
+       flags = 0xdeadbeef;
+       status = acpi_cm_execute_any (node, buf2, buf);
+       if (ACPI_FAILURE (status))
+               printk("error: %lx (%s)\n", status, buf2);
+       else 
+               printk("okay: %lx (%s)\n", status, buf2);
+
+       return -EL3RST;
+}
+
+
+static ACPI_STATUS
+acpi_ns_add_proc_callback (
+       ACPI_HANDLE             obj_handle,
+       u32                     nesting_level,
+       void                    *context,
+       void                    **return_value)
+{
+       ACPI_STATUS             status;
+       ACPI_NAMESPACE_NODE     *node;
+       u32                     flags;
+       DEVICE_ID               device_id;
+       ACPI_GET_DEVICES_INFO   *info;
+
+
+       info = context;
+
+       acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+       printk("acpi_add_proc_callback: %lx\n", obj_handle);
+       node = acpi_ns_convert_handle_to_entry (obj_handle);
+
+       acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+       if (!node) {
+               printk("No node?!\n");
+               return (AE_BAD_PARAMETER);
+       }
+
+       /*
+        * Run _STA to determine if device is present
+        */
+
+#if 0
+       status = acpi_cm_execute_STA (node, &flags);
+       if (ACPI_FAILURE (status)) {
+               return (AE_OK);
+       }
+
+       if (!(flags & 0x01)) {
+               /* don't return at the device or children of the device if not there */
+
+               return (AE_CTRL_DEPTH);
+       }
+#endif
+
+       {
+               char proc_name[120];
+               struct proc_dir_entry *proc;
+
+               status = acpi_cm_execute_HID (node, &device_id);
+
+               if ((status == AE_NOT_FOUND) || (ACPI_FAILURE (status)))
+                       sprintf(proc_name, "power/device_unknown_%lx", obj_handle);
+               else    sprintf(proc_name, "power/device_%s", device_id.buffer );
+               printk("ACPI: creating %s\n", proc_name);
+               proc = create_proc_read_entry(proc_name, 0, NULL,
+                       proc_read_device_info, (void *) obj_handle);
+               if (!proc) printk(KERN_ERR "ACPI: Error creating %s\n", proc_name);
+               else {
+                       proc->write_proc = proc_write_device_info;
+               }
+       }
+
+       return (AE_OK);
+}
+
+
+void
+acpi_namespace_init(
+       void)
+{
+       ACPI_STATUS             status;
+       void ** return_value;
+
+       printk("ACPI: initializing namespace\n");
+
+       acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+       status = acpi_ns_walk_namespace (ACPI_TYPE_ANY,
+                          ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+                          NS_WALK_UNLOCK,
+                          acpi_ns_add_proc_callback, NULL,
+                          return_value);
+
+       acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+       return (status);
+}
+
+/*
+   _PSW -> lid does something interesting (unknown status).
+   _PSC -> PNP0303  (type error)
+   _LID -> lid does get lid status.
+   _ADR -> succeeds on many things
+   _CRS -> sometimes okay
+   _DIS -> 3 times okay
+   _EJ0 -> 1 time okay
+   _HID -> mostly returns integers
+   _PCL -> 2 times okay
+   _PRS -> 2 times okay
+   _PR[W0] -> 4 times okay
+   _PR1 -> okay once
+   _PSC -> 8 times okay
+   _PS3 -> 8 times okay, and seems to work
+   _PS2 -> okay once
+   _PS0 -> 8 times okay
+   _STA -> many times okay
+   _SRS -> error 3008
+   _UID -> many times okay.
+   _BST -> PNP0C0A battery status
+   _STM -> error 3008, sometimes (IDE set transfer timings)
+
+   
+*/
diff -ur -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x 
*.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x 
version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x 
bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x 
*.flags -x *.bak clean/drivers/acpi/power.c linux/drivers/acpi/power.c
--- clean/drivers/acpi/power.c  Wed Jan 31 16:14:33 2001
+++ linux/drivers/acpi/power.c  Thu Apr  5 00:51:28 2001
@@ -118,6 +118,7 @@
        }
 
        acpi_cmbatt_init();
+       acpi_namespace_init();
 
        return 0;
 }
diff -ur -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x 
*.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x 
version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x 
bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* -x 
*.flags -x *.bak clean/drivers/acpi/sys.c linux/drivers/acpi/sys.c
--- clean/drivers/acpi/sys.c    Wed Jan 31 16:14:33 2001
+++ linux/drivers/acpi/sys.c    Thu Apr  5 00:51:17 2001
@@ -79,11 +79,12 @@
 /*
  * Enter soft-off (S5)
  */
-static void
+void
 acpi_power_off(void)
 {
        struct acpi_enter_sx_ctx ctx;
        
+       printk("Entering power off\n");
        init_waitqueue_head(&ctx.wait);
        ctx.state = ACPI_STATE_S5;
        acpi_enter_sx_async(&ctx);

-- 
I'm [EMAIL PROTECTED] "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents at [EMAIL PROTECTED]
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to