IRQ problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
wrozowski
Posts: 13
Joined: Mon Dec 30, 2013 6:41 am
Location: Poland
Contact:

IRQ problem

Post by wrozowski »

Hello,

I am working recently on ISR and IRQ handling. My code is based on James'm tutorial, but i use gas instead of nasm.
ISRs are working okay, but I am not receiving any IRQ. I've tried tu use Bran's code, but also IRQs didn't work. I've tested my os on qemu-system-i386 and virtualbox. What's wrong? Have I mapped PIC in wrong way? Or just my irq handler function in asm is wrong?

Here is my code:
interrupt.S

Code: Select all

.global isr0
isr0:
	cli
	pushl $0
	pushl $0
	jmp isr_common_stub

.global isr1
isr1:
	cli
	pushl $0
	pushl $1
	jmp isr_common_stub

.global isr2
isr2:
	cli
	pushl $0
	pushl $2
	jmp isr_common_stub

.global isr3
isr3:
	cli
	pushl $0
	pushl $3
	jmp isr_common_stub

.global isr4
isr4:
	cli
	pushl $0
	pushl $4
	jmp isr_common_stub

.global isr5
isr5:
	cli
	pushl $0
	pushl $5
	jmp isr_common_stub

.global isr6
isr6:
	cli
	pushl $0
	pushl $6
	jmp isr_common_stub

.global isr7
isr7:
	cli
	pushl $0
	pushl $7
	jmp isr_common_stub

.global isr8
isr8:
	cli
	pushl $8
	jmp isr_common_stub

.global isr9
isr9:
	cli
	pushl $0
	pushl $9
	jmp isr_common_stub

.global isr10
isr10:
	cli
	pushl $10
	jmp isr_common_stub

.global isr11
isr11:
	cli
	pushl $11
	jmp isr_common_stub

.global isr12
isr12:
	cli
	pushl $12
	jmp isr_common_stub

.global isr13
isr13:
	cli
	pushl $13
	jmp isr_common_stub

.global isr14
isr14:
	cli
	pushl $14
	jmp isr_common_stub

.global isr15
isr15:
	cli
	pushl $0
	pushl $15
	jmp isr_common_stub

.global isr16
isr16:
	cli
	pushl $0
	pushl $16
	jmp isr_common_stub

.global isr17
isr17:
	cli
	pushl $0
	pushl $17
	jmp isr_common_stub

.global isr18
isr18:
	cli
	pushl $0
	pushl $18
	jmp isr_common_stub

.global isr19
isr19:
	cli
	pushl $0
	pushl $19
	jmp isr_common_stub

.global isr20
isr20:
	cli
	pushl $0
	pushl $20
	jmp isr_common_stub

.global isr21
isr21:
	cli
	pushl $0
	pushl $21
	jmp isr_common_stub

.global isr22
isr22:
	cli
	pushl $0
	pushl $22
	jmp isr_common_stub

.global isr23
isr23:
	cli
	pushl $0
	pushl $23
	jmp isr_common_stub

.global isr24
isr24:
	cli
	pushl $0
	pushl $24
	jmp isr_common_stub

.global isr25
isr25:
	cli
	pushl $0
	pushl $25
	jmp isr_common_stub

.global isr26
isr26:
	cli
	pushl $0
	pushl $26
	jmp isr_common_stub

.global isr27
isr27:
	cli
	pushl $0
	pushl $27
	jmp isr_common_stub

.global isr28
isr28:
	cli
	pushl $0
	pushl $28
	jmp isr_common_stub

.global isr29
isr29:
	cli
	pushl $0
	pushl $29
	jmp isr_common_stub

.global isr30
isr30:
	cli
	pushl $0
	pushl $30
	jmp isr_common_stub

.global isr31
isr31:
	cli
	pushl $0
	pushl $31
	jmp isr_common_stub



.global irq0
irq0:
	cli
	pushl $0
	pushl $32
	jmp irq_common_stub


.global irq1
irq1:
	cli
	push $0
	push $33
	jmp irq_common_stub

.global irq2
irq2:
	cli
	pushl $0
	pushl $34
	jmp irq_common_stub

.global irq3
irq3:
	cli
	pushl $0
	pushl $35
	jmp irq_common_stub

.global irq4
irq4:
	cli
	pushl $0
	pushl $36
	jmp irq_common_stub

.global irq5
irq5:
	cli
	pushl $0
	pushl $37
	jmp irq_common_stub

.global irq6
irq6:
	cli
	pushl $0
	pushl $38
	jmp irq_common_stub

.global irq7
irq7:
	cli
	pushl $0
	pushl $39
	jmp irq_common_stub

.global irq8
irq8:
	cli
	pushl $0
	pushl $40
	jmp irq_common_stub

.global irq9
irq9:
	pushl $0
	pushl $41
	jmp irq_common_stub

.global irq10
irq10:
	cli
	pushl $0
	pushl $42
	jmp irq_common_stub

.global irq11
irq11:
	cli
	pushl $0
	pushl $43
	jmp irq_common_stub

.global irq12
irq12:
	cli
	pushl $0
	pushl $44
	jmp irq_common_stub

.global irq13
irq13:
	cli
	pushl $0
	pushl $45
	jmp irq_common_stub

.global irq14
irq14:
	cli
	pushl $0
	pushl $46
	jmp irq_common_stub

.global irq15
irq15:
	cli
	pushl $0
	pushl $47
	jmp irq_common_stub

.extern isr_handler
isr_common_stub:
	pushal
	mov %ds, %ax
	pushl %eax
	mov $0x10, %ax
	mov %ax, %ds
	mov %ax, %es
	mov %ax, %fs
	mov %ax, %gs
	mov %ax, %ss
	call isr_handler

	popl %ebx
	mov %bx, %ds
	mov %bx, %es
	mov %bx, %fs
	mov %bx, %gs

	popal
	add $8, %esp
	sti
	iret

.extern irq_handler
irq_common_stub:
	pusha
	mov %ds, %ax
	push %eax
	mov $0x10, %ax
	mov %eax, %ds
	mov %eax, %es
	mov %eax, %fs
	mov %eax, %gs
	call irq_handler
	pop %ebx
	mov %ebx, %ds
	mov %ebx, %es
	mov %ebx, %fs
	mov %ebx, %gs
	popa
	add $0x8, %esp
	sti
	iret

idt.c

Code: Select all

#include <loki/system.h>

extern void idt_flush(uint32_t);
extern void idt_set_gate(uint8_t, uint32_t, uint16_t, uint8_t);
idt_entry_t idt_entries[255];
idt_ptr_t idt_ptr;
isr_t interrupt_handlers[256];
void init_idt()
{

	idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
	idt_ptr.base = (uint32_t)&idt_entries;
	for(int i=0;i<255;i++)
	{
		idt_entries[i].base_lo = 0;
		idt_entries[i].sel = 0;
		idt_entries[i].always0 = 0;
		idt_entries[i].flags = 0;
		idt_entries[i].base_hi = 0;
	}
	outb(0x20, 0x11);
	outb(0xA0, 0x11);
	outb(0x21, 0x20);
	outb(0xA1, 0x28);
	outb(0x21, 0x04);
	outb(0xA1, 0x02);
	outb(0x21, 0x01);
	outb(0xA1, 0x01);
	outb(0x21, 0x0);
	outb(0xA1, 0x0);
	idt_set_gate( 0, (uint32_t)isr0 , 0x08, 0x8E);
	idt_set_gate( 1, (uint32_t)isr1 , 0x08, 0x8E);
	idt_set_gate( 2, (uint32_t)isr2 , 0x08, 0x8E);
	idt_set_gate( 3, (uint32_t)isr3 , 0x08, 0x8E);
	idt_set_gate( 4, (uint32_t)isr4 , 0x08, 0x8E);
	idt_set_gate( 5, (uint32_t)isr5 , 0x08, 0x8E);
	idt_set_gate( 6, (uint32_t)isr6 , 0x08, 0x8E);
	idt_set_gate( 7, (uint32_t)isr7 , 0x08, 0x8E);
	idt_set_gate( 8, (uint32_t)isr8 , 0x08, 0x8E);
	idt_set_gate( 9, (uint32_t)isr9 , 0x08, 0x8E);
	idt_set_gate(10, (uint32_t)isr10, 0x08, 0x8E);
	idt_set_gate(11, (uint32_t)isr11, 0x08, 0x8E);
	idt_set_gate(12, (uint32_t)isr12, 0x08, 0x8E);
	idt_set_gate(13, (uint32_t)isr13, 0x08, 0x8E);
	idt_set_gate(14, (uint32_t)isr14, 0x08, 0x8E);
	idt_set_gate(15, (uint32_t)isr15, 0x08, 0x8E);
	idt_set_gate(16, (uint32_t)isr16, 0x08, 0x8E);
	idt_set_gate(17, (uint32_t)isr17, 0x08, 0x8E);
	idt_set_gate(18, (uint32_t)isr18, 0x08, 0x8E);
	idt_set_gate(19, (uint32_t)isr19, 0x08, 0x8E);
	idt_set_gate(20, (uint32_t)isr20, 0x08, 0x8E);
	idt_set_gate(21, (uint32_t)isr21, 0x08, 0x8E);
	idt_set_gate(22, (uint32_t)isr22, 0x08, 0x8E);
	idt_set_gate(23, (uint32_t)isr23, 0x08, 0x8E);
	idt_set_gate(24, (uint32_t)isr24, 0x08, 0x8E);
	idt_set_gate(25, (uint32_t)isr25, 0x08, 0x8E);
	idt_set_gate(26, (uint32_t)isr26, 0x08, 0x8E);
	idt_set_gate(27, (uint32_t)isr27, 0x08, 0x8E);
	idt_set_gate(28, (uint32_t)isr28, 0x08, 0x8E);
	idt_set_gate(29, (uint32_t)isr29, 0x08, 0x8E);
	idt_set_gate(30, (uint32_t)isr30, 0x08, 0x8E);
	idt_set_gate(31, (uint32_t)isr31, 0x08, 0x8E);
	idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E);
	idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E);
	idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E);
	idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E);
	idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E);
	idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E);
	idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E);
	idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E);
	idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E);
	idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E);
	idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E);
	idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E);
	idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E);
	idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E);
	idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E);
	idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E);
	idt_flush((uint32_t)&idt_ptr);
	init_msg("setting IDT");
}
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
{
	idt_entries[num].base_lo = base & 0xFFFF;
	idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
	idt_entries[num].sel = sel;
	idt_entries[num].always0 = 0;
	idt_entries[num].flags = flags;
}

void register_interrupt_handler(uint8_t n, isr_t handler)
{
	interrupt_handlers[n] = handler;
}


void isr_handler(registers_t regs)
{
	kprintf("Received interrupt: 0x%x\n", (uint32_t) regs.int_no);
	if (interrupt_handlers[regs.int_no] != 0)
	{
		isr_t handler = interrupt_handlers[regs.int_no];
		handler(regs);
	}
}


void irq_handler(registers_t regs)
{

	if (regs.int_no >= 40)
	{

		outb(0xA0, 0x20);
	}

	outb(0x20, 0x20);

	if (interrupt_handlers[regs.int_no] != 0)
	{
		isr_t handler = interrupt_handlers[regs.int_no];
		handler(regs);
	}

}

uint32_t tick = 0;

void timer_callback(registers_t regs)
{
	tick++;
	kprintf("Tick: 0x%x \n", (uint32_t) tick);

}

void init_timer(uint32_t frequency)
{
	
	register_interrupt_handler(IRQ0, &timer_callback);


	uint32_t divisor = 1193180 / frequency;


	outb(0x43, 0x36);


	uint8_t l = (uint8_t)(divisor & 0xFF);
	uint8_t h = (uint8_t)( (divisor>>8) & 0xFF );


	outb(0x40, l);
	outb(0x40, h);
}

idt.h

Code: Select all

#include <loki/system.h>
#ifndef idt_h
#define idt_h

#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46

struct idt_entry
{
	uint16_t base_lo;
	uint16_t sel;
	uint8_t always0;
	uint8_t flags;
	uint16_t base_hi;
} __attribute__((packed));
typedef struct idt_entry idt_entry_t;
struct idt_ptr
{
	uint16_t limit;
	uint32_t base;
} __attribute__((packed));
typedef struct idt_ptr idt_ptr_t;
typedef struct registers
{
	uint32_t ds;
	uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
	uint32_t int_no, err_code;
	uint32_t eip, cs, eflags, useresp, ss;
} registers_t;

void init_idt();
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();

typedef void (*isr_t)(registers_t);
void register_interrupt_handler(uint8_t n, isr_t handler);
void init_timer(uint32_t frequency);
void timer_callback(registers_t regs);
//void init_irq();
void irq_install_handler(int irq, void (*handler)(struct registers *r));
void irq_uninstall_handler(int irq);
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);

#endif

Greetings,
Wrozowski
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: IRQ problem

Post by xenos »

I suggest running your code on Bochs, as it gives you a lot more diagnostic output. In particular, you can look at the state of the PIC and see whether it gets configured correctly and what happens when you expect an IRQ.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: IRQ problem

Post by Icee »

Just some observations.

1. You are using CLI/STI with interrupt gates which is not the cause of your problem but still wrong.
2. EOIs should be issued after the IRQ processing is finished which again is not a big deal in your current setup but will eventually become one.
3. I don't see the "initial" STI that would allow interrupts through in the fragments you posted. The value of "divisor" could also be relevant.
4. Oh, and of course expect trouble as soon as you compile with optimizations enabled (see here).
5. Is IRQ0 unmasked in the IMR?
User avatar
wrozowski
Posts: 13
Joined: Mon Dec 30, 2013 6:41 am
Location: Poland
Contact:

Re: IRQ problem

Post by wrozowski »

Hello Icee,
Thank you for your ansewer.
I've changed my code using your sugestions:
Icee wrote:1. You are using CLI/STI with interrupt gates which is not the cause of your problem but still wrong.
2. EOIs should be issued after the IRQ processing is finished which again is not a big deal in your current setup but will eventually become one.
3. I don't see the "initial" STI that would allow interrupts through in the fragments you posted. The value of "divisor" could also be relevant.
4. Oh, and of course expect trouble as soon as you compile with optimizations enabled (see here).
5. Is IRQ0 unmasked in the IMR?
1.I've deleted CLI&STI
2. I issue EOI after every irq_handler call
3. I've inited STI (just like in Bran's tutorial)
4. Flags are OK
5. IMR is OK

When the C function irq_handler is called it passes register_t (structure containing register states during interrupt) as an argument.
When I try to read interrupt number from that structure using:

Code: Select all

kprintf("interrupt number %d", (uint32_t) regs.int_no);
i get: -4294967264 instead of 32. Why is that happening? How can I fix that?

Greetings
Wrozowski

PS: Thank you XenOS, now I'm using bochs instead of qemu :-)
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

Re: IRQ problem

Post by Octocontrabass »

wrozowski wrote: i get: -4294967264 instead of 32. Why is that happening? How can I fix that?
Combuster's crystal ball says it's a problem in kprintf.
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: IRQ problem

Post by Icee »

Octocontrabass wrote:Combuster's crystal ball says it's a problem in kprintf.
Sounds quite likely, esp. since that value over there is 0xFFFFFFFF00000020, which is 32 with sign extension gone wrong.
User avatar
wrozowski
Posts: 13
Joined: Mon Dec 30, 2013 6:41 am
Location: Poland
Contact:

Re: IRQ problem

Post by wrozowski »

Hi,
Octocontrabass wrote: Combuster's crystal ball says it's a problem in kprintf.
Thank you Octocontrabass. Combuster's crystall ball is right :D. When i use:

Code: Select all

kprintf("interrupt number %d", (uint32_t) regs.int_no);
I get -4294967264 and when I use:

Code: Select all

kprintf("interrupt number: 0x%x", (uint32_t) regs.int_no);
I get 0x20.

I'll have to improve my kprinf. I've found a small bug; in init timer there was:

Code: Select all

register_interrupt_handler(0, &timer_callback); 
and it should be

Code: Select all

register_interrupt_handler(32, &timer_callback);
I've changed my irq_handler to see debugging messages in my log:

Code: Select all

void irq_handler(registers_t regs)
{
	printklog("handler has been called\n");
	printklog("regs int no = %x\n", regs.int_no);
	if (regs.int_no >= 40)
	{
		printklog("sending signal to slave\n");

		outb(0xA0, 0x20);
	}

	printklog("sending signal to master\n");
	outb(0x20, 0x20);

	if (interrupt_handlers[regs.int_no] != 0)
	{
		printklog("preparing function pointer\n");
		isr_t handler = interrupt_handlers[regs.int_no];
		printklog("calling handler \n");
		handler(regs);
	}
}
And after turning on timer, irq's, and other parts of kernel using:

Code: Select all

	init_gdt();
	init_idt();
   init_paging();
	init_irq();
	init_timer(100);
	__asm__ __volatile__ ("sti");
	

my screen looks like this:

Code: Select all

Tick 1
Received interrupt: 0xe
System halted.
and my log looks like this:

Code: Select all

loki 0.01 debug 
MEMORY SECTIONS MAP:
multiboot:
	start: 0x100000
	end: 0x10000c
text:
	start: 0x10000c
	end: 0x102189
rodata:
	start: 0x103000
	end: 0x103000
data:
	start: 0x104000
	end: 0x104038
common:
	start: 0x105000
	end: 0x10b694
bss:
	start: 0x10b694
	end: 0x10b698
bootstrap_stack:
	start: 0x10b698
	end: 0x10f698
multiboot_elf_sec:
	start: 0x110000
	end: 0x110028
module 0x1:
	start: 0x112000
	end: 0x112257
Last module end address: 0x112257
Kheap start address is 0x113000
[mboot diag] mem_lower = 639KB, mem_upper = 130040KB
[mboot diag] boot_device = 0xe0ffffff
[mboot diag] cmdline = /boot/kernel.elf
[mboot diag] mmap_addr = 0x2ce48, mmap_length = 0x90
 size = 0x14, base_addr = 0x00, length = 0x00, type = 0x0
 size = 0x14, base_addr = 0x00, length = 0x9fc000, type = 0x0
 size = 0x14, base_addr = 0x00, length = 0xf00000, type = 0x0
 size = 0x14, base_addr = 0x00, length = 0x1000000, type = 0x0
 size = 0x14, base_addr = 0x00, length = 0x7ffe0000, type = 0x0
 size = 0x14, base_addr = 0x00, length = 0xfffc00000, type = 0x0
We need to map memory to 0x113000 address using 0x113 frames.
Allocated memory for first kernel directory, at 0x113000.
Allocated memory for page_tables, at 0x114000.
We will write 0x113 frames.
Written 0x113 pages in 0x1 page tables.
Loaded page tables to page directory
Writing data to CR3
CR0 = 0x11
Writing CR0 = 0x80000011
CR0 has been loaded. Paging has been enabled!
handler has been called
regs int no = 0x20
sending signal to master
preparing function pointer
calling handler 
Why my irq_handler causes general protection fault? What's wrong?

Greetings
Wrozowski
mallard
Member
Member
Posts: 280
Joined: Tue May 13, 2014 3:02 am
Location: Private, UK

Re: IRQ problem

Post by mallard »

Why my irq_handler causes general protection fault? What's wrong?
Because interrupt_handlers[0x20] has never been set and interrupt_handlers was not initialised, so the contents are undefined (and non-zero).

Chanege the line:

Code: Select all

isr_t interrupt_handlers[256];
to:

Code: Select all

isr_t interrupt_handlers[256]={0};
To ensure that the array is zeroed.
Image
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: IRQ problem

Post by Icee »

mallard wrote:Because interrupt_handlers[0x20] has never been set and interrupt_handlers was not initialised, so the contents are undefined (and non-zero).
The first is done via register_interrupt_handler(), and the second point is invalid because the C standard mandates that global variables are zeroed unless they have an explicit initializer. This effectively places them in .bss, which is cleared by the boot loader. Only the automatic storage class variables have undefined initial values.

To wrozowski: do you compile with optimization enabled (-O1, -O2, -O3, -Os)?
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: IRQ problem

Post by Owen »

You have the same problem as in this thread. The calling convention used by the IRS handler is wrong in the JamesM tutorial.
User avatar
wrozowski
Posts: 13
Joined: Mon Dec 30, 2013 6:41 am
Location: Poland
Contact:

Re: IRQ problem

Post by wrozowski »

Hi,
mallard wrote:To wrozowski: do you compile with optimization enabled (-O1, -O2, -O3, -Os)?
Yes, I do.
Here are my CFLAGS:

Code: Select all

CFLAGS   := -std=gnu99 -ffreestanding -fno-stack-protector -O1 -O2 -O3  -Wall -Wextra -nostdlib -lgcc -D$(ARCH) -I../include
Regards
wrozowski
Icee
Member
Member
Posts: 100
Joined: Wed Jan 08, 2014 8:41 am
Location: Moscow, Russia

Re: IRQ problem

Post by Icee »

Then Owen is right, and I, too, have pointed out the problem to you before (number 4 in the list). The compiler is free to trash your regs structure on return from the irq_handler, see either the wiki link I gave above or the thread Owen is suggesting.

Also, only the last of the -Osomething options is effective, "-O1 -O2 -O3" is equivalent to "-O3".
User avatar
wrozowski
Posts: 13
Joined: Mon Dec 30, 2013 6:41 am
Location: Poland
Contact:

Re: IRQ problem

Post by wrozowski »

Hello again,

Icee and Owen thank you for your help.
Owen wrote:The calling convention used by the IRS handler is wrong in the JamesM tutorial.
I'll check that thread and I'll look to James'm known bugs. My assembly function looks like that:

Code: Select all

.extern irq_handler
irq_common_stub:
   pushal
   mov %ds, %ax
   pushl %eax
   mov $0x10, %ax
   mov %ax, %ds
   mov %ax, %es
   mov %ax, %fs
   mov %ax, %gs
   mov %ax, %ss
   call irq_handler

   popl %ebx
   mov %ebx, %ds
   mov %ebx, %es
   mov %ebx, %fs
   mov %bx, %gs

   popal
   add $8, %esp
   sti
   iret
I'll fix it and send it to you ;-)

Greetings
Wrozowski
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: IRQ problem

Post by Combuster »

Octocontrabass wrote:Combuster's crystal ball says it's a problem in kprintf.
Hey, give that back! :D
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
wrozowski
Posts: 13
Joined: Mon Dec 30, 2013 6:41 am
Location: Poland
Contact:

Re: IRQ problem

Post by wrozowski »

Hi ;),

I've fixed my irq handler. When I enable IRQ and I make interrupt using:

Code: Select all

asm("int $0x20");
Everything is ok. But when I enable PIT it fires only once. What causes that? Is that caused by my emulators(qemu, bochs)? Have I remapped PIC in wrong way? Can your crystal balls help me :)?

in interrupt.S

Code: Select all

.global irq0
irq0:
	cli
	pushl $0
	pushl $32
	jmp irq_common_stub

...

.extern irq_handler
irq_common_stub:

	cld


	pushal
	pushl %ds
	pushl %es
	pushl %fs
	pushl %gs


	movl $0x10, %eax
	movl %eax, %ds
	movl %eax, %es
	movl %eax, %fs
	movl %eax, %gs


	pushl %esp
	call irq_handler
	addl $0x4, %esp
	popl %gs
	popl %fs
	popl %es
	popl %ds
	popal

	add $8, %esp
	iret


in idt.h

Code: Select all

struct regs
{

 uint32_t gs; //segment registers
 uint32_t fs;
 uint32_t es;
 uint32_t ds;
 
 uint32_t edi; //pushal
 uint32_t esi;
 uint32_t ebp;
 uint32_t old_esp;
 uint32_t ebx; 
 uint32_t edx;
 uint32_t ecx;
 uint32_t eax;

 uint32_t intr_no; //pushed by irq(n)
 uint32_t err_code;


 uint32_t eip; //pushed by CPU
 uint32_t cs;    
 uint32_t eflags;  


 uint32_t esp;
 uint32_t ss;
 uint32_t v86_es; //for v86_mode: TODO
 uint32_t v86_ds;
 uint32_t v86_fs;
 uint32_t v86_gs;
} __attribute__((packed));
in idt.c

Code: Select all

void irq_handler(struct regs *r)
{
	printklog("Called handler\n");
	  if (r->intr_no >= 40)
	    {
		  	 printklog("Sending signal to slave.\n");
	        outb(0xA0, 0x20);
	    }

	  	 printklog("Sending signal to master");
	    outb(0x20, 0x20);
}

Greetings
Wrozowski
Post Reply