00001
00039 #ifndef _RTAI_ASM_I386_HAL_H
00040 #define _RTAI_ASM_I386_HAL_H
00041
00042 #include <nucleus/asm-generic/hal.h>
00043
00044 typedef unsigned long long rthal_time_t;
00045
00046 #define __rthal_u64tou32(ull, h, l) ({ \
00047 unsigned long long _ull = (ull); \
00048 (l) = _ull & 0xffffffff; \
00049 (h) = _ull >> 32; \
00050 })
00051
00052 #define __rthal_u64fromu32(h, l) ({ \
00053 unsigned long long _ull; \
00054 asm ( "": "=A"(_ull) : "d"(h), "a"(l)); \
00055 _ull; \
00056 })
00057
00058
00059 static inline __attribute_const__ unsigned long long
00060 rthal_ullmul(unsigned long m1, unsigned long m2) {
00061
00062 return (unsigned long long) m1 * m2;
00063 }
00064
00065
00066
00067 static inline __attribute_const__ unsigned long long
00068 __rthal_uldivrem(const unsigned long long ull, const unsigned long d) {
00069
00070 unsigned long long ret;
00071 __asm__ ("divl %1" : "=A,A"(ret) : "r,?m"(d), "A,A"(ull));
00072
00073 return ret;
00074 }
00075
00076 static inline __attribute_const__ int rthal_imuldiv (const int i,
00077 const int mult,
00078 const int div) {
00079
00080
00081
00082 const unsigned long ui = (const unsigned long) i;
00083 const unsigned long um = (const unsigned long) mult;
00084 return __rthal_uldivrem((const unsigned long long) ui * um, div);
00085 }
00086
00087
00088
00089 static inline unsigned long rthal_uldivrem(unsigned long long ull,
00090 const unsigned long d,
00091 unsigned long *const rp) {
00092
00093 unsigned long q, r;
00094 ull = __rthal_uldivrem(ull, d);
00095 __asm__ ( "": "=d"(r), "=a"(q) : "A"(ull));
00096 if(rp)
00097 *rp = r;
00098 return q;
00099 }
00100
00101
00102
00103
00104 static inline unsigned long long __rthal_div96by32 (const unsigned long long h,
00105 const unsigned long l,
00106 const unsigned long d,
00107 unsigned long *const rp) {
00108
00109 u_long rh;
00110 const u_long qh = rthal_uldivrem(h, d, &rh);
00111 const unsigned long long t = __rthal_u64fromu32(rh, l);
00112 const u_long ql = rthal_uldivrem(t, d, rp);
00113
00114 return __rthal_u64fromu32(qh, ql);
00115 }
00116
00117
00118
00119
00120 static inline unsigned long long rthal_ulldiv (const unsigned long long ull,
00121 const unsigned long d,
00122 unsigned long *const rp) {
00123
00124 unsigned long h, l;
00125 __rthal_u64tou32(ull, h, l);
00126 return __rthal_div96by32(h, l, d, rp);
00127 }
00128
00129
00130 #define rthal_u64div32c rthal_ulldiv
00131
00132 static inline __attribute_const__
00133 unsigned long long __rthal_ullimd (const unsigned long long op,
00134 const unsigned long m,
00135 const unsigned long d) {
00136
00137 unsigned long long th, tl;
00138 u_long oph, opl, tlh, tll;
00139
00140 __rthal_u64tou32(op, oph, opl);
00141 tl = (unsigned long long) opl * m;
00142 __rthal_u64tou32(tl, tlh, tll);
00143 th = (unsigned long long) oph * m;
00144
00145
00146 __asm__ ( "addl %1, %%eax\n\t"
00147 "adcl $0, %%edx"
00148 : "=A,A"(th)
00149 : "r,?m"(tlh), "A,A"(th) );
00150
00151
00152 return __rthal_div96by32(th, tll, d, NULL);
00153 }
00154
00155 static inline __attribute_const__ long long rthal_llimd (const long long op,
00156 const unsigned long m,
00157 const unsigned long d) {
00158
00159 if(op < 0LL)
00160 return -__rthal_ullimd(-op, m, d);
00161 return __rthal_ullimd(op, m, d);
00162 }
00163
00164 static inline __attribute_const__ unsigned long ffnz (unsigned long ul) {
00165
00166 __asm__("bsfl %1, %0"
00167 : "=r,r" (ul)
00168 : "r,?m" (ul));
00169 return ul;
00170 }
00171
00172 #if defined(__KERNEL__) && !defined(__cplusplus)
00173 #include <asm/system.h>
00174 #include <asm/io.h>
00175 #include <asm/timex.h>
00176 #include <nucleus/asm/atomic.h>
00177 #include <asm/processor.h>
00178 #include <io_ports.h>
00179 #ifdef CONFIG_X86_LOCAL_APIC
00180 #include <asm/fixmap.h>
00181 #include <asm/apic.h>
00182 #endif
00183
00184 #define RTHAL_8254_IRQ 0
00185
00186 #ifdef CONFIG_X86_LOCAL_APIC
00187 #define RTHAL_APIC_TIMER_VECTOR ADEOS_SERVICE_VECTOR3
00188 #define RTHAL_APIC_TIMER_IPI ADEOS_SERVICE_IPI3
00189 #define RTHAL_APIC_ICOUNT ((RTHAL_TIMER_FREQ + HZ/2)/HZ)
00190 #endif
00191
00192 #define rthal_irq_descp(irq) (irq_desc + irq)
00193
00194 #ifdef CONFIG_X86_TSC
00195 static inline unsigned long long rthal_rdtsc (void) {
00196 unsigned long long t;
00197 __asm__ __volatile__( "rdtsc" : "=A" (t));
00198 return t;
00199 }
00200 #else
00201 #define RTHAL_8254_COUNT2LATCH 0xfffe
00202 void rthal_setup_8254_tsc(void);
00203 rthal_time_t rthal_get_8254_tsc(void);
00204 #define rthal_rdtsc() rthal_get_8254_tsc()
00205 #endif
00206
00207 #if !defined(CONFIG_ADEOS_NOTHREADS)
00208
00209
00210
00211
00212
00213
00214 static inline struct task_struct *rthal_root_host_task (int cpuid) {
00215 u_long stack = (u_long)adp_root->esp[cpuid] & ~(THREAD_SIZE - 1);
00216 return ((struct thread_info *)(stack))->task;
00217 }
00218
00219 static inline struct task_struct *rthal_current_host_task (int cpuid)
00220
00221 {
00222 int *esp;
00223
00224 __asm__ ("movl %%esp, %0" : "=r,?m" (esp));
00225
00226 if (esp >= rthal_domain.estackbase[cpuid] && esp < rthal_domain.estackbase[cpuid] + 2048)
00227 return rthal_root_host_task(cpuid);
00228
00229 return get_current();
00230 }
00231
00232 #else
00233
00234 static inline struct task_struct *rthal_root_host_task (int cpuid) {
00235 return current;
00236 }
00237
00238 static inline struct task_struct *rthal_current_host_task (int cpuid) {
00239 return current;
00240 }
00241
00242 #endif
00243
00244 static inline void rthal_timer_program_shot (unsigned long delay)
00245 {
00246 unsigned long flags;
00247
00248
00249
00250 if(!delay) delay = 1;
00251 rthal_hw_lock(flags);
00252 #ifdef CONFIG_X86_LOCAL_APIC
00253
00254
00255
00256 apic_read_around(APIC_LVTT);
00257 apic_write_around(APIC_LVTT,RTHAL_APIC_TIMER_VECTOR);
00258 apic_read_around(APIC_TMICT);
00259 apic_write_around(APIC_TMICT,delay);
00260 #else
00261 outb(delay & 0xff,0x40);
00262 outb(delay >> 8,0x40);
00263 #endif
00264 rthal_hw_unlock(flags);
00265 }
00266
00267 static const char *const rthal_fault_labels[] = {
00268 [0] = "Divide error",
00269 [1] = "Debug",
00270 [2] = "",
00271 [3] = "Int3",
00272 [4] = "Overflow",
00273 [5] = "Bounds",
00274 [6] = "Invalid opcode",
00275 [7] = "FPU not available",
00276 [8] = "Double fault",
00277 [9] = "FPU segment overrun",
00278 [10] = "Invalid TSS",
00279 [11] = "Segment not present",
00280 [12] = "Stack segment",
00281 [13] = "General protection",
00282 [14] = "Page fault",
00283 [15] = "Spurious interrupt",
00284 [16] = "FPU error",
00285 [17] = "Alignment check",
00286 [18] = "Machine check",
00287 [19] = "SIMD error",
00288 [20] = NULL,
00289 };
00290
00291 #endif
00292
00295 #endif