ReactOS 0.4.17-dev-1190-g4c812f4
sleep.c
Go to the documentation of this file.
1#include <uacpi/sleep.h>
4#include <uacpi/internal/io.h>
8
9#ifndef UACPI_BAREBONES_MODE
10
11#ifndef UACPI_REDUCED_HARDWARE
12#define CALL_SLEEP_FN(name, state) \
13 (uacpi_is_hardware_reduced() ? \
14 name##_hw_reduced(state) : name##_hw_full(state))
15#else
16#define CALL_SLEEP_FN(name, state) name##_hw_reduced(state);
17#endif
18
21
22#ifndef UACPI_REDUCED_HARDWARE
24 uacpi_phys_addr addr32, uacpi_phys_addr addr64
25)
26{
27 struct acpi_facs *facs = g_uacpi_rt_ctx.facs;
28
29 if (facs == UACPI_NULL)
30 return UACPI_STATUS_OK;
31
32 facs->firmware_waking_vector = addr32;
33
34 // The 64-bit wake vector doesn't exist, we're done
35 if (facs->length < 32)
36 return UACPI_STATUS_OK;
37
38 // Only allow 64-bit wake vector on 1.0 and above FACS
39 if (facs->version >= 1)
40 facs->x_firmware_waking_vector = addr64;
41 else
43
44 return UACPI_STATUS_OK;
45}
46
48{
50 uacpi_interrupt_state int_state;
51 uacpi_u64 wake_status, pm1a, pm1b;
52
55 );
57 return ret;
58
61 return ret;
62
65 return ret;
66
69 return ret;
70
73 return ret;
74
76 pm1b = pm1a;
77
78 pm1a |= g_uacpi_rt_ctx.last_sleep_typ_a << ACPI_PM1_CNT_SLP_TYP_IDX;
79 pm1b |= g_uacpi_rt_ctx.last_sleep_typ_b << ACPI_PM1_CNT_SLP_TYP_IDX;
80
82
83 /*
84 * Just like ACPICA, split writing SLP_TYP and SLP_EN to work around
85 * buggy firmware that can't handle both written at the same time.
86 */
89 goto out;
90
93
94 if (state < UACPI_SLEEP_STATE_S4)
96
99 goto out;
100
101 if (state > UACPI_SLEEP_STATE_S3) {
102 /*
103 * We're still here, this is a bug or very slow firmware.
104 * Just try spinning for a bit.
105 */
106 uacpi_u64 stalled_time = 0;
107
108 // 10 seconds max
109 while (stalled_time < (10 * 1000 * 1000)) {
111 stalled_time += 100;
112 }
113
114 // Try one more time
117 goto out;
118
119 // Nothing we can do here, give up
121 goto out;
122 }
123
124 do {
126 UACPI_REGISTER_FIELD_WAK_STS, &wake_status
127 );
129 goto out;
130 } while (wake_status != 1);
131
132out:
134 return ret;
135}
136
138{
140 uacpi_u64 pm1a, pm1b;
142
143 /*
144 * Some hardware apparently relies on S0 values being written to the PM1
145 * control register on wake, so do this here.
146 */
147
148 if (g_uacpi_rt_ctx.s0_sleep_typ_a == UACPI_SLEEP_TYP_INVALID)
149 goto out;
150
153 goto out;
154
156 pm1b = pm1a;
157
158 pm1a |= g_uacpi_rt_ctx.s0_sleep_typ_a << ACPI_PM1_CNT_SLP_TYP_IDX;
159 pm1b |= g_uacpi_rt_ctx.s0_sleep_typ_b << ACPI_PM1_CNT_SLP_TYP_IDX;
160
162out:
163 // Errors ignored intentionally, we don't want to abort because of this
164 return UACPI_STATUS_OK;
165}
166
168{
170 g_uacpi_rt_ctx.last_sleep_typ_a = UACPI_SLEEP_TYP_INVALID;
171 g_uacpi_rt_ctx.last_sleep_typ_b = UACPI_SLEEP_TYP_INVALID;
172
173 // Set the status to 2 (waking) while we execute the wake method.
174 eval_sst(2);
175
178 return ret;
179
182 return ret;
183
185
186 // Apparently some BIOSes expect us to clear this, so do it
189 );
190
192
193 // Now that we're awake set the status to 1 (running)
194 eval_sst(1);
195
196 return UACPI_STATUS_OK;
197}
198#endif
199
202)
203{
204 uacpi_char path[] = "_S0";
206 uacpi_object *obj0, *obj1, *ret_obj = UACPI_NULL;
207
208 path[2] += state;
209
213 );
214 if (ret != UACPI_STATUS_OK) {
216 uacpi_warn("error while evaluating %s: %s", path,
218 } else {
219 uacpi_trace("sleep state %d is not supported as %s was not found",
220 state, path);
221 }
222 goto out;
223 }
224
225 switch (ret_obj->package->count) {
226 case 0:
227 uacpi_error("empty package while evaluating %s!", path);
229 goto out;
230
231 case 1:
232 obj0 = ret_obj->package->objects[0];
235 "invalid object type at pkg[0] => %s when evaluating %s",
237 );
238 goto out;
239 }
240
241 *a = obj0->integer;
242 *b = obj0->integer >> 8;
243 break;
244
245 default:
246 obj0 = ret_obj->package->objects[0];
247 obj1 = ret_obj->package->objects[1];
248
250 obj1->type != UACPI_OBJECT_INTEGER)) {
252 "invalid object type when evaluating %s: "
253 "pkg[0] => %s, pkg[1] => %s", path,
256 );
258 goto out;
259 }
260
261 *a = obj0->integer;
262 *b = obj1->integer;
263 break;
264 }
265
266out:
267 if (ret != UACPI_STATUS_OK) {
270 }
271
272 uacpi_object_unref(ret_obj);
273 return ret;
274}
275
278)
279{
283
287
288 arg->integer = value;
289 args.objects = &arg;
290 args.count = 1;
291
293 switch (ret) {
294 case UACPI_STATUS_OK:
295 break;
298 break;
299 default:
300 uacpi_error("error while evaluating %s: %s",
302 break;
303 }
304
306 return ret;
307}
308
310{
312}
313
315{
317}
318
320{
321 return eval_sleep_helper(
323 "_SST", value
324 );
325}
326
328{
330
331 /*
332 * This optional object is a control method that OSPM invokes to set the
333 * system status indicator as desired.
334 * Arguments:(1)
335 * Arg0 - An Integer containing the system status indicator identifier:
336 * 0 - No system state indication. Indicator off
337 * 1 - Working
338 * 2 - Waking
339 * 3 - Sleeping. Used to indicate system state S1, S2, or S3
340 * 4 - Sleeping with context saved to non-volatile storage
341 */
342 switch (state) {
343 case UACPI_SLEEP_STATE_S0:
344 arg = 1;
345 break;
346 case UACPI_SLEEP_STATE_S1:
347 case UACPI_SLEEP_STATE_S2:
348 case UACPI_SLEEP_STATE_S3:
349 arg = 3;
350 break;
351 case UACPI_SLEEP_STATE_S4:
352 arg = 4;
353 break;
354 case UACPI_SLEEP_STATE_S5:
355 arg = 0;
356 break;
357 default:
359 }
360
361 return eval_sst(arg);
362}
363
365{
366 uacpi_u8 state = state_enum;
368
370
371 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_S5))
373
375 state,
376 &g_uacpi_rt_ctx.last_sleep_typ_a,
377 &g_uacpi_rt_ctx.last_sleep_typ_b
378 );
379 if (ret != UACPI_STATUS_OK)
380 return ret;
381
383 0,
384 &g_uacpi_rt_ctx.s0_sleep_typ_a,
385 &g_uacpi_rt_ctx.s0_sleep_typ_b
386 );
387
388 ret = eval_pts(state);
390 return ret;
391
393 return UACPI_STATUS_OK;
394}
395
397{
399
400 value = (slp_typ << ACPI_SLP_CNT_SLP_TYP_IDX);
403
404 return value;
405}
406
408{
410 uacpi_u8 sleep_control;
411 uacpi_u64 wake_status;
412 uacpi_interrupt_state int_state;
413 struct acpi_fadt *fadt = &g_uacpi_rt_ctx.fadt;
414
415 if (!fadt->sleep_control_reg.address || !fadt->sleep_status_reg.address)
417
419
423 );
425 goto out;
426
427 sleep_control = make_hw_reduced_sleep_control(
428 g_uacpi_rt_ctx.last_sleep_typ_a
429 );
430
431 if (state < UACPI_SLEEP_STATE_S4)
433
434 /*
435 * To put the system into a sleep state, software will write the HW-reduced
436 * Sleep Type value (obtained from the \_Sx object in the DSDT) and the
437 * SLP_EN bit to the sleep control register.
438 */
441 goto out;
442
443 /*
444 * The OSPM then polls the WAK_STS bit of the SLEEP_STATUS_REG waiting for
445 * it to be one (1), indicating that the system has been transitioned
446 * back to the Working state.
447 */
448 do {
451 );
453 goto out;
454 } while (wake_status != 1);
455
456out:
458 return ret;
459}
460
462{
463 uacpi_u8 sleep_control;
465
466 if (g_uacpi_rt_ctx.s0_sleep_typ_a == UACPI_SLEEP_TYP_INVALID)
467 goto out;
468
469 sleep_control = make_hw_reduced_sleep_control(
470 g_uacpi_rt_ctx.s0_sleep_typ_a
471 );
473
474out:
475 return UACPI_STATUS_OK;
476}
477
479{
480 g_uacpi_rt_ctx.last_sleep_typ_a = UACPI_SLEEP_TYP_INVALID;
481 g_uacpi_rt_ctx.last_sleep_typ_b = UACPI_SLEEP_TYP_INVALID;
482
483 // Set the status to 2 (waking) while we execute the wake method.
484 eval_sst(2);
485
487
488 // Apparently some BIOSes expect us to clear this, so do it
491 );
492
493 // Now that we're awake set the status to 1 (running)
494 eval_sst(1);
495
496 return UACPI_STATUS_OK;
497}
498
500{
501 uacpi_u8 state = state_enum;
502
504
505 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_MAX))
507
508 if (uacpi_unlikely(g_uacpi_rt_ctx.last_sleep_typ_a > ACPI_SLP_TYP_MAX ||
509 g_uacpi_rt_ctx.last_sleep_typ_b > ACPI_SLP_TYP_MAX)) {
510 uacpi_error("invalid SLP_TYP values: 0x%02X:0x%02X",
511 g_uacpi_rt_ctx.last_sleep_typ_a,
512 g_uacpi_rt_ctx.last_sleep_typ_b);
514 }
515
516 return CALL_SLEEP_FN(enter_sleep_state, state);
517}
518
520{
522
525 return ret;
526
528}
529
531 uacpi_sleep_state state_enum
532)
533{
534 uacpi_u8 state = state_enum;
535
537
538 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_MAX))
540
541 return CALL_SLEEP_FN(prepare_for_wake_from_sleep_state, state);
542}
543
545 uacpi_sleep_state state_enum
546)
547{
548 uacpi_u8 state = state_enum;
549
551
552 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_MAX))
554
555 return CALL_SLEEP_FN(wake_from_sleep_state, state);
556}
557
559{
561 uacpi_handle pci_dev = UACPI_NULL, io_handle = UACPI_NULL;
562 struct acpi_fadt *fadt = &g_uacpi_rt_ctx.fadt;
563 struct acpi_gas *reset_reg = &fadt->reset_reg;
564
565 /*
566 * Allow restarting earlier than namespace load so that the kernel can
567 * use this in case of some initialization error.
568 */
570
571 if (!(fadt->flags & ACPI_RESET_REG_SUP) || !reset_reg->address)
573
574 switch (reset_reg->address_space_id) {
576 /*
577 * For SystemIO we don't do any checking, and we ignore bit width
578 * because that's what NT does.
579 */
580 ret = uacpi_kernel_io_map(reset_reg->address, 1, &io_handle);
582 return ret;
583
584 ret = uacpi_kernel_io_write8(io_handle, 0, fadt->reset_value);
585 break;
587 ret = uacpi_write_register(UACPI_REGISTER_RESET, fadt->reset_value);
588 break;
591
592 // Bus is assumed to be 0 here
593 address.segment = 0;
594 address.bus = 0;
595 address.device = (reset_reg->address >> 32) & 0xFF;
596 address.function = (reset_reg->address >> 16) & 0xFF;
597
600 break;
601
603 pci_dev, reset_reg->address & 0xFFFF, fadt->reset_value
604 );
605 break;
606 }
607 default:
609 "unable to perform a reset: unsupported address space '%s' (%d)",
610 uacpi_address_space_to_string(reset_reg->address_space_id),
611 reset_reg->address_space_id
612 );
614 }
615
616 if (ret == UACPI_STATUS_OK) {
617 /*
618 * This should've worked but we're still here.
619 * Spin for a bit then give up.
620 */
621 uacpi_u64 stalled_time = 0;
622
623 while (stalled_time < (1000 * 1000)) {
625 stalled_time += 100;
626 }
627
628 uacpi_error("reset timeout");
630 }
631
632 if (pci_dev != UACPI_NULL)
634 if (io_handle != UACPI_NULL)
635 uacpi_kernel_io_unmap(io_handle);
636
637 return ret;
638}
639
640#endif // !UACPI_BAREBONES_MODE
static int state
Definition: maze.c:121
#define UACPI_ARCH_FLUSH_CPU_CACHE()
Definition: arch_helpers.h:10
unsigned long uacpi_interrupt_state
Definition: arch_helpers.h:14
#define ACPI_SLP_CNT_SLP_EN_MASK
Definition: acpi.h:954
#define ACPI_PM1_CNT_SLP_TYP_MASK
Definition: acpi.h:917
#define ACPI_PM1_STS_CLEAR
Definition: acpi.h:879
#define ACPI_SLP_CNT_SLP_TYP_IDX
Definition: acpi.h:948
#define ACPI_SLP_CNT_SLP_TYP_MASK
Definition: acpi.h:953
#define ACPI_PM1_CNT_SLP_EN_MASK
Definition: acpi.h:918
#define ACPI_SLP_STS_CLEAR
Definition: acpi.h:971
#define ACPI_RESET_REG_SUP
Definition: acpi.h:719
#define ACPI_SLP_TYP_MAX
Definition: acpi.h:912
#define ACPI_PM1_CNT_SLP_TYP_IDX
Definition: acpi.h:907
#define UACPI_ENSURE_INIT_LEVEL_AT_LEAST(lvl)
Definition: context.h:127
#define UACPI_SLEEP_TYP_INVALID
Definition: context.h:34
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:18
#define UACPI_UNUSED(x)
Definition: helpers.h:7
#define uacpi_trace(...)
Definition: log.h:33
#define uacpi_error(...)
Definition: log.h:36
#define uacpi_warn(...)
Definition: log.h:35
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:328
uacpi_namespace_node * uacpi_namespace_get_predefined(uacpi_predefined_namespace)
Definition: namespace.c:269
@ UACPI_PREDEFINED_NAMESPACE_SI
Definition: namespace.h:21
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:264
#define uacpi_unlikely(expr)
Definition: compiler.h:88
uint64_t uacpi_u64
Definition: types.h:22
char uacpi_char
Definition: types.h:44
#define UACPI_NULL
Definition: types.h:33
uint8_t uacpi_u8
Definition: types.h:19
@ UACPI_REGISTER_FIELD_WAK_STS
Definition: registers.h:65
@ UACPI_REGISTER_FIELD_HWR_WAK_STS
Definition: registers.h:64
uacpi_status uacpi_read_register_field(uacpi_register_field, uacpi_u64 *)
Definition: registers.c:487
uacpi_status uacpi_read_register(uacpi_register, uacpi_u64 *)
Definition: registers.c:227
uacpi_status uacpi_write_register(uacpi_register, uacpi_u64)
Definition: registers.c:286
uacpi_status uacpi_write_registers(uacpi_register, uacpi_u64, uacpi_u64)
Definition: registers.c:307
uacpi_status uacpi_write_register_field(uacpi_register_field, uacpi_u64)
Definition: registers.c:518
@ UACPI_REGISTER_RESET
Definition: registers.h:24
@ UACPI_REGISTER_PM1_CNT
Definition: registers.h:19
@ UACPI_REGISTER_SLP_CNT
Definition: registers.h:22
#define uacpi_unlikely_error(expr)
Definition: status.h:50
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
@ UACPI_STATUS_UNIMPLEMENTED
Definition: status.h:19
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_STATUS_AML_INCOMPATIBLE_OBJECT_TYPE
Definition: status.h:38
@ UACPI_STATUS_AML_BAD_ENCODING
Definition: status.h:39
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_HARDWARE_TIMEOUT
Definition: status.h:28
const uacpi_char * uacpi_status_to_string(uacpi_status)
Definition: uacpi.c:61
const uacpi_char * uacpi_address_space_to_string(uacpi_address_space space)
Definition: types.c:12
@ UACPI_OBJECT_PACKAGE_BIT
Definition: types.h:138
uacpi_u64 uacpi_phys_addr
Definition: types.h:17
const uacpi_char * uacpi_object_type_to_string(uacpi_object_type)
Definition: types.c:52
@ UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
Definition: types.h:72
@ UACPI_INIT_LEVEL_NAMESPACE_INITIALIZED
Definition: types.h:84
@ UACPI_OBJECT_INTEGER
Definition: types.h:112
@ UACPI_ADDRESS_SPACE_SYSTEM_MEMORY
Definition: types.h:43
@ UACPI_ADDRESS_SPACE_PCI_CONFIG
Definition: types.h:45
@ UACPI_ADDRESS_SPACE_SYSTEM_IO
Definition: types.h:44
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:761
uacpi_status uacpi_enable_all_wake_gpes(void)
Definition: event.c:2852
uacpi_status uacpi_disable_all_gpes(void)
Definition: event.c:2836
uacpi_status uacpi_enable_all_runtime_gpes(void)
Definition: event.c:2844
void uacpi_events_restore_buttons_post_wake(void)
Definition: event.c:243
uacpi_status uacpi_clear_all_events(void)
Definition: event.c:3391
return ret
Definition: mutex.c:147
r parent
Definition: btrfs.c:3010
GLuint address
Definition: glext.h:9393
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
uacpi_status uacpi_kernel_io_map(uacpi_io_addr base, uacpi_size len, uacpi_handle *out_handle)
Definition: uacpiosl.c:165
void uacpi_kernel_pci_device_close(uacpi_handle)
Definition: uacpiosl.c:251
uacpi_status uacpi_kernel_io_write8(uacpi_handle, uacpi_size offset, uacpi_u8 in_value)
Definition: uacpiosl.c:320
void uacpi_kernel_restore_interrupts(uacpi_interrupt_state state)
void uacpi_kernel_stall(uacpi_u8 usec)
Definition: uacpiosl.c:42
uacpi_interrupt_state uacpi_kernel_disable_interrupts(void)
uacpi_status uacpi_kernel_pci_device_open(uacpi_pci_address address, uacpi_handle *out_handle)
Definition: uacpiosl.c:242
uacpi_status uacpi_kernel_pci_write8(uacpi_handle device, uacpi_size offset, uacpi_u8 value)
Definition: uacpiosl.c:278
void uacpi_kernel_io_unmap(uacpi_handle handle)
Definition: uacpiosl.c:171
#define args
Definition: format.c:66
static uacpi_status enter_sleep_state_hw_reduced(uacpi_u8 state)
Definition: sleep.c:407
uacpi_status uacpi_enter_sleep_state_simple(uacpi_sleep_state state)
Definition: sleep.c:519
uacpi_status uacpi_enter_sleep_state(enum uacpi_sleep_state state_enum)
Definition: sleep.c:499
static uacpi_status eval_wak(uacpi_u8 state)
Definition: sleep.c:314
uacpi_status uacpi_prepare_for_wake_from_sleep_state(uacpi_sleep_state state_enum)
Definition: sleep.c:530
#define CALL_SLEEP_FN(name, state)
Definition: sleep.c:12
static uacpi_status eval_sst(uacpi_u8 value)
Definition: sleep.c:319
static uacpi_status get_slp_type_for_state(uacpi_u8 state, uacpi_u8 *a, uacpi_u8 *b)
Definition: sleep.c:200
uacpi_status uacpi_wake_from_sleep_state(uacpi_sleep_state state_enum)
Definition: sleep.c:544
static uacpi_status prepare_for_wake_from_sleep_state_hw_reduced(uacpi_u8 state)
Definition: sleep.c:461
uacpi_status uacpi_reboot(void)
Definition: sleep.c:558
static uacpi_u8 make_hw_reduced_sleep_control(uacpi_u8 slp_typ)
Definition: sleep.c:396
static uacpi_status prepare_for_wake_from_sleep_state_hw_full(uacpi_u8 state)
Definition: sleep.c:137
uacpi_status uacpi_set_waking_vector(uacpi_phys_addr addr32, uacpi_phys_addr addr64)
Definition: sleep.c:23
uacpi_status uacpi_prepare_for_sleep_state(enum uacpi_sleep_state state_enum)
Definition: sleep.c:364
static uacpi_status wake_from_sleep_state_hw_reduced(uacpi_u8 state)
Definition: sleep.c:478
static uacpi_status wake_from_sleep_state_hw_full(uacpi_u8 state)
Definition: sleep.c:167
static uacpi_status eval_pts(uacpi_u8 state)
Definition: sleep.c:309
static uacpi_status enter_sleep_state_hw_full(uacpi_u8 state)
Definition: sleep.c:47
static uacpi_status eval_sst_for_state(enum uacpi_sleep_state state)
Definition: sleep.c:327
static uacpi_status eval_sleep_helper(uacpi_namespace_node *parent, const uacpi_char *path, uacpi_u8 value)
Definition: sleep.c:276
uacpi_sleep_state
Definition: sleep.h:32
uacpi_u32 length
Definition: acpi.h:805
uacpi_u64 x_firmware_waking_vector
Definition: acpi.h:810
uacpi_u8 version
Definition: acpi.h:811
uacpi_u32 firmware_waking_vector
Definition: acpi.h:807
Definition: match.c:390
uacpi_u8 type
Definition: types.h:252
uacpi_package * package
Definition: types.h:264
uacpi_u64 integer
Definition: types.h:263
uacpi_object ** objects
Definition: types.h:36
uacpi_size count
Definition: types.h:37
uacpi_u16 segment
Definition: types.h:88
uacpi_status uacpi_eval(uacpi_namespace_node *parent, const uacpi_char *path, const uacpi_object_array *args, uacpi_object **ret)
Definition: uacpi.c:721
uacpi_status uacpi_eval_typed(uacpi_namespace_node *parent, const uacpi_char *path, const uacpi_object_array *args, uacpi_object_type_bits ret_mask, uacpi_object **ret)
Definition: uacpi.c:866
Definition: pdh_main.c:64
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
void * arg
Definition: msvc.h:10