Interrupt handling
Interrupt handling
OK, I want to write the timer (IRQ0) interrupt routine:
As far as I know I need the following code to do so:
asm (NASM), something is needed like :-\:
[BITS 32]
[GLOBAL _ks_timerInterruptIRQ0]
[ALIGN 4]
_clock_isr:
push eax
push ds
push es
push fs
push gs
mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
extern _ks_timerInterruptIRQ0
call _ks_timerInterruptIRQ0
mov eax, 0x20
out 0x20, al
pop gs
pop fs
pop es
pop ds
pop eax
iret
C:
void ks_timerInterruptIRQ0(void)
{
// Do something...
}
Till this part, it seems logical, but I can't find anything on how I can tell the processor to use _clock_isr, it seems to me, that I need a pointer to this procedure, somewhere in the memory, but how and where to set it I don't know, does anyone have an idea?
As far as I know I need the following code to do so:
asm (NASM), something is needed like :-\:
[BITS 32]
[GLOBAL _ks_timerInterruptIRQ0]
[ALIGN 4]
_clock_isr:
push eax
push ds
push es
push fs
push gs
mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
extern _ks_timerInterruptIRQ0
call _ks_timerInterruptIRQ0
mov eax, 0x20
out 0x20, al
pop gs
pop fs
pop es
pop ds
pop eax
iret
C:
void ks_timerInterruptIRQ0(void)
{
// Do something...
}
Till this part, it seems logical, but I can't find anything on how I can tell the processor to use _clock_isr, it seems to me, that I need a pointer to this procedure, somewhere in the memory, but how and where to set it I don't know, does anyone have an idea?
Re:Interrupt handling
Well, you have to build an entry in the IDT that points to _clock_isr, so be sure to make _clock_isr global, too.
By the way, you probably want to change
into
By the way, you probably want to change
Code: Select all
[GLOBAL _ks_timerInterruptlIRQ0]
Code: Select all
[EXTERN _ks_timerInterruptlIRQ0]
Re:Interrupt handling
Investigate these (Assuming x86 architecture):2100-OS wrote: Till this part, it seems logical, but I can't find anything on how I can tell the processor to use _clock_isr, it seems to me, that I need a pointer to this procedure, somewhere in the memory, but how and where to set it I don't know, does anyone have an idea?
IDT - Interrupt Descriptor Table, works similarily to the IVT in Real Mode.
PIC - Programmable Interrupt Controller. Takes signals (IRQs) from hardware devices and produces an interrupt in the processor.
PIT - Programmable Interval Timer. Consists of 3 separate timers, the first of which produces an interrupt in the processor.
Make sure you also know how to setup a GDT.
Read up on those things and it should become self evident what steps you need to take to have your routine called.
Re:Interrupt handling
OK, I am seeing some puzzlepieces coming together (like 3, 4 of the 10000 )
I understand what's done right here (in ASM)
[section .text]
;load the IDT, this requires that the data section with
;the IDT exists
lidt [idt_pointer]
[section .data]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the IDT with it's descriptors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start_of_idt:
;interrupt 0
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
;interrupt 1
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
;interrupt 2, intel reserved, we set the 'present' bit to 0 on this one
dw 0x0000
dw 0x10
dw 0xE00
dw 0x20
;interrupts 3-14 now, since we are making the descriptors
;identical, we are going to loop to get them all(12 total)
%rep 0xC
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
%endrep
;interrupt 15, intel reserved, we set the 'present' bit to 0 on this one
dw 0x0000
dw 0x10
dw 0xE00
dw 0x20
;interrupt 16
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
end_of_idt:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; now for the IDT pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idt_pointer:
dw end_of_idt - start_of_idt - 1
dd start_of_idt
What I don't understand is how I can link an interrupt with a basic assembler routine. Somewhere in each of these bytes there must be an address field. Is this the so called Code Selector? If so, it's just doing:
dw _irq_ptr or something similar?
tnx in advance
I understand what's done right here (in ASM)
[section .text]
;load the IDT, this requires that the data section with
;the IDT exists
lidt [idt_pointer]
[section .data]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the IDT with it's descriptors
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start_of_idt:
;interrupt 0
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
;interrupt 1
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
;interrupt 2, intel reserved, we set the 'present' bit to 0 on this one
dw 0x0000
dw 0x10
dw 0xE00
dw 0x20
;interrupts 3-14 now, since we are making the descriptors
;identical, we are going to loop to get them all(12 total)
%rep 0xC
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
%endrep
;interrupt 15, intel reserved, we set the 'present' bit to 0 on this one
dw 0x0000
dw 0x10
dw 0xE00
dw 0x20
;interrupt 16
dw 0x0000
dw 0x10
dw 0x8E00
dw 0x20
end_of_idt:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; now for the IDT pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idt_pointer:
dw end_of_idt - start_of_idt - 1
dd start_of_idt
What I don't understand is how I can link an interrupt with a basic assembler routine. Somewhere in each of these bytes there must be an address field. Is this the so called Code Selector? If so, it's just doing:
dw _irq_ptr or something similar?
tnx in advance
Re:Interrupt handling
Wait, don't mess up things - the Code Selector is s.th. completely different, it has to do with the GDT...
Why not? Because the handler to be executed is split into two 16 bit addresses...the first double word stands for offset 15:0, the last double word for offset 31:16. Anyway, that's how you can implement it (and that's how I do it):
That is the IDT, 256 entries are built, but no handlers are defined yet...
This will setup a common ISR handler for all (256) interrupts...of course, you may want to change it...
common_isr is the function to execute...
good luck
Correct. Unfortunately, you cannot write something like this:Somewhere in each of these bytes there must be an address field
Code: Select all
; interrupt 1
dw my_int1_handler
dw selector
dw 0x8E00
...
Code: Select all
[global idt]
idt:
%rep 256
dw 0 ; offset 15:0
dw CS_SELECTOR ; selector
db 0
db 8Eh ; present, ring 0, '386 interrupt gate
dw 0 ; offset 31:16
%endrep
idt_end:
idt_ptr:
dw idt_end - idt - 1; IDT limit
dd idt ; start of IDT
Code: Select all
mov ecx,(idt_end - idt) >> 3 ; number of descriptors
mov edi,idt ; idt location
mov esi,common_isr ; common handler to esi
fill_idt:
mov eax,esi
mov [edi],ax ; low offset
shr eax,16
mov [edi+6],ax ; high offset
add edi,8 ; descriptor length
loop fill_idt
common_isr is the function to execute...
good luck
Re:Interrupt handling
I read the work again, you're right, about the code selector, the rest of the text seems to be complete enough to work with, btw handling 256, or at least most of them can be handled at the same spot, except the ones with extra values which need to be set O.T.S
tnx
tnx
Re:Interrupt handling
OK one more thing:
I assume that I need to initialize this before I call the main kernel function (or I need to call it from the main kernel function), but which of the labels need to be jumped to, or called?
I assume that I need to initialize this before I call the main kernel function (or I need to call it from the main kernel function), but which of the labels need to be jumped to, or called?
Re:Interrupt handling
You must do this basical steps:
1) Switch from real mode into protected mode.
2) Reprogram the PIC 8259
2) Load the GDT
3) Load the IDT
4) Go on with your kernel!
You can do it into your main routine or into an asm routine... the important is that you do it first of all.
When you link your output files you must ensure that this init-file is placed before any other files...
1) Switch from real mode into protected mode.
2) Reprogram the PIC 8259
2) Load the GDT
3) Load the IDT
4) Go on with your kernel!
You can do it into your main routine or into an asm routine... the important is that you do it first of all.
When you link your output files you must ensure that this init-file is placed before any other files...
Re:Interrupt handling
..if you write this routine in an asm file you can call the C-main program simply by declaring it as [EXTERN _main] or [EXTERN main] ...according to your compiler, and call main!which of the labels need to be jumped to, or called?
Re:Interrupt handling
I don't know if I understand you correctly, so excuse me if my answer doesn't fit to your question...but which of the labels need to be jumped to, or called?
Do you want to know how to jump to a C function? If so, drizzt has already told you how...
If you want to know how "make the IDT active", you have to load it...That is done by the instruction "lidt"...
Now let's take the code I posted before as an example...after setting up the descriptors, we would load the IDT like this:
Code: Select all
lidt [idt_ptr]