Ported ni_mio_common.c to use ni_tio.c for NI general-purpose counter
authorFrank Mori Hess <fmhess@speakeasy.net>
Fri, 5 Jan 2007 20:38:31 +0000 (20:38 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Fri, 5 Jan 2007 20:38:31 +0000 (20:38 +0000)
support.  Have tested only counter in continuous pulse generation mode so
far (see comedilib/demo/gpct_pulse_generator.c which I will soon commit
to comedilib cvs).

comedi/drivers/ni_atmio.c
comedi/drivers/ni_mio_common.c
comedi/drivers/ni_mio_cs.c
comedi/drivers/ni_pcimio.c
comedi/drivers/ni_stc.h

index 55f84148804c28dab2a10910bff82935a3bbc999..f0a1efe2161514f0d520e809f20eae4b653ab868 100644 (file)
@@ -358,7 +358,7 @@ static int ni_isapnp_find_board( struct pnp_dev **dev )
 {
        struct pnp_dev *isapnp_dev = NULL;
        int i;
-       
+
        for( i = 0; i < n_ni_boards; i++ )
        {
                isapnp_dev = pnp_find_dev(NULL,
@@ -405,6 +405,7 @@ static int ni_atmio_attach(comedi_device *dev,comedi_devconfig *it)
        devpriv->stc_writew = &ni_atmio_win_out;
        devpriv->stc_readw = &ni_atmio_win_in;
        devpriv->stc_writel = &win_out2;
+       devpriv->stc_readl = &win_in2;
 
        iobase=it->options[0];
        irq=it->options[1];
index ca049e87d9711640104fdd2a842385ce481f7967..8072c71ea47ee953023114815596741d6f5f384c 100644 (file)
@@ -262,20 +262,6 @@ static int ni_8255_callback(int dir,int port,int data,unsigned long arg);
 
 static int ni_ns_to_timer(comedi_device *dev, int *nanosec, int round_mode);
 
-
-/*GPCT function def's*/
-static int GPCT_G_Watch(comedi_device *dev, int chan);
-
-static void GPCT_Reset(comedi_device *dev, int chan);
-static void GPCT_Gen_Cont_Pulse(comedi_device *dev, int chan, unsigned int length);
-static void GPCT_Gen_Single_Pulse(comedi_device *dev, int chan, unsigned int length);
-static void GPCT_Period_Meas(comedi_device *dev, int chan);
-static void GPCT_Pulse_Width_Meas(comedi_device *dev, int chan);
-static void GPCT_Event_Counting(comedi_device *dev,int chan);
-static int GPCT_Set_Direction(comedi_device *dev,int chan,int direction);
-static int GPCT_Set_Gate(comedi_device *dev,int chan ,int gate);
-static int GPCT_Set_Source(comedi_device *dev,int chan ,int source);
-
 static int ni_gpct_insn_write(comedi_device *dev,comedi_subdevice *s,
        comedi_insn *insn,lsampl_t *data);
 static int ni_gpct_insn_read(comedi_device *dev,comedi_subdevice *s,
@@ -331,8 +317,7 @@ static void ni_flush_ai_fifo(comedi_device *dev){
                ni_writel(0x10, AIFIFO_Control_6143);           // Flush fifo
                ni_writel(0x00, AIFIFO_Control_6143);           // Flush fifo
                while(ni_readl(AIFIFO_Status_6143) & 0x10);     // Wait for complete
-       }
-       else {
+       }else {
                devpriv->stc_writew(dev, 1,ADC_FIFO_Clear);
                if(boardtype.reg_type == ni_reg_625x)
                {
@@ -351,6 +336,14 @@ static void win_out2(comedi_device *dev, uint32_t data, int reg)
        devpriv->stc_writew(dev, data & 0xffff, reg + 1);
 }
 
+static uint32_t win_in2(comedi_device *dev, int reg)
+{
+       uint32_t bits;
+       bits = devpriv->stc_readw(dev, reg) << 16;
+       bits |= devpriv->stc_readw(dev, reg + 1);
+       return bits;
+}
+
 #define ao_win_out(data,addr) ni_ao_win_outw(dev,data,addr)
 static inline void ni_ao_win_outw( comedi_device *dev, uint16_t data, int addr )
 {
@@ -3124,6 +3117,129 @@ static void init_ao_67xx(comedi_device *dev, comedi_subdevice *s)
                ni_ao_win_outw(dev, AO_Channel(i) | 0x0, AO_Configuration_2_67xx);
 }
 
+unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg)
+{
+       unsigned stc_register;
+       switch(reg)
+       {
+       case NITIO_G0_Autoincrement_Reg:
+               stc_register = G_Autoincrement_Register(0);
+               break;
+       case NITIO_G1_Autoincrement_Reg:
+               stc_register = G_Autoincrement_Register(1);
+               break;
+       case NITIO_G0_Command_Reg:
+               stc_register = G_Command_Register(0);
+               break;
+       case NITIO_G1_Command_Reg:
+               stc_register = G_Command_Register(1);
+               break;
+       case NITIO_G0_Mode_Reg:
+               stc_register = G_Mode_Register(0);
+               break;
+       case NITIO_G1_Mode_Reg:
+               stc_register = G_Mode_Register(1);
+               break;
+       case NITIO_G0_LoadA_Reg:
+               stc_register = G_Load_A_Register(0);
+               break;
+       case NITIO_G1_LoadA_Reg:
+               stc_register = G_Load_A_Register(1);
+               break;
+       case NITIO_G0_LoadB_Reg:
+               stc_register = G_Load_B_Register(0);
+               break;
+       case NITIO_G1_LoadB_Reg:
+               stc_register = G_Load_B_Register(1);
+               break;
+       case NITIO_G0_Input_Select_Reg:
+               stc_register = G_Input_Select_Register(0);
+               break;
+       case NITIO_G1_Input_Select_Reg:
+               stc_register = G_Input_Select_Register(1);
+               break;
+       case NITIO_G01_Status_Reg:
+               stc_register = G_Status_Register;
+               break;
+       case NITIO_G01_Joint_Reset_Reg:
+               stc_register = Joint_Reset_Register;
+               break;
+       case NITIO_G01_Joint_Status1_Reg:
+               stc_register = Joint_Status_1_Register;
+               break;
+       case NITIO_G01_Joint_Status2_Reg:
+               stc_register = Joint_Status_2_Register;
+               break;
+       default:
+               BUG();
+               return 0;
+               break;
+       }
+       return stc_register;
+}
+
+static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum ni_gpct_register reg)
+{
+       comedi_device *dev = counter->dev;
+       unsigned stc_register;
+       /* bits in the join reset register which are relevant to counters */
+       static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset;
+       switch(reg)
+       {
+       /* m-series-only registers */
+       case NITIO_G0_Counting_Mode_Reg:
+               ni_writew(bits, M_Offset_G0_Counting_Mode);
+               break;
+       case NITIO_G1_Counting_Mode_Reg:
+               ni_writew(bits, M_Offset_G1_Counting_Mode);
+               break;
+       case NITIO_G0_Second_Gate_Reg:
+               ni_writew(bits, M_Offset_G0_Second_Gate);
+               break;
+       case NITIO_G1_Second_Gate_Reg:
+               ni_writew(bits, M_Offset_G1_Second_Gate);
+               break;
+       /* 32 bit registers */
+       case NITIO_G0_LoadA_Reg:
+       case NITIO_G1_LoadA_Reg:
+       case NITIO_G0_LoadB_Reg:
+       case NITIO_G1_LoadB_Reg:
+               stc_register = ni_gpct_to_stc_register(reg);
+               devpriv->stc_writel(dev, bits, stc_register);
+               break;
+       /* 16 bit registers */
+       case NITIO_G01_Joint_Reset_Reg:
+               BUG_ON(bits & ~gpct_joint_reset_mask);
+               /* fall-through */
+       default:
+               stc_register = ni_gpct_to_stc_register(reg);
+               devpriv->stc_writew(dev, bits, stc_register);
+       }
+}
+
+static unsigned ni_gpct_read_register(struct ni_gpct *counter, enum ni_gpct_register reg)
+{
+       comedi_device *dev = counter->dev;
+       unsigned stc_register;
+       switch(reg)
+       {
+       /* 32 bit registers */
+       case NITIO_G0_HW_Save_Reg:
+       case NITIO_G1_HW_Save_Reg:
+       case NITIO_G0_SW_Save_Reg:
+       case NITIO_G1_SW_Save_Reg:
+               stc_register = ni_gpct_to_stc_register(reg);
+               return devpriv->stc_readl(dev, stc_register);
+               break;
+       /* 16 bit registers */
+       default:
+               stc_register = ni_gpct_to_stc_register(reg);
+               return devpriv->stc_readw(dev, stc_register);
+               break;
+       }
+       return 0;
+}
+
 static int ni_alloc_private(comedi_device *dev)
 {
        int ret;
@@ -3140,6 +3256,7 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
 {
        comedi_subdevice *s;
        int bits;
+       unsigned j;
 
        if(boardtype.n_aochan > MAX_N_AO_CHAN)
        {
@@ -3147,7 +3264,7 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
                return -EINVAL;
        }
 
-       if(alloc_subdevices(dev, 11) < 0)
+       if(alloc_subdevices(dev, 11 + NUM_GPCT) < 0)
                return -ENOMEM;
 
        /* analog input subdevice */
@@ -3246,23 +3363,9 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
                s->type=COMEDI_SUBD_UNUSED;
        }
 
-       /* general purpose counter/timer device */
+       /* formerly general purpose counter/timer device, but no longer used */
        s=dev->subdevices+4;
-       s->type = COMEDI_SUBD_COUNTER;
-       s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_CMD_READ;
-       s->insn_read = ni_gpct_insn_read;
-       s->insn_write = ni_gpct_insn_write;
-       s->insn_config = ni_gpct_insn_config;
-       s->n_chan=2;
-       s->maxdata=1;
-       s->do_cmdtest = ni_gpct_cmdtest;
-       s->do_cmd = ni_gpct_cmd;
-       s->cancel = ni_gpct_cancel;
-//     s->poll=ni_gpct_poll;
-//     s->munge=ni_gpct_munge;
-       devpriv->an_trig_etc_reg = 0;
-       GPCT_Reset(dev,0);
-       GPCT_Reset(dev,1);
+       s->type = COMEDI_SUBD_UNUSED;
 
        /* calibration subdevice -- ai and ao */
        s=dev->subdevices+5;
@@ -3364,6 +3467,38 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
        s->insn_config = ni_rtsi_insn_config;
        ni_rtsi_init(dev);
 
+       /* General purpose counters */
+       for(j = 0; j < NUM_GPCT; ++j)
+       {
+               s = dev->subdevices + 11 + j;
+               s->type = COMEDI_SUBD_COUNTER;
+               s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+               s->n_chan = 3;
+               if(boardtype.reg_type & ni_reg_m_series_mask)
+                       s->maxdata = 0xffffffff;
+               else
+                       s->maxdata = 0xffffff;
+               s->insn_read = ni_gpct_insn_read;
+               s->insn_write = ni_gpct_insn_write;
+               s->insn_config = ni_gpct_insn_config;
+               s->private = &devpriv->counters[j];
+
+               devpriv->counters[j].dev = dev;
+               devpriv->counters[j].chip_index = 0;
+               devpriv->counters[j].counter_index = j;
+               devpriv->counters[j].write_register = ni_gpct_write_register;
+               devpriv->counters[j].read_register = ni_gpct_read_register;
+               if(boardtype.reg_type & ni_reg_m_series_mask)
+               {
+                       devpriv->counters[j].variant = ni_gpct_variant_m_series;
+               }else
+               {
+                       devpriv->counters[j].variant = ni_gpct_variant_e_series;
+               }
+               devpriv->counters[j].clock_period_ps = 0;
+               ni_tio_init_counter(&devpriv->counters[j]);
+       }
+
        /* ai configuration */
        ni_ai_reset(dev,dev->subdevices+0);
        if((boardtype.reg_type & ni_reg_6xxx_mask) == 0){
@@ -3790,42 +3925,7 @@ static int pack_ad8842(int addr,int val,int *bitstring)
 }
 
 
-
-
-
-/*
- *
- *  General Purpose Counter/Timer section
- *
- */
-
-/*
- * Low level stuff...Each STC counter has two 24 bit load registers
- * (A&B).  Just make it easier to access them.
- *
- */
-static inline void GPCT_Load_A(comedi_device *dev, int chan, unsigned int value)
-{
-       devpriv->stc_writel(dev,  value & 0x00ffffff, G_Load_A_Register(chan));
-}
-
-static inline void GPCT_Load_B(comedi_device *dev, int chan, unsigned int value)
-{
-       devpriv->stc_writel(dev,  value & 0x00ffffff, G_Load_B_Register(chan));
-}
-
-/*  Load a value into the counter, using register A as the intermediate step.
-*  You might use GPCT_Load_Using_A to load a 0x000000 into a counter
-*  reset its value.
-*/
-static void GPCT_Load_Using_A(comedi_device *dev, int chan, unsigned int value)
-{
-       devpriv->gpct_mode[chan] &= (~G_Load_Source_Select);
-       devpriv->stc_writew(dev,  devpriv->gpct_mode[chan],G_Mode_Register(chan));
-       GPCT_Load_A(dev,chan,value);
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan]|G_Load,G_Command_Register(chan));
-}
-
+#if 0
 /*
  *     Read the GPCTs current value.
  */
@@ -3850,342 +3950,6 @@ static int GPCT_G_Watch(comedi_device *dev, int chan)
        return (hi1<<16)|lo;
 }
 
-
-static int GPCT_Disarm(comedi_device *dev, int chan)
-{
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan] | G_Disarm,G_Command_Register(chan));
-       return 0;
-}
-
-
-static int GPCT_Arm(comedi_device *dev, int chan)
-{
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan] | G_Arm,G_Command_Register(chan));
-       /* If the counter is doing pulse width measurement, then make
-        sure that the counter did not start counting right away.  This would
-        indicate that we started acquiring the pulse after it had already
-        started and our measurement would be inaccurate */
-       if(devpriv->gpct_cur_operation[chan] == GPCT_SINGLE_PW){
-               int g_status;
-
-               g_status=devpriv->stc_readw(dev, G_Status_Register);
-
-               if(chan == 0){
-                       //TIM 5/2/01 possible error with very short pulses
-                       if((G0_Counting_St & g_status)|| !(G0_Armed_St&g_status)) {
-                               //error: we missed the beginning of the pulse
-                               return -EINVAL; //there is probably a more accurate error code...
-                       }
-               }else{
-                       if((G1_Counting_St & g_status)|| !(G1_Armed_St&g_status)) {
-                               //error: we missed the beginning of the pulse
-                               return -EINVAL;
-                       }
-               }
-       }
-       return 0;
-}
-
-static int GPCT_Set_Source(comedi_device *dev,int chan ,int source)
-{
-       //printk("GPCT_Set_Source...");
-       devpriv->gpct_input_select[chan] &= ~G_Source_Select(0x1f);//reset gate to 0
-       switch(source) {
-               case GPCT_INT_CLOCK:
-               devpriv->gpct_input_select[chan] |= G_Source_Select(0);//INT_TIMEBASE
-               break;
-       case GPCT_EXT_PIN:
-               if(chan==0)
-                       devpriv->gpct_input_select[chan] |= G_Source_Select(9);//PFI8
-               else
-                       devpriv->gpct_input_select[chan] |= G_Source_Select(4);//PFI3
-               break;
-       default:
-               return -EINVAL;
-       }
-       devpriv->stc_writew(dev, devpriv->gpct_input_select[chan], G_Input_Select_Register(chan));
-       //printk("exit GPCT_Set_Source\n");
-       return 0;
-}
-
-static int GPCT_Set_Gate(comedi_device *dev,int chan ,int gate)
-{
-       //printk("GPCT_Set_Gate...");
-       devpriv->gpct_input_select[chan] &= ~G_Gate_Select(0x1f);//reset gate to 0
-       switch(gate) {
-       case GPCT_NO_GATE:
-               devpriv->gpct_input_select[chan] |= G_Gate_Select(31);//Low
-               devpriv->gpct_mode[chan] |= G_Gate_Polarity;
-               break;
-       case GPCT_EXT_PIN:
-               devpriv->gpct_mode[chan] &= ~G_Gate_Polarity;
-               if(chan==0){
-                       devpriv->gpct_input_select[chan] |= G_Gate_Select(10);//PFI9
-               }else{
-                       devpriv->gpct_input_select[chan] |= G_Gate_Select(5);//PFI4
-               }
-               break;
-       default:
-               return -EINVAL;
-       }
-       devpriv->stc_writew(dev, devpriv->gpct_input_select[chan], G_Input_Select_Register(chan));
-       devpriv->stc_writew(dev, devpriv->gpct_mode[chan], G_Mode_Register(chan));
-       //printk("exit GPCT_Set_Gate\n");
-       return 0;
-}
-
-static int GPCT_Set_Direction(comedi_device *dev,int chan,int direction)
-{
-       //printk("GPCT_Set_Direction...");
-
-       devpriv->gpct_command[chan] &= ~G_Up_Down(0x3);
-       switch (direction) {
-               case GPCT_UP:
-                       devpriv->gpct_command[chan] |= G_Up_Down(1);
-                       break;
-               case GPCT_DOWN:
-                       devpriv->gpct_command[chan] |= G_Up_Down(0);
-                       break;
-               case GPCT_HWUD:
-                       devpriv->gpct_command[chan] |= G_Up_Down(2);
-                       break;
-               default:
-                       rt_printk("Error direction=0x%08x..",direction);
-                       return -EINVAL;
-       }
-       devpriv->stc_writew(dev, devpriv->gpct_command[chan], G_Command_Register(chan));
-       //TIM 4/23/01 devpriv->stc_writew(dev, devpriv->gpct_mode[chan], G_Mode_Register(chan));
-       //printk("exit GPCT_Set_Direction\n");
-       return 0;
-}
-
-static void GPCT_Event_Counting(comedi_device *dev,int chan)
-{
-
-       //NOTE: possible residual bits from multibit masks can corrupt
-       //If you config for several measurements between Resets, watch out!
-
-       //printk("GPCT_Event_Counting...");
-
-       devpriv->gpct_cur_operation[chan] = GPCT_SIMPLE_EVENT;
-
-       // Gating_Mode = 1
-       devpriv->gpct_mode[chan] &= ~(G_Gating_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Gating_Mode(1);
-
-       // Trigger_Mode_For_Edge_Gate = 1
-       devpriv->gpct_mode[chan] &= ~(G_Trigger_Mode_For_Edge_Gate(0x3));
-       devpriv->gpct_mode[chan] |= G_Trigger_Mode_For_Edge_Gate(2);
-
-       devpriv->stc_writew(dev,  devpriv->gpct_mode[chan],G_Mode_Register(chan));
-       //printk("exit GPCT_Event_Counting\n");
-}
-
-static void GPCT_Period_Meas(comedi_device *dev, int chan)
-{
-       //printk("GPCT_Period_Meas...");
-
-       devpriv->gpct_cur_operation[chan] = GPCT_SINGLE_PERIOD;
-
-
-       //NOTE: possible residual bits from multibit masks can corrupt
-       //If you config for several measurements between Resets, watch out!
-       devpriv->gpct_mode[chan] &= ~G_OR_Gate;
-       devpriv->gpct_mode[chan] &= ~G_Gate_Select_Load_Source;
-
-       // Output_Mode = 3
-       devpriv->gpct_mode[chan] &= ~(G_Output_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Output_Mode(3);
-
-
-       //Gating Mode=2
-       devpriv->gpct_mode[chan] &= ~(G_Gating_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Gating_Mode(2);
-
-       // Trigger_Mode_For_Edge_Gate=0
-       devpriv->gpct_mode[chan] &= ~(G_Trigger_Mode_For_Edge_Gate(0x3));
-       devpriv->gpct_mode[chan] |= G_Trigger_Mode_For_Edge_Gate(0);
-
-       devpriv->gpct_mode[chan] |= G_Reload_Source_Switching;
-       devpriv->gpct_mode[chan] &= ~G_Loading_On_Gate;
-       devpriv->gpct_mode[chan] &= ~G_Loading_On_TC;
-       devpriv->gpct_mode[chan] &= ~G_Gate_On_Both_Edges;
-
-       // Stop_Mode = 2
-       devpriv->gpct_mode[chan] &= ~(G_Stop_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Stop_Mode(0);
-
-       // Counting_Once = 2
-       devpriv->gpct_mode[chan] &= ~(G_Counting_Once(0x3));
-       devpriv->gpct_mode[chan] |= G_Counting_Once(2);
-
-       // Up_Down = 1
-       devpriv->gpct_command[chan] &= ~(G_Up_Down(0x3));
-       devpriv->gpct_command[chan] |= G_Up_Down(1);
-
-       devpriv->stc_writew(dev,  devpriv->gpct_mode[chan],G_Mode_Register(chan));
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan],G_Command_Register(chan));
-       //printk("exit GPCT_Period_Meas\n");
-}
-
-static void GPCT_Pulse_Width_Meas(comedi_device *dev, int chan)
-{
-       //printk("GPCT_Pulse_Width_Meas...");
-
-       devpriv->gpct_cur_operation[chan] = GPCT_SINGLE_PW;
-
-       devpriv->gpct_mode[chan] &= ~G_OR_Gate;
-       devpriv->gpct_mode[chan] &= ~G_Gate_Select_Load_Source;
-
-       // Output_Mode = 3
-       devpriv->gpct_mode[chan] &= ~(G_Output_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Output_Mode(3);
-
-       //Gating Mode=1
-       devpriv->gpct_mode[chan] &= ~(G_Gating_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Gating_Mode(1);//TIM 4/24/01 was 2
-
-       // Trigger_Mode_For_Edge_Gate=2
-       devpriv->gpct_mode[chan] &= ~(G_Trigger_Mode_For_Edge_Gate(0x3));
-       devpriv->gpct_mode[chan] |= G_Trigger_Mode_For_Edge_Gate(2);//TIM 4/24/01 was 0
-
-
-       devpriv->gpct_mode[chan] |= G_Reload_Source_Switching;//TIM 4/24/01 was 1
-       devpriv->gpct_mode[chan] &= ~G_Loading_On_Gate;//TIM 4/24/01 was 0
-
-       devpriv->gpct_mode[chan] &= ~G_Loading_On_TC;
-       devpriv->gpct_mode[chan] &= ~G_Gate_On_Both_Edges;
-
-       // Stop_Mode = 0
-       devpriv->gpct_mode[chan] &= ~(G_Stop_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Stop_Mode(0);
-
-       // Counting_Once = 2
-       devpriv->gpct_mode[chan] &= ~(G_Counting_Once(0x3));
-       devpriv->gpct_mode[chan] |= G_Counting_Once(2);
-
-       // Up_Down = 1
-       devpriv->gpct_command[chan] &= ~(G_Up_Down(0x3));
-       devpriv->gpct_command[chan] |= G_Up_Down(1);
-
-       devpriv->stc_writew(dev,  devpriv->gpct_mode[chan],G_Mode_Register(chan));
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan],G_Command_Register(chan));
-
-       //printk("exit GPCT_Pulse_Width_Meas\n");
-}
-
-/* GPCT_Gen_Single_Pulse() creates pulse of length pulsewidth which starts after the Arm
-signal is sent.  The pulse is delayed by the value already in the counter.  This function could
-be modified to send a pulse in response to a trigger event at its gate.*/
-static void GPCT_Gen_Single_Pulse(comedi_device *dev, int chan, unsigned int length)
-{
-       //printk("GPCT_Gen_Cont...");
-
-       devpriv->gpct_cur_operation[chan] = GPCT_SINGLE_PULSE_OUT;
-
-       // Set length of the pulse
-       GPCT_Load_B(dev,chan, length-1);
-
-       //Load next time using B, This is reset by GPCT_Load_Using_A()
-       devpriv->gpct_mode[chan] |= G_Load_Source_Select;
-
-       devpriv->gpct_mode[chan] &= ~G_OR_Gate;
-       devpriv->gpct_mode[chan] &= ~G_Gate_Select_Load_Source;
-
-       // Output_Mode = 3
-       devpriv->gpct_mode[chan] &= ~(G_Output_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Output_Mode(2); //TIM 4/26/01 was 3
-
-       //Gating Mode=0 for untriggered single pulse
-       devpriv->gpct_mode[chan] &= ~(G_Gating_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Gating_Mode(0); //TIM 4/25/01 was 1
-
-       // Trigger_Mode_For_Edge_Gate=0
-       devpriv->gpct_mode[chan] &= ~(G_Trigger_Mode_For_Edge_Gate(0x3));
-       devpriv->gpct_mode[chan] |= G_Trigger_Mode_For_Edge_Gate(2);
-
-
-       devpriv->gpct_mode[chan] |= G_Reload_Source_Switching;
-       devpriv->gpct_mode[chan] &= ~G_Loading_On_Gate;
-       devpriv->gpct_mode[chan] |= G_Loading_On_TC; //TIM 4/25/01
-       devpriv->gpct_mode[chan] &= ~G_Gate_On_Both_Edges;
-
-       // Stop_Mode = 2
-       devpriv->gpct_mode[chan] &= ~(G_Stop_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Stop_Mode(2); //TIM 4/25/01
-
-       // Counting_Once = 2
-       devpriv->gpct_mode[chan] &= ~(G_Counting_Once(0x3));
-       devpriv->gpct_mode[chan] |= G_Counting_Once(1); //TIM 4/25/01
-
-       // Up_Down = 1
-       devpriv->gpct_command[chan] &= ~(G_Up_Down(0x3));
-       devpriv->gpct_command[chan] |= G_Up_Down(0); //TIM 4/25/01 was 1
-
-       devpriv->stc_writew(dev,  devpriv->gpct_mode[chan],G_Mode_Register(chan));
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan],G_Command_Register(chan));
-
-       //printk("exit GPCT_Gen_Cont\n");
-}
-
-static void GPCT_Gen_Cont_Pulse(comedi_device *dev, int chan, unsigned int length)
-{
-       //printk("GPCT_Gen_Cont...");
-
-       devpriv->gpct_cur_operation[chan] = GPCT_CONT_PULSE_OUT;
-
-       // Set length of the pulse
-       GPCT_Load_B(dev,chan, length-1);
-
-       //Load next time using B, This is reset by GPCT_Load_Using_A()
-       devpriv->gpct_mode[chan] |= G_Load_Source_Select;
-
-       devpriv->gpct_mode[chan] &= ~G_OR_Gate;
-       devpriv->gpct_mode[chan] &= ~G_Gate_Select_Load_Source;
-
-       // Output_Mode = 3
-       devpriv->gpct_mode[chan] &= ~(G_Output_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Output_Mode(2); //TIM 4/26/01 was 3
-
-       //Gating Mode=0 for untriggered single pulse
-       devpriv->gpct_mode[chan] &= ~(G_Gating_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Gating_Mode(0); //TIM 4/26/01 was 0
-
-       // Trigger_Mode_For_Edge_Gate=0
-       devpriv->gpct_mode[chan] &= ~(G_Trigger_Mode_For_Edge_Gate(0x3));
-       devpriv->gpct_mode[chan] |= G_Trigger_Mode_For_Edge_Gate(2);
-
-
-       devpriv->gpct_mode[chan] |= G_Reload_Source_Switching;
-       devpriv->gpct_mode[chan] &= ~G_Loading_On_Gate;
-       devpriv->gpct_mode[chan] |= G_Loading_On_TC;
-       devpriv->gpct_mode[chan] &= ~G_Gate_On_Both_Edges;
-
-       // Stop_Mode = 2
-       devpriv->gpct_mode[chan] &= ~(G_Stop_Mode(0x3));
-       devpriv->gpct_mode[chan] |= G_Stop_Mode(0); //TIM 4/26/01
-
-       // Counting_Once = 2
-       devpriv->gpct_mode[chan] &= ~(G_Counting_Once(0x3));
-       devpriv->gpct_mode[chan] |= G_Counting_Once(0); //TIM 4/26/01
-
-       // Up_Down = 1
-       devpriv->gpct_command[chan] &= ~(G_Up_Down(0x3));
-       devpriv->gpct_command[chan] |= G_Up_Down(0);
-
-       //TIM 4/26/01
-       //This seems pretty unsafe since I don't think it is cleared anywhere.
-       //I don't think this is working
-       //devpriv->gpct_command[chan] &= ~G_Bank_Switch_Enable;
-       //devpriv->gpct_command[chan] &= ~G_Bank_Switch_Mode;
-
-
-       devpriv->stc_writew(dev,  devpriv->gpct_mode[chan],G_Mode_Register(chan));
-       devpriv->stc_writew(dev,  devpriv->gpct_command[chan],G_Command_Register(chan));
-
-       //printk("exit GPCT_Gen_Cont\n");
-}
-
 static void GPCT_Reset(comedi_device *dev, int chan)
 {
        int temp_ack_reg=0;
@@ -4236,113 +4000,27 @@ static void GPCT_Reset(comedi_device *dev, int chan)
        //printk("exit GPCT_Reset\n");
 }
 
-static int ni_gpct_insn_config(comedi_device *dev,comedi_subdevice *s,
-       comedi_insn *insn,lsampl_t *data)
-{
-       int retval=0;
-       //printk("data[0] is 0x%08x, data[1] is 0x%08x\n",data[0],data[1]);
-       switch(data[0]){
-       case GPCT_RESET:
-               if(insn->n!=1)return -EINVAL;
-               GPCT_Reset(dev,insn->chanspec);
-               break;
-       case GPCT_SET_SOURCE:
-               if(insn->n!=2)return -EINVAL;
-               retval=GPCT_Set_Source(dev,insn->chanspec,data[1]);
-               break;
-       case GPCT_SET_GATE:
-               if(insn->n!=2)return -EINVAL;
-               retval=GPCT_Set_Gate(dev,insn->chanspec,data[1]);
-               break;
-       case GPCT_SET_DIRECTION:
-               if(insn->n!=2) return -EINVAL;
-               retval=GPCT_Set_Direction(dev,insn->chanspec,data[1]);
-               break;
-       case GPCT_GET_INT_CLK_FRQ:
-               if(insn->n!=2) return -EINVAL;
-               //There are actually 2 internal clocks on the STC, we always
-               //use the fast 20MHz one at this time.  Tim  Ousley 5/1/01
-               //NOTE: This is not the final interface, ideally the user
-               //will never need to know the int. clk. freq.
-               data[1]=50;//50ns = 20MHz = internal timebase of STC
-               break;
-       case GPCT_SET_OPERATION:
-               //TIM 5/1/01 if((insn->n<2)||(insn->n>3))return -EINVAL;
-               switch(data[1]){
-                       case GPCT_SIMPLE_EVENT:
-                               GPCT_Event_Counting(dev,insn->chanspec);
-                               break;
-                       case GPCT_SINGLE_PERIOD:
-                               GPCT_Period_Meas(dev,insn->chanspec);
-                               break;
-                       case GPCT_SINGLE_PW:
-                               GPCT_Pulse_Width_Meas(dev,insn->chanspec);
-                               break;
-                       case GPCT_SINGLE_PULSE_OUT:
-                               GPCT_Gen_Single_Pulse(dev,insn->chanspec,data[2]);
-                               break;
-                       case GPCT_CONT_PULSE_OUT:
-                               GPCT_Gen_Cont_Pulse(dev,insn->chanspec,data[2]);
-                               break;
-                       default:
-                               rt_printk("unsupported GPCT operation!\n");
-                               return -EINVAL;
-               }
-               break;
-       case GPCT_ARM:
-               if(insn->n!=1)return -EINVAL;
-               retval=GPCT_Arm(dev,insn->chanspec);
-               break;
-       case GPCT_DISARM:
-               if(insn->n!=1)return -EINVAL;
-               retval=GPCT_Disarm(dev,insn->chanspec);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       //catch any errors from return values
-       if(retval==0){
-               return insn->n;
-       }else{
-               if(data[0]!=GPCT_ARM){
-                       rt_printk("error: retval was %d\n",retval);
-                       rt_printk("data[0] is 0x%08x, data[1] is 0x%08x\n",data[0],data[1]);
-               }
+#endif
 
-               return retval;
-       }
+static int ni_gpct_insn_config(comedi_device *dev, comedi_subdevice *s,
+       comedi_insn *insn, lsampl_t *data)
+{
+       struct ni_gpct *counter = s->private;
+       return ni_tio_insn_config(counter, insn, data);
 }
 
-static int ni_gpct_insn_read(comedi_device *dev,comedi_subdevice *s,
-       comedi_insn *insn,lsampl_t *data) {
-
-       int chan=insn->chanspec;
-       int cur_op = devpriv->gpct_cur_operation[chan];
-
-       //printk("in ni_gpct_insn_read, n=%d, data[0]=%d\n",insn->chanspec,data[0]);
-       if(insn->n!=1)return -EINVAL;
-
-       data[0] = GPCT_G_Watch(dev,insn->chanspec);
-
-       /* for certain modes (period and pulse width measurment), the value
-       in the counter is not valid until the counter stops.  If the value is
-       invalid, return a 0 */
-       if((cur_op == GPCT_SINGLE_PERIOD) || (cur_op == GPCT_SINGLE_PW)){
-               /* is the counter still running? */
-               if(devpriv->stc_readw(dev, G_Status_Register) & (chan?G1_Counting_St:G0_Counting_St))
-                       data[0]=0;
-       }
-       return 1;
+static int ni_gpct_insn_read(comedi_device *dev, comedi_subdevice *s,
+       comedi_insn *insn,lsampl_t *data)
+{
+       struct ni_gpct *counter = s->private;
+       return ni_tio_rinsn(counter, insn, data);
 }
 
-static int ni_gpct_insn_write(comedi_device *dev,comedi_subdevice *s,
-       comedi_insn *insn,lsampl_t *data) {
-
-       //printk("in ni_gpct_insn_write");
-       if(insn->n!=1)return -EINVAL;
-       GPCT_Load_Using_A(dev,insn->chanspec,data[0]);
-       return 1;
+static int ni_gpct_insn_write(comedi_device *dev, comedi_subdevice *s,
+       comedi_insn *insn, lsampl_t *data)
+{
+       struct ni_gpct *counter = s->private;
+       return ni_tio_winsn(counter, insn, data);
 }
 
 static int ni_gpct_cmd(comedi_device *dev, comedi_subdevice *s)
index 738b470f1343afc98ff8a90bb6fd93a1efd77479..099fd15c24981354ea240cff2aed0fac5becc1fb 100644 (file)
@@ -36,9 +36,9 @@ See the notes in the ni_atmio.o driver.
        included by all the E series drivers.
 
        References for specifications:
-       
+
           341080a.pdf  DAQCard E Series Register Level Programmer Manual
-       
+
 */
 
 #include <linux/comedidev.h>
@@ -275,7 +275,7 @@ static int cs_attach(struct pcmcia_device *p_dev)
        link->conf.Attributes = CONF_ENABLE_IRQ;
        link->conf.Vcc = 50;
        link->conf.IntType = INT_MEMORY_AND_IO;
-       
+
        link->next = dev_list;
        dev_list = link;
 
@@ -302,9 +302,9 @@ static void cs_detach(struct pcmcia_device *p_dev)
 {
        dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
-       
+
        DPRINTK("cs_detach(link=%p)\n",link);
-       
+
        for(linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
                if (*linkp == link) break;
        if (*linkp==NULL)
@@ -367,7 +367,7 @@ static void mio_cs_config(dev_link_t *link)
        tuple.TupleOffset = 0;
        tuple.TupleDataMax = 255;
        tuple.Attributes = 0;
-       
+
        tuple.DesiredTuple = CISTPL_CONFIG;
        ret = pcmcia_get_first_tuple(handle, &tuple);
        ret = pcmcia_get_tuple_data(handle, &tuple);
@@ -457,7 +457,7 @@ static int mio_cs_attach(comedi_device *dev,comedi_devconfig *it)
        dev_link_t *link;
        unsigned int irq;
        int ret;
-       
+
        DPRINTK("mio_cs_attach(dev=%p,it=%p)\n",dev,it);
 
        link = dev_list; /* XXX hack */
@@ -490,7 +490,7 @@ static int mio_cs_attach(comedi_device *dev,comedi_devconfig *it)
 #endif
 
        dev->board_ptr = ni_boards + ni_getboardtype(dev,link);
-       
+
        printk(" %s",boardtype.name);
        dev->board_name=boardtype.name;
 
@@ -499,14 +499,15 @@ static int mio_cs_attach(comedi_device *dev,comedi_devconfig *it)
                return -EINVAL;
        }
        dev->irq = irq;
-       
+
        /* allocate private area */
        if((ret=ni_alloc_private(dev))<0)
                return ret;
        devpriv->stc_writew = &mio_cs_win_out;
        devpriv->stc_readw = &mio_cs_win_in;
        devpriv->stc_writel = &win_out2;
-       
+       devpriv->stc_readl = &win_in2;
+
        if( (ret=ni_E_init(dev,it))<0 ){
                return ret;
        }
@@ -531,7 +532,7 @@ static int get_prodid(comedi_device *dev,dev_link_t *link)
           (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)){
                prodid = le16_to_cpu(buf[1]);
        }
-       
+
        return prodid;
 }
 
@@ -539,7 +540,7 @@ static int ni_getboardtype(comedi_device *dev,dev_link_t *link)
 {
        int id;
        int i;
-       
+
        id = get_prodid(dev,link);
 
        for(i=0;i<n_ni_boards;i++){
@@ -580,7 +581,7 @@ struct pcmcia_driver ni_mio_cs_driver =
        .owner = THIS_MODULE,
        .drv = {
                .name = dev_info,
-       },      
+       },
 };
 
 int init_module(void)
index b3cf9b66bc0e7954fd364c4ae9b38a687bff7202..5fb2e374cbaab1a6c23feaad106230bebf6028e5 100644 (file)
@@ -1184,6 +1184,12 @@ static void m_series_stc_writew(comedi_device *dev, uint16_t data, int reg)
        case G_Autoincrement_Register(1):
                offset = M_Offset_G1_Autoincrement;
                break;
+       case G_Command_Register(0):
+               offset = M_Offset_G0_Command;
+               break;
+       case G_Command_Register(1):
+               offset = M_Offset_G1_Command;
+               break;
        case G_Input_Select_Register(0):
                offset = M_Offset_G0_Input_Select;
                break;
@@ -1230,6 +1236,7 @@ static void m_series_stc_writew(comedi_device *dev, uint16_t data, int reg)
         and M_Offset_SCXI_Serial_Data_Out (8 bit) */
        default:
                rt_printk("%s: bug! unhandled register=0x%x in switch.\n", __FUNCTION__, reg);
+               BUG();
                return;
                break;
        }
@@ -1261,6 +1268,7 @@ static uint16_t m_series_stc_readw(comedi_device *dev, int reg)
                break;
        default:
                rt_printk("%s: bug! unhandled register=0x%x in switch.\n", __FUNCTION__, reg);
+               BUG();
                return 0;
                break;
        }
@@ -1287,14 +1295,53 @@ static void m_series_stc_writel(comedi_device *dev, uint32_t data, int reg)
        case AO_UI_Load_A_Register:
                offset = M_Offset_AO_UI_Load_A;
                break;
+       case G_Load_A_Register(0):
+               offset = M_Offset_G0_Load_A;
+               break;
+       case G_Load_A_Register(1):
+               offset = M_Offset_G1_Load_A;
+               break;
+       case G_Load_B_Register(0):
+               offset = M_Offset_G0_Load_B;
+               break;
+       case G_Load_B_Register(1):
+               offset = M_Offset_G1_Load_B;
+               break;
        default:
                rt_printk("%s: bug! unhandled register=0x%x in switch.\n", __FUNCTION__, reg);
+               BUG();
                return;
                break;
        }
        ni_writel(data, offset);
 }
 
+static uint32_t m_series_stc_readl(comedi_device *dev, int reg)
+{
+       unsigned offset;
+       switch(reg)
+       {
+       case G_HW_Save_Register(0):
+               offset = M_Offset_G0_HW_Save;
+               break;
+       case G_HW_Save_Register(1):
+               offset = M_Offset_G1_HW_Save;
+               break;
+       case G_Save_Register(0):
+               offset = M_Offset_G0_Save;
+               break;
+       case G_Save_Register(1):
+               offset = M_Offset_G1_Save;
+               break;
+       default:
+               rt_printk("%s: bug! unhandled register=0x%x in switch.\n", __FUNCTION__, reg);
+               BUG();
+               return 0;
+               break;
+       }
+       return ni_readl(offset);
+}
+
 #define interrupt_pin(a)       0
 #define IRQ_POLARITY 1
 
@@ -1390,11 +1437,13 @@ static int pcimio_attach(comedi_device *dev,comedi_devconfig *it)
                devpriv->stc_writew = &m_series_stc_writew;
                devpriv->stc_readw = &m_series_stc_readw;
                devpriv->stc_writel = &m_series_stc_writel;
+               devpriv->stc_readl = &m_series_stc_readl;
        }else
        {
                devpriv->stc_writew = &e_series_win_out;
                devpriv->stc_readw = &e_series_win_in;
                devpriv->stc_writel = &win_out2;
+               devpriv->stc_readl = &win_in2;
        }
 
        ret = mite_setup(devpriv->mite);
index 13276b6ca0dd13575b3debefa76ae3837beba4cf..04b1eb13c9695d32c4859b9208d8571431907cc0 100644 (file)
@@ -29,6 +29,8 @@
 #ifndef _COMEDI_NI_STC_H
 #define _COMEDI_NI_STC_H
 
+#include "ni_tio.h"
+
 #define _bit15         0x8000
 #define _bit14         0x4000
 #define _bit13         0x2000
@@ -1268,9 +1270,11 @@ static ni_board ni_boards[];
 #define boardtype (*(ni_board *)dev->board_ptr)
 
 #define MAX_N_AO_CHAN 8
+#define NUM_GPCT 2
 
 #define NI_PRIVATE_COMMON                                      \
        uint16_t (*stc_readw)(comedi_device *dev, int register);        \
+       uint32_t (*stc_readl)(comedi_device *dev, int register);        \
        void (*stc_writew)(comedi_device *dev, uint16_t value, int register);   \
        void (*stc_writel)(comedi_device *dev, uint32_t value, int register);   \
        \
@@ -1307,10 +1311,7 @@ static ni_board ni_boards[];
        unsigned short ao_cmd3;                                 \
        unsigned short ao_trigger_select;                       \
                                                                \
-       unsigned short gpct_mode[2];                            \
-       unsigned short gpct_command[2];                         \
-       unsigned short gpct_input_select[2];                    \
-       int gpct_cur_operation[2];                              \
+       struct ni_gpct counters[NUM_GPCT];      \
        unsigned short an_trig_etc_reg;                         \
                                                                \
        unsigned ai_offset[512];                                \