From 4bd46571f2100f8773d48172c1627f0335268f2a Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 25 Nov 2000 00:10:34 +0000 Subject: [PATCH] fixed poll, select, mod use count for RT; many RT fixes/changes; more support for running drivers RT from user space; pcl818: added pcm3718; quatech_daqp_cs: fixed compilation; kcomedilib: added specific EXPORT_SYMBOL()s --- TODO | 6 - comedi/Makefile | 12 -- comedi/comedi_fops.c | 141 ++++++++--------- comedi/comedi_ksyms.c | 6 +- comedi/comedi_rt.h | 83 +++------- comedi/drivers/ni_mio_common.c | 27 ---- comedi/drivers/pcl818.c | 3 + comedi/drivers/quatech_daqp_cs.c | 5 +- comedi/kcomedilib/kcomedilib_main.c | 56 +++++++ comedi/rt.c | 237 ++++++++++++++++++++++------ include/linux/comedidev.h | 11 +- 11 files changed, 343 insertions(+), 244 deletions(-) diff --git a/TODO b/TODO index 2204663e..637e9548 100644 --- a/TODO +++ b/TODO @@ -21,16 +21,10 @@ verify 2.0.x operation develop 8253 and Am9513 code -increase mod use count for RT - different error code for board error vs buffer overflow change _recognize to const char * -implement poll/select - -fix mmap - ni_mio_common: gpct code broken ni_mio_common: external trigger doesn't work diff --git a/comedi/Makefile b/comedi/Makefile index 8213c6dd..04eeae40 100644 --- a/comedi/Makefile +++ b/comedi/Makefile @@ -36,18 +36,6 @@ ifeq ($(CONFIG_COMEDI_RT),y) MI_OBJS += rt.o endif -ifeq ($(CONFIG_COMEDI_RTL),y) -MI_OBJS += rtl.o -endif - -ifeq ($(CONFIG_COMEDI_RTAI),y) -MI_OBJS += rtai.o -endif - -ifeq ($(CONFIG_COMEDI_RTL_V1),y) -MI_OBJS += rtl_v1.o -endif - include $(TOPDIR)/Rules.make diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index 34e970a0..9793377d 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -43,6 +43,7 @@ #if LINUX_VERSION_CODE >= 0x020100 #include #endif +#include comedi_device *comedi_devices; @@ -550,12 +551,6 @@ static int do_trig_ioctl_modeN(comedi_device *dev,comedi_subdevice *s,comedi_tri } s->runflags=SRF_USER; -#ifdef CONFIG_COMEDI_RT - if(s->cur_trig.flags & TRIG_RT){ - s->runflags|=SRF_RT; - // FIXME: TM move device to rt - } -#endif s->subdev_flags|=SDF_RUNNING; @@ -848,15 +843,14 @@ if(s->subdev_flags & SDF_READABLE){ } s->runflags=SRF_USER; -#ifdef CONFIG_COMEDI_RT - if(s->cmd.flags & TRIG_RT){ - s->runflags|=SRF_RT; - // move device to rt - } -#endif s->subdev_flags|=SDF_RUNNING; + if(s->cmd.flags&TRIG_RT){ + comedi_switch_to_rt(dev); + s->runflags |= SRF_RT; + } + ret=s->do_cmd(dev,s); if(ret==0)return 0; @@ -1109,75 +1103,56 @@ static int do_cancel(comedi_device *dev,comedi_subdevice *s) } #ifdef LINUX_V22 +static void comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y); + +static struct vm_operations_struct comedi_vm_ops={ + unmap: comedi_unmap, +}; + /* comedi_mmap_v22 - mmap issues: - - mmap has issues with lock and busy - - mmap has issues with reference counting - - RT issues? - - unmapping: - vm_ops->unmap() - - this needs to call comedi_cancel, or whatever. + issues: + what happens when the underlying buffer gets changed? + */ static int comedi_mmap_v22(struct file * file, struct vm_area_struct *vma) { kdev_t minor=MINOR(RDEV_OF_FILE(file)); comedi_device *dev=comedi_get_device_by_minor(minor); comedi_subdevice *s; - int size; - unsigned long offset; - -#if LINUX_VERSION_CODE < 0x020300 - offset=vma->vm_offset; -#else - offset=0; /* XXX */ -#endif - if(offset >= dev->n_subdevices) - return -EIO; - s=dev->subdevices+offset; - - if((vma->vm_flags & VM_WRITE) && !(s->subdev_flags & SDF_WRITEABLE)) - return -EINVAL; + int subdev; - if((vma->vm_flags & VM_READ) && !(s->subdev_flags & SDF_READABLE)) + if(vma->vm_flags & VM_WRITE){ + subdev=dev->write_subdev; + }else{ + subdev=dev->read_subdev; + } + if(subdev<0){ return -EINVAL; + } + s=dev->subdevices+subdev; - size = vma->vm_end - vma->vm_start; - if(size>(1<<16)) + if(vma->vm_pgoff != 0){ + DPRINTK("comedi: mmap() offset must be 0.\n"); return -EINVAL; + } - if(remap_page_range(vma->vm_start, virt_to_phys(s->prealloc_buf), - size,vma->vm_page_prot)) - return -EAGAIN; + rvmmap(s->prealloc_buf,s->prealloc_bufsz,vma); - vma->vm_file=file; -#if 0 - file->f_count++; -#else + vma->vm_file = file; + vma->vm_ops = &comedi_vm_ops; file_atomic_inc(&file->f_count); -#endif - /* mark subdev as mapped */ + /* XXX mark subdev as mapped */ - /* call subdev about mmap, if necessary */ -printk("mmap done\n"); - return 0; } -#if 0 -/* - I can't find a driver that notices when it gets unmapped. - */ -static void *comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y) +static void comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y) { printk("comedi unmap\n"); - - return NULL; } -#endif #endif @@ -1186,7 +1161,7 @@ static void *comedi_unmap(struct vm_area_struct *area,unsigned long x,size_t y) static unsigned int comedi_poll_v22(struct file *file, poll_table * wait) { comedi_device *dev; - //comedi_subdevice *s; + comedi_subdevice *s; unsigned int mask; dev=comedi_get_device_by_minor(MINOR(RDEV_OF_FILE(file))); @@ -1194,11 +1169,16 @@ static unsigned int comedi_poll_v22(struct file *file, poll_table * wait) poll_wait(file, &dev->read_wait, wait); poll_wait(file, &dev->write_wait, wait); mask = 0; -/* XXX incomplete */ - if(0) - mask |= POLLIN | POLLRDNORM; - if(0) - mask |= POLLOUT | POLLWRNORM; + if(dev->read_subdev>=0){ + s=dev->subdevices+dev->read_subdev; + if(s->buf_user_count < s->buf_int_count) + mask |= POLLIN | POLLRDNORM; + } + if(dev->write_subdev>=0){ + s=dev->subdevices+dev->write_subdev; + if(s->buf_user_count < s->buf_int_count + s->prealloc_bufsz) + mask |= POLLOUT | POLLWRNORM; + } return mask; } @@ -1405,11 +1385,10 @@ static void do_become_nonbusy(comedi_device *dev,comedi_subdevice *s) /* we do this because it's useful for the non-standard cases */ s->subdev_flags &= ~SDF_RUNNING; -#ifdef CONFIG_COMEDI_RT if(s->runflags&SRF_RT){ - // FIXME: TM move device out of rt + comedi_switch_to_non_rt(dev); + s->runflags &= ~SRF_RT; } -#endif if(s->cur_trig.chanlist){ /* XXX wrong? */ kfree(s->cur_trig.chanlist); @@ -1574,6 +1553,9 @@ static struct file_operations comedi_fops={ #define comedi_open_v22 comedi_fop_open static struct file_operations comedi_fops={ +#if LINUX_VERSION_CODE >= 0x020400 + owner : THIS_MODULE, +#endif llseek : comedi_lseek_v22, ioctl : comedi_ioctl_v22, open : comedi_open_v22, @@ -1614,7 +1596,7 @@ int comedi_init(void) comedi_proc_init(); #ifdef CONFIG_COMEDI_RT - comedi_rt_init(); +// comedi_rt_init(); #endif init_drivers(); @@ -1644,7 +1626,7 @@ void comedi_cleanup(void) kfree(comedi_devices); #ifdef CONFIG_COMEDI_RT - comedi_rt_cleanup(); +// comedi_rt_cleanup(); #endif } @@ -1670,20 +1652,31 @@ void comedi_event(comedi_device *dev,comedi_subdevice *s,unsigned int mask) { if(s->cb_mask&mask){ if(s->runflags&SRF_USER){ - if(s->runflags&SRF_RT){ + unsigned int subdev; + + subdev = s - dev->subdevices; + if(dev->rt){ // pend wake up + if(subdev==dev->read_subdev) + comedi_rt_pend_wakeup(&dev->read_wait); + if(subdev==dev->write_subdev) + comedi_rt_pend_wakeup(&dev->write_wait); }else{ - unsigned int subdev; - - subdev = s - dev->subdevices; - if(subdev==dev->read_subdev) wake_up_interruptible(&dev->read_wait); if(subdev==dev->write_subdev) wake_up_interruptible(&dev->write_wait); } }else{ - s->cb_func(mask,s->cb_arg); + if(s->runflags&SRF_RT){ + s->cb_func(mask,s->cb_arg); + }else{ + /* XXX bug here. If subdevice A is rt, and + * subdevice B tries to callback to a normal + * linux kernel function, it will be at the + * wrong priority. Since this isn't very + * common, I'm not going to worry about it. */ + } } } diff --git a/comedi/comedi_ksyms.c b/comedi/comedi_ksyms.c index fb5e8686..baac6bde 100644 --- a/comedi/comedi_ksyms.c +++ b/comedi/comedi_ksyms.c @@ -42,10 +42,11 @@ EXPORT_SYMBOL(comedi_bufcheck); EXPORT_SYMBOL(comedi_done); EXPORT_SYMBOL(comedi_error_done); EXPORT_SYMBOL(comedi_error); -EXPORT_SYMBOL(do_pack); -EXPORT_SYMBOL(di_unpack); EXPORT_SYMBOL(comedi_eobuf); EXPORT_SYMBOL(comedi_eos); +EXPORT_SYMBOL(comedi_event); +EXPORT_SYMBOL(do_pack); +EXPORT_SYMBOL(di_unpack); EXPORT_SYMBOL(range_bipolar10); EXPORT_SYMBOL(range_bipolar5); EXPORT_SYMBOL(range_bipolar2_5); @@ -53,7 +54,6 @@ EXPORT_SYMBOL(range_unipolar10); EXPORT_SYMBOL(range_unipolar5); EXPORT_SYMBOL(range_unknown); #ifdef CONFIG_COMEDI_RT -EXPORT_SYMBOL(comedi_change_irq_flags); EXPORT_SYMBOL(comedi_free_irq); EXPORT_SYMBOL(comedi_request_irq); #endif diff --git a/comedi/comedi_rt.h b/comedi/comedi_rt.h index ecb27688..09a47ee5 100644 --- a/comedi/comedi_rt.h +++ b/comedi/comedi_rt.h @@ -30,80 +30,35 @@ #include #include #include -#include +#include - -#include - - -struct comedi_irq_struct{ - struct comedi_irq_struct *next; - - int irq; - void *dev_id; - unsigned long flags; - void (*handler)(int,void *,struct pt_regs *); - const char *device; -}; - -int get_priority_irq(struct comedi_irq_struct *); -int free_priority_irq(struct comedi_irq_struct *); -struct comedi_irq_struct * get_irq_struct(unsigned int); - -#ifndef SA_PRIORITY -#define SA_PRIORITY 0x08000000 -#endif - -#ifdef CONFIG_COMEDI_RTL -void comedi_rtl_init(void); -void comedi_rtl_cleanup(void); -#define comedi_rt_init comedi_rtl_init -#define comedi_rt_cleanup comedi_rtl_cleanup - -#include - -#define NEED_RT_PEND_TQ -#endif +#ifdef CONFIG_COMEDI_RT #ifdef CONFIG_COMEDI_RTAI -void comedi_rtai_init(void); -void comedi_rtai_cleanup(void); -#define comedi_rt_init comedi_rtai_init -#define comedi_rt_cleanup comedi_rtai_cleanup - -#define NEED_RT_PEND_TQ -#define NEED_RT_PRINTK -#endif - -#ifdef CONFIG_COMEDI_RTL_V1 -void comedi_rtl_v1_init(void); -void comedi_rtl_v1_cleanup(void); -#define comedi_rt_init comedi_rtl_v1_init -#define comedi_rt_cleanup comedi_rtl_v1_cleanup - -/* we do not have sort IRQs (unless my v1 patch is used) T.M. */ - -#define NEED_RT_PRINTK -#endif - -#ifdef NEED_RT_PEND_TQ -#include -extern void wake_up_int_handler(int arg1, void * arg2); -#endif - -#ifdef NEED_RT_PRINTK -#define rt_printk(format,args...) printk(format,##args) -#define rt_printk_init() -#define rt_printk_cleanup() +#include #endif int comedi_request_irq(unsigned int irq,void (*handler)(int,void *, struct pt_regs *regs),unsigned long flags,const char *device, void *dev_id); -int comedi_change_irq_flags(unsigned int irq,void *dev_id, - unsigned long new_flags); void comedi_free_irq(unsigned int irq,void *dev_id); +void comedi_rt_init(void); +void comedi_rt_cleanup(void); +void comedi_switch_to_rt(comedi_device *dev); +void comedi_switch_to_non_rt(comedi_device *dev); +void comedi_rt_pend_wakeup(wait_queue_head_t *q); + +#else + +#define comedi_request_irq(a,b,c,d,e) request_irq(a,b,c,d,e) +#define comedi_free_irq(a,b) free_irq(a,b) +#define comedi_rt_init() do{}while(0) +#define comedi_rt_cleanup() do{}while(0) +#define comedi_swtich_to_rt(a) do{}while(0) +#define comedi_swtich_to_non_rt(a) do{}while(0) +#define comedi_rt_pend_wakeup(a) do{}while(0) +#endif #endif diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index a503ff77..22bfb4b3 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -190,31 +190,6 @@ static int ni_gpct_insn_read(comedi_device *dev,comedi_subdevice *s, #define AIMODE_SCAN 2 #define AIMODE_SAMPLE 3 -#ifdef CONFIG_COMEDI_RT - -#define RTirqmask_AI 1 -#define RTirqmask_AO 2 - -static int ni_ai_lock(comedi_device *dev,comedi_subdevice *s) -{ - comedi_change_irq_flags(dev->irq,dev,NI_E_IRQ_FLAGS | SA_PRIORITY ); - - return 0; -} - -static int ni_ai_unlock(comedi_device *dev,comedi_subdevice *s) -{ - comedi_change_irq_flags(dev->irq,dev,NI_E_IRQ_FLAGS ); - - return 0; -} - -#else - -#define ni_ai_lock NULL -#define ni_ai_unlock NULL - -#endif static void ni_E_interrupt(int irq,void *d,struct pt_regs * regs) { @@ -1665,8 +1640,6 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) s->do_cmdtest=ni_ai_cmdtest; s->do_cmd=ni_ai_cmd; s->cancel=ni_ai_reset; - s->do_lock=ni_ai_lock; - s->do_unlock=ni_ai_unlock; /* analog output subdevice */ /* XXX what about boards without ao? */ diff --git a/comedi/drivers/pcl818.c b/comedi/drivers/pcl818.c index e604dabb..999f2307 100644 --- a/comedi/drivers/pcl818.c +++ b/comedi/drivers/pcl818.c @@ -252,6 +252,9 @@ static boardtype boardtypes[] = 0x0a, 0xfff, 0xfff, 1024, 2, 0 }, {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5, &range_unipolar5, PCLx1x_RANGE, 0x00fc, 0x0a, 0xfff, 0xfff, 1024, 2, 0 }, + /* pcm3718 */ + {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai, &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 1024, 0, 0 }, }; #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype)) diff --git a/comedi/drivers/quatech_daqp_cs.c b/comedi/drivers/quatech_daqp_cs.c index 693269d4..79ae66f2 100644 --- a/comedi/drivers/quatech_daqp_cs.c +++ b/comedi/drivers/quatech_daqp_cs.c @@ -28,10 +28,11 @@ ======================================================================*/ -#include -#include +//#include +//#include #include +#include #include #include #include diff --git a/comedi/kcomedilib/kcomedilib_main.c b/comedi/kcomedilib/kcomedilib_main.c index 898c4289..81d55dc7 100644 --- a/comedi/kcomedilib/kcomedilib_main.c +++ b/comedi/kcomedilib/kcomedilib_main.c @@ -24,6 +24,7 @@ #include +#include #include @@ -669,6 +670,7 @@ int comedi_lock_ioctl(unsigned int minor,unsigned int subdev) if(s->lock && s->lock!=&rtcomedi_lock_semaphore){ ret=-EACCES; }else{ + __MOD_INC_USE_COUNT(dev->driver->module); s->lock=(void *)&rtcomedi_lock_semaphore; if(s->do_lock) @@ -724,6 +726,8 @@ int comedi_unlock_ioctl(unsigned int minor,unsigned int subdev) s->cb_mask=0; s->cb_func=NULL; s->cb_arg=NULL; + + __MOD_DEC_USE_COUNT(dev->driver->module); } return 0; @@ -827,4 +831,56 @@ int comedi_register_callback(unsigned int minor,unsigned int subdev, return 0; } +/* XXX */ +void comedi_cancel(void); +void comedi_lock(void); +void comedi_unlock(void); +void comedi_trigger(void); + + + +#ifdef LINUX_V22 + +EXPORT_SYMBOL(comedi_open); +EXPORT_SYMBOL(comedi_close); +//EXPORT_SYMBOL(comedi_loglevel); +//EXPORT_SYMBOL(comedi_perror); +//EXPORT_SYMBOL(comedi_strerror); +//EXPORT_SYMBOL(comedi_errno); +//EXPORT_SYMBOL(comedi_fileno); +EXPORT_SYMBOL(comedi_get_n_subdevices); +EXPORT_SYMBOL(comedi_find_subdevice_by_type); +EXPORT_SYMBOL(comedi_get_n_channels); +EXPORT_SYMBOL(comedi_get_maxdata); +EXPORT_SYMBOL(comedi_get_rangetype); +//EXPORT_SYMBOL(comedi_get_range); +//EXPORT_SYMBOL(comedi_find_range); +EXPORT_SYMBOL(comedi_get_n_ranges); +//EXPORT_SYMBOL(comedi_range_is_chan_specific); +//EXPORT_SYMBOL(comedi_maxdata_is_chan_specific); +EXPORT_SYMBOL(comedi_cancel); +EXPORT_SYMBOL(comedi_trigger); +//EXPORT_SYMBOL(comedi_command); +//EXPORT_SYMBOL(comedi_command_test); +//EXPORT_SYMBOL(comedi_do_insnlist); +//EXPORT_SYMBOL(comedi_do_insn); +EXPORT_SYMBOL(comedi_lock); +EXPORT_SYMBOL(comedi_unlock); +//EXPORT_SYMBOL(comedi_to_phys); +//EXPORT_SYMBOL(comedi_from_phys); +EXPORT_SYMBOL(comedi_data_read); +EXPORT_SYMBOL(comedi_data_write); +//EXPORT_SYMBOL(comedi_sv_init); +//EXPORT_SYMBOL(comedi_sv_update); +//EXPORT_SYMBOL(comedi_sv_measure); +EXPORT_SYMBOL(comedi_dio_config); +EXPORT_SYMBOL(comedi_dio_read); +EXPORT_SYMBOL(comedi_dio_write); +EXPORT_SYMBOL(comedi_dio_bitfield); +//EXPORT_SYMBOL(comedi_get_timer); +//EXPORT_SYMBOL(comedi_timed_1chan); +//EXPORT_SYMBOL(comedi_set_global_oor_behavior); + + +#endif diff --git a/comedi/rt.c b/comedi/rt.c index a9fc05a2..eff38dc4 100644 --- a/comedi/rt.c +++ b/comedi/rt.c @@ -33,11 +33,43 @@ #include #include #include +#include #include +#ifdef CONFIG_COMEDI_RTAI +#include +#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_RTLINUX +#include + +#define RT_protect() rtl_make_rt_system_active() +#define RT_unprotect() rtl_make_rt_system_idle() +#define RT_spin_lock_irq(x) rt_spin_lock_irq(x) +#define RT_spin_unlock_irq(x) rt_spin_unlock_irq(x) +#endif + + +struct comedi_irq_struct { + int rt; + int irq; + void (*handler)(int irq,void *dev_id,struct pt_regs *regs); + unsigned long flags; + const char *device; + void *dev_id; +}; + +static int rt_get_irq(struct comedi_irq_struct *it); +static int rt_release_irq(struct comedi_irq_struct *it); + + +static struct comedi_irq_struct *comedi_irqs[NR_IRQS]; -static struct comedi_irq_struct *comedi_irqs; int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *), unsigned long flags,const char *device,void *dev_id) @@ -55,81 +87,70 @@ int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs * it->flags=flags; it->device=device; - ret=request_irq(irq,handler,flags&~SA_PRIORITY,device,dev_id); + ret=request_irq(irq,handler,flags,device,dev_id); if(ret<0){ kfree(it); return ret; } - if(flags&SA_PRIORITY){ - get_priority_irq(it); - } - - it->next=comedi_irqs; - comedi_irqs=it; + comedi_irqs[irq]=it; return 0; } -int comedi_change_irq_flags(unsigned int irq,void *dev_id,unsigned long flags) +void comedi_free_irq(unsigned int irq,void *dev_id) { struct comedi_irq_struct *it; - int ret; - it=get_irq_struct(irq); - if(it){ - if((it->flags&~SA_PRIORITY)!=(flags&~SA_PRIORITY)) - return -EINVAL; - - if((it->flags&SA_PRIORITY)==(flags&SA_PRIORITY)) - return 0; - - it->flags=flags; - if(flags&SA_PRIORITY){ - free_irq(it->irq,it->dev_id); - return get_priority_irq(it); - }else{ - ret=free_priority_irq(it); - request_irq(it->irq,it->handler,it->flags,it->device,it->dev_id); - return ret; - } + it=comedi_irqs[irq]; + if(!it)return; + + comedi_irqs[irq]=NULL; + + if(it->rt){ + printk("BUG! \n"); + rt_release_irq(it); } - return -EINVAL; + free_irq(it->irq,it->dev_id); + + kfree(it); } -void comedi_free_irq(unsigned int irq,void *dev_id) +void comedi_switch_to_rt(comedi_device *dev) { - struct comedi_irq_struct *it,*prev; - - prev=NULL; - for(it=comedi_irqs;it;it=it->next){ - if(it->irq==irq){ - break; - } - prev=it; - } - if(it->flags&SA_PRIORITY) - free_priority_irq(it); + struct comedi_irq_struct *it=comedi_irqs[dev->irq]; - free_irq(it->irq,it->dev_id); + spin_lock_irq(&dev->spinlock); + RT_protect(); + sti(); - if(prev) prev->next=it->next; - else comedi_irqs=it->next; + if(!dev->rt) + rt_get_irq(it); - kfree(it); + dev->rt++; + it->rt=1; + spin_unlock(&dev->spinlock); + RT_unprotect(); } -struct comedi_irq_struct *get_irq_struct(unsigned int irq) +void comedi_switch_to_non_rt(comedi_device *dev) +{ + struct comedi_irq_struct *it=comedi_irqs[dev->irq]; + + RT_spin_lock_irq(&dev->spinlock); + + dev->rt--; + if(!dev->rt) + rt_release_irq(it); + + it->rt=0; + RT_spin_unlock_irq(&dev->spinlock); +} + +void comedi_rt_pend_wakeup(wait_queue_head_t *q) { - struct comedi_irq_struct *it; - for(it=comedi_irqs;it;it=it->next){ - if(it->irq==irq){ - return it; - } - } - return NULL; } #ifdef HAVE_RT_PEND_TQ @@ -138,3 +159,115 @@ void wake_up_int_handler(int arg1, void * arg2) wake_up_interruptible((wait_queue_head_t*)arg2); } #endif + + +/* RTAI section */ +#ifdef CONFIG_COMEDI_RTAI + +#define DECLARE_VOID_IRQ(irq) \ +static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);} + +static inline void handle_void_irq(int irq) +{ + struct comedi_irq_struct *it=comedi_irqs[irq]; + it->handler(irq,it->dev_id,NULL); + rt_unmask_irq(irq); +} + +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_free_global_irq(it->irq); + return 0; +} + + +#endif + + +/* RTLinux section */ +#ifdef CONFIG_COMEDI_RTLINUX + +static unsigned int handle_rtl_irq(unsigned int irq,struct pt_regs *regs) +{ + struct comedi_irq_struct *it=comedi_irqs[irq]; + it->handler(irq,it->dev_id,regs); + rtl_hard_enable_irq(irq); +} + +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; +} + +#endif + + diff --git a/include/linux/comedidev.h b/include/linux/comedidev.h index 378af7b8..766fcde5 100644 --- a/include/linux/comedidev.h +++ b/include/linux/comedidev.h @@ -36,10 +36,6 @@ #include "kern_compat.h" -#ifdef CONFIG_COMEDI_RT -#include -#endif - #ifdef CONFIG_COMEDI_DEBUG #define DPRINTK(format, args...) printk("comedi: " format , ## args ) #else @@ -146,6 +142,8 @@ struct comedi_device_struct{ int board; void *board_ptr; int attached; + int rt; + spinlock_t spinlock; int n_subdevices; comedi_subdevice *subdevices; @@ -171,6 +169,7 @@ extern comedi_device *comedi_devices; * function prototypes */ +void comedi_event(comedi_device *dev,comedi_subdevice *s,unsigned int mask); void comedi_error(comedi_device *dev,const char *s); void comedi_done(comedi_device *dev,comedi_subdevice *s); void comedi_error_done(comedi_device *dev,comedi_subdevice *s); @@ -284,6 +283,10 @@ static inline int alloc_private(comedi_device *dev,int size) extern struct symbol_table comedi_syms; #endif +#ifdef CONFIG_COMEDI_RT +#include +#endif + #endif /* _COMEDI_MODULE_H */ -- 2.26.2