8259-Problem(My ISR is not called)

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.
Freanan

8259-Problem(My ISR is not called)

Post 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..?
nullify

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

Post by nullify »

Are interrupts enabled? asm("sti")
Freanan

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

Post 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?
beyondsociety

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

Post 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).
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

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

Post 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.
Freanan

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

Post 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...?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

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

Post 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 ...
Therx

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

Post 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
nullify

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

Post 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);
Freanan

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

Post 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.
nullify

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

Post 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?
Freanan

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

Post 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.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

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

Post 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
nullify

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

Post 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).
Freanan

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

Post 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
Post Reply