00001 #ifndef __L4_UTIL_APIC_H
00002 #define __L4_UTIL_APIC_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define APIC_PHYS_BASE 0xFEE00000
00024 #define APIC_MAP_BASE 0xA0200000
00025 #define APIC_BASE_MSR 0x1b
00026
00027 #define APIC_ID 0x20
00028 #define GET_APIC_ID(x) (((x)>>24)&0x0F)
00029 #define APIC_LVR 0x30
00030 #define GET_APIC_VERSION(x) ((x)&0xFF)
00031 #define APIC_TASKPRI 0x80
00032 #define APIC_TPRI_MASK 0xFF
00033 #define APIC_EOI 0xB0
00034 #define APIC_LDR 0xD0
00035 #define APIC_LDR_MASK (0xFF<<24)
00036 #define APIC_DFR 0xE0
00037 #define SET_APIC_DFR(x) ((x)<<28)
00038 #define APIC_SPIV 0xF0
00039 #define APIC_LVTT 0x320
00040 #define APIC_LVTPC 0x340
00041 #define APIC_LVT0 0x350
00042 #define SET_APIC_TIMER_BASE(x) (((x)<<18))
00043 #define APIC_TIMER_BASE_DIV 0x2
00044 #define APIC_LVT1 0x360
00045 #define APIC_LVTERR 0x370
00046 #define APIC_TMICT 0x380
00047 #define APIC_TMCCT 0x390
00048 #define APIC_TDCR 0x3E0
00049
00050 #define APIC_LVT_MASKED (1<<16)
00051 #define APIC_LVT_TIMER_PERIODIC (1<<17)
00052 #define APIC_TDR_DIV_1 0xB
00053 #define APIC_TDR_DIV_2 0x0
00054 #define APIC_TDR_DIV_4 0x1
00055 #define APIC_TDR_DIV_8 0x2
00056 #define APIC_TDR_DIV_16 0x3
00057 #define APIC_TDR_DIV_32 0x8
00058 #define APIC_TDR_DIV_64 0x9
00059 #define APIC_TDR_DIV_128 0xA
00060
00061 #include <l4/sys/compiler.h>
00062 #include <l4/sys/types.h>
00063
00064 EXTERN_C_BEGIN
00065
00066
00067 extern unsigned long apic_map_base;
00068 extern unsigned long apic_timer_divisor;
00069
00070 extern unsigned long l4_scaler_apic_to_ms;
00071
00072 L4_CV void apic_show_registers(void);
00073 L4_CV int apic_check_working(void);
00074 L4_CV void apic_activate_by_io(void);
00075 L4_CV void apic_timer_set_divisor(int divisor);
00076
00077 L4_CV unsigned long l4_calibrate_apic(void);
00078
00079 EXTERN_C_END
00080
00081 L4_INLINE void apic_write(unsigned long reg, unsigned long v);
00082 L4_INLINE unsigned long apic_read(unsigned long reg);
00083 L4_INLINE void apic_activate_by_msr(void);
00084 L4_INLINE void apic_deactivate_by_msr(void);
00085 L4_INLINE unsigned long apic_read_phys_address(void);
00086 L4_INLINE int apic_test_present(void);
00087 L4_INLINE void apic_soft_enable(void);
00088 L4_INLINE void apic_init(unsigned long map_addr);
00089 L4_INLINE void apic_done(void);
00090 L4_INLINE void apic_irq_ack(void);
00091
00092 L4_INLINE void apic_lvt0_disable_irq(void);
00093 L4_INLINE void apic_lvt0_enable_irq(void);
00094 L4_INLINE void apic_lvt1_disable_irq(void);
00095 L4_INLINE void apic_lvt1_enable_irq(void);
00096
00097 L4_INLINE void apic_timer_write(unsigned long value);
00098 L4_INLINE unsigned long apic_timer_read(void);
00099 L4_INLINE void apic_timer_disable_irq(void);
00100 L4_INLINE void apic_timer_enable_irq(void);
00101 L4_INLINE void apic_timer_assign_irq(unsigned long vector);
00102 L4_INLINE void apic_timer_set_periodic(void);
00103 L4_INLINE void apic_timer_set_one_shot(void);
00104
00105 L4_INLINE void apic_perf_disable_irq(void);
00106 L4_INLINE void apic_perf_enable_irq(void);
00107 L4_INLINE void apic_perf_assign_irq(unsigned long vector);
00108
00109
00110
00111 L4_INLINE void
00112 apic_write(unsigned long reg, unsigned long v)
00113 {
00114 *((volatile unsigned long *)(apic_map_base+reg))=v;
00115 }
00116
00117
00118
00119 L4_INLINE unsigned long
00120 apic_read(unsigned long reg)
00121 {
00122 return *((volatile unsigned long *)(apic_map_base+reg));
00123 }
00124
00125
00126
00127 L4_INLINE void
00128 apic_lvt0_disable_irq(void)
00129 {
00130 unsigned long tmp_val;
00131 tmp_val = apic_read(APIC_LVT0);
00132 tmp_val |= APIC_LVT_MASKED;
00133 apic_write(APIC_LVT0, tmp_val);
00134 }
00135
00136
00137
00138 L4_INLINE void
00139 apic_lvt0_enable_irq(void)
00140 {
00141 unsigned long tmp_val;
00142 tmp_val = apic_read(APIC_LVT0);
00143 tmp_val &= ~(APIC_LVT_MASKED);
00144 apic_write(APIC_LVT0, tmp_val);
00145 }
00146
00147
00148
00149 L4_INLINE void
00150 apic_lvt1_disable_irq(void)
00151 {
00152 unsigned long tmp_val;
00153 tmp_val = apic_read(APIC_LVT1);
00154 tmp_val |= APIC_LVT_MASKED;
00155 apic_write(APIC_LVT1, tmp_val);
00156 }
00157
00158
00159
00160 L4_INLINE void
00161 apic_lvt1_enable_irq(void)
00162 {
00163 unsigned long tmp_val;
00164 tmp_val = apic_read(APIC_LVT1);
00165 tmp_val &= ~(APIC_LVT_MASKED);
00166 apic_write(APIC_LVT1, tmp_val);
00167 }
00168
00169
00170
00171 L4_INLINE void
00172 apic_timer_write(unsigned long value)
00173 {
00174 apic_read(APIC_TMICT);
00175 apic_write(APIC_TMICT,value);
00176 }
00177
00178
00179
00180 L4_INLINE unsigned long
00181 apic_timer_read(void)
00182 {
00183 return apic_read(APIC_TMCCT);
00184 }
00185
00186
00187
00188 L4_INLINE void
00189 apic_timer_disable_irq(void)
00190 {
00191 unsigned long tmp_val;
00192 tmp_val = apic_read(APIC_LVTT);
00193 tmp_val |= APIC_LVT_MASKED;
00194 apic_write(APIC_LVTT, tmp_val);
00195 }
00196
00197
00198
00199 L4_INLINE void
00200 apic_timer_enable_irq(void)
00201 {
00202 unsigned long tmp_val;
00203 tmp_val = apic_read(APIC_LVTT);
00204 tmp_val &= ~(APIC_LVT_MASKED);
00205 apic_write(APIC_LVTT, tmp_val);
00206 }
00207
00208
00209 L4_INLINE void
00210 apic_timer_set_periodic(void)
00211 {
00212 unsigned long tmp_val;
00213 tmp_val = apic_read(APIC_LVTT);
00214 tmp_val |= APIC_LVT_TIMER_PERIODIC;
00215 tmp_val |= APIC_LVT_MASKED;
00216 apic_write(APIC_LVTT, tmp_val);
00217 }
00218
00219
00220 L4_INLINE void
00221 apic_timer_set_one_shot(void)
00222 {
00223 unsigned long tmp_val;
00224 tmp_val = apic_read(APIC_LVTT);
00225 tmp_val &= ~APIC_LVT_TIMER_PERIODIC;
00226 tmp_val |= APIC_LVT_MASKED;
00227 apic_write(APIC_LVTT, tmp_val);
00228 }
00229
00230
00231
00232 L4_INLINE void
00233 apic_timer_assign_irq(unsigned long vector)
00234 {
00235 unsigned long tmp_val;
00236 tmp_val = apic_read(APIC_LVTT);
00237 tmp_val &= 0xffffff00;
00238 tmp_val |= vector;
00239 tmp_val |= APIC_LVT_MASKED;
00240 apic_write(APIC_LVTT, tmp_val);
00241 }
00242
00243
00244
00245 L4_INLINE void
00246 apic_perf_disable_irq(void)
00247 {
00248 unsigned long tmp_val;
00249 tmp_val = apic_read(APIC_LVTPC);
00250 tmp_val |= APIC_LVT_MASKED;
00251 apic_write(APIC_LVTPC, tmp_val);
00252 }
00253
00254
00255
00256 L4_INLINE void
00257 apic_perf_enable_irq(void)
00258 {
00259 unsigned long tmp_val;
00260 tmp_val = apic_read(APIC_LVTPC);
00261 tmp_val &= ~(APIC_LVT_MASKED);
00262 apic_write(APIC_LVTPC, tmp_val);
00263 }
00264
00265
00266
00267 L4_INLINE void
00268 apic_perf_assign_irq(unsigned long vector)
00269 {
00270 unsigned long tmp_val;
00271 tmp_val = apic_read(APIC_LVTPC);
00272 tmp_val &= 0xffffff00;
00273 tmp_val |= vector;
00274 tmp_val |= APIC_LVT_MASKED;
00275 apic_write(APIC_LVTPC, tmp_val);
00276 }
00277
00278
00279
00280 L4_INLINE void
00281 apic_activate_by_msr(void)
00282 {
00283 unsigned long low;
00284 unsigned long high;
00285
00286
00287 asm volatile(".byte 0xf; .byte 0x32\n"
00288 :"=a" (low),
00289 "=d" (high)
00290 :"c" (APIC_BASE_MSR)
00291 );
00292
00293 low |= 0x800;
00294 low &= 0x00000fff;
00295 low |= (APIC_PHYS_BASE & 0xfffff000);
00296
00297
00298 asm volatile(".byte 0xf; .byte 0x30\n"
00299 :
00300 :"c" (APIC_BASE_MSR),
00301 "a" (low),
00302 "d" (high)
00303 );
00304 }
00305
00306
00307
00308 L4_INLINE void
00309 apic_deactivate_by_msr(void)
00310 {
00311 unsigned long low;
00312 unsigned long high;
00313
00314
00315 asm volatile(".byte 0xf; .byte 0x32\n"
00316 :"=a" (low),
00317 "=d" (high)
00318 :"c" (APIC_BASE_MSR)
00319 );
00320
00321 low &= 0xfffff7ff;
00322
00323
00324 asm volatile(".byte 0xf; .byte 0x30\n"
00325 :
00326 :"c" (APIC_BASE_MSR),
00327 "a" (low),
00328 "d" (high)
00329 );
00330 }
00331
00332
00333
00334 L4_INLINE unsigned long
00335 apic_read_phys_address(void)
00336 {
00337 unsigned long low;
00338 unsigned long high;
00339
00340
00341 asm volatile(".byte 0xf; .byte 0x32\n"
00342 :"=a" (low),
00343 "=d" (high)
00344 :"c" (APIC_BASE_MSR)
00345 );
00346
00347 return (low &= 0xfffff000);
00348 }
00349
00350
00351
00352 L4_INLINE int
00353 apic_test_present(void)
00354 {
00355 unsigned int dummy;
00356 unsigned int capability;
00357
00358 asm volatile("pushl %%ebx ; cpuid ; popl %%ebx"
00359 : "=a" (dummy),
00360 "=c" (dummy),
00361 "=d" (capability)
00362 : "a" (0x00000001)
00363 : "cc");
00364
00365 return ((capability & 1<<9) !=0);
00366 }
00367
00368
00369 L4_INLINE void
00370 apic_soft_enable(void)
00371 {
00372 unsigned long tmp_val;
00373 tmp_val = apic_read(APIC_SPIV);
00374 tmp_val |= (1<<8);
00375 tmp_val &= ~(1<<9);
00376 tmp_val |= 0xff;
00377 apic_write(APIC_SPIV, tmp_val);
00378 }
00379
00380
00381 L4_INLINE void
00382 apic_init(unsigned long base_addr)
00383 {
00384 apic_map_base = base_addr;
00385 }
00386
00387
00388 L4_INLINE void
00389 apic_done(void)
00390 {
00391 apic_map_base = 0;
00392 }
00393
00394
00395 L4_INLINE void
00396 apic_irq_ack(void)
00397 {
00398 apic_read(APIC_SPIV);
00399 apic_write(APIC_EOI, 0);
00400 }
00401
00402
00403 #endif