hal.h

Go to the documentation of this file.
00001 
00036 #ifndef _RTAI_ASM_PPC_HAL_H
00037 #define _RTAI_ASM_PPC_HAL_H
00038 
00039 #include <rtai_config.h>
00040 
00041 #define RTHAL_NR_CPUS  ADEOS_NR_CPUS
00042 
00043 typedef unsigned long long rthal_time_t;
00044 
00045 static inline unsigned long long rthal_ulldiv (unsigned long long ull,
00046                                                unsigned long uld,
00047                                                unsigned long *r)
00048 {
00049     unsigned long long q, rf;
00050     unsigned long qh, rh, ql, qf;
00051     
00052     q = 0;
00053     rf = (unsigned long long)(0xFFFFFFFF - (qf = 0xFFFFFFFF / uld) * uld) + 1ULL;
00054     
00055     while (ull >= uld) 
00056         {
00057         ((unsigned long *)&q)[0] += (qh = ((unsigned long *)&ull)[0] / uld);
00058         rh = ((unsigned long *)&ull)[0] - qh * uld;
00059         q += rh * (unsigned long long)qf + (ql = ((unsigned long *)&ull)[1] / uld);
00060         ull = rh * rf + (((unsigned long *)&ull)[1] - ql * uld);
00061         }
00062 
00063     if (r)
00064         *r = ull;
00065 
00066     return q;
00067 }
00068 
00069 #define rthal_uldivrem(ull,ul,rp) ((u_long) rthal_ulldiv((ull),(ul),(rp)))
00070 
00071 static inline unsigned long long rthal_ullmul(unsigned long m0, 
00072                                               unsigned long m1)
00073 {
00074     unsigned long long res;
00075     
00076     __asm__ __volatile__ ("mulhwu %0, %1, %2"
00077                           : "=r" (((unsigned long *)&res)[0]) 
00078                           : "%r" (m0), "r" (m1));
00079 
00080     ((unsigned long *)&res)[1] = m0*m1;
00081     
00082     return res;
00083 }
00084 
00085 static inline int rthal_imuldiv (int i, int mult, int div) {
00086 
00087     /* Returns (int)i = (int)i*(int)(mult)/(int)div. */
00088     
00089     unsigned long q, r;
00090     q = rthal_ulldiv(rthal_ullmul(i, mult), div, &r);
00091     return (r + r) > div ? q + 1 : q;
00092 }
00093 
00094 static inline long long rthal_llimd(long long ll, int mult, int div) {
00095 
00096     /* Returns (long long)ll = (int)ll*(int)(mult)/(int)div. */
00097 
00098     unsigned long long low;
00099     unsigned long q, r;
00100     
00101     low  = rthal_ullmul(((unsigned long *)&ll)[1], mult);       
00102     q = rthal_ulldiv(rthal_ullmul(((unsigned long *)&ll)[0], mult) + 
00103                      ((unsigned long *)&low)[0], div, (unsigned long *)&low);
00104     low = rthal_ulldiv(low, div, &r);
00105     ((unsigned long *)&low)[0] += q;
00106     
00107     return (r + r) > div ? low + 1 : low;
00108 }
00109 
00110 static inline unsigned long ffnz (unsigned long ul) {
00111 
00112     __asm__ __volatile__ ("cntlzw %0, %1" : "=r" (ul) : "r" (ul & (-ul)));
00113     return 31 - ul;
00114 }
00115 
00116 #if defined(__KERNEL__) && !defined(__cplusplus)
00117 #include <linux/sched.h>
00118 #include <linux/interrupt.h>
00119 #include <asm/system.h>
00120 #include <asm/time.h>
00121 #include <asm/timex.h>
00122 #include <nucleus/asm/atomic.h>
00123 #include <asm/processor.h>
00124 
00125 typedef void (*rthal_irq_handler_t)(unsigned irq,
00126                                     void *cookie);
00127 
00128 struct rthal_calibration_data {
00129 
00130     unsigned long cpu_freq;
00131     unsigned long timer_freq;
00132 };
00133 
00134 extern struct rthal_calibration_data rthal_tunables;
00135 
00136 extern volatile unsigned long rthal_cpu_realtime;
00137 
00138 extern adomain_t rthal_domain;
00139 
00140 #define RTHAL_DOMAIN_ID  0x52544149
00141 
00142 #define RTHAL_NR_SRQS    32
00143 
00144 #define RTHAL_TIMER_IRQ   ADEOS_TIMER_VIRQ
00145 #define RTHAL_TIMER_FREQ  (rthal_tunables.timer_freq)
00146 #define RTHAL_CPU_FREQ    (rthal_tunables.cpu_freq)
00147 
00148 static inline unsigned long long rthal_rdtsc (void) {
00149     unsigned long long t;
00150     adeos_hw_tsc(t);
00151     return t;
00152 }
00153 
00154 #define rthal_cli()                     adeos_stall_pipeline_from(&rthal_domain)
00155 #define rthal_sti()                     adeos_unstall_pipeline_from(&rthal_domain)
00156 #define rthal_local_irq_save(x)         ((x) = !!adeos_test_and_stall_pipeline_from(&rthal_domain))
00157 #define rthal_local_irq_restore(x)      adeos_restore_pipeline_from(&rthal_domain,(x))
00158 #define rthal_local_irq_flags(x)        ((x) = !!adeos_test_pipeline_from(&rthal_domain))
00159 #define rthal_local_irq_test()          (!!adeos_test_pipeline_from(&rthal_domain))
00160 #define rthal_local_irq_sync(x)         ((x) = !!adeos_test_and_unstall_pipeline_from(&rthal_domain))
00161 
00162 #define rthal_hw_lock(flags)            adeos_hw_local_irq_save(flags)
00163 #define rthal_hw_unlock(flags)          adeos_hw_local_irq_restore(flags)
00164 #define rthal_hw_enable()               adeos_hw_sti()
00165 #define rthal_hw_disable()              adeos_hw_cli()
00166 
00167 #define rthal_linux_sti()                adeos_unstall_pipeline_from(adp_root)
00168 #define rthal_linux_cli()                adeos_stall_pipeline_from(adp_root)
00169 #define rthal_linux_local_irq_save(x)    ((x) = !!adeos_test_and_stall_pipeline_from(adp_root))
00170 #define rthal_linux_local_irq_restore(x) adeos_restore_pipeline_from(adp_root,x)
00171 #define rthal_linux_local_irq_restore_nosync(x,cpuid) adeos_restore_pipeline_nosync(adp_root,x,cpuid)
00172 
00173 #define rthal_spin_lock(lock)    adeos_spin_lock(lock)
00174 #define rthal_spin_unlock(lock)  adeos_spin_unlock(lock)
00175 
00176 static inline void rthal_spin_lock_irq(spinlock_t *lock) {
00177 
00178     rthal_cli();
00179     rthal_spin_lock(lock);
00180 }
00181 
00182 static inline void rthal_spin_unlock_irq(spinlock_t *lock) {
00183 
00184     rthal_spin_unlock(lock);
00185     rthal_sti();
00186 }
00187 
00188 static inline unsigned long rthal_spin_lock_irqsave(spinlock_t *lock) {
00189 
00190     unsigned long flags;
00191     rthal_local_irq_save(flags);
00192     rthal_spin_lock(lock);
00193     return flags;
00194 }
00195 
00196 static inline void rthal_spin_unlock_irqrestore(unsigned long flags,
00197                                                 spinlock_t *lock) {
00198     rthal_spin_unlock(lock);
00199     rthal_local_irq_restore(flags);
00200 }
00201 
00202 #ifdef CONFIG_SMP
00203 #define rthal_cpu_relax(x) \
00204 do { \
00205    int i = 0; \
00206    do \
00207      cpu_relax(); \
00208    while (++i < x); \
00209 } while(0)
00210 #endif /* CONFIG_SMP */
00211 
00212 #if !defined(CONFIG_ADEOS_NOTHREADS)
00213 
00214 /* Since real-time interrupt handlers are called on behalf of the RTAI
00215    domain stack, we cannot infere the "current" Linux task address
00216    using %esp. We must use the suspended Linux domain's stack pointer
00217    instead. */
00218 
00219 static inline struct task_struct *rthal_get_root_current (int cpuid) {
00220     return ((struct thread_info *)(adp_root->esp[cpuid] & (~8191UL)))->task;
00221 }
00222 
00223 static inline struct task_struct *rthal_get_current (int cpuid)
00224 
00225 {
00226     register unsigned long esp asm ("r1");
00227     /* FIXME: r2 should be ok or even __adeos_current_threadinfo() - offsetof(THREAD) */
00228     
00229     if (esp >= rthal_domain.estackbase[cpuid] && esp < rthal_domain.estackbase[cpuid] + 8192)
00230         return rthal_get_root_current(cpuid);
00231 
00232     return current;
00233 }
00234 
00235 #else /* CONFIG_ADEOS_NOTHREADS */
00236 
00237 static inline struct task_struct *rthal_get_root_current (int cpuid) {
00238     return current;
00239 }
00240 
00241 static inline struct task_struct *rthal_get_current (int cpuid) {
00242     return current;
00243 }
00244 
00245 #endif /* !CONFIG_ADEOS_NOTHREADS */
00246 
00247 static inline void rthal_set_timer_shot (unsigned long delay) {
00248 
00249     if (delay) {
00250 #ifdef CONFIG_40x
00251         mtspr(SPRN_PIT,delay);
00252 #else /* !CONFIG_40x */
00253         set_dec(delay);
00254 #endif /* CONFIG_40x */
00255     }
00256 }
00257 
00258     /* Private interface -- Internal use only */
00259 
00260 unsigned long rthal_critical_enter(void (*synch)(void));
00261 
00262 void rthal_critical_exit(unsigned long flags);
00263 
00264 void rthal_set_linux_task_priority(struct task_struct *task,
00265                                    int policy,
00266                                    int prio);
00267 
00268 /* The following must be in sync w/ rthal_switch_context() in
00269    switch.S */
00270 #define RTHAL_SWITCH_FRAME_SIZE  108
00271 
00272 void rthal_switch_context(unsigned long *out_kspp,
00273                           unsigned long *in_kspp);
00274 
00275 #ifdef CONFIG_RTAI_HW_FPU
00276 
00277 typedef struct rthal_fpenv {
00278     
00279     /* This layout must follow exactely the definition of the FPU
00280        backup area in a PPC thread struct available from
00281        <asm-ppc/processor.h>. Specifically, fpr[] an fpscr words must
00282        be contiguous in memory (see arch/ppc/fpu.S). */
00283 
00284     double fpr[32];
00285     unsigned long fpscr_pad;    /* <= Hi-word of the FPR used to */
00286     unsigned long fpscr;        /* retrieve the FPSCR. */
00287 
00288 } rthal_fpenv_t;
00289 
00290 void rthal_init_fpu(rthal_fpenv_t *fpuenv);
00291 
00292 void rthal_save_fpu(rthal_fpenv_t *fpuenv);
00293 
00294 void rthal_restore_fpu(rthal_fpenv_t *fpuenv);
00295 
00296 #endif /* CONFIG_RTAI_HW_FPU */
00297 
00298 #endif /* __KERNEL__ && !__cplusplus */
00299 
00300     /* Public interface */
00301 
00302 #ifdef __KERNEL__
00303 
00304 #include <linux/kernel.h>
00305 
00306 typedef int (*rthal_trap_handler_t)(adevinfo_t *evinfo);
00307 
00308 #define rthal_printk    printk /* This is safe over Adeos */
00309 
00310 #ifdef __cplusplus
00311 extern "C" {
00312 #endif /* __cplusplus */
00313 
00314 int rthal_request_irq(unsigned irq,
00315                       void (*handler)(unsigned irq, void *cookie),
00316                       void *cookie);
00317 
00318 int rthal_release_irq(unsigned irq);
00319 
00325 int rthal_enable_irq(unsigned irq);
00326 
00327 int rthal_disable_irq(unsigned irq);
00328 
00331 int rthal_request_linux_irq(unsigned irq,
00332                             irqreturn_t (*handler)(int irq,
00333                                                    void *dev_id,
00334                                                    struct pt_regs *regs), 
00335                             char *name,
00336                             void *dev_id);
00337 
00338 int rthal_release_linux_irq(unsigned irq,
00339                             void *dev_id);
00340 
00341 int rthal_pend_linux_irq(unsigned irq);
00342 
00343 int rthal_pend_linux_srq(unsigned srq);
00344 
00345 int rthal_request_srq(unsigned label,
00346                       void (*handler)(void));
00347 
00348 int rthal_release_srq(unsigned srq);
00349 
00350 int rthal_set_irq_affinity(unsigned irq,
00351                            cpumask_t cpumask,
00352                            cpumask_t *oldmask);
00353 
00354 int rthal_request_timer(void (*handler)(void),
00355                         unsigned long nstick);
00356 
00357 void rthal_release_timer(void);
00358 
00359 rthal_trap_handler_t rthal_set_trap_handler(rthal_trap_handler_t handler);
00360 
00361 unsigned long rthal_calibrate_timer(void);
00362 
00363 #ifdef __cplusplus
00364 }
00365 #endif /* __cplusplus */
00366 
00367 #endif /* __KERNEL__ */
00368 
00371 #endif /* !_RTAI_ASM_PPC_HAL_H */

Generated on Mon Dec 13 09:49:49 2004 for RTAI API by  doxygen 1.3.9.1