Rev 1618 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
120 | giacomo | 1 | /* Project: OSLib |
2 | * Description: The OS Construction Kit |
||
3 | * Date: 1.6.2000 |
||
4 | * Idea by: Luca Abeni & Gerardo Lamastra |
||
5 | * |
||
6 | * OSLib is an SO project aimed at developing a common, easy-to-use |
||
7 | * low-level infrastructure for developing OS kernels and Embedded |
||
8 | * Applications; it partially derives from the HARTIK project but it |
||
9 | * currently is independently developed. |
||
10 | * |
||
11 | * OSLib is distributed under GPL License, and some of its code has |
||
12 | * been derived from the Linux kernel source; also some important |
||
13 | * ideas come from studying the DJGPP go32 extender. |
||
14 | * |
||
15 | * We acknowledge the Linux Community, Free Software Foundation, |
||
16 | * D.J. Delorie and all the other developers who believe in the |
||
17 | * freedom of software and ideas. |
||
18 | * |
||
19 | * For legalese, check out the included GPL license. |
||
20 | */ |
||
21 | |||
22 | /* Advanced Timer |
||
23 | * Date: 8.4.2003 |
||
24 | * Author: Giacomo Guidi <giacomo@gandalf.sssup.it> |
||
25 | * |
||
26 | */ |
||
27 | |||
28 | #ifndef __ADVTIMER_H__ |
||
29 | #define __ADVTIMER_H__ |
||
30 | |||
31 | #include <ll/i386/defs.h> |
||
32 | BEGIN_DEF |
||
33 | |||
305 | giacomo | 34 | #include <ll/sys/ll/time.h> |
35 | |||
120 | giacomo | 36 | /* TSC */ |
37 | |||
38 | #define rdtsc(low,high) \ |
||
648 | mauro | 39 | __asm__ __volatile__("xorl %%eax,%%eax\n\t" \ |
40 | "cpuid\n\t" \ |
||
41 | "rdtsc\n\t" \ |
||
42 | : "=a" (low), "=d" (high) \ |
||
43 | :: "ebx", "ecx") |
||
120 | giacomo | 44 | |
45 | #define rdtscll(val) \ |
||
648 | mauro | 46 | __asm__ __volatile__("xorl %%eax,%%eax\n\t" \ |
47 | "cpuid\n\t" \ |
||
48 | "rdtsc\n\t" \ |
||
49 | : "=A" (val) \ |
||
50 | :: "ebx","ecx") |
||
120 | giacomo | 51 | |
330 | giacomo | 52 | #ifdef __O1000__ |
648 | mauro | 53 | #define ll_read_timespec ll_read_timespec_1000 |
330 | giacomo | 54 | #else |
648 | mauro | 55 | #ifdef __02000__ |
56 | #define ll_read_timespec ll_read_timespec_2000 |
||
57 | #else |
||
58 | #ifdef __O4000__ |
||
59 | #define ll_read_timespec ll_read_timespec_4000 |
||
60 | #else |
||
61 | #define ll_read_timespec ll_read_timespec_8000 |
||
62 | #endif |
||
63 | #endif |
||
330 | giacomo | 64 | #endif |
65 | |||
66 | //Low level time read function: Optimized for CPU < 1 GHz |
||
67 | extern __inline__ void ll_read_timespec_1000(struct timespec *tspec) |
||
68 | { |
||
652 | mauro | 69 | extern unsigned int clk_opt_1,clk_opt_2; |
70 | extern unsigned long long *ptr_init_tsc; |
||
653 | mauro | 71 | extern struct timespec init_time; |
330 | giacomo | 72 | |
652 | mauro | 73 | if (clk_opt_1 == 0) { |
74 | NULL_TIMESPEC(tspec); |
||
75 | return; |
||
76 | } |
||
330 | giacomo | 77 | |
652 | mauro | 78 | __asm__("rdtsc\n\t" |
79 | "subl (%%edi),%%eax\n\t" |
||
80 | "sbbl 4(%%edi),%%edx\n\t" |
||
81 | "divl %%ebx\n\t" |
||
82 | "movl %%eax,%%ebx\n\t" |
||
83 | "xorl %%eax,%%eax\n\t" |
||
84 | "divl %%ecx\n\t" |
||
85 | : "=a" (tspec->tv_nsec), "=b" (tspec->tv_sec) |
||
86 | : "D" (ptr_init_tsc) , "b" (clk_opt_1), "c" (clk_opt_2) |
||
87 | : "edx" ); |
||
88 | |||
89 | if (init_time.tv_sec != 0 || init_time.tv_nsec != 0) { |
||
90 | __asm__("divl %%ecx\n\t" |
||
91 | "addl %%ebx,%%eax\n\t" |
||
92 | :"=a" (tspec->tv_sec), "=d" (tspec->tv_nsec) |
||
93 | :"a" (init_time.tv_nsec+tspec->tv_nsec), "b" (tspec->tv_sec+init_time.tv_sec), "c" (1000000000), "d" (0)); |
||
94 | }; |
||
95 | |||
330 | giacomo | 96 | } |
97 | |||
98 | //Low level time read function: Optimized for CPU < 2 GHz |
||
99 | extern __inline__ void ll_read_timespec_2000(struct timespec *tspec) |
||
100 | { |
||
652 | mauro | 101 | extern unsigned int clk_opt_1,clk_opt_3; |
102 | extern unsigned long long *ptr_init_tsc; |
||
653 | mauro | 103 | extern struct timespec init_time; |
330 | giacomo | 104 | |
652 | mauro | 105 | if (clk_opt_1 == 0) { |
106 | NULL_TIMESPEC(tspec); |
||
107 | return; |
||
108 | } |
||
330 | giacomo | 109 | |
652 | mauro | 110 | __asm__("rdtsc\n\t" |
111 | "subl (%%edi),%%eax\n\t" |
||
112 | "sbbl 4(%%edi),%%edx\n\t" |
||
113 | "divl %%ebx\n\t" |
||
114 | "movl %%eax,%%ebx\n\t" |
||
115 | "xorl %%eax,%%eax\n\t" |
||
116 | "shrdl $1,%%edx,%%eax\n\t" |
||
117 | "shrl %%edx\n\t" |
||
118 | "divl %%ecx\n\t" |
||
119 | : "=a" (tspec->tv_nsec), "=b" (tspec->tv_sec) |
||
120 | : "D" (ptr_init_tsc) , "b" (clk_opt_1), "c" (clk_opt_3) |
||
121 | : "edx" ); |
||
122 | |||
123 | if (init_time.tv_sec != 0 || init_time.tv_nsec != 0) { |
||
124 | __asm__("divl %%ecx\n\t" |
||
125 | "addl %%ebx,%%eax\n\t" |
||
126 | :"=a" (tspec->tv_sec), "=d" (tspec->tv_nsec) |
||
127 | :"a" (init_time.tv_nsec+tspec->tv_nsec), "b" (tspec->tv_sec+init_time.tv_sec), "c" (1000000000), "d" (0)); |
||
128 | }; |
||
129 | |||
330 | giacomo | 130 | } |
131 | |||
132 | //Low level time read function: Optimized for CPU < 4 GHz |
||
133 | extern __inline__ void ll_read_timespec_4000(struct timespec *tspec) |
||
134 | { |
||
652 | mauro | 135 | extern unsigned int clk_opt_1,clk_opt_4; |
136 | extern unsigned long long *ptr_init_tsc; |
||
653 | mauro | 137 | extern struct timespec init_time; |
330 | giacomo | 138 | |
652 | mauro | 139 | if (clk_opt_1 == 0) { |
140 | NULL_TIMESPEC(tspec); |
||
141 | return; |
||
142 | } |
||
330 | giacomo | 143 | |
652 | mauro | 144 | __asm__("rdtsc\n\t" |
145 | "subl (%%edi),%%eax\n\t" |
||
146 | "sbbl 4(%%edi),%%edx\n\t" |
||
147 | "divl %%ebx\n\t" |
||
148 | "movl %%eax,%%ebx\n\t" |
||
149 | "xorl %%eax,%%eax\n\t" |
||
150 | "shrdl $2,%%edx,%%eax\n\t" |
||
151 | "shrl $2,%%edx\n\t" |
||
152 | "divl %%ecx\n\t" |
||
153 | : "=a" (tspec->tv_nsec), "=b" (tspec->tv_sec) |
||
154 | : "D" (ptr_init_tsc) , "b" (clk_opt_1), "c" (clk_opt_4) |
||
155 | : "edx" ); |
||
156 | |||
157 | if (init_time.tv_sec != 0 || init_time.tv_nsec != 0) { |
||
158 | __asm__("divl %%ecx\n\t" |
||
159 | "addl %%ebx,%%eax\n\t" |
||
160 | :"=a" (tspec->tv_sec), "=d" (tspec->tv_nsec) |
||
161 | :"a" (init_time.tv_nsec+tspec->tv_nsec), "b" (tspec->tv_sec+init_time.tv_sec), "c" (1000000000), "d" (0)); |
||
162 | }; |
||
163 | |||
330 | giacomo | 164 | } |
165 | |||
305 | giacomo | 166 | //Low level time read function |
336 | giacomo | 167 | extern __inline__ void ll_read_timespec_8000(struct timespec *tspec) |
305 | giacomo | 168 | { |
648 | mauro | 169 | extern unsigned int clk_opt_0,clk_opt_5; |
170 | extern unsigned long long *ptr_init_tsc; |
||
171 | extern struct timespec init_time; |
||
172 | |||
173 | if (clk_opt_0 == 0) { |
||
174 | NULL_TIMESPEC(tspec); |
||
175 | return; |
||
176 | } |
||
305 | giacomo | 177 | |
648 | mauro | 178 | __asm__("rdtsc\n\t" |
179 | "subl (%%edi),%%eax\n\t" |
||
180 | "sbbl 4(%%edi),%%edx\n\t" |
||
181 | "shrdl $1,%%edx,%%eax\n\t" |
||
182 | "shrl %%edx\n\t" |
||
183 | "divl %%ebx\n\t" |
||
184 | "movl %%eax,%%ebx\n\t" |
||
185 | "xorl %%eax,%%eax\n\t" |
||
186 | "shrdl $2,%%edx,%%eax\n\t" |
||
187 | "shrl $2,%%edx\n\t" |
||
188 | "divl %%ecx\n\t" |
||
189 | : "=b" (tspec->tv_sec), "=a" (tspec->tv_nsec) |
||
190 | : "D" (ptr_init_tsc), "b" (clk_opt_0), "c" (clk_opt_5) |
||
191 | : "edx"); |
||
192 | |||
193 | if (init_time.tv_sec != 0 || init_time.tv_nsec != 0) { |
||
194 | __asm__("divl %%ecx\n\t" |
||
195 | "addl %%ebx,%%eax\n\t" |
||
196 | :"=a" (tspec->tv_sec), "=d" (tspec->tv_nsec) |
||
652 | mauro | 197 | :"a" (init_time.tv_nsec+tspec->tv_nsec), "b" (tspec->tv_sec+init_time.tv_sec), "c" (1000000000), "d" (0)); |
648 | mauro | 198 | }; |
199 | |||
305 | giacomo | 200 | } |
201 | |||
299 | giacomo | 202 | #define rdmsr(msr,val1,val2) \ |
648 | mauro | 203 | __asm__ __volatile__("rdmsr" \ |
204 | : "=a" (val1), "=d" (val2) \ |
||
205 | : "c" (msr)) |
||
299 | giacomo | 206 | |
207 | #define wrmsr(msr,val1,val2) \ |
||
648 | mauro | 208 | __asm__ __volatile__("wrmsr" \ |
209 | : /* no outputs */ \ |
||
210 | : "c" (msr), "a" (val1), "d" (val2)) |
||
299 | giacomo | 211 | |
120 | giacomo | 212 | /* RTC */ |
213 | |||
214 | #define RTC_PORT(x) (0x70 + (x)) |
||
215 | |||
216 | #define CMOS_READ(addr,val) \ |
||
217 | { \ |
||
218 | outp(RTC_PORT(0),(addr)); \ |
||
219 | val = inp(RTC_PORT(1)); \ |
||
220 | } |
||
221 | |||
222 | #define CMOS_WRITE(addr,val) \ |
||
223 | { \ |
||
224 | outp(RTC_PORT(0),(addr)); \ |
||
225 | outp(RTC_PORT(1),(val)); \ |
||
226 | } |
||
227 | |||
228 | #define RTC_IRQ 8 |
||
229 | |||
131 | giacomo | 230 | void ll_init_advtimer(void); |
301 | giacomo | 231 | void ll_restore_adv(void); |
646 | mauro | 232 | void ll_scale_advtimer(unsigned int old_f, unsigned int new_f); |
131 | giacomo | 233 | |
120 | giacomo | 234 | END_DEF |
235 | #endif |