Page 1 of 1

IRQ's not working (Yep, another one)

Posted: Sun Jan 12, 2014 6:21 pm
by mbrla0
Sorry guys for posting another one of those.
Also, this is my first time here!

I've been trying to solve this for over a week now, I've checked my code several times and it seems ok.

The first time i tryied to solve the PIT ticked one time, but now it doesn't even do it #-o
The strange is, if i put like this:

Code: Select all

while(0==0) __asm__ __volatile__("sti");
And it works, not quite well, but works! :lol:

Please help me, I'm just so dumb that i can't even pass the IRQ's! #-o

idt.c

Code: Select all


#include "idt.h"

idt_entry_t idt_entries[256];
idt_ptr_t   idt_ptr;

static void idt_set_gate(uint8 num, uint32 base, uint16 sel, uint8 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;
   // We must uncomment the OR below when we get to using user-mode.
   // It sets the interrupt gate's privilege level to 3.
   idt_entries[num].flags   = flags /* | 0x60 */;
}

static void irq_init(){
   idt_set_gate(32, (uint32)irq0  , 0x08, 0x8E);
   idt_set_gate(33, (uint32)irq1  , 0x08, 0x8E);
   idt_set_gate(34, (uint32)irq2  , 0x08, 0x8E);
   idt_set_gate(35, (uint32)irq3  , 0x08, 0x8E);
   idt_set_gate(36, (uint32)irq4  , 0x08, 0x8E);
   idt_set_gate(37, (uint32)irq5  , 0x08, 0x8E);
   idt_set_gate(38, (uint32)irq6  , 0x08, 0x8E);
   idt_set_gate(39, (uint32)irq7  , 0x08, 0x8E);
   idt_set_gate(40, (uint32)irq8  , 0x08, 0x8E);
   idt_set_gate(41, (uint32)irq9  , 0x08, 0x8E);
   idt_set_gate(42, (uint32)irq10 , 0x08, 0x8E);
   idt_set_gate(43, (uint32)irq11 , 0x08, 0x8E);
   idt_set_gate(44, (uint32)irq12 , 0x08, 0x8E);
   idt_set_gate(45, (uint32)irq13 , 0x08, 0x8E);
   idt_set_gate(46, (uint32)irq14 , 0x08, 0x8E);
   idt_set_gate(47, (uint32)irq15 , 0x08, 0x8E);

   // Remap the irq table.
   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);

   k_log(1, "IRQ", "IRQ Setup complete!");
}

void init_idt()
{
   idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
   idt_ptr.base  = (uint32)&idt_entries;

   memset(&idt_entries, 0, sizeof(idt_entry_t)*256);



   idt_set_gate(0,  (uint32)isr0  , 0x08, 0x8E);
   idt_set_gate(1,  (uint32)isr1  , 0x08, 0x8E);
   idt_set_gate(2,  (uint32)isr2  , 0x08, 0x8E);
   idt_set_gate(3,  (uint32)isr3  , 0x08, 0x8E);
   idt_set_gate(4,  (uint32)isr4  , 0x08, 0x8E);
   idt_set_gate(5,  (uint32)isr5  , 0x08, 0x8E);
   idt_set_gate(6,  (uint32)isr6  , 0x08, 0x8E);
   idt_set_gate(7,  (uint32)isr7  , 0x08, 0x8E);
   idt_set_gate(8,  (uint32)isr8  , 0x08, 0x8E);
   idt_set_gate(9,  (uint32)isr9  , 0x08, 0x8E);
   idt_set_gate(10, (uint32)isr10 , 0x08, 0x8E);
   idt_set_gate(11, (uint32)isr11 , 0x08, 0x8E);
   idt_set_gate(12, (uint32)isr12 , 0x08, 0x8E);
   idt_set_gate(13, (uint32)isr13 , 0x08, 0x8E);
   idt_set_gate(14, (uint32)isr14 , 0x08, 0x8E);
   idt_set_gate(15, (uint32)isr15 , 0x08, 0x8E);
   idt_set_gate(16, (uint32)isr16 , 0x08, 0x8E);
   idt_set_gate(17, (uint32)isr17 , 0x08, 0x8E);
   idt_set_gate(18, (uint32)isr18 , 0x08, 0x8E);
   idt_set_gate(19, (uint32)isr19 , 0x08, 0x8E);
   idt_set_gate(20, (uint32)isr20 , 0x08, 0x8E);
   idt_set_gate(21, (uint32)isr21 , 0x08, 0x8E);
   idt_set_gate(22, (uint32)isr22 , 0x08, 0x8E);
   idt_set_gate(23, (uint32)isr23 , 0x08, 0x8E);
   idt_set_gate(24, (uint32)isr24 , 0x08, 0x8E);
   idt_set_gate(25, (uint32)isr25 , 0x08, 0x8E);
   idt_set_gate(26, (uint32)isr26 , 0x08, 0x8E);
   idt_set_gate(27, (uint32)isr27 , 0x08, 0x8E);
   idt_set_gate(28, (uint32)isr28 , 0x08, 0x8E);
   idt_set_gate(29, (uint32)isr29 , 0x08, 0x8E);
   idt_set_gate(30, (uint32)isr30 , 0x08, 0x8E);
   idt_set_gate(31, (uint32)isr31 , 0x08, 0x8E);

   k_log(1, "IDT/ISR", "IDT/ISR Setup complete!");

   irq_init();

   idt_flush((uint32)&idt_ptr);

   asm volatile ("sti");

}
interrupt.S

Code: Select all

.intel_syntax noprefix
.text
 # In isr.c
.extern isr_handler

# This is our common ISR stub. It saves the processor state, sets
# up for kernel mode segments, calls the C-level fault handler,
# and finally restores the stack frame.
isr_common_stub:
   pusha                    # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

   mov ax, ds               # Lower 16-bits of eax = ds.
   push eax                 # save the data segment descriptor

   mov ax, 0x10  # load the kernel data segment descriptor
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   call isr_handler

   pop eax        # reload the original data segment descriptor
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   popa                     # Pops edi,esi,ebp...
   add esp, 8     # Cleans up the pushed error code and pushed ISR number
   sti
   iret           # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP


.extern irq_handler
irq_common_stub:
   pusha                    # Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

   mov ax, ds               # Lower 16-bits of eax = ds.
   push eax                 # save the data segment descriptor

   mov ax, 0x10  # load the kernel data segment descriptor
   mov ds, ax
   mov es, ax
   mov fs, ax
   mov gs, ax

   call irq_handler

   pop ebx        # reload the original data segment descriptor
   mov ds, bx
   mov es, bx
   mov fs, bx
   mov gs, bx

   popa                     # Pops edi,esi,ebp...
   add esp, 8     # Cleans up the pushed error code and pushed ISR number
   sti
   iretd           # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP


.macro ISR_NOERROR ARG1

.global isr\ARG1
isr\ARG1:
  cli                 # Disable interrupts
  push 0        # Push a dummy error code (if ISR0 doesn't push it's own error code)
  push \ARG1        # Push the interrupt number (0)
  jmp isr_common_stub # Go to our common handler.

.endm

.macro IRQ ARG1, ARG2

.global irq\ARG1
  irq\ARG1:
    cli
    push 0
    push \ARG2
    jmp irq_common_stub

.endm

# ISR Macro 0 - 31
ISR_NOERROR 0
ISR_NOERROR 1
ISR_NOERROR 2
ISR_NOERROR 3
ISR_NOERROR 4
ISR_NOERROR 5
ISR_NOERROR 6
ISR_NOERROR 7
ISR_NOERROR 8
ISR_NOERROR 9
ISR_NOERROR 10
ISR_NOERROR 11
ISR_NOERROR 12
ISR_NOERROR 13
ISR_NOERROR 14
ISR_NOERROR 15
ISR_NOERROR 16
ISR_NOERROR 17
ISR_NOERROR 18
ISR_NOERROR 19
ISR_NOERROR 20
ISR_NOERROR 21
ISR_NOERROR 22
ISR_NOERROR 23
ISR_NOERROR 24
ISR_NOERROR 25
ISR_NOERROR 26
ISR_NOERROR 27
ISR_NOERROR 28
ISR_NOERROR 29
ISR_NOERROR 30
ISR_NOERROR 31

# IRQ Macro 0 - 15 (32 - 47)
IRQ 0 ,  32
IRQ 1 ,  33
IRQ 2 ,  34
IRQ 3 ,  35
IRQ 4 ,  36
IRQ 5 ,  37
IRQ 6 ,  38
IRQ 7 ,  39
IRQ 8 ,  40
IRQ 9 ,  41
IRQ 10,  42
IRQ 11,  43
IRQ 12,  44
IRQ 13,  45
IRQ 14,  46
IRQ 15,  47
isr.c

Code: Select all

#include "isr.h"

isr_t interrupt_handlers[256];

void isr_handler(registers_t regs)
{
	ee_printf("\nReceived Interrupt: 0x%X", regs.int_no);
}

void irq_handler(registers_t regs)
{
	if(regs.int_no >= 40)
	{
		outb(0xA0, 0x20);
	}

	outb(0x20, 0x20);

	vga_writestring("\nIRQ!");

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

}

void register_interrupt_handler(uint8 n, isr_t handler){
	interrupt_handlers[n] = handler;
}
pit.c

Code: Select all

#include "pit.h"

uint32 tick = 0;

static void pit_tick_handler(registers_t regs)
{
	++tick;

	ee_printf("\nTick: %d", tick);
}


void pit_init(uint32 freq)
{
	register_interrupt_handler(IRQ0, &pit_tick_handler);

	uint32 divisor = INPUT_CLOCK / freq;

	// Send command byte
	outb(0x43, 0x34);

	uint8 low = (divisor & 0xFF);
	uint8 hight = ((divisor >> 8) & 0xFF);

	// Send the divisor
	outb(0x40, low);
	outb(0x40, hight);
}

Re: IRQ's not working (Yep, another one)

Posted: Sun Jan 12, 2014 7:15 pm
by sortie
Oh hey, it is the same bug as in that other thread.

Re: IRQ's not working (Yep, another one)

Posted: Thu Jan 16, 2014 8:20 am
by mbrla0
Nevermind, the problem was my code halting after a cli :oops: