2 #include "config_gdt.h"
5 #include "tramp-realmode.h"
13 #define SET_VIDEO_MODE 0
14 #define WAK_STS 0x8000
15 #define SLEEP_EN 0x2000
17 /* (c) 2013 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com> */
22 * We are thrown out of sleep directly into real mode. Therefore we must be
23 * below 1MB! We pack it into the .realmode_tramp section, which starts at
26 .section .realmode_tramp , "awx", @progbits
30 .globl _tramp_acpi_wakeup
35 movw $RM_OFFS(_acpi_rm_stack_top), %sp
37 /* Clear all CPU flags */
43 * Mask everything in the PIC for some reason the PIT timer is
44 * unmasked which causes spurious calls to IDT vecotor zero at least
45 * during video mode reset.
51 /* IDT needed for BIOS */
52 lidtw RM_OFFS(rm_idt_desc)
64 /* set graphics mode */
72 /* 32bit code follows */
73 ENABLE_PAGING cr0=_cr0 cr3=_cr3 cr4=_cr4 gdt=_gdt
85 /* restore general purpose registers */
108 /* we cleared the busy flag in C++ code before suspend, so its save to load the TR here */
110 movl $0, %eax // return 0 (success)
111 ret // return from function "acpi_save_cpu_and_suspend"
113 /* small stack needed for bios call */
119 /* Real mode IDT descriptor for bios IDT at physical address zero. */
143 _tr: .quad 0 /* task register */
146 // normal code called from C++
148 .section .text.acpi_suspend , "ax", @progbits
150 .globl acpi_save_cpu_and_suspend
151 acpi_save_cpu_and_suspend:
153 * int FIASCO_FASTCALL acpi_save_cpu_and_suspend(Unsigned32 sleep_type,
154 * Unsigned32 pm1_control_block,
155 * Unsigned32 pm1_event_block);
156 * sleep_type = sleep_type_a | sleep_type_b
157 * pm1_control_block = (pm1b_cntl_blk << 16) | pm1a_cntl_blk
158 * pm1_event_block = (pm1b_evt_blk << 16) | pm1b_evt_blk
159 * Called from do_suspend_system in platform_control-acpi_sleep.cpp
160 * Function will return 1 on error (suspend failed).
161 * It will return 0 after system wakeup (suspend succeeded).
186 /* save control registers */
202 /* save descriptor table (registers) */
209 /* 32bit: eax = sleep_type,
210 edx = (pm1b_cntl << 16) | pm1a_cntl,
211 ecx = (pm1b_sts << 16) | pm1a_sts */
212 /* 64bit: rdi = sleep_type,
213 rsi = (pm1b_cntl << 16) | pm1a_cntl,
214 rdx = (pm1b_sts << 16) | pm1a_sts */
223 /* 32/64bit: di = sleep_type,
224 esi = (pm1b_cntl << 16) | pm1a_cntl,
225 ecx = (pm1b_sts << 16) | pm1a_sts */
231 in %dx, %ax // read from dx into ax
234 out %ax, %dx // write ax to dx
250 // platform will now enter S3, which may or may not take some time
251 // until then we loop on the WAK_STS bit as implemented in
252 // pkg/acpica/lib-acpi/src/acpica/components/hardware/hwsleep.c
253 // (AcpiHwLegacySleep)
255 /* 32/64 bit ecx = (pm1b_sts << 16) | pm1a_sts */
267 /* if we reach this code, suspend failed (this should *never* happen) */
268 /* otherwise the machine started up from from _tramp_acpi_wakeup */