+++ /dev/null
-/*
- module/vd_dds.c
- virtual driver for direct digital signal synthesis
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov>
-
- 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 <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/timer.h>
-#include <asm/io.h>
-#include <linux/comedidev.h>
-#ifdef CONFIG_COMEDI_RTL_V1
-#include <rtl_sched.h>
-#endif
-#ifdef CONFIG_COMEDI_RTL
-#include <rtl.h>
-#include <rtl_sched.h>
-#include <rtl_compat.h>
-#endif
-#ifdef CONFIG_COMEDI_RTAI
-#include <rtai.h>
-#include <rtai_sched.h>
-#endif
-
-static int dds_attach(comedi_device *dev,comedi_devconfig *it);
-static int dds_detach(comedi_device *dev);
-comedi_driver driver_vd_dds={
- driver_name: "vd_dds",
- module: THIS_MODULE,
- attach: dds_attach,
- detach: dds_detach,
-};
-
-#ifdef CONFIG_COMEDI_RTL
-static void dds_interrupt(int irq,void *dev,struct pt_regs * regs);
-#endif
-
-typedef struct{
- int device;
- int subd;
- comedi_device *dev;
- comedi_subdevice *s;
- RT_TASK rt_task;
-
- unsigned int accumulator;
- unsigned int args[3];
-
- sampl_t data[2];
-
- comedi_trig trig;
- int soft_irq;
-}dds_private;
-#define devpriv ((dds_private *)dev->private)
-
-
-static comedi_device *broken_rtl_dev;
-
-#ifdef CONFIG_COMEDI_RTL
-static void dds_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);
-}
-#endif
-
-static inline void buf_add(comedi_device *dev,comedi_subdevice *s,sampl_t x)
-{
- *(sampl_t *)(((void *)(s->cur_trig.data))+s->async->buf_int_ptr)=x&0xfff;
- s->async->buf_int_ptr+=sizeof(sampl_t);
- if(s->async->buf_int_ptr>=s->cur_trig.data_len){
- s->async->buf_int_ptr=0;
- comedi_eobuf(dev,s);
- }
- s->async->buf_int_count+=sizeof(sampl_t);
-}
-
-
-static void dds_ao_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 ret;
-
- while(1){
- it->n_chan=1;
- it->data=devpriv->data;
- it->chanlist=my_trig->chanlist;
-
- devpriv->data[0]^=0x400;
-
- ret=comedi_trig_ioctl(devpriv->device,devpriv->subd,it);
-
- if(ret<0){
- /* eek! */
- }
-#ifdef CONFIG_COMEDI_RTL
- rt_task_wait();
-#endif
-#ifdef CONFIG_COMEDI_RTAI
- rt_task_wait_period();
-#endif
- }
-}
-
-static int dds_cntrl_mode0(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
-{
- int i,chan;
-
- for(i=0;i<it->n_chan;i++){
- chan=CR_CHAN(it->chanlist[i]);
-
- devpriv->args[chan]=it->data[i];
- }
- return i;
-}
-
-
-static int dds_ao_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
-
- devpriv->trig.subdev=devpriv->subd;
- devpriv->trig.mode=0;
- devpriv->trig.flags=TRIG_WRITE;
- devpriv->trig.n=1;
-
- ts.tv_sec=0;
- ts.tv_nsec=it->trigvar;
-
-#ifdef CONFIG_COMEDI_RTAI
- start_rt_timer(nano2count(it->trigvar));
-
- period=nano2count(it->trigvar);
- rt_task_init(&devpriv->rt_task,dds_ao_task_func,(int)dev,3000,4,0,0);
-
- now=rt_get_time();
- rt_task_make_periodic(&devpriv->rt_task,now+period,period);
-#endif
-#ifdef CONFIG_COMEDI_RTL
- period=timespec_to_RTIME(ts);
- rt_task_init(&devpriv->rt_task,dds_ao_task_func,(int)dev,3000,4);
-
- now=rt_get_time();
- rt_task_make_periodic(&devpriv->rt_task,now+period,period);
-#endif
-
- return 0;
-
-unlock:
- comedi_unlock_ioctl(devpriv->device,devpriv->subd);
-out:
- return ret;
-}
-
-int dds_ao_cancel(comedi_device *dev,comedi_subdevice *s)
-{
-#ifdef CONFIG_COMEDI_RTAI
- stop_rt_timer();
- rt_task_suspend(&devpriv->rt_task);
- rt_task_delete(&devpriv->rt_task);
-#endif
-#ifdef CONFIG_COMEDI_RTL
- rt_task_delete(&devpriv->rt_task);
-#endif
-
- comedi_unlock_ioctl(devpriv->device,devpriv->subd);
-
- return 0;
-}
-
-int dds_attach(comedi_device *dev,comedi_devconfig *it)
-{
- int ret;
- comedi_subdevice *s;
-
- printk("comedi%d: dds: ",dev->minor);
- dev->board_name="vd_dds";
-
- dev->n_subdevices=1;
- if((ret=alloc_subdevices(dev))<0)
- return ret;
- if((ret=alloc_private(dev,sizeof(dds_private)))<0)
- return ret;
-
- devpriv->device=it->options[0];
- devpriv->subd=it->options[1];
-
- devpriv->dev=comedi_get_device_by_minor(devpriv->device);
- if(!devpriv->dev || !devpriv->dev->attached){
- printk("target device doesn't exist\n");
- return 0;
- }
- if(devpriv->subd>=devpriv->dev->n_subdevices){
- printk("target subdevice doesn't exist\n");
- return 0;
- }
- devpriv->s=devpriv->dev->subdevices+devpriv->subd;
-
- s=dev->subdevices+0;
- dev->read_subdev=s;
- s->type=COMEDI_SUBD_AO;
- s->subdev_flags=SDF_READABLE;
- s->n_chan=devpriv->s->n_chan;
- s->len_chanlist=1024;
- s->trig[0]=dds_cntrl_mode0;
- s->trig[2]=dds_ao_mode2;
- s->cancel=dds_ao_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_RTAI
-#endif
-#ifdef CONFIG_COMEDI_RTL
- devpriv->soft_irq=rtl_get_soft_irq(dds_interrupt,"dds");
-#endif
- broken_rtl_dev=dev;
-
- printk("\n");
-
- return 1;
-}
-
-
-static int dds_detach(comedi_device *dev)
-{
- printk("comedi%d: dds: remove\n",dev->minor);
-
-#ifdef CONFIG_COMEDI_RTL
- free_irq(devpriv->soft_irq,NULL);
-#endif
-
- return 0;
-}
-
-
-#ifdef MODULE
-int init_module(void)
-{
- comedi_driver_register(&driver_vd_dds);
-
- return 0;
-}
-
-void cleanup_module(void)
-{
- comedi_driver_unregister(&driver_vd_dds);
-}
-#endif
-
+++ /dev/null
-/*
- module/vd_timer.c
- virtual driver for using RTL timing sources
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov>
-
- 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 <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/timer.h>
-#include <asm/io.h>
-#include <linux/comedidev.h>
-#ifdef CONFIG_COMEDI_RTL_V1
-#include <rtl_sched.h>
-#include <asm/rt_irq.h>
-#endif
-#ifdef CONFIG_COMEDI_RTL
-#include <rtl.h>
-#include <rtl_sched.h>
-#include <rtl_compat.h>
-#endif
-#ifdef CONFIG_COMEDI_RTAI
-#include <rtai.h>
-#include <rtai_sched.h>
-#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,
-};
-
-
-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;n<my_trig->n;n++){
- for(i=0;i<n_chan;i++){
- it->n_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;i<n_chan;i++){
- buf_add(dev,s,devpriv->data[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;
-}
-
-