base/include/asm-ppc/rtai_lxrt.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1999-2007 Paolo Mantegazza <mantegazza@aero.polimi.it>
00003  *         2000 Pierre Cloutier <pcloutier@poseidoncontrols.com>
00004            2002 Steve Papacharalambous <stevep@zentropix.com>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library 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 GNU
00014  * Lesser General Public License for more details.
00015 
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_PPC_LXRT_H
00022 #define _RTAI_ASM_PPC_LXRT_H
00023 
00024 #include <linux/version.h>
00025 
00026 #include <asm/rtai_vectors.h>
00027 
00028 #ifndef CONFIG_RTAI_INTERNAL_LXRT_SUPPORT
00029 #define CONFIG_RTAI_INTERNAL_LXRT_SUPPORT 1
00030 #endif
00031 
00032 #ifdef CONFIG_RTAI_LXRT_USE_LINUX_SYSCALL
00033 #define USE_LINUX_SYSCALL
00034 #else
00035 #undef USE_LINUX_SYSCALL
00036 #endif
00037 
00038 #define LINUX_SYSCALL_NR      gpr[0]
00039 #define LINUX_SYSCALL_REG1    gpr[3]
00040 #define LINUX_SYSCALL_REG2    gpr[4]
00041 #define LINUX_SYSCALL_REG3    gpr[5]
00042 #define LINUX_SYSCALL_REG4    gpr[6]
00043 #define LINUX_SYSCALL_REG5    gpr[7]
00044 #define LINUX_SYSCALL_REG6    gpr[8]
00045 #define LINUX_SYSCALL_RETREG  gpr[3]
00046 #define LINUX_SYSCALL_FLAGS   msr
00047 
00048 #define RTAI_SYSCALL_NR      0x70000000
00049 #define RTAI_SYSCALL_CODE    LINUX_SYSCALL_REG1
00050 #define RTAI_SYSCALL_ARGS    LINUX_SYSCALL_REG2
00051 #define RTAI_SYSCALL_RETPNT  LINUX_SYSCALL_REG3
00052 
00053 //#define RTAI_FAKE_LINUX_SYSCALL  39
00054 
00055 //#define NR_syscalls __NR_syscall_max
00056 
00057 #define LXRT_DO_IMMEDIATE_LINUX_SYSCALL(regs) \
00058         do { \
00059         regs->LINUX_SYSCALL_RETREG = ((asmlinkage int (*)(long, ...))sys_call_table[regs->LINUX_SYSCALL_NR])(regs->LINUX_SYSCALL_REG1, regs->LINUX_SYSCALL_REG2, regs->LINUX_SYSCALL_REG3, regs->LINUX_SYSCALL_REG4, regs->LINUX_SYSCALL_REG5, regs->LINUX_SYSCALL_REG6); \
00060         } while (0)
00061 
00062 #define SET_LXRT_RETVAL_IN_SYSCALL(regs, retval) \
00063         do { \
00064         if (regs->RTAI_SYSCALL_RETPNT) { \
00065             rt_copy_to_user((void *)regs->RTAI_SYSCALL_RETPNT, &retval, sizeof(retval)); \
00066         } \
00067         } while (0)
00068 
00069 #define LOW   0
00070 #define HIGH  1
00071 
00072 #define USE_LINUX_TIMER
00073 #define TIMER_NAME        "DECREMENTER"
00074 #define TIMER_FREQ        RTAI_FREQ_8254
00075 #define TIMER_LATENCY     RTAI_LATENCY_8254
00076 #define TIMER_SETUP_TIME  RTAI_SETUP_TIME_8254
00077 #define ONESHOT_SPAN      ((0x7FFF*(CPU_FREQ/TIMER_FREQ))/(CONFIG_RTAI_CAL_FREQS_FACT + 1)) //(0x7FFF*(CPU_FREQ/TIMER_FREQ))
00078 
00079 #define update_linux_timer(cpuid) \
00080     do { rtai_disarm_decr(cpuid, 1); hal_pend_uncond(TIMER_8254_IRQ, cpuid); } while (0)
00081 
00082 union rtai_lxrt_t {
00083     RTIME rt;
00084     long i[2];
00085     void *v[2];
00086 };
00087 
00088 #ifndef THREAD_SIZE
00089 #define THREAD_SIZE  8192    /* 2 pages */
00090 #endif
00091 
00092 #ifdef __cplusplus
00093 extern "C" {
00094 #endif /* __cplusplus */
00095 
00096 #ifdef __KERNEL__
00097 
00098 #include <linux/slab.h>
00099 #include <asm/mmu_context.h>
00100 
00101 static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid)
00102 {
00103 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00104     extern void context_switch(void *, void *);
00105     struct mm_struct *oldmm = prev->active_mm;
00106     switch_mm(oldmm, next->active_mm, next, cpuid);
00107     if (!next->mm) {
00108         enter_lazy_tlb(oldmm, next, cpuid);
00109     }
00110     context_switch(prev, next);
00111 #else /* >= 2.6.0 */
00112         extern void *context_switch(void *, void *, void *);
00113 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
00114         prev->fpu_counter = 0;
00115 #endif
00116         context_switch(NULL, prev, next);
00117 #endif /* < 2.6.0 */
00118 }
00119 
00120 #define IN_INTERCEPT_IRQ_ENABLE()   do { } while (0)
00121 #define IN_INTERCEPT_IRQ_DISABLE()  do { } while (0)
00122 
00123 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00124 {
00125     lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct) + (lnxtsk->thread.ksp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.ksp, GFP_KERNEL);
00126         *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00127     memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.ksp), (lnxtsk->thread.ksp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.ksp);
00128 }
00129 
00130 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00131 {
00132     lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00133         memcpy((void *)lnxtsk->thread.ksp, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (lnxtsk->thread.ksp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.ksp);
00134 }
00135 
00136 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00137 
00138 #define rt_copy_from_user     __copy_from_user
00139 
00140 #define rt_copy_to_user       __copy_to_user
00141 
00142 #define rt_strncpy_from_user  strncpy_from_user
00143 
00144 #else
00145 
00146 #define rt_copy_from_user(a, b, c)  \
00147     ( { int ret = __copy_from_user_inatomic(a, b, c); ret; } )
00148 
00149 #define rt_copy_to_user(a, b, c)  \
00150     ( { int ret = __copy_to_user_inatomic(a, b, c); ret; } )
00151 
00152 #define rt_strncpy_from_user(a, b, c)  \
00153     ( { int ret = strncpy_from_user(a, b, c); ret; } )
00154 
00155 #endif
00156 
00157 #define rt_put_user  __put_user
00158 #define rt_get_user  __get_user
00159 
00160 //#define RTAI_DO_LINUX_SIGNAL
00161 //extern int FASTCALL(do_signal(sigset_t *oldset, struct pt_regs *regs));
00162 #define RT_DO_SIGNAL(regs)  do_signal(NULL, regs)
00163 
00164 #else /* !__KERNEL__ */
00165 
00166 #include <sys/syscall.h>
00167 #include <unistd.h>
00168 
00169 static inline union rtai_lxrt_t __rtai_lxrt(unsigned long arg0, unsigned long arg1, unsigned long arg2)
00170 { 
00171     union rtai_lxrt_t __sc_ret;
00172     {
00173         register unsigned long __sc_0  __asm__ ("r0");
00174         register unsigned long __sc_3  __asm__ ("r3");
00175         register unsigned long __sc_4  __asm__ ("r4");
00176         
00177         __sc_0 = arg0;
00178         __sc_3 = arg1;
00179         __sc_4 = arg2;
00180 
00181         __asm__ __volatile__
00182             ("sc           \n\t"
00183             : "=&r" (__sc_0),
00184               "=&r" (__sc_3),  "=&r" (__sc_4)
00185             : "0" (__sc_0), 
00186               "1" (__sc_3), "2" (__sc_4)
00187             : "cr0", "ctr", "memory",
00188               "r9", "r10","r11", "r12");
00189 
00190         __sc_ret.i[0] = __sc_3;
00191         __sc_ret.i[1] = __sc_4;
00192     }
00193     return __sc_ret;
00194 }
00195 
00196 static union rtai_lxrt_t _rtai_lxrt(long srq, void *arg)
00197 {
00198     union rtai_lxrt_t retval;
00199 #if 1 //def USE_LINUX_SYSCALL
00200     syscall(RTAI_SYSCALL_NR, srq, arg, &retval);
00201 #else
00202     retval = __rtai_lxrt(RTAI_SYSCALL_NR, srq, arg);
00203 #endif
00204     return retval;
00205 }
00206 
00207 static inline union rtai_lxrt_t rtai_lxrt(long dynx, long lsize, long srq, void *arg)
00208 {
00209     return _rtai_lxrt(ENCODE_LXRT_REQ(dynx, srq, lsize), arg);
00210 }
00211 
00212 #define rtai_iopl()  do { } while (0)
00213 
00214 #endif /* __KERNEL__ */
00215 
00216 #ifdef __cplusplus
00217 }
00218 #endif /* __cplusplus */
00219 
00220 #endif /* !_RTAI_ASM_PPC_LXRT_H */
00221 
00222 #if 0 // to be checked
00223 #include <linux/slab.h>
00224 
00225 #if 0 // optimised (?)
00226 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00227 {
00228     lnxtsk->rtai_tskext(TSKEXT2) =
00229          kmalloc(sizeof(struct thread_struct) + (lnxtsk->thread.esp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.esp,
00230          GFP_KERNEL);
00231     *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00232     memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/,
00233         (void *)(lnxtsk->thread.esp),
00234         (lnxtsk->thread.esp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.esp);
00235 }
00236 
00237 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00238 {
00239     lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00240     memcpy((void *)lnxtsk->thread.esp,
00241         lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/,
00242         (lnxtsk->thread.esp & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.esp);
00243 }
00244 #else  // brute force
00245 #include <asm/thread_info.h>
00246 
00247 //this solution could be used in i386 too...
00248 
00249 // This function save the current thread_struct and stack of the task
00250 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00251 {
00252     lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct) + THREAD_SIZE, GFP_KERNEL);
00253     *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00254 // Page 85 Understanding the Linux Kernel tell that all the architecture stack have at the bottom the struct thread_info so...
00255 // GPR is the small data area pointer and point to the thread_info of the process
00256 // note: this copy the thread_info struct too
00257     memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void*) lnxtsk->thread_info, THREAD_SIZE);
00258 }
00259 
00260 // This function RESTORE the thread_struct and stack of the task
00261 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00262 {
00263     lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00264 // this copy the thread_info struct too
00265     memcpy((void*) lnxtsk->thread_info, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), THREAD_SIZE);
00266 }
00267 #endif
00268 #endif

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