From 28293b678d2f2dcde1fc4627c92f5c0787b2b882 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Fri, 22 Jun 2007 20:08:14 +0000 Subject: [PATCH] A little more code intended to support counter commands eventually. --- comedi/drivers/ni_mio_common.c | 105 ++++++++++++++++++++++++--------- comedi/drivers/ni_stc.h | 17 ++++-- 2 files changed, 91 insertions(+), 31 deletions(-) diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index f815b8e1..ee4e889e 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -260,8 +260,6 @@ static int ni_ao_reset(comedi_device *dev,comedi_subdevice *s); 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); - 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, @@ -312,6 +310,7 @@ static int ni_ai_drain_dma(comedi_device *dev ); /* DMA channel setup */ +// negative channel means no channel static inline void ni_set_ai_dma_channel(comedi_device *dev, int channel) { unsigned long flags; @@ -327,6 +326,7 @@ static inline void ni_set_ai_dma_channel(comedi_device *dev, int channel) comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); } +// negative channel means no channel static inline void ni_set_ao_dma_channel(comedi_device *dev, int channel) { unsigned long flags; @@ -361,11 +361,10 @@ static inline void ni_set_gpct_dma_channel(comedi_device *dev, unsigned gpct_ind static int ni_request_ai_mite_channel(comedi_device *dev) { unsigned long flags; - static const unsigned max_dma_channel = 5; comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); BUG_ON(devpriv->ai_mite_chan); - devpriv->ai_mite_chan = mite_request_channel_in_range(devpriv->mite, devpriv->ai_mite_ring, 0, max_dma_channel); + devpriv->ai_mite_chan = mite_request_channel(devpriv->mite, devpriv->ai_mite_ring); if(devpriv->ai_mite_chan == NULL) { comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); @@ -380,11 +379,10 @@ static int ni_request_ai_mite_channel(comedi_device *dev) static int ni_request_ao_mite_channel(comedi_device *dev) { unsigned long flags; - static const unsigned max_dma_channel = 5; comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); BUG_ON(devpriv->ao_mite_chan); - devpriv->ao_mite_chan = mite_request_channel_in_range(devpriv->mite, devpriv->ao_mite_ring, 0, max_dma_channel); + devpriv->ao_mite_chan = mite_request_channel(devpriv->mite, devpriv->ao_mite_ring); if(devpriv->ao_mite_chan == NULL) { comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); @@ -396,6 +394,25 @@ static int ni_request_ao_mite_channel(comedi_device *dev) return 0; } +static int ni_request_gpct_mite_channel(comedi_device *dev, unsigned gpct_index) +{ + unsigned long flags; + + BUG_ON(gpct_index >= NUM_GPCT); + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + BUG_ON(devpriv->gpct_mite_chan[gpct_index]); + devpriv->gpct_mite_chan[gpct_index] = mite_request_channel(devpriv->mite, devpriv->gpct_mite_ring[gpct_index]); + if(devpriv->gpct_mite_chan[gpct_index] == NULL) + { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + comedi_error(dev, "failed to reserve mite dma channel for counter."); + return -EBUSY; + } + ni_set_gpct_dma_channel(dev, gpct_index, devpriv->gpct_mite_chan[gpct_index]->channel); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + return 0; +} + #endif // PCIDMA static void ni_release_ai_mite_channel(comedi_device *dev) @@ -434,6 +451,25 @@ static void ni_release_ao_mite_channel(comedi_device *dev) #endif // PCIDMA } +void ni_release_gpct_mite_channel(comedi_device *dev, unsigned gpct_index) +{ +#ifdef PCIDMA + unsigned long flags; + + BUG_ON(gpct_index >= NUM_GPCT); + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if(devpriv->gpct_mite_chan[gpct_index]) + { + ni_set_gpct_dma_channel(dev, gpct_index, -1); + mite_dma_disarm(devpriv->gpct_mite_chan[gpct_index]); + mite_dma_reset(devpriv->gpct_mite_chan[gpct_index]); + mite_release_channel(devpriv->gpct_mite_chan[gpct_index]); + devpriv->gpct_mite_chan[gpct_index] = NULL; + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif // PCIDMA +} + static void ni_clear_ai_fifo(comedi_device *dev){ if(boardtype.reg_type == ni_reg_6143){ // Flush the 6143 data FIFO @@ -1272,7 +1308,7 @@ static void ni_ai_munge(comedi_device *dev, comedi_subdevice *s, #ifdef PCIDMA -static int ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd) +static int ni_ai_setup_MITE_dma(comedi_device *dev) { comedi_subdevice *s = dev->subdevices + 0; int retval; @@ -1303,7 +1339,7 @@ static int ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd) return 0; } -static int ni_ao_setup_MITE_dma(comedi_device *dev, comedi_cmd *cmd) +static int ni_ao_setup_MITE_dma(comedi_device *dev) { comedi_subdevice *s = dev->subdevices + 1; int retval; @@ -1744,27 +1780,30 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan, } } -static int ni_ns_to_timer(comedi_device *dev, int *nanosec, int round_mode) +static int ni_ns_to_timer(const comedi_device *dev, unsigned nanosec, int round_mode) { int divider; switch(round_mode) { case TRIG_ROUND_NEAREST: default: - divider = (*nanosec + devpriv->clock_ns / 2) / devpriv->clock_ns; + divider = (nanosec + devpriv->clock_ns / 2) / devpriv->clock_ns; break; case TRIG_ROUND_DOWN: - divider = (*nanosec) / devpriv->clock_ns; + divider = (nanosec) / devpriv->clock_ns; break; case TRIG_ROUND_UP: - divider=(*nanosec + devpriv->clock_ns - 1) / devpriv->clock_ns; + divider=(nanosec + devpriv->clock_ns - 1) / devpriv->clock_ns; break; } - - *nanosec = devpriv->clock_ns * divider; return divider - 1; } +static unsigned ni_timer_to_ns(const comedi_device *dev, int timer) +{ + return devpriv->clock_ns * (timer + 1); +} + static unsigned ni_min_ai_scan_period_ns(comedi_device *dev, unsigned num_channels) { switch(boardtype.reg_type) @@ -1939,16 +1978,17 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) if(cmd->scan_begin_src==TRIG_TIMER){ tmp=cmd->scan_begin_arg; - ni_ns_to_timer(dev, &cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK); + cmd->scan_begin_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK)); if(tmp!=cmd->scan_begin_arg)err++; } if(cmd->convert_src==TRIG_TIMER){ if((boardtype.reg_type != ni_reg_611x) && (boardtype.reg_type != ni_reg_6143)){ tmp=cmd->convert_arg; - ni_ns_to_timer(dev, &cmd->convert_arg, cmd->flags&TRIG_ROUND_MASK); + cmd->convert_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK)); if(tmp!=cmd->convert_arg)err++; if(cmd->scan_begin_src==TRIG_TIMER && - cmd->scan_begin_argconvert_arg*cmd->scan_end_arg){ + cmd->scan_begin_argconvert_arg*cmd->scan_end_arg) + { cmd->scan_begin_arg=cmd->convert_arg*cmd->scan_end_arg; err++; } @@ -1962,7 +2002,7 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s) { - comedi_cmd *cmd=&s->async->cmd; + const comedi_cmd *cmd=&s->async->cmd; int timer; int mode1=0; /* mode1 is needed for both stop and convert */ int mode2=0; @@ -2093,7 +2133,7 @@ static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s) devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); /* load SI */ - timer = ni_ns_to_timer(dev, &cmd->scan_begin_arg, TRIG_ROUND_NEAREST); + timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, TRIG_ROUND_NEAREST); devpriv->stc_writel(dev, timer,AI_SI_Load_A_Registers); devpriv->stc_writew(dev, AI_SI_Load,AI_Command_1_Register); break; @@ -2117,7 +2157,7 @@ static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s) if( cmd->convert_arg == 0 || cmd->convert_src == TRIG_NOW ) timer = 1; else - timer = ni_ns_to_timer(dev, &cmd->convert_arg, TRIG_ROUND_NEAREST); + timer = ni_ns_to_timer(dev, cmd->convert_arg, TRIG_ROUND_NEAREST); devpriv->stc_writew(dev, 1,AI_SI2_Load_A_Register); /* 0,0 does not work. */ devpriv->stc_writew(dev, timer,AI_SI2_Load_B_Register); @@ -2219,7 +2259,7 @@ static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s) #ifdef PCIDMA { - int retval = ni_ai_setup_MITE_dma(dev,cmd); + int retval = ni_ai_setup_MITE_dma(dev); if(retval) return retval; } //mite_dump_regs(devpriv->mite); @@ -2604,7 +2644,7 @@ static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s, devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); if(boardtype.reg_type & ni_reg_6xxx_mask) ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); - ret = ni_ao_setup_MITE_dma(dev, &s->async->cmd); + ret = ni_ao_setup_MITE_dma(dev); if(ret) return ret; ret = ni_ao_wait_for_dma_load(dev); if(ret < 0) return ret; @@ -2647,7 +2687,7 @@ static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s, static int ni_ao_cmd(comedi_device *dev,comedi_subdevice *s) { - comedi_cmd *cmd = &s->async->cmd; + const comedi_cmd *cmd = &s->async->cmd; int trigvar; int bits; int i; @@ -2657,7 +2697,7 @@ static int ni_ao_cmd(comedi_device *dev,comedi_subdevice *s) comedi_error(dev, "cannot run command without an irq"); return -EIO; } - trigvar = ni_ns_to_timer(dev, &cmd->scan_begin_arg, TRIG_ROUND_NEAREST); + trigvar = ni_ns_to_timer(dev, cmd->scan_begin_arg, TRIG_ROUND_NEAREST); devpriv->stc_writew(dev, AO_Configuration_Start,Joint_Reset_Register); @@ -2874,7 +2914,7 @@ static int ni_ao_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) /* step 4: fix up any arguments */ tmp = cmd->scan_begin_arg; - ni_ns_to_timer(dev, &cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK); + cmd->scan_begin_arg = ni_timer_to_ns(dev, ni_ns_to_timer(dev, cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK)); if(tmp!=cmd->scan_begin_arg)err++; if(err)return 4; @@ -4159,24 +4199,35 @@ static int ni_gpct_insn_write(comedi_device *dev, comedi_subdevice *s, static int ni_gpct_cmd(comedi_device *dev, comedi_subdevice *s) { +// XXX set M_Offset_GX_DMA_Config for m-series #ifdef PCIDMA struct ni_gpct *counter = s->private; + const comedi_cmd *cmd = &s->async->cmd; + int retval = ni_request_gpct_mite_channel(dev, counter->counter_index); + if(retval) + { + comedi_error(dev, "no dma channel available for use by counter"); + return retval; + } return ni_tio_cmd(counter, s->async); #else - return -EIO; + return -ENOTSUPP; #endif } static int ni_gpct_cmdtest(comedi_device *dev, comedi_subdevice *s, comedi_cmd *cmd) { struct ni_gpct *counter = s->private; + //XXX check chanlist_len == 1 return ni_tio_cmdtest(counter); } static int ni_gpct_cancel(comedi_device *dev, comedi_subdevice *s) { struct ni_gpct *counter = s->private; - return ni_tio_cancel(counter); + int retval = ni_tio_cancel(counter); + ni_release_gpct_mite_channel(dev, counter->counter_index); + return retval; } /* diff --git a/comedi/drivers/ni_stc.h b/comedi/drivers/ni_stc.h index b5d31d88..cba372ac 100644 --- a/comedi/drivers/ni_stc.h +++ b/comedi/drivers/ni_stc.h @@ -904,9 +904,9 @@ enum m_series_register_offsets { M_Offset_CDIO_DMA_Select = 0x7, // write M_Offset_SCXI_Status = 0x7, // read - M_Offset_AI_AO_Select = 0x9, // write + M_Offset_AI_AO_Select = 0x9, // write, same offset as e-series M_Offset_SCXI_Serial_Data_In = 0x9, // read - M_Offset_G0_G1_Select = 0xb, + M_Offset_G0_G1_Select = 0xb, // write, same offset as e-series M_Offset_Misc_Command = 0xf, M_Offset_SCXI_Serial_Data_Out = 0x11, M_Offset_SCXI_Control = 0x13, @@ -1252,6 +1252,15 @@ static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel, unsign return (bits >> ((channel % 3) * 5)) & 0x1f; }; +enum MSeries_Gi_DMA_Config_Bits +{ + Gi_DMA_BankSW_Error_Bit = 0x10, + Gi_DMA_Reset_Bit = 0x8, + Gi_DMA_Int_Enable_Bit = 0x4, + Gi_DMA_Write_Bit = 0x2, + Gi_DMA_Enable_Bit = 0x1, +}; + #define M_SERIES_EEPROM_SIZE 1024 typedef struct ni_board_struct{ @@ -1368,10 +1377,10 @@ static ni_board ni_boards[]; struct mite_struct *mite; \ struct mite_channel *ai_mite_chan; \ struct mite_channel *ao_mite_chan;\ - struct mite_channel *gpct_mite_chan[2]; \ + struct mite_channel *gpct_mite_chan[NUM_GPCT]; \ struct mite_dma_descriptor_ring *ai_mite_ring; \ struct mite_dma_descriptor_ring *ao_mite_ring; \ - struct mite_dma_descriptor_ring *gpct_mite_ring[2]; + struct mite_dma_descriptor_ring *gpct_mite_ring[NUM_GPCT]; #endif /* _COMEDI_NI_STC_H */ -- 2.26.2