i dunno if you'll find it easy to understand, but here's mine:
control.asm gets the interrupt signal through KEYBOARD auto_generated code:
Code: Select all
KEYBOARD:
push ebp
mov ebp, esp ;; this is for C stackframe compatibility (enable stack tracing)
pushad ;; saves all the registers
mov al, 1 ;; record the IRQ
jmp processIrq
then processIrq (common to every interrupt handlers) do the save/restore job on segment registers and calls irqProcessList(1)
which is a C function described in
interrpt.c
This one will sweep a list of handlers (basically a function pointer + a "next" pointer plus flags) until it has a handler that asks the interrupt not to be delivered to any other handler behind him.
I've chosen this model because i think it is cleaner than the MS-Dos like "hooking" process which can be performed only with assembly code and where one can hardly keep an interrupt handler "at the top" of the list. Clicker interrupt processor has a priority feature that ensures every high-level handler will be called before a low-level handler is called. This way, you can easily compose your keyboard service with (for instance) a highest-priority handler that check for CTRL+ALT+DEL (or any other magic escape sequence) plus a handler from GUI that checks for CTRL+ALT+Fi in order to switch from one virtual desktop to another and finally the stdin handler which translate remaining scancodes into ASCII characters.
The highest-priority handler for keyboard is defined in
display.c in the _readKey() function
and basically read data from port 0x60 and sets/clear a bit in a table that will reflect the keyboard state for the rest of the system.
Any lower handlers such as the virtual console switcher in _consoleSwap() or the CTRL+L feature for clearing the debug console in _clearDebug() will read that bittable rather than re-probe the port 0x60 (which would do nothing good !)