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

📄 rt.c

📁 rtlinux-3.2源码
💻 C
字号:
/*    comedi/rt.c    comedi kernel module    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>    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; 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., 675 Mass Ave, Cambridge, MA 02139, USA.*/#undef DEBUG#define __NO_VERSION__#include <linux/comedidev.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fcntl.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/irq.h>#include <asm/io.h>#include "rt_pend_tq.h"#ifdef CONFIG_COMEDI_RTAI#include <rtai.h>#define RT_protect()	hard_cli()#define RT_unprotect()	hard_sti()#define RT_spin_lock_irq(x)	rt_spin_lock_irq(x)#define RT_spin_unlock_irq(x)	rt_spin_unlock_irq(x)#endif#ifdef CONFIG_COMEDI_RTL#include <rtl_core.h>#include <rtl_sync.h>#define RT_protect()	rtl_make_rt_system_active()#define RT_unprotect()	rtl_make_rt_system_idle()/* RTL doesn't have the necessary primitives, so we have to hack * it, dealing with the race */#define RT_spin_lock_irq(x)	do{RT_protect();rtl_spin_lock(x);}while(0)#define RT_spin_unlock_irq(x)	do{rtl_spin_unlock(x);RT_unprotect();}while(0)#endif#ifdef CONFIG_PRIORITY_IRQ#define RT_protect()	__local_irq_disable()#define RT_unprotect()	__local_irq_enable()#define RT_spin_lock_irq(x)	spin_lock_hard_irq(x)#define RT_spin_unlock_irq(x)	spin_unlock_hard_irq(x)#endifstruct comedi_irq_struct {	int rt;	int irq;	void (*handler)(int irq,void *dev_id,struct pt_regs *regs);	unsigned long flags;	const char *device;	comedi_device *dev_id;};static int rt_get_irq(struct comedi_irq_struct *it);static int rt_release_irq(struct comedi_irq_struct *it);#define MAX_IRQ_SHARING 6static struct comedi_irq_struct *comedi_irqs[NR_IRQS][MAX_IRQ_SHARING];static struct comedi_irq_struct * find_comedi_irq_struct( int irq, comedi_device *dev_id ){	int i;	for( i = 0; i < MAX_IRQ_SHARING; i++)	{		if( comedi_irqs[ irq ][ i ] &&			comedi_irqs[ irq ][ i ]->dev_id == dev_id )		{			return comedi_irqs[ irq ][ i ];		}	}	return NULL;}static void free_comedi_irq_struct( int irq, comedi_device *dev_id ){	int i;	for( i = 0; i < MAX_IRQ_SHARING; i++)	{		if( comedi_irqs[ irq ][ i ] &&			comedi_irqs[ irq ][ i ]->dev_id == dev_id )		{			kfree( comedi_irqs[ irq ][ i ] );			comedi_irqs[ irq ][ i ] = NULL;			return;		}	}}static int insert_comedi_irq_struct( int irq,	struct comedi_irq_struct *it ){	int i;	for( i = 0; i < MAX_IRQ_SHARING; i++ )	{		if( comedi_irqs[ irq ][ i ] == NULL )		{			comedi_irqs[ irq ][ i ] = it;			return 0;		}	}	return -1;}int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *),		unsigned long flags,const char *device,comedi_device *dev_id){	struct comedi_irq_struct *it;	int ret;	it=kmalloc(sizeof(*it),GFP_KERNEL);	if(!it)		return -ENOMEM;	memset(it,0,sizeof(*it));	it->handler=handler;	it->irq=irq;	it->dev_id=dev_id;	it->device=device;	/* null shared interrupt flag, since rt interrupt handlers do not	 * support it, and this version of comedi_request_irq() is only	 * called for kernels with rt support */	it->flags = flags & ~SA_SHIRQ;	ret=request_irq(irq,handler,it->flags,device,dev_id);	if(ret<0){		// we failed, so fall back on allowing shared interrupt		if(flags & SA_SHIRQ)		{			it->flags = flags;			ret=request_irq(irq,handler,it->flags,device,dev_id);		}		if(ret<0){			kfree(it);			return ret;		}	}	if( insert_comedi_irq_struct( irq, it ) )	{		kfree(it);		return -1;	}	return 0;}void comedi_free_irq(unsigned int irq,comedi_device *dev_id){	struct comedi_irq_struct *it;	it = find_comedi_irq_struct( irq, dev_id );	if( it == NULL ) return;	if(it->rt){		printk("real-time IRQ allocated at board removal (ignore)\n");		rt_release_irq(it);	}	free_irq(it->irq,it->dev_id);	free_comedi_irq_struct( irq, dev_id );}int comedi_switch_to_rt(comedi_device *dev){	struct comedi_irq_struct *it;	unsigned long flags;	it = find_comedi_irq_struct( dev->irq, dev );	/* drivers might not be using an interrupt for commands */	if( it == NULL ) return -1;	/* rt interrupts and shared interrupts don't mix */	if(it->flags & SA_SHIRQ){		DPRINTK( "cannot switch shared interrupt to real time priority\n" );		return -1;	}	comedi_spin_lock_irqsave( &dev->spinlock, flags );	if(!dev->rt)		rt_get_irq(it);	dev->rt++;	it->rt=1;	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );	return 0;}void comedi_switch_to_non_rt(comedi_device *dev){	struct comedi_irq_struct *it;	unsigned long flags;	it = find_comedi_irq_struct( dev->irq, dev );	if(it == NULL)		return;	/* rt interrupts and shared interrupts don't mix */	if(it->flags & SA_SHIRQ)		return;	comedi_spin_lock_irqsave( &dev->spinlock, flags );	dev->rt--;	if(!dev->rt)		rt_release_irq(it);	it->rt=0;	comedi_spin_unlock_irqrestore( &dev->spinlock, flags );}void wake_up_int_handler(int arg1, void * arg2){	wake_up_interruptible((wait_queue_head_t*)arg2);}void comedi_rt_pend_wakeup(wait_queue_head_t *q){	rt_pend_call(wake_up_int_handler,0,q);}/* RTAI section */#ifdef CONFIG_COMEDI_RTAI#ifdef CONFIG_PPC#define HAVE_RT_REQUEST_IRQ_WITH_ARG#endif#ifndef HAVE_RT_REQUEST_IRQ_WITH_ARG#define DECLARE_VOID_IRQ(irq) \static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);}static void handle_void_irq(int irq){	int i;	struct comedi_irq_struct *it;	for( i = 0; i < MAX_IRQ_SHARING; i++ )	{		it = comedi_irqs[ irq ][ i ];		if( it == NULL ) continue;		it->handler( irq, it->dev_id, NULL );	}}DECLARE_VOID_IRQ(0);DECLARE_VOID_IRQ(1);DECLARE_VOID_IRQ(2);DECLARE_VOID_IRQ(3);DECLARE_VOID_IRQ(4);DECLARE_VOID_IRQ(5);DECLARE_VOID_IRQ(6);DECLARE_VOID_IRQ(7);DECLARE_VOID_IRQ(8);DECLARE_VOID_IRQ(9);DECLARE_VOID_IRQ(10);DECLARE_VOID_IRQ(11);DECLARE_VOID_IRQ(12);DECLARE_VOID_IRQ(13);DECLARE_VOID_IRQ(14);DECLARE_VOID_IRQ(15);DECLARE_VOID_IRQ(16);DECLARE_VOID_IRQ(17);DECLARE_VOID_IRQ(18);DECLARE_VOID_IRQ(19);DECLARE_VOID_IRQ(20);DECLARE_VOID_IRQ(21);DECLARE_VOID_IRQ(22);DECLARE_VOID_IRQ(23);typedef void (*V_FP_V)(void);static V_FP_V handle_void_irq_ptrs[]={	handle_void_irq_0,	handle_void_irq_1,	handle_void_irq_2,	handle_void_irq_3,	handle_void_irq_4,	handle_void_irq_5,	handle_void_irq_6,	handle_void_irq_7,	handle_void_irq_8,	handle_void_irq_9,	handle_void_irq_10,	handle_void_irq_11,	handle_void_irq_12,	handle_void_irq_13,	handle_void_irq_14,	handle_void_irq_15,	handle_void_irq_16,	handle_void_irq_17,	handle_void_irq_18,	handle_void_irq_19,	handle_void_irq_20,	handle_void_irq_21,	handle_void_irq_22,	handle_void_irq_23,};/* if you need more, fix it yourself... */static int rt_get_irq(struct comedi_irq_struct *it){	rt_request_global_irq(it->irq,handle_void_irq_ptrs[it->irq]);	rt_startup_irq(it->irq);	return 0;}static int rt_release_irq(struct comedi_irq_struct *it){	rt_shutdown_irq(it->irq);	rt_free_global_irq(it->irq);	return 0;}#elsestatic int rt_get_irq(struct comedi_irq_struct *it){	int ret;	ret = rt_request_global_irq_arg(it->irq,it->handler,it->flags,			it->device,it->dev_id);	if(ret<0){		rt_printk("rt_request_global_irq_arg() returned %d\n",ret);		return ret;	}	rt_startup_irq(it->irq);	return 0;}static int rt_release_irq(struct comedi_irq_struct *it){	rt_shutdown_irq(it->irq);	rt_free_global_irq(it->irq);	return 0;}#endifvoid comedi_rt_init(void){	rt_mount_rtai();	rt_pend_tq_init();}void comedi_rt_cleanup(void){	rt_umount_rtai();	rt_pend_tq_cleanup();}#endif/* RTLinux section */#ifdef CONFIG_COMEDI_RTLstatic unsigned int handle_rtl_irq(unsigned int irq,struct pt_regs *regs){	int i;	struct comedi_irq_struct *it;	for( i = 0; i < MAX_IRQ_SHARING; i++ )	{		it = comedi_irqs[ irq ][ i ];		if( it == NULL ) continue;		it->handler( irq, it->dev_id, regs );	}	rtl_hard_enable_irq(irq);	return 0;}static int rt_get_irq(struct comedi_irq_struct *it){	rtl_request_global_irq(it->irq,handle_rtl_irq);	return 0;}static int rt_release_irq(struct comedi_irq_struct *it){	rtl_free_global_irq(it->irq);	return 0;}void comedi_rt_init(void){	rt_pend_tq_init();}void comedi_rt_cleanup(void){	rt_pend_tq_cleanup();}#endif#ifdef CONFIG_COMEDI_PIRQstatic int rt_get_irq(struct comedi_irq_struct *it){	int ret;	free_irq(it->irq,it->dev_id);	ret=request_irq(it->irq,it->handler,it->flags|SA_PRIORITY,		it->device,it->dev_id);	return ret;}static int rt_release_irq(struct comedi_irq_struct *it){	int ret;	free_irq(it->irq,it->dev_id);	ret=request_irq(it->irq,it->handler,it->flags,		it->device,it->dev_id);	return ret;}void comedi_rt_init(void){	//rt_pend_tq_init();}void comedi_rt_cleanup(void){	//rt_pend_tq_cleanup();}#endif

⌨️ 快捷键说明

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