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,
static const int num_adc_stages_611x = 3;
-static void handle_a_interrupt(comedi_device *dev,unsigned short status,
- unsigned int m_status);
-static void handle_b_interrupt(comedi_device *dev,unsigned short status,
- unsigned int m_status);
+static void handle_a_interrupt(comedi_device *dev, unsigned short status,
+ unsigned ai_mite_status, unsigned gpct0_mite_status);
+static void handle_b_interrupt(comedi_device *dev, unsigned short status,
+ unsigned ao_mite_status, unsigned gpct1_mite_status);
static void get_last_sample_611x( comedi_device *dev );
static void get_last_sample_6143( comedi_device *dev );
#ifdef PCIDMA
/* DMA channel setup */
+// negative channel means no channel
static inline void ni_set_ai_dma_channel(comedi_device *dev, int channel)
{
unsigned long flags;
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;
comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
}
+// negative mite_channel means no channel
+static inline void ni_set_gpct_dma_channel(comedi_device *dev, unsigned gpct_index, int mite_channel)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
+ devpriv->g0_g1_select_reg &= ~GPCT_DMA_Select_Mask(gpct_index);
+ if(mite_channel >= 0)
+ {
+ devpriv->g0_g1_select_reg |= GPCT_DMA_Select_Bits(gpct_index, mite_channel);
+ }
+ ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select);
+ mmiowb();
+ comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
+}
+
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);
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);
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)
comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if(devpriv->ai_mite_chan)
{
+ ni_set_ai_dma_channel(dev, -1);
+ mite_dma_disarm(devpriv->ai_mite_chan);
+ mite_dma_reset(devpriv->ai_mite_chan);
mite_release_channel(devpriv->ai_mite_chan);
devpriv->ai_mite_chan = NULL;
- ni_set_ai_dma_channel(dev, -1);
}
comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
#endif // PCIDMA
comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if(devpriv->ao_mite_chan)
{
+ ni_set_ao_dma_channel(dev, -1);
+ mite_dma_disarm(devpriv->ao_mite_chan);
+ mite_dma_reset(devpriv->ao_mite_chan);
mite_release_channel(devpriv->ao_mite_chan);
devpriv->ao_mite_chan = NULL;
- ni_set_ao_dma_channel(dev, -1);
+ }
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
+#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
unsigned short b_status;
unsigned int ai_mite_status = 0;
unsigned int ao_mite_status = 0;
+ unsigned gpct0_mite_status = 0;
+ unsigned gpct1_mite_status = 0;
unsigned long flags;
-#ifdef PCIDMA
struct mite_struct *mite = devpriv->mite;
-#endif
if(dev->attached == 0) return IRQ_NONE;
+ smp_mb(); // make sure dev->attached is checked before handler does anything else.
+
// lock to avoid race with comedi_poll
comedi_spin_lock_irqsave(&dev->spinlock, flags);
- a_status=devpriv->stc_readw(dev, AI_Status_1_Register);
- b_status=devpriv->stc_readw(dev, AO_Status_1_Register);
-#ifdef PCIDMA
- if(devpriv->ai_mite_chan)
- ai_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ai_mite_chan->channel));
- if(devpriv->ao_mite_chan)
- ao_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ao_mite_chan->channel));
-#endif
-
- 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 )
- handle_b_interrupt(dev, b_status, ao_mite_status);
+ a_status = devpriv->stc_readw(dev, AI_Status_1_Register);
+ b_status = devpriv->stc_readw(dev, AO_Status_1_Register);
+ if(mite)
+ {
+ unsigned long flags_too;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
+ if(devpriv->ai_mite_chan)
+ ai_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ai_mite_chan->channel));
+ if(devpriv->ao_mite_chan)
+ ao_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->ao_mite_chan->channel));
+ if(devpriv->gpct_mite_chan[0])
+ gpct0_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->gpct_mite_chan[0]->channel));
+ if(devpriv->gpct_mite_chan[1])
+ gpct1_mite_status = readl(mite->mite_io_addr + MITE_CHSR(devpriv->gpct_mite_chan[1]->channel));
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too);
+ }
+ if((a_status & Interrupt_A_St) || ((ai_mite_status | gpct0_mite_status) & CHSR_INT))
+ handle_a_interrupt(dev, a_status, ai_mite_status, gpct0_mite_status);
+ if((b_status & Interrupt_B_St) || ((ao_mite_status | gpct1_mite_status) & CHSR_INT))
+ handle_b_interrupt(dev, b_status, ao_mite_status, gpct1_mite_status);
comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
return IRQ_HANDLED;
}
static void ni_sync_ai_dma(comedi_device *dev)
{
comedi_subdevice *s = dev->subdevices + 0;
- int retval;
+ unsigned long flags;
- if(devpriv->ai_mite_chan == NULL) return;
- retval = mite_sync_input_dma(devpriv->ai_mite_chan, s->async);
- if(retval < 0)
- {
- ni_ai_reset(dev,s);
- return;
- }
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ if(devpriv->ai_mite_chan)
+ mite_sync_input_dma(devpriv->ai_mite_chan, s->async);
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
}
static void mite_handle_b_linkc(struct mite_struct *mite, comedi_device *dev)
if(mite_sync_output_dma(devpriv->ao_mite_chan, s->async) < 0)
{
- ni_ao_reset(dev, s);
+ s->async->events |= COMEDI_CB_ERROR;
return;
}
}
/* handle special case of single scan using AI_End_On_End_Of_Scan */
if((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)){
shutdown_ai_command( dev );
- ni_ai_reset(dev, s);
}
}
#ifdef PCIDMA
ni_ai_drain_dma( dev );
- if(devpriv->ai_mite_chan)
- {
- mite_dma_disarm(devpriv->ai_mite_chan);
- }
#endif
ni_handle_fifo_dregs(dev);
get_last_sample_611x(dev);
get_last_sample_6143(dev);
- ni_set_bits(dev, Interrupt_A_Enable_Register,
- AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable|
- AI_START2_Interrupt_Enable| AI_START_Interrupt_Enable|
- AI_STOP_Interrupt_Enable| AI_Error_Interrupt_Enable|
- AI_FIFO_Interrupt_Enable,0);
-
s->async->events |= COMEDI_CB_EOA;
}
-static void handle_a_interrupt(comedi_device *dev,unsigned short status,
- unsigned int m_status)
+static void handle_gpct_interrupt(comedi_device *dev, struct mite_channel *mite_chan, unsigned short is_terminal_count)
+{
+ unsigned gpct_mite_status;
+
+ gpct_mite_status = readl(mite_chan->mite->mite_io_addr + MITE_CHSR(mite_chan->channel));
+ if(gpct_mite_status & CHSR_INT)
+ {}
+}
+
+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);
+}
+
+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;
+ }
+ if(a_status & AI_START1_St)
+ {
+ ack |= AI_START1_Interrupt_Ack;
+ }
+ if(a_status & AI_START_St)
+ {
+ ack |= AI_START_Interrupt_Ack;
+ }
+ if(a_status & AI_STOP_St)
+ {
+ /* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */
+ ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack*/;
+ }
+ if(a_status & G0_TC_St)
+ {
+ ack |= G0_TC_Interrupt_Ack;
+ }
+ if(a_status & G0_Gate_Interrupt_St)
+ {
+ ack |= G0_Gate_Interrupt_Ack;
+ }
+ if(ack) devpriv->stc_writew(dev, ack, Interrupt_A_Ack_Register);
+}
+
+static void handle_a_interrupt(comedi_device *dev, unsigned short status,
+ unsigned ai_mite_status, unsigned gpct0_mite_status)
{
comedi_subdevice *s=dev->subdevices+0;
- unsigned short ack=0;
s->async->events = 0;
#ifdef DEBUG_INTERRUPT
- rt_printk("ni_mio_common: interrupt: a_status=%04x m0_status=%08x\n",
- status, m_status);
+ 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(m_status & CHSR_LINKC){
+ if(ai_mite_status & CHSR_LINKC){
writel(CHOR_CLRLC, devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->ai_mite_chan->channel));
ni_sync_ai_dma(dev);
}
- if(m_status & CHSR_DONE){
+ if(ai_mite_status & CHSR_DONE){
writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->ai_mite_chan->channel));
}
- if(m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)){
- rt_printk("unknown mite interrupt, ack! (m_status=%08x)\n", m_status);
- //mite_print_chsr(m_status);
- mite_dma_disarm(devpriv->ai_mite_chan);
- mite_dma_reset(devpriv->ai_mite_chan);
+ if(ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)){
+ rt_printk("unknown mite interrupt, ack! (ai_mite_status=%08x)\n", ai_mite_status);
+ //mite_print_chsr(ai_mite_status);
+ s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
//disable_irq(dev->irq);
}
#endif
* so it's a good idea to be careful. */
if(s->subdev_flags&SDF_RUNNING){
s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
- comedi_event(dev,s,s->async->events);
+ ni_event(dev, s, s->async->events);
}
return;
}
status);
ni_mio_print_status_a(status);
- ni_ai_reset(dev,dev->subdevices);
-
-
shutdown_ai_command( dev );
s->async->events |= COMEDI_CB_ERROR;
if(status & (AI_Overrun_St | AI_Overflow_St))
s->async->events |= COMEDI_CB_OVERFLOW;
- comedi_event(dev,s,s->async->events);
+ ni_event(dev, s, s->async->events);
return;
}
rt_printk("ni_mio_common: SC_TC interrupt\n");
#endif
if(!devpriv->ai_continuous){
- shutdown_ai_command( dev );
+ shutdown_ai_command(dev);
}
- ack|=AI_SC_TC_Interrupt_Ack;
- }
- if(status&AI_START1_St){
- ack|=AI_START1_Interrupt_Ack;
}
}
#ifndef PCIDMA
if( (status & AI_STOP_St) ){
ni_handle_eos(dev, s);
- /* we need to ack the START, also */
- ack |= AI_STOP_Interrupt_Ack|AI_START_Interrupt_Ack;
}
-#if 0
- if(devpriv->aimode==AIMODE_SAMPLE){
- ni_handle_fifo_dregs(dev);
- //s->async->events |= COMEDI_CB_SAMPLE;
+ if(status & (G0_TC_St | G0_Gate_Interrupt_St))
+ {
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
+ if(devpriv->gpct_mite_chan)
+ handle_gpct_interrupt(dev, devpriv->gpct_mite_chan[0], (status & G0_TC_St));
+ comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
}
-#endif
- if(ack) devpriv->stc_writew(dev, ack,Interrupt_A_Ack_Register);
- comedi_event(dev,s,s->async->events);
+
+ ni_event(dev,s,s->async->events);
#ifdef DEBUG_INTERRUPT
status=devpriv->stc_readw(dev, AI_Status_1_Register);
#endif
}
-static void handle_b_interrupt(comedi_device *dev,unsigned short b_status, unsigned int m_status)
+static void ack_b_interrupt(comedi_device *dev, unsigned short b_status)
+{
+ unsigned short ack = 0;
+ if(b_status & AO_BC_TC_St)
+ {
+ ack |= AO_BC_TC_Interrupt_Ack;
+ }
+ if(b_status & AO_Overrun_St)
+ {
+ ack |= AO_Error_Interrupt_Ack;
+ }
+ if(b_status & AO_START_St)
+ {
+ ack |= AO_START_Interrupt_Ack;
+ }
+ if(b_status & AO_START1_St)
+ {
+ ack |= AO_START1_Interrupt_Ack;
+ }
+ if(b_status & AO_UC_TC_St)
+ {
+ ack |= AO_UC_TC_Interrupt_Ack;
+ }
+ if(b_status & AO_UI2_TC_St)
+ {
+ ack |= AO_UI2_TC_Interrupt_Ack;
+ }
+ if(b_status & AO_UPDATE_St)
+ {
+ ack |= AO_UPDATE_Interrupt_Ack;
+ }
+ if(b_status & G1_Gate_Interrupt_St)
+ {
+ ack |= G1_Gate_Interrupt_Ack;
+ }
+ if(b_status & G1_TC_St)
+ {
+ ack |= G1_TC_Interrupt_Ack;
+ }
+ if(ack) devpriv->stc_writew(dev, ack, Interrupt_B_Ack_Register);
+}
+
+static void handle_b_interrupt(comedi_device *dev, unsigned short b_status,
+ unsigned ao_mite_status, unsigned gpct1_mite_status)
{
comedi_subdevice *s=dev->subdevices+1;
//unsigned short ack=0;
#ifdef DEBUG_INTERRUPT
rt_printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n",
- b_status,m_status);
+ 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 */
- if(m_status & CHSR_LINKC){
+ if(ao_mite_status & CHSR_LINKC){
mite_handle_b_linkc(devpriv->mite, dev);
}
- if(m_status & CHSR_DONE){
+ if(ao_mite_status & CHSR_DONE){
writel(CHOR_CLRDONE, devpriv->mite->mite_io_addr + MITE_CHOR(devpriv->ao_mite_chan->channel));
}
- if(m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)){
- rt_printk("unknown mite interrupt, ack! (m_status=%08x)\n", m_status);
- //mite_print_chsr(m_status);
- mite_dma_disarm(devpriv->ao_mite_chan);
- mite_dma_reset(devpriv->ao_mite_chan);
+ if(ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)){
+ rt_printk("unknown mite interrupt, ack! (ao_mite_status=%08x)\n", ao_mite_status);
+ //mite_print_chsr(ao_mite_status);
+ s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
}
#endif
if(b_status==0xffff)return;
if(b_status&AO_Overrun_St){
rt_printk("ni_mio_common: AO FIFO underrun status=0x%04x status2=0x%04x\n",b_status,devpriv->stc_readw(dev, AO_Status_2_Register));
- ni_ao_reset(dev,s);
s->async->events |= COMEDI_CB_OVERFLOW;
}
if(b_status&AO_BC_TC_St){
MDPRINTK("ni_mio_common: AO BC_TC status=0x%04x status2=0x%04x\n",b_status,devpriv->stc_readw(dev, AO_Status_2_Register));
- ni_ao_reset(dev,s);
s->async->events |= COMEDI_CB_EOA;
}
}
#endif
- b_status=devpriv->stc_readw(dev, AO_Status_1_Register);
- if(b_status&Interrupt_B_St){
- if(b_status&AO_FIFO_Request_St){
- rt_printk("ni_mio_common: AO buffer underrun\n");
- }
- rt_printk("Ack! didn't clear AO interrupt. b_status=0x%04x\n",b_status);
- ni_set_bits(dev,Interrupt_B_Enable_Register,~0,0);
- ni_ao_reset(dev,s);
- s->async->events |= COMEDI_CB_OVERFLOW;
- }
-
- comedi_event(dev,s,s->async->events);
+ ni_event(dev,s,s->async->events);
}
#ifdef DEBUG_STATUS_A
#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;
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;
/* read alloc the entire buffer */
comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz);
- /* Barrier is intended to insure comedi_buf_read_alloc
- is done touching the async struct before we write
- to the mite's registers and arm it. */
- smp_wmb();
devpriv->ao_mite_chan->dir = COMEDI_OUTPUT;
if(boardtype.reg_type & (ni_reg_611x | ni_reg_6713))
static int ni_ai_reset(comedi_device *dev,comedi_subdevice *s)
{
-#ifdef PCIDMA
- if(devpriv->ai_mite_chan)
- {
- mite_dma_disarm(devpriv->ai_mite_chan);
- }
-#endif
+ ni_release_ai_mite_channel(dev);
/* ai configuration */
devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset, Joint_Reset_Register);
}
}
-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)
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_arg<cmd->convert_arg*cmd->scan_end_arg){
+ cmd->scan_begin_arg<cmd->convert_arg*cmd->scan_end_arg)
+ {
cmd->scan_begin_arg=cmd->convert_arg*cmd->scan_end_arg;
err++;
}
return 0;
}
-static void ni_ai_cmd_cleanup(comedi_device *dev, comedi_subdevice *s)
-{
- ni_release_ai_mite_channel(dev);
-}
-
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;
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;
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);
#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);
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;
return 0;
}
-static void ni_ao_cmd_cleanup(comedi_device *dev,comedi_subdevice *s)
-{
- ni_release_ao_mite_channel(dev);
-}
-
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;
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);
bits |= AO_FIFO_Enable;
else
bits |= AO_DMA_PIO_Control;
+#if 0
+ /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281,
+ verified with bus analyzer. */
if(boardtype.reg_type & ni_reg_m_series_mask)
- bits |= AO_Number_Of_DAC_Packages/* | AO_Multiple_DACS_Per_Package*/;
+ bits |= AO_Number_Of_DAC_Packages;
+#endif
devpriv->stc_writew(dev, bits, AO_Personal_Register);
// enable sending of ao dma requests
devpriv->stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register);
cmd->start_arg=0;
err++;
}
-#if 0
- /* XXX need ao_speed */
- if(cmd->scan_begin_arg<boardtype.ao_speed){
- cmd->scan_begin_arg=boardtype.ao_speed;
+ if(cmd->scan_begin_arg < boardtype.ao_speed){
+ cmd->scan_begin_arg = boardtype.ao_speed;
err++;
}
-#endif
- if(cmd->scan_begin_arg>devpriv->clock_ns*0xffffff){ /* XXX check */
- cmd->scan_begin_arg=devpriv->clock_ns*0xffffff;
+ if(cmd->scan_begin_arg > devpriv->clock_ns * 0xffffff){ /* XXX check */
+ cmd->scan_begin_arg = devpriv->clock_ns * 0xffffff;
err++;
}
if(cmd->convert_arg!=0){
/* 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;
//devpriv->ao1p=AO_Channel(1);
//ni_writew(devpriv->ao1p,AO_Configuration);
-#ifdef PCIDMA
- if(devpriv->ao_mite_chan)
- {
- mite_dma_disarm(devpriv->ao_mite_chan);
- mite_dma_reset(devpriv->ao_mite_chan);
- }
-#endif
+ ni_release_ao_mite_channel(dev);
devpriv->stc_writew(dev, AO_Configuration_Start,Joint_Reset_Register);
devpriv->stc_writew(dev, AO_Disarm,AO_Command_1_Register);
case NITIO_G1_Second_Gate_Reg:
ni_writew(bits, M_Offset_G1_Second_Gate);
break;
+ case NITIO_G0_ABZ_Reg:
+ ni_writew(bits, M_Offset_G0_MSeries_ABZ);
+ break;
+ case NITIO_G1_ABZ_Reg:
+ ni_writew(bits, M_Offset_G1_MSeries_ABZ);
+ break;
+
/* 32 bit registers */
case NITIO_G0_LoadA_Reg:
case NITIO_G1_LoadA_Reg:
s->insn_config = &ni_ai_insn_config;
s->do_cmdtest = &ni_ai_cmdtest;
s->do_cmd = &ni_ai_cmd;
- s->cmd_cleanup = &ni_ai_cmd_cleanup;
s->cancel = &ni_ai_reset;
s->poll = &ni_ai_poll;
s->munge = &ni_ai_munge;
dev->write_subdev=s;
s->subdev_flags |= SDF_CMD_WRITE;
s->do_cmd = &ni_ao_cmd;
- s->cmd_cleanup = &ni_ao_cmd_cleanup;
s->do_cmdtest = &ni_ao_cmdtest;
s->len_chanlist = boardtype.n_aochan;
if((boardtype.reg_type & ni_reg_m_series_mask) == 0)
s->maxdata=1;
s->io_bits=0; /* all bits input */
s->range_table=&range_digital;
+ s->n_chan = boardtype.num_p0_dio_channels;
if(boardtype.reg_type & ni_reg_m_series_mask)
{
- s->n_chan = 32;
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->n_chan=8;
s->insn_bits=ni_dio_insn_bits;
s->insn_config=ni_dio_insn_config;
devpriv->dio_control = DIO_Pins_Dir(s->io_bits);
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;
}
/*