Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / acpi / sys.c
blob13648c25502375a24f2a00281105e98ff6901cb9
1 /*
2 * sys.c - System management (suspend, ...)
4 * Copyright (C) 2000 Andrew Henroid
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.
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.
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
21 #include <linux/kernel.h>
22 #include <linux/pm.h>
23 #include <linux/acpi.h>
24 #include "acpi.h"
25 #include "driver.h"
27 #define _COMPONENT OS_DEPENDENT
28 MODULE_NAME ("sys")
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)
34 struct acpi_enter_sx_ctx
36 wait_queue_head_t wait;
37 unsigned int state;
40 volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
41 static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
44 * Enter system sleep state
46 static void
47 acpi_enter_sx_async(void *context)
49 struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context;
50 ACPI_OBJECT_LIST arg_list;
51 ACPI_OBJECT arg;
54 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
57 // run the _PTS method
58 memset(&arg_list, 0, sizeof(arg_list));
59 arg_list.count = 1;
60 arg_list.pointer = &arg;
62 memset(&arg, 0, sizeof(arg));
63 arg.type = ACPI_TYPE_NUMBER;
64 arg.number.value = ctx->state;
66 acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
68 // clear wake status by writing a 1
69 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
71 acpi_sleep_state = ctx->state;
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);
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;
86 // wait until S1 is entered
87 while (!(acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, WAK_STS)))
88 safe_halt();
90 // run the _WAK method
91 memset(&arg_list, 0, sizeof(arg_list));
92 arg_list.count = 1;
93 arg_list.pointer = &arg;
95 memset(&arg, 0, sizeof(arg));
96 arg.type = ACPI_TYPE_NUMBER;
97 arg.number.value = ctx->state;
99 acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
101 out:
102 acpi_sleep_state = ACPI_S0;
104 if (waitqueue_active(&ctx->wait))
105 wake_up_interruptible(&ctx->wait);
109 * Enter soft-off (S5)
111 static void
112 acpi_power_off(void)
114 struct acpi_enter_sx_ctx ctx;
116 if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
117 || acpi_slptyp[ACPI_S5] == ACPI_INVALID)
118 return;
120 init_waitqueue_head(&ctx.wait);
121 ctx.state = ACPI_S5;
122 acpi_enter_sx_async(&ctx);
126 * Enter system sleep state and wait for completion
129 acpi_enter_sx(acpi_sstate_t state)
131 struct acpi_enter_sx_ctx ctx;
132 DECLARE_WAITQUEUE(wait, current);
133 int ret = 0;
135 if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
136 || acpi_slptyp[state] == ACPI_INVALID)
137 return -EINVAL;
139 init_waitqueue_head(&ctx.wait);
140 ctx.state = state;
142 set_current_state(TASK_INTERRUPTIBLE);
143 add_wait_queue(&ctx.wait, &wait);
145 if (acpi_os_queue_for_execution(0, acpi_enter_sx_async, &ctx))
146 ret = -1;
148 if (!ret)
149 schedule();
151 set_current_state(TASK_RUNNING);
152 remove_wait_queue(&ctx.wait, &wait);
154 if (!ret && signal_pending(current))
155 ret = -ERESTARTSYS;
157 return ret;
161 acpi_sys_init(void)
163 u8 sx;
164 u8 type_a;
165 u8 type_b;
167 printk(KERN_INFO "ACPI: System firmware supports:");
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))) {
176 acpi_slptyp[sx] = ACPI_SLP_TYP(type_a, type_b);
177 printk(" S%d", sx);
179 else {
180 acpi_slptyp[sx] = ACPI_INVALID;
183 printk("\n");
185 pm_power_off = acpi_power_off;
187 return 0;