]>
Commit | Line | Data |
---|---|---|
91447636 A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
37839358 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
91447636 | 11 | * |
37839358 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
91447636 A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
37839358 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
91447636 A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | ||
23 | #include <i386/misc_protos.h> | |
24 | #include <i386/proc_reg.h> | |
25 | #include <i386/pmap.h> | |
26 | #include <i386/mtrr.h> | |
27 | #include <i386/acpi.h> | |
c0fea474 | 28 | #include <i386/fpu.h> |
91447636 | 29 | #include <i386/mp.h> |
c0fea474 | 30 | #include <i386/mp_desc.h> |
91447636 A |
31 | |
32 | #include <kern/cpu_data.h> | |
3a60a9f5 A |
33 | |
34 | #include <IOKit/IOHibernatePrivate.h> | |
91447636 A |
35 | #include <IOKit/IOPlatformExpert.h> |
36 | ||
37 | extern void acpi_sleep_cpu(acpi_sleep_callback, void * refcon); | |
38 | extern char acpi_wake_start[]; | |
39 | extern char acpi_wake_end[]; | |
40 | ||
41 | extern int serial_init(void); | |
42 | extern unsigned int disableSerialOuput; | |
43 | ||
44 | extern void set_kbd_leds(int leds); | |
45 | ||
c0fea474 A |
46 | extern void fpinit(void); |
47 | ||
91447636 A |
48 | vm_offset_t |
49 | acpi_install_wake_handler(void) | |
50 | { | |
51 | /* copy wake code to ACPI_WAKE_ADDR in low memory */ | |
c0fea474 | 52 | bcopy_phys(kvtophys((vm_offset_t)acpi_wake_start), |
91447636 A |
53 | (addr64_t) ACPI_WAKE_ADDR, |
54 | acpi_wake_end - acpi_wake_start); | |
55 | ||
56 | /* flush cache */ | |
57 | wbinvd(); | |
58 | ||
59 | /* return physical address of the wakeup code */ | |
60 | return ACPI_WAKE_ADDR; | |
61 | } | |
62 | ||
3a60a9f5 | 63 | typedef struct acpi_hibernate_callback_data { |
91447636 A |
64 | acpi_sleep_callback func; |
65 | void *refcon; | |
3a60a9f5 | 66 | } acpi_hibernate_callback_data; |
91447636 A |
67 | |
68 | static void | |
3a60a9f5 | 69 | acpi_hibernate(void *refcon) |
91447636 | 70 | { |
c0fea474 | 71 | boolean_t dohalt; |
3a60a9f5 A |
72 | |
73 | acpi_hibernate_callback_data *data = (acpi_hibernate_callback_data *)refcon; | |
91447636 | 74 | |
3a60a9f5 | 75 | if (current_cpu_datap()->cpu_hibernate) { |
c0fea474 A |
76 | |
77 | dohalt = hibernate_write_image(); | |
78 | if (dohalt) | |
79 | { | |
80 | // off | |
81 | HIBLOG("power off\n"); | |
82 | if (PE_halt_restart) | |
83 | (*PE_halt_restart)(kPEHaltCPU); | |
84 | } | |
85 | else | |
86 | { | |
87 | // sleep | |
88 | HIBLOG("sleep\n"); | |
89 | ||
90 | // should we come back via regular wake, set the state in memory. | |
91 | cpu_datap(0)->cpu_hibernate = 0; | |
92 | } | |
3a60a9f5 | 93 | } |
91447636 A |
94 | |
95 | (data->func)(data->refcon); | |
96 | ||
97 | /* should never get here! */ | |
98 | } | |
99 | ||
100 | void | |
101 | acpi_sleep_kernel(acpi_sleep_callback func, void *refcon) | |
102 | { | |
3a60a9f5 A |
103 | acpi_hibernate_callback_data data; |
104 | boolean_t did_hibernate; | |
91447636 | 105 | |
c0fea474 A |
106 | kprintf("acpi_sleep_kernel hib=%d\n", current_cpu_datap()->cpu_hibernate); |
107 | ||
108 | /* shutdown local APIC before passing control to BIOS */ | |
109 | lapic_shutdown(); | |
91447636 A |
110 | |
111 | data.func = func; | |
112 | data.refcon = refcon; | |
113 | ||
c0fea474 A |
114 | /* Save HPET state */ |
115 | hpet_save(); | |
116 | ||
117 | /* | |
118 | * If we're in 64-bit mode, drop back into legacy mode during sleep. | |
119 | */ | |
120 | if (cpu_mode_is64bit()) { | |
121 | cpu_IA32e_disable(current_cpu_datap()); | |
122 | kprintf("acpi_sleep_kernel legacy mode re-entered\n"); | |
123 | } | |
124 | ||
125 | /* | |
126 | * Save master CPU state and sleep platform. | |
127 | * Will not return until platform is woken up, | |
128 | * or if sleep failed. | |
129 | */ | |
3a60a9f5 | 130 | acpi_sleep_cpu(acpi_hibernate, &data); |
91447636 | 131 | |
c0fea474 A |
132 | /* reset UART if kprintf is enabled */ |
133 | if (FALSE == disableSerialOuput) | |
134 | serial_init(); | |
135 | ||
136 | kprintf("ret from acpi_sleep_cpu hib=%d\n", current_cpu_datap()->cpu_hibernate); | |
91447636 | 137 | |
3a60a9f5 | 138 | if (current_cpu_datap()->cpu_hibernate) { |
c0fea474 A |
139 | int i; |
140 | for (i=0; i<PMAP_NWINDOWS; i++) { | |
141 | *current_cpu_datap()->cpu_pmap->mapwindow[i].prv_CMAP = 0; | |
142 | } | |
143 | current_cpu_datap()->cpu_hibernate = 0; | |
144 | did_hibernate = TRUE; | |
3a60a9f5 | 145 | |
c0fea474 A |
146 | } else { |
147 | did_hibernate = FALSE; | |
148 | } | |
3a60a9f5 | 149 | |
c0fea474 A |
150 | /* Re-enable 64-bit mode if necessary. */ |
151 | if (cpu_mode_is64bit()) { | |
152 | cpu_IA32e_enable(current_cpu_datap()); | |
153 | cpu_desc_load64(current_cpu_datap()); | |
154 | kprintf("acpi_sleep_kernel 64-bit mode re-enabled\n"); | |
155 | fast_syscall_init64(); | |
3a60a9f5 | 156 | } else { |
c0fea474 | 157 | fast_syscall_init(); |
3a60a9f5 | 158 | } |
91447636 | 159 | |
c0fea474 A |
160 | /* restore MTRR settings */ |
161 | mtrr_update_cpu(); | |
91447636 | 162 | |
c0fea474 A |
163 | /* set up PAT following boot processor power up */ |
164 | pat_init(); | |
91447636 | 165 | |
3a60a9f5 A |
166 | if (did_hibernate) { |
167 | hibernate_machine_init(); | |
168 | } | |
169 | ||
c0fea474 A |
170 | /* re-enable and re-init local apic */ |
171 | if (lapic_probe()) | |
172 | lapic_init(); | |
173 | ||
174 | /* Restore HPET state */ | |
175 | hpet_restore(); | |
176 | ||
177 | /* let the realtime clock reset */ | |
178 | rtc_sleep_wakeup(); | |
91447636 | 179 | |
c0fea474 A |
180 | fpinit(); |
181 | clear_fpu(); | |
91447636 | 182 | |
3a60a9f5 A |
183 | if (did_hibernate) { |
184 | enable_preemption(); | |
185 | } | |
91447636 | 186 | } |