00001
00035 #ifndef _RTAI_ASM_I386_HAL_H
00036 #define _RTAI_ASM_I386_HAL_H
00037
00038 #include <nucleus/asm-generic/hal.h>
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
00055 static inline __attribute_const__ unsigned long long
00056 rthal_ullmul(unsigned long m1, unsigned long m2) {
00057
00058 return (unsigned long long) m1 * m2;
00059 }
00060
00061
00062
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
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
00077
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
00084
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
00099
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
00115
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
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
00141
00142 __asm__ ( "addl %1, %%eax\n\t"
00143 "adcl $0, %%edx"
00144 : "=A,A"(th)
00145 : "r,?m"(tlh), "A,A"(th) );
00146
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
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
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
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
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
00202
00203 #if defined(CONFIG_ADEOS_CORE) && !defined(CONFIG_ADEOS_NOTHREADS)
00204
00205
00206
00207
00208
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
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
00239
00240 static inline void rthal_timer_program_shot (unsigned long delay)
00241 {
00242 unsigned long flags;
00243
00244
00245
00246 if(!delay) delay = 1;
00247 rthal_local_irq_save_hw(flags);
00248 #ifdef CONFIG_X86_LOCAL_APIC
00249
00250
00251
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
00257 outb(delay & 0xff,0x40);
00258 outb(delay >> 8,0x40);
00259 #endif
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] = "",
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
00292
00293 #endif