Merge trunk HEAD (46152)
[reactos.git] / 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
29 #define _COMPONENT ACPI_HARDWARE
30 MODULE_NAME ("hwsleep")
31
32
33 /******************************************************************************
34 *
35 * FUNCTION: Acpi_set_firmware_waking_vector
36 *
37 * PARAMETERS: Physical_address - Physical address of ACPI real mode
38 * entry point.
39 *
40 * RETURN: AE_OK or AE_ERROR
41 *
42 * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
43 *
44 ******************************************************************************/
45
46 ACPI_STATUS
47 acpi_set_firmware_waking_vector (
48 ACPI_PHYSICAL_ADDRESS physical_address)
49 {
50
51
52 /* Make sure that we have an FACS */
53
54 if (!acpi_gbl_FACS) {
55 return (AE_NO_ACPI_TABLES);
56 }
57
58 /* Set the vector */
59
60 if (acpi_gbl_FACS->vector_width == 32) {
61 * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address;
62 }
63 else {
64 *acpi_gbl_FACS->firmware_waking_vector = physical_address;
65 }
66
67 return (AE_OK);
68 }
69
70
71 /******************************************************************************
72 *
73 * FUNCTION: Acpi_get_firmware_waking_vector
74 *
75 * PARAMETERS: *Physical_address - Output buffer where contents of
76 * the Firmware_waking_vector field of
77 * the FACS will be stored.
78 *
79 * RETURN: Status
80 *
81 * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
82 *
83 ******************************************************************************/
84
85 ACPI_STATUS
86 acpi_get_firmware_waking_vector (
87 ACPI_PHYSICAL_ADDRESS *physical_address)
88 {
89
90
91 if (!physical_address) {
92 return (AE_BAD_PARAMETER);
93 }
94
95 /* Make sure that we have an FACS */
96
97 if (!acpi_gbl_FACS) {
98 return (AE_NO_ACPI_TABLES);
99 }
100
101 /* Get the vector */
102
103 if (acpi_gbl_FACS->vector_width == 32) {
104 *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector;
105 }
106 else {
107 *physical_address = *acpi_gbl_FACS->firmware_waking_vector;
108 }
109
110 return (AE_OK);
111 }
112
113 /******************************************************************************
114 *
115 * FUNCTION: Acpi_enter_sleep_state
116 *
117 * PARAMETERS: Sleep_state - Which sleep state to enter
118 *
119 * RETURN: Status
120 *
121 * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
122 *
123 ******************************************************************************/
124
125 ACPI_STATUS
126 acpi_enter_sleep_state (
127 u8 sleep_state)
128 {
129 ACPI_STATUS status;
130 ACPI_OBJECT_LIST arg_list;
131 ACPI_OBJECT arg;
132 u8 type_a;
133 u8 type_b;
134 u16 PM1_acontrol;
135 u16 PM1_bcontrol;
136
137 /*
138 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
139 */
140
141 status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b);
142
143 if (!ACPI_SUCCESS(status)) {
144 return status;
145 }
146
147 /* run the _PTS and _GTS methods */
148 MEMSET(&arg_list, 0, sizeof(arg_list));
149 arg_list.count = 1;
150 arg_list.pointer = &arg;
151
152 MEMSET(&arg, 0, sizeof(arg));
153 arg.type = ACPI_TYPE_INTEGER;
154 arg.integer.value = sleep_state;
155
156 acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
157 acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL);
158
159 /* clear wake status */
160 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
161
162 PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL);
163
164 /* mask off SLP_EN and SLP_TYP fields */
165 PM1_acontrol &= 0xC3FF;
166
167 /* mask in SLP_EN */
168 PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
169
170 PM1_bcontrol = PM1_acontrol;
171
172 /* mask in SLP_TYP */
173 PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
174 PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
175
176 disable();
177
178 acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol);
179 acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol);
180 acpi_hw_register_write(ACPI_MTX_LOCK, PM1_CONTROL,
181 (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)));
182
183 enable();
184
185 return (AE_OK);
186 }