*/
+//#define USE_CMD 1
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/comedidev.h>
#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={
}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)
{
}
}
-#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);
if(n_int < 10){
DPRINTK("new status 0x%02x\n",b);
n_int++;
- }
+ }*/
+ return;
}
#endif
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_arg<MAX_SPEED){
+ cmd->scan_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_arg<MAX_SPEED){
+ cmd->convert_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;
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;
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);