⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 4 页
字号:
/** *   @ingroup hal *   @file * *   ARTI -- RTAI-compatible Adeos-based Real-Time Interface. Based on *   the original RTAI layer for x86. * *   Original RTAI/x86 layer implementation: \n *   Copyright &copy; 2000 Paolo Mantegazza, \n *   Copyright &copy; 2000 Steve Papacharalambous, \n *   Copyright &copy; 2000 Stuart Hughes, \n *   and others. * *   RTAI/x86 rewrite over Adeos: \n *   Copyright &copy 2002 Philippe Gerum. * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, *   USA; either version 2 of the License, or (at your option) any later *   version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//** * @defgroup hal RTAI services functions. * * This module defines some functions that can be used by RTAI tasks, for * managing interrupts and communication services with Linux processes. * *@{*/#include <linux/version.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/console.h>#include <asm/system.h>#include <asm/hw_irq.h>#include <asm/irq.h>#include <asm/desc.h>#include <asm/io.h>#include <asm/mmu_context.h>#include <asm/uaccess.h>#include <asm/unistd.h>#ifdef CONFIG_X86_LOCAL_APIC#include <asm/fixmap.h>#include <asm/bitops.h>#include <asm/mpspec.h>#ifdef CONFIG_X86_IO_APIC#include <asm/io_apic.h>#endif /* CONFIG_X86_IO_APIC */#include <asm/apic.h>#endif /* CONFIG_X86_LOCAL_APIC */#define __RTAI_HAL__#include <asm/rtai_hal.h>#ifdef CONFIG_PROC_FS#include <linux/stat.h>#include <linux/proc_fs.h>#include <rtai_proc_fs.h>#endif /* CONFIG_PROC_FS */#include <stdarg.h>MODULE_LICENSE("GPL");static unsigned long rtai_cpufreq_arg = RTAI_CALIBRATED_CPU_FREQ;MODULE_PARM(rtai_cpufreq_arg,"i");#ifdef CONFIG_X86_LOCAL_APICstatic unsigned long rtai_apicfreq_arg = RTAI_CALIBRATED_APIC_FREQ;MODULE_PARM(rtai_apicfreq_arg,"i");static long long rtai_timers_sync_time;static struct apic_timer_setup_data rtai_timer_mode[RTAI_NR_CPUS];static inline void rtai_setup_periodic_apic (unsigned count,					     unsigned vector){    apic_read(APIC_LVTT);    apic_write(APIC_LVTT,APIC_LVT_TIMER_PERIODIC|vector);    apic_read(APIC_TMICT);    apic_write(APIC_TMICT,count);}static inline void rtai_setup_oneshot_apic (unsigned count,					    unsigned vector){    apic_read(APIC_LVTT);    apic_write(APIC_LVTT,vector);    apic_read(APIC_TMICT);    apic_write(APIC_TMICT,count);}#else /* !CONFIG_X86_LOCAL_APIC */#define rtai_setup_periodic_apic(count,vector);#define rtai_setup_oneshot_apic(count,vector);#endif /* CONFIG_X86_LOCAL_APIC */#ifdef CONFIG_SMPstatic unsigned long rtai_old_irq_affinity[NR_IRQS],                     rtai_set_irq_affinity[NR_IRQS];static spinlock_t rtai_iset_lock = SPIN_LOCK_UNLOCKED;#endif /* CONFIG_SMP */#ifdef CONFIG_RTAI_SCHED_ISR_LOCKstatic int rtai_isr_nesting[RTAI_NR_CPUS];static void (*rtai_isr_hook)(int nesting);#endif /* CONFIG_RTAI_SCHED_ISR_LOCK */extern struct desc_struct idt_table[];adomain_t rtai_domain;static struct {    void (*handler)(unsigned irq, void *cookie);    void *cookie;} rtai_realtime_irq[NR_IRQS];static struct {    unsigned long flags;    int count;} rtai_linux_irq[NR_IRQS];static struct {    void (*k_handler)(void);    long long (*u_handler)(unsigned);    unsigned label;} rtai_sysreq_table[RTAI_NR_SRQS];static unsigned rtai_sysreq_virq;static unsigned long rtai_sysreq_map = 3; /* srqs #[0-1] are reserved */static unsigned long rtai_sysreq_pending;static unsigned long rtai_sysreq_running;static spinlock_t rtai_ssrq_lock = SPIN_LOCK_UNLOCKED;static volatile int rtai_sync_level;static atomic_t rtai_sync_count = ATOMIC_INIT(1);static int rtai_last_8254_counter2;static RTIME rtai_ts_8254;static struct desc_struct rtai_sysvec;static RT_TRAP_HANDLER rtai_trap_handler;static void (*rtai_exit_callback)(void);struct rt_times rt_times;struct rt_times rt_smp_times[RTAI_NR_CPUS];struct rtai_switch_data rtai_linux_context[RTAI_NR_CPUS];struct calibration_data rtai_tunables;volatile unsigned long rtai_status ;volatile unsigned long rtai_cpu_realtime;volatile unsigned long rtai_cpu_lock;volatile unsigned long rtai_cpu_lxrt;int rtai_adeos_ptdbase = -1;unsigned long rtai_critical_enter (void (*synch)(void)){    unsigned long flags = adeos_critical_enter(synch);    if (atomic_dec_and_test(&rtai_sync_count))	rtai_sync_level = 0;    else if (synch != NULL)	printk("RTAI: warning: nested sync will fail.\n");    return flags;}void rtai_critical_exit (unsigned long flags){    atomic_inc(&rtai_sync_count);    adeos_critical_exit(flags);}int rt_request_irq (unsigned irq,		    void (*handler)(unsigned irq, void *cookie),		    void *cookie){    unsigned long flags;    if (handler == NULL || irq >= NR_IRQS)	return -EINVAL;    flags = rtai_critical_enter(NULL);    if (rtai_realtime_irq[irq].handler != NULL)	{	rtai_critical_exit(flags);	return -EBUSY;	}    rtai_realtime_irq[irq].handler = handler;    rtai_realtime_irq[irq].cookie = cookie;    rtai_critical_exit(flags);    return 0;}int rt_release_irq (unsigned irq){    if (irq >= NR_IRQS)	return -EINVAL;    xchg(&rtai_realtime_irq[irq].handler,NULL);    return 0;}void rt_set_irq_cookie (unsigned irq, void *cookie) {    if (irq < NR_IRQS)	rtai_realtime_irq[irq].cookie = cookie;}/* Note: Adeos already does all the magic that allows the calling the   interrupt controller routines safely. *//** * start and initialize the PIC to accept interrupt request irq. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you * allow also any new interrupts on the same request as soon as you enable * interrupts at the CPU level. *  * Often some of the above functions do equivalent things. Once more there is no * way of doing it right except by knowing the hardware you are manipulating. * Furthermore you must also remember that when you install a hard real time * handler the related interrupt is usually disabled, unless you are overtaking * one already owned by Linux which has been enabled by it.   Recall that if * have done it right, and interrupts do not show up, it is likely you have just * to rt_enable_irq() your irq. */unsigned rt_startup_irq (unsigned irq) {    return irq_desc[irq].handler->startup(irq);}/** * Shut down an IRQ source. * * No further interrupt request irq can be accepted. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you * allow also any new interrupts on the same request as soon as you enable * interrupts at the CPU level. *  * Often some of the above functions do equivalent things. Once more there is no * way of doing it right except by knowing the hardware you are manipulating. * Furthermore you must also remember that when you install a hard real time * handler the related interrupt is usually disabled, unless you are overtaking * one already owned by Linux which has been enabled by it.   Recall that if * have done it right, and interrupts do not show up, it is likely you have just * to rt_enable_irq() your irq. */void rt_shutdown_irq (unsigned irq) {    irq_desc[irq].handler->shutdown(irq);}/** * Enable an IRQ source. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you * allow also any new interrupts on the same request as soon as you enable * interrupts at the CPU level. *  * Often some of the above functions do equivalent things. Once more there is no * way of doing it right except by knowing the hardware you are manipulating. * Furthermore you must also remember that when you install a hard real time * handler the related interrupt is usually disabled, unless you are overtaking * one already owned by Linux which has been enabled by it.   Recall that if * have done it right, and interrupts do not show up, it is likely you have just * to rt_enable_irq() your irq. */void rt_enable_irq (unsigned irq) {    irq_desc[irq].handler->enable(irq);}/** * Disable an IRQ source. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you * allow also any new interrupts on the same request as soon as you enable * interrupts at the CPU level. *  * Often some of the above functions do equivalent things. Once more there is no * way of doing it right except by knowing the hardware you are manipulating. * Furthermore you must also remember that when you install a hard real time * handler the related interrupt is usually disabled, unless you are overtaking * one already owned by Linux which has been enabled by it.   Recall that if * have done it right, and interrupts do not show up, it is likely you have just * to rt_enable_irq() your irq. */void rt_disable_irq (unsigned irq) {    irq_desc[irq].handler->disable(irq);}/** * Mask and acknowledge and IRQ source. * * No  * other interrupts can be accepted, once also the CPU will enable * interrupts, which ones depends on the PIC at hand and on how it is * programmed. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you * allow also any new interrupts on the same request as soon as you enable * interrupts at the CPU level. *  * Often some of the above functions do equivalent things. Once more there is no * way of doing it right except by knowing the hardware you are manipulating. * Furthermore you must also remember that when you install a hard real time * handler the related interrupt is usually disabled, unless you are overtaking * one already owned by Linux which has been enabled by it.   Recall that if * have done it right, and interrupts do not show up, it is likely you have just * to rt_enable_irq() your irq. */void rt_mask_and_ack_irq (unsigned irq) {    irq_desc[irq].handler->ack(irq);}/** * Unmask and IRQ source. * * The related request can then interrupt the CPU again, provided it has also * been acknowledged. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you * allow also any new interrupts on the same request as soon as you enable * interrupts at the CPU level. *  * Often some of the above functions do equivalent things. Once more there is no * way of doing it right except by knowing the hardware you are manipulating. * Furthermore you must also remember that when you install a hard real time * handler the related interrupt is usually disabled, unless you are overtaking * one already owned by Linux which has been enabled by it.   Recall that if * have done it right, and interrupts do not show up, it is likely you have just * to rt_enable_irq() your irq. */void rt_unmask_irq (unsigned irq) {    irq_desc[irq].handler->end(irq);}/** * Acknowledge an IRQ source. * * The related request can then interrupt the CPU again, provided it has not * been masked. * * The above function allow you to manipulate the PIC at hand, but you must * know what you are doing. Such a duty does not pertain to this manual and * you should refer to your PIC datasheet. * * Note that Linux has the same functions, but they must be used only for its * interrupts. Only the above ones can be safely used in real time handlers. * * It must also be remarked that when you install a real time interrupt handler, * RTAI already calls either rt_mask_and_ack_irq(), for level triggered * interrupts, or rt_ack_irq(), for edge triggered interrupts, before passing * control to you interrupt handler. hus generally you should just call * rt_unmask_irq() at due time, for level triggered interrupts, while nothing * should be done for edge triggered ones. Recall that in the latter case you

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -