rtai-core/include/asm-ppc/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 */

Generated on Sat Jul 24 19:36:02 2004 for RTAI API by doxygen 1.3.4