inb(0x60) always gives zero on the IRQ1

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.
Post Reply
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

inb(0x60) always gives zero on the IRQ1

Post 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;
}

User avatar
BenLunt
Member
Member
Posts: 1029
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

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

Post 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
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

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

Post 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);
}
Octocontrabass
Member
Member
Posts: 6245
Joined: Mon Mar 25, 2013 7:01 pm

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

Post 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");
OSdeving123
Posts: 2
Joined: Fri Jan 16, 2026 12:13 am

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

Post by OSdeving123 »

it means you have no buffer

Code: Select all

char buffer[64];
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

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

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