Attaching an interrupt handler

To attach to an interrupt source, you'd use either InterruptAttach() or InterruptAttachEvent().

#include <sys/neutrino.h>

int
InterruptAttachEvent (int intr,
                      const struct sigevent *event,
                      unsigned flags);

int
InterruptAttach (int intr,
                 const struct sigevent *
                     (*handler) (void *area, int id),
                 const void *area,
                 int size,
                 unsigned flags);

The intr argument specifies which interrupt you wish to attach the specified handler to. The values passed are defined by the startup code that initialized the PIC (amongst other things) just before QNX Neutrino was started. (There's more information on the startup code in your QNX Neutrino documentation; see the startup-* entries in the Utilities Reference.)

Note: Since attaching an interrupt isn't something you want everyone to be able to do, QNX Neutrino allows only threads that have "I/O privileges" enabled to do it (see the ThreadCtl() function in the QNX Neutrino C Library Reference). Only threads that have the PROCMGR_AID_IO ability enabled (see procmgr_ability()) can obtain I/O privileges. Threads must also have the PROCMGR_AID_INTERRUPT ability enabled.

At this point, the two functions InterruptAttach() and InterruptAttachEvent() differ. Let's look at InterruptAttachEvent() as it's simpler, first. Then we'll come back to InterruptAttach().

Attaching with InterruptAttachEvent()

The InterruptAttachEvent() function takes two additional arguments: the argument event, which is a pointer to the struct sigevent that should be delivered, and a flags parameter. InterruptAttachEvent() tells the kernel that the event should be returned whenever the interrupt is detected, and that the interrupt level should be masked off. Note that it's the kernel that interprets the event and figures out which thread should be made READY.

Attaching with InterruptAttach()

With InterruptAttach(), we're specifying a different set of parameters. The handler parameter is the address of a function to call. As you can see from the prototype, handler() returns a struct sigevent, which indicates what kind of an event to return, and takes two parameters. The first passed parameter is the area, which is simply the area parameter that's passed to InterruptAttach() to begin with. The second parameter, id, is the identification of the interrupt, which is also the return value from InterruptAttach(). This is used to identify the interrupt and to mask, unmask, lock, or unlock the interrupt. The fourth parameter to InterruptAttach() is the size, which indicates how big (in bytes) the data area that you passed in area is. Finally, the flags parameter is the same as that passed for the InterruptAttachEvent(); we'll discuss that shortly.