#endif
ret=s->do_cmd(dev,s);
-
if(ret==0)return 0;
cleanup:
s = dev->read_subdev;
if(s == NULL || s->async == NULL || (s->subdev_flags & SDF_CMD_READ) == 0) return -EIO;
async = s->async;
-
if(!nbytes)return 0;
if(!s->busy)
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (devpriv->pfi_direction_bits & (((uint64_t)1) << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
- return insn->n;
+ return 0;
case INSN_CONFIG_FILTER:
ni660x_config_filter(dev, chan, data[1]);
- return 0;
+ break;
default:
return -EINVAL;
break;
};
- return insn->n;
+ return 0;
}
comedi_insn *insn, lsampl_t *data);
static int ni_set_master_clock(comedi_device *dev, unsigned source, unsigned period_ns);
+static void ack_a_interrupt(comedi_device *dev, unsigned short a_status);
+static void ack_b_interrupt(comedi_device *dev, unsigned short b_status);
enum aimodes
{
static void get_last_sample_611x( comedi_device *dev );
static void get_last_sample_6143( comedi_device *dev );
#ifdef PCIDMA
-//static void mite_handle_interrupt(comedi_device *dev,unsigned int status);
static int ni_ai_drain_dma(comedi_device *dev );
/* DMA channel setup */
ao_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ao_mite_chan->channel));
comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too);
}
+ ack_a_interrupt(dev, a_status);
+ ack_b_interrupt(dev, b_status);
if((a_status & Interrupt_A_St) || (ai_mite_status & CHSR_INT))
handle_a_interrupt(dev, a_status, ai_mite_status);
if((b_status & Interrupt_B_St) || (ao_mite_status & CHSR_INT))
s->async->events |= COMEDI_CB_EOA;
}
+static void ni_event(comedi_device *dev, comedi_subdevice *s, unsigned events)
+{
+ if(events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW | COMEDI_CB_EOA))
+ {
+ switch(dev->subdevices - s)
+ {
+ case NI_AI_SUBDEV:
+ ni_ai_reset(dev, s);
+ break;
+ case NI_AO_SUBDEV:
+ ni_ao_reset(dev, s);
+ break;
+ case NI_GPCT0_SUBDEV:
+ case NI_GPCT1_SUBDEV:
+ ni_gpct_cancel(dev, s);
+ break;
+ default:
+ break;
+ }
+ }
+ comedi_event(dev, s, events);
+}
+
static void handle_gpct_interrupt(comedi_device *dev, unsigned short counter_index, unsigned short is_terminal_count)
{
unsigned gpct_mite_status;
mite_sync_input_dma(mite_chan, s->async);
comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
-}
-
-static void ni_event(comedi_device *dev, comedi_subdevice *s, unsigned events)
-{
- if(events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW | COMEDI_CB_EOA))
- {
- switch(s->type)
- {
- case COMEDI_SUBD_AI:
- ni_ai_reset(dev, s);
- break;
- case COMEDI_SUBD_AO:
- ni_ao_reset(dev, s);
- break;
- default:
- break;
- }
- }
- comedi_event(dev, s, events);
+ if(s->async->events)
+ ni_event(dev, s, s->async->events);
}
static void ack_a_interrupt(comedi_device *dev, unsigned short a_status)
{
unsigned short ack = 0;
- /* test for all uncommon interrupt events at the same time */
if(a_status & AI_SC_TC_St)
{
ack |= AI_SC_TC_Interrupt_Ack;
{
comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV;
- s->async->events = 0;
+ //67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt
+ if(s->type == COMEDI_SUBD_UNUSED) return;
#ifdef DEBUG_INTERRUPT
rt_printk("ni_mio_common: interrupt: a_status=%04x ai_mite_status=%08x\n",
status, ai_mite_status);
ni_mio_print_status_a(status);
#endif
- ack_a_interrupt(dev, status);
#ifdef PCIDMA
/* Currently, mite.c requires us to handle LINKC and DONE */
if(ai_mite_status & CHSR_LINKC){
b_status,ao_mite_status);
ni_mio_print_status_b(b_status);
#endif
- ack_b_interrupt(dev, b_status);
#ifdef PCIDMA
/* Currently, mite.c requires us to handle LINKC and DONE */
break;
}
- devpriv->stc_writew(dev, 0x3f80,Interrupt_A_Ack_Register); /* clear interrupts */
+ devpriv->stc_writew(dev, AI_Error_Interrupt_Ack |
+ AI_STOP_Interrupt_Ack |
+ AI_START_Interrupt_Ack |
+ AI_START2_Interrupt_Ack |
+ AI_START1_Interrupt_Ack |
+ AI_SC_TC_Interrupt_Ack |
+ AI_SC_TC_Error_Confirm,
+ Interrupt_A_Ack_Register); /* clear interrupts */
ni_set_bits(dev, Interrupt_A_Enable_Register, interrupt_a_enable, 1);
s->n_chan = boardtype.num_p0_dio_channels;
if(boardtype.reg_type & ni_reg_m_series_mask)
{
- s->insn_bits = ni_m_series_dio_insn_bits;
- s->insn_config=ni_m_series_dio_insn_config;
+ s->insn_bits = &ni_m_series_dio_insn_bits;
+ s->insn_config = &ni_m_series_dio_insn_config;
ni_writel(s->io_bits, M_Offset_DIO_Direction);
}else
{
- s->insn_bits=ni_dio_insn_bits;
- s->insn_config=ni_dio_insn_config;
+ s->insn_bits = &ni_dio_insn_bits;
+ s->insn_config = &ni_dio_insn_config;
devpriv->dio_control = DIO_Pins_Dir(s->io_bits);
ni_writew(devpriv->dio_control, DIO_Control_Register);
}
s->n_chan = 512;
s->insn_read = &ni_eeprom_insn_read;
}
+
/* PFI */
s = dev->subdevices + NI_PFI_DIO_SUBDEV;
s->type = COMEDI_SUBD_DIO;
s->n_chan = 10;
}
s->maxdata = 1;
- s->insn_bits = ni_pfi_insn_bits;
- s->insn_config = ni_pfi_insn_config;
+ if(boardtype.reg_type & ni_reg_m_series_mask)
+ {
+ s->insn_bits = &ni_pfi_insn_bits;
+ }
+ s->insn_config = &ni_pfi_insn_config;
ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0);
/* cs5529 calibration adc */
{
s = dev->subdevices + NI_GPCT_SUBDEV(j);
s->type = COMEDI_SUBD_COUNTER;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_CMD_READ;
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->do_cmd = ni_gpct_cmd;
- s->do_cmdtest = ni_gpct_cmdtest;
- s->cancel = ni_gpct_cancel;
+ s->insn_read = &ni_gpct_insn_read;
+ s->insn_write = &ni_gpct_insn_write;
+ s->insn_config = &ni_gpct_insn_config;
+ s->do_cmd = &ni_gpct_cmd;
+ s->do_cmdtest = &ni_gpct_cmdtest;
+ s->cancel = &ni_gpct_cancel;
s->async_dma_dir = DMA_BIDIRECTIONAL;
s->private = &devpriv->counter_dev->counters[j];
return ni_tio_winsn(counter, insn, data);
}
+static inline unsigned Gi_Interrupt_Enable_Register(unsigned counter_index)
+{
+ unsigned reg;
+
+ switch(counter_index)
+ {
+ case 0:
+ reg = Interrupt_A_Enable_Register;
+ break;
+ case 1:
+ reg = Interrupt_B_Enable_Register;
+ break;
+ default:
+ BUG();
+ return 0;
+ break;
+ }
+ return reg;
+}
+
+static inline unsigned Gi_Gate_Interrupt_Enable_Bit(unsigned counter_index)
+{
+ unsigned bit;
+
+ switch(counter_index)
+ {
+ case 0:
+ bit = G0_Gate_Interrupt_Enable;
+ break;
+ case 1:
+ bit = G1_Gate_Interrupt_Enable;
+ break;
+ default:
+ BUG();
+ return 0;
+ break;
+ }
+ return bit;
+}
+
+static inline unsigned Gi_Interrupt_Ack_Register(unsigned counter_index)
+{
+ unsigned reg;
+
+ switch(counter_index)
+ {
+ case 0:
+ reg = Interrupt_A_Ack_Register;
+ break;
+ case 1:
+ reg = Interrupt_B_Ack_Register;
+ break;
+ default:
+ BUG();
+ return 0;
+ break;
+ }
+ return reg;
+}
+
+static inline unsigned Gi_Gate_Interrupt_Ack_Bit(unsigned counter_index)
+{
+ unsigned bit;
+
+ switch(counter_index)
+ {
+ case 0:
+ bit = G0_Gate_Interrupt_Ack;
+ break;
+ case 1:
+ bit = G1_Gate_Interrupt_Ack;
+ break;
+ default:
+ BUG();
+ return 0;
+ break;
+ }
+ return bit;
+}
+
static int ni_gpct_cmd(comedi_device *dev, comedi_subdevice *s)
{
int retval;
comedi_error(dev, "no dma channel available for use by counter");
return retval;
}
+ if(cmd->flags & TRIG_WAKE_EOS)
+ {
+ devpriv->stc_writew(dev, Gi_Gate_Interrupt_Ack_Bit(counter->counter_index),
+ Gi_Interrupt_Ack_Register(counter->counter_index));
+ ni_set_bits(dev, Gi_Interrupt_Enable_Register(counter->counter_index),
+ Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), 1);
+ }
+
comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
retval = ni_tio_cmd(counter, s->async);
comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
retval = ni_tio_cancel(counter);
comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+ ni_set_bits(dev, Gi_Interrupt_Enable_Register(counter->counter_index),
+ Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), 0);
ni_release_gpct_mite_channel(dev, counter->counter_index);
return retval;
}
return ni_old_get_pfi_routing(dev, chan);
}
+static int ni_config_filter(comedi_device *dev, unsigned pfi_channel, enum ni_pfi_filter_select filter)
+{
+ unsigned bits;
+ if((boardtype.reg_type & ni_reg_m_series_mask) == 0)
+ {
+ return -ENOTSUPP;
+ }
+ bits = ni_readl(M_Offset_PFI_Filter);
+ bits &= ~MSeries_PFI_Filter_Select_Mask(pfi_channel);
+ bits |= MSeries_PFI_Filter_Select_Bits(pfi_channel, filter);
+ ni_writel(bits, M_Offset_PFI_Filter);
+ return 0;
+}
+
static int ni_pfi_insn_bits(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data)
{
if((boardtype.reg_type & ni_reg_m_series_mask) == 0)
{
- data[1] = 0;
- return 2;
+ return -ENOTSUPP;
}
if(data[0])
{
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (devpriv->io_bidirection_pin_reg & (1<<chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
- return insn->n;
+ return 0;
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;
+ case INSN_CONFIG_FILTER:
+ return ni_config_filter(dev, chan, data[1]);
break;
default:
return -EINVAL;
}
-
- return 1;
+ return 0;
}
/*
#define AO_START1_Interrupt_Enable _bit1
#define AO_BC_TC_Interrupt_Enable _bit0
+#define Second_IRQ_A_Enable_Register 74
+enum Second_IRQ_A_Enable_Bits
+{
+ AI_SC_TC_Second_Irq_Enable = _bit0,
+ AI_START1_Second_Irq_Enable = _bit1,
+ AI_START2_Second_Irq_Enable = _bit2,
+ AI_START_Second_Irq_Enable = _bit3,
+ AI_STOP_Second_Irq_Enable = _bit4,
+ AI_Error_Second_Irq_Enable = _bit5,
+ G0_TC_Second_Irq_Enable = _bit6,
+ AI_FIFO_Second_Irq_Enable = _bit7,
+ G0_Gate_Second_Irq_Enable = _bit8,
+ Pass_Thru_0_Second_Irq_Enable = _bit9
+};
+
#define Second_IRQ_B_Enable_Register 76
+enum Second_IRQ_B_Enable_Bits
+{
+ AO_BC_TC_Second_Irq_Enable = _bit0,
+ AO_START1_Second_Irq_Enable = _bit1,
+ AO_UPDATE_Second_Irq_Enable = _bit2,
+ AO_START_Second_Irq_Enable = _bit3,
+ AO_STOP_Second_Irq_Enable = _bit4,
+ AO_Error_Second_Irq_Enable = _bit5,
+ AO_UC_TC_Second_Irq_Enable = _bit6,
+ AO_UI2_TC_Second_Irq_Enable = _bit7,
+ AO_FIFO_Second_Irq_Enable = _bit8,
+ G1_TC_Second_Irq_Enable = _bit9,
+ G1_Gate_Second_Irq_Enable = _bit10,
+ Pass_Thru_1_Second_Irq_Enable = _bit11
+};
+
#define AI_Personal_Register 77
#define AI_SHIFTIN_Pulse_Width _bit15
#define AI_EOC_Polarity _bit14
#define G_Bank_Switch_Mode _bit11
#define G_Load _bit2 /* strobe */
-
/* input select register */
#define G_Gate_Select(a) (((a)&0x1f)<<7)
#define G_Source_Select(a) (((a)&0x1f)<<2)
#define G_OR_Gate _bit13
#define G_Gate_Select_Load_Source _bit12
-
/* mode register */
#define G_Loading_On_TC _bit12
#define G_Output_Mode(a) (((a)&0x03)<<8)
#define G0_Save_St _bit0
/* general purpose counter timer */
-#define G0_TC_Interrupt_Enable _bit6
-#define G1_TC_Interrupt_Enable _bit9
-#define G0_Gate_Interrupt_Enable _bit8
-#define G1_Gate_Interrupt_Enable _bit10
-#define G0_Synchronized_Gate _bit8
-#define G1_Synchronized_Gate _bit8
-#define G0_Gate_Error_Confirm _bit5
-#define G1_Gate_Error_Confirm _bit1
-#define G0_TC_Error_Confirm _bit6
-#define G1_TC_Error_Confirm _bit2
-#define G0_TC_Interrupt_Ack _bit14
-#define G1_TC_Interrupt_Ack _bit14
-#define G0_Gate_Interrupt_Ack _bit15
-#define G1_Gate_Interrupt_Ack _bit15
-#define G_Autoincrement(a) ((a)<<0)
#define G_Autoincrement(a) ((a)<<0)
-#define G0_Arm _bit0
-#define G1_Arm _bit0
/*Analog_Trigger_Etc_Register*/
#define Analog_Trigger_Mode(x) ((x) & 0x7)
Gi_DMA_Enable_Bit = 0x1,
};
+static inline unsigned MSeries_PFI_Filter_Select_Mask(unsigned channel)
+{
+ return 0x3 << (channel * 2);
+}
+static inline unsigned MSeries_PFI_Filter_Select_Bits(unsigned channel, unsigned filter)
+{
+ return (filter << (channel * 2)) & MSeries_PFI_Filter_Select_Mask(channel);
+}
+
#define M_SERIES_EEPROM_SIZE 1024
typedef struct ni_board_struct{
return 0;
}
+static inline enum ni_gpct_register NITIO_Gi_DMA_Status_Reg(int counter_index)
+{
+ switch(counter_index)
+ {
+ case 0:
+ return NITIO_G0_DMA_Status_Reg;
+ break;
+ case 1:
+ return NITIO_G1_DMA_Status_Reg;
+ break;
+ case 2:
+ return NITIO_G2_DMA_Status_Reg;
+ break;
+ case 3:
+ return NITIO_G3_DMA_Status_Reg;
+ break;
+ default:
+ BUG();
+ break;
+ }
+ return 0;
+}
+
static inline enum ni_gpct_register NITIO_Gi_ABZ_Reg(int counter_index)
{
switch(counter_index)
Gi_Gating_Disabled_Bits = 0x0,
Gi_Level_Gating_Bits = 0x1,
Gi_Rising_Edge_Gating_Bits = 0x2,
- Gi_Falling_Edge_Gating_Bits = 0x2,
+ Gi_Falling_Edge_Gating_Bits = 0x3,
Gi_Gate_On_Both_Edges_Bit = 0x4, /* used in conjunction with rising edge gating mode */
Gi_Trigger_Mode_for_Edge_Gate_Mask = 0x18,
Gi_Edge_Gate_Starts_Stops_Bits = 0x0,
switch(selected_gate)
{
+ case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT:
case NI_GPCT_AI_START2_GATE_SELECT:
case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT:
case NI_GPCT_NEXT_OUT_GATE_SELECT:
switch(ni_m_series_gate_select)
{
- case NI_660x_Source_Pin_i_Gate_Select:
- return NI_GPCT_SOURCE_PIN_i_GATE_SELECT;
+ case NI_M_Series_Timestamp_Mux_Gate_Select:
+ return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT;
break;
- case NI_660x_Gate_Pin_i_Gate_Select:
- return NI_GPCT_GATE_PIN_i_GATE_SELECT;
+ case NI_M_Series_AI_START2_Gate_Select:
+ return NI_GPCT_AI_START2_GATE_SELECT;
break;
- case NI_660x_Next_SRC_Gate_Select:
- return NI_GPCT_NEXT_SOURCE_GATE_SELECT;
+ case NI_M_Series_PXI_Star_Trigger_Gate_Select:
+ return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT;
break;
- case NI_660x_Next_Out_Gate_Select:
+ case NI_M_Series_Next_Out_Gate_Select:
return NI_GPCT_NEXT_OUT_GATE_SELECT;
break;
- case NI_660x_Logic_Low_Gate_Select:
+ case NI_M_Series_AI_START1_Gate_Select:
+ return NI_GPCT_AI_START1_GATE_SELECT;
+ break;
+ case NI_M_Series_Next_SRC_Gate_Select:
+ return NI_GPCT_NEXT_SOURCE_GATE_SELECT;
+ break;
+ case NI_M_Series_Analog_Trigger_Out_Gate_Select:
+ return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT;
+ break;
+ case NI_M_Series_Logic_Low_Gate_Select:
return NI_GPCT_LOGIC_LOW_GATE_SELECT;
break;
default:
BUG();
break;
}
- if(counter_dev->regs[input_select_reg] & Gi_Gate_Polarity_Bit)
+ if(counter_dev->regs[mode_reg] & Gi_Gate_Polarity_Bit)
{
*gate_source |= CR_INVERT;
}
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
comedi_cmd *cmd = &async->cmd;
+ const unsigned command_reg = NITIO_Gi_Command_Reg(counter->counter_index);
/* write alloc the entire buffer */
comedi_buf_write_alloc(async, async->prealloc_bufsz);
-
counter->mite_chan->dir = COMEDI_INPUT;
mite_prep_dma(counter->mite_chan, 32, 32);
+ counter_dev->regs[command_reg] &= ~Gi_Save_Trace_Bit;
+ counter_dev->write_register(counter, counter_dev->regs[command_reg], command_reg);
if(counter_dev->variant == ni_gpct_variant_m_series ||
counter_dev->variant == ni_gpct_variant_660x)
{
counter_dev->regs[gi_dma_config_reg] |= Gi_DMA_Enable_Bit;
counter_dev->regs[gi_dma_config_reg] &= ~Gi_DMA_Write_Bit;
+ counter_dev->regs[gi_dma_config_reg] |= Gi_DMA_Int_Bit;
counter_dev->write_register(counter, counter_dev->regs[gi_dma_config_reg], gi_dma_config_reg);
}
- /*start the MITE*/
mite_dma_arm(counter->mite_chan);
return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
}
counter_dev->regs[gi_dma_config_reg] |= Gi_DMA_Enable_Bit | Gi_DMA_Write_Bit;
counter_dev->write_register(counter, counter_dev->regs[gi_dma_config_reg], gi_dma_config_reg);
}
+ mite_dma_arm(counter->mite_chan);
return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE);
}
retval = -EIO;
}else
{
- ni_tio_reset_count_and_disarm(counter);
if(cmd->flags & CMDF_WRITE)
{
retval = ni_tio_output_cmd(counter, async);
int ni_tio_cancel(struct ni_gpct *counter)
{
struct ni_gpct_device *counter_dev = counter->counter_dev;
- if(counter->mite_chan == NULL)
- {
- return 0;
- }
+
ni_tio_arm(counter, 0, 0);
if(counter_dev->variant == ni_gpct_variant_m_series ||
counter_dev->variant == ni_gpct_variant_660x)
const unsigned gi_dma_config_reg = NITIO_Gi_DMA_Config_Reg(counter->counter_index);
counter_dev->regs[gi_dma_config_reg] &= ~Gi_DMA_Enable_Bit;
+ counter_dev->regs[gi_dma_config_reg] &= ~Gi_DMA_Int_Bit;
counter_dev->write_register(counter, counter_dev->regs[gi_dma_config_reg], gi_dma_config_reg);
}
- mite_dma_disarm(counter->mite_chan);
+ if(counter->mite_chan)
+ {
+ mite_dma_disarm(counter->mite_chan);
+ }
return 0;
}
/* everything after this line is ALPHA */
/**********************************************************/
-/*
- Added by Klaas Gadeyne after implementation of driver for comedi NI
- 660x counter card.
- Please see
- <http://people.mech.kuleuven.ac.be/~kgadeyne/linux/> for more
- information about their use
-*/
-
-// X1 encoding
-#define GPCT_X1 0x01
-// X2 encoding
-#define GPCT_X2 0x02
-// X3 encoding
-#define GPCT_X4 0x04
-// When to take into account the indexpulse:
-#define GPCT_IndexPhaseHighHigh 0
-#define GPCT_IndexPhaseLowHigh 1
-#define GPCT_IndexPhaseLowLow 2
-#define GPCT_IndexPhaseHighLow 3
-// Reset when index pulse arrives?
-#define GPCT_RESET_COUNTER_ON_INDEX 1
-
/*
8254 specific configuration.
enum ni_gpct_gate_select
{
/* m-series gates */
+ NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0,
NI_GPCT_AI_START2_GATE_SELECT = 0x12,
NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13,
NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14,