00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _RTAI_ASM_I386_LXRT_H
00022 #define _RTAI_ASM_I386_LXRT_H
00023
00024 #include <linux/version.h>
00025
00026 #include <asm/rtai_vectors.h>
00027
00028 #ifdef CONFIG_RTAI_LXRT_USE_LINUX_SYSCALL
00029 #define USE_LINUX_SYSCALL
00030 #else
00031 #undef USE_LINUX_SYSCALL
00032 #endif
00033
00034 #define RTAI_SYSCALL_NR 0x70000000
00035
00036 #if defined(__KERNEL__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
00037
00038 #define RT_REG_ORIG_AX orig_ax
00039 #define RT_REG_SP sp
00040 #define RT_REG_FLAGS flags
00041 #define RT_REG_IP ip
00042 #define RT_REG_CS cs
00043 #define RT_REG_BP bp
00044
00045 #define RTAI_SYSCALL_CODE bx
00046 #define RTAI_SYSCALL_ARGS cx
00047 #define RTAI_SYSCALL_RETPNT dx
00048
00049 #define LINUX_SYSCALL_NR RT_REG_ORIG_AX
00050 #define LINUX_SYSCALL_REG1 bx
00051 #define LINUX_SYSCALL_REG2 cx
00052 #define LINUX_SYSCALL_REG3 dx
00053 #define LINUX_SYSCALL_REG4 si
00054 #define LINUX_SYSCALL_REG5 di
00055 #define LINUX_SYSCALL_REG6 RT_REG_BP
00056 #define LINUX_SYSCALL_RETREG ax
00057 #define LINUX_SYSCALL_FLAGS RT_REG_FLAGS
00058
00059 #else
00060
00061 #define RT_REG_ORIG_AX orig_eax
00062 #define RT_REG_SP esp
00063 #define RT_REG_FLAGS eflags
00064 #define RT_REG_IP eip
00065 #define RT_REG_CS xcs
00066 #define RT_REG_BP ebp
00067
00068 #define RTAI_SYSCALL_CODE ebx
00069 #define RTAI_SYSCALL_ARGS ecx
00070 #define RTAI_SYSCALL_RETPNT edx
00071
00072 #define LINUX_SYSCALL_NR RT_REG_ORIG_AX
00073 #define LINUX_SYSCALL_REG1 ebx
00074 #define LINUX_SYSCALL_REG2 ecx
00075 #define LINUX_SYSCALL_REG3 edx
00076 #define LINUX_SYSCALL_REG4 esi
00077 #define LINUX_SYSCALL_REG5 edi
00078 #define LINUX_SYSCALL_REG6 RT_REG_BP
00079 #define LINUX_SYSCALL_RETREG eax
00080 #define LINUX_SYSCALL_FLAGS RT_REG_FLAGS
00081
00082 #endif
00083
00084 #define LXRT_DO_IMMEDIATE_LINUX_SYSCALL(regs) \
00085 do { \
00086 regs->LINUX_SYSCALL_RETREG = sys_call_table[regs->LINUX_SYSCALL_NR](*regs); \
00087 } while (0)
00088
00089 #define SET_LXRT_RETVAL_IN_SYSCALL(regs, retval) \
00090 do { \
00091 if (regs->RTAI_SYSCALL_RETPNT) { \
00092 rt_copy_to_user((void *)regs->RTAI_SYSCALL_RETPNT, &retval, sizeof(retval)); \
00093 } \
00094 } while (0)
00095
00096 #define LOW 0
00097 #define HIGH 1
00098
00099 #if defined(CONFIG_RTAI_RTC_FREQ) && CONFIG_RTAI_RTC_FREQ >= 2
00100
00101 #define TIMER_NAME "RTC"
00102 #define HRT_LINUX_TIMER_NAME "rtc"
00103 #define TIMER_FREQ CONFIG_RTAI_RTC_FREQ
00104 #define TIMER_LATENCY 0
00105 #define TIMER_SETUP_TIME 0
00106 #define ONESHOT_SPAN 0
00107
00108 #else
00109
00110 #ifdef CONFIG_X86_LOCAL_APIC
00111
00112 #define TIMER_NAME "APIC"
00113 #define TIMER_TYPE 1
00114 #define HRT_LINUX_TIMER_NAME "lapic"
00115 #define FAST_TO_READ_TSC
00116 #define TIMER_FREQ RTAI_FREQ_APIC
00117 #define TIMER_LATENCY RTAI_LATENCY_APIC
00118 #define TIMER_SETUP_TIME RTAI_SETUP_TIME_APIC
00119 #define ONESHOT_SPAN (CPU_FREQ/(CONFIG_RTAI_CAL_FREQS_FACT + 2)) //(0x7FFFFFFFLL*(CPU_FREQ/TIMER_FREQ))
00120 #ifdef CONFIG_GENERIC_CLOCKEVENTS
00121 #define USE_LINUX_TIMER
00122 #define update_linux_timer(cpuid) \
00123 do { hal_pend_uncond(LOCAL_TIMER_IPI, cpuid); } while (0)
00124 #else
00125 #define update_linux_timer(cpuid)
00126 #endif
00127
00128 #else
00129
00130 #define USE_LINUX_TIMER
00131 #define TIMER_NAME "8254-PIT"
00132 #define TIMER_TYPE 0
00133 #define HRT_LINUX_TIMER_NAME "pit"
00134 #define TIMER_FREQ RTAI_FREQ_8254
00135 #define TIMER_LATENCY RTAI_LATENCY_8254
00136 #define TIMER_SETUP_TIME RTAI_SETUP_TIME_8254
00137 #define ONESHOT_SPAN ((0x7FFF*(CPU_FREQ/TIMER_FREQ))/(CONFIG_RTAI_CAL_FREQS_FACT + 1)) //(0x7FFF*(CPU_FREQ/TIMER_FREQ))
00138 #define update_linux_timer(cpuid) \
00139 do { \
00140 if (!IS_FUSION_TIMER_RUNNING()) { \
00141 hal_pend_uncond(TIMER_8254_IRQ, cpuid); \
00142 } \
00143 } while (0)
00144
00145 #endif
00146
00147 #endif
00148
00149 union rtai_lxrt_t {
00150 RTIME rt;
00151 int i[2];
00152 void *v[2];
00153 };
00154
00155 #ifdef __cplusplus
00156 extern "C" {
00157 #endif
00158
00159 #ifdef __KERNEL__
00160
00161 #include <asm/segment.h>
00162 #include <asm/mmu_context.h>
00163
00164 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00165 #define __LXRT_GET_DATASEG(reg) "movl $" STR(__KERNEL_DS) ",%" #reg "\n\t"
00166 #else
00167 #define __LXRT_GET_DATASEG(reg) "movl $" STR(__USER_DS) ",%" #reg "\n\t"
00168 #endif
00169
00170 static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid)
00171 {
00172 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00173 extern void context_switch(void *, void *);
00174 struct mm_struct *oldmm = prev->active_mm;
00175 switch_mm(oldmm, next->active_mm, next, cpuid);
00176 if (!next->mm) enter_lazy_tlb(oldmm, next, cpuid);
00177 context_switch(prev, next);
00178 #else
00179 extern void context_switch(void *, void *, void *);
00180 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
00181 prev->fpu_counter = 0;
00182 #endif
00183 context_switch(0, prev, next);
00184 #endif
00185 }
00186
00187 #if 0
00188 #define IN_INTERCEPT_IRQ_ENABLE() do { rtai_hw_sti(); } while (0)
00189 #define IN_INTERCEPT_IRQ_DISABLE() do { rtai_hw_cli(); } while (0)
00190 #else
00191 #define IN_INTERCEPT_IRQ_ENABLE() do { } while (0)
00192 #define IN_INTERCEPT_IRQ_DISABLE() do { } while (0)
00193 #endif
00194
00195 #include <linux/slab.h>
00196
00197 #if 1 // optimised (?)
00198 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00199 {
00200 lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct) + (lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.RT_REG_SP, GFP_KERNEL);
00201 *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00202
00203 memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.RT_REG_SP), (lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.RT_REG_SP);
00204 }
00205
00206 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00207 {
00208 lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00209
00210 memcpy((void *)lnxtsk->thread.RT_REG_SP, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.RT_REG_SP);
00211 }
00212 #else // brute force
00213 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00214 {
00215 lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct) + THREAD_SIZE, GFP_KERNEL);
00216 *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00217 memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), THREAD_SIZE);
00218 }
00219
00220 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00221 {
00222 lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00223 memcpy((void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), THREAD_SIZE);
00224 }
00225 #endif
00226
00227 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00228 #define rt_copy_from_user __copy_from_user
00229 #define rt_copy_to_user __copy_to_user
00230 #define rt_strncpy_from_user strncpy_from_user
00231 #else
00232 #define rt_copy_from_user(a, b, c) \
00233 ( { int ret = __copy_from_user_inatomic(a, b, c); ret; } )
00234 #define rt_copy_to_user(a, b, c) \
00235 ( { int ret = __copy_to_user_inatomic(a, b, c); ret; } )
00236 #define rt_strncpy_from_user(a, b, c) \
00237 ( { int ret = strncpy_from_user(a, b, c); ret; } )
00238 #endif
00239 #define rt_put_user __put_user
00240 #define rt_get_user __get_user
00241
00242
00243 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
00244 extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
00245 #define RT_DO_SIGNAL(regs) do_signal(regs, NULL)
00246 #else
00247 __attribute__((regparm(3))) void do_notify_resume(struct pt_regs *regs, void *_unused, __u32 thread_info_flags);
00248 #define RT_DO_SIGNAL(regs) do_notify_resume(regs, NULL, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK));
00249 #endif
00250
00251 #else
00252
00253
00254
00255
00256 #include <sys/syscall.h>
00257 #include <unistd.h>
00258
00259 static union rtai_lxrt_t _rtai_lxrt(int srq, void *arg)
00260 {
00261 union rtai_lxrt_t retval;
00262 #ifdef USE_LINUX_SYSCALL
00263 syscall(RTAI_SYSCALL_NR, srq, arg, &retval);
00264 #else
00265 RTAI_DO_TRAP(RTAI_SYS_VECTOR, retval, srq, arg);
00266 #endif
00267 return retval;
00268 }
00269
00270 static inline union rtai_lxrt_t rtai_lxrt(short int dynx, short int lsize, int srq, void *arg)
00271 {
00272 return _rtai_lxrt(ENCODE_LXRT_REQ(dynx, srq, lsize), arg);
00273 }
00274
00275 #define rtai_iopl() do { extern int iopl(int); iopl(3); } while (0)
00276
00277 #endif
00278
00279 #ifdef __cplusplus
00280 }
00281 #endif
00282
00283 #endif