00001
00040 #ifndef _RTAI_ASM_PPC_HAL_H
00041 #define _RTAI_ASM_PPC_HAL_H
00042
00043 #include <asm/rtai_vectors.h>
00044 #include <rtai_types.h>
00045
00046 #ifdef CONFIG_SMP
00047 #define RTAI_NR_CPUS CONFIG_RTAI_CPUS
00048 #else
00049 #define RTAI_NR_CPUS 1
00050 #endif
00051
00052 static inline int ffnz(unsigned long ul) {
00053
00054 __asm__ __volatile__ ("cntlzw %0, %1" : "=r" (ul) : "r" (ul & (-ul)));
00055
00056 return 31 - ul;
00057 }
00058
00059
00060 static inline unsigned long long rtai_ullmul(unsigned long m0,
00061 unsigned long m1) {
00062
00063 unsigned long long res;
00064
00065 __asm__ __volatile__ ("mulhwu %0, %1, %2"
00066 : "=r" (((unsigned long *)&res)[0])
00067 : "%r" (m0), "r" (m1));
00068 ((unsigned long *)&res)[1] = m0*m1;
00069
00070 return res;
00071 }
00072
00073
00074 static inline unsigned long long rtai_ulldiv(unsigned long long ull,
00075 unsigned long uld,
00076 unsigned long *r) {
00077
00078 unsigned long long q, rf;
00079 unsigned long qh, rh, ql, qf;
00080
00081 q = 0;
00082 rf = (unsigned long long)(0xFFFFFFFF - (qf = 0xFFFFFFFF / uld) * uld) + 1ULL;
00083
00084 while (ull >= uld)
00085 {
00086 ((unsigned long *)&q)[0] += (qh = ((unsigned long *)&ull)[0] / uld);
00087 rh = ((unsigned long *)&ull)[0] - qh * uld;
00088 q += rh * (unsigned long long)qf + (ql = ((unsigned long *)&ull)[1] / uld);
00089 ull = rh * rf + (((unsigned long *)&ull)[1] - ql * uld);
00090 }
00091
00092 *r = ull;
00093 return q;
00094 }
00095
00096 static inline int rtai_imuldiv(int i, int mult, int div) {
00097
00098
00099
00100 unsigned long q, r;
00101
00102 q = rtai_ulldiv(rtai_ullmul(i, mult), div, &r);
00103
00104 return (r + r) > div ? q + 1 : q;
00105 }
00106
00107 static inline unsigned long long rtai_llimd(unsigned long long ull,
00108 unsigned long mult,
00109 unsigned long div) {
00110
00111
00112
00113 unsigned long long low;
00114 unsigned long q, r;
00115
00116 low = rtai_ullmul(((unsigned long *)&ull)[1], mult);
00117 q = rtai_ulldiv(rtai_ullmul(((unsigned long *)&ull)[0], mult) +
00118 ((unsigned long *)&low)[0], div, (unsigned long *)&low);
00119 low = rtai_ulldiv(low, div, &r);
00120 ((unsigned long *)&low)[0] += q;
00121
00122 return (r + r) > div ? low + 1 : low;
00123 }
00124
00125
00126 #if defined(__KERNEL__) && !defined(__cplusplus)
00127 #include <linux/sched.h>
00128 #include <asm/system.h>
00129 #include <asm/io.h>
00130 #include <asm/time.h>
00131 #include <asm/rtai_atomic.h>
00132 #include <asm/rtai_fpu.h>
00133 #include <rtai_trace.h>
00134
00135 #define RTAI_DOMAIN_ID 0x52544149
00136 #define RTAI_NR_SRQS 32
00137
00138 #ifdef FIXME
00139 #define RTAI_SMP_NOTIFY_VECTOR RTAI_APIC3_VECTOR
00140 #define RTAI_SMP_NOTIFY_IPI RTAI_APIC3_IPI
00141 #define RTAI_APIC_TIMER_VECTOR RTAI_APIC4_VECTOR
00142 #define RTAI_APIC_TIMER_IPI RTAI_APIC4_IPI
00143 #endif
00144
00145 #define RTAI_TIMER_DECR_IRQ IPIPE_VIRQ_BASE
00146 #define RTAI_TIMER_8254_IRQ RTAI_TIMER_DECR_IRQ
00147 #define RTAI_FREQ_8254 (rtai_tunables.cpu_freq)
00148 #ifdef FIXME
00149 #define RTAI_APIC_ICOUNT ((RTAI_FREQ_APIC + HZ/2)/HZ)
00150 #define RTAI_COUNTER_2_LATCH 0xfffe
00151 #endif
00152 #define RTAI_LATENCY_8254 CONFIG_RTAI_SCHED_8254_LATENCY
00153 #define RTAI_SETUP_TIME_8254 500
00154
00155 #ifdef FIXME
00156 #define RTAI_CALIBRATED_APIC_FREQ 0
00157 #define RTAI_FREQ_APIC (rtai_tunables.apic_freq)
00158 #define RTAI_LATENCY_APIC CONFIG_RTAI_SCHED_APIC_LATENCY
00159 #define RTAI_SETUP_TIME_APIC 1000
00160 #endif
00161
00162 #define RTAI_TIME_LIMIT 0x7FFFFFFFFFFFFFFFLL
00163
00164 #define RTAI_IFLAG 15
00165
00166 #define rtai_cli() adeos_stall_pipeline_from(&rtai_domain)
00167 #define rtai_sti() adeos_unstall_pipeline_from(&rtai_domain)
00168 #define rtai_local_irq_save(x) ((x) = adeos_test_and_stall_pipeline_from(&rtai_domain))
00169 #define rtai_local_irq_restore(x) adeos_restore_pipeline_from(&rtai_domain,(x))
00170 #define rtai_local_irq_flags(x) ((x) = adeos_test_pipeline_from(&rtai_domain))
00171 #define rtai_local_irq_test() adeos_test_pipeline_from(&rtai_domain)
00172 #define rtai_get_iflag_and_cli() ((!adeos_test_and_stall_pipeline_from(&rtai_domain)) << RTAI_IFLAG)
00173
00174 #define rtai_hw_lock(flags) adeos_hw_local_irq_save(flags)
00175 #define rtai_hw_unlock(flags) adeos_hw_local_irq_restore(flags)
00176 #define rtai_hw_enable() adeos_hw_sti()
00177 #define rtai_hw_disable() adeos_hw_cli()
00178
00179 typedef void (*rt_irq_handler_t)(unsigned irq,
00180 void *cookie);
00181 void rtai_linux_cli(void);
00182
00183 void rtai_linux_sti(void);
00184
00185 unsigned rtai_linux_save_flags(void);
00186
00187 void rtai_linux_restore_flags(unsigned flags);
00188
00189 void rtai_linux_restore_flags_nosync(unsigned flags, int cpuid);
00190
00191 unsigned rtai_linux_save_flags_and_cli(void);
00192
00193
00194 #define RTAI_USE_APIC 0
00195
00196 #define RTAI_CALIBRATED_CPU_FREQ 0
00197 #define RTAI_CPU_FREQ (rtai_tunables.cpu_freq)
00198
00199 static inline unsigned long long rtai_rdtsc (void) {
00200
00201 unsigned long long ts;
00202 unsigned long chk;
00203
00204 __asm__ __volatile__ ("1: mftbu %0\n"
00205 " mftb %1\n"
00206 " mftbu %2\n"
00207 " cmpw %2,%0\n"
00208 " bne 1b\n"
00209 : "=r" (((unsigned long *)&ts)[0]),
00210 "=r" (((unsigned long *)&ts)[1]),
00211 "=r" (chk));
00212 return ts;
00213 }
00214
00215 struct calibration_data {
00216
00217 unsigned long cpu_freq;
00218 unsigned long apic_freq;
00219 int latency;
00220 int setup_time_TIMER_CPUNIT;
00221 int setup_time_TIMER_UNIT;
00222 int timers_tol[RTAI_NR_CPUS];
00223 };
00224
00225 struct apic_timer_setup_data {
00226
00227 int mode;
00228 int count;
00229 };
00230
00231 extern struct rt_times rt_times;
00232
00233 extern struct rt_times rt_smp_times[RTAI_NR_CPUS];
00234
00235 extern struct calibration_data rtai_tunables;
00236
00237 extern volatile unsigned long rtai_status;
00238
00239 extern volatile unsigned long rtai_cpu_realtime;
00240
00241 extern volatile unsigned long rtai_cpu_lock;
00242
00243 extern volatile unsigned long rtai_cpu_lxrt;
00244
00245 extern struct rtai_switch_data {
00246 struct task_struct *oldtask;
00247 unsigned long oldflags;
00248 } rtai_linux_context[RTAI_NR_CPUS];
00249
00250 extern adomain_t rtai_domain;
00251
00252 extern int rtai_adeos_ptdbase;
00253
00254
00255
00256
00257
00258
00259 static inline struct task_struct *rtai_get_current (int cpuid)
00260
00261 {
00262 register int *esp asm ("r1");
00263 #ifdef FIXME
00264 __asm__ volatile("movl %%esp, %0" : "=r" (esp));
00265 #endif
00266 if (esp >= rtai_domain.estackbase[cpuid] && esp < rtai_domain.estackbase[cpuid] + 2048)
00267 return (struct task_struct *)(((u_long)adp_root->esp[cpuid]) & (~8191UL));
00268
00269 return current;
00270 }
00271
00272 #define rt_spin_lock(lock) spin_lock(lock)
00273 #define rt_spin_unlock(lock) spin_unlock(lock)
00274
00275 static inline void rt_spin_lock_irq(spinlock_t *lock) {
00276
00277 rtai_cli();
00278 rt_spin_lock(lock);
00279 }
00280
00281 static inline void rt_spin_unlock_irq(spinlock_t *lock) {
00282
00283 rt_spin_unlock(lock);
00284 rtai_sti();
00285 }
00286
00287 static inline unsigned long rt_spin_lock_irqsave(spinlock_t *lock) {
00288
00289 unsigned long flags;
00290 rtai_local_irq_save(flags);
00291 rt_spin_lock(lock);
00292 return flags;
00293 }
00294
00295 static inline void rt_spin_unlock_irqrestore(unsigned long flags,
00296 spinlock_t *lock) {
00297 rt_spin_unlock(lock);
00298 rtai_local_irq_restore(flags);
00299 }
00300
00301 #ifdef CONFIG_SMP
00302
00303 #define CPU_RELAX(x) \
00304 do { \
00305 int i = 0; \
00306 do \
00307 cpu_relax(); \
00308 while (++i < x); \
00309 } while(0)
00310 #else
00311 #define CPU_RELAX(x)
00312
00313 void rtai_broadcast_to_timers(int irq,
00314 void *dev_id,
00315 struct pt_regs *regs);
00316 #endif
00317
00318 static inline void rt_get_global_lock(void) {
00319
00320 adeos_declare_cpuid;
00321
00322 rtai_cli();
00323
00324 #ifdef adeos_load_cpuid
00325 adeos_load_cpuid();
00326 #endif
00327
00328 if (!test_and_set_bit(cpuid,&rtai_cpu_lock))
00329 while (test_and_set_bit(31,&rtai_cpu_lock))
00330 CPU_RELAX(cpuid);
00331 }
00332
00333 static inline void rt_release_global_lock(void) {
00334
00335 adeos_declare_cpuid;
00336
00337 rtai_cli();
00338
00339 #ifdef adeos_load_cpuid
00340 adeos_load_cpuid();
00341 #endif
00342
00343 if (test_and_clear_bit(cpuid,&rtai_cpu_lock)) {
00344 clear_bit(31,&rtai_cpu_lock);
00345 CPU_RELAX(cpuid);
00346 }
00347 }
00348
00361 static inline void rt_global_cli(void) {
00362 rt_get_global_lock();
00363 }
00364
00371 static inline void rt_global_sti(void) {
00372 rt_release_global_lock();
00373 rtai_sti();
00374 }
00375
00382 static inline int rt_global_save_flags_and_cli(void) {
00383
00384 unsigned long flags = rtai_get_iflag_and_cli();
00385 adeos_declare_cpuid;
00386
00387 #ifdef adeos_load_cpuid
00388 adeos_load_cpuid();
00389 #endif
00390
00391 if (!test_and_set_bit(cpuid,&rtai_cpu_lock))
00392 {
00393 while (test_and_set_bit(31,&rtai_cpu_lock))
00394 CPU_RELAX(cpuid);
00395
00396 return flags | 1;
00397 }
00398
00399 return flags;
00400 }
00401
00409 static inline void rt_global_save_flags(unsigned long *flags) {
00410
00411 unsigned long hflags = rtai_get_iflag_and_cli(), rflags;
00412 adeos_declare_cpuid;
00413
00414 #ifdef adeos_load_cpuid
00415 adeos_load_cpuid();
00416 #endif
00417
00418 if (test_bit(cpuid,&rtai_cpu_lock))
00419 rflags = hflags;
00420 else
00421 rflags = hflags | 1;
00422
00423 if (hflags)
00424 rtai_sti();
00425
00426 *flags = rflags;
00427 }
00428
00436 static inline void rt_global_restore_flags(unsigned long flags) {
00437
00438 switch (flags)
00439 {
00440 case (1 << RTAI_IFLAG) | 1:
00441
00442 rt_release_global_lock();
00443 rtai_sti();
00444 break;
00445
00446 case (1 << RTAI_IFLAG) | 0:
00447
00448 rt_get_global_lock();
00449 rtai_sti();
00450 break;
00451
00452 case (0 << RTAI_IFLAG) | 1:
00453
00454 rt_release_global_lock();
00455 break;
00456
00457 case (0 << RTAI_IFLAG) | 0:
00458
00459 rt_get_global_lock();
00460 break;
00461 }
00462 }
00463
00464 static inline void rt_switch_to_real_time(int cpuid) {
00465
00466 TRACE_RTAI_SWITCHTO_RT(cpuid);
00467 rtai_linux_context[cpuid].oldtask = rtai_get_current(cpuid);
00468 rtai_linux_context[cpuid].oldflags = rtai_linux_save_flags_and_cli();
00469 set_bit(cpuid,&rtai_cpu_realtime);
00470 }
00471
00472 static inline void rt_switch_to_linux(int cpuid) {
00473
00474 TRACE_RTAI_SWITCHTO_LINUX(cpuid);
00475 clear_bit(cpuid,&rtai_cpu_realtime);
00476 rtai_linux_restore_flags_nosync(rtai_linux_context[cpuid].oldflags,cpuid);
00477 rtai_linux_context[cpuid].oldtask = NULL;
00478 }
00479
00480 static inline struct task_struct *rt_whoislinux(int cpuid) {
00481
00482 return rtai_linux_context[cpuid].oldtask;
00483 }
00484
00485 static inline int rt_is_linux (void) {
00486
00487 return !test_bit(adeos_processor_id(),&rtai_cpu_realtime);
00488 }
00489
00490 static inline int rt_is_lxrt (void) {
00491
00492 return test_bit(adeos_processor_id(),&rtai_cpu_lxrt);
00493 }
00494
00495 static inline void rt_set_timer_delay (int delay) {
00496
00497
00498 if (delay == 0)
00499 {
00500 #ifdef CONFIG_40x
00501 return;
00502 #else
00503 if ((delay = rt_times.intr_time - rtai_rdtsc()) <= 0)
00504 {
00505 int lost = 0;
00506 do
00507 {
00508 lost++;
00509 rt_times.intr_time += (RTIME)rt_times.periodic_tick;
00510 }
00511 while ((delay = rt_times.intr_time - rtai_rdtsc()) <= 0);
00512 printk("%d timer interrupt(s) lost\n", lost);
00513 }
00514 #endif
00515 }
00516 #ifdef CONFIG_40x
00517 mtspr(SPRN_PIT, delay);
00518 #else
00519 set_dec(delay);
00520 #endif
00521 }
00522
00523
00524
00525 #ifdef FIXME
00526 void rtai_attach_lxrt(void);
00527
00528 void rtai_detach_lxrt(void);
00529
00530 void rtai_switch_linux_mm(struct task_struct *prev,
00531 struct task_struct *next,
00532 int cpuid);
00533 #endif
00534
00535 #endif
00536
00537
00538
00539 #ifdef __KERNEL__
00540
00541 #include <linux/kernel.h>
00542
00543 #ifdef __cplusplus
00544 extern "C" {
00545 #endif
00546
00547 int rt_request_irq(unsigned irq,
00548 void (*handler)(unsigned irq, void *cookie),
00549 void *cookie);
00550
00551 int rt_release_irq(unsigned irq);
00552
00553 void rt_set_irq_cookie(unsigned irq,
00554 void *cookie);
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);
00575 void rt_do_irq(unsigned irq);
00576
00577 int rt_request_linux_irq(unsigned irq,
00578 void (*handler)(int irq,
00579 void *dev_id,
00580 struct pt_regs *regs),
00581 char *name,
00582 void *dev_id);
00583
00584 int rt_free_linux_irq(unsigned irq,
00585 void *dev_id);
00586
00587 void rt_pend_linux_irq(unsigned irq);
00588
00589 void rt_pend_linux_srq(unsigned srq);
00590
00591 int rt_request_srq(unsigned label,
00592 void (*k_handler)(void),
00593 long long (*u_handler)(unsigned));
00594
00595 int rt_free_srq(unsigned srq);
00596
00597 int rt_assign_irq_to_cpu(int irq,
00598 unsigned long cpus_mask);
00599
00600 int rt_reset_irq_to_sym_mode(int irq);
00601
00602 void rt_request_timer_cpuid(void (*handler)(void),
00603 unsigned tick,
00604 int cpuid);
00605
00606 #ifdef FIXME
00607 void rt_request_apic_timers(void (*handler)(void),
00608 struct apic_timer_setup_data *tmdata);
00609
00610 void rt_free_apic_timers(void);
00611 #endif
00612
00613 int rt_request_timer(void (*handler)(void),
00614 unsigned tick,
00615 int use_apic);
00616
00617 void rt_free_timer(void);
00618
00619 #ifdef FIXME
00620 RT_TRAP_HANDLER rt_set_trap_handler(RT_TRAP_HANDLER handler);
00621 #endif
00622
00623 void rt_mount(void);
00624
00625 void rt_umount(void);
00626
00627 void (*rt_set_ihook(void (*hookfn)(int)))(int);
00628
00629 #define rt_printk printk
00630
00631 #ifdef __cplusplus
00632 }
00633 #endif
00634
00635 #endif
00636
00637 #include <asm/rtai_oldnames.h>
00638
00639 #define RTAI_DEFAULT_TICK 100000
00640 #ifdef CONFIG_RTAI_TRACE
00641 #define RTAI_DEFAULT_STACKSZ 8192
00642 #else
00643 #define RTAI_DEFAULT_STACKSZ 4092
00644 #endif
00645
00648 #endif