I Can't Get Interrupts Working: Difference between revisions

Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content deleted Content added
Creature (talk | contribs)
m Fixed some grammar mistakes.
added source tags
Line 38: Line 38:
Use the mask feature of the PIC to enable/disable some handlers.
Use the mask feature of the PIC to enable/disable some handlers.


<source lang="c">
<pre>
outb(0x21,0xfd);
outb(0x21,0xfd);
outb(0xa1,0xff);
outb(0xa1,0xff);
enable(); // asm("sti");
enable(); // asm("sti");
</pre>
</source>


=== I'm receiving EXC9 instead of IRQ1 when striking a key ?! ===
=== I'm receiving EXC9 instead of IRQ1 when striking a key ?! ===
Line 55: Line 55:
=== I can only receive one IRQ ===
=== I can only receive one IRQ ===


Each IRQ needs to be acknowledged to the PIC manually. You need to have <pre> outb(0x20,0x20) </pre> within any master handler and any <pre> outb(0x20,0x20); outb(0xa0,0x20); </pre> within any slave handler.
Each IRQ needs to be acknowledged to the PIC manually. You need to have <source lang="c"> outb(0x20,0x20) </source> within any master handler and any <source lang="c"> outb(0x20,0x20); outb(0xa0,0x20); </source> within any slave handler.


=== When I try to enable the PIT, the keyboard doesn't work anymore ===
=== When I try to enable the PIT, the keyboard doesn't work anymore ===
Line 63: Line 63:
=== I keep getting an IRQ7 for no apparent reason ===
=== I keep getting an IRQ7 for no apparent reason ===


This is a known problem that cannot be prevented from happening, although there is a workaround. When any IRQ7 is received, simply read the In-Service Register <pre> outb(0x20, 0x0B); unsigned char irr = inb(0x20);</pre> and check if bit 7 <pre>irr & 0x80</pre> is set. If it isn't, then return from the interrupt without sending an EOI.
This is a known problem that cannot be prevented from happening, although there is a workaround. When any IRQ7 is received, simply read the In-Service Register <source lang="c"> outb(0x20, 0x0B); unsigned char irr = inb(0x20);</source> and check if bit 7 <source lang="c">irr & 0x80</source> is set. If it isn't, then return from the interrupt without sending an EOI.


For more information, including a more detailed explanation, see Brendan's post in [[Topic:11379|this thread]].
For more information, including a more detailed explanation, see Brendan's post in [[Topic:11379|this thread]].
Line 73: Line 73:


You're trying to load a 16-bits field (a part of the IDT descriptor) with a reference to a 32-bit label that is subject to relocation. Try to replace
You're trying to load a 16-bits field (a part of the IDT descriptor) with a reference to a 32-bit label that is subject to relocation. Try to replace
<source lang="asm">

isr_label:
isr_label:
iret
iret
Line 80: Line 80:
dw 0xbeef
dw 0xbeef
dw isr_label >> 16
dw isr_label >> 16
</source>


by something that extracts a 'pure value' from the address (e.g. the difference of two addresses are a pure value and <tt>$$</tt> means to NASM the start of the section)
by something that extracts a 'pure value' from the address (e.g. the difference of two addresses are a pure value and <tt>$$</tt> means to NASM the start of the section)
<source lang="asm">

%define BASE_OF_SECTION SOME_CONSTANT_YOU_SHOULD_KNOW
%define BASE_OF_SECTION SOME_CONSTANT_YOU_SHOULD_KNOW
isr_label:
isr_label:
Line 90: Line 91:
dw 0xbabe
dw 0xbabe
dw (BASE_OF_SECTION isr_label - $$) >> 16
dw (BASE_OF_SECTION isr_label - $$) >> 16
</source>


The role of <pre>BASE_OF_SECTION</pre> is to adjust the pure offset to the real situation (usually as defined in your linker script), e.g. if your kernel get loaded at 1MB, you'll set it to 0x100000 to keep the CPU happy.
The role of <pre>BASE_OF_SECTION</pre> is to adjust the pure offset to the real situation (usually as defined in your linker script), e.g. if your kernel get loaded at 1MB, you'll set it to 0x100000 to keep the CPU happy.


==Assembly Example==
==Assembly Example==
<source lang="asm">

int_handler:
int_handler:
mov ax, LINEAR_DATA_SELECTOR
mov ax, LINEAR_DATA_SELECTOR
Line 117: Line 119:
mov [idt+49*8+6],ax
mov [idt+49*8+6],ax
int 49
int 49
</source>


should display a smiley on the top-left corner ... then the CPU is halted indefinitely.
should display a smiley on the top-left corner ... then the CPU is halted indefinitely.
Line 131: Line 134:
simple, but not like Nasm.
simple, but not like Nasm.
a little example, so you can see how it works:
a little example, so you can see how it works:
<source lang="asm">
idt:
idt:
dw ((isr1 shl 0x30) shr 0x30) ; the low part of the address
dw ((isr1 shl 0x30) shr 0x30) ; the low part of the address
Line 138: Line 141:
db 010001110b ; type
db 010001110b ; type
dw (isr1 shr 0x10) the high part of the address
dw (isr1 shr 0x10) the high part of the address


isr1:
isr1:
mov ax,0xdead
mov ax,0xdead
</source>