Added some ack'ing of b interrupts, and do acks before handling
authorFrank Mori Hess <fmhess@speakeasy.net>
Fri, 6 Jul 2007 17:08:58 +0000 (17:08 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Fri, 6 Jul 2007 17:08:58 +0000 (17:08 +0000)
interrupts, to avoid a race (which seems possible in theory).

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

index 4caaf5add0fe7e0560442e1fc87a84b5bf29fa29..0bab766abd9250b0eb5a673556e3f17d5c6c920c 100644 (file)
@@ -767,11 +767,43 @@ static void ni_event(comedi_device *dev, comedi_subdevice *s, unsigned events)
        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;
 
@@ -780,8 +812,7 @@ static void handle_a_interrupt(comedi_device *dev, unsigned short status,
                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){
@@ -835,10 +866,6 @@ static void handle_a_interrupt(comedi_device *dev, unsigned short status,
                        if(!devpriv->ai_continuous){
                                shutdown_ai_command(dev);
                        }
-                       ack|=AI_SC_TC_Interrupt_Ack;
-               }
-               if(status&AI_START1_St){
-                       ack|=AI_START1_Interrupt_Ack;
                }
        }
 #ifndef PCIDMA
@@ -858,18 +885,8 @@ static void handle_a_interrupt(comedi_device *dev, unsigned short status,
 
        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(status & G0_TC_St)
-       {
-               ack |= G0_TC_Interrupt_Ack;
-       }
-       if(status & G0_Gate_Interrupt_St)
-       {
-               ack |= G0_Gate_Interrupt_Ack;
-       }
        if(status & (G0_TC_St | G0_Gate_Interrupt_St))
        {
                unsigned long flags;
@@ -880,7 +897,6 @@ static void handle_a_interrupt(comedi_device *dev, unsigned short status,
                comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
        }
 
-       if(ack) devpriv->stc_writew(dev, ack,Interrupt_A_Ack_Register);
        ni_event(dev,s,s->async->events);
 
 #ifdef DEBUG_INTERRUPT
@@ -891,6 +907,48 @@ static void handle_a_interrupt(comedi_device *dev, unsigned short status,
 #endif
 }
 
+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)
 {
@@ -901,7 +959,7 @@ static void handle_b_interrupt(comedi_device *dev, unsigned short b_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 */
@@ -3377,7 +3435,7 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum
        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:
index cba372acfd7885a46742bc47918fb07633803698..89f2b33deb8df25bbeb7a476f895a0d493186952 100644 (file)
 #define Interrupt_B_Ack_Register       3
 enum Interrupt_B_Ack_Bits
 {
+       G1_Gate_Error_Confirm = _bit1,
+       G1_TC_Error_Confirm = _bit2,
+       AO_BC_TC_Trigger_Error_Confirm = _bit3,
+       AO_BC_TC_Error_Confirm = _bit4,
+       AO_UI2_TC_Error_Confrim = _bit5,
+       AO_UI2_TC_Interrupt_Ack = _bit6,
+       AO_UC_TC_Interrupt_Ack = _bit7,
        AO_BC_TC_Interrupt_Ack = _bit8,
+       AO_START1_Interrupt_Ack = _bit9,
+       AO_UPDATE_Interrupt_Ack = _bit10,
+       AO_START_Interrupt_Ack = _bit11,
+       AO_STOP_Interrupt_Ack = _bit12,
        AO_Error_Interrupt_Ack = _bit13,
+       G1_TC_Interrupt_Ack = _bit14,
+       G1_Gate_Interrupt_Ack = _bit15
 };
 
 #define AO_Status_1_Register           3