Page 1 of 1

inb(0x60) always gives zero on the IRQ1

Posted: Thu Jan 15, 2026 3:42 am
by yucarp
So I have been developing my kernel a little bit and while testing I noticed something. When I press a key it appears as a blank character on the screen. When I checked for the value, inb(0x60) was always returning zero, no matter which key I pressed. I couldn't find any problem with the inb() function, as the keyboard was initialized. The values seem to be read by the kernel as can be seen on the QEMU log. The wiki says that it's a key detection error or internal buffer overrun but I couldn't figure out why it's happening.

The QEMU log:

Code: Select all

pckbd_kbd_read_status 0x1c
pckbd_kbd_read_status 0x1c
pckbd_kbd_read_status 0x1c
pckbd_kbd_write_command 0xae
ps2_keyboard_event 0x557537a2ac58 qcode 23 down 1 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_put_keycode 0x557537a2ac58 keycode 0x15
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0x15
ps2_keyboard_event 0x557537a2ac58 qcode 23 down 0 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_put_keycode 0x557537a2ac58 keycode 0xf0
ps2_put_keycode 0x557537a2ac58 keycode 0x15
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0xf0
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0x15
The PS/2 initialization code:

Code: Select all

int initialize_ps2(){
        uint8_t status = 0;

        outb(PS2_COMMAND, 0xAD);
        wait_ps2();
        outb(PS2_COMMAND, 0xA7);
        wait_ps2();

        int timeout = 0;
        for(; timeout < 1024; ++timeout){

            inb(PS2_DATA);

            if(!(inb(PS2_COMMAND) & 1)){
                break;
            }
        }

        if(timeout == 1023) return -1;

        outb(PS2_COMMAND, 0x20);
        wait_ps2();
        status = inb(PS2_DATA);
        wait_ps2();

        status |= 0b0101001;

        outb(PS2_COMMAND, 0x60);
        wait_ps2();
        outb(PS2_DATA, status);
        wait_ps2();

        outb(PS2_COMMAND, 0xAE);

        set_irq_function(1, &ps2_handler);
        return 0;
}


Re: inb(0x60) always gives zero on the IRQ1

Posted: Thu Jan 15, 2026 11:03 am
by BenLunt

Code: Select all

ps2_keyboard_event 0x557537a2ac58 qcode 23 down 1 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_put_keycode 0x557537a2ac58 keycode 0x15
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0x15
ps2_keyboard_event 0x557537a2ac58 qcode 23 down 0 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_put_keycode 0x557537a2ac58 keycode 0xf0
ps2_put_keycode 0x557537a2ac58 keycode 0x15
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0xf0
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0x15
Reading in a 0x00 is probably because there is nothing there to read. Let me explain.

Since you did not post your actual ISR handler, I don't know for sure, but from the log above, and knowing that most people when just starting with the PS2 (myself included so, oh so long ago), assume that when the interrupt fires, you can read multiple keycodes when expecting a multi-byte key event.

When the interrupt fires, does your handler read in the 0xF0 and then try to read in the 0x15 in the same event? If so, you cannot do this. You must only read in the 0xF0, place it in a buffer, then exit the ISR. On the next interrupt, read in the 0x15.

I am not too familiar with QEMU's log, but I would expect the following log if you read the bytes correctly:

Code: Select all

ps2_keyboard_event 0x557537a2ac58 qcode 23 down 1 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_put_keycode 0x557537a2ac58 keycode 0x15
ps2_put_keycode 0x557537a2ac58 keycode 0xf0
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0x15
ps2_keyboard_event 0x557537a2ac58 qcode 23 down 0 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_read_data 0x557537a2ac58
pckbd_kbd_read_data 0xf0
ps2_keyboard_event 0x557537a2ac?? qcode 23 down 0 modifier 0x0 modifiers 0x0 set 2 xlate 0
ps2_read_data 0x557537a2ac??
pckbd_kbd_read_data 0x15
Does that make sense?

- Ben
https://www.fysnet.net/osdesign_book_series.htm

Re: inb(0x60) always gives zero on the IRQ1

Posted: Thu Jan 15, 2026 11:53 am
by yucarp
Currently I am just taking the keyboard output and printing them on the screen. I know that ASCII letters aren't equal to keycodes but I was too busy doing other things such as a scheduler, a memory manager etc. I am just reading a byte per interrupt.

Code: Select all

void ps2_handler(struct x86Registers *regs){
    uint8_t key = inb(PS2_DATA);
    *(char *)(0xB8000) = key + 0x30; //I will implement a kprintf function outside of the kernel later
    acknowledge_irq(1);
}

Re: inb(0x60) always gives zero on the IRQ1

Posted: Thu Jan 15, 2026 8:56 pm
by Octocontrabass
Your inline assembly doesn't work. It should be something like this:

Code: Select all

asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");

Re: inb(0x60) always gives zero on the IRQ1

Posted: Fri Jan 16, 2026 12:23 am
by OSdeving123
it means you have no buffer

Code: Select all

char buffer[64];

Re: inb(0x60) always gives zero on the IRQ1

Posted: Fri Jan 16, 2026 12:48 am
by yucarp
I was wondering why compiler threw an error when putting = to the "a" operand, I was putting it on the wrong place...

Code: Select all

asm volatile("inb %w1, %b0" :: "a"(value), "Nd"(port) : "memory");
					      ^ this should be here

Code: Select all

asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
Thank you for all of your answers