From: David Schleef Date: Tue, 15 Jan 2002 11:25:42 +0000 (+0000) Subject: Added preliminary command support. From Ildefond Magrans X-Git-Tag: r0_7_62~25 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=5ad13b14f69c21b70fc6b526076cf74868625f42;p=comedi.git Added preliminary command support. From Ildefond Magrans --- diff --git a/comedi/drivers/ni_pcidio.c b/comedi/drivers/ni_pcidio.c index 9d39ccbd..09d3f3eb 100644 --- a/comedi/drivers/ni_pcidio.c +++ b/comedi/drivers/ni_pcidio.c @@ -58,6 +58,8 @@ AT-MIO96. */ +//#define USE_CMD 1 + #include #include #include @@ -167,6 +169,8 @@ AT-MIO96. #define ClockSpeed Protocol_Register_14 #define DAQOptions Protocol_Register_15 +#define IntEn 3 + static int nidio_attach(comedi_device *dev,comedi_devconfig *it); static int nidio_detach(comedi_device *dev); comedi_driver driver_pcidio={ @@ -263,10 +267,12 @@ typedef struct{ }nidio96_private; #define devpriv ((nidio96_private *)dev->private) -static int nidio_find_device(comedi_device *dev,int bus,int slot); -#if 0 -static int setup_mite(comedi_device *dev); +#ifdef USE_CMD +static int ni_pcidio_cmdtest(comedi_device *dev,comedi_subdevice *s, + comedi_cmd *cmd); +static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s); #endif +static int nidio_find_device(comedi_device *dev,int bus,int slot); static int nidio96_8255_cb(int dir,int port,int data,unsigned long iobase) { @@ -278,15 +284,157 @@ static int nidio96_8255_cb(int dir,int port,int data,unsigned long iobase) } } -#ifdef not_working +#ifdef USE_CMD static void nidio_interrupt(int irq, void *d, struct pt_regs *regs) { comedi_device *dev=d; - //comedi_subdevice *s=dev->subdevices; + comedi_subdevice *s=dev->subdevices; int a,b; static int n_int=0; - //int i; + int i; struct timeval tv; + //int tag=0; + long int AuxData = 0; + sampl_t MyData1 = 0; + sampl_t MyData2 = 0; + comedi_async *async; + int Flags; + int Status; + int j; + + + //writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + + + async = s->async; + async->events = 0; + + //printk("%d ",async->buf_int_count); + + //writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + + Flags = readb(dev->iobase+Group_Flags); + + //IntEn es un parametre!!!! + + Status = readb(dev->iobase+Interrupt_And_Window_Status); + + //interrupcions parasites + if(dev->attached == 0) + { + comedi_error(dev,"premature interrupt"); + async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA; + } + + if((Flags & (TransferReady | CountExpired | Waited | PrimaryTC | SecondaryTC))==0) + { + comedi_error(dev,"spurious interrupt"); + async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA; + } + // printk("IntEn=%d,Flags=%d,Status=%d\n",IntEn,Flags,Status); + + while(Status&1) + { + //printk("1)IntEn=%d,Flags=%d,Status=%d\n",IntEn,Flags,Status); + //printk("hola11\n"); + + if(Flags & IntEn & CountExpired) + { + printk("count expired "); + writeb(CountExpired,dev->iobase+Group_First_Clear); + async->events |= COMEDI_CB_EOA; + async->events |= COMEDI_CB_BLOCK; + //for(i=0;i<16;i++) + //{ + AuxData = readl(dev->iobase+Group_FIFO); + MyData1 = AuxData & 0xffff; + MyData2 = (AuxData & 0xffff0000) >> 16; + comedi_buf_put(async,MyData1); + comedi_buf_put(async,MyData2); + //printk("lectura:%d, %d\n",MyData1,MyData2); + //} + + writeb(0x00,dev->iobase+OpMode); + writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + writeb(0xff,dev->iobase+Group_First_Clear); + writeb(0xff,dev->iobase+Group_First_Clear); + break; + } + + else if(Flags & IntEn & TransferReady) + { + //aixo no surt en el manual de NI + writeb(TransferReady,dev->iobase+Group_First_Clear); + //printk("transfer ready 1ยบ"); + //for(i=0;i<16;i++) + //{ + /*Flags = 0; + j=0; + while(!(Flags & TransferReady) && j<320) + { + Flags = readb(dev->iobase+Group_Flags); + //printk("Flags:%d ",Flags); + j++; + }*/ + AuxData = readl(dev->iobase+Group_FIFO); + MyData1 = AuxData & 0xffff; + MyData2 = (AuxData & 0xffff0000) >> 16; + comedi_buf_put(async,MyData1); + comedi_buf_put(async,MyData2); + //printk("lectura:%d, %d\n",MyData1,MyData2); + //Flags = readb(dev->iobase+Group_Flags); + //} + // Flags = readb(dev->iobase+Group_Flags); + // } + //printk("%d ",async->buf_int_count); + //printk("1)IntEn=%d,Flags=%d,Status=%d\n",IntEn,Flags,Status); + async->events |= COMEDI_CB_BLOCK; + } + + else if(Flags & IntEn & Waited) + { + printk("waited\n"); + writeb(Waited,dev->iobase+Group_First_Clear); + writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + } + + else if(Flags & IntEn & PrimaryTC) + { + printk("primaryTC\n"); + writeb(PrimaryTC,dev->iobase+Group_First_Clear); + async->events |= COMEDI_CB_EOA; + writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + } + + else if(Flags & IntEn & SecondaryTC) + { + printk("secondaryTC\n"); + writeb(SecondaryTC,dev->iobase+Group_First_Clear); + async->events |= COMEDI_CB_EOA; + writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + } + + /*else + { + printk("interrupcio desconeguda\n"); + async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA; + writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control); + }*/ + + Flags = readb(dev->iobase+Group_Flags); + Status = readb(dev->iobase+Interrupt_And_Window_Status); + //printk("2) IntEn=%d,Flags=%d,Status=%d\n",IntEn,Flags,Status); + } + + comedi_event(dev,s,async->events); + async->events = 0; + + //printk("hola2\n"); + + //if (!tag) + // writeb(0x03,dev->iobase+Master_DMA_And_Interrupt_Control); + + /* do_gettimeofday(&tv); a=readb(dev->iobase+Group_Status); @@ -306,7 +454,8 @@ static void nidio_interrupt(int irq, void *d, struct pt_regs *regs) if(n_int < 10){ DPRINTK("new status 0x%02x\n",b); n_int++; - } + }*/ + return; } #endif @@ -343,7 +492,198 @@ static int ni_pcidio_insn_bits(comedi_device *dev,comedi_subdevice *s, return 2; } -#ifdef not_working +#ifdef USE_CMD +static int ni_pcidio_cmdtest(comedi_device *dev,comedi_subdevice *s, + comedi_cmd *cmd) +{ + int err=0; + int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + tmp=cmd->start_src; + cmd->start_src &= TRIG_NOW; + if(!cmd->start_src || tmp!=cmd->start_src)err++; + + tmp=cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER|TRIG_EXT; + if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++; + + tmp=cmd->convert_src; + cmd->convert_src &= TRIG_TIMER|TRIG_EXT; + if(!cmd->convert_src || tmp!=cmd->convert_src)err++; + + tmp=cmd->scan_end_src; + cmd->scan_end_src &= TRIG_COUNT; + if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++; + + tmp=cmd->stop_src; + cmd->stop_src &= TRIG_COUNT|TRIG_NONE; + if(!cmd->stop_src || tmp!=cmd->stop_src)err++; + + if(err)return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if(cmd->scan_begin_src!=TRIG_TIMER && + cmd->scan_begin_src!=TRIG_EXT)err++; + if(cmd->convert_src!=TRIG_TIMER && + cmd->convert_src!=TRIG_EXT)err++; + if(cmd->stop_src!=TRIG_COUNT && + cmd->stop_src!=TRIG_NONE)err++; + + if(err)return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if(cmd->start_arg!=0){ + cmd->start_arg=0; + err++; + } + +#define MAX_SPEED 10000 /* in nanoseconds */ +#define MIN_SPEED 1000000000 /* in nanoseconds */ + + if(cmd->scan_begin_src==TRIG_TIMER){ + if(cmd->scan_begin_argscan_begin_arg=MAX_SPEED; + err++; + } + if(cmd->scan_begin_arg>MIN_SPEED){ + cmd->scan_begin_arg=MIN_SPEED; + err++; + } + }else{ + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + /* should specify multiple external triggers */ + if(cmd->scan_begin_arg>9){ + cmd->scan_begin_arg=9; + err++; + } + } + if(cmd->convert_src==TRIG_TIMER){ + if(cmd->convert_argconvert_arg=MAX_SPEED; + err++; + } + if(cmd->convert_arg>MIN_SPEED){ + cmd->convert_arg=MIN_SPEED; + err++; + } + }else{ + /* external trigger */ + /* see above */ + if(cmd->convert_arg>9){ + cmd->convert_arg=9; + err++; + } + } + + if(cmd->scan_end_arg!=cmd->chanlist_len){ + cmd->scan_end_arg=cmd->chanlist_len; + err++; + } + if(cmd->stop_src==TRIG_COUNT){ + if(cmd->stop_arg>0x00ffffff){ + cmd->stop_arg=0x00ffffff; + err++; + } + }else{ + /* TRIG_NONE */ + if(cmd->stop_arg!=0){ + cmd->stop_arg=0; + err++; + } + } + + if(err)return 3; + + /* step 4: fix up any arguments */ + + + if(err)return 4; + + return 0; +} + + +static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s) +{ + int i; + + writeb( 0 ,dev->iobase+OpMode); + + /*ho vui per entrada(els ports)*/ + writel(0x0000,dev->iobase+Port_Pin_Directions(0)); + + /* choose chan A,B (grup in,i 4 fifos sense funneling) */ + writeb(0x0F,dev->iobase+Data_Path); + + /* set transfer width a 32 bits*/ + writeb(0x00,dev->iobase+Transfer_Size_Control); + + + /* protocol configuration */ + writeb(0x00,dev->iobase+ClockReg); + writeb( 0 ,dev->iobase+Sequence); + writeb(0x00,dev->iobase+ReqReg); + writeb( 4 ,dev->iobase+BlockMode); + writeb( 0 ,dev->iobase+LinePolarities); + writeb(0x00,dev->iobase+AckSer); + writeb( 1 ,dev->iobase+StartDelay); + writeb( 1 ,dev->iobase+ReqDelay); + writeb( 1 ,dev->iobase+ReqNotDelay); + writeb( 1 ,dev->iobase+AckDelay); + writeb(0x0C,dev->iobase+AckNotDelay); + writeb(0x10,dev->iobase+Data1Delay); + writew( 0 ,dev->iobase+ClockSpeed); + writeb(0x60,dev->iobase+DAQOptions); + + /* ReadyLevel */ + /*writeb( 0 ,dev->iobase+FIFO_Control);*/ + + /*for(i=0;i<16;i++){ + writew(i,dev->iobase+Group_FIFO); + }*/ + //printk("arg:%d\n",s->async->cmd.stop_arg); + writel(s->async->cmd.stop_arg,dev->iobase+Transfer_Count); + +#define USEDMA 0 + if(USEDMA){ + writeb(0x05,dev->iobase+DMA_Line_Control); + writeb(0x30,dev->iobase+Group_First_Clear); + + mite_dma_prep(devpriv->mite,s); + }else{ + writeb(0x00,dev->iobase+DMA_Line_Control); + } + + /* clear and enable interrupts */ + writeb(0xff,dev->iobase+Group_First_Clear); + /* interrupcions degudas a FIFO ple, s'ha fet totes les transferencies + primaryTC=1??? secondaryTC=1???*/ + writeb(IntEn,dev->iobase+Interrupt_Enable); + writeb(0x03,dev->iobase+Master_DMA_And_Interrupt_Control); + + /* start */ + /*amb aixo ja s'esta dient numbered=1 + runmode=7*/ + writeb(0x0f,dev->iobase+OpMode); + + printk("\nhas configurat la tarja chaval\n"); + return 0; +} +#endif + +#ifdef unused static int nidio_dio_cmd(comedi_device *dev,comedi_subdevice *s) { int i; @@ -463,6 +803,7 @@ static int nidio_attach(comedi_device *dev,comedi_devconfig *it) s=dev->subdevices+0; + dev->read_subdev = s; s->type=COMEDI_SUBD_DIO; s->subdev_flags=SDF_READABLE|SDF_WRITEABLE|SDF_RT; s->n_chan=32; @@ -470,13 +811,17 @@ static int nidio_attach(comedi_device *dev,comedi_devconfig *it) s->maxdata=1; s->insn_config = ni_pcidio_insn_config; s->insn_bits = ni_pcidio_insn_bits; +#ifdef USE_CMD + s->do_cmd = ni_pcidio_cmd; + s->do_cmdtest = ni_pcidio_cmdtest; +#endif s->len_chanlist=32; /* XXX */ writel(0,dev->iobase+Port_IO(0)); writel(0,dev->iobase+Port_Pin_Directions(0)); writel(0,dev->iobase+Port_Pin_Mask(0)); -#ifdef not_working +#ifdef USE_CMD /* disable interrupts on board */ writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);