From 3a39c9a4c6f08dd153419206ac0ef0a1a300b10a Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 21 Mar 2001 23:59:46 +0000 Subject: [PATCH] Moved real-time timer code from comedi/realtime/vd_timer.c --- comedi/drivers/Makefile | 2 + comedi/drivers/comedi_rt_timer.c | 324 +++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 comedi/drivers/comedi_rt_timer.c diff --git a/comedi/drivers/Makefile b/comedi/drivers/Makefile index 010c5a6e..d6b1e48a 100644 --- a/comedi/drivers/Makefile +++ b/comedi/drivers/Makefile @@ -75,6 +75,8 @@ obj-$(CONFIG_COMEDI_RTI802) += rti802.o obj-$(CONFIG_COMEDI_SKEL) += skel.o +obj-$(CONFIG_COMEDI_RT_TIMER) += comedi_rt_timer.o + #obj-m += $(obj-y) O_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) diff --git a/comedi/drivers/comedi_rt_timer.c b/comedi/drivers/comedi_rt_timer.c new file mode 100644 index 00000000..a041ed03 --- /dev/null +++ b/comedi/drivers/comedi_rt_timer.c @@ -0,0 +1,324 @@ +/* + module/vd_timer.c + virtual driver for using RTL timing sources + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999,2001 David A. Schleef + + 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. + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_COMEDI_RTL_V1 +#include +#include +#endif +#ifdef CONFIG_COMEDI_RTL +#include +#include +#include +#endif +#ifdef CONFIG_COMEDI_RTAI +#include +#include +#endif + +static int timer_attach(comedi_device *dev,comedi_devconfig *it); +static int timer_detach(comedi_device *dev); +comedi_driver driver_timer={ + driver_name: "timer", + attach: timer_attach, + detach: timer_detach, +}; +COMEDI_INITCLEANUP(driver_timer); + + +static void timer_interrupt(int irq,void *dev,struct pt_regs * regs); + +typedef struct{ + int device; + int subd; + comedi_device *dev; + comedi_subdevice *s; + RT_TASK rt_task; + sampl_t *data; + comedi_trig trig; + int soft_irq; +}timer_private; +#define devpriv ((timer_private *)dev->private) + + +static comedi_device *broken_rtl_dev; + +static void timer_interrupt(int irq,void *d,struct pt_regs * regs) +{ + comedi_device *dev=broken_rtl_dev; + + comedi_done(dev,dev->subdevices+0); + + comedi_unlock_ioctl(devpriv->device,devpriv->subd); +} + +static inline void buf_add(comedi_device *dev,comedi_subdevice *s,sampl_t x) +{ + *(sampl_t *)(((void *)(s->cur_trig.data))+s->buf_int_ptr)=x&0xfff; + s->buf_int_ptr+=sizeof(sampl_t); + if(s->buf_int_ptr>=s->cur_trig.data_len){ + s->buf_int_ptr=0; + comedi_eobuf(dev,s); + } + s->buf_int_count+=sizeof(sampl_t); +} + + +static void timer_ai_task_func(int d) +{ + comedi_device *dev=(comedi_device *)d; + comedi_subdevice *s=dev->subdevices+0; + comedi_trig *it=&devpriv->trig; + comedi_trig *my_trig=&s->cur_trig; + int i,n,ret; + int n_chan; + + n_chan=s->cur_trig.n_chan; + + for(n=0;nn;n++){ + for(i=0;in_chan=1; + it->data=devpriv->data+i; + it->chanlist=my_trig->chanlist+i; + + ret=comedi_trig_ioctl(devpriv->device,devpriv->subd,it); + + if(ret<0){ + /* eek! */ + } + } + for(i=0;idata[i]); + } +#ifdef CONFIG_COMEDI_RTL + rt_task_wait(); +#endif +#ifdef CONFIG_COMEDI_RTAI + //rt_task_wait(); +#endif + } +#ifdef CONFIG_COMEDI_RTL + rtl_global_pend_irq(devpriv->soft_irq); +#endif +#ifdef CONFIG_COMEDI_RTAI + //rtl_global_pend_irq(devpriv->soft_irq); +#endif + + rt_task_delete(&devpriv->rt_task); + + /* eek! */ +} + +static int timer_ai_mode0(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) +{ + return comedi_trig_ioctl(devpriv->device,devpriv->subd,it); +} + +static int timer_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) +{ + if(cmd->scan_begin_arg<100000) /* 10 khz */ + cmd->scan_begin_arg=100000; + if(cmd->scan_begin_arg>1e9) /* 1 hz */ + cmd->scan_begin_arg=1e9; + + return 0; +} + +static int timer_cmd(comedi_device *dev,comedi_subdevice *s) +{ + int ret; + RTIME now,period; + struct timespec ts; + comedi_cmd *cmd = &s->cmd; + + ret=comedi_lock_ioctl(devpriv->device,devpriv->subd); + if(ret<0)return ret; + + /* XXX this does not get freed */ + devpriv->data=kmalloc(sizeof(sampl_t)*cmd->chanlist_len,GFP_KERNEL); + if(!devpriv->data){ + ret=-ENOMEM; + goto unlock; + } + + devpriv->trig.subdev=devpriv->subd; + devpriv->trig.mode=0; + devpriv->trig.flags=0; + devpriv->trig.n=1; + + ts.tv_sec=0; + ts.tv_nsec=cmd->scan_begin_arg; + +#ifdef CONFIG_COMEDI_RTL + period=timespec_to_RTIME(ts); + rt_task_init(&devpriv->rt_task,timer_ai_task_func,(int)dev,3000,4); +#endif +#ifdef CONFIG_COMEDI_RTAI + period = 0; + //period=timespec_to_RTIME(ts); + //rt_task_init(&devpriv->rt_task,timer_ai_task_func,(int)dev,3000,4); +#endif + + now=rt_get_time(); + rt_task_make_periodic(&devpriv->rt_task,now+period,period); + + return 0; + +unlock: + comedi_unlock_ioctl(devpriv->device,devpriv->subd); + return ret; +} + +static int timer_ai_mode2(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) +{ + int ret; + RTIME now,period; + struct timespec ts; + + //if(it->trigvar1!=0)return -EINVAL; + if(it->trigvar<100000)return -EINVAL; /* 10 khz */ + + ret=comedi_lock_ioctl(devpriv->device,devpriv->subd); + if(ret<0)goto out; + +#if 0 + struct timespec ts; + + ts.tv_sec=0; + ts.tv_nsec=it->trigvar; +#endif + + /* XXX this does not get freed */ + devpriv->data=kmalloc(sizeof(sampl_t)*it->n_chan,GFP_KERNEL); + if(!devpriv->data){ + ret=-ENOMEM; + goto unlock; + } + + devpriv->trig.subdev=devpriv->subd; + devpriv->trig.mode=0; + devpriv->trig.flags=0; + devpriv->trig.n=1; + + ts.tv_sec=0; + ts.tv_nsec=it->trigvar; +#ifdef CONFIG_COMEDI_RTL + period=timespec_to_RTIME(ts); + rt_task_init(&devpriv->rt_task,timer_ai_task_func,(int)dev,3000,4); +#endif +#ifdef CONFIG_COMEDI_RTAI + period = 0; + //period=timespec_to_RTIME(ts); + //rt_task_init(&devpriv->rt_task,timer_ai_task_func,(int)dev,3000,4); +#endif + + now=rt_get_time(); + rt_task_make_periodic(&devpriv->rt_task,now+period,period); + + return 0; + +unlock: + comedi_unlock_ioctl(devpriv->device,devpriv->subd); +out: + return ret; +} + +int timer_cancel(comedi_device *dev,comedi_subdevice *s) +{ + rt_task_delete(&devpriv->rt_task); + + comedi_unlock_ioctl(devpriv->device,devpriv->subd); + + return 0; +} + +static int timer_attach(comedi_device *dev,comedi_devconfig *it) +{ + int ret; + comedi_subdevice *s; + + printk("comedi%d: timer: ",dev->minor); + dev->board_name="timer"; + + dev->n_subdevices=1; + if((ret=alloc_subdevices(dev))<0) + return ret; + if((ret=alloc_private(dev,sizeof(timer_private)))<0) + return ret; + + devpriv->device=it->options[0]; + devpriv->subd=it->options[1]; + + devpriv->dev=comedi_get_device_by_minor(devpriv->device); + devpriv->s=devpriv->dev->subdevices+devpriv->subd; + + s=dev->subdevices+0; + s->type=COMEDI_SUBD_AI; + s->subdev_flags=SDF_READABLE; + s->n_chan=devpriv->s->n_chan; + s->len_chanlist=1024; + s->trig[0]=timer_ai_mode0; + s->trig[2]=timer_ai_mode2; + s->do_cmd=timer_cmd; + s->do_cmdtest=timer_cmdtest; + s->cancel=timer_cancel; + s->maxdata=devpriv->s->maxdata; + s->range_table=devpriv->s->range_table; + s->range_table_list=devpriv->s->range_table_list; + +#ifdef CONFIG_COMEDI_RTL + devpriv->soft_irq=rtl_get_soft_irq(timer_interrupt,"timer"); + broken_rtl_dev=dev; +#endif +#ifdef CONFIG_COMEDI_RTAI + //devpriv->soft_irq=rtl_get_soft_irq(timer_interrupt,"timer"); +#endif + + printk("\n"); + + return 1; +} + + +static int timer_detach(comedi_device *dev) +{ + printk("comedi%d: timer: remove\n",dev->minor); + + free_irq(devpriv->soft_irq,NULL); + + return 0; +} + + -- 2.26.2