📄 rtai.c
字号:
#ifdef CONFIG_RTAI_MOUNT_ON_LOADvoid rt_mount_rtai(void) {MOD_INC_USE_COUNT;}void rt_umount_rtai(void) {MOD_DEC_USE_COUNT;}#elsevoid rt_mount_rtai(void){ rt_spin_lock(&rtai_mount_lock); rtai_mounted++; MOD_INC_USE_COUNT; if(rtai_mounted == 1) { __rtai_mount_rtai(); } rt_spin_unlock(&rtai_mount_lock);} /* End function - rt_mount_rtai */void rt_umount_rtai(void){ rt_spin_lock(&rtai_mount_lock); rtai_mounted--; MOD_DEC_USE_COUNT; if(!rtai_mounted) { __rtai_umount_rtai(); } rt_spin_unlock(&rtai_mount_lock);} /* End function - rt_umount_rtai */#endif/* * Module parameters to allow frequencies to be overriden via insmod. */static int CpuFreq = CALIBRATED_CPU_FREQ;MODULE_PARM(CpuFreq, "i");/* * Module initialization and cleanup. *//* * Let's prepare our side without any problem, so that there remain just a few * things to be done when mounting RTAI. All the zeroings are strictly not * required as mostly related to static data. Done esplicitly for emphasis. */static int __init rtai_init(void){ extern unsigned int mips_counter_frequency; unsigned int i; /* * Passed in CPU frequency overides auto detected Linux value. */ if(CpuFreq == 0) { CpuFreq = mips_counter_frequency; } tuned.cpu_freq = CpuFreq; printk("rtai: Using cpu_freq %d\n", tuned.cpu_freq); linux_rthal = rthal; global.pending_irqs_l = 0; global.pending_irqs_h = 0; global.activ_irqs = 0; global.pending_srqs = 0; global.activ_srqs = 0; global.cpu_in_sti = 0; global.used_by_linux = ~(0xFFFFFFFF << smp_num_cpus); global.locked_cpus = 0; global.hard_nesting = 0; spin_lock_init(&(global.data_lock)); spin_lock_init(&(global.hard_lock)); spin_lock_init(&global.global.ic_lock); for(i = 0; i < NR_RT_CPUS; i++) { processor[i].intr_flag = (1 << IFLAG) | (1 << i); processor[i].linux_intr_flag = (1 << IFLAG) | (1 << i); processor[i].pending_irqs_l = 0; processor[i].pending_irqs_h = 0; processor[i].activ_irqs = 0; } for(i = 0; i < NR_IRQS; i++) { linux_irq_desc_handler[i] = IRQ_DESC[i].handler; linux_isr[i] = rthal.mips_interrupt; //steve's 2.4.21 kernel works right } for(i = 0; i < NR_GLOBAL_IRQS; i++) { global_irq_handler[i] = 0; ic_ack_irq[i] = internal_ic_ack_irq[i] = linux_irq_desc_handler[i]->ack; linux_end_irq[i] = ic_end_irq[i] = linux_irq_desc_handler[i]->end; } /* * Initialize the Linux tick period. */ linux_hz = (long)(mips_counter_frequency) / cycles_per_jiffy; rt_timer_active = 0;#ifdef CONFIG_RTAI_MOUNT_ON_LOAD __rt_mount_rtai();#endif#ifdef CONFIG_PROC_FS rtai_proc_register();#endif return(0);} /* End function - rtai_init */static void __exit rtai_end(void){#ifdef CONFIG_RTAI_MOUNT_ON_LOAD __rt_umount_rtai();#endif#ifdef CONFIG_PROC_FS rtai_proc_unregister();#endif return;} /* End function - rtai_end */module_init(rtai_init);module_exit(rtai_end);MODULE_DESCRIPTION("RTAI core services module.");MODULE_AUTHOR("Paolo Mantegazza <mantegazza@aero.polimi.it>"); /* ----------------------< proc filesystem section >---------------------- */#ifdef CONFIG_PROC_FSstruct proc_dir_entry *rtai_proc_root = NULL; static int rtai_read_rtai(char *page, char **start, off_t off, int count, int *eof, void *data){ PROC_PRINT_VARS; int i; PROC_PRINT("\nRTAI Real Time Kernel, Version: %s\n\n", RTAI_RELEASE); PROC_PRINT(" RTAI mount count: %d\n", rtai_mounted);#ifdef CONFIG_SMP PROC_PRINT(" APIC Frequency: %d\n", tuned.apic_freq); PROC_PRINT(" APIC Latency: %d ns\n", LATENCY_APIC); PROC_PRINT(" APIC Setup: %d ns\n", SETUP_TIME_APIC);#endif PROC_PRINT("\nGlobal irqs used by RTAI: \n"); for (i = 0; i < NR_GLOBAL_IRQS; i++) { if (global_irq_handler[i]) { PROC_PRINT("%d ", i); } } PROC_PRINT("\nRTAI sysreqs in use: \n"); for (i = 0; i < NR_GLOBAL_IRQS; i++) { if (sysrq[i].rtai_handler || sysrq[i].user_handler) { PROC_PRINT("%d ", i); } } PROC_PRINT("\nMIPS Timer controlled by: %s\n", rt_timer_active ? "RTAI" : "Linux"); if(rt_timer_active) { PROC_PRINT("RTAI Tick Frequency: %ldHz\n", rtai_hz); } else { PROC_PRINT("Linux Tick Frequency: %ldHz\n", linux_hz); } PROC_PRINT("RTHAL TSC: 0x%.8lx%.8lx\n", rthal.tsc.hltsc[1], rthal.tsc.hltsc[0]); PROC_PRINT("\n\n"); PROC_PRINT_DONE;} /* End function - rtai_read_rtai */static int rtai_proc_register(void){ struct proc_dir_entry *ent; rtai_proc_root = create_proc_entry("rtai", S_IFDIR, 0); if (!rtai_proc_root) { printk("Unable to initialize /proc/rtai\n"); return(-1); } rtai_proc_root->owner = THIS_MODULE; ent = create_proc_entry("rtai", S_IFREG|S_IRUGO|S_IWUSR, rtai_proc_root); if (!ent) { printk("Unable to initialize /proc/rtai/rtai\n"); return(-1); } ent->read_proc = rtai_read_rtai; return(0);} /* End function - rtai_proc_register */static void rtai_proc_unregister(void){ remove_proc_entry("rtai", rtai_proc_root); remove_proc_entry("rtai", 0);} /* End function - rtai_proc_unregister */ #endif /* CONFIG_PROC_FS *//* ------------------< end of proc filesystem section >------------------ *//* ---------------------------< Timer section >--------------------------- *//********** SOME TIMER FUNCTIONS TO BE LIKELY NEVER PUT ELSWHERE *************/ /* * Real time timers. No oneshot, and related timer programming, calibration. * Use the utility module. It is also been decided that this stuff has to * stay here. */struct calibration_data tuned;struct rt_times rt_times = {0};/* * Restore the MIPS timer to its Linux kernel value. */void restore_mips_timer(unsigned long linux_tick){ unsigned long flags; unsigned long cp0_compare = 0; /* Counter value at next timer irq */ flags = hard_lock_all(); cp0_compare = ((unsigned long)read_c0_count()); cp0_compare += linux_tick; write_c0_compare(cp0_compare); hard_unlock_all(flags);} /* End function - restore_mips_timer */int rt_request_timer(void (*handler)(void), unsigned int tick, int apic){ unsigned long flags; int r_c = 0; RTIME t; flags = hard_lock_all(); t = rdtsc(); rt_times.linux_tick = cycles_per_jiffy; rt_times.periodic_tick = tick > 0 && tick < cycles_per_jiffy ? tick : rt_times.linux_tick; rt_times.tick_time = t; rt_times.intr_time = rt_times.tick_time + rt_times.periodic_tick; rt_times.linux_time = rt_times.tick_time + rt_times.linux_tick; rt_free_global_irq(IRQ_TIMER); if(rt_request_global_irq(IRQ_TIMER, handler) < 0) { r_c = -EINVAL; goto set_timer_exit; } linux_isr[IRQ_TIMER] = (unsigned int (*)(int,struct pt_regs *))rthal.linux_soft_mips_timer_intr; rt_set_timer_delay(rt_times.periodic_tick); if(rt_times.periodic_tick != 0) { rtai_hz = tuned.cpu_freq / rt_times.periodic_tick; } rt_timer_active = 1;set_timer_exit: hard_unlock_all(flags); return(r_c);} /* End function - rt_request_timer */int rt_free_timer(void){ unsigned long flags; int r_c = 0; flags = hard_lock_all(); clear_c0_status(IE_IRQ5); rt_timer_active = 0; linux_isr[IRQ_TIMER] = linux_rthal.mips_interrupt; //since handler set up through linux, don't do mips_timer_interrupt if(rt_free_global_irq(IRQ_TIMER) < 0) { r_c = -EINVAL; } restore_mips_timer(cycles_per_jiffy); set_c0_status(IE_IRQ5); processor[hard_cpu_id()].irqs[IRQ_TIMER] = 0; clear_bit(IRQ_TIMER, &global.pending_irqs_l); hard_unlock_all(flags); return(r_c);} /* End function - rt_free_timer *//* ------------------------< End of timer section >----------------------- *//* ---------------------------< printk section >--------------------------- */#include <linux/console.h>int rtai_print_to_screen(const char *format, ...){ static spinlock_t display_lock = SPIN_LOCK_UNLOCKED; static char display[25*80]; unsigned long flags; struct console *c; va_list args; int len; flags = rt_spin_lock_irqsave(&display_lock); va_start(args, format); len = vsprintf(display, format, args); va_end(args); c = console_drivers; while(c) { if((c->flags & CON_ENABLED) && c->write) { c->write(c, display, len); } c = c->next; } rt_spin_unlock_irqrestore(flags, &display_lock); return(len);} /* End function - rtai_print_to_screen *//* * rt_printk.c, hacked from linux/kernel/printk.c. * * Modified for RT support, David Schleef. * * Adapted to RTAI, and restyled his way by Paolo Mantegazza. Now it has been * taken away from the fifos module and has become an integral part of the * basic RTAI module. */ #define PRINTK_BUF_LEN (4096*2) /* Some programs generate much output. PC */#define TEMP_BUF_LEN (256) static char rt_printk_buf[PRINTK_BUF_LEN];static int buf_front, buf_back; static char buf[TEMP_BUF_LEN];int rt_printk(const char *fmt, ...){ static spinlock_t display_lock = SPIN_LOCK_UNLOCKED; va_list args; int len, i; unsigned long flags, lflags; //steve added lflags at othersteve's suggestion lflags = linux_save_flags_and_cli(); flags = rt_spin_lock_irqsave(&display_lock); va_start(args, fmt); len = vsprintf(buf, fmt, args); va_end(args); if(buf_front + len >= PRINTK_BUF_LEN) { i = PRINTK_BUF_LEN - buf_front; memcpy(rt_printk_buf + buf_front, buf, i); memcpy(rt_printk_buf, buf + i, len - i); buf_front = len - i; } else { memcpy(rt_printk_buf + buf_front, buf, len); buf_front += len; } rt_spin_unlock_irqrestore(flags, &display_lock); rtai_just_copy_back(lflags, hard_cpu_id()); rt_pend_linux_srq(1); return len;} /* End function - rt_printk */ static void rt_printk_sysreq_handler(void){ int tmp; while(1) { tmp = buf_front; if(buf_back > tmp) { printk("%.*s", PRINTK_BUF_LEN - buf_back, rt_printk_buf + buf_back); buf_back = 0; } if(buf_back == tmp) { break; } printk("%.*s", tmp - buf_back, rt_printk_buf + buf_back); buf_back = tmp; }} /* End function - rt_printk_sysreq_handler *//* ------------------------< End of printk section >----------------------- *//* ----------------------------< End of File >--------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -