00001
00038 #ifndef _RTAI_ASM_I386_HAL_H
00039 #define _RTAI_ASM_I386_HAL_H
00040
00041 #include <asm/rtai_vectors.h>
00042 #include <rtai_types.h>
00043
00044 #ifdef CONFIG_SMP
00045 #define RTAI_NR_CPUS CONFIG_RTAI_CPUS
00046 #else
00047 #define RTAI_NR_CPUS 1
00048 #endif
00049
00050 static __inline__ unsigned long ffnz (unsigned long word) {
00051
00052 __asm__("bsfl %1, %0"
00053 : "=r" (word)
00054 : "r" (word));
00055 return word;
00056 }
00057
00058 static inline unsigned long long rtai_ulldiv (unsigned long long ull,
00059 unsigned long uld,
00060 unsigned long *r) {
00061
00062
00063
00064
00065
00066
00067 unsigned long long qf, rf;
00068 unsigned long tq, rh;
00069 union { unsigned long long ull; unsigned long ul[2]; } p, q;
00070
00071 p.ull = ull;
00072 q.ull = 0;
00073 rf = 0x100000000ULL - (qf = 0xFFFFFFFFUL / uld) * uld;
00074
00075 while (p.ull >= uld) {
00076 q.ul[1] += (tq = p.ul[1] / uld);
00077 rh = p.ul[1] - tq * uld;
00078 q.ull += rh * qf + (tq = p.ul[0] / uld);
00079 p.ull = rh * rf + (p.ul[0] - tq * uld);
00080 }
00081
00082 if (r)
00083 *r = p.ull;
00084
00085 return q.ull;
00086 }
00087
00088 static inline int rtai_imuldiv (int i, int mult, int div) {
00089
00090
00091
00092 int dummy;
00093
00094 __asm__ __volatile__ ( \
00095 "mull %%edx\t\n" \
00096 "div %%ecx\t\n" \
00097 : "=a" (i), "=d" (dummy)
00098 : "a" (i), "d" (mult), "c" (div));
00099
00100 return i;
00101 }
00102
00103 static inline long long rtai_llimd(long long ll, int mult, int div) {
00104
00105
00106
00107 __asm__ __volatile ( \
00108 "movl %%edx,%%ecx\t\n" \
00109 "mull %%esi\t\n" \
00110 "movl %%eax,%%ebx\n\t" \
00111 "movl %%ecx,%%eax\t\n" \
00112 "movl %%edx,%%ecx\t\n" \
00113 "mull %%esi\n\t" \
00114 "addl %%ecx,%%eax\t\n" \
00115 "adcl $0,%%edx\t\n" \
00116 "divl %%edi\n\t" \
00117 "movl %%eax,%%ecx\t\n" \
00118 "movl %%ebx,%%eax\t\n" \
00119 "divl %%edi\n\t" \
00120 "sal $1,%%edx\t\n" \
00121 "cmpl %%edx,%%edi\t\n" \
00122 "movl %%ecx,%%edx\n\t" \
00123 "jge 1f\t\n" \
00124 "addl $1,%%eax\t\n" \
00125 "adcl $0,%%edx\t\n" \
00126 "1:\t\n" \
00127 : "=A" (ll) \
00128 : "A" (ll), "S" (mult), "D" (div) \
00129 : "%ebx", "%ecx");
00130
00131 return ll;
00132 }
00133
00134
00135
00136
00137
00138
00139 static inline unsigned long long rtai_u64div32c(unsigned long long a,
00140 unsigned long b,
00141 int *r) {
00142 __asm__ __volatile(
00143 "\n movl %%eax,%%ebx"
00144 "\n movl %%edx,%%eax"
00145 "\n xorl %%edx,%%edx"
00146 "\n divl %%ecx"
00147 "\n xchgl %%eax,%%ebx"
00148 "\n divl %%ecx"
00149 "\n movl %%edx,%%ecx"
00150 "\n movl %%ebx,%%edx"
00151 : "=a" (((unsigned long *)((void *)&a))[0]), "=d" (((unsigned long *)((void *)&a))[1])
00152 : "a" (((unsigned long *)((void *)&a))[0]), "d" (((unsigned long *)((void *)&a))[1]), "c" (b)
00153 : "%ebx"
00154 );
00155
00156 return a;
00157 }
00158
00159 #if defined(__KERNEL__) && !defined(__cplusplus)
00160 #include <linux/sched.h>
00161 #include <linux/interrupt.h>
00162 #include <asm/desc.h>
00163 #include <asm/system.h>
00164 #include <asm/io.h>
00165 #include <asm/rtai_atomic.h>
00166 #include <asm/rtai_fpu.h>
00167 #ifdef CONFIG_X86_LOCAL_APIC
00168 #include <asm/fixmap.h>
00169 #include <asm/apic.h>
00170 #endif
00171 #include <rtai_trace.h>
00172
00173 #define RTAI_DOMAIN_ID 0x52544149
00174 #define RTAI_NR_SRQS 32
00175
00176 #define RTAI_SMP_NOTIFY_VECTOR RTAI_APIC1_VECTOR
00177 #define RTAI_SMP_NOTIFY_IPI RTAI_APIC1_IPI
00178 #define RTAI_APIC_TIMER_VECTOR RTAI_APIC2_VECTOR
00179 #define RTAI_APIC_TIMER_IPI RTAI_APIC2_IPI
00180
00181 #define RTAI_TIMER_8254_IRQ 0
00182 #define RTAI_FREQ_8254 1193180
00183 #define RTAI_APIC_ICOUNT ((RTAI_FREQ_APIC + HZ/2)/HZ)
00184 #define RTAI_COUNTER_2_LATCH 0xfffe
00185 #define RTAI_LATENCY_8254 CONFIG_RTAI_SCHED_8254_LATENCY
00186 #define RTAI_SETUP_TIME_8254 2011
00187
00188 #define RTAI_CALIBRATED_APIC_FREQ 0
00189 #define RTAI_FREQ_APIC (rtai_tunables.apic_freq)
00190 #define RTAI_LATENCY_APIC CONFIG_RTAI_SCHED_APIC_LATENCY
00191 #define RTAI_SETUP_TIME_APIC 1000
00192
00193 #define RTAI_TIME_LIMIT 0x7FFFFFFFFFFFFFFFLL
00194
00195 #define RTAI_IFLAG 9
00196
00197 #define rtai_cpuid() adeos_processor_id()
00198 #define rtai_tskext ptd
00199
00200 extern adomain_t rtai_domain;
00201
00202
00203 #define rtai_hw_cli() adeos_hw_cli()
00204 #define rtai_hw_sti() adeos_hw_sti()
00205 #define rtai_hw_save_flags_and_cli(x) adeos_hw_local_irq_save(flags)
00206 #define rtai_hw_restore_flags(x) adeos_hw_local_irq_restore(flags)
00207 #define rtai_hw_save_flags(x) adeos_hw_local_irq_flags(flags)
00208
00209
00210 #define rtai_cli() adeos_stall_pipeline_from(&rtai_domain)
00211 #define rtai_sti() adeos_unstall_pipeline_from(&rtai_domain)
00212 #define rtai_save_flags_and_cli(x) ((x) = adeos_test_and_stall_pipeline_from(&rtai_domain))
00213 #define rtai_restore_flags(x) adeos_restore_pipeline_from(&rtai_domain,(x))
00214 #define rtai_save_flags(x) ((x) = adeos_test_pipeline_from(&rtai_domain))
00215
00216
00217 #define local_irq_restore_nosync(flags, cpuid) do { adeos_restore_pipeline_nosync(adp_root, flags, cpuid); } while (0)
00218
00219 typedef int (*rt_irq_handler_t)(unsigned irq, void *cookie);
00220
00221 #ifdef CONFIG_X86_TSC
00222
00223 #define RTAI_CALIBRATED_CPU_FREQ 0
00224 #define RTAI_CPU_FREQ (rtai_tunables.cpu_freq)
00225
00226 #if 0
00227 static inline unsigned long long _rtai_hidden_rdtsc (void) {
00228 unsigned long long t;
00229 __asm__ __volatile__( "rdtsc" : "=A" (t));
00230 return t;
00231 }
00232 #define rtai_rdtsc() _rtai_hidden_rdtsc()
00233 #else
00234 #define rtai_rdtsc() ({ unsigned long long t; __asm__ __volatile__( "rdtsc" : "=A" (t)); t; })
00235 #endif
00236
00237 #else
00238
00239 #define RTAI_CPU_FREQ RTAI_FREQ_8254
00240 #define RTAI_CALIBRATED_CPU_FREQ RTAI_FREQ_8254
00241
00242 #define rtai_rdtsc() rd_8254_ts()
00243
00244 #endif
00245
00246 struct calibration_data {
00247
00248 unsigned long cpu_freq;
00249 unsigned long apic_freq;
00250 int latency;
00251 int setup_time_TIMER_CPUNIT;
00252 int setup_time_TIMER_UNIT;
00253 int timers_tol[RTAI_NR_CPUS];
00254 };
00255
00256 struct apic_timer_setup_data {
00257
00258 int mode;
00259 int count;
00260 };
00261
00262 extern struct rt_times rt_times;
00263
00264 extern struct rt_times rt_smp_times[RTAI_NR_CPUS];
00265
00266 extern struct calibration_data rtai_tunables;
00267
00268 extern volatile unsigned long rtai_cpu_realtime;
00269
00270 extern volatile unsigned long rtai_cpu_lock;
00271
00272 extern struct rtai_switch_data {
00273 volatile unsigned long depth;
00274 volatile unsigned long oldflags;
00275 } rtai_linux_context[RTAI_NR_CPUS];
00276
00277 irqreturn_t rtai_broadcast_to_local_timers(int irq,
00278 void *dev_id,
00279 struct pt_regs *regs);
00280
00281 #ifdef CONFIG_SMP
00282
00283 #define SCHED_VECTOR RTAI_SMP_NOTIFY_VECTOR
00284 #define SCHED_IPI RTAI_SMP_NOTIFY_IPI
00285
00286 #define _send_sched_ipi(dest) \
00287 do { \
00288 apic_wait_icr_idle(); \
00289 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(dest)); \
00290 apic_write_around(APIC_ICR, APIC_DEST_LOGICAL | SCHED_VECTOR); \
00291 } while (0)
00292
00293 #ifdef CONFIG_PREEMPT
00294 #define rt_spin_lock(lock) _raw_spin_lock(lock)
00295 #define rt_spin_unlock(lock) _raw_spin_unlock(lock)
00296 #else
00297 #define rt_spin_lock(lock) spin_lock(lock)
00298 #define rt_spin_unlock(lock) spin_unlock(lock)
00299 #endif
00300
00301 static inline void rt_spin_lock_irq(spinlock_t *lock) {
00302
00303 rtai_cli();
00304 rt_spin_lock(lock);
00305 }
00306
00307 static inline void rt_spin_unlock_irq(spinlock_t *lock) {
00308
00309 rt_spin_unlock(lock);
00310 rtai_sti();
00311 }
00312
00313 static inline unsigned long rt_spin_lock_irqsave(spinlock_t *lock) {
00314
00315 unsigned long flags;
00316 rtai_save_flags_and_cli(flags);
00317 rt_spin_lock(lock);
00318 return flags;
00319 }
00320
00321 static inline void rt_spin_unlock_irqrestore(unsigned long flags, spinlock_t *lock)
00322 {
00323 rt_spin_unlock(lock);
00324 rtai_restore_flags(flags);
00325 }
00326
00327 static inline void rt_get_global_lock(void)
00328 {
00329 rtai_cli();
00330 if (!test_and_set_bit(adeos_processor_id(), &rtai_cpu_lock)) {
00331 while (test_and_set_bit(31, &rtai_cpu_lock)) {
00332 cpu_relax();
00333 }
00334 }
00335 }
00336
00337 static inline void rt_release_global_lock(void)
00338 {
00339 rtai_cli();
00340 if (test_and_clear_bit(adeos_processor_id(), &rtai_cpu_lock)) {
00341 test_and_clear_bit(31, &rtai_cpu_lock);
00342 cpu_relax();
00343 }
00344 }
00345
00358 static inline void rt_global_cli(void)
00359 {
00360 rt_get_global_lock();
00361 }
00362
00369 static inline void rt_global_sti(void)
00370 {
00371 rt_release_global_lock();
00372 rtai_sti();
00373 }
00374
00375 #define rtai_save_flags_irqbit_and_cli() ((!adeos_test_and_stall_pipeline_from(&rtai_domain)) << RTAI_IFLAG)
00376
00383 static inline int rt_global_save_flags_and_cli(void)
00384 {
00385 unsigned long flags = rtai_save_flags_irqbit_and_cli();
00386
00387 if (!test_and_set_bit(adeos_processor_id(), &rtai_cpu_lock)) {
00388 while (test_and_set_bit(31, &rtai_cpu_lock)) {
00389 cpu_relax();
00390 }
00391 return flags | 1;
00392 }
00393 return flags;
00394 }
00395
00403 static inline void rt_global_save_flags(unsigned long *flags)
00404 {
00405 unsigned long hflags = rtai_save_flags_irqbit_and_cli();
00406
00407 *flags = test_bit(adeos_processor_id(), &rtai_cpu_lock) ? hflags : hflags | 1;
00408 if (hflags) {
00409 rtai_sti();
00410 }
00411 }
00412
00420 static inline void rt_global_restore_flags(unsigned long flags)
00421 {
00422 switch (flags & ((1 << RTAI_IFLAG) | 1)) {
00423 case (1 << RTAI_IFLAG) | 1:
00424 rt_release_global_lock();
00425 rtai_sti();
00426 break;
00427 case (1 << RTAI_IFLAG) | 0:
00428 rt_get_global_lock();
00429 rtai_sti();
00430 break;
00431 case (0 << RTAI_IFLAG) | 1:
00432 rt_release_global_lock();
00433 break;
00434 case (0 << RTAI_IFLAG) | 0:
00435 rt_get_global_lock();
00436 break;
00437 }
00438 }
00439
00440 #else
00441
00442 #define _send_sched_ipi(dest)
00443
00444 #define rt_spin_lock(lock)
00445 #define rt_spin_unlock(lock)
00446
00447 #define rt_spin_lock_irq(lock) do { rtai_cli(); } while (0)
00448 #define rt_spin_unlock_irq(lock) do { rtai_sti(); } while (0)
00449
00450 static inline unsigned long rt_spin_lock_irqsave(spinlock_t *lock)
00451 {
00452 unsigned long flags;
00453 rtai_save_flags_and_cli(flags);
00454 return flags;
00455 }
00456 #define rt_spin_unlock_irqrestore(flags, lock) do { rtai_restore_flags(flags); } while (0)
00457
00458 #define rt_get_global_lock() do { rtai_cli(); } while (0)
00459 #define rt_release_global_lock()
00460
00461 #define rt_global_cli() do { rtai_cli(); } while (0)
00462 #define rt_global_sti() do { rtai_sti(); } while (0)
00463
00464 static inline unsigned long rt_global_save_flags_and_cli(void)
00465 {
00466 unsigned long flags;
00467 rtai_save_flags_and_cli(flags);
00468 return flags;
00469 }
00470 #define rt_global_restore_flags(flags) do { rtai_restore_flags(flags); } while (0)
00471
00472 #define rt_global_save_flags(flags) do { rtai_save_flags(*flags); } while (0)
00473
00474 #endif
00475
00476 #define rt_printk printk
00477
00478 static inline void rt_switch_to_real_time(int cpuid)
00479 {
00480 TRACE_RTAI_SWITCHTO_RT(cpuid);
00481 if (!rtai_linux_context[cpuid].depth++) {
00482 local_irq_save(rtai_linux_context[cpuid].oldflags);
00483 test_and_set_bit(cpuid, &rtai_cpu_realtime);
00484 }
00485 }
00486
00487 static inline void rt_switch_to_linux(int cpuid)
00488 {
00489 TRACE_RTAI_SWITCHTO_LINUX(cpuid);
00490 if (rtai_linux_context[cpuid].depth) {
00491 if (!--rtai_linux_context[cpuid].depth) {
00492 test_and_clear_bit(cpuid, &rtai_cpu_realtime);
00493 local_irq_restore_nosync(rtai_linux_context[cpuid].oldflags, cpuid);
00494 }
00495 return;
00496 }
00497 rt_printk("*** ERROR: EXCESS LINUX_UNLOCK ***\n");
00498 }
00499
00500 #define in_hrt_mode(cpuid) (test_bit(cpuid, &rtai_cpu_realtime))
00501
00502
00503 static inline void rt_set_timer_delay (int delay) {
00504
00505 if (delay) {
00506 unsigned long flags;
00507 rtai_hw_save_flags_and_cli(flags);
00508 #ifdef CONFIG_X86_LOCAL_APIC
00509 apic_read(APIC_TMICT);
00510 apic_write(APIC_TMICT, delay);
00511 #else
00512 outb(delay & 0xff,0x40);
00513 outb(delay >> 8,0x40);
00514 #endif
00515 rtai_hw_restore_flags(flags);
00516 }
00517 }
00518
00519
00520
00521 unsigned long rtai_critical_enter(void (*synch)(void));
00522
00523 void rtai_critical_exit(unsigned long flags);
00524
00525 int rtai_calibrate_8254(void);
00526
00527 void rtai_set_linux_task_priority(struct task_struct *task,
00528 int policy,
00529 int prio);
00530
00531 #endif
00532
00533
00534
00535 #ifdef __KERNEL__
00536
00537 #include <linux/kernel.h>
00538
00539 #define rtai_print_to_screen printk
00540
00541 #ifdef __cplusplus
00542 extern "C" {
00543 #endif
00544
00545 int rt_request_irq(unsigned irq,
00546 int (*handler)(unsigned irq, void *cookie),
00547 void *cookie,
00548 int retmode);
00549
00550 int rt_release_irq(unsigned irq);
00551
00552 void rt_set_irq_cookie(unsigned irq, void *cookie);
00553
00554 void rt_set_irq_retmode(unsigned irq, int fastret);
00555
00560 unsigned rt_startup_irq(unsigned irq);
00561
00562 void rt_shutdown_irq(unsigned irq);
00563
00564 void rt_enable_irq(unsigned irq);
00565
00566 void rt_disable_irq(unsigned irq);
00567
00568 void rt_mask_and_ack_irq(unsigned irq);
00569
00570 void rt_unmask_irq(unsigned irq);
00571
00572 void rt_ack_irq(unsigned irq);
00573
00576
00577 #define rtai_do_x86int(irq, handler) \
00578 do { \
00579 __asm__ __volatile__ ( "pushfl; push %%cs; call *%1": : "a" (irq), "m" (handler)); \
00580 } while (0)
00581
00582 struct desc_struct rtai_set_gate_vector (unsigned vector, int type, int dpl, void *handler);
00583
00584 void rtai_reset_gate_vector(unsigned vector, struct desc_struct e);
00585
00586
00587 void rt_do_irq(unsigned irq);
00588
00589 int rt_request_linux_irq(unsigned irq,
00590 irqreturn_t (*handler)(int irq,
00591 void *dev_id,
00592 struct pt_regs *regs),
00593 char *name,
00594 void *dev_id);
00595
00596 int rt_free_linux_irq(unsigned irq,
00597 void *dev_id);
00598
00599 void rt_pend_linux_irq(unsigned irq);
00600
00601 #define adeos_pend_uncond(irq, cpuid) rt_pend_linux_irq(irq)
00602
00603 void rt_pend_linux_srq(unsigned srq);
00604
00605 int rt_request_srq(unsigned label,
00606 void (*k_handler)(void),
00607 long long (*u_handler)(unsigned));
00608
00609 int rt_free_srq(unsigned srq);
00610
00611 int rt_assign_irq_to_cpu(int irq,
00612 unsigned long cpus_mask);
00613
00614 int rt_reset_irq_to_sym_mode(int irq);
00615
00616 void rt_request_timer_cpuid(void (*handler)(void),
00617 unsigned tick,
00618 int cpuid);
00619
00620 void rt_request_apic_timers(void (*handler)(void),
00621 struct apic_timer_setup_data *tmdata);
00622
00623 void rt_free_apic_timers(void);
00624
00625 int rt_request_timer(void (*handler)(void), unsigned tick, int use_apic);
00626
00627 void rt_free_timer(void);
00628
00629 RT_TRAP_HANDLER rt_set_trap_handler(RT_TRAP_HANDLER handler);
00630
00631 #define rt_mount()
00632
00633 #define rt_umount()
00634
00635 RTIME rd_8254_ts(void);
00636
00637 void rt_setup_8254_tsc(void);
00638
00639 void (*rt_set_ihook(void (*hookfn)(int)))(int);
00640
00641
00642
00643 static inline int rt_request_global_irq(unsigned irq, void (*handler)(void))
00644 {
00645 return rt_request_irq(irq, (int (*)(unsigned,void *))handler, 0, 0);
00646 }
00647
00648 static inline int rt_request_global_irq_ext(unsigned irq, void (*handler)(void), unsigned long cookie)
00649 {
00650 return rt_request_irq(irq, (int (*)(unsigned,void *))handler, (void *)cookie, 1);
00651 }
00652
00653 static inline void rt_set_global_irq_ext(unsigned irq, int ext, unsigned long cookie)
00654 {
00655 rt_set_irq_cookie(irq, (void *)cookie);
00656 }
00657
00658 static inline int rt_free_global_irq(unsigned irq)
00659 {
00660 return rt_release_irq(irq);
00661 }
00662
00663 #ifdef __cplusplus
00664 }
00665 #endif
00666
00667 #if !defined(CONFIG_ADEOS_NOTHREADS)
00668
00669 static inline struct task_struct *rtai_get_root_current (int cpuid)
00670 {
00671 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00672 return (struct task_struct *)(((u_long)adp_root->esp[cpuid]) & (~8191UL));
00673 #else
00674 return ((struct thread_info *)(((u_long)adp_root->esp[cpuid]) & (~((THREAD_SIZE)-1))))->task;
00675 #endif
00676 }
00677
00678 #else
00679
00680 static inline struct task_struct *rtai_get_root_current (int cpuid)
00681 {
00682 return current;
00683 }
00684
00685 #endif
00686
00687 #endif
00688
00689 #include <asm/rtai_oldnames.h>
00690 #include <asm/rtai_emulate_tsc.h>
00691
00692 #define RTAI_DEFAULT_TICK 100000
00693 #ifdef CONFIG_RTAI_TRACE
00694 #define RTAI_DEFAULT_STACKSZ 8192
00695 #else
00696 #define RTAI_DEFAULT_STACKSZ 1024
00697 #endif
00698
00701 #endif