Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/ACPICodec/acpi_codec.c

  • Property svn:executable set to *
1/*
2 * Copyright 2008 mackerintel
3 */
4
5/*
6 Copyright (c) 2010, Intel Corporation
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11
12 * Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 * Neither the name of Intel Corporation nor the names of its contributors
18 may be used to endorse or promote products derived from this software
19 without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 2011 cparm <armelcadetpetit@gmail.com>. All rights reserved.
35 *
36 */
37
38#include "libsaio.h"
39#include "boot.h"
40#include "bootstruct.h"
41#include "acpi.h"
42#include "acpidecode.h"
43#include "acpicode.h"
44#include "efi_tables.h"
45#include "fake_efi.h"
46#include "acpi_codec.h"
47#include "platform.h"
48#include "cpu.h"
49#include "xml.h"
50#include "pci_root.h"
51#include "sl.h"
52
53U64 rsd_p;
54ACPI_TABLES acpi_tables;
55
56#ifndef DEBUG_ACPI
57#define DEBUG_ACPI 0
58#endif
59
60#if DEBUG_ACPI==2
61#define DBG(x...) {printf(x); sleep(1);}
62#elif DEBUG_ACPI==1
63#define DBG(x...) printf(x)
64#else
65#define DBG(x...)
66#endif
67
68#define OLD_SSDT 0
69#define BETA 0
70#define BUILD_ACPI_TSS 0
71#define pstate_power_support 1
72
73#if BETA
74#ifdef pstate_power_support
75#undef pstate_power_support
76#endif
77#define pstate_power_support 1
78#endif
79
80extern EFI_STATUS addConfigurationTable();
81
82extern EFI_GUID gEfiAcpiTableGuid;
83extern EFI_GUID gEfiAcpi20TableGuid;
84
85#if DEBUG_ACPI
86static void print_nameseg(U32 i);
87#endif
88
89static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex );
90static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved );
91static void sanitize_new_table_list(U32 *new_table_list );
92static void move_table_list_to_kmem(U32 *new_table_list );
93static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp );
94static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt);
95static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt);
96static void *loadACPITable(char *dirspec, char *filename );
97static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer);
98static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length);
99static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list);
100static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list);
101static ACPI_TABLE_FADT * patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT);
102
103#if OLD_SSDT
104#include "modules.h"
105struct aml_chunk
106{
107unsigned charType;
108unsigned intLength;
109char*Buffer;
110
111unsigned intSize;
112
113struct aml_chunk*Next;
114struct aml_chunk*First;
115struct aml_chunk*Last;
116};
117static U32 get_needed_symbols (void);
118static ACPI_TABLE_SSDT *generate_cst_ssdt(ACPI_TABLE_FADT* fadt);
119static ACPI_TABLE_SSDT *generate_pss_ssdt(ACPI_TABLE_DSDT* dsdt);
120struct aml_chunk* (*aml_create_node)(struct aml_chunk*) = NULL;
121struct aml_chunk* (*aml_add_buffer)(struct aml_chunk*,const char*, unsigned int) = NULL;
122struct aml_chunk* (*aml_add_byte)(struct aml_chunk*, unsigned char) = NULL;
123struct aml_chunk* (*aml_add_word)(struct aml_chunk*, unsigned int) = NULL;
124struct aml_chunk* (*aml_add_dword)(struct aml_chunk*, unsigned long) = NULL;
125struct aml_chunk* (*aml_add_qword)(struct aml_chunk*, unsigned long long) = NULL;
126struct aml_chunk* (*aml_add_scope)(struct aml_chunk*, const char*) = NULL;
127struct aml_chunk* (*aml_add_name)(struct aml_chunk*, const char*) = NULL;
128struct aml_chunk* (*aml_add_package)(struct aml_chunk*) = NULL;
129struct aml_chunk* (*aml_add_alias)(struct aml_chunk*, const char*, const char*) = NULL;
130void (*aml_destroy_node)(struct aml_chunk*) = NULL;
131unsigned int (*aml_calculate_size)(struct aml_chunk*) = NULL;
132unsigned int (*aml_write_node)(struct aml_chunk*, char*, unsigned int) = NULL;
133bool (*aml_add_to_parent)(struct aml_chunk*, struct aml_chunk*) = NULL;
134
135#else
136
137#define IA32_MISC_ENABLES 0x01A0
138#define MSR_TURBO_POWER_CURRENT_LIMIT 0x1AC
139#define MSR_PKG_CST_CONFIG_CONTROL 0x00E2
140#define MSR_RAPL_POWER_UNIT 0x606
141#define MSR_PKG_RAPL_POWER_LIMIT 0x610
142static U32 turbo_enabled = 0;
143static U32 BuildSsdt(ACPI_TABLE_MADT * madt, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates);
144static bool is_sandybridge(void);
145static bool is_jaketown(void);
146static U32 encode_pstate(U32 ratio);
147static void collect_cpu_info(CPU_DETAILS * cpu);
148#ifndef BETA
149static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu);
150#endif
151static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase);
152static U32 BuildPstateInfo(CPU_DETAILS * cpu);
153static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, bool enable_cstates, bool enable_pstates, bool enable_tstates );
154static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath);
155static void * buildPDC(void * current);
156static void * buildOSC(void * current);
157static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates);
158static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination);
159static void * buildPPC(void * current);
160static void * buildPCT(void * current);
161static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate);
162static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates);
163static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates);
164#if BUILD_ACPI_CSD
165static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates);
166#endif
167#if BUILD_ACPI_TSS
168static U32 BuildTstateInfo(CPU_DETAILS * cpu);
169static void * buildTPC(void * current);
170static void * buildPTC(void * current);
171static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates);
172static void * buildTSD(void * current, U32 domain, U32 cpusInDomain);
173#endif
174#if pstate_power_support
175static U64 mulU64byU64(U64 a, U64 b, U64 * high);
176static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP);
177#endif
178#if BUILD_ACPI_TSS || pstate_power_support
179static U64 divU64byU64(U64 n, U64 d, U64 * rem);
180static U32 compute_tdp(CPU_DETAILS * cpu);
181#endif
182static bool is_sandybridge(void);
183static bool is_jaketown(void);
184static U32 get_bclk(void);
185static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate);
186static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit);
187
188#endif // OLD_SSDT
189
190#if UNUSED
191static ACPI_TABLE_FACS* generate_facs(bool updatefacs );
192#endif
193
194#define MAX_NON_SSDT_TABLE 15
195#define MAX_SSDT_TABLE 15 // 15 additional SSDT tables
196#define MAX_ACPI_TABLE MAX_NON_SSDT_TABLE + MAX_SSDT_TABLE
197
198// Security space for SSDT & FACP generation,
199// the size can be increased
200// note: the table will not placed in the reserved space if the 'normal' space is not full
201#if OLD_SSDT
202#define RESERVED_AERA 3
203#else
204#define RESERVED_AERA 2
205#endif
206
207#define ACPI_TABLE_LIST_FULL MAX_ACPI_TABLE + RESERVED_AERA + 1
208
209#define ACPI_TABLE_LIST_FULL_NON_RESERVED MAX_ACPI_TABLE + 1
210
211#define ULONG_MAX_32 4294967295UL
212
213#define __RES(s, u)\
214inline unsigned u\
215resolve_##s(unsigned u defaultentry, char *str, int base) \
216{\
217unsigned u entry = defaultentry;\
218if (str && (strcmp(str,"Default") != 0)) {\
219entry = strtoul((const char *)str, NULL,base);\
220}\
221return entry;\
222}
223
224__RES(pss, long)
225__RES(cst, int)
226
227
228static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex )
229{
230ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
231U8 index ;
232*retIndex = 0;
233
234for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
235{
236if (*(U32 *) (table_array[index]->Signature) == Signature)
237{
238*retIndex = index;
239return table_array[index] ;
240}
241}
242return (void*)0ul;
243}
244
245static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved )
246{
247U8 index ;
248
249U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE;
250
251for (index = 0; index < maximum; index++)
252{
253if (new_table_list[index] == 0ul)
254{
255return index ;
256}
257}
258return (reserved == true)? ACPI_TABLE_LIST_FULL : ACPI_TABLE_LIST_FULL_NON_RESERVED;
259}
260
261/* cparm : This time we check it by the acpi signature */
262static void sanitize_new_table_list(U32 *new_table_list )
263{
264ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
265U8 index ;
266
267for (index = 0; index < MAX_ACPI_TABLE; index++)
268{
269U32 current_sig = *(U32 *) (table_array[index]->Signature);
270
271if ((current_sig == NAMESEG(ACPI_SIG_FACS) /* not supported */ )
272|| (current_sig == NAMESEG(ACPI_SIG_XSDT))
273|| (current_sig == NAMESEG(ACPI_SIG_RSDT)) || (*(volatile U64 *)table_array[index] == NAMESEG64(ACPI_SIG_RSDP)) )
274{
275
276void *buf = (void*)new_table_list[index];
277free(buf);
278new_table_list[index] = 0ul ;
279}
280}
281}
282
283/* cparm : move all tables to kernel memory */
284static void move_table_list_to_kmem(U32 *new_table_list )
285{
286ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
287U8 index ;
288
289for (index = 0; index < MAX_ACPI_TABLE; index++)
290{
291if (new_table_list[index] != 0ul)
292{
293
294U32 current_sig = *(U32 *) (table_array[index]->Signature);
295if ((current_sig != NAMESEG(ACPI_SIG_FACS) /* not supported */ )
296&& (current_sig != NAMESEG(ACPI_SIG_XSDT))
297&& (current_sig != NAMESEG(ACPI_SIG_RSDT)) && (*(volatile U64 *)table_array[index] != NAMESEG64(ACPI_SIG_RSDP))
298&& (GetChecksum(table_array[index], table_array[index]->Length) == 0))
299{
300
301void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length);
302if (!tableAddr) {
303printf("Unable to allocate kernel memory for aml file ");
304
305void *buf = (void*)new_table_list[index];
306free(buf);
307new_table_list[index] = 0ul ;
308continue;
309}
310bcopy(table_array[index], tableAddr, table_array[index]->Length);
311new_table_list[index] = 0ul ;
312new_table_list[index] = (U32)tableAddr ;
313
314}
315else
316{
317
318void *buf = (void*)new_table_list[index];
319free(buf);
320new_table_list[index] = 0ul ;
321}
322}
323}
324}
325
326static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp )
327{
328
329ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP));
330
331if (rsdp_conv) {
332bzero(rsdp_conv, sizeof(ACPI_TABLE_RSDP));
333memcpy(rsdp_conv, rsdp, ACPI_RSDP_REV0_SIZE);
334
335/* Add/change fields */
336rsdp_conv->Revision = 2; /* ACPI version 3 */
337rsdp_conv->Length = sizeof(ACPI_TABLE_RSDP);
338
339/* Correct checksums */
340setRsdpchecksum(rsdp_conv);
341setRsdpXchecksum(rsdp_conv);
342}
343
344 return (rsdp_conv) ? rsdp_conv : (void*)0ul ;
345}
346
347static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt)
348{
349 U32 index;
350 U32 num_tables;
351
352DBG("Attempting to generate RSDT from XSDT \n");
353
354 num_tables= get_num_tables64(xsdt);
355
356 ACPI_TABLE_RSDT * rsdt_conv=(ACPI_TABLE_RSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
357if (!rsdt_conv)
358{
359printf("Unable to allocate kernel memory for rsdt conv\n");
360return (void*)0ul;
361}
362
363
364bzero(rsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
365 memcpy(&rsdt_conv->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
366
367 rsdt_conv->Header.Signature[0] = 'R';
368 rsdt_conv->Header.Signature[1] = 'S';
369 rsdt_conv->Header.Signature[2] = 'D';
370 rsdt_conv->Header.Signature[3] = 'T';
371 rsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 4);
372
373for (index=0;index<num_tables;index++)
374 {
375U64 ptr = xsdt->TableOffsetEntry[index];
376
377{
378if (ptr > ULONG_MAX_32)
379{
380#if DEBUG_ACPI
381printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
382#endif
383continue;
384}
385#if DEBUG_ACPI
386printf("* Processing : ");
387print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
388printf("\n");
389#endif
390bool unsafe = false;
391getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
392
393if (!unsafe)
394{
395if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
396((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
397{
398#if DEBUG_ACPI
399printf("Warning : Invalide checksum, ignored !!!\n",index);
400#endif
401continue;
402}
403}
404
405}
406
407{
408if ((*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == NAMESEG(ACPI_SIG_FADT)))
409{
410ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)ptr);
411
412ACPI_TABLE_FADT *fadt_conv = (void*)0ul;
413
414if (fadt->Header.Revision > 1)
415{
416U8 buffer[0x74];
417DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision);
418fadt_conv=(ACPI_TABLE_FADT *)buffer;
419memcpy(fadt_conv, fadt, 0x74);
420fadt_conv->Header.Length = 0x74;
421fadt_conv->Header.Revision = 0x01;
422SetChecksum(&fadt_conv->Header);
423}
424else
425{
426fadt_conv = fadt;
427}
428
429ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false);
430if (fadt_mod == (void*)0ul)
431{
432printf("Error: Failed to patch FADT Table, trying wiht the original fadt pointer\n");
433fadt_mod = fadt;
434}
435
436rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod);
437#if DEBUG_ACPI
438print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
439printf(" table converted and added succesfully\n");
440#endif
441continue;
442}
443}
444
445{
446rsdt_conv->TableOffsetEntry[index] = (U32)ptr;
447#if DEBUG_ACPI
448print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
449printf(" table converted and added succesfully\n");
450#endif
451}
452
453 }
454 DBG("RSDT_CONV : Original checksum %d\n", rsdt_conv->Header.Checksum);
455 SetChecksum(&rsdt_conv->Header);
456 DBG("New checksum %d\n", rsdt_conv->Header.Checksum);
457
458 return rsdt_conv;
459}
460
461static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt)
462{
463U32 index;
464 U32 num_tables;
465
466DBG("Attempting to generate XSDT from RSDT \n");
467
468 num_tables= get_num_tables(rsdt);
469
470 ACPI_TABLE_XSDT * xsdt_conv=(ACPI_TABLE_XSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
471
472if (!xsdt_conv) {
473printf("Unable to allocate kernel memory for xsdt conv\n");
474return (void*)0ul;
475}
476
477bzero(xsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
478 memcpy(&xsdt_conv->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
479
480 xsdt_conv->Header.Signature[0] = 'X';
481 xsdt_conv->Header.Signature[1] = 'S';
482 xsdt_conv->Header.Signature[2] = 'D';
483 xsdt_conv->Header.Signature[3] = 'T';
484 xsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 8);
485
486ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
487
488 for (index=0;index<num_tables;index++)
489 {
490{
491#if DEBUG_ACPI
492printf("* Processing : ");
493print_nameseg(*(U32*) (table_array[index]->Signature));
494printf("\n");
495#endif
496bool unsafe = false;
497getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
498
499if (!unsafe)
500{
501if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
502{
503#if DEBUG_ACPI
504printf("Warning : Invalide checksum, ignored !!!\n",index);
505#endif
506continue;
507}
508}
509
510}
511
512{
513if ((*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT)))
514{
515ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]);
516ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true);
517if (fadt_mod == (void*)0ul)
518{
519printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n");
520fadt_mod = FacpPointer;
521}
522xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod));
523
524continue;
525}
526}
527
528xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index]));
529 }
530 DBG("XSDT_CONV : Original checksum %d\n", xsdt_conv->Header.Checksum);
531 SetChecksum(&xsdt_conv->Header);
532 DBG("New checksum %d\n", xsdt_conv->Header.Checksum);
533
534 return xsdt_conv;
535}
536
537static void *loadACPITable(char *dirspec, char *filename )
538{
539int fd = -1;
540char acpi_file[512];
541
542DBG("Searching for %s file ...\n", filename);
543// Check booting partition
544
545sprintf(acpi_file, "%s%s",dirspec, filename);
546
547fd=open(acpi_file);
548
549if (fd<0)
550{
551DBG("Couldn't open ACPI Table: %s\n", acpi_file);
552return (void *)0ul ;
553}
554
555void *tableAddr=(void*)malloc(file_size (fd));
556
557if (tableAddr)
558{
559if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
560{
561printf("Couldn't read table %s\n",acpi_file);
562free (tableAddr);
563close (fd);
564return (void *)0ul ;
565}
566
567close (fd);
568
569ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr;
570
571if (GetChecksum(header, header->Length) == 0)
572{
573DBG("Found valid AML file : %s", filename);
574DBG(" ( %s ) read and stored at: %x", acpi_file, tableAddr);
575DBG("\n");
576return tableAddr;
577}
578else
579{
580printf("Warning : Incorrect cheksum for the file : %s,", acpi_file);
581printf(" this file will be dropped.\n");
582free(tableAddr);
583return (void*)0ul;
584}
585}
586
587printf("Couldn't allocate memory for table %s\n", acpi_file);
588close (fd);
589
590return (void *)0ul ;
591}
592
593static U32 pmbase;
594static short cpuNamespace;
595PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT];
596unsigned int cpu_map_count;
597int cpu_map_error;
598
599#if DEBUG_ACPI
600static void print_nameseg(U32 i)
601{
602 printf("%c%c%c%c",
603 (int)(i & 0x000000ff),
604 (int)((i & 0x0000ff00) >> 8),
605 (int)((i & 0x00ff0000) >> 16),
606 (int)(i >> 24));
607}
608#endif
609
610static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer)
611{
612 PROCESSOR_NUMBER_TO_NAMESEG *map = cpu_map;
613 U32 processor_namespace = 0;
614 U32 cpu;
615 U8 *current, *end;
616 ACPI_TABLE_HEADER *header;
617 struct acpi_namespace ns;
618
619if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul))
620return 1;
621else if (cpu_map_count > 0)
622return 0;
623
624 DBG("Attempting to autodetect CPU map from ACPI DSDT; wish me luck\n");
625
626 current = (U8 *) DsdtPointer;
627 current = decodeTableHeader(current, &header);
628 end = current - sizeof(*header) + header->Length;
629 ns.depth = 0;
630 acpi_processor_count = 0;
631//DBG("* DSDT debug start\n");
632 parse_acpi_termlist(&ns, current, end);
633//DBG("* DSDT debug end\n");
634
635 if (acpi_processor_count > CPU_MAP_LIMIT)
636{
637verbose("Too many processors: found %u processors\n", acpi_processor_count);
638 return (cpu_map_error = 1);
639}
640 if (acpi_processor_count == 0)
641{
642verbose( "Found no processors in ACPI\n");
643 return (cpu_map_error = 1);
644}
645 for (cpu = 0; cpu < acpi_processor_count; cpu++)
646{
647 U32 nameseg;
648 if (acpi_processors[cpu].pmbase)
649{
650 U32 cpu_pmbase = acpi_processors[cpu].pmbase - 0x10;
651 if (pmbase && cpu_pmbase != pmbase)
652{
653verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase);
654return (cpu_map_error = 1);
655}
656 pmbase = cpu_pmbase;
657 }
658 if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1)
659{
660verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth);
661return (cpu_map_error = 1);
662}
663 if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace)
664{
665verbose("Processor namespaces inconsistent\n");
666return (cpu_map_error = 1);
667}
668 processor_namespace = acpi_processors[cpu].ns.nameseg[0];
669 map->acpi_processor_number = acpi_processors[cpu].id;
670 map->seg_count = acpi_processors[cpu].ns.depth - 1;
671 for (nameseg = 0; nameseg < map->seg_count; nameseg++)
672 map->nameseg[nameseg] = acpi_processors[cpu].ns.nameseg[nameseg + 1];
673 map++;
674 }
675 if (!pmbase)
676{
677verbose("No pmbase found in ACPI\n");
678return (cpu_map_error = 1);
679}
680 if (processor_namespace == NAMESEG("_PR_"))
681 cpuNamespace = CPU_NAMESPACE_PR;
682 else if (processor_namespace == NAMESEG("_SB_"))
683 cpuNamespace = CPU_NAMESPACE_SB;
684 else
685{
686 verbose("Found processors in invalid namespace; not _PR_ or _SB_\n");
687return (cpu_map_error = 1);
688}
689 cpu_map_count = map - cpu_map;
690
691#if DEBUG_ACPI
692verbose("Found %d processors in ACPI, pmbase : 0x%x, cpu_map_count : %d, namespace : ",acpi_processor_count, pmbase, cpu_map_count );
693print_nameseg(processor_namespace);
694verbose("\n");
695 U32 i;
696 verbose("Found processors name : \n" );
697 for ( i = 0; i<cpu_map_count; i++)
698{
699U32 nseg = *(U32*)cpu_map[i].nameseg;
700 print_nameseg(nseg);
701verbose(" ");
702 }
703 verbose("\n");
704#endif
705
706// TODO: Save the cpu map into the device tree
707 return (cpu_map_error = 0);
708}
709
710#if OLD_SSDT
711
712static U32 get_needed_symbols (void)
713{
714/* aml_generator symbols */
715aml_create_node = (void*)lookup_all_symbols("_aml_create_node");
716if (aml_create_node == (void*)0xFFFFFFFF) goto Failed;
717
718aml_add_buffer = (void*)lookup_all_symbols("_aml_add_buffer");
719if (aml_add_buffer == (void*)0xFFFFFFFF) goto Failed;
720
721aml_add_byte = (void*)lookup_all_symbols("_aml_add_byte");
722if (aml_add_byte == (void*)0xFFFFFFFF) goto Failed;
723
724aml_add_word = (void*)lookup_all_symbols("_aml_add_word");
725if (aml_add_word == (void*)0xFFFFFFFF) goto Failed;
726
727aml_add_dword = (void*)lookup_all_symbols("_aml_add_dword");
728if (aml_add_dword == (void*)0xFFFFFFFF) goto Failed;
729
730aml_add_qword = (void*)lookup_all_symbols("_aml_add_qword");
731if (aml_add_qword == (void*)0xFFFFFFFF) goto Failed;
732
733aml_add_scope = (void*)lookup_all_symbols("_aml_add_scope");
734if (aml_add_scope == (void*)0xFFFFFFFF) goto Failed;
735
736aml_add_name = (void*)lookup_all_symbols("_aml_add_name");
737if (aml_add_name == (void*)0xFFFFFFFF) goto Failed;
738
739aml_add_package = (void*)lookup_all_symbols("_aml_add_package");
740if (aml_add_package == (void*)0xFFFFFFFF) goto Failed;
741
742aml_add_alias = (void*)lookup_all_symbols("_aml_add_alias");
743if (aml_add_alias == (void*)0xFFFFFFFF) goto Failed;
744
745aml_destroy_node = (void*)lookup_all_symbols("_aml_destroy_node");
746if (aml_destroy_node == (void*)0xFFFFFFFF) goto Failed;
747
748aml_calculate_size = (void*)lookup_all_symbols("_aml_calculate_size");
749if (aml_calculate_size == (void*)0xFFFFFFFF) goto Failed;
750
751aml_write_node = (void*)lookup_all_symbols("_aml_write_node");
752if (aml_write_node == (void*)0xFFFFFFFF) goto Failed;
753
754aml_add_to_parent = (void*)lookup_all_symbols("_aml_add_to_parent");
755if (aml_add_to_parent == (void*)0xFFFFFFFF) goto Failed;
756
757DBG("struct aml_chunk* _aml_create_node: 0x%x\n",(UInt32)aml_create_node);
758DBG("struct aml_chunk* _aml_add_buffer: 0x%x\n",(UInt32)aml_add_buffer);
759DBG("struct aml_chunk* _aml_add_byte: 0x%x\n",(UInt32)aml_add_byte);
760DBG("struct aml_chunk* _aml_add_word: 0x%x\n",(UInt32)aml_add_word);
761DBG("struct aml_chunk* _aml_add_dword: 0x%x\n",(UInt32)aml_add_dword);
762DBG("struct aml_chunk* _aml_add_qword: 0x%x\n",(UInt32)aml_add_qword);
763DBG("struct aml_chunk* _aml_add_scope: 0x%x\n",(UInt32)aml_add_scope);
764DBG("struct aml_chunk* _aml_add_name: 0x%x\n",(UInt32)aml_add_name);
765DBG("struct aml_chunk* _aml_add_package: 0x%x\n",(UInt32)aml_add_package);
766DBG("struct aml_chunk* _aml_add_alias: 0x%x\n",(UInt32)aml_add_alias);
767DBG("void _aml_destroy_node: 0x%x\n",(UInt32)aml_destroy_node);
768DBG("unsigned int _aml_calculate_size: 0x%x\n",(UInt32)aml_calculate_size);
769DBG("unsigned int _aml_write_node: 0x%x\n",(UInt32)aml_write_node);
770DBG("bool _aml_add_to_parent: 0x%x\n",(UInt32)aml_add_to_parent);
771return (1);
772Failed:
773printf("Failed to find aml_generator symbols, SSDT will not be generated !!!");
774return (0);
775}
776
777static ACPI_TABLE_SSDT *generate_cst_ssdt(ACPI_TABLE_FADT* fadt)
778{
779char ssdt_header[] =
780{
7810x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
7820x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
7830x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
7840x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
7850x31, 0x03, 0x10, 0x20 /* 1.._*/
786};
787
788char cstate_resource_template[] =
789{
7900x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
7910x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
7920x00, 0x00, 0x00, 0x79, 0x00
793};
794
795if (Platform->CPU.Vendor != 0x756E6547) {
796verbose ("Not an Intel platform: C-States will not be generated !!!\n");
797return (void *)0ul;
798}
799
800if (fadt == (void *)0ul) {
801verbose ("FACP not exists: C-States will not be generated !!!\n");
802return (void *)0ul;
803}
804
805ACPI_TABLE_DSDT* dsdt = ((fadt->Header.Revision >= 3) && (fadt->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt->XDsdt):(ACPI_TABLE_DSDT*)fadt->Dsdt;
806if (dsdt == (void *)0ul) {
807verbose ("DSDT not found: C-States will not be generated !!!\n");
808return (void *)0ul;
809}
810
811if (generate_cpu_map_from_acpi(dsdt) == 0)
812{
813bool c2_enabled = fadt->C2Latency < 100;
814bool c3_enabled = fadt->C3Latency < 1000;
815bool c4_enabled = false;
816
817getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->bootConfig);
818
819unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + ((c3_enabled || c4_enabled) ? 1 : 0);
820char *Lat = NULL, *Pw = NULL, *tmpstr =NULL;
821int base = 16;
822TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));
823
824if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base")))) {
825
826int mybase = strtol(tmpstr, NULL, 10);
827
828if (mybase == 8 || mybase == 10 || mybase == 16 )
829base = mybase;
830}
831
832struct aml_chunk* root = aml_create_node(NULL);
833 aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
834 struct aml_chunk* scop;
835if (cpuNamespace == CPU_NAMESPACE_PR)
836scop = aml_add_scope(root, "\\_PR_");
837else if (cpuNamespace == CPU_NAMESPACE_SB)
838scop = aml_add_scope(root, "\\_SB_");
839else
840{
841aml_destroy_node(root);
842goto out;
843}
844 struct aml_chunk* name = aml_add_name(scop, "CST_");
845 struct aml_chunk* pack = aml_add_package(name);
846 aml_add_byte(pack, cstates_count);
847
848 struct aml_chunk* tmpl = aml_add_package(pack);
849 TagPtr match_Status = XMLGetProperty(personality, (const char*)"C1");
850 if (match_Status) {
851 Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
852 Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
853 }
854 cstate_resource_template[11] = 0x00; // C1
855 aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
856 aml_add_byte(tmpl, 0x01); // C1
857 aml_add_byte(tmpl, (unsigned char)resolve_cst(0x01, Lat, base)); // Latency
858 aml_add_word(tmpl, resolve_cst(0x03e8, Pw, base)); // Power
859// C2
860if (c2_enabled)
861{
862tmpl = aml_add_package(pack);
863Lat = NULL;
864Pw = NULL;
865match_Status = XMLGetProperty(personality, (const char*)"C2");
866if (match_Status) {
867Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
868Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
869}
870
871cstate_resource_template[11] = 0x10; // C2
872aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
873aml_add_byte(tmpl, 0x02); // C2
874aml_add_word(tmpl, resolve_cst(fadt->C2Latency, Lat, base)); // Latency
875aml_add_word(tmpl, resolve_cst(0x01f4, Pw, base)); // Power
876}
877
878// C4
879if (c4_enabled)
880{
881tmpl = aml_add_package(pack);
882Lat = NULL;
883Pw = NULL;
884match_Status = XMLGetProperty(personality, (const char*)"C4");
885if (match_Status) {
886Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
887Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
888}
889cstate_resource_template[11] = 0x30; // C4
890aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
891aml_add_byte(tmpl, 0x04); // C4
892aml_add_word(tmpl, resolve_cst(fadt->C3Latency / 2, Lat, base)); // TODO: right latency for C4
893aml_add_word(tmpl, resolve_cst(0xfa, Pw, base)); // Power
894
895// you can check if the C4 state is correctly activated or not with the following command Lines (you will need the 'lspci for mac' package):
896
897// according to the intel ich10 dataheet ( Power Management PCI Configuration Registers (PM—D31:F0) ):
898// setpci -s 0:1f.0 0xa0.w (must return an hex where bit 12 is 0 and bit 7 is 1, usually 06a0h )
899// setpci -s 0:1f.0 0xa6.b (must return an hex where bit 7 is 1, usually 80h )
900
901
902}
903// C3
904else if (c3_enabled)
905{
906tmpl = aml_add_package(pack);
907Lat = NULL;
908Pw = NULL;
909match_Status = XMLGetProperty(personality, (const char*)"C3");
910if (match_Status) {
911Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
912Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
913}
914cstate_resource_template[11] = 0x20; // C3
915aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
916aml_add_byte(tmpl, 0x03); // C3
917aml_add_word(tmpl, resolve_cst(fadt->C3Latency , Lat, base));
918aml_add_word(tmpl, resolve_cst(0x015e, Pw, base)); // Power
919
920}
921
922 // Aliaces
923 unsigned int i;
924 for (i = 0; i < cpu_map_count; i++)
925 {
926 char name[9];
927 U32 nseg = *(U32*)cpu_map[i].nameseg;
928 if (cpuNamespace == CPU_NAMESPACE_PR) {
929 sprintf(name, "_PR_%c%c%c%c",
930 (int)(nseg & 0x000000ff),
931 (int)((nseg & 0x0000ff00) >> 8),
932 (int)((nseg & 0x00ff0000) >> 16),
933 (int)(nseg >> 24));
934 } else if (cpuNamespace == CPU_NAMESPACE_SB) {
935 sprintf(name, "_SB_%c%c%c%c",
936 (int)(nseg & 0x000000ff),
937 (int)((nseg & 0x0000ff00) >> 8),
938 (int)((nseg & 0x00ff0000) >> 16),
939 (int)(nseg >> 24));
940 } else {
941 aml_destroy_node(root);
942 goto out;
943 }
944
945 scop = aml_add_scope(root, name);
946 aml_add_alias(scop, "CST_", "_CST");
947 }
948
949aml_calculate_size(root);
950
951ACPI_TABLE_SSDT *ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(root->Size);
952
953aml_write_node(root, (void*)ssdt, 0);
954
955ssdt->Header.Length = root->Size;
956
957SetChecksum(&ssdt->Header);
958
959aml_destroy_node(root);
960
961verbose ("SSDT with CPU C-States generated successfully\n");
962
963return ssdt;
964}
965else
966{
967out:
968verbose ("ACPI CPUs not found: C-States will not be generated !!!\n");
969}
970
971return (void *)0ul;
972}
973
974static ACPI_TABLE_SSDT *generate_pss_ssdt(ACPI_TABLE_DSDT* dsdt)
975{
976
977char ssdt_header[] =
978{
9790x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
9800x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
9810x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
9820x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
9830x31, 0x03, 0x10, 0x20,/* 1.._*/
984};
985
986if (Platform->CPU.Vendor != 0x756E6547) {
987verbose ("Not an Intel platform: P-States will not be generated !!!\n");
988return (void *)0ul;
989}
990
991if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {
992verbose ("Unsupported CPU: P-States will not be generated !!!\n");
993return (void *)0ul;
994}
995
996if (dsdt == (void *)0ul) {
997verbose ("DSDT not found: P-States will not be generated !!!\n");
998return (void *)0ul;
999}
1000
1001if (generate_cpu_map_from_acpi(dsdt) == 0 )
1002{
1003struct p_state /*initial,*/ maximum, minimum, p_states[32];
1004U8 p_states_count = 0;
1005
1006// Retrieving P-States, ported from code by superhai (c)
1007switch (Platform->CPU.Family) {
1008case 0x06:
1009{
1010switch (Platform->CPU.Model)
1011{
1012case CPUID_MODEL_DOTHAN:
1013case CPUID_MODEL_YONAH: // Yonah
1014case CPUID_MODEL_MEROM: // Merom
1015case CPUID_MODEL_PENRYN: // Penryn
1016case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1017{
1018bool cpu_dynamic_fsb = false;
1019
1020if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
1021{
1022wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
1023delay(1);
1024cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
1025}
1026
1027bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
1028
1029initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
1030
1031maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
1032maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
1033
1034minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
1035minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
1036
1037if (minimum.FID == 0)
1038{
1039U64 msr;
1040U8 i;
1041// Probe for lowest fid
1042for (i = maximum.FID; i >= 0x6; i--)
1043{
1044msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1045wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
1046intel_waitforsts();
1047minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
1048delay(1);
1049}
1050
1051msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1052wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1053intel_waitforsts();
1054}
1055
1056if (minimum.VID == maximum.VID)
1057{
1058U64 msr;
1059U8 i;
1060// Probe for lowest vid
1061for (i = maximum.VID; i > 0xA; i--)
1062{
1063msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1064wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
1065intel_waitforsts();
1066minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
1067delay(1);
1068}
1069
1070msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1071wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1072intel_waitforsts();
1073}
1074
1075minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
1076
1077// Sanity check
1078if (maximum.CID < minimum.CID)
1079{
1080DBG("Insane FID values!");
1081p_states_count = 0;
1082}
1083else
1084{
1085// Finalize P-States
1086// Find how many P-States machine supports
1087p_states_count = maximum.CID - minimum.CID + 1;
1088
1089if (p_states_count > 32) // MAX_PSTATES ??
1090p_states_count = 32; // MAX_PSTATES ??
1091
1092U8 vidstep;
1093U8 i = 0, u, invalid = 0;
1094
1095vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
1096
1097for (u = 0; u < p_states_count; u++)
1098{
1099i = u - invalid;
1100
1101p_states[i].CID = maximum.CID - u;
1102p_states[i].FID = (p_states[i].CID >> 1);
1103
1104if (p_states[i].FID < 0x6)
1105{
1106if (cpu_dynamic_fsb)
1107p_states[i].FID = (p_states[i].FID << 1) | 0x80;
1108}
1109else if (cpu_noninteger_bus_ratio)
1110{
1111p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
1112}
1113
1114if (i && p_states[i].FID == p_states[i-1].FID)
1115invalid++;
1116
1117p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
1118
1119U32 multiplier = p_states[i].FID & 0x1f;// = 0x08
1120bool half = p_states[i].FID & 0x40;// = 0x01
1121bool dfsb = p_states[i].FID & 0x80;// = 0x00
1122U32 fsb = Platform->CPU.FSBFrequency / 1000000; // = 400
1123U32 halffsb = (fsb + 1) >> 1;// = 200
1124U32 frequency = (multiplier * fsb);// = 3200
1125
1126p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
1127}
1128
1129p_states_count -= invalid;
1130}
1131break;
1132}
1133case CPUID_MODEL_FIELDS:
1134case CPUID_MODEL_DALES:
1135case CPUID_MODEL_DALES_32NM:
1136case CPUID_MODEL_NEHALEM:
1137case CPUID_MODEL_NEHALEM_EX:
1138case CPUID_MODEL_WESTMERE:
1139case CPUID_MODEL_WESTMERE_EX:
1140case CPUID_MODEL_SANDYBRIDGE:
1141 case CPUID_MODEL_JAKETOWN:
1142{
1143maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
1144minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
1145
1146verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
1147
1148// Sanity check
1149if (maximum.Control < minimum.Control)
1150{
1151DBG("Insane control values!");
1152p_states_count = 0;
1153}
1154else
1155{
1156U8 i;
1157p_states_count = 0;
1158
1159for (i = maximum.Control; i >= minimum.Control; i--)
1160{
1161p_states[p_states_count].Control = i;
1162p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
1163p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i;
1164p_states_count++;
1165if (p_states_count >= 32) {
1166
1167if (p_states_count > 32) // MAX_PSTATES ??
1168p_states_count = 32; // MAX_PSTATES ??
1169
1170break;
1171}
1172}
1173}
1174
1175break;
1176}
1177default:
1178verbose ("Unsupported CPU: P-States will not be generated !!!\n");
1179break;
1180}
1181}
1182default:
1183break;
1184}
1185
1186// Generating SSDT
1187if (p_states_count)
1188{
1189unsigned int i;
1190
1191struct aml_chunk* root = aml_create_node(NULL);
1192 aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
1193struct aml_chunk* scop;
1194if (cpuNamespace == CPU_NAMESPACE_PR)
1195scop = aml_add_scope(root, "\\_PR_");
1196else if (cpuNamespace == CPU_NAMESPACE_SB)
1197scop = aml_add_scope(root, "\\_SB_");
1198 else
1199{
1200 aml_destroy_node(root);
1201 goto out;
1202 }
1203 struct aml_chunk* name = aml_add_name(scop, "PSS_");
1204 struct aml_chunk* pack = aml_add_package(name);
1205
1206 U8 minPSratio = (p_states[p_states_count-1].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
1207 U8 maxPSratio = (p_states[0].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
1208
1209 U8 cpu_div = Platform->CPU.CurrDiv;
1210 U8 cpu_ratio = 0;
1211
1212 if (cpu_div)
1213 cpu_ratio = (Platform->CPU.CurrCoef * 10) + 5;
1214 else
1215 cpu_ratio = Platform->CPU.CurrCoef * 10;
1216
1217
1218 int user_max_ratio = 0;
1219 getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->bootConfig);
1220 if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio) {
1221
1222 U8 maxcurrdiv = 0, maxcurrcoef = (int)(user_max_ratio / 10);
1223
1224 U8 maxdiv = user_max_ratio - (maxcurrcoef * 10);
1225 if (maxdiv > 0)
1226 maxcurrdiv = 1;
1227
1228 if (maxcurrdiv)
1229 cpu_ratio = (maxcurrcoef * 10) + 5;
1230 else
1231 cpu_ratio = maxcurrcoef * 10;
1232 }
1233
1234 int user_min_ratio = 0;
1235 getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->bootConfig);
1236 if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio) {
1237
1238 U8 mincurrdiv = 0, mincurrcoef = (int)(user_min_ratio / 10);
1239
1240 U8 mindiv = user_min_ratio - (mincurrcoef * 10);
1241
1242 if (mindiv > 0)
1243 mincurrdiv = 1;
1244
1245 if (mincurrdiv)
1246 minPSratio = (mincurrcoef * 10) + 5;
1247 else
1248 minPSratio = mincurrcoef * 10;
1249
1250 }
1251
1252 if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)maxPSratio = cpu_ratio;
1253
1254 TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"P-States"));
1255 char* MatchStat = 0;
1256 int dropPSS = 0, Pstatus = 0, base = 16;
1257 int expert = 0;/* Default: 0 , mean mixed mode | expert mode : 1 , mean add only p-states found in boot.plist*/
1258 char *tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Mode"));
1259
1260 if (strcmp(tmpstr,"Expert") == 0) {
1261 p_states_count = XMLTagCount(personality) - 1 ; // - 1 = - ("Mode" tag)
1262 expert = 1;
1263 }
1264
1265
1266 if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base")))) {
1267
1268 if (expert) p_states_count--; // -= ("Base" tag)
1269
1270 int mybase = strtol(tmpstr, NULL, 10);
1271
1272 if (mybase == 8 || mybase == 10 || mybase == 16 )
1273 base = mybase;
1274 }
1275
1276 for (i = 0; i < p_states_count; i++)
1277 {
1278 sprintf(MatchStat, "%d",i);
1279 TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
1280
1281 char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;
1282
1283 if (match_Status) {
1284
1285 clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));
1286 Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1287 Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));
1288 Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));
1289 Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));
1290
1291
1292 } else if (expert)
1293 continue;
1294
1295
1296 unsigned long Frequency = 0x00000000;
1297
1298 if (!expert) Frequency = p_states[i].Frequency;
1299
1300 if (clk)
1301 Frequency = strtoul((const char *)clk, NULL,base);
1302
1303 if (!Frequency || Frequency > p_states[0].Frequency ) continue;
1304
1305 U8 curr_ratio = (Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
1306
1307 if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
1308 goto dropPstate;
1309
1310 struct aml_chunk* pstt = aml_add_package(pack);
1311 aml_add_dword(pstt, Frequency); // CoreFreq (in MHz).
1312 aml_add_dword(pstt, resolve_pss(0x00000000, Pw, base)); // Power (in milliWatts)
1313 aml_add_dword(pstt, resolve_pss(0x0000000A, Lat1, base)); // Transition Latency (in microseconds).
1314 aml_add_dword(pstt, resolve_pss(0x0000000A, Lat2, base)); // Bus Master Latency (in microseconds).
1315 unsigned long Control = 0x00000000;
1316 if (!expert) Control = p_states[i].Control;
1317 aml_add_dword(pstt, resolve_pss(Control, Ctrl, base)); // Control
1318 Pstatus++;
1319 aml_add_dword(pstt, Pstatus); // Status
1320 continue;
1321 dropPstate:
1322
1323 DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
1324
1325 dropPSS++;
1326
1327
1328 }
1329
1330
1331// Add aliaces
1332for (i = 0; i < cpu_map_count; i++)
1333{
1334char name[9];
1335 U32 nseg = *(U32*)cpu_map[i].nameseg;
1336 if (cpuNamespace == CPU_NAMESPACE_PR) {
1337 sprintf(name, "_PR_%c%c%c%c",
1338 (int)(nseg & 0x000000ff),
1339 (int)((nseg & 0x0000ff00) >> 8),
1340 (int)((nseg & 0x00ff0000) >> 16),
1341 (int)(nseg >> 24));
1342 } else if (cpuNamespace == CPU_NAMESPACE_SB) {
1343 sprintf(name, "_SB_%c%c%c%c",
1344 (int)(nseg & 0x000000ff),
1345 (int)((nseg & 0x0000ff00) >> 8),
1346 (int)((nseg & 0x00ff0000) >> 16),
1347 (int)(nseg >> 24));
1348 } else {
1349 aml_destroy_node(root);
1350 goto out;
1351 }
1352
1353scop = aml_add_scope(root, name);
1354aml_add_alias(scop, "PSS_", "_PSS");
1355}
1356
1357aml_calculate_size(root);
1358
1359ACPI_TABLE_SSDT *ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(root->Size);
1360
1361aml_write_node(root, (void*)ssdt, 0);
1362
1363ssdt->Header.Length = root->Size;
1364
1365 SetChecksum(&ssdt->Header);
1366
1367aml_destroy_node(root);
1368
1369verbose ("SSDT with CPU P-States generated successfully");
1370
1371if (dropPSS)
1372 verbose(", %d P-state(s) dropped",dropPSS);
1373
1374verbose("\n");
1375
1376return ssdt;
1377}
1378}
1379else
1380{
1381out:
1382verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
1383}
1384
1385return (void *)0ul;
1386}
1387#else
1388
1389static bool is_sandybridge(void)
1390{
1391 return Platform->CPU.Model == CPUID_MODEL_SANDYBRIDGE;
1392}
1393
1394static bool is_jaketown(void)
1395{
1396 return Platform->CPU.Model == CPUID_MODEL_JAKETOWN;
1397}
1398
1399static U32 get_bclk(void)
1400{
1401return (is_jaketown() || is_sandybridge()) ? 100 : 133;
1402}
1403
1404//-----------------------------------------------------------------------------
1405static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate)
1406{
1407U32 ratiorange = max-min;
1408U32 numGaps = numStates-1-turboEnabled;
1409U32 adjPstate = pstate-turboEnabled;
1410return (pstate == 0) ? (max + turboEnabled) :
1411(ratiorange == 0) ? max :
1412max-(((adjPstate*ratiorange)+(numGaps/2))/numGaps);
1413}
1414//-----------------------------------------------------------------------------
1415static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit)
1416{
1417U32 ratiorange, maxStates, numStates;
1418
1419ratiorange = max - min + 1;
1420maxStates = ratiorange + (turboEnabled ? 1 : 0);
1421numStates = (pssLimit < maxStates) ? pssLimit : maxStates;
1422return (numStates < 2) ? 0 : numStates;
1423}
1424
1425#if BUILD_ACPI_TSS || pstate_power_support
1426static U64 divU64byU64(U64 n, U64 d, U64 * rem)
1427{
1428 U32 i;
1429 U64 q = n;
1430 U64 r = 0;
1431
1432 for (i = 0; i < 64; i++) {
1433 r <<= 1;
1434 r |= (q & (1ULL << 63)) >> 63;
1435 q <<= 1;
1436 if (r >= d) {
1437 r -= d;
1438 q |= 1;
1439 }
1440 }
1441 if (rem)
1442 *rem = r;
1443 return q;
1444}
1445
1446static U32 compute_tdp(CPU_DETAILS * cpu)
1447{
1448
1449 {
1450 if (is_jaketown() || is_sandybridge())
1451 {
1452 U64 power_limit_1 = cpu->package_power_limit & ((1ULL << 15) - 1);
1453 U64 power_unit = cpu->package_power_sku_unit & ((1ULL << 4) - 1);
1454 U64 tdp = divU64byU64(power_limit_1, 1 << power_unit, NULL);
1455 return (U32)tdp;
1456 }
1457 else
1458 {
1459 // tdp = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [14:0] / 8) Watts
1460 return cpu->tdp_limit / 8;
1461 }
1462 }
1463
1464}
1465#endif
1466
1467#if pstate_power_support
1468static U64 mulU64byU64(U64 a, U64 b, U64 * high)
1469{
1470 U64 b_high = 0;
1471 U64 r_high = 0, r_low = 0;
1472 U64 bit;
1473
1474 for (bit = 1; bit; bit <<= 1) {
1475 if (a & bit) {
1476 if (r_low + b < r_low)
1477 r_high++;
1478 r_low += b;
1479 r_high += b_high;
1480 }
1481 b_high <<= 1;
1482 b_high |= (b & (1ULL << 63)) >> 63;
1483 b <<= 1;
1484 }
1485
1486 if (high)
1487 *high = r_high;
1488 return r_low;
1489}
1490
1491static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP)
1492{
1493if (is_jaketown() || is_sandybridge())
1494{
1495U32 P1_Ratio = cpu->max_ratio_as_mfg;
1496U64 M, pstate_power;
1497
1498// M = ((1.1 - ((P1_ratio - ratio) * 0.00625)) / 1.1) ^2
1499// To prevent loss of precision compute M * 10^5 (preserves 5 decimal places)
1500M = (P1_Ratio - ratio) * 625;
1501M = (110000 - M);
1502M = divU64byU64(M, 11, NULL);
1503M = divU64byU64(mulU64byU64(M, M, NULL), 1000, NULL);
1504
1505// pstate_power = ((ratio/p1_ratio) * M * TDP)
1506// Divide the final answer by 10^5 to remove the precision factor
1507pstate_power = mulU64byU64(ratio, M, NULL);
1508pstate_power = mulU64byU64(pstate_power, TDP, NULL);
1509pstate_power = divU64byU64(pstate_power, P1_Ratio, NULL);
1510pstate_power = divU64byU64(pstate_power, 100000, NULL);
1511return (U32)pstate_power; // in Watts
1512}
1513else
1514{
1515// pstate_power[ratio] = (ratio/P1_ratio)^3 * Core_TDP + Uncore_TDP
1516
1517// Core_TDP = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [30:16] / 8) Watts
1518U32 Core_TDP = cpu->tdc_limit / 8;
1519
1520// Uncore_TDP = TDP - Core_TDP
1521U32 Uncore_TDP = TDP - Core_TDP;
1522
1523// max_ratio_as_mfg = P1_Ratio derived from Brand String returned by CPUID instruction
1524U32 P1_Ratio = cpu->max_ratio_as_mfg;
1525
1526#define PRECISION_FACTOR (U32) 30
1527#define PRECISION_FACTOR_CUBED (U32) (PRECISION_FACTOR * PRECISION_FACTOR * PRECISION_FACTOR)
1528
1529U32 ratio_factor = (ratio * PRECISION_FACTOR)/P1_Ratio;
1530return ((ratio_factor * ratio_factor * ratio_factor * Core_TDP) / PRECISION_FACTOR_CUBED) + Uncore_TDP;
1531}
1532}
1533#endif
1534
1535static U32 encode_pstate(U32 ratio)
1536{
1537if (is_jaketown() || is_sandybridge())
1538return ratio << 8;
1539return ratio;
1540}
1541
1542//-----------------------------------------------------------------------------
1543void GetMaxRatio(U32 * max_non_turbo_ratio)
1544{
1545U32 index;
1546U32 max_ratio=0;
1547U32 frequency=0;
1548 U32 multiplier = 0;
1549// Verify CPUID brand string function is supported
1550if (Platform->CPU.cpuid_max_ext < 80000004)
1551{
1552*max_non_turbo_ratio = max_ratio;
1553return;
1554}
1555
1556 // -2 to prevent buffer overrun because looking for y in yHz, so z is +2 from y
1557 for (index=0; index<48-2; index++) {
1558 // format is either “x.xxyHz” or “xxxxyHz”, where y=M,G,T and x is digits
1559 // Search brand string for “yHz” where y is M, G, or T
1560 // Set multiplier so frequency is in MHz
1561 if ( Platform->CPU.BrandString[index+1] == 'H' && Platform->CPU.BrandString[index+2] == 'z')
1562 {
1563 if (Platform->CPU.BrandString[index] == 'M')
1564 multiplier = 1;
1565 else if (Platform->CPU.BrandString[index] == 'G')
1566 multiplier = 1000;
1567 else if (Platform->CPU.BrandString[index] == 'T')
1568 multiplier = 1000000;
1569 }
1570 if (multiplier > 0 && index >= 4 /* who can i call that, buffer underflow :-) ??*/)
1571 {
1572 // Copy 7 characters (length of “x.xxyHz”)
1573 // index is at position of y in “x.xxyHz”
1574
1575 // Compute frequency (in MHz) from brand string
1576 if (Platform->CPU.BrandString[index-3] == '.')
1577 { // If format is “x.xx”
1578 if (isdigit(Platform->CPU.BrandString[index-4]) && isdigit(Platform->CPU.BrandString[index-2]) &&
1579 isdigit(Platform->CPU.BrandString[index-1]))
1580 {
1581 frequency = (U32)(Platform->CPU.BrandString[index-4] - '0') * multiplier;
1582 frequency += (U32)(Platform->CPU.BrandString[index-2] - '0') * (multiplier / 10);
1583 frequency += (U32)(Platform->CPU.BrandString[index-1] - '0') * (multiplier / 100);
1584 }
1585 }
1586 else
1587 { // If format is xxxx
1588 if (isdigit(Platform->CPU.BrandString[index-4]) && isdigit(Platform->CPU.BrandString[index-3]) &&
1589 isdigit(Platform->CPU.BrandString[index-2]) && isdigit(Platform->CPU.BrandString[index-1]))
1590 {
1591 frequency = (U32)(Platform->CPU.BrandString[index-4] - '0') * 1000;
1592 frequency += (U32)(Platform->CPU.BrandString[index-3] - '0') * 100;
1593 frequency += (U32)(Platform->CPU.BrandString[index-2] - '0') * 10;
1594 frequency += (U32)(Platform->CPU.BrandString[index-1] - '0');
1595 frequency *= multiplier;
1596 }
1597
1598 }
1599
1600 max_ratio = frequency / get_bclk();
1601 break;
1602 }
1603 }
1604
1605// Return non-zero Max Non-Turbo Ratio obtained from CPUID brand string
1606// or return 0 indicating Max Non-Turbo Ratio not available
1607*max_non_turbo_ratio = max_ratio;
1608}
1609
1610//-----------------------------------------------------------------------------
1611static void collect_cpu_info(CPU_DETAILS * cpu)
1612{
1613
1614#if BUILD_ACPI_TSS || pstate_power_support
1615 cpu->turbo_available = Platform->CPU.dynamic_acceleration;
1616
1617{
1618U32 temp32 = 0;
1619U64 temp64= 0;
1620int tdp;
1621if (getIntForKey("TDP", &tdp, &bootInfo->bootConfig))
1622{
1623temp32 = (U32) (tdp*8) ;
1624
1625int tdc;
1626if (getIntForKey("TDC", &tdc, &bootInfo->bootConfig))
1627{
1628temp32 = (U32) (temp32) | tdc<<16 ;
1629
1630}
1631else if (tdp)
1632{
1633temp32 = (U32) (temp32) | ((tdp)*8)<<16 ;
1634}
1635
1636}
1637else if (!is_sandybridge() && !is_jaketown())
1638{
1639if (turbo_enabled && cpu->turbo_available)
1640{
1641temp64 = rdmsr64(MSR_TURBO_POWER_CURRENT_LIMIT);
1642temp32 = (U32)temp64;
1643}
1644else
1645{
1646// Unfortunately, Intel don't provide a better method for non turbo processors
1647// and it will give a TDP of 95w (for ex. mine is 65w) , to fix this issue,
1648// you can set this value by simply adding the option TDP = XX (XX is an integer)
1649// in your boot.plist
1650temp32 = (U32)0x02a802f8;
1651}
1652
1653}
1654if (temp32) {
1655cpu->tdp_limit = ( temp32 & 0x7fff );
1656cpu->tdc_limit = ( (temp32 >> 16) & 0x7fff );
1657}
1658}
1659
1660#endif
1661
1662switch (Platform->CPU.Family)
1663{
1664case 0x06:
1665{
1666switch (Platform->CPU.Model)
1667{
1668case CPUID_MODEL_DOTHAN:
1669case CPUID_MODEL_YONAH: // Yonah
1670case CPUID_MODEL_MEROM: // Merom
1671case CPUID_MODEL_PENRYN: // Penryn
1672case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1673{
1674
1675cpu->core_c1_supported = ((Platform->CPU.sub_Cstates >> 4) & 0xf) ? 1 : 0;
1676cpu->core_c4_supported = ((Platform->CPU.sub_Cstates >> 16) & 0xf) ? 1 : 0;
1677
1678if (Platform->CPU.Model == CPUID_MODEL_ATOM)
1679{
1680cpu->core_c2_supported = cpu->core_c3_supported = ((Platform->CPU.sub_Cstates >> 8) & 0xf) ? 1 : 0;
1681cpu->core_c6_supported = ((Platform->CPU.sub_Cstates >> 12) & 0xf) ? 1 : 0;
1682
1683}
1684else
1685{
1686cpu->core_c3_supported = ((Platform->CPU.sub_Cstates >> 12) & 0xf) ? 1 : 0;
1687cpu->core_c2_supported = ((Platform->CPU.sub_Cstates >> 8) & 0xf) ? 1 : 0;
1688cpu->core_c6_supported = 0;
1689
1690}
1691
1692cpu->core_c7_supported = 0;
1693
1694#if BETA
1695GetMaxRatio(&cpu->max_ratio_as_mfg);
1696U64 msr = rdmsr64(MSR_IA32_PERF_STATUS);
1697U16 idlo = (msr >> 48) & 0xffff;
1698U16 idhi = (msr >> 32) & 0xffff;
1699cpu->min_ratio = (U32) (idlo >> 8) & 0xff;
1700cpu->max_ratio_as_cfg = (U32) (idhi >> 8) & 0xff;
1701
1702#else
1703if (Platform->CPU.MaxCoef)
1704{
1705if (Platform->CPU.MaxDiv)
1706{
1707cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) (Platform->CPU.MaxCoef * 10) + 5;
1708}
1709else
1710{
1711cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) Platform->CPU.MaxCoef * 10;
1712}
1713}
1714#endif
1715
1716break;
1717}
1718case CPUID_MODEL_FIELDS:
1719case CPUID_MODEL_DALES:
1720case CPUID_MODEL_DALES_32NM:
1721case CPUID_MODEL_NEHALEM:
1722case CPUID_MODEL_NEHALEM_EX:
1723case CPUID_MODEL_WESTMERE:
1724case CPUID_MODEL_WESTMERE_EX:
1725case CPUID_MODEL_SANDYBRIDGE:
1726case CPUID_MODEL_JAKETOWN:
1727{
1728
1729cpu->core_c1_supported = ((Platform->CPU.sub_Cstates >> 4) & 0xf) ? 1 : 0;
1730cpu->core_c3_supported = ((Platform->CPU.sub_Cstates >> 8) & 0xf) ? 1 : 0;
1731cpu->core_c6_supported = ((Platform->CPU.sub_Cstates >> 12) & 0xf) ? 1 : 0;
1732cpu->core_c7_supported = ((Platform->CPU.sub_Cstates >> 16) & 0xf) ? 1 : 0;
1733cpu->core_c2_supported = 0;
1734cpu->core_c4_supported = 0;
1735
1736GetMaxRatio(&cpu->max_ratio_as_mfg);
1737 U64 platform_info = rdmsr64(MSR_PLATFORM_INFO);
1738 cpu->max_ratio_as_cfg = (U32) ((U32)platform_info >> 8) & 0xff;
1739cpu->min_ratio = (U32) ((platform_info >> 40) & 0xff);
1740
1741if (is_sandybridge() || is_jaketown())
1742{
1743cpu->package_power_limit = rdmsr64(MSR_PKG_RAPL_POWER_LIMIT);
1744cpu->package_power_sku_unit = rdmsr64(MSR_RAPL_POWER_UNIT);
1745}
1746break;
1747}
1748default:
1749verbose ("Unsupported CPU\n");
1750return /*(0)*/;
1751break;
1752}
1753}
1754default:
1755break;
1756}
1757
1758cpu->mwait_supported = (Platform->CPU.extensions & (1UL << 0)) ? 1 : 0;
1759
1760 cpu->invariant_apic_timer_flag = Platform->CPU.invariant_APIC_timer;
1761
1762#if DEBUG_ACPI
1763printf("CPU INFO : \n");
1764#if BETA
1765printf("min_ratio : %d\n", cpu->min_ratio);
1766#endif
1767printf("max_ratio_as_cfg : %d\n", cpu->max_ratio_as_cfg);
1768printf("max_ratio_as_mfg : %d\n", cpu->max_ratio_as_mfg);
1769
1770printf("turbo_available : %d\n",cpu->turbo_available);
1771
1772printf("core_c1_supported : %d\n",cpu->core_c1_supported);
1773printf("core_c2_supported : %d\n",cpu->core_c1_supported);
1774printf("core_c3_supported : %d\n",cpu->core_c3_supported);
1775printf("core_c6_supported : %d\n",cpu->core_c6_supported);
1776printf("core_c7_supported : %d\n",cpu->core_c7_supported);
1777printf("mwait_supported : %d\n",cpu->mwait_supported);
1778
1779#if BUILD_ACPI_TSS || pstate_power_support
1780if (is_sandybridge() || is_jaketown())
1781{
1782
1783printf("package_power_limit : %d\n",cpu->package_power_limit);
1784printf("package_power_sku_unit : %d\n",cpu->package_power_sku_unit);
1785
1786}
1787#endif
1788
1789DBG("invariant_apic_timer_flag : %d\n",cpu->invariant_apic_timer_flag);
1790
1791
1792#endif
1793}
1794
1795#if BETA
1796//-----------------------------------------------------------------------------
1797static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1798{
1799// Build P-state table info based on verified options
1800
1801// Compute the number of p-states based on the ratio range
1802cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1803
1804if (!cpu->pkg_pstates.num_pstates)
1805{
1806return (0);
1807}
1808
1809// Compute pstate data
1810{
1811U32 TDP = compute_tdp(cpu);
1812
1813U32 index;
1814for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1815{
1816PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1817
1818// Set ratio
1819pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1820
1821// Compute frequency based on ratio
1822if ((index != 0) || (cpu->turbo_available == 0))
1823pstate->frequency = pstate->ratio * get_bclk();
1824else
1825pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1826
1827// Compute power based on ratio and other data
1828if (pstate->ratio >= cpu->max_ratio_as_mfg)
1829// Use max power in mW
1830pstate->power = TDP * 1000;
1831else
1832{
1833pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1834
1835// Convert to mW
1836pstate->power*= 1000;
1837}
1838}
1839}
1840
1841return (1);
1842}
1843#else
1844
1845//-----------------------------------------------------------------------------
1846static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu)
1847{
1848// Build P-state table info based on verified options
1849
1850// Compute the number of p-states based on the ratio range
1851cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1852
1853if (!cpu->pkg_pstates.num_pstates)
1854{
1855return (0);
1856}
1857
1858// Compute pstate data
1859{
1860#ifdef pstate_power_support
1861U32 TDP = compute_tdp(cpu);
1862#endif
1863
1864U32 index;
1865for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1866{
1867PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1868
1869// Set ratio
1870pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1871
1872// Compute frequency based on ratio
1873if ((index != 0) || (cpu->turbo_available == 0))
1874pstate->frequency = pstate->ratio * get_bclk();
1875else
1876pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1877
1878#ifdef pstate_power_support
1879// Compute power based on ratio and other data
1880if (pstate->ratio >= cpu->max_ratio_as_mfg)
1881// Use max power in mW
1882pstate->power = TDP * 1000;
1883else
1884{
1885pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1886
1887// Convert to mW
1888pstate->power*= 1000;
1889}
1890#else
1891pstate->power = 0;
1892#endif
1893}
1894}
1895
1896return (1);
1897}
1898
1899//-----------------------------------------------------------------------------
1900static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1901{
1902
1903struct p_state p_states[32];
1904U8 p_states_count = 0;
1905{
1906#if UNUSED
1907struct p_state initial;
1908#endif
1909struct p_state maximum, minimum;
1910// Retrieving P-States, ported from code by superhai (c)
1911switch (Platform->CPU.Family)
1912{
1913case 0x06:
1914{
1915switch (Platform->CPU.Model)
1916{
1917case CPUID_MODEL_DOTHAN:
1918case CPUID_MODEL_YONAH: // Yonah
1919case CPUID_MODEL_MEROM: // Merom
1920case CPUID_MODEL_PENRYN: // Penryn
1921case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1922{
1923bool cpu_dynamic_fsb = false;
1924
1925if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
1926{
1927wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
1928delay(1);
1929cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
1930}
1931
1932bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
1933#if UNUSED
1934//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
1935#endif
1936maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
1937maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
1938
1939minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
1940minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
1941
1942if (minimum.FID == 0)
1943{
1944U64 msr;
1945U8 i;
1946// Probe for lowest fid
1947for (i = maximum.FID; i >= 0x6; i--)
1948{
1949msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1950wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
1951intel_waitforsts();
1952minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
1953delay(1);
1954}
1955
1956msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1957wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1958intel_waitforsts();
1959}
1960
1961if (minimum.VID == maximum.VID)
1962{
1963U64 msr;
1964U8 i;
1965// Probe for lowest vid
1966for (i = maximum.VID; i > 0xA; i--)
1967{
1968msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1969wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
1970intel_waitforsts();
1971minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
1972delay(1);
1973}
1974
1975msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1976wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1977intel_waitforsts();
1978}
1979
1980minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
1981
1982// Sanity check
1983if (maximum.CID < minimum.CID)
1984{
1985DBG("Insane FID values!");
1986p_states_count = 0;
1987}
1988else
1989{
1990// Finalize P-States
1991// Find how many P-States machine supports
1992p_states_count = maximum.CID - minimum.CID + 1;
1993
1994if (p_states_count > MAX_PSTATES) // was 32
1995p_states_count = MAX_PSTATES; // was 32
1996
1997U8 vidstep;
1998U8 i = 0, u, invalid = 0;
1999
2000vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
2001
2002for (u = 0; u < p_states_count; u++)
2003{
2004i = u - invalid;
2005
2006p_states[i].CID = maximum.CID - u;
2007p_states[i].FID = (p_states[i].CID >> 1);
2008
2009if (p_states[i].FID < 0x6)
2010{
2011if (cpu_dynamic_fsb)
2012p_states[i].FID = (p_states[i].FID << 1) | 0x80;
2013}
2014else if (cpu_noninteger_bus_ratio)
2015{
2016p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
2017}
2018
2019if (i && p_states[i].FID == p_states[i-1].FID)
2020invalid++;
2021
2022p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
2023
2024U32 multiplier = p_states[i].FID & 0x1f;// = 0x08
2025bool half = p_states[i].FID & 0x40;// = 0x01
2026bool dfsb = p_states[i].FID & 0x80;// = 0x00
2027U32 fsb = Platform->CPU.FSBFrequency / 1000000; // = 400
2028U32 halffsb = (fsb + 1) >> 1;// = 200
2029U32 frequency = (multiplier * fsb);// = 3200
2030
2031p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
2032}
2033
2034p_states_count -= invalid;
2035}
2036break;
2037}
2038case CPUID_MODEL_FIELDS:
2039case CPUID_MODEL_DALES:
2040case CPUID_MODEL_DALES_32NM:
2041case CPUID_MODEL_NEHALEM:
2042case CPUID_MODEL_NEHALEM_EX:
2043case CPUID_MODEL_WESTMERE:
2044case CPUID_MODEL_WESTMERE_EX:
2045case CPUID_MODEL_SANDYBRIDGE:
2046case CPUID_MODEL_JAKETOWN:
2047{
2048/*
2049 maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
2050 minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
2051
2052 verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
2053
2054 // Sanity check
2055 if (maximum.Control < minimum.Control)
2056 {
2057 DBG("Insane control values!");
2058 p_states_count = 0;
2059 }
2060 else
2061 {
2062 U8 i;
2063 p_states_count = 0;
2064
2065 for (i = maximum.Control; i >= minimum.Control; i--)
2066 {
2067 p_states[p_states_count].Control = i;
2068 p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
2069 p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i;
2070 p_states_count++;
2071 if (p_states_count >= MAX_PSTATES) { // was 32
2072
2073 if (p_states_count > MAX_PSTATES) // was 32
2074 p_states_count = MAX_PSTATES; // was 32
2075
2076 break;
2077 }
2078 }
2079 }
2080 */
2081
2082bool sta = BuildCoreIPstateInfo(cpu);
2083if (sta)
2084{
2085DBG("_PSS PGK generated successfully\n");
2086return (1);
2087
2088}
2089else
2090{
2091verbose("CoreI _PSS Generation failed !!\n");
2092return (0);
2093}
2094
2095break;
2096}
2097default:
2098verbose ("Unsupported CPU: P-States will not be generated !!!\n");
2099return (0);
2100break;
2101}
2102}
2103default:
2104break;
2105}
2106}
2107
2108// Generating Pstate PKG
2109if (p_states_count)
2110{
2111U8 minPSratio = (p_states[p_states_count-1].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
2112U8 maxPSratio = (p_states[0].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
2113U8 cpu_ratio = 0;
2114
2115{
2116U8 cpu_div = Platform->CPU.CurrDiv;
2117
2118if (cpu_div)
2119cpu_ratio = (Platform->CPU.CurrCoef * 10) + 5;
2120else
2121cpu_ratio = Platform->CPU.CurrCoef * 10;
2122}
2123
2124
2125{
2126int user_max_ratio = 0;
2127getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->bootConfig);
2128if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio)
2129{
2130
2131U8 maxcurrdiv = 0, maxcurrcoef = (int)(user_max_ratio / 10);
2132
2133U8 maxdiv = user_max_ratio - (maxcurrcoef * 10);
2134if (maxdiv > 0)
2135maxcurrdiv = 1;
2136
2137if (maxcurrdiv)
2138cpu_ratio = (maxcurrcoef * 10) + 5;
2139else
2140cpu_ratio = maxcurrcoef * 10;
2141}
2142}
2143
2144{
2145int user_min_ratio = 0;
2146getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->bootConfig);
2147if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio)
2148{
2149
2150U8 mincurrdiv = 0, mincurrcoef = (int)(user_min_ratio / 10);
2151
2152U8 mindiv = user_min_ratio - (mincurrcoef * 10);
2153
2154if (mindiv > 0)
2155mincurrdiv = 1;
2156
2157if (mincurrdiv)
2158minPSratio = (mincurrcoef * 10) + 5;
2159else
2160minPSratio = mincurrcoef * 10;
2161
2162}
2163}
2164
2165
2166if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)maxPSratio = cpu_ratio;
2167
2168{
2169TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"P-States"));
2170int base = 16;
2171U8 expert = 0; /* Default: 0 , mean mixed mode
2172 * expert mode : 1 , mean add only p-states found in boot.plist
2173 */
2174
2175
2176{
2177if (personality)
2178{
2179char *tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Mode"));
2180
2181if (strcmp(tmpstr,"Expert") == 0)
2182{
2183p_states_count = XMLTagCount(personality) - 1 ; // - 1 = - ("Mode" tag)
2184expert = 1;
2185}
2186
2187
2188if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))))
2189{
2190
2191if (expert) p_states_count--; // -= ("Base" tag)
2192
2193int mybase = strtol(tmpstr, NULL, 10);
2194
2195if (mybase == 8 || mybase == 10 || mybase == 16 )
2196base = mybase;
2197}
2198}
2199
2200}
2201
2202{
2203U32 dropPSS = 0, Pstatus = 0;
2204char MatchStat[5];
2205#ifdef pstate_power_support
2206U32 TDP = compute_tdp(cpu);
2207#endif
2208U32 i;
2209for (i = 0; i < p_states_count; i++)
2210{
2211char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;
2212
2213if (personality)
2214{
2215sprintf(MatchStat, "%d",i);
2216TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
2217
2218if (match_Status)
2219{
2220
2221clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));
2222Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
2223Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));
2224Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));
2225Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));
2226
2227
2228} else if (expert)
2229continue;
2230}
2231
2232unsigned long Frequency = 0x00000000;
2233
2234if (!expert || !personality) Frequency = p_states[i].Frequency;
2235
2236if (clk)
2237Frequency = strtoul((const char *)clk, NULL,base);
2238
2239if (!Frequency || Frequency > p_states[0].Frequency ) continue;
2240
2241U8 curr_ratio = (Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
2242
2243
2244 {
2245U8 fixed_ratio = (Frequency / (Platform->CPU.FSBFrequency / 1000000 ))*10;
2246U8 diff = curr_ratio - fixed_ratio ;
2247
2248if (diff)
2249{
2250if (diff < 5)
2251{
2252curr_ratio = fixed_ratio;
2253}
2254else
2255{
2256curr_ratio = fixed_ratio + 5;
2257}
2258}
2259
2260}
2261
2262if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
2263goto dropPstate;
2264
2265{
2266PSTATE * pstate = &cpu->pkg_pstates.pstate[Pstatus];
2267
2268pstate->ratio = curr_ratio;
2269
2270pstate->frequency = Frequency; // CoreFreq (in MHz).
2271
2272U32 power = 0x00000000;
2273#ifdef pstate_power_support
2274// Compute power based on ratio and other data
2275if (pstate->ratio >= cpu->max_ratio_as_mfg)
2276// Use max power in mW
2277power = TDP * 1000;
2278else
2279{
2280power = compute_pstate_power(cpu, pstate->ratio, TDP);
2281
2282// Convert to mW
2283power*= 1000;
2284}
2285#endif
2286pstate->power = resolve_pss(power, Pw, base); // Power (in milliWatts)
2287pstate->translatency = resolve_pss(0x0000000A, Lat1, base); // Transition Latency (in microseconds).
2288pstate->bmlatency = resolve_pss(0x0000000A, Lat2, base); // Bus Master Latency (in microseconds).
2289
2290{
2291U32 Control = 0 /*encode_pstate(curr_ratio)*/ ;
2292if (!expert || !personality) Control = p_states[i].Control;
2293pstate->control = resolve_pss(Control, Ctrl, base); // Control
2294}
2295
2296pstate->status = Pstatus+1; // Status
2297
2298DBG("state :: frequency :%d power: %d translatency: %d bmlatency: %d control: %d status: %d ratio :%d :: registred !! \n",pstate->frequency,pstate->power,
2299pstate->translatency,pstate->bmlatency,pstate->control,pstate->status,pstate->ratio );
2300}
2301
2302
2303Pstatus++;
2304continue;
2305
2306dropPstate:
2307DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
2308dropPSS++;
2309
2310
2311}
2312
2313if (Pstatus == 0)
2314{
2315verbose("No suitable P-states found, P-States will not be generated !!!\n");
2316return (0);
2317}
2318cpu->pkg_pstates.num_pstates = Pstatus;
2319}
2320}
2321}
2322else
2323{
2324verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
2325return (0);
2326}
2327
2328DBG("_PSS PGK generated successfully\n");
2329return (1);
2330}
2331#endif
2332
2333//-----------------------------------------------------------------------------
2334static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase)
2335{
2336{
2337TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));
2338
2339if (personality)
2340{
2341int base = 16;
2342
2343U32 entry_count = XMLTagCount(personality);
2344char *tmpstr =NULL;
2345
2346if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))))
2347{
2348
2349entry_count--; // -= ("Base" tag)
2350
2351int mybase = strtol(tmpstr, NULL, 10);
2352
2353if (mybase == 8 || mybase == 10 || mybase == 16 )
2354base = mybase;
2355}
2356
2357if (entry_count)
2358{
2359
2360cpu->pkg_io_cstates.num_cstates = 0;
2361cpu->pkg_mwait_cstates.num_cstates = 0;
2362U32 num_cstates = 0;
2363
2364{
2365U32 i;
2366char MatchStat[5];
2367
2368for (i = 0; i < 32 ; i++)
2369{
2370char *Lat = NULL, *Pw = NULL, *BWidth= NULL, *BOffset= NULL, *Address= NULL, *AccessSize= NULL, *index= NULL;
2371
2372sprintf(MatchStat, "C%d",i);
2373TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
2374if (match_Status)
2375{
2376Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
2377Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
2378BWidth= XMLCastString(XMLGetProperty(match_Status, (const char*)"BitWidth"));
2379
2380BOffset = XMLCastString(XMLGetProperty(match_Status, (const char*)"BitOffset"));
2381Address = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
2382AccessSize = XMLCastString(XMLGetProperty(match_Status, (const char*)"AccessSize"));
2383index = XMLCastString(XMLGetProperty(match_Status, (const char*)"index"));
2384
2385if (Pw && Lat && BWidth && BOffset && Address && AccessSize && index)
2386{
2387U32 bw= strtoul((const char *)BWidth, NULL,base);
2388U32 boff= strtoul((const char *)BOffset, NULL,base);
2389U32 acs= strtoul((const char *)AccessSize, NULL,base);
2390U32 addr= strtoul((const char *)Address, NULL,base);
2391U32 idx= strtoul((const char *)index, NULL,base);
2392U32 lat= strtoul((const char *)Lat, NULL,base);
2393U32 pw= strtoul((const char *)Pw, NULL,base);
2394
2395ACPI_GENERIC_ADDRESS mwait_gas = {GAS_TYPE_FFH,bw,boff,acs,addr};
2396ACPI_GENERIC_ADDRESS io_gas = {(i == 1) ? GAS_TYPE_FFH : GAS_TYPE_SYSTEM_IO,bw,boff,acs,addr};
2397
2398CSTATE mwait_cstate = {idx,lat,pw};
2399CSTATE io_cstate = {idx,lat,pw};
2400
2401{
2402cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate;
2403cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas;
2404cpu->pkg_mwait_cstates.num_cstates++;
2405}
2406
2407{
2408cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate;
2409cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas;
2410cpu->pkg_io_cstates.num_cstates++;
2411}
2412num_cstates++;
2413
2414if (num_cstates >= MAX_CSTATES)
2415{
2416break;
2417}
2418}
2419}
2420}
2421}
2422
2423if (num_cstates)
2424{
2425return (1);
2426}
2427}
2428}
2429}
2430
2431{
2432static const ACPI_GENERIC_ADDRESS mwait_gas[] = {
2433{GAS_TYPE_FFH,1,2,1,0x00}, // processor C1
2434{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C2
2435{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C3
2436{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C4
2437{GAS_TYPE_FFH,1,2,1,0x20}, // processor C6
2438{GAS_TYPE_FFH,1,2,1,0x30}, // processor C7
2439};
2440
2441static const ACPI_GENERIC_ADDRESS io_gas[] = {
2442{GAS_TYPE_FFH, 0,0,0,0x00}, // processor C1
2443{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C2 or processor C2
2444{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C3
2445{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C4 as ACPI C4
2446{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C6
2447{GAS_TYPE_SYSTEM_IO,8,0,0,0x16}, // processor C7
2448};
2449
2450static const CSTATE mwait_cstate [] = {
2451{1,0x01,0x3e8}, // processor C1
2452{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
2453{3,0x40,0x1f4}, // processor C3 as ACPI C3
2454{4,0x40,0x1f4}, // processor C4
2455{6/*was 3*/,0x60,0x15e}, // processor C6
2456{7/*was 3*/,0x60,0x0c8}, // processor C7
2457};
2458
2459static const CSTATE io_cstate [] = {
2460{1,0x01,0x3e8}, // processor C1
2461{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
2462{3,0x40,0x1f4}, // processor C3 as ACPI C3
2463{4,0x40,0x1f4}, // processor C4
2464{6/*was 3*/,0x60,0x15e}, // processor C6
2465{7/*was 3*/,0x60,0x0c8}, // processor C7
2466};
2467
2468static const U32 cstate_2_index [] = {0,0,0,1,2,3,4,5};
2469
2470// Build C-state table info based on verified options
2471
2472// Desired state for the processor core C3 state included in the _CST as an
2473// ACPI C2 state.
2474// 1= processor core C3 can be used as an ACPI C2 state
2475// 0= processor core C3 cannot be used as an ACPI C2 state
2476int c2_enabled = 0;
2477
2478// Desired state for the processor core C3 state included in the _CST
2479// 0= processor core C3 cannot be used as an ACPI C state
2480// 2= processor core C3 can be used as an ACPI C2 state
2481// 3= processor core C3 can be used as an ACPI C3 state
2482// 4= processor core C3 can be used as an ACPI C2 state
2483// if Invariant APIC Timer detected, else not used as ACPI C state
2484// 5= processor core C3 can be used as an ACPI C2 state
2485// if Invariant APIC Timer detected, else APIC C3 state
2486// 6= processor core C3 can be used as an ACPI C4 state
2487int c3_enabled = 3;
2488
2489// Desired state for the processor core C3 state included in the _CST as an
2490// ACPI C4 state.
2491// 1= processor core C3 can be used as an ACPI C4 state
2492// 0= processor core C3 cannot be used as an ACPI C4 state
2493int c4_enabled = 0;
2494
2495// Desired state for the processor core C6 state included in the _CST as an
2496// ACPI C3 state.
2497// 1= processor core C6 can be used as an ACPI C3 state
2498// 0= processor core C6 cannot be used as an ACPI C3 state
2499int c6_enabled = 0;
2500
2501// Desired state for the processor core C7 state included in the _CST as an
2502// ACPI C3 state.
2503// 1= processor core C7 can be used as an ACPI C7 state
2504// 0= processor core C7 cannot be used as an ACPI C7 state
2505int c7_enabled = 0;
2506
2507{
2508bool tmpval;
2509
2510
2511if (getBoolForKey(kEnableC2State, &tmpval, &bootInfo->bootConfig))
2512{
2513c2_enabled = tmpval;
2514}
2515
2516if (!getIntForKey("C3StateOption", &c3_enabled, &bootInfo->bootConfig))
2517{
2518c3_enabled = (getBoolForKey(kEnableC3State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 3 : 0;
2519}
2520if (c3_enabled == 6)
2521{
2522c4_enabled = 1;
2523}
2524else
2525{
2526c4_enabled = (getBoolForKey(kEnableC4State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
2527}
2528c6_enabled = (getBoolForKey(kEnableC6State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
2529c7_enabled = (getBoolForKey(kEnableC7State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
2530}
2531
2532cpu->pkg_mwait_cstates.num_cstates = 0;
2533{
2534{
2535cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C1]];
2536cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C1]];
2537cpu->pkg_mwait_cstates.num_cstates++;
2538}
2539if (((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled)) && ((c3_enabled == 2) ||
2540 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
2541{
2542cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
2543cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C2]];
2544cpu->pkg_mwait_cstates.num_cstates++;
2545}
2546if (cpu->core_c4_supported && c4_enabled)
2547{
2548
2549cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C4]];
2550cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C4]];
2551cpu->pkg_mwait_cstates.num_cstates++;
2552
2553}
2554else
2555{
2556
2557if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2558 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2559{
2560cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2561cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2562cpu->pkg_mwait_cstates.num_cstates++;
2563}
2564}
2565
2566
2567if (cpu->core_c6_supported && c6_enabled)
2568{
2569cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C6]];
2570cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C6]];
2571cpu->pkg_mwait_cstates.num_cstates++;
2572}
2573if (cpu->core_c7_supported && c7_enabled)
2574{
2575cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C7]];
2576cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C7]];
2577cpu->pkg_mwait_cstates.num_cstates++;
2578}
2579}
2580
2581cpu->pkg_io_cstates.num_cstates = 0;
2582{
2583{
2584cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C1]];
2585cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C1]];
2586cpu->pkg_io_cstates.num_cstates++;
2587}
2588if ((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled || (c3_enabled == 2) ||
2589 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
2590{
2591cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
2592cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C2]];
2593cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2594cpu->pkg_io_cstates.num_cstates++;
2595}
2596if (cpu->core_c4_supported && c4_enabled)
2597{
2598
2599cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C4]];
2600cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C4]];
2601cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2602cpu->pkg_io_cstates.num_cstates++;
2603
2604}
2605else
2606{
2607
2608if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2609 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2610{
2611cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2612cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2613cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2614cpu->pkg_io_cstates.num_cstates++;
2615}
2616}
2617
2618if (cpu->core_c6_supported && c6_enabled)
2619{
2620cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C6]];
2621cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C6]];
2622cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2623cpu->pkg_io_cstates.num_cstates++;
2624}
2625if (cpu->core_c7_supported && c7_enabled)
2626{
2627cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C7]];
2628cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C7]];
2629cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2630cpu->pkg_io_cstates.num_cstates++;
2631}
2632}
2633}
2634
2635return (1);
2636}
2637
2638#if BUILD_ACPI_TSS
2639//-----------------------------------------------------------------------------
2640static U32 BuildTstateInfo(CPU_DETAILS * cpu)
2641{
2642 // Coarse grained clock modulation is available if cpuid.6.eax[5] = 0
2643 // Max of 8 T-states using 12.5% increments
2644 static const TSTATE tstate_coarse_grain [] = {
2645 {100,0,0,0x00,0},
2646 { 88,0,0,0x1e,0},
2647 { 75,0,0,0x1c,0},
2648 { 63,0,0,0x1a,0},
2649 { 50,0,0,0x18,0},
2650 { 38,0,0,0x16,0},
2651 { 25,0,0,0x14,0},
2652 { 13,0,0,0x12,0},
2653 };
2654
2655 // Fine grained clock modulation is available if cpuid.6.eax[5] = 1
2656 // Max of 15 T-states using 6.25% increments
2657 static const TSTATE tstate_fine_grain [] = {
2658 {100,0,0,0x00,0},
2659 { 94,0,0,0x1f,0},
2660 { 88,0,0,0x1e,0},
2661 { 81,0,0,0x1d,0},
2662 { 75,0,0,0x1c,0},
2663 { 69,0,0,0x1b,0},
2664 { 63,0,0,0x1a,0},
2665 { 56,0,0,0x19,0},
2666 { 50,0,0,0x18,0},
2667 { 44,0,0,0x17,0},
2668 { 38,0,0,0x16,0},
2669 { 31,0,0,0x15,0},
2670 { 25,0,0,0x14,0},
2671 { 19,0,0,0x13,0},
2672 { 13,0,0,0x12,0},
2673 };
2674
2675 // Build T-state table info based on verified options
2676 U32 num_cpu;
2677 const TSTATE * tstate;
2678 U32 num_tstates;
2679
2680 for (num_cpu = 0; num_cpu < cpu_map_count; num_cpu ++)
2681 {
2682 // Check if fine or coarse grained clock modulation is available
2683 if (Platform->CPU.fine_grain_clock_mod)
2684 {
2685 // Fine grain thermal throttling is available
2686 num_tstates = 15;
2687 tstate = tstate_fine_grain;
2688 }
2689 else
2690 {
2691 // Coarse grain thermal throttling is available
2692 num_tstates = 8;
2693 tstate = tstate_coarse_grain;
2694 }
2695
2696 cpu->pkg_tstates.num_tstates = num_tstates;
2697 {
2698 U32 index;
2699 for (index = 0; index < num_tstates; index++)
2700 {
2701 cpu->pkg_tstates.tstate[index] = tstate[index];
2702 cpu->pkg_tstates.tstate[index].power = 1000 * (compute_tdp(cpu) * (num_tstates - index)) / num_tstates;
2703 }
2704 }
2705
2706
2707 }
2708 return (1);
2709}
2710#endif
2711
2712static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, bool enable_cstates, bool enable_pstates, bool enable_tstates )
2713{
2714DBG("Processing SSDT\n");
2715
2716ACPI_TABLE_MADT * madt_file = (void*)0ul;
2717ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
2718U8 new_table_index = 0;
2719bool oem_apic=false;
2720
2721if (Platform->CPU.Vendor != 0x756E6547) {
2722verbose ("Not an Intel platform: SSDT will not be generated !!!\n");
2723return(0);
2724}
2725
2726if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {
2727verbose ("Unsupported CPU: SSDT will not be generated !!!\n");
2728return(0);
2729}
2730
2731if (dsdt == (void *)0ul) {
2732verbose ("DSDT not found: SSDT will not be generated !!!\n");
2733return (0);
2734}
2735
2736{
2737bool tmpval;
2738oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
2739}
2740
2741// Get an empty space in the new_talbe_list (true = allow reserved space)
2742U8 empty = get_0ul_index_in_list(new_table_list, true);
2743
2744// Check to confirm space is available
2745if (empty == ACPI_TABLE_LIST_FULL)
2746{
2747printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n ");
2748printf(" please increase the RESERVED_AERA\n");
2749return(0);
2750}
2751
2752if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
2753{
2754if (oem_apic == false)
2755{
2756MadtPointer = (ACPI_TABLE_MADT *)madt_file;
2757//new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list // note: for now we don't patch this table
2758}
2759
2760} else
2761MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
2762
2763// Create buffer for SSDT
2764U8 memory_for_ssdt[20 * 1024];
2765
2766// Build the SSDT
2767if ( (BuildSsdt(MadtPointer, dsdt, memory_for_ssdt, sizeof(memory_for_ssdt), enable_cstates, enable_pstates, enable_tstates)) == 0)
2768{
2769printf("Error: Failed to build SSDT table\n");
2770return (0);
2771}
2772
2773// insert SSDT in the new_table_list
2774{
2775// Create pointer to SSDT just built in the stack buffer
2776ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
2777
2778// Reserved kernel memory for the ssdt table
2779ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
2780
2781if (!new_ssdt)
2782{
2783printf("Unable to allocate kernel memory for SSDT ");
2784return (0);
2785}
2786// Move the old stack buffer to kernel memory
2787memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
2788
2789// Add the new ssdt into an empty space of the new_table_list
2790new_table_list[empty] = (U32)new_ssdt;
2791}
2792
2793verbose ("SSDT table generated successfully\n");
2794return(1);
2795}
2796
2797//-----------------------------------------------------------------------------
2798static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
2799{
2800ACPI_SCOPE * scope = current;
2801current = scope + 1;
2802
2803scope->scopeOpcode = AML_SCOPE_OP;
2804scope->rootChar = AML_ROOT_PREFIX;
2805
2806if (aslCpuNamePath->seg_count == 1)
2807{
2808DUAL_NAME_PATH * dualNamePath = current;
2809current = dualNamePath + 1;
2810dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
2811dualNamePath->nameseg[0] = cpu_namespace;
2812dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
2813}
2814else
2815{
2816MULTI_NAME_PATH * multiNamePath = current;
2817current = multiNamePath + 1;
2818multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
2819// the nameseg count includes the root prefix and all other namesegs
2820multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
2821multiNamePath->nameseg[0] = cpu_namespace;
2822{
2823U32 i;
2824for (i=0; i<aslCpuNamePath->seg_count; i++)
2825multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
2826}
2827}
2828return (current);
2829}
2830//-----------------------------------------------------------------------------
2831static void * buildPDC(void * current)
2832{
2833ACPI_METHOD * pdc = current;
2834current = buildMethod(current, NAMESEG("_PDC"), 1);
2835
2836// CreateDWordField (Arg0, 0x08, CAPA)
2837current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2838current = buildOpCode(current, AML_ARG0_OP);
2839current = buildByteConst(current, 0x08);
2840current = buildNameSeg(current, NAMESEG("CAPA"));
2841
2842// Store (CAPA, TYPE)
2843current = buildOpCode(current, AML_STORE_OP);
2844current = buildNameSeg(current, NAMESEG("CAPA"));
2845current = buildNameSeg(current, NAMESEG("TYPE"));
2846
2847// CreateDWordField (Arg0, 0x00, REVS)
2848current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2849current = buildOpCode(current, AML_ARG0_OP);
2850current = buildByteConst(current, 0x00);
2851current = buildNameSeg(current, NAMESEG("REVS"));
2852
2853// CreateDWordField (Arg0, 0x04, SIZE)
2854current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2855current = buildOpCode(current, AML_ARG0_OP);
2856current = buildByteConst(current, 0x04);
2857current = buildNameSeg(current, NAMESEG("SIZE"));
2858
2859// Store(SizeOf(Arg0), Local0)
2860current = buildOpCode(current, AML_STORE_OP);
2861current = buildOpCode(current, AML_SIZEOF_OP);
2862current = buildOpCode(current, AML_ARG0_OP);
2863current = buildOpCode(current, AML_LOCAL0_OP);
2864
2865// Store(Subtract(Local0, 0x08),Local1)
2866current = buildOpCode(current, AML_STORE_OP);
2867current = buildOpCode(current, AML_SUBTRACT_OP);
2868current = buildOpCode(current, AML_LOCAL0_OP);
2869current = buildByteConst(current, 0x08);
2870current = buildOpCode(current, AML_ZERO_OP);
2871current = buildOpCode(current, AML_LOCAL1_OP);
2872
2873// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
2874current = buildOpCode(current, AML_EXT_OP_PREFIX);
2875current = buildOpCode(current, AML_CREATE_FIELD_OP);
2876current = buildOpCode(current, AML_ARG0_OP);
2877current = buildByteConst(current, 0x40);
2878current = buildOpCode(current, AML_MULTIPLY_OP);
2879current = buildOpCode(current, AML_LOCAL1_OP);
2880current = buildByteConst(current, 0x08);
2881current = buildOpCode(current, AML_ZERO_OP);
2882current = buildNameSeg(current, NAMESEG("TEMP"));
2883
2884// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
2885// Create STS0 as named buffer
2886current = buildNamePath(current, NAMESEG("STS0"));
2887{
2888ACPI_SMALL_BUFFER * buff = current;
2889current = buildSmallBuffer(current);
2890
2891// count of buffer elements
2892current = buildByteConst(current, 4);
2893
2894current = buildOpCode(current, AML_ZERO_OP);
2895current = buildOpCode(current, AML_ZERO_OP);
2896current = buildOpCode(current, AML_ZERO_OP);
2897current = buildOpCode(current, AML_ZERO_OP);
2898{
2899U32 length = (U8 *)current - (U8 *)buff;
2900buff->packageLength = (U8)length - 1;
2901}
2902}
2903
2904//Concatenate (STS0, TEMP, Local2)
2905current = buildOpCode(current, AML_CONCAT_OP);
2906current = buildNameSeg(current, NAMESEG("STS0"));
2907current = buildNameSeg(current, NAMESEG("TEMP"));
2908current = buildOpCode(current, AML_LOCAL2_OP);
2909
2910//_OSC (Buffer (0x10)
2911// {
2912// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2913// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2914// }, REVS, SIZE, Local2)
2915current = buildNameSeg(current, NAMESEG("_OSC"));
2916{
2917ACPI_SMALL_BUFFER * buff = current;
2918current = buildSmallBuffer(current);
2919
2920// count of buffer elements
2921current = buildByteConst(current, 0x10);
2922
2923current = buildOpCode(current, 0x16);
2924current = buildOpCode(current, 0xa6);
2925current = buildOpCode(current, 0x77);
2926current = buildOpCode(current, 0x40);
2927current = buildOpCode(current, 0x0c);
2928current = buildOpCode(current, 0x29);
2929current = buildOpCode(current, 0xbe);
2930current = buildOpCode(current, 0x47);
2931current = buildOpCode(current, 0x9e);
2932current = buildOpCode(current, 0xbd);
2933current = buildOpCode(current, 0xd8);
2934current = buildOpCode(current, 0x70);
2935current = buildOpCode(current, 0x58);
2936current = buildOpCode(current, 0x71);
2937current = buildOpCode(current, 0x39);
2938current = buildOpCode(current, 0x53);
2939{
2940U32 length = (U8 *)current - (U8 *)buff;
2941buff->packageLength = (U8)length - 1;
2942}
2943}
2944current = buildNameSeg(current, NAMESEG("REVS"));
2945current = buildNameSeg(current, NAMESEG("SIZE"));
2946current = buildOpCode(current, AML_LOCAL2_OP);
2947
2948// Update package length in PDC object
2949//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
2950setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
2951
2952return(current);
2953}
2954
2955//-----------------------------------------------------------------------------
2956static void * buildOSC(void * current)
2957{
2958//
2959//
2960ACPI_METHOD * osc = current;
2961current = buildMethod(current, NAMESEG("_OSC"), 4);
2962
2963// CreateDWordField (Arg3, 0x04, CAPA)
2964current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2965current = buildOpCode(current, AML_ARG3_OP);
2966current = buildByteConst(current, 0x04);
2967current = buildNameSeg(current, NAMESEG("CAPA"));
2968
2969// Store (CAPA, TYPE)
2970current = buildOpCode(current, AML_STORE_OP);
2971current = buildNameSeg(current, NAMESEG("CAPA"));
2972current = buildNameSeg(current, NAMESEG("TYPE"));
2973
2974// CreateDWordField (Arg3, 0x00, STS0)
2975current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2976current = buildOpCode(current, AML_ARG3_OP);
2977current = buildByteConst(current, 0x00);
2978current = buildNameSeg(current, NAMESEG("STS0"));
2979
2980// CreateDWordField (Arg3, 0x04, CAP0)
2981current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2982current = buildOpCode(current, AML_ARG3_OP);
2983current = buildByteConst(current, 0x04);
2984current = buildNameSeg(current, NAMESEG("CAP0"));
2985
2986// CreateDWordField (Arg0, 0x00, IID0)
2987current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2988current = buildOpCode(current, AML_ARG0_OP);
2989current = buildByteConst(current, 0x00);
2990current = buildNameSeg(current, NAMESEG("IID0"));
2991
2992// CreateDWordField (Arg0, 0x04, IID1)
2993current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2994current = buildOpCode(current, AML_ARG0_OP);
2995current = buildByteConst(current, 0x04);
2996current = buildNameSeg(current, NAMESEG("IID1"));
2997
2998// CreateDWordField (Arg0, 0x08, IID2)
2999current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3000