Examining the QNX RTOS 6.1
by Bart Van Beneden 

Listing One
/****************************************************************************/
/*** This test program installs two interrupt handlers; one hooking into ***/
/*** into IRQ9, the other one into IRQ10.                                ***/
/*** Both interrupts simultaneously generated by two PCI bus exersizers. ***/
/*** This test program measures the time the system needs to react to    ***/
/*** both interrupts. By adding a small delay between the interrupts,    ***/
/*** this program can also be used to verify that the interrupt handling ***/
/*** is prioritized, and that the handlers can be nested.                ***/ 
/****************************************************************************/

/* Include files */
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <sys/neutrino.h>
#include <sched.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <semaphore.h>
#include <stdlib.h>
#include "trace.h"

/* Defintion of some constants */
#define PCI_MEMORY   0xE1000000
#define P_DRIVE_1    0xE1100000
#define P_DRIVE_2    0xE1200000
#define PCI_IRQ_1    0x09
#define PCI_IRQ_2    0x0a

/* Global variables */
unsigned long*    pulp_trace;               // PCI_MEMORY
unsigned long*    pulp_pdrive_1;            // P_DRIVE_1
unsigned long*    pulp_pdrive_2;            // P_DRIVE_2
int               iFlag1, iFlag2;

/* Function prototypes */
const struct sigevent*  isr_handler_1(void* pvp_arg,int id);
const struct sigevent*  isr_handler_2(void* pvp_arg,int id);

/***************************************************************************/
/*** The main program entry. This function sets up the interrupt handlers **/
/*** and initializes the hardware.                                        **/
/***************************************************************************/
void main()
{
   int nb_trace,  i_status, i, l, b;
   /* Set this thread to highest priority */
   setprio( 0, 63 );
   /* Map the PCI memory into this thread's virtual address space */
   pulp_trace = (unsigned long*) mmap(0, 4, PROT_READ | 
                 PROT_WRITE,MAP_PHYS | MAP_SHARED, NOFD, PCI_MEMORY);
   /* Map the P_drive_1 into this thread's virtual address space */
   pulp_pdrive_1 = (unsigned long*) mmap( 0, 4, PROT_READ | 
                 PROT_WRITE,MAP_PHYS | MAP_SHARED, NOFD, P_DRIVE_1);
   /* Map the P_drive_2 into this thread's virtual address space */
   pulp_pdrive_2 = (unsigned long*) mmap( 0, 4, PROT_READ | 
                 PROT_WRITE,MAP_PHYS | MAP_SHARED, NOFD, P_DRIVE_2);
   /* Initialise P-Drive-1 */
   *(pulp_pdrive_1 + 0x68/4) = INIT_CODE_PDRIVE;
   *(pulp_pdrive_1 + 0x60/4) = 0x01;

   /* Initialise P-Drive-2 */
   *(pulp_pdrive_2 + 0x68/4) = INIT_CODE_PDRIVE;
   *(pulp_pdrive_2 + 0x60/4) = 0x01;

   /* Enable I/O privilege. You need to have root privileges */
   /* to execute this */
   ThreadCtl(_NTO_TCTL_IO, 0);

   /* Attach the high-priority ISR */
   i_status= InterruptAttach(PCI_IRQ_1, isr_handler_1 , NULL, 0, 0);
   if(i_status==-1) printf(" error attaching ISR-1");

   /* Attach the low-priority ISR */
   i_status= InterruptAttach(PCI_IRQ_2, isr_handler_2 , NULL, 0, 0);
   if(i_status==-1) printf(" error attaching ISR-2");

   /* Enable interrupts */
   InterruptEnable();
   sleep(1);

   /* Generate interrupts */
   for(;;)
   {
      /* Write 1 to PDRive mailbox register 0 to generate interrupt */
      *( pulp_pdrive_1 + ( 0x40/4 ) )= 0x01;    
      *( pulp_pdrive_2 + ( 0x40/4 ) )= 0x01;

      /* Write traces to PCI bus to calculate interrupt latencies   */
      /* Write the only until the interrupts have been serviced.    */ 
      /* This prevents the trace buffer from filling up immediately */
      for(i=0; i<250; i++)
      {
         *pulp_trace = MAIN_LOOP_TRACE;
         if((iFlag1==1)&&(iFlag2==1)) break;
      }
      /* Dummy loop to create a busy delay */
      for(l=0; l<2000; l++)
      {
         i = i << (b+5*3); b++;
      }
      iFlag1=0;
      iFlag2=0;
   }
   exit(0);
}
/***************************************************************************/
/*** The interrupt handler that is hooked to IRQ9                        ***/
/***************************************************************************/
const struct sigevent* isr_handler_1(void* pvp_arg, int id)
{
   /* Write the trace to get interrupt latency and re-init the PDrive */
   *pulp_trace    = ISR1_TRACE;
   *(pulp_pdrive_1 + (0x64/4)) = 0x1;
   iFlag1 = 1;
   return 0; 
}
/***************************************************************************/
/*** The interrupt handler that is hooked to IRQ10                       ***/
/***************************************************************************/
const struct sigevent* isr_handler_2(void* pvp_arg, int id)
{
   /* Write the trace to get interrupt latency and re-init the PDrive */
   *pulp_trace    = ISR2_TRACE;
   *(pulp_pdrive_2 + (0x64/4)) = 0x1;
   iFlag2 = 1;
   return 0; 
}





3

