Root/
Source at commit 1137 created 13 years 7 days ago. By meklort, Applies patch in issue #62 to trunk - Adds skip_partno support for multiboot bootloaders. | |
---|---|
1 | /*␊ |
2 | * Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>␊ |
3 | * AsereBLN: 2009: cleanup and bugfix␊ |
4 | */␊ |
5 | ␊ |
6 | #ifndef __LIBSAIO_CPU_H␊ |
7 | #define __LIBSAIO_CPU_H␊ |
8 | ␊ |
9 | #include "libsaio.h"␊ |
10 | ␊ |
11 | #define CPU_VIA_C3␉␉␉0x07␊ |
12 | #define CPU_VIA_C3_Ezra_T␉0x08␊ |
13 | ␊ |
14 | #define CPU_VIA_NANO␉␉0x0F␊ |
15 | ␊ |
16 | ␊ |
17 | ␊ |
18 | extern void scan_cpu(PlatformInfo_t *);␊ |
19 | ␊ |
20 | #define bit(n)␉␉␉(1UL << (n))␊ |
21 | #define bitmask(h,l)␉␉((bit(h)|(bit(h)-1)) & ~(bit(l)-1))␊ |
22 | #define bitfield(x,h,l)␉␉(((x) & bitmask(h,l)) >> l)␊ |
23 | ␊ |
24 | #define CPU_STRING_UNKNOWN␉␉"Unknown CPU Typ"␊ |
25 | ␊ |
26 | #define␉MSR_IA32_PERF_STATUS␉0x198␊ |
27 | #define MSR_IA32_PERF_CONTROL␉0x199␊ |
28 | #define MSR_IA32_EXT_CONFIG␉␉0x00EE␊ |
29 | #define MSR_IA32_EBL_CR_POWERON␉0x2A␊ |
30 | ␊ |
31 | #define MSR_FLEX_RATIO␉␉␉0x194␊ |
32 | #define␉MSR_PLATFORM_INFO␉␉0xCE␊ |
33 | ␊ |
34 | #define K8_FIDVID_STATUS␉␉0xC0010042␊ |
35 | #define K10_COFVID_STATUS␉␉0xC0010071␊ |
36 | ␊ |
37 | /* Centaur-Hauls/IDT defined MSRs. */␊ |
38 | #define MSR_IDT_FCR1␉␉␉0x00000107␊ |
39 | #define MSR_IDT_FCR2␉␉␉0x00000108␊ |
40 | #define MSR_IDT_FCR3␉␉␉0x00000109␊ |
41 | #define MSR_IDT_FCR4␉␉␉0x0000010a␊ |
42 | ␊ |
43 | #define MSR_IDT_MCR0␉␉␉0x00000110␊ |
44 | #define MSR_IDT_MCR1␉␉␉0x00000111␊ |
45 | #define MSR_IDT_MCR2␉␉␉0x00000112␊ |
46 | #define MSR_IDT_MCR3␉␉␉0x00000113␊ |
47 | #define MSR_IDT_MCR4␉␉␉0x00000114␊ |
48 | #define MSR_IDT_MCR5␉␉␉0x00000115␊ |
49 | #define MSR_IDT_MCR6␉␉␉0x00000116␊ |
50 | #define MSR_IDT_MCR7␉␉␉0x00000117␊ |
51 | #define MSR_IDT_MCR_CTRL␉␉0x00000120␊ |
52 | ␊ |
53 | /* VIA Nano defined MSTs */␊ |
54 | #define MSR_NANO_FCR1 0x1204 // This MSR contains control bits and family, model, etc.␊ |
55 | #define MSR_NANO_FCR2 0x1206 // This MSR contains part of the vendor string␊ |
56 | #define MSR_NANO_FCR3 0x1207 // This MSR contains part of the vendor string␊ |
57 | #define VIA_ALTERNATIVE_VENDOR_BIT (1 << 8) // This bit in MSR_IDT_FCR1 enables alternative vendor string␊ |
58 | ␊ |
59 | /* VIA Cyrix defined MSRs */␊ |
60 | #define MSR_VIA_FCR␉␉␉␉0x00001107␊ |
61 | #define MSR_VIA_LONGHAUL␉␉0x0000110a␊ |
62 | #define MSR_VIA_RNG␉␉␉␉0x0000110b␊ |
63 | #define MSR_VIA_BCR2␉␉␉0x00001147␊ |
64 | ␊ |
65 | ␊ |
66 | ␊ |
67 | #define DEFAULT_FSB␉␉100000 /* for now, hardcoding 100MHz for old CPUs */␊ |
68 | ␊ |
69 | // DFE: This constant comes from older xnu:␊ |
70 | #define CLKNUM␉␉␉1193182␉␉/* formerly 1193167 */␊ |
71 | ␊ |
72 | // DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM␊ |
73 | #define CALIBRATE_TIME_MSEC␉30␉␉/* 30 msecs */␊ |
74 | #define CALIBRATE_LATCH␉␉((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)␊ |
75 | ␊ |
76 | static inline uint64_t rdtsc64(void)␊ |
77 | {␊ |
78 | ␉uint64_t ret;␊ |
79 | ␉__asm__ volatile("rdtsc" : "=A" (ret));␊ |
80 | ␉return ret;␊ |
81 | }␊ |
82 | ␊ |
83 | static inline uint64_t rdmsr64(uint32_t msr)␊ |
84 | {␊ |
85 | uint64_t ret;␊ |
86 | __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));␊ |
87 | return ret;␊ |
88 | }␊ |
89 | ␊ |
90 | static inline void wrmsr64(uint32_t msr, uint64_t val)␊ |
91 | {␊ |
92 | ␉__asm__ volatile("wrmsr" : : "c" (msr), "A" (val));␊ |
93 | }␊ |
94 | ␊ |
95 | ␊ |
96 | static inline void intel_waitforsts(void) {␊ |
97 | ␉uint32_t inline_timeout = 100000;␊ |
98 | ␉while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; }␊ |
99 | }␊ |
100 | ␊ |
101 | ␊ |
102 | ␊ |
103 | ␊ |
104 | ␊ |
105 | static inline void do_cpuid(uint32_t selector, uint32_t *data)␊ |
106 | {␊ |
107 | ␉asm volatile ("cpuid"␊ |
108 | ␉␉␉␉ : "=a" (data[0]),␊ |
109 | ␉␉␉␉ "=b" (data[1]),␊ |
110 | ␉␉␉␉ "=c" (data[2]),␊ |
111 | ␉␉␉␉ "=d" (data[3])␊ |
112 | ␉␉␉␉ : "a" (selector));␊ |
113 | }␊ |
114 | ␊ |
115 | static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)␊ |
116 | {␊ |
117 | ␉asm volatile ("cpuid"␊ |
118 | ␉␉␉␉ : "=a" (data[0]),␊ |
119 | ␉␉␉␉ "=b" (data[1]),␊ |
120 | ␉␉␉␉ "=c" (data[2]),␊ |
121 | ␉␉␉␉ "=d" (data[3])␊ |
122 | ␉␉␉␉ : "a" (selector), "c" (selector2));␊ |
123 | }␊ |
124 | ␊ |
125 | // DFE: enable_PIT2 and disable_PIT2 come from older xnu␊ |
126 | ␊ |
127 | /*␊ |
128 | * Enable or disable timer 2.␊ |
129 | * Port 0x61 controls timer 2:␊ |
130 | * bit 0 gates the clock,␊ |
131 | * bit 1 gates output to speaker.␊ |
132 | */␊ |
133 | static inline void enable_PIT2(void)␊ |
134 | {␊ |
135 | /* Enable gate, disable speaker */␊ |
136 | __asm__ volatile(␊ |
137 | ␉␉␉␉␉ " inb $0x61,%%al \n\t"␊ |
138 | ␉␉␉␉␉ " and $0xFC,%%al \n\t" /* & ~0x03 */␊ |
139 | ␉␉␉␉␉ " or $1,%%al \n\t"␊ |
140 | ␉␉␉␉␉ " outb %%al,$0x61 \n\t"␊ |
141 | ␉␉␉␉␉ : : : "%al" );␊ |
142 | }␊ |
143 | ␊ |
144 | static inline void disable_PIT2(void)␊ |
145 | {␊ |
146 | /* Disable gate and output to speaker */␊ |
147 | __asm__ volatile(␊ |
148 | ␉␉␉␉␉ " inb $0x61,%%al \n\t"␊ |
149 | ␉␉␉␉␉ " and $0xFC,%%al \n\t"␉/* & ~0x03 */␊ |
150 | ␉␉␉␉␉ " outb %%al,$0x61 \n\t"␊ |
151 | ␉␉␉␉␉ : : : "%al" );␊ |
152 | }␊ |
153 | ␊ |
154 | // DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are␊ |
155 | // roughly based on Linux code␊ |
156 | ␊ |
157 | /* Set the 8254 channel 2 to mode 0 with the specified value.␊ |
158 | In mode 0, the counter will initially set its gate low when the␊ |
159 | timer expires. For this to be useful, you ought to set it high␊ |
160 | before calling this function. The enable_PIT2 function does this.␊ |
161 | */␊ |
162 | static inline void set_PIT2_mode0(uint16_t value)␊ |
163 | {␊ |
164 | __asm__ volatile(␊ |
165 | ␉␉␉␉␉ " movb $0xB0,%%al \n\t"␊ |
166 | ␉␉␉␉␉ " outb␉%%al,$0x43␉\n\t"␊ |
167 | ␉␉␉␉␉ " movb␉%%dl,%%al␉\n\t"␊ |
168 | ␉␉␉␉␉ " outb␉%%al,$0x42␉\n\t"␊ |
169 | ␉␉␉␉␉ " movb␉%%dh,%%al␉\n\t"␊ |
170 | ␉␉␉␉␉ " outb␉%%al,$0x42"␊ |
171 | ␉␉␉␉␉ : : "d"(value) /*: no clobber */ );␊ |
172 | }␊ |
173 | ␊ |
174 | /* Returns the number of times the loop ran before the PIT2 signaled */␊ |
175 | static inline unsigned long poll_PIT2_gate(void)␊ |
176 | {␊ |
177 | unsigned long count = 0;␊ |
178 | unsigned char nmi_sc_val;␊ |
179 | do {␊ |
180 | ++count;␊ |
181 | __asm__ volatile(␊ |
182 | ␉␉␉␉␉␉ "inb␉$0x61,%0"␊ |
183 | ␉␉␉␉␉␉ : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);␊ |
184 | } while( (nmi_sc_val & 0x20) == 0);␊ |
185 | return count;␊ |
186 | }␊ |
187 | ␊ |
188 | #endif /* !__LIBSAIO_CPU_H */␊ |
189 |