Main Page   File List  

apic.h

00001 #ifndef __L4_UTIL_APIC_H
00002 #define __L4_UTIL_APIC_H
00003 
00004 /*
00005  * Local APIC programming library
00006  *
00007  * For documentation, see
00008  *
00009  * "Intel Architecture Software Developer's Manual", Volume 3, chapter 7.5:
00010  * "Advanced Programmable Interrupt Controller (APIC)"
00011  *
00012  * Local APIC is present since
00013  * - INTEL P6 (PPro)
00014  * - AMD K7 (Athlon), Model 2
00015  *
00016  * In non-SMP-boards, local APIC is disabled, but
00017  * can be activated by writing to a MSR register.
00018  * For using APIC see packets cpufreq and l4rtl.
00019  *
00020  * See linux/include/asm-i386/i82489.h for further details.
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 /* prototypes */
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 /* write APIC register */
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 /* read APIC register */
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 /* disable LINT0 */
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 /* enable LINT0 */
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 /* disable LINT1 */
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 /* enable LINT1 */
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 /* write APIC timer register */
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 /* read APIC timer register */
00180 L4_INLINE unsigned long
00181 apic_timer_read(void)
00182 {
00183   return apic_read(APIC_TMCCT);
00184 }
00185 
00186 
00187 /* disable IRQ when APIC timer passes 0 */
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 /* enable IRQ when APIC timer passes 0 */
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 /* set vector of APIC timer irq */
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 /* disable IRQ when performance counter passes 0 */
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 /* enable IRQ when performance counter passes 0 */
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 /* set vector of performance counter irq */
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 /* activate APIC by writing to appropriate MSR */
00280 L4_INLINE void
00281 apic_activate_by_msr(void)
00282 {
00283   unsigned long low;
00284   unsigned long high;
00285     
00286   /* rdmsr */
00287   asm volatile(".byte 0xf; .byte 0x32\n"
00288                :"=a" (low),
00289                 "=d" (high)
00290                :"c" (APIC_BASE_MSR)
00291                );
00292 
00293   low |= 0x800;                         /* activate APIC */
00294   low &= 0x00000fff;
00295   low |= (APIC_PHYS_BASE & 0xfffff000); /* set address */
00296   
00297   /* wrmsr */
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 /* deactivate APIC by writing to appropriate MSR */
00308 L4_INLINE void
00309 apic_deactivate_by_msr(void)
00310 {
00311   unsigned long low;
00312   unsigned long high;
00313     
00314   /* rdmsr */
00315   asm volatile(".byte 0xf; .byte 0x32\n"
00316                :"=a" (low),
00317                 "=d" (high)
00318                :"c" (APIC_BASE_MSR)
00319                );
00320 
00321   low  &= 0xfffff7ff;                    /* deactivate APIC */
00322     
00323   /* wrmsr */
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 /* read memory mapped address of apic */
00334 L4_INLINE unsigned long
00335 apic_read_phys_address(void)
00336 {
00337   unsigned long low;
00338   unsigned long high;
00339 
00340   /* rdmsr */
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 /* test if APIC present */
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);          /* enable APIC */
00375   tmp_val &= ~(1<<9);         /* enable Focus Processor Checking */
00376   tmp_val |= 0xff;            /* Set spurious IRQ vector to 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 /* __L4_UTIL_APIC_H */

L4 Utilities, part of DROPS  © 2000-2003