base/include/asm-ppc/rtai_legacy.h

Go to the documentation of this file.
00001 /* 00002 COPYRIGHT (C) 2000 Paolo Mantegazza (mantegazza@aero.polimi.it) 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public 00015 License along with this library; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00017 */ 00018 00019 00020 #ifndef _RTAI_ASM_PPC_RTAI_H_ 00021 #define _RTAI_ASM_PPC_RTAI_H_ 00022 00023 #include <rtai_types.h> 00024 00025 // These are truly PPC specific. 00026 #define LATENCY_DECR 2500 00027 #define SETUP_TIME_DECR 500 00028 00029 // CPU frequency calibration 00030 #define CPU_FREQ (tuned.cpu_freq) 00031 #define FREQ_DECR CPU_FREQ 00032 #define CALIBRATED_CPU_FREQ 0 // Use this if you know better than Linux! 00033 00034 // Do not be messed up by macros names below, is a trick for keeping i386 code. 00035 #define FREQ_8254 FREQ_DECR 00036 #define FREQ_APIC FREQ_DECR 00037 #define LATENCY_8254 3000 00038 #define SETUP_TIME_8254 500 00039 #define TIMER_8254_IRQ 0xFFFFFFFF 00040 00041 #define IFLAG 15 00042 00043 #define RTAI_NR_TRAPS 32 00044 00045 // These and the related vector are of no use, at the moment. 00046 #define RTAI_1_IPI 6 00047 #define RTAI_2_IPI 7 00048 #define RTAI_3_IPI 8 00049 #define RTAI_4_IPI 9 00050 00051 #define RTAI_1_VECTOR 0xD9 00052 #define RTAI_2_VECTOR 0xE1 00053 #define RTAI_3_VECTOR 0xE9 00054 #define RTAI_4_VECTOR 0xF1 00055 00056 #define RT_TIME_END 0x7FFFFFFFFFFFFFFFLL 00057 00058 #ifdef INLINE_MATH 00059 unsigned long long ullmul(unsigned long m0, unsigned long m1); 00060 unsigned long long ulldiv(unsigned long long ull, unsigned long uld, unsigned long *r); 00061 int imuldiv(int i, int mult, int div); 00062 unsigned long long llimd(unsigned long long ull, unsigned long mult, unsigned long div); 00063 #else /* !INLINE_MATH */ 00064 // One of the silly thing of 32 bits PPCs, no 64 bits result for 32 bits mul. 00065 static inline unsigned long long ullmul(unsigned long m0, unsigned long m1) 00066 { 00067 unsigned long long res; 00068 00069 __asm__ __volatile__ ("mulhwu %0, %1, %2" 00070 : "=r" (((unsigned long *)&res)[0]) : "%r" (m0), "r" (m1)); 00071 ((unsigned long *)&res)[1] = m0*m1; 00072 00073 return res; 00074 00075 } 00076 00077 // One of the silly thing of 32 bits PPCs, no 64 by 32 bits divide. 00078 static inline unsigned long long ulldiv(unsigned long long ull, unsigned long uld, unsigned long *r) 00079 { 00080 unsigned long long q, rf; 00081 unsigned long qh, rh, ql, qf; 00082 00083 q = 0; 00084 rf = (unsigned long long)(0xFFFFFFFF - (qf = 0xFFFFFFFF / uld) * uld) + 1ULL; 00085 00086 while (ull >= uld) { 00087 ((unsigned long *)&q)[0] += (qh = ((unsigned long *)&ull)[0] / uld); 00088 rh = ((unsigned long *)&ull)[0] - qh * uld; 00089 q += rh * (unsigned long long)qf + (ql = ((unsigned long *)&ull)[1] / uld); 00090 ull = rh * rf + (((unsigned long *)&ull)[1] - ql * uld); 00091 } 00092 00093 *r = ull; 00094 return q; 00095 } 00096 00097 static inline int imuldiv(int i, int mult, int div) 00098 { 00099 unsigned long q, r; 00100 00101 q = ulldiv(ullmul(i, mult), div, &r); 00102 00103 return (r + r) > div ? q + 1 : q; 00104 } 00105 00106 static inline unsigned long long llimd(unsigned long long ull, unsigned long mult, unsigned long div) 00107 { 00108 unsigned long long low; 00109 unsigned long q, r; 00110 00111 low = ullmul(((unsigned long *)&ull)[1], mult); 00112 q = ulldiv( ullmul(((unsigned long *)&ull)[0], mult) + ((unsigned long *)&low)[0], div, (unsigned long *)&low); 00113 low = ulldiv(low, div, &r); 00114 ((unsigned long *)&low)[0] += q; 00115 00116 return (r + r) > div ? low + 1 : low; 00117 } 00118 #endif /* INLINE_MATH */ 00119 00120 #ifdef __KERNEL__ 00121 00122 #ifndef __cplusplus 00123 #include <linux/types.h> 00124 #include <linux/rtc.h> /* to avoid warnings in time.h */ 00125 #include <asm/time.h> 00126 #include <linux/kernel.h> 00127 #include <linux/smp.h> 00128 #include <linux/irq.h> 00129 #include <asm/page.h> 00130 #include <asm/ptrace.h> 00131 #include <asm/hw_irq.h> 00132 #include <asm/processor.h> 00133 #include <asm/bitops.h> 00134 #include <asm/rtai_fpu.h> 00135 #include <asm/rtai_atomic.h> 00136 #endif /* !__cplusplus */ 00137 00138 // Write to parallel port if present 00139 #if defined(CONFIG_PPC) 00140 #define LPT_OUTB(v) do { } while (0) 00141 #else 00142 #define LPT_OUTB(v) do { outb(v,0x378); } while(0) 00143 #endif 00144 00145 struct apic_timer_setup_data { int mode, count; }; 00146 00147 struct desc_struct { void *fun; }; 00148 00149 extern unsigned volatile int *locked_cpus; 00150 00151 extern void send_ipi_shorthand(unsigned int shorthand, int irq); 00152 extern void send_ipi_logical(unsigned long dest, int irq); 00153 #define rt_assign_irq_to_cpu(irq, cpu) 00154 #define rt_reset_irq_to_sym_mode(irq) 00155 extern int rt_request_global_irq(unsigned int irq, void (*handler)(unsigned int irq)); 00156 extern int rt_request_global_irq_arg(unsigned int irq, 00157 int (*handler)(int,void *,struct pt_regs *), 00158 unsigned long flags,const char *dev,void *dev_id); 00159 extern int rt_request_global_irq_ext(unsigned int irq, 00160 int (*handler)(unsigned int irq, unsigned long handler), 00161 unsigned long data); 00162 extern void rt_set_global_irq_ext(unsigned int irq, int ext, unsigned long data); 00163 extern int rt_free_global_irq(unsigned int irq); 00164 extern void rt_ack_irq(unsigned int irq); 00165 extern void rt_mask_and_ack_irq(unsigned int irq); 00166 extern void rt_unmask_irq(unsigned int irq); 00167 extern unsigned int rt_startup_irq(unsigned int irq); 00168 extern void rt_shutdown_irq(unsigned int irq); 00169 extern void rt_enable_irq(unsigned int irq); 00170 extern void rt_disable_irq(unsigned int irq); 00171 extern int rt_request_linux_irq(unsigned int irq, 00172 void (*linux_handler)(int irq, void *dev_id, struct pt_regs *regs), 00173 char *linux_handler_id, void *dev_id); 00174 extern int rt_free_linux_irq(unsigned int irq, void *dev_id); 00175 extern void rt_pend_linux_irq(unsigned int irq); 00176 extern void rt_tick_linux_timer(void); 00177 extern struct desc_struct rt_set_full_intr_vect(unsigned int vector, int type, int dpl, void *handler); 00178 extern void rt_reset_full_intr_vect(unsigned int vector, struct desc_struct idt_element); 00179 #define rt_set_intr_handler(vector, handler) ((void *)0) 00180 #define rt_reset_intr_handler(vector, handler) 00181 extern int rt_request_srq(unsigned int label, void (*rtai_handler)(void), long long (*user_handler)(unsigned int whatever)); 00182 extern int rt_free_srq(unsigned int srq); 00183 extern void rt_pend_linux_srq(unsigned int srq); 00184 #define rt_request_cpu_own_irq(irq, handler) rt_request_global_irq((irq), (handler)) 00185 #define rt_free_cpu_own_irq(irq) rt_free_global_irq((irq)) 00186 extern void rt_request_timer(void (*handler)(void), unsigned int tick, int apic); 00187 extern void rt_free_timer(void); 00188 extern void rt_request_apic_timers(void (*handler)(void), struct apic_timer_setup_data *apic_timer_data); 00189 extern void rt_free_apic_timers(void); 00190 extern void rt_mount_rtai(void); 00191 extern void rt_umount_rtai(void); 00192 extern int rt_printk(const char *format, ...); 00193 extern int rtai_print_to_screen(const char *format, ...); 00194 extern void rt_switch_to_linux(int cpuid); 00195 extern void rt_switch_to_real_time(int cpuid); 00196 00197 #ifndef DEBUG_FLAGS 00198 #define debug_flags_set(ptr,a) 00199 #define debug_flags_check(ptr) 00200 #else 00201 void debug_flags_set(void *ptr,unsigned long flags); 00202 void debug_flags_check(void *ptr); 00203 #endif 00204 00205 static inline void hard_cli(void) 00206 { 00207 debug_flags_set(__builtin_return_address(0),0); 00208 __asm__ __volatile__ ( 00209 "\tmfmsr 0\n" 00210 //"\trlwinm 3,0,16+1,32-1,31\n" 00211 "\trlwinm 0,0,0,17,15\n" 00212 "\tmtmsr 0\n" 00213 : : : "r0" 00214 ); 00215 } 00216 00217 00218 static inline void hard_restore_flags(unsigned long flags) 00219 { 00220 debug_flags_set(__builtin_return_address(0),flags); 00221 __asm__ __volatile__ ( 00222 "\tmfmsr 0\n" 00223 "\trlwimi %0,0,0,17,15\n" 00224 "\tmtmsr %0\n" 00225 : : "r" (flags) : "r0" 00226 ); 00227 } 00228 00229 static inline void hard_sti(void) 00230 { 00231 debug_flags_set(__builtin_return_address(0),MSR_EE); 00232 __asm__ __volatile__ ( 00233 "\tmfmsr 0\n" 00234 "\tori 0,0,(1<<15)\n" 00235 "\tmtmsr 0\n" 00236 : : : "r0" 00237 ); 00238 } 00239 00240 static inline void __hard_save_flags(unsigned long *flags) 00241 { 00242 __asm__ __volatile__ ( 00243 "\tmfmsr %0\n" 00244 : "=r" (*flags) 00245 ); 00246 } 00247 00248 #define hard_save_flags(flags) do { __hard_save_flags(&(flags)); } while (0) 00249 #define hard_save_flags_and_cli(flags) do { __hard_save_flags(&(flags)); hard_cli(); } while (0) 00250 00251 #ifdef CONFIG_SMP 00252 00253 #define rt_spin_lock(lock) spin_lock((lock)) 00254 00255 #define rt_spin_unlock(lock) spin_unlock((lock)) 00256 00257 #define hard_cpu_id() hard_smp_processor_id() 00258 00259 static inline void rt_get_global_lock(void) 00260 { 00261 hard_cli(); 00262 if (!test_and_set_bit(hard_cpu_id(), locked_cpus)) { 00263 while (test_and_set_bit(31, locked_cpus)); 00264 } 00265 } 00266 00267 static inline void rt_release_global_lock(void) 00268 { 00269 hard_cli(); 00270 if (test_and_clear_bit(hard_cpu_id(), locked_cpus)) { 00271 clear_bit(31, locked_cpus); 00272 } 00273 } 00274 00275 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00276 // If NR_RT_CPUS > 8 RTAI must be changed as it cannot use APIC flat delivery 00277 // and the way processor[?].intr_flag is used must be changed (right now it 00278 // exploits the fact that the IF flags is at bit 16 so that bits 0-7 are used 00279 // to mark a cpu as Linux soft irq enabled/disabled. Bad but comfortable, it 00280 // will take a very very long time before I'll have available SMP with more 00281 // than 8 cpus. Right now they are only: 00282 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00283 #define NR_RT_CPUS 2 00284 00285 #else /* !CONFIG_SMP */ 00286 00287 #define rt_spin_lock(whatever) 00288 #define rt_spin_unlock(whatever) 00289 00290 #define rt_get_global_lock() hard_cli() 00291 #define rt_release_global_lock() 00292 00293 #define hard_cpu_id() 0 00294 00295 #define NR_RT_CPUS 1 00296 00297 #endif /* CONFIG_SMP */ 00298 00299 static inline void rt_spin_lock_irq(spinlock_t *lock) 00300 { 00301 hard_cli(); 00302 rt_spin_lock(lock); 00303 } 00304 00305 static inline void rt_spin_unlock_irq(spinlock_t *lock) 00306 { 00307 rt_spin_unlock(lock); 00308 hard_sti(); 00309 } 00310 00311 // Note that the spinlock calling convention below for irqsave/restore is 00312 // sligtly different from the one used in Linux. Done on purpose to get an 00313 // error if you use Linux spinlocks in real time applications as they do not 00314 // guaranty any protection because of the soft irq disable. Be careful and 00315 // sure to call the other spinlocks the right way, as they are compatible 00316 // with Linux. 00317 00318 static inline unsigned int rt_spin_lock_irqsave(spinlock_t *lock) 00319 { 00320 unsigned long flags; 00321 hard_save_flags_and_cli(flags); 00322 rt_spin_lock(lock); 00323 return flags; 00324 } 00325 00326 static inline void rt_spin_unlock_irqrestore(unsigned long flags, spinlock_t *lock) 00327 { 00328 rt_spin_unlock(lock); 00329 hard_restore_flags(flags); 00330 } 00331 00332 /* Global interrupts and flags control (simplified, and modified, version of */ 00333 /* similar global stuff in Linux irq.c). */ 00334 00335 static inline void rt_global_cli(void) 00336 { 00337 rt_get_global_lock(); 00338 } 00339 00340 static inline void rt_global_sti(void) 00341 { 00342 rt_release_global_lock(); 00343 hard_sti(); 00344 } 00345 00346 static inline int rt_global_save_flags_and_cli(void) 00347 { 00348 unsigned long flags; 00349 00350 hard_save_flags_and_cli(flags); 00351 if (!test_and_set_bit(hard_cpu_id(), locked_cpus)) { 00352 while (test_and_set_bit(31, locked_cpus)); 00353 return ((flags & (1 << IFLAG)) + 1); 00354 } else { 00355 return (flags & (1 << IFLAG)); 00356 } 00357 } 00358 00359 static inline void rt_global_save_flags(unsigned long *flags) 00360 { 00361 unsigned long hflags, rflags; 00362 00363 hard_save_flags_and_cli(hflags); 00364 hflags = hflags & (1 << IFLAG); 00365 rflags = hflags | !test_bit(hard_cpu_id(), locked_cpus); 00366 if (hflags) { 00367 hard_sti(); 00368 } 00369 *flags = rflags; 00370 } 00371 00372 static inline void rt_global_restore_flags(unsigned long flags) 00373 { 00374 switch (flags) { 00375 case (1 << IFLAG) | 1: rt_release_global_lock(); 00376 hard_sti(); 00377 break; 00378 case (1 << IFLAG) | 0: rt_get_global_lock(); 00379 hard_sti(); 00380 break; 00381 case (0 << IFLAG) | 1: rt_release_global_lock(); 00382 break; 00383 case (0 << IFLAG) | 0: rt_get_global_lock(); 00384 break; 00385 } 00386 } 00387 00388 static inline RT_TRAP_HANDLER rt_set_rtai_trap_handler(RT_TRAP_HANDLER handler) 00389 { 00390 return (RT_TRAP_HANDLER) 0; 00391 } 00392 00393 struct calibration_data { 00394 unsigned int cpu_freq; 00395 int latency; 00396 int setup_time_TIMER_CPUNIT; 00397 int setup_time_TIMER_UNIT; 00398 int timers_tol[NR_RT_CPUS]; 00399 }; 00400 00401 extern struct rt_times rt_times; 00402 extern struct rt_times rt_smp_times[NR_RT_CPUS]; 00403 extern struct calibration_data tuned; 00404 00405 #if 0 00406 static inline unsigned int get_dec(void) 00407 { 00408 return (mfspr(SPRN_DEC)); 00409 } 00410 00411 static inline void set_dec(unsigned int val) 00412 { 00413 mtspr(SPRN_DEC, val); 00414 } 00415 #endif 00416 #ifdef CONFIG_4xx 00417 static inline unsigned int get_dec_4xx(void) 00418 { 00419 return (mfspr(SPRN_PIT)); 00420 } 00421 00422 static inline void set_dec_4xx(unsigned int val) 00423 { 00424 mtspr(SPRN_PIT, val); 00425 } 00426 #endif 00427 00428 #if 0 00429 #define DECLR_8254_TSC_EMULATION 00430 #define TICK_8254_TSC_EMULATION 00431 #define SETUP_8254_TSC_EMULATION 00432 #define CLEAR_8254_TSC_EMULATION 00433 #endif 00434 00435 static inline unsigned long long rdtsc(void) 00436 { 00437 unsigned long long ts; 00438 unsigned long chk; 00439 // The code below is as suggested in Motorola reference manual for 32 bits PPCs. 00440 __asm__ __volatile__ ("1: mftbu %0; mftb %1; mftbu %2; cmpw %2,%0; bne 1b" 00441 : "=r" (((unsigned long *)&ts)[0]), "=r" (((unsigned long *)&ts)[1]), "=r" (chk) ); 00442 00443 return ts; 00444 } 00445 00446 #define RT_BUG() do{hard_cli();BUG();}while(0) 00447 00448 static inline void rt_set_decrementer_count(int delay) 00449 { 00450 // NOTE: delay MUST be 0 if a periodic timer is being used. 00451 if(!delay)delay = rt_times.intr_time - rdtsc(); 00452 00453 if(delay<1){RT_BUG();} 00454 #ifdef CONFIG_4xx 00455 set_dec_4xx(delay); 00456 #else 00457 set_dec(delay); 00458 #endif 00459 } 00460 00461 // We like keeping it as for i386. 00462 static inline int ffnz(long ul) 00463 { 00464 __asm__ __volatile__ ("cntlzw %0, %1" : "=r" (ul) : "r" (ul & (-ul))); 00465 00466 return 31 - ul; 00467 } 00468 00469 #define rt_set_timer_delay(x) rt_set_decrementer_count(x) 00470 00471 #endif /* __KERNEL__ */ 00472 00473 #define RTAI_DEFAULT_TICK 200000 00474 #define RTAI_DEFAULT_STACKSZ 2000 00475 00476 #endif /* !_RTAI_ASM_PPC_RTAI_H_ */

Generated on Thu Nov 20 11:49:48 2008 for RTAI API by doxygen 1.3.8