static int ni_eeprom_insn_read(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data);
+static int ni_m_series_eeprom_insn_read(comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,lsampl_t *data);
static int ni_pfi_insn_bits(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data);
return insn->n;
}
+void ni_prime_channelgain_list(comedi_device *dev)
+{
+ int i;
+ devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
+ for(i = 0; i < NI_TIMEOUT; ++i)
+ {
+ if(!(devpriv->stc_readw(dev, AI_Status_1_Register) & AI_FIFO_Empty_St))
+ {
+ devpriv->stc_writew(dev, 1, ADC_FIFO_Clear);
+ return;
+ }
+ comedi_udelay(1);
+ }
+ rt_printk("ni_mio_common: timeout loading channel/gain list\n");
+}
+
+/* m series boards have new ai_config_fifo_data register which replaces
+ * old configuration_memory_low and high registers. But the old registers still
+ * seem to work, so I'm not going to bother to change it yet. */
+static void ni_m_series_load_channelgain_list(comedi_device *dev,unsigned int n_chan,
+ unsigned int *list)
+{
+ unsigned int chan, range, aref;
+ unsigned int i;
+ unsigned int hi,lo;
+ unsigned offset;
+ unsigned int dither;
+ unsigned int use_alt_src;
+ unsigned range_code;
+
+ devpriv->stc_writew(dev, 1, Configuration_Memory_Clear);
+
+ offset = 1 << (boardtype.adbits - 1);
+ for(i = 0; i < n_chan; i++)
+ {
+ chan = CR_CHAN(list[i]);
+ aref = CR_AREF(list[i]);
+ range = CR_RANGE(list[i]);
+ dither = ((list[i] & CR_ALT_FILTER) != 0);
+ use_alt_src = ((list[i] & CR_ALT_SOURCE) != 0);
+
+ range_code = ni_gainlkup[boardtype.gainlkup][range];
+ devpriv->ai_offset[i] = offset;
+
+ hi = 0;
+ if(use_alt_src)
+ {
+ unsigned bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit;
+ bypass_bits |= chan;
+ bypass_bits |= MSeries_AI_Bypass_Cal_Sel_Pos_Bits(devpriv->ai_calib_source);
+ bypass_bits |= MSeries_AI_Bypass_Gain_Bits(range_code);
+ if(dither)
+ bypass_bits |= MSeries_AI_Bypass_Dither_Bit;
+ ni_writel(bypass_bits, M_Offset_AI_Config_FIFO_Bypass);
+ }else
+ {
+ ni_writel(0, M_Offset_AI_Config_FIFO_Bypass);
+ switch( aref )
+ {
+ case AREF_DIFF:
+ hi |= AI_DIFFERENTIAL;
+ break;
+ case AREF_COMMON:
+ hi |= AI_COMMON;
+ break;
+ case AREF_GROUND:
+ hi |= AI_GROUND;
+ break;
+ case AREF_OTHER:
+ break;
+ }
+ }
+ hi |= AI_CONFIG_CHANNEL( chan );
+
+ ni_writew(hi,Configuration_Memory_High);
+
+ lo = range_code;
+ if(i == n_chan - 1) lo |= AI_LAST_CHANNEL;
+ if( dither ) lo |= AI_DITHER;
+
+ ni_writew(lo,Configuration_Memory_Low);
+ }
+ ni_prime_channelgain_list(dev);
+}
+
/*
* Notes on the 6110 and 6111:
* These boards a slightly different than the rest of the series, since
unsigned offset;
unsigned int dither;
+ if(boardtype.reg_type == ni_reg_m_series)
+ {
+ ni_m_series_load_channelgain_list(dev, n_chan, list);
+ return;
+ }
if(n_chan == 1 && boardtype.reg_type != ni_reg_611x){
if(devpriv->changain_state && devpriv->changain_spec==list[0]){
// ready to go.
/* prime the channel/gain list */
if(boardtype.reg_type != ni_reg_611x){
- devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
- for(i=0;i<NI_TIMEOUT;i++){
- if(!(devpriv->stc_readw(dev, AI_Status_1_Register)&AI_FIFO_Empty_St)){
- devpriv->stc_writew(dev, 1,ADC_FIFO_Clear);
- return;
- }
- comedi_udelay(1);
- }
- rt_printk("ni_mio_common: timeout loading channel/gain list\n");
+ ni_prime_channelgain_list(dev);
}
}
s=dev->subdevices+6;
s->type=COMEDI_SUBD_MEMORY;
s->subdev_flags=SDF_READABLE|SDF_INTERNAL;
- s->n_chan=512;
s->maxdata=0xff;
- s->insn_read=ni_eeprom_insn_read;
-
+ if(boardtype.reg_type == ni_reg_m_series)
+ {
+ s->n_chan = M_SERIES_EEPROM_SIZE;
+ s->insn_read = &ni_m_series_eeprom_insn_read;
+ }else
+ {
+ s->n_chan = 512;
+ s->insn_read = &ni_eeprom_insn_read;
+ }
/* PFI */
s=dev->subdevices+7;
s->type=COMEDI_SUBD_DIO;
return bitstring;
}
+static int ni_m_series_eeprom_insn_read(comedi_device *dev,comedi_subdevice *s,
+ comedi_insn *insn,lsampl_t *data)
+{
+ data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)];
+
+ return 1;
+}
+
static void ni_write_caldac(comedi_device *dev,int addr,int val);
/*
calibration subdevice
static int pcimio_ao_change(comedi_device *dev, comedi_subdevice *s,
unsigned long new_size);
+static void m_series_init_eeprom_buffer(comedi_device *dev)
+{
+ static const int Start_Cal_EEPROM = 0x400;
+ static const unsigned window_size = 10;
+ unsigned old_iodwbsr_bits;
+ unsigned old_iodwbsr1_bits;
+ unsigned old_iodwcr1_bits;
+ int i;
+
+ old_iodwbsr_bits = readl(devpriv->mite->mite_io_addr + MITE_IODWBSR);
+ old_iodwbsr1_bits = readl(devpriv->mite->mite_io_addr + MITE_IODWBSR_1);
+ old_iodwcr1_bits = readl(devpriv->mite->mite_io_addr + MITE_IODWCR_1);
+ writel(0x0, devpriv->mite->mite_io_addr + MITE_IODWBSR);
+ writel(((0x80 | window_size) | devpriv->mite->daq_phys_addr), devpriv->mite->mite_io_addr + MITE_IODWBSR_1);
+ writel(0x0, devpriv->mite->mite_io_addr + MITE_IODWCR_1);
+ writel(0xf, devpriv->mite->mite_io_addr + 0x30);
+
+ for(i = 0; i < M_SERIES_EEPROM_SIZE; ++i)
+ {
+ devpriv->eeprom_buffer[i] = ni_readb(Start_Cal_EEPROM + i);
+ }
+
+ writel(old_iodwbsr1_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR_1);
+ writel(old_iodwbsr_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR);
+ writel(old_iodwcr1_bits, devpriv->mite->mite_io_addr + MITE_IODWCR_1);
+ writel(0x0, devpriv->mite->mite_io_addr + 0x30);
+}
/* cleans up allocated resources */
static int pcimio_detach(comedi_device *dev)
printk(" error setting up mite\n");
return ret;
}
+ if(boardtype.reg_type == ni_reg_m_series)
+ m_series_init_eeprom_buffer(dev);
dev->irq=mite_irq(devpriv->mite);
return offset[channel];
};
+enum MSeries_AI_Config_FIFO_Bypass_Bits
+{
+ MSeries_AI_Bypass_Channel_Mask = 0x7,
+ MSeries_AI_Bypass_Bank_Mask = 0x38,
+ MSeries_AI_Bypass_Cal_Sel_Pos_Mask = 0x380,
+ MSeries_AI_Bypass_Cal_Sel_Neg_Mask = 0x1c00,
+ MSeries_AI_Bypass_Mode_Mux_Mask = 0x6000,
+ MSeries_AO_Bypass_AO_Cal_Sel_Mask = 0x38000,
+ MSeries_AI_Bypass_Gain_Mask = 0x1c0000,
+ MSeries_AI_Bypass_Dither_Bit = 0x200000,
+ MSeries_AI_Bypass_Polarity_Bit = 0x400000,
+ MSeries_AI_Bypass_Config_FIFO_Bit = 0x80000000
+};
+static inline unsigned MSeries_AI_Bypass_Cal_Sel_Pos_Bits(int calibration_source)
+{
+ return (calibration_source << 7) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask;
+}
+static inline unsigned MSeries_AI_Bypass_Cal_Sel_Neg_Bits(int calibration_source)
+{
+ return (calibration_source << 10) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask;
+}
+static inline unsigned MSeries_AI_Bypass_Gain_Bits(int gain)
+{
+ return (gain << 18) & MSeries_AI_Bypass_Gain_Mask;
+}
+
enum MSeries_AO_Config_Bank_Bits
{
MSeries_AO_DAC_Offset_Select_Mask = 0x7,
MSeries_Attenuate_x5_Bit = 0x1
};
+#define M_SERIES_EEPROM_SIZE 1024
+
typedef struct ni_board_struct{
int device_id;
int isapnp_id;
unsigned short atrig_low; \
\
sampl_t ai_fifo_buffer[0x2000]; \
-
+ uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE];
+
#endif /* _COMEDI_NI_STC_H */