]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/acpi.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / osfmk / i386 / acpi.c
CommitLineData
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
37extern void acpi_sleep_cpu(acpi_sleep_callback, void * refcon);
38extern char acpi_wake_start[];
39extern char acpi_wake_end[];
40
41extern int serial_init(void);
42extern unsigned int disableSerialOuput;
43
44extern void set_kbd_leds(int leds);
45
c0fea474
A
46extern void fpinit(void);
47
91447636
A
48vm_offset_t
49acpi_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 63typedef struct acpi_hibernate_callback_data {
91447636
A
64 acpi_sleep_callback func;
65 void *refcon;
3a60a9f5 66} acpi_hibernate_callback_data;
91447636
A
67
68static void
3a60a9f5 69acpi_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
100void
101acpi_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}