Added support for configuring pfi routing on m-series boards with
authorFrank Mori Hess <fmhess@speakeasy.net>
Tue, 24 Oct 2006 18:52:22 +0000 (18:52 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Tue, 24 Oct 2006 18:52:22 +0000 (18:52 +0000)
INSN_CONFIG_SET_ROUTING.

comedi/drivers/ni_mio_common.c
comedi/drivers/ni_stc.h
include/linux/comedi.h

index 1a5063309019958189e233d9c8877c7cb0947db4..9ab59820ccd77418d4a41fdf64559eea5a25efe8 100644 (file)
@@ -4263,6 +4263,88 @@ static int ni_gpct_insn_write(comedi_device *dev,comedi_subdevice *s,
  *
  */
 
+int ni_m_series_set_pfi_routing(comedi_device *dev, unsigned chan, unsigned source)
+{
+       if((source & 0x1f) != source) return -EINVAL;
+       const unsigned pfi_reg_index = 1 + chan / 3;
+       const unsigned array_offset = pfi_reg_index - 1;
+       devpriv->pfi_output_select_reg[array_offset] &= ~MSeries_PFI_Output_Select_Mask(chan);
+       devpriv->pfi_output_select_reg[array_offset] |= MSeries_PFI_Output_Select_Bits(chan, source);
+       ni_writew(devpriv->pfi_output_select_reg[array_offset], M_Offset_PFI_Output_Select(pfi_reg_index));
+       return 2;
+}
+
+int ni_old_set_pfi_routing(comedi_device *dev, unsigned chan, unsigned source)
+{
+       // pre-m-series boards have fixed signals on pfi pins
+       if(source != ni_old_get_pfi_routing(dev, chan)) return -EINVAL;
+       return 2;
+}
+
+int ni_set_pfi_routing(comedi_device *dev, unsigned chan, unsigned source)
+{
+       if(boardtype.reg_type == ni_reg_m_series)
+               return ni_m_series_set_pfi_routing(dev, chan, source);
+       else
+               return ni_old_set_pfi_routing(dev, chan, source);
+}
+
+unsigned ni_m_series_get_pfi_routing(comedi_device *dev, unsigned chan)
+{
+       const unsigned array_offset = chan / 3;
+       return MSeries_PFI_Output_Select_Source(chan, devpriv->pfi_output_select_reg[array_offset]);
+}
+
+unsigned ni_old_get_pfi_routing(comedi_device *dev, unsigned chan)
+{
+       // pre-m-series boards have fixed signals on pfi pins
+       switch(chan)
+       {
+       case 0:
+               return NI_PFI_OUTPUT_AI_START1;
+               break;
+       case 1:
+               return NI_PFI_OUTPUT_AI_START2;
+               break;
+       case 2:
+               return NI_PFI_OUTPUT_AI_CONVERT;
+               break;
+       case 3:
+               return NI_PFI_OUTPUT_G_SRC1;
+               break;
+       case 4:
+               return NI_PFI_OUTPUT_G_GATE1;
+               break;
+       case 5:
+               return NI_PFI_OUTPUT_AO_UPDATE_N;
+               break;
+       case 6:
+               return NI_PFI_OUTPUT_AO_START1;
+               break;
+       case 7:
+               return NI_PFI_OUTPUT_AI_START_PULSE;
+               break;
+       case 8:
+               return NI_PFI_OUTPUT_G_SRC0;
+               break;
+       case 9:
+               return NI_PFI_OUTPUT_G_GATE0;
+               break;
+       default:
+               rt_printk("%s: bug, unhandled case in switch.\n", __FUNCTION__);
+               break;
+       }
+       return 0;
+}
+
+unsigned ni_get_pfi_routing(comedi_device *dev, unsigned chan)
+{
+       if(boardtype.reg_type == ni_reg_m_series)
+               return ni_m_series_get_pfi_routing(dev, chan);
+       else
+               return ni_old_get_pfi_routing(dev, chan);
+}
+
 static int ni_pfi_insn_bits(comedi_device *dev,comedi_subdevice *s,
        comedi_insn *insn,lsampl_t *data)
 {
@@ -4293,6 +4375,13 @@ static int ni_pfi_insn_config(comedi_device *dev,comedi_subdevice *s,
                data[1] = (devpriv->io_bidirection_pin_reg & (1<<chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
                return insn->n;
                break;
+       case INSN_CONFIG_SET_ROUTING:
+               return ni_set_pfi_routing(dev, chan, data[1]);
+               break;
+       case INSN_CONFIG_GET_ROUTING:
+               data[1] = ni_get_pfi_routing(dev, chan);
+               return 2;
+               break;
        default:
                return -EINVAL;
        }
@@ -4586,8 +4675,8 @@ unsigned ni_get_rtsi_routing(comedi_device *dev, unsigned chan)
        {
                if(chan == old_RTSI_clock_channel)
                        return NI_RTSI_OUTPUT_RTSI_OSC;
-               rt_printk("%s: invalid channel=%i\n", __FUNCTION__, chan);
-               return -EINVAL;
+               rt_printk("%s: bug! should never get here?\n", __FUNCTION__);
+               return 0;
        }
 }
 
index 9bfafa836b67fbae177bc0681b0d98c6db770dea..f237fff26316cbed34d5a4c2deac3f1c18d2c248 100644 (file)
@@ -1040,6 +1040,15 @@ static inline int M_Offset_AO_Reference_Attenuation(int channel)
        }
        return offset[channel];
 };
+static inline unsigned M_Offset_PFI_Output_Select(unsigned n)
+{
+       if(n < 1 || n > 6)
+       {
+               rt_printk("%s: invalid pfi output select register=%i\n", __FUNCTION__, n);
+               return M_Offset_PFI_Output_Select_1;
+       }
+       return M_Offset_PFI_Output_Select_1 + (n - 1) * 2;
+}
 
 enum MSeries_AI_Config_FIFO_Data_Bits
 {
@@ -1179,6 +1188,20 @@ static inline unsigned MSeries_Cal_PWM_Low_Time_Bits(unsigned count)
        return count & 0xffff;
 }
 
+static inline unsigned MSeries_PFI_Output_Select_Mask(unsigned channel)
+{
+       return 0x1f << (channel % 3) * 5;
+};
+static inline unsigned MSeries_PFI_Output_Select_Bits(unsigned channel, unsigned source)
+{
+       return (source & 0x1f) << ((channel % 3) * 5);
+};
+// inverse to MSeries_PFI_Output_Select_Bits
+static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel, unsigned bits)
+{
+       return (bits >> ((channel % 3) * 5)) & 0x1f;
+};
+
 #define M_SERIES_EEPROM_SIZE 1024
 
 typedef struct ni_board_struct{
@@ -1273,6 +1296,7 @@ static ni_board ni_boards[];
        unsigned short rtsi_trig_direction_reg;                 \
        unsigned short rtsi_trig_a_output_reg; \
        unsigned short rtsi_trig_b_output_reg; \
+       unsigned short pfi_output_select_reg[6]; \
        \
        unsigned clock_ns; \
        unsigned clock_source; \
index d6cba93003253dac4d3f4db650a84a9cdc590e42..ae62b1fdd3b262b586495ecf435dadaf90ff3554 100644 (file)
@@ -538,9 +538,9 @@ static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel)
 }
 
 /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING.
- The numbers are assigned are not arbitrary, they correspond to the bits required
+ The numbers assigned are not arbitrary, they correspond to the bits required
  to program the board. */
-enum ni_rtsi_output
+enum ni_rtsi_routing
 {
        NI_RTSI_OUTPUT_ADR_START1 = 0,
        NI_RTSI_OUTPUT_ADR_START2 = 1,
@@ -558,6 +558,44 @@ static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n)
        return NI_RTSI_OUTPUT_RTSI_BRD_0 + n;
 }
 
+/* Signals which can be routed to an NI PFI pin on an m-series board
+ with INSN_CONFIG_SET_ROUTING.  These numbers are also returned
+ by INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though
+ their routing cannot be changed.  The numbers assigned are
+ not arbitrary, they correspond to the bits required
+ to program the board. */
+enum ni_pfi_routing
+{
+       NI_PFI_OUTPUT_PFI_DEFAULT = 0,
+       NI_PFI_OUTPUT_AI_START1 = 1,
+       NI_PFI_OUTPUT_AI_START2 = 2,
+       NI_PFI_OUTPUT_AI_CONVERT = 3,
+       NI_PFI_OUTPUT_G_SRC1 = 4,
+       NI_PFI_OUTPUT_G_GATE1 = 5,
+       NI_PFI_OUTPUT_AO_UPDATE_N = 6,
+       NI_PFI_OUTPUT_AO_START1 = 7,
+       NI_PFI_OUTPUT_AI_START_PULSE = 8,
+       NI_PFI_OUTPUT_G_SRC0 = 9,
+       NI_PFI_OUTPUT_G_GATE0 = 10,
+       NI_PFI_OUTPUT_EXT_STROBE = 11,
+       NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12,
+       NI_PFI_OUTPUT_GOUT0 = 13,
+       NI_PFI_OUTPUT_GOUT1 = 14,
+       NI_PFI_OUTPUT_FREQ_OUT = 15,
+       NI_PFI_OUTPUT_PFI_DO = 16,
+       NI_PFI_OUTPUT_I_ATRIG = 17,
+       NI_PFI_OUTPUT_RTSI0 = 18,
+       NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26,
+       NI_PFI_OUTPUT_SCXI_TRIG1 = 27,
+       NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28,
+       NI_PFI_OUTPUT_CDI_SAMPLE = 29,
+       NI_PFI_OUTPUT_CDO_UPDATE = 30
+};
+static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel)
+{
+       return NI_PFI_OUTPUT_RTSI0 + rtsi_channel;
+}
+
 /* NI External Trigger lines.  These values are not arbitrary, but are related to
        the bits required to program the board (offset by 1 for historical reasons). */
 static inline unsigned NI_EXT_PFI(unsigned pfi_channel)