base/include/asm-arm/rtai_hal.h

Go to the documentation of this file.
00001 /* 00002 * ARTI -- RTAI-compatible Adeos-based Real-Time Interface. 00003 * Based on ARTI for x86 and RTHAL for ARM. 00004 * 00005 * Original RTAI/x86 layer implementation: 00006 * Copyright (c) 2000 Paolo Mantegazza (mantegazza@aero.polimi.it) 00007 * Copyright (c) 2000 Steve Papacharalambous (stevep@zentropix.com) 00008 * Copyright (c) 2000 Stuart Hughes 00009 * and others. 00010 * 00011 * RTAI/x86 rewrite over Adeos: 00012 * Copyright (c) 2002 Philippe Gerum (rpm@xenomai.org) 00013 * 00014 * Original RTAI/ARM RTHAL implementation: 00015 * Copyright (c) 2000 Pierre Cloutier (pcloutier@poseidoncontrols.com) 00016 * Copyright (c) 2001 Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de) 00017 * Copyright (c) 2002 Guennadi Liakhovetski DSA GmbH (gl@dsa-ac.de) 00018 * Copyright (c) 2002 Steve Papacharalambous (stevep@zentropix.com) 00019 * Copyright (c) 2002 Wolfgang Müller (wolfgang.mueller@dsa-ac.de) 00020 * Copyright (c) 2003 Bernard Haible, Marconi Communications 00021 * Copyright (c) 2003 Thomas Gleixner (tglx@linutronix.de) 00022 * Copyright (c) 2003 Philippe Gerum (rpm@xenomai.org) 00023 * 00024 * RTAI/ARM over Adeos rewrite: 00025 * Copyright (c) 2004-2005 Michael Neuhauser, Firmix Software GmbH (mike@firmix.at) 00026 * 00027 * 00028 * This program is free software; you can redistribute it and/or modify it under 00029 * the terms of the GNU General Public License as published by the Free Software 00030 * Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, USA; either version 2 of 00031 * the License, or (at your option) any later version. 00032 * 00033 * This program is distributed in the hope that it will be useful, but WITHOUT 00034 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00035 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 00036 * details. 00037 * 00038 * You should have received a copy of the GNU General Public License along with 00039 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00040 * Place - Suite 330, Boston, MA 02111-1307, USA. 00041 */ 00042 #ifndef _RTAI_ASM_ARM_HAL_H 00043 #define _RTAI_ASM_ARM_HAL_H 00044 00045 #include <rtai_types.h> 00046 #include <asm/rtai_vectors.h> 00047 #include <linux/bitops.h> 00048 #ifndef __KERNEL__ 00049 #include <strings.h> 00050 #endif 00051 00052 /* sanity checks */ 00053 #ifndef CONFIG_RTAI_ADEOS 00054 #error "Sorry, you have to use a Kernel patched with Adeos for ARM" 00055 #endif 00056 #ifdef CONFIG_SMP 00057 #error "Sorry, SMP is not supported on ARM" 00058 #endif 00059 00060 #define RTAI_NR_CPUS 1 00061 00062 /* no, we don't have a 8254 to emulate TSC (sub-arch has to provide TSC stuff!) */ 00063 #undef DECLR_8254_TSC_EMULATION 00064 00065 extern inline unsigned long 00066 ffnz(unsigned long word) 00067 { 00068 return ffs(word) - 1; 00069 } 00070 00071 extern inline unsigned long long 00072 rtai_ulldiv(unsigned long long ull, 00073 unsigned long uld, 00074 unsigned long *r) 00075 { 00076 unsigned long long q = ull / uld; 00077 *r = ull - q * uld; 00078 return q; 00079 } 00080 00081 extern inline long long 00082 rtai_llimd(long long ll, int mult, int div) 00083 { 00084 long long q; 00085 int r; 00086 00087 if (mult == div) 00088 return ll; 00089 00090 ll *= mult; 00091 q = ll / div; 00092 r = ll - q * div; 00093 00094 return (r + r) < div ? q : q + 1; 00095 } 00096 00097 extern inline int 00098 rtai_imuldiv(int i, int mult, int div) 00099 { 00100 long long ll = i; 00101 int q; 00102 int r; 00103 00104 if (mult == div) 00105 return i; 00106 00107 ll *= mult; 00108 q = ll / div; 00109 r = ll - (long long)q * div; 00110 00111 return (r + r) < div ? q : q + 1; 00112 } 00113 00114 /* get architecture specific things (using <asm/...> breaks 00115 * build-in-seperate-directory feature!) */ 00116 #include <asm-arm/arch/rtai_arch.h> 00117 00118 #define RTAI_CPU_FREQ RTAI_TSC_FREQ 00119 #define RTAI_CALIBRATED_CPU_FREQ RTAI_TSC_FREQ 00120 00121 #if defined(__KERNEL__) && !defined(__cplusplus) 00122 #include <linux/sched.h> 00123 #include <rtai_trace.h> 00124 #include <asm/rtai_sched.h> 00125 #include <asm/rtai_atomic.h> 00126 #include <asm/rtai_fpu.h> 00127 00128 #define RTAI_DOMAIN_ID 0x52544149 00129 #define RTAI_NR_SRQS 32 00130 00131 #define RTAI_TIME_LIMIT 0x7FFFFFFFFFFFFFFFLL 00132 00133 #define RTAI_IFLAG (7) 00134 00135 #define rtai_cpuid() adeos_processor_id() 00136 #define rtai_tskext(idx) ptd[idx] 00137 00138 /* Use these in hard real time code to achieve UP-atomicity. */ 00139 #define rtai_cli() adeos_stall_pipeline_from(&rtai_domain) 00140 #define rtai_sti() adeos_unstall_pipeline_from(&rtai_domain) 00141 #define rtai_save_flags_and_cli(x) ((x) = adeos_test_and_stall_pipeline_from(&rtai_domain)) 00142 #define rtai_restore_flags(x) adeos_restore_pipeline_from(&rtai_domain,(x)) 00143 #define rtai_save_flags(x) ((x) = adeos_test_pipeline_from(&rtai_domain)) 00144 00145 /* Use these when accessing the hardware. */ 00146 #define rtai_hw_disable() adeos_hw_cli() 00147 #define rtai_hw_enable() adeos_hw_sti() 00148 #define rtai_hw_lock(flags) adeos_hw_local_irq_save(flags) 00149 #define rtai_hw_unlock(flags) adeos_hw_local_irq_restore(flags) 00150 #define rtai_hw_flags(x) adeos_hw_local_irq_flags(flags) 00151 /* alternative names */ 00152 #define rtai_hw_cli() rtai_hw_disable() 00153 #define rtai_hw_sti() rtai_hw_enable() 00154 #define rtai_hw_save_flags_and_cli(f) rtai_hw_lock(f) 00155 #define rtai_hw_restore_flags(f) rtai_hw_unlock(f) 00156 #define rtai_hw_save_flags(f) rtai_hw_flags(f) 00157 00158 #define __adeos_pend_uncond(irq, cpuid) adeos_propagate_irq(irq) 00159 00160 struct calibration_data { 00161 unsigned long cpu_freq; /* TSC (i.e. rtai_rdtsc()) clock frequency, set in hal.c */ 00162 int latency; /* all other values are set by the scheduler, see there */ 00163 int setup_time_TIMER_CPUNIT; 00164 int setup_time_TIMER_UNIT; 00165 int timers_tol[RTAI_NR_CPUS]; 00166 }; 00167 extern struct calibration_data rtai_tunables; 00168 00169 struct rtai_switch_data { 00170 volatile unsigned long depth; 00171 volatile unsigned long oldflags; 00172 }; 00173 00174 /* x86 legacy type (needed because some general code still uses x86 specific stuff) */ 00175 struct apic_timer_setup_data { 00176 int mode; 00177 int count; 00178 }; 00179 00180 extern struct rt_times rt_times; 00181 extern struct rt_times rt_smp_times[RTAI_NR_CPUS]; 00182 extern volatile unsigned long rtai_cpu_realtime; 00183 extern struct rtai_switch_data rtai_linux_context[RTAI_NR_CPUS]; 00184 extern int rtai_adeos_ptdbase; 00185 extern adomain_t rtai_domain; 00186 00187 /* type of rt irq handler (general + timer) */ 00188 typedef void (*rt_irq_handler_t)(unsigned irq, void *cookie); 00189 typedef void (*rt_timer_irq_handler_t)(void); 00190 00191 #ifdef CONFIG_ADEOS_THREADS 00192 00193 /* rtai_get_current() is Adeos-specific. Since real-time interrupt 00194 handlers are called on behalf of the RTAI domain stack, we cannot 00195 infere the "current" Linux task address using a CPU-register. We must use the 00196 suspended Linux domain's stack pointer instead. */ 00197 extern inline struct task_struct * 00198 rtai_get_root_current(int cpuid) 00199 { 00200 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) 00201 return (struct task_struct *)(((u_long)adp_root->esp[cpuid]) & (~8191UL)); 00202 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ 00203 return ((struct thread_info *)(((u_long)adp_root->esp[cpuid]) & (~((THREAD_SIZE)-1))))->task; 00204 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */ 00205 } 00206 00207 #else /* !CONFIG_ADEOS_THREADS */ 00208 00209 extern inline struct task_struct * 00210 rtai_get_root_current(int cpuid) 00211 { 00212 return current; 00213 } 00214 00215 #endif /* CONFIG_ADEOS_THREADS */ 00216 00217 /* following macros only valid for UP */ 00218 00219 #ifndef CONFIG_SMP 00220 00221 #define rt_spin_lock(lock) (void)(lock) /* Not "unused variable". */ 00222 #define rt_spin_unlock(lock) do { /* nop */ } while (0) 00223 #define rt_spin_lock_irq(lock) do { (void)(lock); rtai_cli(); } while (0) 00224 #define rt_spin_unlock_irq(lock) rtai_sti() 00225 #define rt_spin_lock_irqsave(lock) ({ unsigned long flags; (void)(lock); rtai_save_flags_and_cli(flags); flags; }) 00226 #define rt_spin_unlock_irqrestore(flags, lock) rtai_restore_flags(flags) 00227 00228 #define rt_get_global_lock() rtai_cli() 00229 #define rt_release_global_lock() do { /* nop */ } while (0) 00230 00231 #define rt_global_cli() rtai_cli() 00232 #define rt_global_sti() rtai_sti() 00233 #define rt_global_save_flags_and_cli() ({ unsigned long flags; rtai_save_flags_and_cli(flags); flags; }) 00234 #define rt_global_restore_flags(flags) rtai_restore_flags(flags) 00235 #define rt_global_save_flags(flags) rtai_save_flags(*flags) 00236 00237 #endif /* !CONFIG_SMP */ 00238 00239 extern inline void 00240 rt_switch_to_real_time(int cpuid) 00241 { 00242 ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); 00243 TRACE_RTAI_SWITCHTO_RT(cpuid); 00244 if (!rtai_linux_context[cpuid].depth++) { 00245 rtai_linux_context[cpuid].oldflags = adeos_test_and_stall_pipeline_from(adp_root); 00246 __set_bit(cpuid, &rtai_cpu_realtime); 00247 } else { 00248 ADEOS_PARANOIA_ASSERT(test_bit(IPIPE_STALL_FLAG, &adp_root->cpudata[cpuid].status) != 0); 00249 } 00250 } 00251 00252 extern inline void 00253 rt_switch_to_linux(int cpuid) 00254 { 00255 ADEOS_PARANOIA_ASSERT(adeos_hw_irqs_disabled()); 00256 TRACE_RTAI_SWITCHTO_LINUX(cpuid); 00257 if (rtai_linux_context[cpuid].depth) { 00258 if (!--rtai_linux_context[cpuid].depth) { 00259 __clear_bit(cpuid, &rtai_cpu_realtime); 00260 adeos_restore_pipeline_nosync(adp_root, rtai_linux_context[cpuid].oldflags, cpuid); 00261 } 00262 } 00263 } 00264 00265 #define in_hrt_mode(cpuid) (test_bit(cpuid, &rtai_cpu_realtime)) 00266 00267 /* Private interface -- internal use only 00268 * ====================================== */ 00269 00270 extern unsigned long rtai_critical_enter(void (*synch)(void)); 00271 extern void rtai_critical_exit(unsigned long flags); 00272 extern void rtai_set_linux_task_priority(struct task_struct *task, 00273 int policy, int prio); 00274 00275 #endif /* __KERNEL__ && !__cplusplus */ 00276 00277 /* Public interface 00278 * ================ */ 00279 00280 #ifdef __KERNEL__ 00281 00282 #include <linux/kernel.h> 00283 00284 /* printk is safe to use with Adeos */ 00285 #define rt_printk printk 00286 #define rtai_print_to_screen printk 00287 00288 #ifdef __cplusplus 00289 extern "C" { 00290 #endif /* __cplusplus */ 00291 00292 extern int rt_request_irq(unsigned irq, rt_irq_handler_t handler, void *cookie, int retmode); 00293 extern int rt_release_irq(unsigned irq); 00294 extern void rt_set_irq_cookie(unsigned irq, void *cookie); 00295 extern unsigned rt_startup_irq(unsigned irq); 00296 extern void rt_shutdown_irq(unsigned irq); 00297 extern void rt_enable_irq(unsigned irq); 00298 extern void rt_disable_irq(unsigned irq); 00299 extern void rt_mask_and_ack_irq(unsigned irq); 00300 extern void rt_unmask_irq(unsigned irq); 00301 extern void rt_ack_irq(unsigned irq); 00302 extern int rt_request_linux_irq(unsigned irq, 00303 irqreturn_t (*handler)(int irq, void *dev_id, 00304 struct pt_regs *regs), 00305 char *name, void *dev_id); 00306 extern int rt_free_linux_irq(unsigned irq, void *dev_id); 00307 extern void rt_pend_linux_irq(unsigned irq); 00308 extern void rt_pend_linux_srq(unsigned srq); 00309 extern int rt_request_srq(unsigned label, void (*k_handler)(void), 00310 long long (*u_handler)(unsigned)); 00311 extern int rt_free_srq(unsigned srq); 00312 extern int rt_assign_irq_to_cpu(int irq, unsigned long cpus_mask); 00313 extern int rt_reset_irq_to_sym_mode(int irq); 00314 extern void rt_request_timer_cpuid(rt_timer_irq_handler_t handler, unsigned tick, int cpuid); 00315 extern int rt_request_timer(rt_timer_irq_handler_t handler, unsigned tick, int use_apic); 00316 extern void rt_free_timer(void); 00317 extern RT_TRAP_HANDLER rt_set_trap_handler(RT_TRAP_HANDLER handler); 00318 extern void rt_mount(void); 00319 extern void rt_umount(void); 00320 extern void (*rt_set_ihook(void (*hookfn)(int)))(int); 00321 00322 /* deprecated calls */ 00323 00324 extern inline int 00325 rt_request_global_irq(unsigned irq, void (*handler)(void)) 00326 { 00327 /* cast is okay because retmode is 0 (i.e. irq-handling doesn't use return 00328 * value of handler, so it does not need to have one) */ 00329 return rt_request_irq(irq, (rt_irq_handler_t)handler, NULL, 0); 00330 } 00331 00332 extern inline int 00333 rt_request_global_irq_ext(unsigned irq, void (*handler)(void), unsigned long cookie) 00334 { 00335 /* cast is okay because retmode is 0 (i.e. irq-handling doesn't use return 00336 * value of handler, so it does not need to have one) */ 00337 return rt_request_irq(irq, (rt_irq_handler_t)handler, (void *)cookie, 0); 00338 } 00339 00340 extern inline void 00341 rt_set_global_irq_ext(unsigned irq, int ext, unsigned long cookie) 00342 { 00343 rt_set_irq_cookie(irq, (void *)cookie); 00344 } 00345 00346 extern inline int 00347 rt_free_global_irq(unsigned irq) 00348 { 00349 return rt_release_irq(irq); 00350 } 00351 00352 #ifdef __cplusplus 00353 } 00354 #endif /* __cplusplus */ 00355 00356 /* include rtai_timer.h late (it might need something from above) 00357 * it has to provide: 00358 * - rtai_timer_irq_ack() 00359 * - rtai_rdtsc() 00360 * - void rt_set_timer_delay(int delay) 00361 */ 00362 #include <asm-arm/arch/rtai_timer.h> 00363 00364 #endif /* __KERNEL__ */ 00365 00366 #include <asm/rtai_oldnames.h> 00367 00368 #endif /* !_RTAI_ASM_ARM_HAL_H */

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