00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <linux/version.h>
00048 #include <linux/autoconf.h>
00049 #include <linux/module.h>
00050 #include <linux/init.h>
00051 #include <linux/stddef.h>
00052 #include <linux/sched.h>
00053 #include <linux/timer.h>
00054 #include <linux/interrupt.h>
00055 #include <asm/mach/irq.h>
00056 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00057 # include <asm/proc/ptrace.h>
00058 #else
00059 # include <asm/ptrace.h>
00060 # include <asm/uaccess.h>
00061 # include <asm/unistd.h>
00062 # include <stdarg.h>
00063 #endif
00064 #define __RTAI_HAL__
00065 #include <asm/rtai_hal.h>
00066 #include <asm/rtai_lxrt.h>
00067 #include <asm/rtai_usi.h>
00068 #ifdef CONFIG_PROC_FS
00069 #include <linux/proc_fs.h>
00070 #include <rtai_proc_fs.h>
00071 #endif
00072 #include <rtai_version.h>
00073
00074 #include <asm/rtai_usi.h>
00075 #include <asm/unistd.h>
00076
00077 MODULE_LICENSE("GPL");
00078
00079 static unsigned long rtai_cpufreq_arg = RTAI_CALIBRATED_CPU_FREQ;
00080 RTAI_MODULE_PARM(rtai_cpufreq_arg, ulong);
00081
00082 static unsigned long IsolCpusMask = 0;
00083 RTAI_MODULE_PARM(IsolCpusMask, ulong);
00084
00085 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,31) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
00086
00087 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
00088 #define rtai_irq_desc(irq) (irq_desc[irq].handler)
00089 #else
00090 #define rtai_irq_desc(irq) (irq_desc[irq].chip)
00091 #endif
00092
00093 #define BEGIN_PIC()
00094 #define END_PIC()
00095 #undef hal_lock_irq
00096 #undef hal_unlock_irq
00097 #define hal_lock_irq(x, y, z)
00098 #define hal_unlock_irq(x, y)
00099
00100 #else
00101
00102 extern struct hw_interrupt_type hal_std_irq_dtype[];
00103 #define rtai_irq_desc(irq) (&hal_std_irq_dtype[irq])
00104
00105 #define BEGIN_PIC() \
00106 do { \
00107 unsigned long flags, pflags, cpuid; \
00108 rtai_save_flags_and_cli(flags); \
00109 cpuid = rtai_cpuid(); \
00110 pflags = xchg(ipipe_root_status[cpuid], 1 << IPIPE_STALL_FLAG); \
00111 rtai_save_and_lock_preempt_count()
00112
00113 #define END_PIC() \
00114 rtai_restore_preempt_count(); \
00115 *ipipe_root_status[cpuid] = pflags; \
00116 rtai_restore_flags(flags); \
00117 } while (0)
00118
00119 #endif
00120
00121
00122
00123 struct rtai_realtime_irq_s rtai_realtime_irq[RTAI_NR_IRQS];
00124 struct hal_domain_struct rtai_domain;
00125 struct rt_times rt_times;
00126 struct rt_times rt_smp_times[RTAI_NR_CPUS] = { { 0 } };
00127 struct rtai_switch_data rtai_linux_context[RTAI_NR_CPUS];
00128 volatile unsigned long *ipipe_root_status[RTAI_NR_CPUS];
00129 struct calibration_data rtai_tunables;
00130 volatile unsigned long rtai_cpu_realtime;
00131 volatile unsigned long rtai_cpu_lock;
00132 long long (*rtai_lxrt_invoke_entry)(unsigned long, void *);
00133 struct { volatile int locked, rqsted; } rt_scheduling[RTAI_NR_CPUS];
00134 #ifdef CONFIG_PROC_FS
00135 struct proc_dir_entry *rtai_proc_root = NULL;
00136 #endif
00137
00138 #ifdef CONFIG_RTAI_SCHED_ISR_LOCK
00139 static void (*rtai_isr_hook)(int cpuid);
00140 #endif
00141
00142 #define CHECK_KERCTX()
00143
00144
00145
00146 static struct {
00147 unsigned long flags;
00148 int count;
00149 } rtai_linux_irq[NR_IRQS];
00150 static struct {
00151 void (*k_handler)(void);
00152 long long (*u_handler)(unsigned long);
00153 unsigned long label;
00154 } rtai_sysreq_table[RTAI_NR_SRQS];
00155 static unsigned rtai_sysreq_virq;
00156 static unsigned long rtai_sysreq_map = 3;
00157 static unsigned long rtai_sysreq_pending;
00158 static unsigned long rtai_sysreq_running;
00159 static spinlock_t rtai_lsrq_lock = SPIN_LOCK_UNLOCKED;
00160 static volatile int rtai_sync_level;
00161 static atomic_t rtai_sync_count = ATOMIC_INIT(1);
00162 static RT_TRAP_HANDLER rtai_trap_handler;
00163 volatile unsigned long hal_pended;
00164
00165 unsigned long
00166 rtai_critical_enter(void (*synch)(void))
00167 {
00168 unsigned long flags = hal_critical_enter(synch);
00169
00170 if (atomic_dec_and_test(&rtai_sync_count))
00171 rtai_sync_level = 0;
00172 else if (synch != NULL)
00173 printk(KERN_INFO "RTAI[hal]: warning: nested sync will fail.\n");
00174
00175 return flags;
00176 }
00177
00178 void
00179 rtai_critical_exit(unsigned long flags)
00180 {
00181 atomic_inc(&rtai_sync_count);
00182 hal_critical_exit(flags);
00183 }
00184
00185 int
00186 rt_request_irq(unsigned irq, int (*handler)(unsigned irq, void *cookie), void *cookie, int retmode)
00187 {
00188 unsigned long flags;
00189
00190 if (handler == NULL || irq >= RTAI_NR_IRQS)
00191 return -EINVAL;
00192
00193 if (rtai_realtime_irq[irq].handler != NULL)
00194 return -EBUSY;
00195
00196 flags = rtai_critical_enter(NULL);
00197 rtai_realtime_irq[irq].handler = (void *)handler;
00198 rtai_realtime_irq[irq].irq_ack = hal_root_domain->irqs[irq].acknowledge;
00199 rtai_realtime_irq[irq].cookie = cookie;
00200 rtai_critical_exit(flags);
00201 return 0;
00202 }
00203
00204 int
00205 rt_release_irq(unsigned irq)
00206 {
00207 unsigned long flags;
00208 if (irq >= RTAI_NR_IRQS || !rtai_realtime_irq[irq].handler) {
00209 return -EINVAL;
00210 }
00211 flags = rtai_critical_enter(NULL);
00212 rtai_realtime_irq[irq].handler = NULL;
00213 rtai_realtime_irq[irq].irq_ack = hal_root_domain->irqs[irq].acknowledge;
00214 rtai_critical_exit(flags);
00215 return 0;
00216 }
00217
00218 int rt_set_irq_ack(unsigned irq, int (*irq_ack)(unsigned int))
00219 {
00220 if (irq >= RTAI_NR_IRQS) {
00221 return -EINVAL;
00222 }
00223 rtai_realtime_irq[irq].irq_ack = irq_ack ? irq_ack : hal_root_domain->irqs[irq].acknowledge;
00224 return 0;
00225 }
00226
00227 void
00228 rt_set_irq_cookie(unsigned irq, void *cookie)
00229 {
00230 if (irq < NR_IRQS)
00231 rtai_realtime_irq[irq].cookie = cookie;
00232 }
00233
00234
00235
00236
00237
00238 void rt_request_apic_timers (void (*handler)(void), struct apic_timer_setup_data *tmdata) { return; }
00239 void rt_free_apic_timers(void) { rt_free_timer(); }
00240 int rt_assign_irq_to_cpu (int irq, unsigned long cpus_mask) { return 0; }
00241 int rt_reset_irq_to_sym_mode (int irq) { return 0; }
00242
00243 void rt_request_rtc(long rtc_freq, void *handler)
00244 {
00245 rt_printk("*** RTC NOT IMPLEMENTED YET ON THIS ARCH ***\n");
00246 }
00247
00248 void rt_release_rtc(void)
00249 {
00250 rt_printk("*** RTC NOT IMPLEMENTED YET ON THIS ARCH ***\n");
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 unsigned
00283 rt_startup_irq(unsigned irq)
00284 {
00285 int retval;
00286
00287 BEGIN_PIC();
00288 hal_unlock_irq(hal_root_domain, irq);
00289 rtai_irq_desc(irq)->unmask(irq);
00290 retval = rtai_irq_desc(irq)->startup(irq);
00291 END_PIC();
00292 return retval;
00293 }
00294
00295 void
00296 rt_shutdown_irq(unsigned irq)
00297 {
00298 BEGIN_PIC();
00299 rtai_irq_desc(irq)->shutdown(irq);
00300 hal_clear_irq(hal_root_domain, irq);
00301 END_PIC();
00302 }
00303
00304 void
00305 rt_enable_irq(unsigned irq)
00306 {
00307 BEGIN_PIC();
00308 hal_unlock_irq(hal_root_domain, irq);
00309 rtai_irq_desc(irq)->enable(irq);
00310 END_PIC();
00311 }
00312
00313 void
00314 rt_disable_irq(unsigned irq)
00315 {
00316 BEGIN_PIC();
00317 rtai_irq_desc(irq)->disable(irq);
00318 hal_lock_irq(hal_root_domain, cpuid, irq);
00319 END_PIC();
00320 }
00321
00322 void
00323 rt_mask_and_ack_irq(unsigned irq)
00324 {
00325 BEGIN_PIC();
00326 rtai_irq_desc(irq)->mask(irq);
00327 END_PIC();
00328 }
00329
00330 static inline void _rt_end_irq (unsigned irq)
00331 {
00332 BEGIN_PIC();
00333 if (
00334 !(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
00335 hal_unlock_irq(hal_root_domain, irq);
00336 }
00337 rtai_irq_desc(irq)->end(irq);
00338 END_PIC();
00339 }
00340
00341 void
00342 rt_unmask_irq(unsigned irq)
00343 {
00344 BEGIN_PIC();
00345 rtai_irq_desc(irq)->unmask(irq);
00346 END_PIC();
00347 }
00348
00349 void
00350 rt_ack_irq(unsigned irq)
00351 {
00352 BEGIN_PIC();
00353 hal_unlock_irq(hal_root_domain, irq);
00354 rtai_irq_desc(irq)->enable(irq);
00355 END_PIC();
00356 }
00357
00358 void rt_end_irq (unsigned irq)
00359 {
00360 _rt_end_irq(irq);
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 int
00389 rt_request_linux_irq (unsigned irq, void *handler, char *name, void *dev_id)
00390 {
00391 unsigned long flags;
00392
00393 if (irq >= RTAI_NR_IRQS || !handler) {
00394 return -EINVAL;
00395 }
00396
00397 rtai_save_flags_and_cli(flags);
00398 spin_lock(&irq_desc[irq].lock);
00399 if (rtai_linux_irq[irq].count++ == 0 && irq_desc[irq].action) {
00400 rtai_linux_irq[irq].flags = irq_desc[irq].action->flags;
00401 irq_desc[irq].action->flags |= SA_SHIRQ;
00402 }
00403 spin_unlock(&irq_desc[irq].lock);
00404 rtai_restore_flags(flags);
00405
00406 request_irq(irq, handler, SA_SHIRQ, name, dev_id);
00407
00408 return 0;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 int
00423 rt_free_linux_irq(unsigned irq, void *dev_id)
00424 {
00425 unsigned long flags;
00426
00427 if (irq >= RTAI_NR_IRQS || rtai_linux_irq[irq].count == 0) {
00428 return -EINVAL;
00429 }
00430
00431 rtai_save_flags_and_cli(flags);
00432 free_irq(irq, dev_id);
00433
00434 spin_lock(&irq_desc[irq].lock);
00435 if (--rtai_linux_irq[irq].count == 0 && irq_desc[irq].action) {
00436 irq_desc[irq].action->flags = rtai_linux_irq[irq].flags;
00437 }
00438 spin_unlock(&irq_desc[irq].lock);
00439
00440 rtai_restore_flags(flags);
00441
00442 return 0;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 void
00454 rt_pend_linux_irq(unsigned irq)
00455 {
00456 unsigned long flags;
00457 rtai_save_flags_and_cli(flags);
00458 hal_pend_uncond(irq, rtai_cpuid());
00459 rtai_restore_flags(flags);
00460 }
00461
00462 RTAI_SYSCALL_MODE void usr_rt_pend_linux_irq (unsigned irq)
00463 {
00464 unsigned long flags;
00465 rtai_save_flags_and_cli(flags);
00466 hal_pend_uncond(irq, rtai_cpuid());
00467 rtai_restore_flags(flags);
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 int
00490 rt_request_srq(unsigned label, void (*k_handler)(void), long long (*u_handler)(unsigned long))
00491 {
00492 unsigned long flags;
00493 int srq;
00494
00495 if (k_handler == NULL)
00496 return -EINVAL;
00497
00498 rtai_save_flags_and_cli(flags);
00499
00500 if (rtai_sysreq_map != ~0) {
00501 srq = ffz(rtai_sysreq_map);
00502 set_bit(srq, &rtai_sysreq_map);
00503 rtai_sysreq_table[srq].k_handler = k_handler;
00504 rtai_sysreq_table[srq].u_handler = u_handler;
00505 rtai_sysreq_table[srq].label = label;
00506 } else
00507 srq = -EBUSY;
00508
00509 rtai_restore_flags(flags);
00510
00511 return srq;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 int
00523 rt_free_srq(unsigned srq)
00524 {
00525 return (srq < 2 || srq >= RTAI_NR_SRQS || !test_and_clear_bit(srq, &rtai_sysreq_map))
00526 ? -EINVAL
00527 : 0;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 void
00541 rt_pend_linux_srq(unsigned srq)
00542 {
00543 if (srq > 0 && srq < RTAI_NR_SRQS) {
00544 unsigned long flags;
00545 set_bit(srq, &rtai_sysreq_pending);
00546 rtai_save_flags_and_cli(flags);
00547 hal_pend_uncond(rtai_sysreq_virq, rtai_cpuid());
00548 rtai_restore_flags(flags);
00549 }
00550 }
00551
00552 #ifdef CONFIG_RTAI_SCHED_ISR_LOCK
00553 static void (*rtai_isr_hook)(int cpuid);
00554 #define RTAI_SCHED_ISR_LOCK() \
00555 do { \
00556 if (!rt_scheduling[cpuid = rtai_cpuid()].locked++) { \
00557 rt_scheduling[cpuid].rqsted = 0; \
00558 } \
00559 } while (0)
00560 #define RTAI_SCHED_ISR_UNLOCK() \
00561 do { \
00562 if (rt_scheduling[cpuid].locked && !(--rt_scheduling[cpuid].locked)) { \
00563 if (rt_scheduling[cpuid].rqsted > 0 && rtai_isr_hook) { \
00564 rtai_isr_hook(cpuid); \
00565 } \
00566 } \
00567 } while (0)
00568 #else
00569 #define RTAI_SCHED_ISR_LOCK() \
00570 do { cpuid = rtai_cpuid(); } while (0)
00571 #define RTAI_SCHED_ISR_UNLOCK() \
00572 do { } while (0)
00573 #endif
00574
00575 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,31) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
00576 #define HAL_TICK_REGS hal_tick_regs[cpuid]
00577 #else
00578 #define HAL_TICK_REGS hal_tick_regs
00579 #endif
00580
00581 #ifdef LOCKED_LINUX_IN_IRQ_HANDLER
00582 #define HAL_LOCK_LINUX() do { sflags = rt_save_switch_to_real_time(cpuid); } while (0)
00583 #define HAL_UNLOCK_LINUX() do { rtai_cli(); rt_restore_switch_to_linux(sflags, cpuid); } while (0)
00584 #else
00585 #define HAL_LOCK_LINUX() do { sflags = xchg(ipipe_root_status[cpuid], (1 << IPIPE_STALL_FLAG)); } while (0)
00586 #define HAL_UNLOCK_LINUX() do { rtai_cli(); *ipipe_root_status[cpuid] = sflags; } while (0)
00587 #endif
00588
00589
00590 int rtai_timer_handler(struct pt_regs *regs)
00591 {
00592 unsigned long cpuid=rtai_cpuid();
00593 unsigned long sflags;
00594
00595 RTAI_SCHED_ISR_LOCK();
00596 HAL_LOCK_LINUX();
00597 rtai_realtime_irq[RTAI_TIMER_IRQ].irq_ack(RTAI_TIMER_IRQ);
00598 ((void (*)(void))rtai_realtime_irq[RTAI_TIMER_IRQ].handler)();
00599 HAL_UNLOCK_LINUX();
00600 RTAI_SCHED_ISR_UNLOCK();
00601
00602 if (test_and_clear_bit(cpuid, &hal_pended) && !test_bit(IPIPE_STALL_FLAG, ipipe_root_status[cpuid])) {
00603 rtai_sti();
00604 hal_fast_flush_pipeline(cpuid);
00605 return 1;
00606 }
00607 return 0;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 static void rtai_hirq_dispatcher(int irq, struct pt_regs *regs)
00626 {
00627 unsigned long cpuid;
00628 if (rtai_realtime_irq[irq].handler) {
00629 unsigned long sflags;
00630
00631 RTAI_SCHED_ISR_LOCK();
00632 HAL_LOCK_LINUX();
00633 rtai_realtime_irq[irq].irq_ack(irq); mb();
00634 rtai_realtime_irq[irq].handler(irq, rtai_realtime_irq[irq].cookie);
00635 HAL_UNLOCK_LINUX();
00636 RTAI_SCHED_ISR_UNLOCK();
00637 if (rtai_realtime_irq[irq].retmode || !test_and_clear_bit(cpuid, &hal_pended) || test_bit(IPIPE_STALL_FLAG, ipipe_root_status[cpuid])) {
00638 return;
00639 }
00640 } else {
00641 unsigned long lflags;
00642
00643 lflags = xchg(ipipe_root_status[cpuid = rtai_cpuid()], (1 << IPIPE_STALL_FLAG));
00644 rtai_realtime_irq[irq].irq_ack(irq); mb();
00645 hal_pend_uncond(irq, cpuid);
00646 *ipipe_root_status[cpuid] = lflags;
00647 if (test_bit(IPIPE_STALL_FLAG, &lflags)) {
00648 return;
00649 }
00650 }
00651 rtai_sti();
00652 hal_fast_flush_pipeline(cpuid);
00653 return;
00654 }
00655
00656 RT_TRAP_HANDLER
00657 rt_set_trap_handler(RT_TRAP_HANDLER handler)
00658 {
00659 return (RT_TRAP_HANDLER)xchg(&rtai_trap_handler, handler);
00660 }
00661
00662 static int rtai_trap_fault (unsigned event, void *evdata)
00663 {
00664 static const int trap2sig[] = {
00665 SIGSEGV,
00666 SIGBUS,
00667 SIGFPE,
00668 SIGFPE,
00669 SIGFPE,
00670 SIGFPE,
00671 SIGTRAP,
00672 SIGFPE,
00673 SIGTRAP,
00674 SIGSEGV,
00675 SIGILL,
00676 SIGTRAP,
00677 SIGSEGV,
00678 SIGFPE,
00679 0,
00680 0, 0, 0, 0, 0,
00681 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00682 0, 0
00683 };
00684
00685 TRACE_RTAI_TRAP_ENTRY(evdata->event, 0);
00686
00687 if (!in_hrt_mode(rtai_cpuid())) {
00688 goto propagate;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697 if (rtai_trap_handler && rtai_trap_handler(event, trap2sig[event], (struct pt_regs *)evdata, NULL)) {
00698 goto endtrap;
00699 }
00700
00701 propagate:
00702 return 0;
00703
00704 endtrap:
00705 TRACE_RTAI_TRAP_EXIT();
00706 return 1;
00707 }
00708
00709
00710
00711
00712
00713 static void rtai_lsrq_dispatcher (unsigned virq)
00714 {
00715 unsigned long pending, srq;
00716
00717 spin_lock(&rtai_lsrq_lock);
00718 while ((pending = rtai_sysreq_pending & ~rtai_sysreq_running)) {
00719 set_bit(srq = ffnz(pending), &rtai_sysreq_running);
00720 clear_bit(srq, &rtai_sysreq_pending);
00721 spin_unlock(&rtai_lsrq_lock);
00722
00723 if (test_bit(srq, &rtai_sysreq_map)) {
00724 rtai_sysreq_table[srq].k_handler();
00725 }
00726
00727 clear_bit(srq, &rtai_sysreq_running);
00728 spin_lock(&rtai_lsrq_lock);
00729 }
00730 spin_unlock(&rtai_lsrq_lock);
00731 }
00732
00733
00734
00735
00736
00737
00738 static inline long long rtai_usrq_dispatcher (unsigned long srq, unsigned long label)
00739 {
00740 TRACE_RTAI_SRQ_ENTRY(srq);
00741
00742 if (srq > 1 && srq < RTAI_NR_SRQS && test_bit(srq, &rtai_sysreq_map) && rtai_sysreq_table[srq].u_handler) {
00743 return rtai_sysreq_table[srq].u_handler(label);
00744 }
00745 else {
00746 for (srq = 2; srq < RTAI_NR_SRQS; srq++) {
00747 if (test_bit(srq, &rtai_sysreq_map) && rtai_sysreq_table[srq].label == label) {
00748 return (long long)srq;
00749 }
00750 }
00751 }
00752
00753 TRACE_RTAI_SRQ_EXIT();
00754
00755 return 0LL;
00756 }
00757
00758 long long (*rtai_lxrt_dispatcher)(unsigned long, unsigned long, void *);
00759
00760 static int (*sched_intercept_syscall_prologue)(struct pt_regs *);
00761
00762 static int intercept_syscall_prologue(unsigned long event, struct pt_regs *regs){
00763 if (likely(regs->ARM_r0 >= RTAI_SYSCALL_NR)) {
00764 unsigned long srq = regs->ARM_r1;
00765 unsigned long arg = regs->ARM_r2;
00766
00767 IF_IS_A_USI_SRQ_CALL_IT(srq, arg, (long long *)regs->ARM_r5, regs->msr, 1);
00768 *((long long *)regs->ARM_r3) = srq > RTAI_NR_SRQS ? rtai_lxrt_dispatcher(srq, arg, regs) : rtai_usrq_dispatcher(srq, arg);
00769 if (!in_hrt_mode(srq = rtai_cpuid())) {
00770 hal_test_and_fast_flush_pipeline(srq);
00771 return 0;
00772 }
00773 return 1;
00774 }
00775 return likely(sched_intercept_syscall_prologue != NULL) ? sched_intercept_syscall_prologue(regs) : 0;
00776 }
00777
00778 int rtai_syscall_dispatcher (struct pt_regs *regs)
00779 {
00780 unsigned long srq = regs->ARM_r0;
00781 unsigned long arg = regs->ARM_r1;
00782
00783 IF_IS_A_USI_SRQ_CALL_IT(srq, regs->ARM_r2, (long long *)regs->ARM_r3, regs->msr, 1);
00784
00785 *((long long*)®s->ARM_r0) = srq > RTAI_NR_SRQS ? rtai_lxrt_dispatcher(srq, arg, regs) : rtai_usrq_dispatcher(srq, arg);
00786 if (!in_hrt_mode(srq = rtai_cpuid())) {
00787 hal_test_and_fast_flush_pipeline(srq);
00788 return 1;
00789 }
00790 return 0;
00791 }
00792
00793 static void rtai_domain_entry(int iflag)
00794 {
00795 if (iflag) {
00796 rt_printk(KERN_INFO "RTAI[hal]: <%s> mounted over %s %s.\n", PACKAGE_VERSION, HAL_TYPE, HAL_VERSION_STRING);
00797 rt_printk(KERN_INFO "RTAI[hal]: compiled with %s.\n", CONFIG_RTAI_COMPILER);
00798 }
00799 for (;;) hal_suspend_domain();
00800 }
00801
00802 long rtai_catch_event (struct hal_domain_struct *from, unsigned long event, int (*handler)(unsigned long, void *))
00803 {
00804 if (event == HAL_SYSCALL_PROLOGUE) {
00805 sched_intercept_syscall_prologue = (void *)handler;
00806 return 0;
00807 }
00808 return (long)hal_catch_event(from, event, (void *)handler);
00809 }
00810
00811 static void *saved_hal_irq_handler;
00812 extern void *hal_irq_handler;
00813
00814 #ifdef CONFIG_PROC_FS
00815
00816 static int
00817 rtai_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
00818 {
00819 PROC_PRINT_VARS;
00820 int i, none;
00821
00822 PROC_PRINT("\n** RTAI/ARM %s over Adeos %s\n\n", RTAI_RELEASE, HAL_VERSION_STRING);
00823 PROC_PRINT(" TSC frequency: %d Hz\n", RTAI_TSC_FREQ);
00824 PROC_PRINT(" Timer frequency: %d Hz\n", RTAI_TIMER_FREQ);
00825 PROC_PRINT(" Timer latency: %d ns, %d TSC ticks\n", RTAI_TIMER_LATENCY,
00826 rtai_imuldiv(RTAI_TIMER_LATENCY, RTAI_TSC_FREQ, 1000000000));
00827 PROC_PRINT(" Timer setup: %d ns\n", RTAI_TIMER_SETUP_TIME);
00828 PROC_PRINT(" Timer setup: %d TSC ticks, %d IRQ-timer ticks\n",
00829 rtai_imuldiv(RTAI_TIMER_SETUP_TIME, RTAI_TSC_FREQ, 1000000000),
00830 rtai_imuldiv(RTAI_TIMER_SETUP_TIME, RTAI_TIMER_FREQ, 1000000000));
00831
00832 none = 1;
00833
00834 PROC_PRINT("\n** Real-time IRQs used by RTAI: ");
00835
00836 for (i = 0; i < NR_IRQS; i++) {
00837 if (rtai_realtime_irq[i].handler) {
00838 if (none) {
00839 PROC_PRINT("\n");
00840 none = 0;
00841 }
00842 PROC_PRINT("\n #%d at %p", i, rtai_realtime_irq[i].handler);
00843 }
00844 }
00845
00846 if (none)
00847 PROC_PRINT("none");
00848
00849 PROC_PRINT("\n\n");
00850
00851 PROC_PRINT("** RTAI extension traps: \n\n");
00852 PROC_PRINT(" SYSREQ=0x%x\n", RTAI_SYS_VECTOR);
00853 #if 0
00854 PROC_PRINT(" SHM=0x%x\n", RTAI_SHM_VECTOR);
00855 #endif
00856 PROC_PRINT("\n");
00857
00858 none = 1;
00859 PROC_PRINT("** RTAI SYSREQs in use: ");
00860
00861 for (i = 0; i < RTAI_NR_SRQS; i++) {
00862 if (rtai_sysreq_table[i].k_handler || rtai_sysreq_table[i].u_handler) {
00863 PROC_PRINT("#%d ", i);
00864 none = 0;
00865 }
00866 }
00867
00868 if (none)
00869 PROC_PRINT("none");
00870
00871 PROC_PRINT("\n\n");
00872
00873 PROC_PRINT_DONE;
00874 }
00875
00876 static int
00877 rtai_proc_register(void)
00878 {
00879 struct proc_dir_entry *ent;
00880
00881 rtai_proc_root = create_proc_entry("rtai", S_IFDIR, 0);
00882
00883 if (!rtai_proc_root) {
00884 printk(KERN_ERR "RTAI[hal]: Unable to initialize /proc/rtai.\n");
00885 return -1;
00886 }
00887
00888 rtai_proc_root->owner = THIS_MODULE;
00889
00890 ent = create_proc_entry("rtai", S_IFREG|S_IRUGO|S_IWUSR, rtai_proc_root);
00891
00892 if (!ent) {
00893 printk(KERN_ERR "RTAI[hal]: Unable to initialize /proc/rtai/rtai.\n");
00894 return -1;
00895 }
00896
00897 ent->read_proc = rtai_read_proc;
00898
00899 return 0;
00900 }
00901
00902 static void
00903 rtai_proc_unregister(void)
00904 {
00905 remove_proc_entry("rtai", rtai_proc_root);
00906 remove_proc_entry("rtai", 0);
00907 }
00908
00909 #endif
00910
00911
00912 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
00913 static inline void *hal_set_irq_handler(void *hirq_dispatcher)
00914 {
00915 if (saved_hal_irq_handler != hirq_dispatcher) {
00916 saved_hal_irq_handler = hal_irq_handler;
00917 hal_irq_handler = hirq_dispatcher;
00918 return saved_hal_irq_handler;
00919 }
00920 hal_irq_handler = hirq_dispatcher;
00921 return rtai_hirq_dispatcher;
00922 }
00923 #endif
00924
00925 void (*rt_set_ihook (void (*hookfn)(int)))(int)
00926 {
00927 #ifdef CONFIG_RTAI_SCHED_ISR_LOCK
00928 return (void (*)(int))xchg(&rtai_isr_hook, hookfn);
00929 #else
00930 return NULL;
00931 #endif
00932 }
00933
00934 void rtai_set_linux_task_priority (struct task_struct *task, int policy, int prio)
00935 {
00936 hal_set_linux_task_priority(task, policy, prio);
00937 if (task->rt_priority != prio || task->policy != policy) {
00938 printk("RTAI[hal]: sched_setscheduler(policy = %d, prio = %d) failed, (%s -- pid = %d)\n", policy, prio, task->comm, task->pid);
00939 }
00940 }
00941
00942
00943
00944
00945
00946 static void rtai_install_archdep (void)
00947 {
00948 struct hal_sysinfo_struct sysinfo;
00949
00950 #if !defined(USE_LINUX_SYSCALL) && !defined(CONFIG_RTAI_LXRT_USE_LINUX_SYSCALL)
00951
00952 #endif
00953
00954 hal_catch_event(hal_root_domain, HAL_SYSCALL_PROLOGUE, (void *)intercept_syscall_prologue);
00955
00956 hal_get_sysinfo(&sysinfo);
00957
00958 rtai_cpufreq_arg = (unsigned long)sysinfo.cpufreq;
00959
00960 rtai_tunables.cpu_freq = rtai_cpufreq_arg;
00961 }
00962
00963
00964
00965
00966
00967 static void rtai_uninstall_archdep (void)
00968 {
00969
00970 hal_catch_event(hal_root_domain, HAL_SYSCALL_PROLOGUE, NULL);
00971 rtai_archdep_exit();
00972 }
00973
00974 #define RT_PRINTK_SRQ 1
00975
00976 static void *saved_hal_irq_handler;
00977 extern void *hal_irq_handler;
00978
00979 int
00980 __rtai_hal_init(void)
00981 {
00982 int trapnr, halinv;
00983 struct hal_attr_struct attr;
00984
00985
00986 for (halinv = trapnr = 0; trapnr < HAL_NR_EVENTS; trapnr++) {
00987 if (hal_root_domain->hal_event_handler_fun(trapnr)) {
00988 halinv = 1;
00989 printk("EVENT %d INVALID\n", trapnr);
00990 }
00991 }
00992 if (halinv) {
00993 printk(KERN_ERR "RTAI[hal]: HAL IMMEDIATE EVENT DISPATCHING BROKEN\n");
00994 return -1;
00995 }
00996
00997
00998 if (!(rtai_sysreq_virq = hal_alloc_irq())) {
00999 printk(KERN_ERR "RTAI[hal]: no virtual interrupt available.\n");
01000 return -1;
01001 }
01002
01003
01004 for (trapnr = 0; trapnr < RTAI_NR_IRQS; trapnr++) {
01005 rtai_realtime_irq[trapnr].irq_ack = hal_root_domain->irqs[trapnr].acknowledge;
01006 }
01007 for (trapnr = 0; trapnr < RTAI_NR_CPUS; trapnr++) {
01008 ipipe_root_status[trapnr] = &hal_root_domain->cpudata[trapnr].status;
01009 }
01010
01011
01012 hal_virtualize_irq(hal_root_domain, rtai_sysreq_virq, &rtai_lsrq_dispatcher, NULL, IPIPE_HANDLE_MASK);
01013 saved_hal_irq_handler = hal_irq_handler;
01014 hal_irq_handler = rtai_hirq_dispatcher;
01015
01016
01017 rtai_install_archdep();
01018
01019 #ifdef CONFIG_PROC_FS
01020 rtai_proc_register();
01021 #endif
01022
01023
01024 hal_init_attr(&attr);
01025 attr.name = "RTAI";
01026 attr.domid = RTAI_DOMAIN_ID;
01027 attr.entry = (void *)rtai_domain_entry;
01028 attr.priority = get_domain_pointer(1)->priority + 100;
01029 hal_register_domain(&rtai_domain, &attr);
01030
01031
01032 for (trapnr = 0; trapnr < HAL_NR_FAULTS; trapnr++) {
01033 hal_catch_event(hal_root_domain, trapnr, (void *)rtai_trap_fault);
01034 }
01035
01036
01037 printk(KERN_INFO "RTAI[hal]: mounted (%s, IMMEDIATE (INTERNAL IRQs %s).\n", HAL_TYPE, CONFIG_RTAI_DONT_DISPATCH_CORE_IRQS ? "VECTORED" : "DISPATCHED");
01038
01039
01040 printk("PIPELINE layers:\n");
01041 for (trapnr = 1; ; trapnr++) {
01042 struct hal_domain_struct *next_domain;
01043 next_domain = get_domain_pointer(trapnr);
01044 if ((unsigned long)next_domain < 10) break;
01045 printk("%p %x %s %d\n", next_domain, next_domain->domid, next_domain->name, next_domain->priority);
01046 }
01047
01048 #ifdef CONFIG_RTAI_DIAG_TSC_SYNC
01049 init_tsc_sync();
01050 #endif
01051
01052 return 0;
01053 }
01054
01055 void
01056 __rtai_hal_exit(void)
01057 {
01058 int trapnr;
01059 #ifdef CONFIG_PROC_FS
01060 rtai_proc_unregister();
01061 #endif
01062
01063 hal_irq_handler = saved_hal_irq_handler;
01064 hal_unregister_domain(&rtai_domain);
01065 for (trapnr = 0; trapnr < HAL_NR_FAULTS; trapnr++) {
01066 hal_catch_event(hal_root_domain, trapnr, NULL);
01067 }
01068 hal_virtualize_irq(hal_root_domain, rtai_sysreq_virq, NULL, NULL, 0);
01069 hal_free_irq(rtai_sysreq_virq);
01070
01071 rtai_uninstall_archdep();
01072
01073 #ifdef CONFIG_RTAI_DIAG_TSC_SYNC
01074 cleanup_tsc_sync();
01075 #endif
01076
01077 printk(KERN_INFO "RTAI[hal]: unmounted.\n");
01078 }
01079
01080 module_init(__rtai_hal_init);
01081 module_exit(__rtai_hal_exit);
01082
01083
01084
01085
01086
01087 asmlinkage int rt_printk(const char *fmt, ...)
01088 {
01089 va_list args;
01090 int r;
01091
01092 va_start(args, fmt);
01093 r = vprintk(fmt, args);
01094 va_end(args);
01095
01096 return r;
01097 }
01098
01099
01100
01101
01102
01103 asmlinkage int rt_sync_printk(const char *fmt, ...)
01104 {
01105 va_list args;
01106 int r;
01107
01108 va_start(args, fmt);
01109 hal_set_printk_sync(&rtai_domain);
01110 r = vprintk(fmt, args);
01111 hal_set_printk_async(&rtai_domain);
01112 va_end(args);
01113
01114 return r;
01115 }
01116
01117 EXPORT_SYMBOL(rtai_realtime_irq);
01118 EXPORT_SYMBOL(rt_request_irq);
01119 EXPORT_SYMBOL(rt_release_irq);
01120 EXPORT_SYMBOL(rt_set_irq_cookie);
01121 EXPORT_SYMBOL(rt_startup_irq);
01122 EXPORT_SYMBOL(rt_shutdown_irq);
01123 EXPORT_SYMBOL(rt_enable_irq);
01124 EXPORT_SYMBOL(rt_disable_irq);
01125 EXPORT_SYMBOL(rt_mask_and_ack_irq);
01126 EXPORT_SYMBOL(rt_unmask_irq);
01127 EXPORT_SYMBOL(rt_ack_irq);
01128 EXPORT_SYMBOL(rt_request_linux_irq);
01129 EXPORT_SYMBOL(rt_free_linux_irq);
01130 EXPORT_SYMBOL(rt_pend_linux_irq);
01131 EXPORT_SYMBOL(usr_rt_pend_linux_irq);
01132 EXPORT_SYMBOL(rt_set_irq_ack);
01133
01134 EXPORT_SYMBOL(rt_request_srq);
01135 EXPORT_SYMBOL(rt_free_srq);
01136 EXPORT_SYMBOL(rt_pend_linux_srq);
01137 EXPORT_SYMBOL(rt_assign_irq_to_cpu);
01138
01139 EXPORT_SYMBOL(rt_reset_irq_to_sym_mode);
01140 EXPORT_SYMBOL(rt_request_timer);
01141 EXPORT_SYMBOL(rt_free_timer);
01142 EXPORT_SYMBOL(rt_request_rtc);
01143 EXPORT_SYMBOL(rt_release_rtc);
01144
01145 extern int rtai_calibrate_TC (void);
01146 EXPORT_SYMBOL(rtai_calibrate_TC);
01147
01148 EXPORT_SYMBOL(rt_set_trap_handler);
01149
01150 EXPORT_SYMBOL(rt_set_ihook);
01151
01152 EXPORT_SYMBOL(rtai_critical_enter);
01153 EXPORT_SYMBOL(rtai_critical_exit);
01154 EXPORT_SYMBOL(rtai_set_linux_task_priority);
01155 EXPORT_SYMBOL(rtai_linux_context);
01156 EXPORT_SYMBOL(rtai_domain);
01157 EXPORT_SYMBOL(rtai_proc_root);
01158 EXPORT_SYMBOL(rtai_tunables);
01159 EXPORT_SYMBOL(rtai_cpu_lock);
01160 EXPORT_SYMBOL(rtai_cpu_realtime);
01161 EXPORT_SYMBOL(rt_times);
01162 EXPORT_SYMBOL(rt_smp_times);
01163
01164 EXPORT_SYMBOL(rt_printk);
01165 EXPORT_SYMBOL(rt_sync_printk);
01166
01167 EXPORT_SYMBOL(rtai_catch_event);
01168
01169 EXPORT_SYMBOL(rtai_lxrt_dispatcher);
01170 EXPORT_SYMBOL(rt_scheduling);
01171 EXPORT_SYMBOL(hal_pended);
01172 EXPORT_SYMBOL(ipipe_root_status);