:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / hardware / hwsleep.c
1
2 /******************************************************************************
3  *
4  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5  *              $Revision$
6  *
7  *****************************************************************************/
8
9 /*
10  *  Copyright (C) 2000, 2001 R. Byron Moore
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27 #include "acpi.h"
28 #include "acnamesp.h"
29 #include "achware.h"
30
31 #define _COMPONENT          ACPI_HARDWARE
32          MODULE_NAME         ("hwsleep")
33
34
35 /******************************************************************************
36  *
37  * FUNCTION:    Acpi_set_firmware_waking_vector
38  *
39  * PARAMETERS:  Physical_address    - Physical address of ACPI real mode
40  *                                    entry point.
41  *
42  * RETURN:      AE_OK or AE_ERROR
43  *
44  * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
45  *
46  ******************************************************************************/
47
48 ACPI_STATUS
49 acpi_set_firmware_waking_vector (
50         ACPI_PHYSICAL_ADDRESS physical_address)
51 {
52
53
54         /* Make sure that we have an FACS */
55
56         if (!acpi_gbl_FACS) {
57                 return (AE_NO_ACPI_TABLES);
58         }
59
60         /* Set the vector */
61
62         if (acpi_gbl_FACS->vector_width == 32) {
63                 * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address;
64         }
65         else {
66                 *acpi_gbl_FACS->firmware_waking_vector = physical_address;
67         }
68
69         return (AE_OK);
70 }
71
72
73 /******************************************************************************
74  *
75  * FUNCTION:    Acpi_get_firmware_waking_vector
76  *
77  * PARAMETERS:  *Physical_address   - Output buffer where contents of
78  *                                    the Firmware_waking_vector field of
79  *                                    the FACS will be stored.
80  *
81  * RETURN:      Status
82  *
83  * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
84  *
85  ******************************************************************************/
86
87 ACPI_STATUS
88 acpi_get_firmware_waking_vector (
89         ACPI_PHYSICAL_ADDRESS *physical_address)
90 {
91
92
93         if (!physical_address) {
94                 return (AE_BAD_PARAMETER);
95         }
96
97         /* Make sure that we have an FACS */
98
99         if (!acpi_gbl_FACS) {
100                 return (AE_NO_ACPI_TABLES);
101         }
102
103         /* Get the vector */
104
105         if (acpi_gbl_FACS->vector_width == 32) {
106                 *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector;
107         }
108         else {
109                 *physical_address = *acpi_gbl_FACS->firmware_waking_vector;
110         }
111
112         return (AE_OK);
113 }
114
115 /******************************************************************************
116  *
117  * FUNCTION:    Acpi_enter_sleep_state
118  *
119  * PARAMETERS:  Sleep_state         - Which sleep state to enter
120  *
121  * RETURN:      Status
122  *
123  * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
124  *
125  ******************************************************************************/
126
127 ACPI_STATUS
128 acpi_enter_sleep_state (
129         u8 sleep_state)
130 {
131         ACPI_STATUS status;
132         ACPI_OBJECT_LIST arg_list;
133         ACPI_OBJECT arg;
134         u8 type_a;
135         u8 type_b;
136         u16 PM1_acontrol;
137         u16 PM1_bcontrol;
138
139         /*
140          * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
141          */
142
143         status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b);
144
145         if (!ACPI_SUCCESS(status)) {
146                 return status;
147         }
148
149         /* run the _PTS and _GTS methods */
150         MEMSET(&arg_list, 0, sizeof(arg_list));
151         arg_list.count = 1;
152         arg_list.pointer = &arg;
153
154         MEMSET(&arg, 0, sizeof(arg));
155         arg.type = ACPI_TYPE_INTEGER;
156         arg.integer.value = sleep_state;
157
158         acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
159         acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL);
160
161         /* clear wake status */
162         acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
163
164         PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL);
165
166         /* mask off SLP_EN and SLP_TYP fields */
167         PM1_acontrol &= 0xC3FF;
168
169         /* mask in SLP_EN */
170         PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
171
172         PM1_bcontrol = PM1_acontrol;
173
174         /* mask in SLP_TYP */
175         PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
176         PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
177
178         disable();
179
180         acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol);
181         acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol);
182         acpi_hw_register_write(ACPI_MTX_LOCK, PM1_CONTROL,
183                 (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)));
184
185         enable();
186
187         return (AE_OK);
188 }