rtai-core/include/asm-i386/rtai_hal.h

Go to the documentation of this file.
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 /* !CONFIG_SMP */
00046 #define RTAI_NR_CPUS  1
00047 #endif /* CONFIG_SMP */
00048 
00049 static __inline__ unsigned long ffnz (unsigned long word) {
00050     /* Derived from bitops.h's ffs() */
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      * Fixed by Marco Morandini <morandini@aero.polimi.it> to work
00062      * with the -fnostrict-aliasing and -O2 combination using GCC
00063      * 3.x.
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     /* Returns (int)i = (int)i*(int)(mult)/(int)div. */
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     /* Returns (long long)ll = (int)ll*(int)(mult)/(int)div. */
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  *  u64div32c.c is a helper function provided, 2003-03-03, by:
00135  *  Copyright (C) 2003 Nils Hagge <hagge@rts.uni-hannover.de>
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 /* __USE_APIC__ */
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 /* Use these ones when fiddling with the (local A)PIC */
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 /* Bits from rtai_status. */
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  /* !CONFIG_X86_TSC */
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 /* CONFIG_X86_TSC */
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 /* rtai_get_current() is Adeos-specific. Since real-time interrupt
00278    handlers are called on behalf of the RTAI domain stack, we cannot
00279    infere the "current" Linux task address using %esp. We must use the
00280    suspended Linux domain's stack pointer instead. */
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 /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
00286     return ((struct thread_info *)(((u_long)adp_root->esp[cpuid]) & (~((THREAD_SIZE)-1))))->task;
00287 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
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 /* !CONFIG_SMP */
00346 #define CPU_RELAX(x)
00347 #endif /* CONFIG_SMP */
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 /* adeos_load_cpuid */
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 /* adeos_load_cpuid */
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 /* adeos_load_cpuid */
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 /* adeos_load_cpuid */
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 /* !__USE_APIC__ */
00535         outb(delay & 0xff,0x40);
00536         outb(delay >> 8,0x40);
00537 #endif /* __USE_APIC__ */
00538         rtai_hw_unlock(flags);
00539     }
00540 }
00541 
00542     /* Private interface -- Internal use only */
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 /* __KERNEL__ && !__cplusplus */
00555 
00556     /* Public interface */
00557 
00558 #ifdef __KERNEL__
00559 
00560 #include <linux/kernel.h>
00561 
00562 #define rt_printk             printk /* This is safe over Adeos */
00563 #define rtai_print_to_screen  printk
00564 
00565 #ifdef __cplusplus
00566 extern "C" {
00567 #endif /* __cplusplus */
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 /* Deprecated calls. */
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 /* __cplusplus */
00681 
00682 #endif /* __KERNEL__ */
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 /* !CONFIG_RTAI_TRACE */
00690 #define RTAI_DEFAULT_STACKSZ 1024
00691 #endif /* CONFIG_RTAI_TRACE */
00692 
00695 #endif /* !_RTAI_ASM_I386_HAL_H */

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