merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / bus / acpi / hardware / hwsleep.c
1
2 /******************************************************************************
3 *
4 * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5 * $Revision: 1.1 $
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 }