Anonymous user
Interrupts: Difference between revisions
Jump to navigation
Jump to search
no edit summary
[unchecked revision] | [unchecked revision] |
No edit summary |
No edit summary |
||
Line 1:
{{Convert}}
An interrupt is a message from a device, such as the keyboard, to the CPU, telling it to immediately stop whatever it is currently doing and do something else. For example, the keyboard controller sends an interrupt when a key is pressed. To know what to do when a specifc interrupt arise, the CPU has a table called the *IDT* which is setup by the OS, and stored in memory. There are 256 interrupts, numbered from 0 to 255, but only 16 are used by devices. These are called *IRQs* (Interrupt ~ReQuest) or hardware interrupts. The 16 IRQs are numbered from 0 to 15. Applications can call interrupts with the INT instruction, such as:
Non-IRQ interrupts are often used for APIs, or sets of functions that can be called by applications. The linux API is 0x80, or 80h and the DOS API is 0x21, or 21h. These are called software interrupts. Note that the first 32 (0-31) interrupts are reserved and used by the CPU, as exceptions, so don't use those for APIs or IRQs.
Line 11 ⟶ 10:
Basically, when a key is pressed, the keyboard controller tells a device called the [Programmable Interrupt Controller|What is the PIC?], or PIC, to cause an interrupt. Because of the wiring of keyboard and PIC, IRQ #1 is the keyboard interrupt, so when a key is pressed, IRQ 1 is sent to the PIC. The role of the PIC will be to decide whether the CPU should be immediately notified of that IRQ or not and to translate the IRQ number into an _interrupt vector_ (i.e. a number between 0 and 255) for the CPU's table.
Line 17 ⟶ 16:
There are actually two PICs on most systems, and each handles 8 different interrupts. Actually, IRQ 2 and IRQ 9 (handled by the master and slave PICs, respectively) are connected, so whenever IRQ 2 occurs, IRQ 9 also occurs (this can be changed, but most devices expect IRQ 2 to be reserved for this purpose, and therefore do not use it).
A device sends the PIC an interrupt, and the PIC tells the CPU which interrupt number (between 00h and FFh, or 0 and 255 decimal) is to be serviced. When the system first starts up, the IRQs 0-7 are set to interrupts 08h-0Fh. IRQs 8-F are set to interrupts 70h-77h. Therefore, if IRQ 6 is sent to the PIC by a device, the PIC would tell the CPU to service INT 0Eh, which presumably has code for interacting with whatever device sent the interrupt in the first place. Of course, there can be trouble when two or more devices share an IRQ; if you wonder how this works, check out [Plug and Play|Where can I find programming info on PNP?]. Note that interrupts are handled by priority level: 0, 1, 2, 8, 9, 10, 11, 12, 13, 14, 15, 3, 4, 5, 6, 7. So, if IRQ 8 and IRQ 3 come in simultaneously, IRQ 8 is sent to the CPU. When the CPU finishes handling the interrupt, it tells the PIC that it's OK to resume sending interrupts:
<pre>
out 20h,al
</
or if the interrupt came from the slave PIC:
<pre>
out A0h, al
out 20h, al
</
and the PIC sends the interrupt assigned to IRQ 3, which the CPU handles (using the IDT to look up the handler for that interrupt).
Alert readers will notice that the CPU has reserved interrupts 0-31, yet IRQs 0-7 are set to interrupts 08-0Fh. Now the reserved interrupts are called when, for example, a dreadful error has
See [Can I remap the PIC?] for detailed information.
The current program can, however, prevent the CPU from being disturbed by interrupts by the mean of the _interrupt flag_ (IF in status register). As long as this flag is cleared, the CPU ignores the PIC's requests and continues running the current program. Assembly instructions =cli= and =sti= can control that flag.
When an interrupt comes in, the IDT (which is setup by the OS in advance) is used to jump to code portion of the OS, which handles the interrupt (and therefore called the "interrupt handler" or "[
<pre>
out 20h,al
</
In the case of the [keyboard|Getting Keyboard Input], the interrupt handler asks the keyboard what key was pressed, does something with the information, then acknowledges and return:
<pre>
push eax ;; make sure you don't damage current state
in al,60h ;; read information from the keyboard
Line 61 ⟶ 63:
pop eax ;; restore state
iret ;; return to code executed before.
</
Whatever the CPU was previously doing is then resumed (unless another INT was received by the PIC while servicing this one, in which case the PIC tells the CPU about it and a new interrupt handler is executed, once the CPU saves state information on the stack again).
Step by step, now that you've grabbed the whole thing and know what's to be done:
* Make space for the interrupt descriptor table
* Tell the CPU where that space is (see
* Tell the PIC that you no longer want to use the BIOS defaults (see [Can I remap the PIC?])
* Write a couple of ISR handlers (see
* Put the addresses of the ISR handlers in the appropriate descriptors
* Enable all supported interrupts in the IRQ mask (of the PIC)
▲!! Magic Numbers:
* irq0 : timer interrupt
Line 93 ⟶ 90:
* irq14, irq15: ATA hard disks
* int 8-15: default mapping of IRQ0-7 by the BIOS at bootstrap
* int 0-31: reserved for
* int 70h-78h: default mapping of IRQ8-15 by the BIOS at bootstrap
* port 20h/21h : control/mask ports of the master PIC
Line 101 ⟶ 98:
* 8042 : keyboard controller chip
* 8259 : programmable interrupt controller
|