# rtai.h

    00001 /* 020222 asm-arm/rtai.h
    00002 Copyright (c) 2003, Thomas Gleixner, <tglx@linutronix.de)
    00003 COPYRIGHT (C) 2002 Guennadi Liakhovetski, DSA GmbH (gl@dsa-ac.de)
    00004 COPYRIGHT (C) 2002 Wolfgang Müller (wolfgang.mueller@dsa-ac.de)
    00005 Copyright (c) 2001 Alex Züpke, SYSGO RTS GmbH (azu@sysgo.de)
    00006
    00007 This program is free software; you can redistribute it and/or modify
    00008 it under the terms of version 2 of the GNU General Public License as
    00009 published by the Free Software Foundation.
    00010
    00011 This program is distributed in the hope that it will be useful,
    00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 GNU General Public License for more details.
    00015
    00016 You should have received a copy of the GNU General Public License
    00017 along with this program; if not, write to the Free Software
    00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00019 */
    00020 /*
    00021 --------------------------------------------------------------------------
    00022 Acknowledgements
    00023 - Paolo Mantegazza      (mantegazza@aero.polimi.it)
    00024         creator of RTAI
    00025 */
    00026
    00027 #ifndef _RTAI_ASM_ARM_RTAI_H
    00028 #define _RTAI_ASM_ARM_RTAI_H
    00029
    00030 #define rt_printk_srq           1
    00031
    00032 #define NR_GLOBAL_IRQS          NR_IRQS
    00033 #define NR_CPU_OWN_IRQS         NR_GLOBAL_IRQS
    00034
    00035 #define RTAI_1_IPI  -1 /* Just to make things compile */
    00036 #define RTAI_2_IPI  -1
    00037 #define RTAI_3_IPI  -1
    00038 #define RTAI_4_IPI  -1
    00039
    00040 // Do not be messed up by macros names below, is a trick for keeping i386 code.
    00041 #define FREQ_8254       FREQ_SYS_CLK
    00042 #define LATENCY_8254    LATENCY_MATCH_REG
    00043 #define SETUP_TIME_8254 SETUP_TIME_MATCH_REG
    00044 #define FREQ_APIC       FREQ_SYS_CLK
    00045
    00046 #define RT_TIME_END 0x7FFFFFFFFFFFFFFFLL
    00047
    00048 #define DECLR_8254_TSC_EMULATION
    00049 #define TICK_8254_TSC_EMULATION
    00050 #define SETUP_8254_TSC_EMULATION
    00051 #define CLEAR_8254_TSC_EMULATION
    00052
    00053 struct desc_struct { void *fun; };
    00054
    00055 /* not all ARM cores support 32bit x 32bit = 64bit native ... */
    00056 static inline unsigned long long ullmul(unsigned long m0, unsigned long m1)
    00057 {
    00058         unsigned long long res;
    00059
    00060         res = (unsigned long long)m0 * (unsigned long long)m1;
    00061
    00062         return res;
    00063 }
    00064
    00065 static inline unsigned long long ulldiv(unsigned long long ull, unsigned long uld, unsigned long *r)
    00066 {
    00067         unsigned long long q = ull/(unsigned long long) uld;
    00068
    00069         *r = (unsigned long) (ull - q * (unsigned long long) uld);
    00070
    00071         return q;
    00072 }
    00073
    00074 static inline int imuldiv(unsigned long i, unsigned long mult, unsigned long div)
    00075 {
    00076         unsigned long q , r;
    00077         unsigned long long m;
    00078
    00079         if ( mult == div )
    00080                 return i;
    00081
    00082         m = ((unsigned long long) i * (unsigned long long) mult);
    00083         q = (unsigned long) (m / (unsigned long long) div);
    00084         r = (unsigned long) (m - (unsigned long long) q * (unsigned long long) div );
    00085
    00086         return (r + r) < div ? q : q + 1;
    00087 }
    00088
    00089 static inline unsigned long long llimd(unsigned long long ull, unsigned long mult, unsigned long div)
    00090 {
    00091         unsigned long long low, high, q;
    00092         unsigned long r;
    00093
    00094         low  = ullmul(((unsigned long *)&ull)[0], mult);
    00095         high = ullmul(((unsigned long *)&ull)[1], mult);
    00096         q = ulldiv(high,div,&r) << 32;
    00097         high = ((unsigned long long) r) << 32;
    00098         q += ulldiv( high + low, div , &r);
    00099         return (r + r) < div ? q : q + 1;
    00100 }
    00101
    00102 #ifdef __KERNEL__
    00103
    00104 #ifndef __cplusplus
    00105 #include <asm/rtai_debug.h> /* Keep it first */
    00106 #include <rtai_types.h>
    00107 #include <asm/rtai_fpu.h>
    00108 #include <asm/rtai_atomic.h>
    00109 #include <linux/ptrace.h>
    00110 #include <linux/spinlock.h>
    00111 #include <asm/io.h>
    00112 #include <asm/ptrace.h>
    00113 #include <asm/irq.h>
    00114 #include <asm/system.h>
    00115 #include <asm/bitops.h>
    00116 #include <asm/proc/hard_system.h>
    00117 #endif /* __cplusplus */
    00118
    00119 extern unsigned volatile int *locked_cpus;
    00120
    00121 #ifndef CONFIG_SMP
    00122 extern unsigned long cpu_present_map;
    00123 #define smp_num_cpus 1
    00124 #endif
    00125
    00126 #ifndef CONFIG_RTAI_FPU_SUPPORT
    00127 #define enable_fpu()
    00128 #endif
    00129
    00130 #define hard_unlock_all(flags) hard_restore_flags((flags))
    00131 #define hard_save_flags_and_cli(x) hard_save_flags_cli((x))
    00132 #define IRQ_DESC irq_desc
    00133 extern struct rt_times rt_times;
    00134
    00135 typedef unsigned long long rtai_irq_mask_t;
    00136
    00137 extern void send_ipi_shorthand(unsigned int shorthand, unsigned int irq);
    00138 extern void send_ipi_logical(unsigned long dest, unsigned int irq);
    00139 #define rt_assign_irq_to_cpu(irq, cpu)
    00140 #define rt_reset_irq_to_sym_mode(irq)
    00141 extern int  rt_request_global_irq_ext(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), void *dev_id);
    00142 static inline int rt_request_global_irq(int irq, void (*handler)(void))
    00143 {
    00144         return rt_request_global_irq_ext(irq, (void (*)(int, void*, struct pt_regs*))handler, NULL);
    00145 }
    00146 extern int  rt_free_global_irq(unsigned int irq);
    00147 extern void rt_ack_irq(unsigned int irq);
    00148 extern void rt_mask_and_ack_irq(unsigned int irq);
    00149 extern void rt_unmask_irq(unsigned int irq);
    00150 extern unsigned int rt_startup_irq(unsigned int irq);
    00151 extern void rt_shutdown_irq(unsigned int irq);
    00152 extern void rt_enable_irq(unsigned int irq);
    00153 extern void rt_disable_irq(unsigned int irq);
    00154 extern int rt_request_linux_irq(unsigned int irq,
    00155         void (*linux_handler)(int irq, void *dev_id, struct pt_regs *regs),
    00156         char *linux_handler_id, void *dev_id);
    00157 extern int rt_free_linux_irq(unsigned int irq, void *dev_id);
    00158 extern void rt_tick_linux_timer(void);
    00159 extern struct desc_struct rt_set_full_intr_vect(unsigned int vector, int type, int dpl, void *handler);
    00160 extern void rt_reset_full_intr_vect(unsigned int vector, struct desc_struct idt_element);
    00161 #define rt_set_intr_handler(vector, handler) ((void *)0)
    00162 #define rt_reset_intr_handler(vector, handler)
    00163 extern int rt_request_srq(unsigned int label, void (*rtai_handler)(void), long long (*user_handler)(unsigned int whatever));
    00164 extern int rt_free_srq(unsigned int srq);
    00165 extern void rt_pend_linux_irq(unsigned int irq);
    00166 extern void rt_pend_linux_srq(unsigned int srq);
    00167 #define rt_request_cpu_own_irq(irq, handler) rt_request_global_irq((irq), (handler))
    00168 #define rt_free_cpu_own_irq(irq) rt_free_global_irq((irq))
    00169 extern void rt_request_timer(void (*handler)(void), unsigned int tick, int apic);
    00170 extern void rt_request_timer_cpuid(void (*handler)(void), unsigned int tick, int cpuid);
    00171 extern void rt_free_timer(void);
    00172 struct apic_timer_setup_data { int mode, count; };
    00173 //extern void rt_request_apic_timers(void (*handler)(void), struct apic_timer_setup_data *apic_timer_data);
    00174 //extern void rt_free_apic_timers(void);
    00175 extern void rt_mount_rtai(void);
    00176 extern void rt_umount_rtai(void);
    00177 extern int rt_printk(const char *format, ...);
    00178 extern int rtai_print_to_screen(const char *format, ...);
    00179 extern int rt_is_linux(void);
    00180
    00181 extern RT_TRAP_HANDLER rt_set_rtai_trap_handler(int trap, RT_TRAP_HANDLER handler);
    00182 extern void rt_free_rtai_trap_handler(int trap);
    00183
    00184 #define ffnz(ul) (ffs(ul)-1)
    00185
    00186 /* Timers are architecture dependent */
    00187 #include <asm-arm/arch/rtai_arch.h>
    00188 #include <asm-arm/arch/rtai_timer.h>
    00189
    00190 extern void asmlinkage up_task_sw(void *, void *, void *);
    00191 extern void rt_switch_to_linux(int cpuid);
    00192 extern void rt_switch_to_real_time(int cpuid);
    00193
    00194 #define rt_spin_lock(whatever)
    00195 #define rt_spin_unlock(whatever)
    00196
    00197 #define rt_get_global_lock()  hard_cli()
    00198 #define rt_release_global_lock()
    00199
    00200 #define hard_cpu_id()  0
    00201
    00202 #define NR_RT_CPUS  1
    00203
    00204 #define RTAI_NR_TRAPS 32
    00205
    00206 #define save_cr0_and_clts(x)
    00207
    00208 #define restore_cr0(x)
    00209
    00210 /* Macro to retrieve the link register */
    00211 #define getlr(x)                \
    00212         ({                      \
    00213         __asm__ __volatile__(   \
    00214         "mov    %0, lr"         \
    00215           : "=r" (x)            \
    00216           :                     \
    00217           : "memory");          \
    00218         })
    00219
    00220 #ifdef CONFIG_RTAI_FPU_SUPPORT
    00221 /* someone should implement FPU support if necessary ... */
    00222 extern void save_fpenv(long *fpu_reg);
    00223 extern void restore_fpenv(long *fpu_reg);
    00224 typedef struct arm_fpu_env { unsigned long fpu_reg[1]; } FPU_ENV;
    00225 #else
    00226 typedef struct arm_fpu_env { unsigned long fpu_reg[1]; } FPU_ENV;
    00227 #endif
    00228
    00229 static inline unsigned long hard_lock_all(void)
    00230 {
    00231         unsigned long flags;
    00232         hard_save_flags_and_cli(flags);
    00233         hard_clf(); /* we should block FIQs too */
    00234         return flags;
    00235 }
    00236
    00237 static inline void rt_spin_lock_irq(volatile spinlock_t *lock)
    00238 {
    00239         hard_cli();
    00240         rt_spin_lock(lock);
    00241 }
    00242
    00243 static inline void rt_spin_unlock_irq(volatile spinlock_t *lock)
    00244 {
    00245         rt_spin_unlock(lock);
    00246         hard_sti();
    00247 }
    00248
    00249 // Note that the spinlock calling convention below for irqsave/restore is
    00250 // sligtly different from the one used in Linux. Done on purpose to get an
    00251 // error if you use Linux spinlocks in real time applications as they do not
    00252 // guaranty any protection because of the soft irq disable. Be careful and
    00253 // sure to call the other spinlocks the right way, as they are compatible
    00254 // with Linux.
    00255
    00256 static inline unsigned int rt_spin_lock_irqsave(volatile spinlock_t *lock)
    00257 {
    00258         unsigned long flags;
    00259         hard_save_flags_and_cli(flags);
    00260         rt_spin_lock(lock);
    00261         return flags;
    00262 }
    00263
    00264 static inline void rt_spin_unlock_irqrestore(unsigned long flags, volatile spinlock_t *lock)
    00265 {
    00266         rt_spin_unlock(lock);
    00267         hard_restore_flags(flags);
    00268 }
    00269
    00270 /* Global interrupts and flags control (simplified, and modified, version of */
    00271 /* similar global stuff in Linux irq.c).                                     */
    00272
    00273 static inline void rt_global_cli(void)
    00274 {
    00275         rt_get_global_lock();
    00276 }
    00277
    00278 static inline void rt_global_sti(void)
    00279 {
    00280         rt_release_global_lock();
    00281         hard_sti();
    00282 }
    00283
    00284 static inline int rt_global_save_flags_and_cli(void)
    00285 {
    00286         unsigned long flags;
    00287
    00288         hard_save_flags_and_cli(flags);
    00289         if (!test_and_set_bit(hard_cpu_id(), locked_cpus)) {
    00290                 while (test_and_set_bit(31, locked_cpus));
    00291                 return ((~flags & I_BIT) | 1);
    00292         } else {
    00293                 return (~flags & I_BIT);
    00294         }
    00295 }
    00296
    00297 static inline void rt_global_save_flags(unsigned long *flags)
    00298 {
    00299         unsigned long hflags, rflags;
    00300
    00301         hard_save_flags_and_cli(hflags);
    00302         hflags = ~hflags & I_BIT;
    00303         rflags = hflags | !test_bit(hard_cpu_id(), &locked_cpus);
    00304         if (hflags) {
    00305                 hard_sti();
    00306         }
    00307         *flags = rflags;
    00308 }
    00309
    00310 static inline void rt_global_restore_flags(unsigned long flags)
    00311 {
    00312         switch (flags) {
    00313                 case I_BIT | 1:
    00314                         rt_release_global_lock();
    00315                         hard_sti();
    00316                         break;
    00317                 case I_BIT | 0:
    00318                         rt_get_global_lock();
    00319                         hard_sti();
    00320                         break;
    00321                 case 0 | 1:
    00322                         rt_release_global_lock();
    00323                         break;
    00324                 case 0 | 0:
    00325                         rt_get_global_lock();
    00326                         break;
    00327         }
    00328 }
    00329
    00330 struct calibration_data {
    00331         unsigned int cpu_freq;
    00332         int latency;
    00333         int setup_time_TIMER_CPUNIT;
    00334         int setup_time_TIMER_UNIT;
    00335         int timers_tol[NR_RT_CPUS];
    00336 };
    00337
    00338 extern struct rt_times rt_smp_times[NR_RT_CPUS];
    00339 extern struct calibration_data tuned;
    00340
    00341 static inline unsigned long xchg_u32(unsigned long *up, unsigned long val)
    00342 {
    00343         unsigned long flags, ret;
    00344
    00345         hard_save_flags_and_cli(flags);
    00346         ret = *up;
    00347         *up = val;
    00348         hard_restore_flags(flags);
    00349         return ret;
    00350 }
    00351
    00352 extern unsigned long linux_save_flags_and_cli_cpuid(int);
    00353
    00354 #endif /* !__KERNEL__ */
    00355
    00356 #endif /* !_RTAI_ASM_ARM_RTAI_H */