Page 1 of 2

8259-Problem(My ISR is not called)

Posted: Wed Aug 27, 2003 4:56 am
by Freanan
I just tried to init and remap the PIC and to enable irq 1, so that an isr should be called when hitting the keyboard.
The problem is, that when i hit a key, nothing happens.
When i call the interrupt via 'int 0x21' it is called properly, so the problem must be something about the PIC or the Keyboard itsself.
Here are the important Parts of my code:

Code: Select all

void kmain(void)
{
 InitPIC(0x20,0x28);//IRQ0=Int20h, IRQ8=Int28h
 enable_irq(1);
 for (;;);                 
};
Here is the very simple ISR itsself - it is installed in my assembler-setuproutine

Code: Select all

void irqstd()
{
 kprint("Hardware-Interrupt!",RED);
 for(;;);
};
This is my PIC-Initialisation code and the irq-enabling function:

Code: Select all


#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01

void InitPIC(int pic1, int pic2)
{
 //ICW1
 outportb(PIC1,ICW1);
 outportb(PIC2,ICW1);
 //ICW2--> Remap
 outportb(PIC1+1,pic1);
 outportb(PIC2+1,pic2);
 //ICW3
 outportb(PIC1+1,4);
 outportb(PIC2+1,2);
 //ICW4
 outportb(PIC1+1,ICW4);
 outportb(PIC2+1,ICW4);
 //Disable all irqs
 outportb(PIC1+1,0xFF);
};

unsigned int irq_mask = 0xFFFF;

//enable IRQ
void enable_irq(unsigned short irq_no)
{
 irq_mask &= ~(1 << irq_no);
 if(irq_no >= 8)
   irq_mask &= ~(1 << 2);

 outportb(PIC1+1, irq_mask & 0xFF);
 outportb(PIC2+1, (irq_mask >> 8) & 0xFF);
}
And this is the outportb-routine which i get from GazOS:

Code: Select all

inline void outportb(unsigned int port,unsigned char value)   
{
 asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value));
}
I saw this all done very similarly... did i forget something..?

Re:8259-Problem(My ISR is not called)

Posted: Wed Aug 27, 2003 7:58 am
by nullify
Are interrupts enabled? asm("sti")

Re:8259-Problem(My ISR is not called)

Posted: Wed Aug 27, 2003 3:07 pm
by Freanan
nullify wrote: Are interrupts enabled? asm("sti")
Thanks for your advice! I added 'sti' to make sure, that Interrupts are enabled.
Now i get ONE Interrupt, but without pressing any key :o. Pressing a key after that does again not call my ISR.
I'm just getting into the PIC and Keyboard stuff-
do i have to send special stuff to the Keyboard or to the PIC at the end of my ISR to enable the handling of further interrupts or something like that?

Re:8259-Problem(My ISR is not called)

Posted: Wed Aug 27, 2003 4:12 pm
by beyondsociety
Pressing a key after that does again not call my ISR.
The computer won't send another interrupt until you send an EOI(end of interrupt).

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 1:15 am
by Pype.Clicker
btw, with an interrupt handler that has an endless loop in it (for (;;); ), i'm not surprised you get no more than 1 interrupt :p

For the keyboard, as for other interrupts on the master PIC, the "End Of Interrupt" is just sending value 0x20 on port 0x20.

For devices on the second PIC (hard disk, mouse, etc.) you must send 0x20 on both 0x20 and 0xa0 ports.

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 2:17 am
by Freanan
Thought about sending eoi myself last night-
i added : "outportb(PIC1,0x20);" before the loop but it still did not work.

But you say with a looping-isr it will never work
-OK, so i will instead do an iret at the end!
I just thought the isr might be interrupted itsself...
Will try it, thank you!

Edit:
I tried it - now i get one Hardware Interrupt and one Exception. Perhaps i should add all the code to save registers and so on...?

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 3:35 am
by Pype.Clicker
oh dear... why isn't this in the FAQ already ?

you cannot just issue an asm("iret") in a C function an hope it will be a valid Interrupt Service Routine

You need a specific stub that will be called by the CPU, save everything *then* call your C function and when the C function return, restore everything and IRET ...

Giving a look at your disassembled C function (especially pushes and pops) will let you better understand.

this thread should give you required inspiration ...

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 5:18 am
by Therx
If this is the keyboard ISR then you also need to read a byte from port 0x60 before it will send another interrupt

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 11:01 am
by nullify
Freanan wrote:Perhaps i should add all the code to save registers and so on...?
Yes. Basically you want an assembly wrapper around your C handler which does all the stuff of a valid ISR. Here's a simple example of what I mean:

Code: Select all

/* assembly wrapper */
void asmstub_kbhandler(void);
__asm__
(
".text\n"
".globl asmstub_kbhandler\n"
"asmstub_kbhandler:\n"
"   pusha\n"          /* preserve registers */
"   call kbhandler\n"
"   popa\n"          /* restore register contents */
"   iret\n"          /* Interrupt RETurn */
);

/* C handler */
void kbhandler()
{
   /* must read port 60h on each keyboard interrupt,
 so you can continue receiving keyboard interrupts */
   char byte = inb(0x60);

   kprintf("keyboard interrupt received\n");

   /* send end-of-interrupt to PIC for the same reason */
   outb(0x20, 0x20);
}

...
/* put the assembly stub in the IDT */
set_idt_entry(0x21, (unsigned int)asmstub_kbhandler);

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 1:34 pm
by Freanan
I added the wrapper function to my assembler-startup-file, where i also setup the idt:

Code: Select all

EXTERN irqstd

;Other code...

irqwrap:
pusha
push gs
push fs
push es
push ds
mov eax, 0x10
mov ds, eax
mov es, eax
call irqstd
pop ds
pop es
pop fs
pop gs
popa
iret
Good to know, that i have to read from 0x60 to get more Keyboard-ints!
I added it to my isr...

Code: Select all

void irqstd()
{
 char inbyte;
 inbyte=inportb(0x60);
 kprint("Hardware-Interrupt!",RED);
 outportb(PIC1, 0x20);//EOI
};
But all this has not changed anything - i get one interrupt and then an exception when trying to return with iret.

A really strange thing is, that i got no exception, when i tried to return with 'iret' from another isr, that i had inside my assembler-startup-file.

Re:8259-Problem(My ISR is not called)

Posted: Thu Aug 28, 2003 4:25 pm
by nullify
Freanan wrote:A really strange thing is, that i got no exception, when i tried to return with 'iret' from another isr, that i had inside my assembler-startup-file.
Strange indeed. Did you set up the other (working) ISR any differently in the IDT compared with your keyboard ISR?

Re:8259-Problem(My ISR is not called)

Posted: Fri Aug 29, 2003 2:08 am
by Freanan
nullify wrote:
Freanan wrote:A really strange thing is, that i got no exception, when i tried to return with 'iret' from another isr, that i had inside my assembler-startup-file.
Strange indeed. Did you set up the other (working) ISR any differently in the IDT compared with your keyboard ISR?
No! Both times i used the following descriptor - the difference was only the name of the isr:

Code: Select all

dw handler
dw 0x08       
db 0            
db 0x8E      
dw  0    
Even before i tried to use the Keyboard, returning from assembler-isr's worked, but returning from c-isr's did cause a reboot or an exception.
My assembler-routine did'nt even save any registers:

Code: Select all

handler:
mov byte [0xB8000], "I" 
mov byte [0xB8001],  4
iret
I would just write everything in assembler, but i am not that good at it, so i'd preffer the use of C.

Re:8259-Problem(My ISR is not called)

Posted: Fri Aug 29, 2003 2:36 am
by Pype.Clicker
remember that way of setting up an IRQ handler is dangerous for it assumes the address of the handler will be in the first 64K of the code segment ... Now, i admit this doesn't explain why you get a fault "on iret".

Maybe you should use bochs's internal debugger and see what's on the stack (either with print-stack, but this doesn't seem to work in pmode, or using dump_cpu and then x <virtual address> (iirc))

You can also set up a breakpoint on *iret* if post-mortem debugging doesn't work.

Btw, make sure you checked there was no buffer overflow nor uninitialized pointers in the C code you call, for it may result in damaged stack and errors while unpopping stuff ...

So, be wise, everywhere you see char *var; make sure you replace it with char *var=NULL; :p

Re:8259-Problem(My ISR is not called)

Posted: Fri Aug 29, 2003 9:11 am
by nullify
Freanan wrote: My assembler-routine did'nt even save any registers:

Code: Select all

handler:
mov byte [0xB8000], "I" 
mov byte [0xB8001],  4
iret
It worked even though you didn't save any registers because you never modified any registers in the ISR in the first place :-)

Also, that last word of an IDT entry is supposed to contain the upper 16-bits of the handler address (which may not necessarily be 0).

Re:8259-Problem(My ISR is not called)

Posted: Sat Aug 30, 2003 4:18 am
by Freanan
I just wrote an timer- and an keyboard- interrupt in assembler which (read a byte from 0x60 in the keyboard-isr), put out a character in the variable 'color' and then increment color for the next time, send eoi and iret.

Both work exactly as they should, so i can be sure C did something that causes the fault.


EDIT:
More strange things: I removed the instructions to save ds, es..., so that in the framework there is only left pusha and popa and the iret - and now it works :o