# rtai_hal.h

Go to the documentation of this file.

    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 /* !CONFIG_SMP */
    00049 #define RTAI_NR_CPUS  1
    00050 #endif /* CONFIG_SMP */
    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 /* One of the silly thing of 32 bits PPCs, no 64 bits result for 32 bits mul. */
    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 /* One of the silly thing of 32 bits PPCs, no 64 by 32 bits divide. */
    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     /* Returns (int)i = (int)i*(int)(mult)/(int)div. */
    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     /* Returns (long long)ll = (int)ll*(int)(mult)/(int)div. */
    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 /* Use these ones when fiddling with the (local A)PIC */
    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 /* Bits from rtai_status. */
    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         /* See Motorola reference manual for 32 bits PPCs. */
    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 /* rtai_get_current() is Adeos-specific. Since real-time interrupt
    00255    handlers are called on behalf of the RTAI domain stack, we cannot
    00256    infere the "current" Linux task address using %esp. We must use the
    00257    suspended Linux domain's stack pointer instead. */
    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 /* !CONFIG_SMP */
    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 /* CONFIG_SMP */
    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 /* adeos_load_cpuid */
    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 /* adeos_load_cpuid */
    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 /* adeos_load_cpuid */
    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 /* adeos_load_cpuid */
    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     /* NOTE: delay MUST be 0 if a periodic timer is being used. */
    00498     if (delay == 0)
    00499         {
    00500 #ifdef CONFIG_40x
    00501         return;
    00502 #else  /* !CONFIG_40x */
    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 /* CONFIG_40x */
    00515         }
    00516 #ifdef CONFIG_40x
    00517     mtspr(SPRN_PIT, delay);
    00518 #else
    00519     set_dec(delay);
    00520 #endif
    00521 }
    00522
    00523     /* Private interface -- Internal use only */
    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 /* __KERNEL__ && !__cplusplus */
    00536
    00537     /* Public interface */
    00538
    00539 #ifdef __KERNEL__
    00540
    00541 #include <linux/kernel.h>
    00542
    00543 #ifdef __cplusplus
    00544 extern "C" {
    00545 #endif /* __cplusplus */
    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 /* This is safe over Adeos */
    00630
    00631 #ifdef __cplusplus
    00632 }
    00633 #endif /* __cplusplus */
    00634
    00635 #endif /* __KERNEL__ */
    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 /* !CONFIG_RTAI_TRACE */
    00643 #define RTAI_DEFAULT_STACKSZ 4092
    00644 #endif /* CONFIG_RTAI_TRACE */
    00645
    00648 #endif /* !_RTAI_ASM_PPC_HAL_H */