# rtai_lxrt.h

    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 //#define USE_LINUX_SYSCALL
    00029
    00030 #define SYSCALL_NR      orig_eax
    00031 #define SYSCALL_ARGS    ecx
    00032 #define SYSCALL_RETPNT  edx
    00033
    00034 #define SET_LXRT_RETVAL_IN_SYSCALL(retval) \
    00035         do { \
    00036                 if (r->SYSCALL_RETPNT) { \
    00037                         copy_to_user((void *)r->SYSCALL_RETPNT, &retval, sizeof(retval)); \
    00038                 } \
    00039         } while (0)
    00040
    00041 #define LOW  0
    00042 #define HIGH 1
    00043
    00044 #ifdef CONFIG_X86_LOCAL_APIC
    00045
    00046 #define TIMER_NAME "APIC"
    00047 #define FAST_TO_READ_TSC
    00048 #define TIMER_FREQ RTAI_FREQ_APIC
    00049 #define TIMER_LATENCY RTAI_LATENCY_APIC
    00050 #define TIMER_SETUP_TIME RTAI_SETUP_TIME_APIC
    00051 #define ONESHOT_SPAN (0x7FFFFFFFLL*(CPU_FREQ/TIMER_FREQ))
    00052 #define update_linux_timer(cpuid)
    00053
    00054 #else /* !CONFIG_X86_LOCAL_APIC */
    00055
    00056 #define USE_LINUX_TIMER
    00057 #define TIMER_NAME "8254-PIT"
    00058 #define TIMER_FREQ RTAI_FREQ_8254
    00059 #define TIMER_LATENCY RTAI_LATENCY_8254
    00060 #define TIMER_SETUP_TIME RTAI_SETUP_TIME_8254
    00061 #define ONESHOT_SPAN (0x7FFF*(CPU_FREQ/TIMER_FREQ))
    00062 #define update_linux_timer(cpuid) adeos_pend_uncond(TIMER_8254_IRQ, cpuid)
    00063
    00064 #endif /* CONFIG_X86_LOCAL_APIC */
    00065
    00066 union rtai_lxrt_t {
    00067
    00068     RTIME rt;
    00069     int i[2];
    00070     void *v[2];
    00071 };
    00072
    00073 #ifdef __cplusplus
    00074 extern "C" {
    00075 #endif /* __cplusplus */
    00076
    00077 #ifdef __KERNEL__
    00078
    00079 #include <asm/segment.h>
    00080 #include <asm/mmu_context.h>
    00081
    00082 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
    00083 #define __LXRT_GET_DATASEG(reg) "movl $" STR(__KERNEL_DS) ",%" #reg "\n\t"
    00084 #else /* KERNEL_VERSION >= 2.6.0 */
    00085 #define __LXRT_GET_DATASEG(reg) "movl $" STR(__USER_DS) ",%" #reg "\n\t"
    00086 #endif  /* KERNEL_VERSION < 2.6.0 */
    00087
    00088 static inline void _lxrt_context_switch (struct task_struct *prev,
    00089                                          struct task_struct *next,
    00090                                          int cpuid)
    00091 {
    00092     struct mm_struct *oldmm = prev->active_mm;
    00093
    00094 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
    00095     switch_mm(oldmm,next->active_mm,next,cpuid);
    00096
    00097     if (!next->mm)
    00098         enter_lazy_tlb(oldmm,next,cpuid);
    00099 #else /* >= 2.6.0 */
    00100     switch_mm(oldmm,next->active_mm,next);
    00101
    00102     if (!next->mm) enter_lazy_tlb(oldmm,next);
    00103 #endif /* < 2.6.0 */
    00104
    00105 /* NOTE: Do not use switch_to() directly: this is a compiler
    00106    compatibility issue. */
    00107
    00108 /* It might be so but, with 2.6.xx at least, only for the inlined case.
    00109    Compiler compatibility issues related to inlines can appear anywhere.
    00110    This case seems to be solved by staticalising without inlining, see LXRT.
    00111    So let's experiment a bit more, simple Linux reuse is better (Paolo) */
    00112
    00113 #if 1
    00114     switch_to(prev, next, prev);
    00115 #else
    00116     __asm__ __volatile__(                                               \
    00117                  "pushfl\n\t"                                           \
    00118                  "cli\n\t"                                              \
    00119                  "pushl %%esi\n\t"                                      \
    00120                  "pushl %%edi\n\t"                                      \
    00121                  "pushl %%ebp\n\t"                                      \
    00122                  "movl %%esp,%0\n\t"    /* save ESP */                  \
    00123                  "movl %3,%%esp\n\t"    /* restore ESP */               \
    00124                  "movl $1f,%1\n\t"      /* save EIP */                  \
    00125                  "pushl %4\n\t"         /* restore EIP */               \
    00126                  "jmp "SYMBOL_NAME_STR(__switch_to)"\n"                 \
    00127                  "1:\t"                                                 \
    00128                  "popl %%ebp\n\t"                                       \
    00129                  "popl %%edi\n\t"                                       \
    00130                  "popl %%esi\n\t"                                       \
    00131                  "popfl\n\t"                                            \
    00132                  :"=m" (prev->thread.esp),"=m" (prev->thread.eip),      \
    00133                   "=b" (prev)                                           \
    00134                  :"m" (next->thread.esp),"m" (next->thread.eip),        \
    00135                   "a" (prev), "d" (next),                               \
    00136                   "b" (prev));
    00137 #endif
    00138     barrier();
    00139 }
    00140
    00141 #if 0
    00142 #define IN_INTERCEPT_IRQ_ENABLE()   do { rtai_hw_sti(); } while (0)
    00143 #define IN_INTERCEPT_IRQ_DISABLE()  do { rtai_hw_cli(); } while (0)
    00144 #else
    00145 #define IN_INTERCEPT_IRQ_ENABLE()   do { } while (0)
    00146 #define IN_INTERCEPT_IRQ_DISABLE()  do { } while (0)
    00147 #endif
    00148
    00149 #else /* !__KERNEL__ */
    00150
    00151 /* NOTE: Keep the following routines unfold: this is a compiler
    00152    compatibility issue. */
    00153
    00154 static union rtai_lxrt_t _rtai_lxrt(int srq, void *arg)
    00155 {
    00156         union rtai_lxrt_t retval;
    00157 #ifdef USE_LINUX_SYSCALL
    00158         RTAI_DO_TRAP(SYSCALL_VECTOR, retval, srq, arg);
    00159 #else
    00160         RTAI_DO_TRAP(RTAI_SYS_VECTOR, retval, srq, arg);
    00161 #endif
    00162         return retval;
    00163 }
    00164
    00165 static inline union rtai_lxrt_t rtai_lxrt(short int dynx, short int lsize, int srq, void *arg)
    00166 {
    00167         return _rtai_lxrt(ENCODE_LXRT_REQ(dynx, srq, lsize), arg);
    00168 }
    00169
    00170 #endif /* __KERNEL__ */
    00171
    00172 #ifdef __cplusplus
    00173 }
    00174 #endif /* __cplusplus */
    00175
    00176 #endif /* !_RTAI_ASM_I386_LXRT_H */