~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/acpi/sys.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  sys.c - System management (suspend, ...)
  3  *
  4  *  Copyright (C) 2000 Andrew Henroid
  5  *
  6  *  This program is free software; you can redistribute it and/or modify
  7  *  it under the terms of the GNU General Public License as published by
  8  *  the Free Software Foundation; either version 2 of the License, or
  9  *  (at your option) any later version.
 10  *
 11  *  This program is distributed in the hope that it will be useful,
 12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  *  GNU General Public License for more details.
 15  *
 16  *  You should have received a copy of the GNU General Public License
 17  *  along with this program; if not, write to the Free Software
 18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19  */
 20 
 21 #include <linux/kernel.h>
 22 #include <linux/pm.h>
 23 #include <linux/acpi.h>
 24 #include "acpi.h"
 25 #include "driver.h"
 26 
 27 #define _COMPONENT      OS_DEPENDENT
 28         MODULE_NAME     ("sys")
 29 
 30 #define ACPI_SLP_TYP(typa, typb)        (((int)(typa) << 8) | (int)(typb))
 31 #define ACPI_SLP_TYPA(value)            ((value) >> 8)
 32 #define ACPI_SLP_TYPB(value)            ((value) & 0xff)
 33 
 34 struct acpi_enter_sx_ctx
 35 {
 36         wait_queue_head_t wait;
 37         unsigned int      state;
 38 };
 39 
 40 volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
 41 static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
 42 
 43 /*
 44  * Enter system sleep state
 45  */
 46 static void
 47 acpi_enter_sx_async(void *context)
 48 {
 49         struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context;
 50         ACPI_OBJECT_LIST arg_list;
 51         ACPI_OBJECT arg;
 52 
 53         /*
 54          * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
 55          */
 56 
 57         // run the _PTS method
 58         memset(&arg_list, 0, sizeof(arg_list));
 59         arg_list.count = 1;
 60         arg_list.pointer = &arg;
 61 
 62         memset(&arg, 0, sizeof(arg));
 63         arg.type = ACPI_TYPE_NUMBER;
 64         arg.number.value = ctx->state;
 65 
 66         acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
 67         
 68         // clear wake status by writing a 1
 69         acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
 70                 
 71         acpi_sleep_state = ctx->state;
 72 
 73         // set ACPI_SLP_TYPA/b and ACPI_SLP_EN
 74         acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_A,
 75                 ACPI_SLP_TYPA(acpi_slptyp[ctx->state]));
 76         acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_B,
 77                 ACPI_SLP_TYPB(acpi_slptyp[ctx->state]));
 78         acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_EN, 1);
 79         
 80         if (ctx->state != ACPI_S1) {
 81                 /* we should have just shut off - what are we doing here? */
 82                 printk(KERN_ERR "ACPI: S%d failed\n", ctx->state);
 83                 goto out;
 84         }
 85 
 86         // wait until S1 is entered
 87         while (!(acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, WAK_STS)))
 88                 safe_halt();
 89 
 90         // run the _WAK method
 91         memset(&arg_list, 0, sizeof(arg_list));
 92         arg_list.count = 1;
 93         arg_list.pointer = &arg;
 94 
 95         memset(&arg, 0, sizeof(arg));
 96         arg.type = ACPI_TYPE_NUMBER;
 97         arg.number.value = ctx->state;
 98 
 99         acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
100 
101  out:
102         acpi_sleep_state = ACPI_S0;
103 
104         if (waitqueue_active(&ctx->wait))
105                 wake_up_interruptible(&ctx->wait);
106 }
107 
108 /*
109  * Enter soft-off (S5)
110  */
111 static void
112 acpi_power_off(void)
113 {
114         struct acpi_enter_sx_ctx ctx;
115 
116         if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
117             || acpi_slptyp[ACPI_S5] == ACPI_INVALID)
118                 return;
119         
120         init_waitqueue_head(&ctx.wait);
121         ctx.state = ACPI_S5;
122         acpi_enter_sx_async(&ctx);
123 }
124 
125 /*
126  * Enter system sleep state and wait for completion
127  */
128 int
129 acpi_enter_sx(acpi_sstate_t state)
130 {
131         struct acpi_enter_sx_ctx ctx;
132         DECLARE_WAITQUEUE(wait, current);
133         int ret = 0;
134 
135         if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
136             || acpi_slptyp[state] == ACPI_INVALID)
137                 return -EINVAL;
138         
139         init_waitqueue_head(&ctx.wait);
140         ctx.state = state;
141 
142         set_current_state(TASK_INTERRUPTIBLE);
143         add_wait_queue(&ctx.wait, &wait);
144 
145         if (acpi_os_queue_for_execution(0, acpi_enter_sx_async, &ctx))
146                 ret = -1;
147 
148         if (!ret)
149                 schedule();
150 
151         set_current_state(TASK_RUNNING);
152         remove_wait_queue(&ctx.wait, &wait);
153 
154         if (!ret && signal_pending(current))
155                 ret = -ERESTARTSYS;
156 
157         return ret;
158 }
159 
160 int
161 acpi_sys_init(void)
162 {
163         u8 sx;
164         u8 type_a;
165         u8 type_b;
166 
167         printk(KERN_INFO "ACPI: System firmware supports:");
168 
169         for (sx = ACPI_S0; sx <= ACPI_S5; sx++) {
170                 int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1);
171                 if (ACPI_SUCCESS(
172                            acpi_hw_obtain_sleep_type_register_data(ca_sx,
173                                                                    &type_a,
174                                                                    &type_b))) {
175 
176                         acpi_slptyp[sx] = ACPI_SLP_TYP(type_a, type_b);
177                         printk(" S%d", sx);
178                 }
179                 else {
180                         acpi_slptyp[sx] = ACPI_INVALID;
181                 }
182         }
183         printk("\n");
184         
185         pm_power_off = acpi_power_off;
186 
187         return 0;
188 }
189 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.