ReactOS 0.4.16-dev-1537-g4e425b5
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_u64 wake_status, pm1a, pm1b;
51
54 );
56 return ret;
57
60 return ret;
61
64 return ret;
65
68 return ret;
69
72 return ret;
73
75 pm1b = pm1a;
76
77 pm1a |= g_uacpi_rt_ctx.last_sleep_typ_a << ACPI_PM1_CNT_SLP_TYP_IDX;
78 pm1b |= g_uacpi_rt_ctx.last_sleep_typ_b << ACPI_PM1_CNT_SLP_TYP_IDX;
79
80 /*
81 * Just like ACPICA, split writing SLP_TYP and SLP_EN to work around
82 * buggy firmware that can't handle both written at the same time.
83 */
86 return ret;
87
90
91 if (state < UACPI_SLEEP_STATE_S4)
93
96 return ret;
97
98 if (state > UACPI_SLEEP_STATE_S3) {
99 /*
100 * We're still here, this is a bug or very slow firmware.
101 * Just try spinning for a bit.
102 */
103 uacpi_u64 stalled_time = 0;
104
105 // 10 seconds max
106 while (stalled_time < (10 * 1000 * 1000)) {
108 stalled_time += 100;
109 }
110
111 // Try one more time
114 return ret;
115
116 // Nothing we can do here, give up
118 }
119
120 do {
122 UACPI_REGISTER_FIELD_WAK_STS, &wake_status
123 );
125 return ret;
126 } while (wake_status != 1);
127
128 return UACPI_STATUS_OK;
129}
130
132{
134 uacpi_u64 pm1a, pm1b;
136
137 /*
138 * Some hardware apparently relies on S0 values being written to the PM1
139 * control register on wake, so do this here.
140 */
141
142 if (g_uacpi_rt_ctx.s0_sleep_typ_a == UACPI_SLEEP_TYP_INVALID)
143 goto out;
144
147 goto out;
148
150 pm1b = pm1a;
151
152 pm1a |= g_uacpi_rt_ctx.s0_sleep_typ_a << ACPI_PM1_CNT_SLP_TYP_IDX;
153 pm1b |= g_uacpi_rt_ctx.s0_sleep_typ_b << ACPI_PM1_CNT_SLP_TYP_IDX;
154
156out:
157 // Errors ignored intentionally, we don't want to abort because of this
158 return UACPI_STATUS_OK;
159}
160
162{
164 g_uacpi_rt_ctx.last_sleep_typ_a = UACPI_SLEEP_TYP_INVALID;
165 g_uacpi_rt_ctx.last_sleep_typ_b = UACPI_SLEEP_TYP_INVALID;
166
167 // Set the status to 2 (waking) while we execute the wake method.
168 eval_sst(2);
169
172 return ret;
173
176 return ret;
177
179
180 // Apparently some BIOSes expect us to clear this, so do it
183 );
184
185 // Now that we're awake set the status to 1 (running)
186 eval_sst(1);
187
188 return UACPI_STATUS_OK;
189}
190#endif
191
194)
195{
196 uacpi_char path[] = "_S0";
198 uacpi_object *obj0, *obj1, *ret_obj = UACPI_NULL;
199
200 path[2] += state;
201
205 );
206 if (ret != UACPI_STATUS_OK) {
208 uacpi_warn("error while evaluating %s: %s\n", path,
210 } else {
211 uacpi_trace("sleep state %d is not supported as %s was not found\n",
212 state, path);
213 }
214 goto out;
215 }
216
217 switch (ret_obj->package->count) {
218 case 0:
219 uacpi_error("empty package while evaluating %s!\n", path);
221 goto out;
222
223 case 1:
224 obj0 = ret_obj->package->objects[0];
227 "invalid object type at pkg[0] => %s when evaluating %s\n",
229 );
230 goto out;
231 }
232
233 *a = obj0->integer;
234 *b = obj0->integer >> 8;
235 break;
236
237 default:
238 obj0 = ret_obj->package->objects[0];
239 obj1 = ret_obj->package->objects[1];
240
242 obj1->type != UACPI_OBJECT_INTEGER)) {
244 "invalid object type when evaluating %s: "
245 "pkg[0] => %s, pkg[1] => %s\n", path,
248 );
250 goto out;
251 }
252
253 *a = obj0->integer;
254 *b = obj1->integer;
255 break;
256 }
257
258out:
259 if (ret != UACPI_STATUS_OK) {
262 }
263
264 uacpi_object_unref(ret_obj);
265 return ret;
266}
267
270)
271{
275
279
280 arg->integer = value;
281 args.objects = &arg;
282 args.count = 1;
283
285 switch (ret) {
286 case UACPI_STATUS_OK:
287 break;
290 break;
291 default:
292 uacpi_error("error while evaluating %s: %s\n",
294 break;
295 }
296
298 return ret;
299}
300
302{
304}
305
307{
309}
310
312{
313 return eval_sleep_helper(
315 "_SST", value
316 );
317}
318
320{
322
323 /*
324 * This optional object is a control method that OSPM invokes to set the
325 * system status indicator as desired.
326 * Arguments:(1)
327 * Arg0 - An Integer containing the system status indicator identifier:
328 * 0 - No system state indication. Indicator off
329 * 1 - Working
330 * 2 - Waking
331 * 3 - Sleeping. Used to indicate system state S1, S2, or S3
332 * 4 - Sleeping with context saved to non-volatile storage
333 */
334 switch (state) {
335 case UACPI_SLEEP_STATE_S0:
336 arg = 1;
337 break;
338 case UACPI_SLEEP_STATE_S1:
339 case UACPI_SLEEP_STATE_S2:
340 case UACPI_SLEEP_STATE_S3:
341 arg = 3;
342 break;
343 case UACPI_SLEEP_STATE_S4:
344 arg = 4;
345 break;
346 case UACPI_SLEEP_STATE_S5:
347 arg = 0;
348 break;
349 default:
351 }
352
353 return eval_sst(arg);
354}
355
357{
358 uacpi_u8 state = state_enum;
360
362
363 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_S5))
365
367 state,
368 &g_uacpi_rt_ctx.last_sleep_typ_a,
369 &g_uacpi_rt_ctx.last_sleep_typ_b
370 );
371 if (ret != UACPI_STATUS_OK)
372 return ret;
373
375 0,
376 &g_uacpi_rt_ctx.s0_sleep_typ_a,
377 &g_uacpi_rt_ctx.s0_sleep_typ_b
378 );
379
380 ret = eval_pts(state);
382 return ret;
383
385 return UACPI_STATUS_OK;
386}
387
389{
391
392 value = (slp_typ << ACPI_SLP_CNT_SLP_TYP_IDX);
395
396 return value;
397}
398
400{
402 uacpi_u8 sleep_control;
403 uacpi_u64 wake_status;
404 struct acpi_fadt *fadt = &g_uacpi_rt_ctx.fadt;
405
406 if (!fadt->sleep_control_reg.address || !fadt->sleep_status_reg.address)
408
412 );
414 return ret;
415
416 sleep_control = make_hw_reduced_sleep_control(
417 g_uacpi_rt_ctx.last_sleep_typ_a
418 );
419
420 if (state < UACPI_SLEEP_STATE_S4)
422
423 /*
424 * To put the system into a sleep state, software will write the HW-reduced
425 * Sleep Type value (obtained from the \_Sx object in the DSDT) and the
426 * SLP_EN bit to the sleep control register.
427 */
430 return ret;
431
432 /*
433 * The OSPM then polls the WAK_STS bit of the SLEEP_STATUS_REG waiting for
434 * it to be one (1), indicating that the system has been transitioned
435 * back to the Working state.
436 */
437 do {
440 );
442 return ret;
443 } while (wake_status != 1);
444
445 return UACPI_STATUS_OK;
446}
447
449{
450 uacpi_u8 sleep_control;
452
453 if (g_uacpi_rt_ctx.s0_sleep_typ_a == UACPI_SLEEP_TYP_INVALID)
454 goto out;
455
456 sleep_control = make_hw_reduced_sleep_control(
457 g_uacpi_rt_ctx.s0_sleep_typ_a
458 );
460
461out:
462 return UACPI_STATUS_OK;
463}
464
466{
467 g_uacpi_rt_ctx.last_sleep_typ_a = UACPI_SLEEP_TYP_INVALID;
468 g_uacpi_rt_ctx.last_sleep_typ_b = UACPI_SLEEP_TYP_INVALID;
469
470 // Set the status to 2 (waking) while we execute the wake method.
471 eval_sst(2);
472
474
475 // Apparently some BIOSes expect us to clear this, so do it
478 );
479
480 // Now that we're awake set the status to 1 (running)
481 eval_sst(1);
482
483 return UACPI_STATUS_OK;
484}
485
487{
488 uacpi_u8 state = state_enum;
489
491
492 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_MAX))
494
495 if (uacpi_unlikely(g_uacpi_rt_ctx.last_sleep_typ_a > ACPI_SLP_TYP_MAX ||
496 g_uacpi_rt_ctx.last_sleep_typ_b > ACPI_SLP_TYP_MAX)) {
497 uacpi_error("invalid SLP_TYP values: 0x%02X:0x%02X\n",
498 g_uacpi_rt_ctx.last_sleep_typ_a,
499 g_uacpi_rt_ctx.last_sleep_typ_b);
501 }
502
503 return CALL_SLEEP_FN(enter_sleep_state, state);
504}
505
507 uacpi_sleep_state state_enum
508)
509{
510 uacpi_u8 state = state_enum;
511
513
514 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_MAX))
516
517 return CALL_SLEEP_FN(prepare_for_wake_from_sleep_state, state);
518}
519
521 uacpi_sleep_state state_enum
522)
523{
524 uacpi_u8 state = state_enum;
525
527
528 if (uacpi_unlikely(state > UACPI_SLEEP_STATE_MAX))
530
531 return CALL_SLEEP_FN(wake_from_sleep_state, state);
532}
533
535{
537 uacpi_handle pci_dev = UACPI_NULL, io_handle = UACPI_NULL;
538 struct acpi_fadt *fadt = &g_uacpi_rt_ctx.fadt;
539 struct acpi_gas *reset_reg = &fadt->reset_reg;
540
541 /*
542 * Allow restarting earlier than namespace load so that the kernel can
543 * use this in case of some initialization error.
544 */
546
547 if (!(fadt->flags & ACPI_RESET_REG_SUP) || !reset_reg->address)
549
550 switch (reset_reg->address_space_id) {
552 /*
553 * For SystemIO we don't do any checking, and we ignore bit width
554 * because that's what NT does.
555 */
556 ret = uacpi_kernel_io_map(reset_reg->address, 1, &io_handle);
558 return ret;
559
560 ret = uacpi_kernel_io_write8(io_handle, 0, fadt->reset_value);
561 break;
563 ret = uacpi_write_register(UACPI_REGISTER_RESET, fadt->reset_value);
564 break;
566 // Bus is assumed to be 0 here
568 .segment = 0,
569 .bus = 0,
570 .device = (reset_reg->address >> 32) & 0xFF,
571 .function = (reset_reg->address >> 16) & 0xFF,
572 };
573
576 break;
577
579 pci_dev, reset_reg->address & 0xFFFF, fadt->reset_value
580 );
581 break;
582 }
583 default:
585 "unable to perform a reset: unsupported address space '%s' (%d)\n",
586 uacpi_address_space_to_string(reset_reg->address_space_id),
587 reset_reg->address_space_id
588 );
590 }
591
592 if (ret == UACPI_STATUS_OK) {
593 /*
594 * This should've worked but we're still here.
595 * Spin for a bit then give up.
596 */
597 uacpi_u64 stalled_time = 0;
598
599 while (stalled_time < (1000 * 1000)) {
601 stalled_time += 100;
602 }
603
604 uacpi_error("reset timeout\n");
606 }
607
608 if (pci_dev != UACPI_NULL)
610 if (io_handle != UACPI_NULL)
611 uacpi_kernel_io_unmap(io_handle);
612
613 return ret;
614}
615
616#endif // !UACPI_BAREBONES_MODE
static int state
Definition: maze.c:121
#define UACPI_ARCH_FLUSH_CPU_CACHE()
Definition: arch_helpers.h:10
#define ACPI_SLP_CNT_SLP_EN_MASK
Definition: acpi.h:949
#define ACPI_PM1_CNT_SLP_TYP_MASK
Definition: acpi.h:912
#define ACPI_PM1_STS_CLEAR
Definition: acpi.h:874
#define ACPI_SLP_CNT_SLP_TYP_IDX
Definition: acpi.h:943
#define ACPI_SLP_CNT_SLP_TYP_MASK
Definition: acpi.h:948
#define ACPI_PM1_CNT_SLP_EN_MASK
Definition: acpi.h:913
#define ACPI_SLP_STS_CLEAR
Definition: acpi.h:966
#define ACPI_RESET_REG_SUP
Definition: acpi.h:714
#define ACPI_SLP_TYP_MAX
Definition: acpi.h:907
#define ACPI_PM1_CNT_SLP_TYP_IDX
Definition: acpi.h:902
#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:17
#define UACPI_UNUSED(x)
Definition: helpers.h:7
#define uacpi_trace(...)
Definition: log.h:18
#define uacpi_error(...)
Definition: log.h:21
#define uacpi_warn(...)
Definition: log.h:20
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:327
uacpi_namespace_node * uacpi_namespace_get_predefined(uacpi_predefined_namespace)
Definition: namespace.c:272
@ UACPI_PREDEFINED_NAMESPACE_SI
Definition: namespace.h:21
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:267
#define uacpi_unlikely(expr)
Definition: compiler.h:58
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:49
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:50
const uacpi_char * uacpi_address_space_to_string(uacpi_address_space space)
Definition: types.c:11
@ UACPI_OBJECT_PACKAGE_BIT
Definition: types.h:132
uacpi_u64 uacpi_phys_addr
Definition: types.h:17
const uacpi_char * uacpi_object_type_to_string(uacpi_object_type)
Definition: types.c:51
@ UACPI_INIT_LEVEL_SUBSYSTEM_INITIALIZED
Definition: types.h:66
@ UACPI_INIT_LEVEL_NAMESPACE_INITIALIZED
Definition: types.h:78
@ UACPI_OBJECT_INTEGER
Definition: types.h:106
@ UACPI_ADDRESS_SPACE_SYSTEM_MEMORY
Definition: types.h:37
@ UACPI_ADDRESS_SPACE_PCI_CONFIG
Definition: types.h:39
@ UACPI_ADDRESS_SPACE_SYSTEM_IO
Definition: types.h:38
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:755
uacpi_status uacpi_enable_all_wake_gpes(void)
Definition: event.c:1956
uacpi_status uacpi_disable_all_gpes(void)
Definition: event.c:1940
uacpi_status uacpi_enable_all_runtime_gpes(void)
Definition: event.c:1948
uacpi_status uacpi_clear_all_events(void)
Definition: event.c:2419
return ret
Definition: mutex.c:146
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_stall(uacpi_u8 usec)
Definition: uacpiosl.c:42
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:399
uacpi_status uacpi_enter_sleep_state(enum uacpi_sleep_state state_enum)
Definition: sleep.c:486
static uacpi_status eval_wak(uacpi_u8 state)
Definition: sleep.c:306
uacpi_status uacpi_prepare_for_wake_from_sleep_state(uacpi_sleep_state state_enum)
Definition: sleep.c:506
#define CALL_SLEEP_FN(name, state)
Definition: sleep.c:12
static uacpi_status eval_sst(uacpi_u8 value)
Definition: sleep.c:311
static uacpi_status get_slp_type_for_state(uacpi_u8 state, uacpi_u8 *a, uacpi_u8 *b)
Definition: sleep.c:192
uacpi_status uacpi_wake_from_sleep_state(uacpi_sleep_state state_enum)
Definition: sleep.c:520
static uacpi_status prepare_for_wake_from_sleep_state_hw_reduced(uacpi_u8 state)
Definition: sleep.c:448
uacpi_status uacpi_reboot(void)
Definition: sleep.c:534
static uacpi_u8 make_hw_reduced_sleep_control(uacpi_u8 slp_typ)
Definition: sleep.c:388
static uacpi_status prepare_for_wake_from_sleep_state_hw_full(uacpi_u8 state)
Definition: sleep.c:131
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:356
static uacpi_status wake_from_sleep_state_hw_reduced(uacpi_u8 state)
Definition: sleep.c:465
static uacpi_status wake_from_sleep_state_hw_full(uacpi_u8 state)
Definition: sleep.c:161
static uacpi_status eval_pts(uacpi_u8 state)
Definition: sleep.c:301
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:319
static uacpi_status eval_sleep_helper(uacpi_namespace_node *parent, const uacpi_char *path, uacpi_u8 value)
Definition: sleep.c:268
uacpi_sleep_state
Definition: sleep.h:32
uacpi_u32 length
Definition: acpi.h:800
uacpi_u64 x_firmware_waking_vector
Definition: acpi.h:805
uacpi_u8 version
Definition: acpi.h:806
uacpi_u32 firmware_waking_vector
Definition: acpi.h:802
Definition: match.c:390
uacpi_u8 type
Definition: types.h:249
uacpi_package * package
Definition: types.h:254
uacpi_u64 integer
Definition: types.h:253
uacpi_object ** objects
Definition: types.h:36
uacpi_size count
Definition: types.h:37
uacpi_u16 segment
Definition: types.h:82
uacpi_status uacpi_eval(uacpi_namespace_node *parent, const uacpi_char *path, const uacpi_object_array *args, uacpi_object **ret)
Definition: uacpi.c:699
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:844
Definition: pdh_main.c:96
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
void * arg
Definition: msvc.h:10