base/include/asm-i386/rtai_lxrt.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
00003  * extensions for user space modules are jointly copyrighted (2000) with:
00004  *      Pierre Cloutier <pcloutier@poseidoncontrols.com>,
00005  *      Steve Papacharalambous <stevep@zentropix.com>.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
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 /* CONFIG_RTAI_RTC_FREQ == 0 */
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 /* !CONFIG_GENERIC_CLOCKEVENTS */
00125 #define update_linux_timer(cpuid)
00126 #endif /* CONFIG_GENERIC_CLOCKEVENTS */
00127 
00128 #else /* !CONFIG_X86_LOCAL_APIC */
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 /* CONFIG_X86_LOCAL_APIC */
00146 
00147 #endif /* CONFIG_RTAI_RTC_FREQ != 0 */
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 /* __cplusplus */
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 /* KERNEL_VERSION >= 2.6.0 */
00167 #define __LXRT_GET_DATASEG(reg) "movl $" STR(__USER_DS) ",%" #reg "\n\t"
00168 #endif  /* KERNEL_VERSION < 2.6.0 */
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); // was switch_to(prev, next, prev);
00178 #else /* >= 2.6.0 */
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 /* < 2.6.0 */
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)/* + sizeof(struct thread_info)*/ + (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 //  memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), sizeof(struct thread_info));
00203     memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (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 //  memcpy((void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), sizeof(struct thread_info));
00210     memcpy((void *)lnxtsk->thread.RT_REG_SP, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (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 //#define RTAI_DO_LINUX_SIGNAL
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 /* !__KERNEL__ */
00252 
00253 /* NOTE: Keep the following routines unfold: this is a compiler
00254    compatibility issue. */
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 /* __KERNEL__ */
00278 
00279 #ifdef __cplusplus
00280 }
00281 #endif /* __cplusplus */
00282 
00283 #endif /* !_RTAI_ASM_I386_LXRT_H */

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7