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

📄 rtai.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 3 页
字号:
/*COPYRIGHT (C) 2000  Paolo Mantegazza (mantegazza@aero.polimi.it)              2001  David Schleef <ds@schleef.org>              2001  Lineo, Inc. <ds@lineo.com>	      2002  Wolfgang Grandegger (wg@denx.de)This program is free software; you can redistribute it and/or modifyit under the terms of version 2 of the GNU General Public License aspublished by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//* ACKNOWLEDGMENTS (LIKELY JUST A PRELIMINARY DRAFT): - Steve Papacharalambous (stevep@zentropix.com) has contributed an informative   proc filesystem procedure.*/#include <linux/module.h>#include <linux/version.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/irq.h>#ifdef CONFIG_SMP#include <linux/openpic.h>#endif#include <asm/system.h>#include <asm/hw_irq.h>#include <asm/smp.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/atomic.h>#ifdef CONFIG_PROC_FS#include <linux/stat.h>#include <linux/proc_fs.h>#include "rtai_proc_fs.h"#include "rtai_version.h"#endif#include <asm/rtai.h>#include <asm/rtai_srq.h>MODULE_LICENSE("GPL");#ifndef CONFIG_RTAI_MOUNT_ON_LOAD#define CONFIG_RTAI_MOUNT_ON_LOAD y#endif#ifdef CONFIG_MPC8260ADSvoid mpc8260ads_set_led(int led,int state);#endif#include <rtai_trace.h>// proc filesystem additions.static int rtai_proc_register(void);static void rtai_proc_unregister(void);// End of proc filesystem additions./* Some defines */#define BITS_PER_INT  	 	32 		#ifdef CONFIG_SMP/* The SMP code untested. We don't care about it for the moment */#define NR_RTAI_IRQS  	 	(2 * BITS_PER_INT)#define LAST_GLOBAL_RTAI_IRQ 	(BITS_PER_INT - 1)#define HARD_LOCK_IPI 	        62#else#if NR_IRQS < BITS_PER_INT#define NR_RTAI_IRQS  	 	NR_IRQS#else#define NR_RTAI_IRQS  	 	BITS_PER_INT#endif#define LAST_GLOBAL_RTAI_IRQ 	(NR_RTAI_IRQS - 1)#endif#define NR_SYSRQS  	 	32#define TIMER_IRQ 	31#define IRQ_DESC irq_desc/* * This allows LINUX to handle IRQs requested with the function  * rt_request_global_irq(). By default it's off for compatibility   * with the i386 port. */#undef GLOBAL_PEND_LINUX_IRQ/* Debugging for events that change the interrupt flag * * If you want to use this, you need to define the functions * blink() or blink_out().  blink() is called with 0 or 1 * to indicate whether interrupts are disabled or enabled. * blink_out() is called with the return address of the code * that triggered the interrupt flag change, with the low * bit set/unset as in blink.  (Since ppc code is always * word aligned, we can freely use the bottom 2 bits.) * * I use blink() to turn on/off LEDs and blink_out() to * write the return address serially over digital I/O lines * to a host system. -ds */#if defined(DEBUG_INTR_BLINK)#define set_intr_flag(a,b) do{			\		(a)=(b);			\		blink((b)&1);			\	}while(0)#define set_intr_flag_wasset(b) do{		\		blink((b)&1);			\	}while(0)#elif defined(DEBUG_INTR_SERIAL)#define set_intr_flag(a,b) do{			\		(a)=(b);			\		blink_out(((unsigned int)__builtin_return_address(0))|((b)&1));	\	}while(0)#define set_intr_flag_wasset(b) do{		\		blink_out(((unsigned int)__builtin_return_address(0))|((b)&1));	\	}while(0)#else#define set_intr_flag(a,b) do{ (a)=(b); }while(0)#define set_intr_flag_wasset(b)#endif/* Most of our data */#define RTAI_IRQ_UNMAPPED    0#define RTAI_IRQ_MAPPED      1#define RTAI_IRQ_MAPPED_TEMP 2static struct irq_handling {	int ppc_irq;	int mapped;#ifdef CONFIG_SMP	volatile unsigned long dest_status;		#endif	volatile int ext;			unsigned long data;	void (*handler)(unsigned int irq);	unsigned int irq_count;} global_irq[NR_RTAI_IRQS];static int rtai_irq[NR_IRQS];static struct hw_interrupt_type *linux_irq_desc_handler[NR_IRQS];static int map_ppc_irq(int irq, int rtai_irq_from, int rtai_irq_to){	int rirq;	for (rirq =  rtai_irq_from; rirq <= rtai_irq_to; rirq++) {		if (global_irq[rirq].mapped == RTAI_IRQ_UNMAPPED) {			global_irq[rirq].mapped = RTAI_IRQ_MAPPED;			global_irq[rirq].ppc_irq = irq;			rtai_irq[irq] = rirq;			return rirq;		}	}	printk("map_ppc_irq: no more slot available for IRQ %d!\n", irq);	return -1;}static inline int map_global_ppc_irq(int irq){	return map_ppc_irq(irq, 0, LAST_GLOBAL_RTAI_IRQ);}#ifdef CONFIG_SMPstatic inline void map_cpu_own_ppc_irq(int irq){	return map_ppc_irq(irq, LAST_GLOBAL_RTAI_IRQ + 1, NR_RTAI_IRQS - 1);}#endifstatic inline void unmap_ppc_irq(int irq){	int rirq;	if ((rirq = rtai_irq[irq]) >= 0) {		if (global_irq[rirq].mapped == RTAI_IRQ_MAPPED_TEMP) {			global_irq[rirq].mapped = RTAI_IRQ_UNMAPPED;			global_irq[rirq].ppc_irq = 0;			rtai_irq[irq] = -1;		} else {			printk("unmap_ppc_irq: oops, conistency error!\n"); 		}	} else {		printk("unmap_ppc_irq: IRQ %d is not mapped!\n", irq);	}}static struct sysrq_t {	unsigned int label;	void (*rtai_handler)(void);	long long (*user_handler)(unsigned int whatever);} sysrq[NR_SYSRQS];// The main items to be saved-restored to make Linux our humble slaveextern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,3)struct int_control_struct ppc_int_control;#endifstatic int (*ppc_get_irq)(struct pt_regs *regs);unsigned long ppc_irq_dispatcher, ppc_timer_handler;extern int (*rtai_srq_bckdr)(struct pt_regs *regs);/* Hook in the interrupt return path */extern void (*rtai_soft_sti)(void);static struct pt_regs rtai_regs;  // Dummy registers.static struct global_rt_status {	volatile unsigned int pending_irqs;	volatile unsigned int activ_irqs;	volatile unsigned int pending_srqs;	volatile unsigned int activ_srqs;	volatile unsigned int cpu_in_sti;	volatile unsigned int used_by_linux;  	volatile unsigned int locked_cpus;#ifdef CONFIG_SMP  	volatile unsigned int hard_nesting;	volatile unsigned int hard_lock_all_service;	spinlock_t hard_lock;#endif	spinlock_t data_lock;	spinlock_t ic_lock;} global;volatile unsigned int *locked_cpus = &global.locked_cpus;static struct cpu_own_status {	volatile unsigned int intr_flag;	volatile unsigned int linux_intr_flag;	volatile unsigned int pending_irqs;	volatile unsigned int activ_irqs;	void (*rt_timer_handler)(void);	void (*trailing_irq_handler)(int irq, void *dev_id, struct pt_regs *regs);} processor[NR_RT_CPUS]; #ifdef CONFIG_SMP/* Our interprocessor messaging */ void send_ipi_shorthand(unsigned int shorthand, int irq){	int cpuid;	unsigned long flags;	cpuid = hard_cpu_id();	hard_save_flags(flags);	hard_cli();	if (shorthand == APIC_DEST_ALLINC) {		openpic_cause_IPI(cpuid, irq, 0xFFFFFFFF);	} else {		openpic_cause_IPI(cpuid, irq, 0xFFFFFFFF & ~(1 << cpuid));	}	hard_restore_flags(flags);}void send_ipi_logical(unsigned long dest, int irq){	unsigned long flags;	if ((dest &= cpu_online_map)) {		hard_save_flags(flags);		openpic_cause_IPI(hard_cpu_id(), irq, dest);		hard_cli();		hard_restore_flags(flags);	}}static void hard_lock_all_handler(void){	int cpuid;	set_bit(cpuid = hard_cpu_id(), &global_irq[HARD_LOCK_IPI].dest_status);	rt_spin_lock(&(global.hard_lock));// No service at the moment.	rt_spin_unlock(&(global.hard_lock));	clear_bit(cpuid, &globa_irql[HARD_LOCK_IPI].dest_status);}static inline int hard_lock_all(void){	unsigned long flags;	flags = rt_global_save_flags_and_cli();	if (!global.hard_nesting++) {		global.hard_lock_all_service = 0;		rt_spin_lock(&(global.hard_lock));		send_ipi_shorthand(APIC_DEST_ALLBUT, HARD_LOCK_IPI);		while (global_irq[HARD_LOCK_IPI].dest_status != (cpu_online_map & ~global.locked_cpus));	}	return flags;}static inline void hard_unlock_all(unsigned long flags){	if (global.hard_nesting > 0) {		if (!(--global.hard_nesting)) {			rt_spin_unlock(&(global.hard_lock));			while (global_irq[HARD_LOCK_IPI].dest_status);		}	}	rt_global_restore_flags(flags);}#elsevoid send_ipi_shorthand(unsigned int shorthand, int irq) { }void send_ipi_logical(unsigned long dest, int irq) { }#if 0static void hard_lock_all_handler(void) { }#endifstatic inline unsigned long hard_lock_all(void){	unsigned long flags;	hard_save_flags_and_cli(flags);	return flags;}#define hard_unlock_all(flags) hard_restore_flags((flags))#endifstatic void linux_cli(void){ 	set_intr_flag(processor[hard_cpu_id()].intr_flag,0);}#if 0static void linux_soft_sti(void){       	unsigned long cpuid;       	struct cpu_own_status *cpu;	cpu = processor + (cpuid = hard_cpu_id());	set_intr_flag(cpu->intr_flag,(1 << IFLAG) | (1 << cpuid));}#endifstatic void run_pending_irqs(void){       	unsigned long irq, cpuid;       	struct cpu_own_status *cpu;	cpuid = hard_cpu_id();	if (!test_and_set_bit(cpuid, &global.cpu_in_sti)) {					cpu = processor + cpuid;		while (global.pending_irqs | cpu->pending_irqs | global.pending_srqs) {			hard_cli();			if ((irq = cpu->pending_irqs & ~(cpu->activ_irqs))) {				irq = ffnz(irq);				set_bit(irq, &cpu->activ_irqs);				clear_bit(irq, &cpu->pending_irqs);				hard_sti();				set_intr_flag(cpu->intr_flag,0);				if (irq == TIMER_IRQ) {					timer_interrupt(&rtai_regs);					if (cpu->trailing_irq_handler) {						(cpu->trailing_irq_handler)(TIMER_IRQ, 0, &rtai_regs);					}		       		} else {					printk("WHY HERE? AT THE MOMENT IT IS JUST UP, SO NO LOCAL IRQs.\n");				}				clear_bit(irq, &cpu->activ_irqs);	       		} else {				hard_sti();			}			rt_spin_lock_irq(&(global.data_lock));			if ((irq = global.pending_srqs & ~global.activ_srqs)) {				irq = ffnz(irq);				set_bit(irq, &global.activ_srqs);				clear_bit(irq, &global.pending_srqs);				rt_spin_unlock_irq(&(global.data_lock));				if (sysrq[irq].rtai_handler) {					sysrq[irq].rtai_handler();				}				clear_bit(irq, &global.activ_srqs);			} else {				rt_spin_unlock_irq(&(global.data_lock));			}			rt_spin_lock_irq(&(global.data_lock));			if ((irq = global.pending_irqs & ~global.activ_irqs)) {				irq = ffnz(irq);				set_bit(irq, &global.activ_irqs);				clear_bit(irq, &global.pending_irqs);				rt_spin_unlock_irq(&(global.data_lock));				set_intr_flag(cpu->intr_flag,0);                                /* from Linux do_IRQ */                                hardirq_enter(cpuid);				ppc_irq_dispatch_handler(&rtai_regs, global_irq[irq].ppc_irq);                                hardirq_exit(cpuid);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) /* ? */				if (softirq_pending(cpuid)) {					do_softirq();				}#endif				clear_bit(irq, &global.activ_irqs);			} else {				rt_spin_unlock_irq(&(global.data_lock));			}		}		clear_bit(cpuid, &global.cpu_in_sti);	} 	/* We _should_ do this, but it doesn't work correctly */	//if(atomic_read(&ppc_n_lost_interrupts))do_lost_interrupts(MSR_EE);}static void linux_sti(void){	run_pending_irqs();	set_intr_flag(processor[hard_cpu_id()].intr_flag,		      (1 << IFLAG) | (1 << hard_cpu_id()));}static void linux_save_flags(unsigned long *flags){	*flags = processor[hard_cpu_id()].intr_flag;}static void linux_restore_flags(unsigned long flags){	if (flags) {		linux_sti();	} else {		set_intr_flag(processor[hard_cpu_id()].intr_flag,0);	}}unsigned int linux_save_flags_and_cli(void){	unsigned int ret;	ret = xchg_u32((void *)(&(processor[hard_cpu_id()].intr_flag)), 0);	set_intr_flag_wasset(0);	return ret;}unsigned int linux_save_flags_and_cli_cpuid(int cpuid)  // LXRT specific{	return xchg_u32((void *)&(processor[cpuid].intr_flag), 0);}void rtai_just_copy_back(unsigned long flags, int cpuid){        set_intr_flag(processor[cpuid].intr_flag,flags);}static void (*ic_ack_irq[NR_IRQS])    (unsigned int irq);static void do_nothing_picfun(unsigned int irq) { };unsigned int rt_startup_irq(unsigned int irq){	unsigned long flags, retval;	struct hw_interrupt_type *irq_desc;	if ((irq_desc = linux_irq_desc_handler[irq]) && irq_desc->startup) {		flags = rt_spin_lock_irqsave(&global.ic_lock);		retval = irq_desc->startup(irq);		rt_spin_unlock_irqrestore(flags, &global.ic_lock);		return retval;	}	return 0;}void rt_shutdown_irq(unsigned int irq){	unsigned int flags;	struct hw_interrupt_type *irq_desc;	if ((irq_desc = linux_irq_desc_handler[irq]) && irq_desc->shutdown) {		flags = rt_spin_lock_irqsave(&global.ic_lock);		irq_desc->shutdown(irq);		rt_spin_unlock_irqrestore(flags, &global.ic_lock);	}}void rt_enable_irq(unsigned int irq){	unsigned int flags;	struct hw_interrupt_type *irq_desc;	if ((irq_desc = linux_irq_desc_handler[irq]) && irq_desc->enable) {		flags = rt_spin_lock_irqsave(&global.ic_lock);		irq_desc->enable(irq);		rt_spin_unlock_irqrestore(flags, &global.ic_lock);	}}void rt_disable_irq(unsigned int irq){	unsigned int flags;	struct hw_interrupt_type *irq_desc;	if ((irq_desc = linux_irq_desc_handler[irq]) && irq_desc->disable) {		flags = rt_spin_lock_irqsave(&global.ic_lock);		irq_desc->disable(irq);		rt_spin_unlock_irqrestore(flags, &global.ic_lock);	}}void rt_ack_irq(unsigned int irq){	unsigned int flags;	flags = rt_spin_lock_irqsave(&global.ic_lock);	if(ic_ack_irq[irq])		ic_ack_irq[irq](irq);	rt_spin_unlock_irqrestore(flags, &global.ic_lock);}void rt_unmask_irq(unsigned int irq){	unsigned int flags;	struct hw_interrupt_type *irq_desc;	if ((irq_desc = linux_irq_desc_handler[irq])) {		flags = rt_spin_lock_irqsave(&global.ic_lock);		if(linux_irq_desc_handler[irq]->end)			linux_irq_desc_handler[irq]->end(irq);		else if(linux_irq_desc_handler[irq]->enable)			linux_irq_desc_handler[irq]->enable(irq);		rt_spin_unlock_irqrestore(flags, &global.ic_lock);	}}static int dispatch_irq(struct pt_regs *regs, int isfake){	int irq, rirq;		rt_spin_lock(&global.ic_lock);	if ((irq = ppc_get_irq(regs)) >= 0) {		if(ic_ack_irq[irq])			ic_ack_irq[irq](irq);            // Any umasking must be done in the irq handler.		rt_spin_unlock(&global.ic_lock);

⌨️ 快捷键说明

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