1 | /*␊ |
2 | * Copyright 2008 mackerintel␊ |
3 | *␊ |
4 | * state_generator.h␊ |
5 | * Chameleon␊ |
6 | *␊ |
7 | * Created by Mozodojo on 20/07/10.␊ |
8 | * Copyright 2010 mozodojo. All rights reserved.␊ |
9 | *␊ |
10 | */␊ |
11 | ␊ |
12 | #include "libsaio.h"␊ |
13 | #include "boot.h"␊ |
14 | #include "bootstruct.h"␊ |
15 | #include "acpi.h"␊ |
16 | #include "efi_tables.h"␊ |
17 | #include "fake_efi.h"␊ |
18 | #include "acpi_patcher.h"␊ |
19 | #include "platform.h"␊ |
20 | #include "cpu.h"␊ |
21 | #include "aml_generator.h"␊ |
22 | #include "state_generator.h"␊ |
23 | ␊ |
24 | #ifndef DEBUG_STATE␊ |
25 | #define DEBUG_STATE 0␊ |
26 | #endif␊ |
27 | ␊ |
28 | #if DEBUG_STATE==2␊ |
29 | #define DBG(x...) {printf(x); sleep(1);}␊ |
30 | #elif DEBUG_STATE==1␊ |
31 | #define DBG(x...) printf(x)␊ |
32 | #else␊ |
33 | #define DBG(x...) msglog(x)␊ |
34 | #endif␊ |
35 | ␊ |
36 | extern uint8_t acpi_cpu_count;␊ |
37 | extern uint32_t acpi_cpu_p_blk;␊ |
38 | extern char* acpi_cpu_name[32];␊ |
39 | ␊ |
40 | static char const pss_ssdt_header[] =␊ |
41 | {␊ |
42 | ␉0x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
43 | ␉0x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */␊ |
44 | ␉0x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */␊ |
45 | ␉0x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */␊ |
46 | ␉0x31, 0x03, 0x10, 0x20,␉␉␉␉/* 1.._␉␉*/␊ |
47 | };␊ |
48 | ␊ |
49 | static char const cst_ssdt_header[] =␊ |
50 | {␊ |
51 | ␉0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
52 | ␉0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */␊ |
53 | ␉0x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */␊ |
54 | ␉0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */␊ |
55 | ␉0x31, 0x03, 0x10, 0x20␉␉␉␉/* 1.._␉␉*/␊ |
56 | };␊ |
57 | ␊ |
58 | char resource_template_register_fixedhw[] =␊ |
59 | {␊ |
60 | ␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,␊ |
61 | ␉0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,␊ |
62 | ␉0x00, 0x00, 0x01, 0x79, 0x00␊ |
63 | };␊ |
64 | ␊ |
65 | char resource_template_register_systemio[] =␊ |
66 | {␊ |
67 | ␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x01,␊ |
68 | ␉0x08, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, 0x00,␊ |
69 | ␉0x00, 0x00, 0x00, 0x79, 0x00,␊ |
70 | };␊ |
71 | ␊ |
72 | struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt *dsdt)␊ |
73 | {␊ |
74 | ␊ |
75 | ␉if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) // 0x756E6547␊ |
76 | ␉{␊ |
77 | ␉␉DBG("Not an Intel platform: P-States will not be generated !!!\n");␊ |
78 | ␉␉return NULL;␊ |
79 | ␉}␊ |
80 | ␊ |
81 | ␉if (!(Platform.CPU.Features & CPU_FEATURE_MSR))␊ |
82 | ␉{␊ |
83 | ␉␉DBG("Unsupported CPU: P-States will not be generated !!! No MSR support\n");␊ |
84 | ␉␉return NULL;␊ |
85 | ␉}␊ |
86 | ␊ |
87 | ␉if (acpi_cpu_count == 0)␊ |
88 | ␉{␊ |
89 | ␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
90 | ␉}␊ |
91 | ␊ |
92 | ␉if (acpi_cpu_count > 0)␊ |
93 | ␉{␊ |
94 | ␉␉struct p_state initial, maximum, minimum, p_states[32];␊ |
95 | ␉␉uint8_t p_states_count = 0;␊ |
96 | ␊ |
97 | ␉␉// Retrieving P-States, ported from code by superhai (c)␊ |
98 | ␉␉switch (Platform.CPU.Family)␊ |
99 | ␉␉{␊ |
100 | ␉␉␉case 0x06:␊ |
101 | ␉␉␉{␊ |
102 | ␉␉␉␉switch (Platform.CPU.Model)␊ |
103 | ␉␉␉␉{␊ |
104 | ␉␉␉␉␉case CPUID_MODEL_DOTHAN:␉// Intel Pentium M␊ |
105 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␉// Intel Mobile Core Solo, Duo␊ |
106 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␉// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx␊ |
107 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␉// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx␊ |
108 | ␉␉␉␉␉case CPUID_MODEL_ATOM:␉// Intel Atom (45nm)␊ |
109 | ␉␉␉␉␉{␊ |
110 | ␉␉␉␉␉␉bool cpu_dynamic_fsb = false;␊ |
111 | ␊ |
112 | ␉␉␉␉␉␉if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))␊ |
113 | ␉␉␉␉␉␉{␊ |
114 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); ␊ |
115 | ␉␉␉␉␉␉␉delay(1);␊ |
116 | ␉␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);␊ |
117 | ␉␉␉␉␉␉}␊ |
118 | ␊ |
119 | ␉␉␉␉␉␉bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));␊ |
120 | ␊ |
121 | ␉␉␉␉␉␉initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
122 | ␊ |
123 | ␉␉␉␉␉␉maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);␊ |
124 | ␉␉␉␉␉␉maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;␊ |
125 | ␊ |
126 | ␉␉␉␉␉␉minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);␊ |
127 | ␉␉␉␉␉␉minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);␊ |
128 | ␊ |
129 | ␉␉␉␉␉␉if (minimum.FID == 0)␊ |
130 | ␉␉␉␉␉␉{␊ |
131 | ␉␉␉␉␉␉␉uint64_t msr;␊ |
132 | ␉␉␉␉␉␉␉uint8_t i;␊ |
133 | ␉␉␉␉␉␉␉// Probe for lowest fid␊ |
134 | ␉␉␉␉␉␉␉for (i = maximum.FID; i >= 0x6; i--)␊ |
135 | ␉␉␉␉␉␉␉{␊ |
136 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
137 | ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
138 | ␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
139 | ␉␉␉␉␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
140 | ␉␉␉␉␉␉␉␉delay(1);␊ |
141 | ␉␉␉␉␉␉␉}␊ |
142 | ␊ |
143 | ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
144 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
145 | ␉␉␉␉␉␉␉intel_waitforsts();␊ |
146 | ␉␉␉␉␉␉}␊ |
147 | ␊ |
148 | ␉␉␉␉␉␉if (minimum.VID == maximum.VID) ␊ |
149 | ␉␉␉␉␉␉{␊ |
150 | ␉␉␉␉␉␉␉uint64_t msr;␊ |
151 | ␉␉␉␉␉␉␉uint8_t i;␊ |
152 | ␉␉␉␉␉␉␉// Probe for lowest vid␊ |
153 | ␉␉␉␉␉␉␉for (i = maximum.VID; i > 0xA; i--) ␊ |
154 | ␉␉␉␉␉␉␉{␊ |
155 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
156 | ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
157 | ␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
158 | ␉␉␉␉␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
159 | ␉␉␉␉␉␉␉␉delay(1);␊ |
160 | ␉␉␉␉␉␉␉}␊ |
161 | ␊ |
162 | ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
163 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
164 | ␉␉␉␉␉␉␉intel_waitforsts();␊ |
165 | ␉␉␉␉␉␉}␊ |
166 | ␊ |
167 | ␉␉␉␉␉␉minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;␊ |
168 | ␊ |
169 | ␉␉␉␉␉␉// Sanity check␊ |
170 | ␉␉␉␉␉␉if (maximum.CID < minimum.CID)␊ |
171 | ␉␉␉␉␉␉{␊ |
172 | ␉␉␉␉␉␉␉DBG("P-States: Insane FID values!");␊ |
173 | ␉␉␉␉␉␉␉p_states_count = 0;␊ |
174 | ␉␉␉␉␉␉}␊ |
175 | ␉␉␉␉␉␉else␊ |
176 | ␉␉␉␉␉␉{␊ |
177 | ␉␉␉␉␉␉␉uint8_t vidstep;␊ |
178 | ␉␉␉␉␉␉␉uint8_t u, invalid = 0;␊ |
179 | ␉␉␉␉␉␉␉// Finalize P-States␊ |
180 | ␉␉␉␉␉␉␉// Find how many P-States machine supports␊ |
181 | ␉␉␉␉␉␉␉p_states_count = (uint8_t)(maximum.CID - minimum.CID + 1);␊ |
182 | ␊ |
183 | ␉␉␉␉␉␉␉if (p_states_count > 32)␊ |
184 | ␉␉␉␉␉␉␉{␊ |
185 | ␉␉␉␉␉␉␉␉p_states_count = 32;␊ |
186 | ␉␉␉␉␉␉␉}␊ |
187 | ␊ |
188 | ␉␉␉␉␉␉␉vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);␊ |
189 | ␊ |
190 | ␉␉␉␉␉␉␉for (u = 0; u < p_states_count; u++)␊ |
191 | ␉␉␉␉␉␉␉{␊ |
192 | ␉␉␉␉␉␉␉␉uint8_t i = u - invalid;␊ |
193 | ␊ |
194 | ␉␉␉␉␉␉␉␉p_states[i].CID = maximum.CID - u;␊ |
195 | ␉␉␉␉␉␉␉␉p_states[i].FID = (uint8_t)(p_states[i].CID >> 1);␊ |
196 | ␊ |
197 | ␉␉␉␉␉␉␉␉if (p_states[i].FID < 0x6)␊ |
198 | ␉␉␉␉␉␉␉␉{␊ |
199 | ␉␉␉␉␉␉␉␉␉if (cpu_dynamic_fsb)␊ |
200 | ␉␉␉␉␉␉␉␉␉{␊ |
201 | ␉␉␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].FID << 1) | 0x80;␊ |
202 | ␉␉␉␉␉␉␉␉␉}␊ |
203 | ␉␉␉␉␉␉␉␉}␊ |
204 | ␉␉␉␉␉␉␉␉else if (cpu_noninteger_bus_ratio)␊ |
205 | ␉␉␉␉␉␉␉␉{␊ |
206 | ␉␉␉␉␉␉␉␉␉p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));␊ |
207 | ␉␉␉␉␉␉␉␉}␊ |
208 | ␊ |
209 | ␉␉␉␉␉␉␉␉if (i && p_states[i].FID == p_states[i-1].FID)␊ |
210 | ␉␉␉␉␉␉␉␉{␊ |
211 | ␉␉␉␉␉␉␉␉␉invalid++;␊ |
212 | ␉␉␉␉␉␉␉␉}␊ |
213 | ␉␉␉␉␉␉␉␉p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;␊ |
214 | ␉␉␉␉␉␉␉␉uint32_t multiplier = p_states[i].FID & 0x1f;␉␉// = 0x08␊ |
215 | ␉␉␉␉␉␉␉␉bool half = p_states[i].FID & 0x40;␉␉␉␉␉// = 0x01␊ |
216 | ␉␉␉␉␉␉␉␉bool dfsb = p_states[i].FID & 0x80;␉␉␉␉␉// = 0x00␊ |
217 | ␉␉␉␉␉␉␉␉uint32_t fsb = (uint32_t)(Platform.CPU.FSBFrequency / 1000000); // = 400␊ |
218 | ␉␉␉␉␉␉␉␉uint32_t halffsb = (fsb + 1) >> 1;␉␉␉␉␉// = 200␊ |
219 | ␉␉␉␉␉␉␉␉uint32_t frequency = (multiplier * fsb);␉␉␉// = 3200␊ |
220 | ␊ |
221 | ␉␉␉␉␉␉␉␉p_states[i].Frequency = (uint32_t)(frequency + (half * halffsb)) >> dfsb;␉// = 3200 + 200 = 3400␊ |
222 | ␉␉␉␉␉␉␉}␊ |
223 | ␊ |
224 | ␉␉␉␉␉␉␉p_states_count -= invalid;␊ |
225 | ␉␉␉␉␉␉}␊ |
226 | ␊ |
227 | ␉␉␉␉␉␉break;␊ |
228 | ␉␉␉␉␉}␊ |
229 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␉␉// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)␊ |
230 | ␉␉␉␉␉case CPUID_MODEL_DALES:␉␉␉//␊ |
231 | ␉␉␉␉␉case CPUID_MODEL_DALES_32NM:␉␉// Intel Core i3, i5 LGA1156 (32nm)␊ |
232 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␉␉// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)␊ |
233 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␉␉// Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65xx␊ |
234 | ␉␉␉␉␉case CPUID_MODEL_WESTMERE:␉␉// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core␊ |
235 | ␉␉␉␉␉case CPUID_MODEL_WESTMERE_EX:␉␉// Intel Xeon E7␊ |
236 | ␉␉␉␉␉case CPUID_MODEL_SANDYBRIDGE:␉␉// Intel Core i3, i5, i7 LGA1155 (32nm)␊ |
237 | ␉␉␉␉␉case CPUID_MODEL_JAKETOWN:␉␉// Intel Core i7, Xeon E5 LGA2011 (32nm)␊ |
238 | ␉␉␉␉␉case CPUID_MODEL_IVYBRIDGE:␉␉// Intel Core i3, i5, i7 LGA1155 (22nm)␊ |
239 | ␉␉␉␉␉case CPUID_MODEL_HASWELL:␉␉//␊ |
240 | ␉␉␉␉␉case CPUID_MODEL_IVYBRIDGE_XEON:␉//␊ |
241 | ␉␉␉␉␉//case CPUID_MODEL_HASWELL_H:␉␉//␊ |
242 | ␉␉␉␉␉case CPUID_MODEL_HASWELL_SVR:␉␉//␊ |
243 | ␉␉␉␉␉case CPUID_MODEL_HASWELL_ULT:␉␉//␊ |
244 | ␉␉␉␉␉case CPUID_MODEL_CRYSTALWELL:␉␉//␊ |
245 | ␊ |
246 | ␉␉␉␉␉{␊ |
247 | ␉␉␉␉␉if ( (Platform.CPU.Model == CPUID_MODEL_SANDYBRIDGE) ||␊ |
248 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_JAKETOWN) ||␊ |
249 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_IVYBRIDGE) ||␊ |
250 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL) ||␊ |
251 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_IVYBRIDGE_XEON) ||␊ |
252 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL_SVR) ||␊ |
253 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_HASWELL_ULT) ||␊ |
254 | ␉␉␉␉␉␉(Platform.CPU.Model == CPUID_MODEL_CRYSTALWELL) )␊ |
255 | ␉␉␉␉␉{␊ |
256 | ␉␉␉␉␉␉maximum.Control = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0xff;␊ |
257 | ␉␉␉␉␉}␊ |
258 | ␉␉␉␉␉else␊ |
259 | ␉␉␉␉␉{␊ |
260 | ␉␉␉␉␉␉maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff;␊ |
261 | ␉␉␉␉␉}␊ |
262 | ␊ |
263 | ␉␉␉␉␉minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;␊ |
264 | ␊ |
265 | ␉␉␉␉␉DBG("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);␊ |
266 | ␊ |
267 | ␉␉␉␉␉// Sanity check␊ |
268 | ␉␉␉␉␉if (maximum.Control < minimum.Control)␊ |
269 | ␉␉␉␉␉{␊ |
270 | ␉␉␉␉␉␉DBG("Insane control values!");␊ |
271 | ␉␉␉␉␉␉p_states_count = 0;␊ |
272 | ␉␉␉␉␉}␊ |
273 | ␉␉␉␉␉else␊ |
274 | ␉␉␉␉␉{␊ |
275 | ␉␉␉␉␉␉uint8_t i;␊ |
276 | ␉␉␉␉␉␉p_states_count = 0;␊ |
277 | ␊ |
278 | ␉␉␉␉␉␉for (i = maximum.Control; i >= minimum.Control; i--)␊ |
279 | ␉␉␉␉␉␉{␊ |
280 | ␉␉␉␉␉␉␉p_states[p_states_count].Control = i;␊ |
281 | ␉␉␉␉␉␉␉p_states[p_states_count].CID = p_states[p_states_count].Control << 1;␊ |
282 | ␉␉␉␉␉␉␉p_states[p_states_count].Frequency = (Platform.CPU.FSBFrequency / 1000000) * i;␊ |
283 | ␉␉␉␉␉␉␉p_states_count++;␊ |
284 | ␉␉␉␉␉␉}␊ |
285 | ␉␉␉␉␉}␊ |
286 | ␊ |
287 | ␉␉␉␉␉break;␊ |
288 | ␉␉␉␉}␊ |
289 | ␉␉␉␉default:␊ |
290 | ␉␉␉␉␉DBG("Unsupported CPU (0x%X): P-States not generated !!!\n", Platform.CPU.Family);␊ |
291 | ␉␉␉␉␉break;␊ |
292 | ␉␉␉}␊ |
293 | ␉␉}␊ |
294 | ␉}␊ |
295 | ␊ |
296 | ␉// Generating SSDT␊ |
297 | ␉if (p_states_count > 0)␊ |
298 | ␉{␊ |
299 | ␊ |
300 | ␉␉int i;␊ |
301 | ␊ |
302 | ␉␉AML_CHUNK* root = aml_create_node(NULL);␊ |
303 | ␉␉aml_add_buffer(root, pss_ssdt_header, sizeof(pss_ssdt_header)); // SSDT header␊ |
304 | ␊ |
305 | ␉␉AML_CHUNK* scop = aml_add_scope(root, "\\_PR_");␊ |
306 | ␉␉AML_CHUNK* name = aml_add_name(scop, "PSS_");␊ |
307 | ␉␉AML_CHUNK* pack = aml_add_package(name);␊ |
308 | ␊ |
309 | ␉␉for (i = 0; i < p_states_count; i++)␊ |
310 | ␉␉{␊ |
311 | ␉␉␉AML_CHUNK* pstt = aml_add_package(pack);␊ |
312 | ␊ |
313 | ␉␉␉aml_add_dword(pstt, p_states[i].Frequency);␊ |
314 | ␉␉␉aml_add_dword(pstt, 0x00000000); // Power␊ |
315 | ␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
316 | ␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
317 | ␉␉␉aml_add_dword(pstt, p_states[i].Control);␊ |
318 | ␉␉␉aml_add_dword(pstt, i+1); // Status␊ |
319 | ␉␉}␊ |
320 | ␊ |
321 | ␉␉␉// Add aliaces␊ |
322 | ␉␉␉for (i = 0; i < acpi_cpu_count; i++)␊ |
323 | ␉␉␉{␊ |
324 | ␉␉␉␉char name[9];␊ |
325 | ␉␉␉␉sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);␊ |
326 | ␊ |
327 | ␉␉␉␉scop = aml_add_scope(root, name);␊ |
328 | ␉␉␉␉aml_add_alias(scop, "PSS_", "_PSS");␊ |
329 | ␉␉␉}␊ |
330 | ␊ |
331 | ␉␉␉aml_calculate_size(root);␊ |
332 | ␊ |
333 | ␉␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
334 | ␊ |
335 | ␉␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
336 | ␊ |
337 | ␉␉␉ssdt->Length = root->Size;␊ |
338 | ␉␉␉ssdt->Checksum = 0;␊ |
339 | ␉␉␉ssdt->Checksum = (uint8_t)(256 - checksum8(ssdt, ssdt->Length));␊ |
340 | ␊ |
341 | ␉␉␉aml_destroy_node(root);␊ |
342 | ␊ |
343 | ␉␉␉//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);␊ |
344 | ␊ |
345 | ␉␉␉DBG("SSDT with CPU P-States generated successfully\n");␊ |
346 | ␊ |
347 | ␉␉␉return ssdt;␊ |
348 | ␉␉}␊ |
349 | ␉}␊ |
350 | ␉else␊ |
351 | ␉{␊ |
352 | ␉␉DBG("ACPI CPUs not found: P-States not generated !!!\n");␊ |
353 | ␉}␊ |
354 | ␊ |
355 | ␉return NULL;␊ |
356 | }␊ |
357 | ␊ |
358 | struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt *fadt)␊ |
359 | {␊ |
360 | ␊ |
361 | ␉if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) // 0x756E6547␊ |
362 | ␉{␊ |
363 | ␉␉DBG("Not an Intel platform: C-States will not be generated !!!\n");␊ |
364 | ␉␉return NULL;␊ |
365 | ␉}␊ |
366 | ␊ |
367 | ␉if (fadt == NULL)␊ |
368 | ␉{␊ |
369 | ␉␉DBG("FACP not exists: C-States will not be generated !!!\n");␊ |
370 | ␉␉return NULL;␊ |
371 | ␉}␊ |
372 | ␊ |
373 | ␉struct acpi_2_dsdt *dsdt = (void *)fadt->DSDT;␊ |
374 | ␊ |
375 | ␉if (dsdt == NULL)␊ |
376 | ␉{␊ |
377 | ␉␉DBG("DSDT not found: C-States will not be generated !!!\n");␊ |
378 | ␉␉return NULL;␊ |
379 | ␉}␊ |
380 | ␊ |
381 | ␉if (acpi_cpu_count == 0)␊ |
382 | ␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
383 | ␊ |
384 | ␉if (acpi_cpu_count > 0)␊ |
385 | ␉{␊ |
386 | ␉␉bool c2_enabled = false;␊ |
387 | ␉␉bool c3_enabled = false;␊ |
388 | ␉␉bool c4_enabled = false;␊ |
389 | ␉␉bool c6_enabled = false;␊ |
390 | ␉␉bool c7_enabled = false;␊ |
391 | ␉␉bool cst_using_systemio = false;␊ |
392 | ␊ |
393 | ␉␉getBoolForKey(kEnableC2State, &c2_enabled, &bootInfo->chameleonConfig);␊ |
394 | ␉␉getBoolForKey(kEnableC3State, &c3_enabled, &bootInfo->chameleonConfig);␊ |
395 | ␉␉getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->chameleonConfig);␊ |
396 | ␉␉getBoolForKey(kEnableC6State, &c6_enabled, &bootInfo->chameleonConfig);␊ |
397 | ␉␉getBoolForKey(kEnableC7State, &c7_enabled, &bootInfo->chameleonConfig);␊ |
398 | ␉␉getBoolForKey(kCSTUsingSystemIO, &cst_using_systemio, &bootInfo->chameleonConfig);␊ |
399 | ␊ |
400 | ␉␉c2_enabled = c2_enabled | (fadt->C2_Latency < 100);␊ |
401 | ␉␉c3_enabled = c3_enabled | (fadt->C3_Latency < 1000);␊ |
402 | ␊ |
403 | ␉␉unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + ((c3_enabled || c4_enabled)? 1 : 0) + (c6_enabled ? 1 : 0) + (c7_enabled ? 1 : 0);␊ |
404 | ␊ |
405 | ␉␉AML_CHUNK* root = aml_create_node(NULL);␊ |
406 | ␉␉aml_add_buffer(root, cst_ssdt_header, sizeof(cst_ssdt_header)); // SSDT header␊ |
407 | ␉␉AML_CHUNK* scop = aml_add_scope(root, "\\_PR_");␊ |
408 | ␉␉AML_CHUNK* name = aml_add_name(scop, "CST_");␊ |
409 | ␉␉AML_CHUNK* pack = aml_add_package(name);␊ |
410 | ␉␉aml_add_byte(pack, cstates_count);␊ |
411 | ␊ |
412 | ␉␉AML_CHUNK* tmpl = aml_add_package(pack);␊ |
413 | ␉␉if (cst_using_systemio)␊ |
414 | ␉␉{␊ |
415 | ␉␉␉// C1␊ |
416 | ␉␉␉resource_template_register_fixedhw[8] = 0x00;␊ |
417 | ␉␉␉resource_template_register_fixedhw[9] = 0x00;␊ |
418 | ␉␉␉resource_template_register_fixedhw[18] = 0x00;␊ |
419 | ␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
420 | ␉␉␉aml_add_byte(tmpl, 0x01);␉␉// C1␊ |
421 | ␉␉␉aml_add_word(tmpl, 0x0001);␉␉// Latency␊ |
422 | ␉␉␉aml_add_dword(tmpl, 0x000003e8);␉// Power␊ |
423 | ␊ |
424 | ␉␉␉uint8_t p_blk_lo, p_blk_hi;␊ |
425 | ␊ |
426 | ␉␉␉if (c2_enabled) // C2␊ |
427 | ␉␉␉{␊ |
428 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 4;␊ |
429 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 4) >> 8;␊ |
430 | ␊ |
431 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
432 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C2␊ |
433 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C2␊ |
434 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
435 | ␉␉␉␉aml_add_byte(tmpl, 0x02);␉␉// C2␊ |
436 | ␉␉␉␉aml_add_word(tmpl, 0x0040);␉␉// Latency␊ |
437 | ␉␉␉␉aml_add_dword(tmpl, 0x000001f4);␉// Power␊ |
438 | ␉␉␉}␊ |
439 | ␊ |
440 | ␉␉␉if (c4_enabled) // C4␊ |
441 | ␉␉␉{␊ |
442 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
443 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
444 | ␊ |
445 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
446 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C4␊ |
447 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C4␊ |
448 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
449 | ␉␉␉␉aml_add_byte(tmpl, 0x04);␉␉// C4␊ |
450 | ␉␉␉␉aml_add_word(tmpl, 0x0080);␉␉// Latency␊ |
451 | ␉␉␉␉aml_add_dword(tmpl, 0x000000C8);␉// Power␊ |
452 | ␉␉␉}␊ |
453 | ␉␉␉else if (c3_enabled) // C3␊ |
454 | ␉␉␉{␊ |
455 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
456 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
457 | ␊ |
458 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
459 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C3␊ |
460 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C3␊ |
461 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
462 | ␉␉␉␉aml_add_byte(tmpl, 0x03);␉␉// C3␊ |
463 | ␉␉␉␉aml_add_word(tmpl, 0x0043);␉␉// Latency␊ |
464 | ␉␉␉␉aml_add_dword(tmpl, 0x000001F4);␉// Power␊ |
465 | ␉␉␉}␊ |
466 | ␉␉␉if (c6_enabled) // C6␊ |
467 | ␉␉␉{␊ |
468 | ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
469 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
470 | ␊ |
471 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
472 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C6␊ |
473 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C6␊ |
474 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));␊ |
475 | ␉␉␉␉aml_add_byte(tmpl, 0x06);␉␉␉// C6␊ |
476 | ␉␉␉␉aml_add_word(tmpl, 0x0046);␉␉␉// Latency␊ |
477 | ␉␉␉␉aml_add_dword(tmpl, 0x0000015E);␉␉// Power␊ |
478 | ␉␉␉}␊ |
479 | ␉␉␉if (c7_enabled) //C7␊ |
480 | ␉␉␉{␊ |
481 | ␉␉␉␉p_blk_lo = (acpi_cpu_p_blk + 6) & 0xff;␊ |
482 | ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
483 | ␊ |
484 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
485 | ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C4 or C7␊ |
486 | ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi;␊ |
487 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
488 | ␉␉␉␉aml_add_byte(tmpl, 0x07);␉␉␉// C7␊ |
489 | ␉␉␉␉aml_add_word(tmpl, 0xF5);␉␉␉// Latency as in iMac14,1␊ |
490 | ␉␉␉␉aml_add_dword(tmpl, 0xC8);␉␉␉// Power␊ |
491 | ␉␉␉}␊ |
492 | ␉␉}␊ |
493 | ␉␉else␊ |
494 | ␉␉{␊ |
495 | ␉␉␉// C1␊ |
496 | ␉␉␉resource_template_register_fixedhw[8] = 0x01;␊ |
497 | ␉␉␉resource_template_register_fixedhw[9] = 0x02;␊ |
498 | ␉␉␉resource_template_register_fixedhw[18] = 0x01;␊ |
499 | ␊ |
500 | ␉␉␉resource_template_register_fixedhw[11] = 0x00; // C1␊ |
501 | ␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
502 | ␉␉␉aml_add_byte(tmpl, 0x01);␉␉// C1␊ |
503 | ␉␉␉aml_add_word(tmpl, 0x0001);␉␉// Latency␊ |
504 | ␉␉␉aml_add_dword(tmpl, 0x000003e8);␉// Power␊ |
505 | ␊ |
506 | ␉␉␉resource_template_register_fixedhw[18] = 0x03;␊ |
507 | ␊ |
508 | ␉␉␉if (c2_enabled) // C2␊ |
509 | ␉␉␉{␊ |
510 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
511 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x10; // C2␊ |
512 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
513 | ␉␉␉␉aml_add_byte(tmpl, 0x02);␉␉// C2␊ |
514 | ␉␉␉␉aml_add_word(tmpl, 0x0040);␉␉// Latency␊ |
515 | ␉␉␉␉aml_add_dword(tmpl, 0x000001f4);␉// Power␊ |
516 | ␉␉␉}␊ |
517 | ␊ |
518 | ␉␉␉if (c4_enabled) // C4␊ |
519 | ␉␉␉{␊ |
520 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
521 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x30; // C4␊ |
522 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
523 | ␉␉␉␉aml_add_byte(tmpl, 0x04);␉␉// C4␊ |
524 | ␉␉␉␉aml_add_word(tmpl, 0x0080);␉␉// Latency␊ |
525 | ␉␉␉␉aml_add_dword(tmpl, 0x000000C8);␉// Power␊ |
526 | ␉␉␉}␊ |
527 | ␉␉␉else if (c3_enabled)␊ |
528 | ␉␉␉{␊ |
529 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
530 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x20; // C3␊ |
531 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
532 | ␉␉␉␉aml_add_byte(tmpl, 0x03);␉␉// C3␊ |
533 | ␉␉␉␉aml_add_word(tmpl, 0x0043);␉␉// Latency␊ |
534 | ␉␉␉␉aml_add_dword(tmpl, 0x000001F4);␉// Power␊ |
535 | ␉␉␉}␊ |
536 | ␉␉␉if (c6_enabled) // C6␊ |
537 | ␉␉␉{␊ |
538 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
539 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x20; // C6␊ |
540 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
541 | ␉␉␉␉aml_add_byte(tmpl, 0x06);␉␉␉// C6␊ |
542 | ␉␉␉␉aml_add_word(tmpl, 0x0046);␉␉␉// Latency as in MacPro6,1␊ |
543 | ␉␉␉␉aml_add_dword(tmpl, 0x0000015E);␉// Power␊ |
544 | ␉␉␉}␊ |
545 | ␉␉␉if (c7_enabled) // C7␊ |
546 | ␉␉␉{␊ |
547 | ␉␉␉␉tmpl = aml_add_package(pack);␊ |
548 | ␉␉␉␉resource_template_register_fixedhw[11] = 0x30; // C4 or C7␊ |
549 | ␉␉␉␉aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));␊ |
550 | ␉␉␉␉aml_add_byte(tmpl, 0x07);␉␉␉// C7␊ |
551 | ␉␉␉␉aml_add_word(tmpl, 0xF5);␉␉␉// Latency as in iMac14,1␊ |
552 | ␉␉␉␉aml_add_dword(tmpl, 0xC8);␉// Power␊ |
553 | ␉␉␉}␊ |
554 | ␉␉}␊ |
555 | ␊ |
556 | ␉␉// Aliaces␊ |
557 | ␉␉int i;␊ |
558 | ␉␉for (i = 0; i < acpi_cpu_count; i++)␊ |
559 | ␉␉{␊ |
560 | ␉␉␉char name[9];␊ |
561 | ␉␉␉sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);␊ |
562 | ␊ |
563 | ␉␉␉scop = aml_add_scope(root, name);␊ |
564 | ␉␉␉aml_add_alias(scop, "CST_", "_CST");␊ |
565 | ␉␉}␊ |
566 | ␊ |
567 | ␉␉aml_calculate_size(root);␊ |
568 | ␊ |
569 | ␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
570 | ␊ |
571 | ␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
572 | ␊ |
573 | ␉␉ssdt->Length = root->Size;␊ |
574 | ␉␉ssdt->Checksum = 0;␊ |
575 | ␉␉ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);␊ |
576 | ␊ |
577 | ␉␉aml_destroy_node(root);␊ |
578 | ␊ |
579 | ␉␉// dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);␊ |
580 | ␊ |
581 | ␉␉DBG("SSDT with CPU C-States generated successfully\n");␊ |
582 | ␊ |
583 | ␉␉return ssdt;␊ |
584 | ␉}␊ |
585 | ␉else␊ |
586 | ␉{␊ |
587 | ␉␉DBG("ACPI CPUs not found: C-States not generated !!!\n");␊ |
588 | ␉}␊ |
589 | ␊ |
590 | ␉return NULL;␊ |
591 | }␊ |
592 | |