Index: pcmmio/ChangeLog
===================================================================
--- pcmmio/ChangeLog	(revision 396c14396bb6880de57e3c2f5d6be3122c83490a)
+++ pcmmio/ChangeLog	(revision 03aa739f63099ec461aa2828e5fa2b3a413a80d6)
@@ -1,2 +1,7 @@
+2011-10-05	Joel Sherrill <joel.sherrill@oarcorp.com>
+
+	* mio_io_rtems.c, multiio_pcmmio.c: Rework interrupt handler to reduce
+	overhead per pin change.
+
 2011-10-05	Cindy Cicalese <cicalese@mitre.org>
 
Index: pcmmio/mio_io_rtems.c
===================================================================
--- pcmmio/mio_io_rtems.c	(revision 396c14396bb6880de57e3c2f5d6be3122c83490a)
+++ pcmmio/mio_io_rtems.c	(revision 03aa739f63099ec461aa2828e5fa2b3a413a80d6)
@@ -32,9 +32,11 @@
 /* Function prototypes for local functions */
 static int get_buffered_int(
-  unsigned long long *timestamp
+  struct timespec *timestamp
 );
 static void init_io(unsigned short io_address);
 static void clr_int(int bit_number);
 static int get_int(void);
+
+int report_dio_ints(void);
 
 /* RTEMS Ids for Wait Queues */
@@ -53,6 +55,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 typedef struct {
-  unsigned long long timestamp;
-  int                pin;
+  struct timespec timestamp;
+  int             pin;
 } din_message_t;
 
@@ -340,5 +342,5 @@
 
 int dio_get_int_with_timestamp(
-  unsigned long long *timestamp
+  struct timespec *timestamp
 )
 {
@@ -405,6 +407,6 @@
 
 int wait_dio_int_with_timestamp(
-  int                 milliseconds,
-  unsigned long long *timestamp
+  int              milliseconds,
+  struct timespec *timestamp
 )
 {
@@ -426,10 +428,10 @@
   );
   if ( rc == RTEMS_UNSATISFIED ) {
+    mio_error_code = MIO_READ_DATA_FAILURE;
+    return -1;
+  }
+
+  if ( rc == RTEMS_TIMEOUT ) {
     mio_error_code = MIO_TIMEOUT_ERROR;
-    return -1;
-  }
-
-  if ( rc == RTEMS_TIMEOUT ) {
-    mio_error_code = MIO_READ_DATA_FAILURE;
     return -1;
   }
@@ -536,4 +538,6 @@
   if ( rc == RTEMS_SUCCESSFUL )
     return 0;
+
+  mio_error_code = MIO_TIMEOUT_ERROR;
   return -1;
 }
@@ -543,8 +547,7 @@
 )
 {
-  rtems_status_code rc;
-  uint32_t          unblocked;
-
-  rc = rtems_barrier_release(*id, &unblocked);
+  uint32_t  unblocked;
+
+  (void) rtems_barrier_release(*id, &unblocked);
 }
 
@@ -636,4 +639,11 @@
   if ( base_port && irq ) {
     int status = 0;
+
+    /*
+     *  Process any pending interrupts
+     */
+
+    common_handler();
+
     pcmmio_irq.name = irq;
     #if defined(BSP_SHARED_HANDLER_SUPPORT)
@@ -650,6 +660,4 @@
 }
 
-#include <libcpu/cpuModel.h> /* for rdtsc */
-
 /*
  *  From this point down, we should be able to share easily with the Linux
@@ -668,12 +676,14 @@
 {
   unsigned char status;
+#if 0
   unsigned char int_num;
+#endif
 
   /* Read the interrupt ID register from ADC2 */
-
   adc2_port_image = adc2_port_image | 0x20;
   outb(adc2_port_image,base_port + 0x0f);
 
   status = inb(base_port + 0x0f);
+#if !defined(PCMMIO_DISABLE_ADC_IRQ)
   if (status & 1) {
     /* Clear ADC1 interrupt */
@@ -699,14 +709,19 @@
     wake_up_interruptible(&wq_dac_1);
   }
+#endif
 
   if (status & 8) {
 
+#if 1
+    report_dio_ints();
+#else
     /* DIO interrupt. Find out which bit */
-    while ((int_num = get_int()) != 0) {
+    int_num = get_int();
+    if (int_num) {
       rtems_status_code  rc;
       din_message_t      din;
 
-      din.timestamp = rdtsc(); 
-      din.pin       = int_num; 
+      rtems_clock_get_uptime( &din.timestamp );
+      din.pin = int_num; 
 
       rc = rtems_message_queue_send( wq_dio, &din, sizeof(din_message_t) );
@@ -724,4 +739,5 @@
       clr_int(int_num);
     }
+#endif
   }
 
@@ -846,4 +862,102 @@
 }
 
+void report_dio_interrupt(
+  din_message_t   *din,
+  int              pin
+)
+{
+  rtems_status_code  rc;
+
+  din->pin = pin; 
+
+  rc = rtems_message_queue_send( wq_dio, &din, sizeof(din_message_t) );
+  if ( rc != RTEMS_SUCCESSFUL ) {
+    pcmmio_dio_missed_interrupts++;
+    #ifdef DEBUG
+      printk("<1>Missed DIO interrupt\n" );
+    #endif
+ }
+ #ifdef DEBUG
+   printk("<1>Buffering DIO interrupt on bit %d\n",int_num);
+ #endif
+
+  /* Clear the interrupt */
+  clr_int(pin);
+}
+
+int report_dio_ints(void)
+{
+  int                temp;
+  int                x;
+  unsigned short     dio_port;
+  din_message_t      din;
+  bool               found = false;
+
+  rtems_clock_get_uptime( &din.timestamp );
+  /* din.pin set in report_dio_interrupts() */
+
+  dio_port = base_port + 0x10;
+
+  /* Read the master interrupt pending register,
+           mask off undefined bits */
+  temp = inb(dio_port+6) & 0x07;
+
+  /* If there are no pending interrupts, return 0 */
+  if ((temp & 7) == 0)
+    return 0;
+
+  /* There is something pending, now we need to identify it */
+
+  /* Set access to page 3 for interrupt id register */
+  outb(0xc0, dio_port + 7);
+
+  /* Read the interrupt ID register for port 0 */
+  temp = inb(dio_port+8);
+
+  /* See if any bit set, if so return the bit number */
+  for (x=0; temp && x<=7; x++) {
+    if (temp & (1 << x)) {
+      outb(0,dio_port+7);
+      report_dio_interrupt( &din, x+1 );
+      found = true;
+      temp &= ~(1 << x);
+    }
+  }
+
+  /* Now check port 0, read port 1 interrupt ID register */
+  temp = inb(dio_port+9);
+
+  /* See if any bit set, if so return the bit number */
+  for (x=0; temp && x<=7; x++) {
+    if (temp & (1 << x)) {
+      outb(0,dio_port+7);
+      report_dio_interrupt( &din, x+9 );
+      found = true;
+      temp &= ~(1 << x);
+    }
+  }
+
+  /* Now read the status of port 2 interrupt ID register */
+  temp = inb(dio_port+0x0a);
+
+  /* If any pending, return the appropriate bit number */
+  for (x=0; temp && x<=7; x++) {
+    if (temp & (1 << x)) {
+      outb(0,dio_port+7);
+      report_dio_interrupt( &din, x+17 );
+      temp &= ~(1 << x);
+      found = true;
+    }
+  }
+
+  /* We should never get here unless the hardware is seriously
+     misbehaving, but just to be sure, we'll turn the page access
+     back to 0 and return a 0 for no interrupt found
+  */
+  if ( !found )
+    outb(0,dio_port+7);
+  return 0;
+}
+
 void flush_buffered_ints(void)
 {
@@ -859,5 +973,5 @@
 
 int get_buffered_int(
-  unsigned long long *timestamp
+  struct timespec *timestamp
 )
 {
@@ -881,6 +995,8 @@
     0
   );
-  if ( rc == RTEMS_UNSATISFIED )
+  if ( rc == RTEMS_UNSATISFIED ) {
+    mio_error_code = MIO_READ_DATA_FAILURE;
     return 0;
+  }
 
   if ( rc != RTEMS_SUCCESSFUL ) {
Index: pcmmio/multiio_pcmmio.c
===================================================================
--- pcmmio/multiio_pcmmio.c	(revision 396c14396bb6880de57e3c2f5d6be3122c83490a)
+++ pcmmio/multiio_pcmmio.c	(revision 03aa739f63099ec461aa2828e5fa2b3a413a80d6)
@@ -112,7 +112,5 @@
 )
 {
-  rtems_status_code sc;
-
-  sc = wait_dio_int_with_timestamp(milliseconds, timestamp);
+  (void) wait_dio_int_with_timestamp(milliseconds, timestamp);
   return 0;
 }
