attach a handler to a hardware interrupt
#include <sys/irqinfo.h> int qnx_hint_attach( unsigned intnum, void __far *handler, unsigned ds );
The qnx_hint_attach() function attaches the interrupt function handler to hardware interrupt intnum, where intnum must be between 0 and 15, inclusive, on an AT.
The following list contains typical interrupt assignments. Note that a request for interrupt 2 on an AT is changed to interrupt 9, since 2 is used internally to connect the slave 8259.
Interrupt | Assignment |
---|---|
-1 | fixed 50 ms timer |
0 | timer |
1 | keyboard |
2 | slave |
3 | com2 |
4 | com1 |
5 | net card / other |
6 | floppy |
7 | parallel printer / net card / other |
8 | realtime clock |
9 | remapped interrupt 2 |
10 | |
11 | |
12 | |
13 | NDP co-processor |
14 | AT hard disk |
15 | second hd controller (standard) |
Interrupts 8 through 15 are mapped to a single (round-robin) priority. |
If you pass a value of -1 for intnum, your handler is invoked every 50 milliseconds. This time period won't change, even if you program the physical timer (interrupt 0) to run faster using the clock_setres() function. This timer interrupt is driven from the timer, and scaled in software, to provide a fixed time interval of 50 milliseconds.
The handler function is invoked via a far call (not an interrupt), and runs in the environment of your process (Local Descriptor Table set). The data segment is set to the ds parameter. The SS register is set to a special kernel stack, which will differ from your data segment (DS). For this reason, you must disable stack checking in the interrupt handler function and any functions that it calls. |
Most functions in the system library are compiled with stack checking disabled; routines that require a significant amount of stack might not. The latter tend to be functions that may not be called at interrupt time anyway, such as printf() and open(). If your functions contain any auto variables on the stack, we highly recommend that you place the interrupt function in its own file and compile it with the -zu option, which instructs the compiler that SS != DS.
Any variables modified by the handler should be specified with the volatile keyword.
The return value of the handler function must be 0, or a valid proxy pid that will be triggered to send a message.
The interrupt structure allows interrupts to be shared. For example, if two processes take over the same physical interrupt, both handlers are invoked consecutively. Interrupts (sti) are enabled during the execution of your handler. However, interrupts at your level and those of lower priority are masked out. You shouldn't attempt to talk to the 8259 interrupt controller chip yourself. The end of interrupt is issued by the operating system after processing all handlers at a given level. |
If you are the first process to attach to the interrupt, the interrupt is unmasked. When the last process detaches from an interrupt the system masks it.
The following important guidelines should be followed when writing interrupt handlers:
An interrupt handler ID (a small positive int) on success. On error, -1 is returned, and errno is set.
/* * Please note that stack checking must be disabled in your * handler. Use the "-Wc,-s" option to the cc command. * It's also a good idea to put the interrupt handler * in its own module. */ #include <stdio.h> #include <sys/irqinfo.h> #include <sys/proxy.h> #include <sys/kernel.h> pid_t proxy; volatile unsigned counter; /* The hardware interrupt handler */ pid_t far handler() { /* Kick a proxy every 100 timer interrupts */ if( (++counter % 100) == 0 ) return( proxy ); return( 0 ); } void main() { int id, i; /* Get a proxy for the interrupt handler to kick */ if( ( proxy = qnx_proxy_attach( 0, 0, 0, -1 ) ) == -1 ) { printf( " Unable to attach proxy. " ); return; } /* Attach to the timer */ if( ( id = qnx_hint_attach( 0, &handler, FP_SEG( &counter ) ) ) == -1 ) { printf( "Unable to attach interrupt." ); return; } /* Wait for the proxy */ for( i = 0 ; i < 10 ; ++i ) { Receive( proxy, 0, 0 ); printf( "100 ticks.\n" ); } qnx_hint_detach( id ); }
QNX
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | Yes, but modifies errno |
Thread | Yes |
If your application calls this function, it must run as root.
errno, qnx_hint_detach(), qnx_hint_query()