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