hal.h

Go to the documentation of this file.
00001 
00035 #ifndef _RTAI_ASM_I386_HAL_H
00036 #define _RTAI_ASM_I386_HAL_H
00037 
00038 #include <nucleus/asm-generic/hal.h>    /* Read the generic bits. */
00039 
00040 typedef unsigned long long rthal_time_t;
00041 
00042 #define __rthal_u64tou32(ull, h, l) ({          \
00043     unsigned long long _ull = (ull);            \
00044     (l) = _ull & 0xffffffff;                    \
00045     (h) = _ull >> 32;                           \
00046 })
00047 
00048 #define __rthal_u64fromu32(h, l) ({             \
00049     unsigned long long _ull;                    \
00050     asm ( "": "=A"(_ull) : "d"(h), "a"(l));     \
00051     _ull;                                       \
00052 })
00053 
00054 /* Fast longs multiplication. */
00055 static inline __attribute_const__ unsigned long long
00056 rthal_ullmul(unsigned long m1, unsigned long m2) {
00057     /* Gcc (at least for versions 2.95 and higher) optimises correctly here. */
00058     return (unsigned long long) m1 * m2;
00059 }
00060 
00061 /* const helper for rthal_uldivrem, so that the compiler will eliminate
00062    multiple calls with same arguments, at no additionnal cost. */
00063 static inline __attribute_const__ unsigned long long
00064 __rthal_uldivrem(const unsigned long long ull, const unsigned long d) {
00065 
00066     unsigned long long ret;
00067     __asm__ ("divl %1" : "=A,A"(ret) : "r,?m"(d), "A,A"(ull));
00068     /* Exception if quotient does not fit on unsigned long. */
00069     return ret;
00070 }
00071 
00072 static inline __attribute_const__ int rthal_imuldiv (const int i,
00073                                                      const int mult,
00074                                                      const int div) {
00075 
00076     /* Returns (unsigned)i =
00077                (unsigned long long)i*(unsigned)(mult)/(unsigned)div. */
00078     const unsigned long ui = (const unsigned long) i;
00079     const unsigned long um = (const unsigned long) mult;
00080     return __rthal_uldivrem((const unsigned long long) ui * um, div);
00081 }
00082 
00083 /* Fast long long division: when the quotient and remainder fit on 32 bits.
00084    Recent compilers remove redundant calls to this function. */
00085 static inline unsigned long rthal_uldivrem(unsigned long long ull,
00086                                            const unsigned long d,
00087                                            unsigned long *const rp) {
00088 
00089     unsigned long q, r;
00090     ull = __rthal_uldivrem(ull, d);
00091     __asm__ ( "": "=d"(r), "=a"(q) : "A"(ull));
00092     if(rp)
00093         *rp = r;
00094     return q;
00095 }
00096 
00097 
00098 /* Division of an unsigned 96 bits ((h << 32) + l) by an unsigned 32 bits.
00099    Common building block for ulldiv and llimd. */
00100 static inline unsigned long long __rthal_div96by32 (const unsigned long long h,
00101                                                     const unsigned long l,
00102                                                     const unsigned long d,
00103                                                     unsigned long *const rp) {
00104 
00105     u_long rh;
00106     const u_long qh = rthal_uldivrem(h, d, &rh);
00107     const unsigned long long t = __rthal_u64fromu32(rh, l);
00108     const u_long ql = rthal_uldivrem(t, d, rp);
00109 
00110     return __rthal_u64fromu32(qh, ql);
00111 }
00112 
00113 
00114 /* Slow long long division. Uses rthal_uldivrem, hence has the same property:
00115    the compiler removes redundant calls. */
00116 static inline unsigned long long rthal_ulldiv (const unsigned long long ull,
00117                                                const unsigned long d,
00118                                                unsigned long *const rp) {
00119 
00120     unsigned long h, l;
00121     __rthal_u64tou32(ull, h, l);
00122     return __rthal_div96by32(h, l, d, rp);
00123 }
00124 
00125 /* Replaced the helper with rthal_ulldiv. */
00126 #define rthal_u64div32c rthal_ulldiv
00127 
00128 static inline __attribute_const__
00129 unsigned long long __rthal_ullimd (const unsigned long long op,
00130                                    const unsigned long m,
00131                                    const unsigned long d) {
00132 
00133     unsigned long long th, tl;
00134     u_long oph, opl, tlh, tll;
00135 
00136     __rthal_u64tou32(op, oph, opl);
00137     tl = (unsigned long long) opl * m;
00138     __rthal_u64tou32(tl, tlh, tll);
00139     th = (unsigned long long) oph * m;
00140     /* op * m == ((th + tlh) << 32) + tll */
00141 
00142     __asm__ (  "addl %1, %%eax\n\t"
00143                "adcl $0, %%edx"
00144                : "=A,A"(th)
00145                : "r,?m"(tlh), "A,A"(th) );
00146     /* op * m == (th << 32) + tll */
00147 
00148     return __rthal_div96by32(th, tll, d, NULL);
00149 }
00150 
00151 static inline __attribute_const__ long long rthal_llimd (const long long op,
00152                                                          const unsigned long m,
00153                                                          const unsigned long d) {
00154 
00155     if(op < 0LL)
00156         return -__rthal_ullimd(-op, m, d);
00157     return __rthal_ullimd(op, m, d);
00158 }
00159 
00160 static inline __attribute_const__ unsigned long ffnz (unsigned long ul) {
00161     /* Derived from bitops.h's ffs() */
00162     __asm__("bsfl %1, %0"
00163             : "=r,r" (ul)
00164             : "r,?m"  (ul));
00165     return ul;
00166 }
00167 
00168 #if defined(__KERNEL__) && !defined(__cplusplus)
00169 #include <asm/system.h>
00170 #include <asm/io.h>
00171 #include <asm/timex.h>
00172 #include <nucleus/asm/atomic.h>
00173 #include <asm/processor.h>
00174 #include <io_ports.h>
00175 #ifdef CONFIG_X86_LOCAL_APIC
00176 #include <asm/fixmap.h>
00177 #include <asm/apic.h>
00178 #endif /* CONFIG_X86_LOCAL_APIC */
00179 
00180 #define RTHAL_8254_IRQ    0
00181 
00182 #ifdef CONFIG_X86_LOCAL_APIC
00183 #define RTHAL_APIC_TIMER_VECTOR    RTHAL_SERVICE_VECTOR3
00184 #define RTHAL_APIC_TIMER_IPI       RTHAL_SERVICE_IPI3
00185 #define RTHAL_APIC_ICOUNT          ((RTHAL_TIMER_FREQ + HZ/2)/HZ)
00186 #endif /* CONFIG_X86_LOCAL_APIC */
00187 
00188 #define rthal_irq_descp(irq)  (irq_desc + irq)
00189 
00190 #ifdef CONFIG_X86_TSC
00191 static inline unsigned long long rthal_rdtsc (void) {
00192     unsigned long long t;
00193     rthal_read_tsc(t);
00194     return t;
00195 }
00196 #else  /* !CONFIG_X86_TSC */
00197 #define RTHAL_8254_COUNT2LATCH  0xfffe
00198 void rthal_setup_8254_tsc(void);
00199 rthal_time_t rthal_get_8254_tsc(void);
00200 #define rthal_rdtsc() rthal_get_8254_tsc()
00201 #endif /* CONFIG_X86_TSC */
00202 
00203 #if defined(CONFIG_ADEOS_CORE) && !defined(CONFIG_ADEOS_NOTHREADS)
00204 
00205 /* Since real-time interrupt handlers are called on behalf of the RTAI
00206    domain stack, we cannot infere the "current" Linux task address
00207    using %esp. We must use the suspended Linux domain's stack pointer
00208    instead. */
00209 
00210 static inline struct task_struct *rthal_root_host_task (int cpuid) {
00211     u_long stack = (u_long)rthal_root_domain->esp[cpuid] & ~(THREAD_SIZE - 1);
00212     return ((struct thread_info *)(stack))->task;
00213 }
00214 
00215 static inline struct task_struct *rthal_current_host_task (int cpuid)
00216 
00217 {
00218     int *esp;
00219 
00220     __asm__ ("movl %%esp, %0" : "=r,?m" (esp));
00221 
00222     if (esp >= rthal_domain.estackbase[cpuid] && esp < rthal_domain.estackbase[cpuid] + 2048)
00223         return rthal_root_host_task(cpuid);
00224 
00225     return get_current();
00226 }
00227 
00228 #else /* !CONFIG_ADEOS_CORE || CONFIG_ADEOS_NOTHREADS */
00229 
00230 static inline struct task_struct *rthal_root_host_task (int cpuid) {
00231     return current;
00232 }
00233 
00234 static inline struct task_struct *rthal_current_host_task (int cpuid) {
00235     return current;
00236 }
00237 
00238 #endif /* CONFIG_ADEOS_CORE && !CONFIG_ADEOS_NOTHREADS */
00239 
00240 static inline void rthal_timer_program_shot (unsigned long delay)
00241 {
00242     unsigned long flags;
00243     /* Neither the 8254 nor most APICs won't trigger any interrupt
00244        upon receiving a null timer count, so don't let this
00245        happen. --rpm */
00246     if(!delay) delay = 1;
00247     rthal_local_irq_save_hw(flags);
00248 #ifdef CONFIG_X86_LOCAL_APIC
00249     /* Note: reading before writing just to work around the Pentium
00250        APIC double write bug. apic_read_around() expands to nil
00251        whenever CONFIG_X86_GOOD_APIC is set. --rpm */
00252     apic_read_around(APIC_LVTT);
00253     apic_write_around(APIC_LVTT,RTHAL_APIC_TIMER_VECTOR);
00254     apic_read_around(APIC_TMICT);
00255     apic_write_around(APIC_TMICT,delay);
00256 #else /* !CONFIG_X86_LOCAL_APIC */
00257     outb(delay & 0xff,0x40);
00258     outb(delay >> 8,0x40);
00259 #endif /* CONFIG_X86_LOCAL_APIC */
00260     rthal_local_irq_restore_hw(flags);
00261 }
00262 
00263 static const char *const rthal_fault_labels[] = {
00264     [0] = "Divide error",
00265     [1] = "Debug",
00266     [2] = "",   /* NMI is not pipelined. */
00267     [3] = "Int3",
00268     [4] = "Overflow",
00269     [5] = "Bounds",
00270     [6] = "Invalid opcode",
00271     [7] = "FPU not available",
00272     [8] = "Double fault",
00273     [9] = "FPU segment overrun",
00274     [10] = "Invalid TSS",
00275     [11] = "Segment not present",
00276     [12] = "Stack segment",
00277     [13] = "General protection",
00278     [14] = "Page fault",
00279     [15] = "Spurious interrupt",
00280     [16] = "FPU error",
00281     [17] = "Alignment check",
00282     [18] = "Machine check",
00283     [19] = "SIMD error",
00284     [20] = NULL,
00285 };
00286 
00287 long rthal_strncpy_from_user(char *dst,
00288                              const char __user *src,
00289                              long count);
00290 
00291 #endif /* __KERNEL__ && !__cplusplus */
00292 
00293 #endif /* !_RTAI_ASM_I386_HAL_H */

Generated on Sat Sep 3 12:32:46 2005 for RTAI Fusion API by  doxygen 1.4.2