In the code snippet from above, you seem to send EOI twice. What does PIC_SendEOI() do? And why do you need to pass the interrupt number to it?thehardcoreOS wrote:Code: Select all
if (r->int_no >= 40) { outportb(0xA0, 0x20); } outportb(0x20, 0x20); PIC_SendEOI(r->int_no);
[Solved] IRQ Firing Bug
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: IRQ Firing Bug
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: IRQ Firing Bug
Oh I see, I removed this line PIC_SendEOI(1);omarrx024 wrote:In the code snippet from above, you seem to send EOI twice. What does PIC_SendEOI() do? And why do you need to pass the interrupt number to it?thehardcoreOS wrote:Code: Select all
if (r->int_no >= 40) { outportb(0xA0, 0x20); } outportb(0x20, 0x20); PIC_SendEOI(r->int_no);
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Re: IRQ Firing Bug
Here is what it does:
Code: Select all
void PIC_SendEOI(unsigned char irq)
{
if(irq >= 8)
{
outportb(PIC2_COMMAND,PIC_EOI);
}
outportb(PIC1_COMMAND,PIC_EOI);
}
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: IRQ Firing Bug
OK, well does it work now?
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: IRQ Firing Bug
Nope. I noticed that Keyboard_Handler never gets called. RIPomarrx024 wrote:OK, well does it work now?
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: IRQ Firing Bug
That's really odd. Can you make your keyboard handler just put a character on the screen and carefully follow the keyboard initialization code I gave you?thehardcoreOS wrote:Nope. I noticed that Keyboard_Handler never gets called. RIPomarrx024 wrote:OK, well does it work now?
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: IRQ Firing Bug
No I can not make my keyboard_handler do anything, because it never gets called when interrupt happens.omarrx024 wrote:That's really odd. Can you make your keyboard handler just put a character on the screen and carefully follow the keyboard initialization code I gave you?thehardcoreOS wrote:Nope. I noticed that Keyboard_Handler never gets called. RIPomarrx024 wrote:OK, well does it work now?
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: IRQ Firing Bug
And what does that have to do with PIC_SendEOI()?
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: IRQ Firing Bug
omarrx024 wrote:And what does that have to do with PIC_SendEOI()?
I followed wiki.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Re: IRQ Firing Bug
Entire irq.c
entire keyboard.c
Code: Select all
#include "../Include/irq.h"
#define ICW1_ICW4 0x01
#define ICW1_SINGLE 0x02
#define ICW1_INTERVAL4 0x04
#define ICW1_LEVEL 0x08
#define ICW1_INIT 0x10
#define ICW4_8086 0x01
#define ICW4_AUTO 0x02
#define ICW4_BUF_SLAVE 0x08
#define ICW4_BUF_MASTER 0x0C
#define ICW4_SFNM 0x10
#define PIC1 0x20
#define PIC2 0xA0
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20
void *irq_routines[16] ={
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
struct regs
{
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_no, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};
static volatile int sync_depth = 0;
#define SYNC_CLI() asm volatile("cli")
#define SYNC_STI() asm volatile("sti")
void Disable_Interrupts(void)
{
uint32_t flags;
asm volatile("pushf\n\t" "pop %%eax\n\t" "movl %%eax, %0\n\t" : "=r"(flags): : "%eax");
SYNC_CLI();
if (flags & (1 << 9))
{
sync_depth = 1;
}
else
{
sync_depth++;
}
}
void Resume_Interrupts(void)
{
if (sync_depth == 0 || sync_depth == 1)
{
SYNC_STI();
}
else
{
sync_depth--;
}
}
void Enable_Interrupts(void)
{
sync_depth = 0;
SYNC_STI();
}
void IRQ_Uninstall_Handler(int irq)
{
SYNC_CLI();
irq_routines[irq] = 0;
SYNC_STI();
}
void IRQ_Remap(void)
{
outportb(0x20, 0x11);
outportb(0xA0, 0x11);
outportb(0x21, 0x20);
outportb(0xA1, 0x28);
outportb(0x21, 0x04);
outportb(0xA1, 0x02);
outportb(0x21, 0x01);
outportb(0xA1, 0x01);
outportb(0x21, 0x0);
outportb(0xA1, 0x0);
}
void InstallIRQS()
{
IRQ_Remap();
IDTSetGate(32, (unsigned)irq0, 0x08, 0x8E);
IDTSetGate(33, (unsigned)irq1, 0x08, 0x8E);
IDTSetGate(34, (unsigned)irq2, 0x08, 0x8E);
IDTSetGate(35, (unsigned)irq3, 0x08, 0x8E);
IDTSetGate(36, (unsigned)irq4, 0x08, 0x8E);
IDTSetGate(37, (unsigned)irq5, 0x08, 0x8E);
IDTSetGate(38, (unsigned)irq6, 0x08, 0x8E);
IDTSetGate(39, (unsigned)irq7, 0x08, 0x8E);
IDTSetGate(40, (unsigned)irq8, 0x08, 0x8E);
IDTSetGate(41, (unsigned)irq9, 0x08, 0x8E);
IDTSetGate(42, (unsigned)irq10, 0x08, 0x8E);
IDTSetGate(43, (unsigned)irq11, 0x08, 0x8E);
IDTSetGate(44, (unsigned)irq12, 0x08, 0x8E);
IDTSetGate(45, (unsigned)irq13, 0x08, 0x8E);
IDTSetGate(46, (unsigned)irq14, 0x08, 0x8E);
IDTSetGate(47, (unsigned)irq15, 0x08, 0x8E);
IRQSSucceeded();
}
void IRQSSucceeded()
{
PrintString("\nIRQS Loaded! ");
PrintColoredString("[ Passed ]", 11, 0);
ResetColors();
}
void IRQ_Set_Mask(unsigned char IRQline)
{
uint16_t port;
uint8_t value;
if(IRQline < 8)
{
port = PIC1_DATA;
}
else
{
port = PIC2_DATA;
IRQline -= 8;
}
value = inportb(port) | (1 << IRQline);
outportb(port, value);
}
void IRQ_Clear_Mask(unsigned char IRQline)
{
uint16_t port;
uint8_t value;
if(IRQline < 8)
{
port = PIC1_DATA;
}
else
{
port = PIC2_DATA;
IRQline -= 8;
}
value = inportb(port) & ~ (1 << IRQline);
outportb(port, value);
}
void PIC_Remap(int offset1, int offset2)
{
unsigned char a1, a2;
a1 = inportb(PIC1_DATA);
a2 = inportb(PIC2_DATA);
outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);
IO_Wait();
outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
IO_Wait();
outportb(PIC1_DATA, offset1);
IO_Wait();
outportb(PIC2_DATA, offset2);
IO_Wait();
outportb(PIC1_DATA, 4);
IO_Wait();
outportb(PIC2_DATA, 2);
IO_Wait();
outportb(PIC1_DATA, ICW4_8086);
IO_Wait();
outportb(PIC2_DATA, ICW4_8086);
IO_Wait();
outportb(PIC1_DATA, a1);
outportb(PIC2_DATA, a2);
}
void PIC_SendEOI(unsigned char irq)
{
if(irq >= 8)
{
outportb(PIC2_COMMAND,PIC_EOI);
}
outportb(PIC1_COMMAND,PIC_EOI);
}
void IRQ_Install_Handler(int irq, void (*handler)(struct regs *r))
{
///SYNC_CLI();
irq_routines[irq] = handler;
//SYNC_STI(); //if I enable this line I get only one interrupt
PrintString("IRQ install handler call for irq");
PrintString(IntToString(irq));
}
void IRQ_Handler(struct regs *r)
{
//Disable_Interrupts();
void (*handler)(struct regs *r);
handler = irq_routines[r->int_no - 32];
if (handler)
{
handler(r);
//Resume_Interrupts();
}
if (r->int_no >= 40)
{
outportb(0xA0, 0x20);
}
outportb(0x20, 0x20);
PrintString("\nIRQ_Handler Called from asm with interupt number ");
PrintString(IntToString(r->int_no));
}
Code: Select all
#include "../Include/keyboard.h"
struct regs
{
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_no, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};
unsigned char kbdus[128] =
{
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'q', 'w', 'e', 'r', /* 19 */
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
0, /* 29 - Control */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
'\'', '`', 0, /* Left shift */
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
'm', ',', '.', '/', 0, /* Right shift */
'*',
0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 key ... > */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* < ... F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home key */
0, /* Up Arrow */
0, /* Page Up */
'-',
0, /* Left Arrow */
0,
0, /* Right Arrow */
'+',
0, /* 79 - End key*/
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert Key */
0, /* Delete Key */
0, 0, 0,
0, /* F11 Key */
0, /* F12 Key */
0, /* All other keys are undefined */
};
void KeyboardSucceeded()
{
PrintString("\nKeyboard Loaded! ");
PrintColoredString("[ Passed ]", 11, 0);
ResetColors();
}
void Keyboard_Handler(struct regs *r)
{
PrintString("Keyboard Handler Called");
unsigned char scancode;
scancode = inportb(0x60);
if (scancode & 0x80)
{
//use this to see if user released any control keys aka shift ctrl alt altgr
}
else
{
PrintString(kbdus[scancode]);
WriteOutputToQemu(kbdus[scancode]);
}
PIC_SendEOI(1);
}
uint8 PS2_Send(uint8 data)
{
PS2_Wait_Write();
outportb(0x60, data);
PS2_Wait_Read();
return inportb(0x60);
}
void InstallKeyboard()
{
PS2_Send(0xFF);
PS2_Send(0xF3);
PS2_Send(0x20);
PS2_Send(0xF0);
PS2_Send(0x02);
PS2_Send(0xFA);
PS2_Send(0xF4);
IRQ_Install_Handler(33, &Keyboard_Handler);
KeyboardSucceeded();
}
void PS2_Wait_Write()
{
while(inportb(0x64) & 2 == 0);
}
void PS2_Wait_Read()
{
while(inportb(0x64) & 1 == 0);
}
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Re: IRQ Firing Bug
This keyboard setup doesnt work for me on VBox.
Using simple PS2_Send(0xF4); only works fine for me on all emulators and machines (Qemu, Bochs, VBox, VMWare)
I didnt read your code but it looks like you copy and pasted some stuff and didnt completely understood how it works.
I suggest reading another tutorial in this case.
You should also empty your keyboard buffer like this:
Using simple PS2_Send(0xF4); only works fine for me on all emulators and machines (Qemu, Bochs, VBox, VMWare)
I didnt read your code but it looks like you copy and pasted some stuff and didnt completely understood how it works.
I suggest reading another tutorial in this case.
You should also empty your keyboard buffer like this:
Code: Select all
while (inb(0x64) & 0x1)
inb(0x60);
Re: IRQ Firing Bug
Okay, I added clear buffer code inside my keyboard handler. There is no point of making a proper keyboard driver if I can't get my IRQ to fire up my keyboard handler (in this case).Ch4ozz wrote:This keyboard setup doesnt work for me on VBox.
Using simple PS2_Send(0xF4); only works fine for me on all emulators and machines (Qemu, Bochs, VBox, VMWare)
I didnt read your code but it looks like you copy and pasted some stuff and didnt completely understood how it works.
I suggest reading another tutorial in this case.
You should also empty your keyboard buffer like this:Code: Select all
while (inb(0x64) & 0x1) inb(0x60);
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
- BrightLight
- Member
- Posts: 901
- Joined: Sat Dec 27, 2014 9:11 am
- Location: Maadi, Cairo, Egypt
- Contact:
Re: IRQ Firing Bug
That's odd. My keyboard setup works on VBox, Bochs, QEMU, VMware and two real PCs.Ch4ozz wrote:This keyboard setup doesnt work for me on VBox.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
Re: IRQ Firing Bug
So... is there a solution? I just can't fix this myself. Handlers get installed but never called again, only when I enable interrupts with sti they get called once and never again.omarrx024 wrote:That's odd. My keyboard setup works on VBox, Bochs, QEMU, VMware and two real PCs.Ch4ozz wrote:This keyboard setup doesnt work for me on VBox.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Re: IRQ Firing Bug
Either you are not acknowledging the interrupt or you are not reading the character from the keyboard. A little simple debugging, single-stepping through the code, should tell you which.