Setting the Scan Code set

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
User avatar
zvoncika
Posts: 13
Joined: Wed Aug 16, 2017 12:38 am
Location: Wonderland

Setting the Scan Code set

Post by zvoncika »

I'm using the following code to try and set the Scan Code set ( 2 ).

Code: Select all

outb(0x60,0xF0);
	outb(0x64,0x02);
However,when I try to boot my OS in QEMU or VirtualBox they both reset.
Bochs doesn't.
What am I doing wrong here?
Here is my init function:

Code: Select all

void ps2_keyboard_install()
{
	while(inb(PS2_KB_CMD) & 0x1)
		inb(PS2_KB_DATA);
	// Test the PS/2 controller
	outb(PS2_KB_CMD,0xAA);
	if(inb(PS2_KB_DATA) != 0x55)
	{
		// PS/2 Controller test failed
		// Kernel Panic
		asm volatile("int $19");
	}
	// Test the first port
	outb(PS2_KB_CMD,0xAB);
	if(inb(PS2_KB_DATA) != 0x00)
	{
		// First port didn't pass the test
		// Kernel Panic
		asm volatile("int $19");
	}
	// Enable the first port
	outb(PS2_KB_CMD,0xAE);
	// Set SCS
	outb(PS2_KB_CMD,0xF0);
	outb(PS2_KB_DATA,0x02);
	// Get config
	outb(PS2_KB_CMD,0x20);
	uint8_t cfg = (inb(PS2_KB_DATA) | 1) & ~0x10;
	// Set config
	outb(PS2_KB_CMD,0x60);
	outb(PS2_KB_DATA,cfg);
	// Set scan code set
	// Install our handler
	irq_install_handler(1, ps2_keyboard_handler);
}
Talk is cheap, show me the code.
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: Setting the Scan Code set

Post by Octocontrabass »

Code: Select all

outb(0x60,0xF0);
	outb(0x64,0x02);
This code sends the first byte to the keyboard, and then (without waiting for the keyboard controller to send that byte to the keyboard or receive the keyboard's response) sends an undocumented command to the keyboard controller. This code does not appear to match your ps2_keyboard_install function.

For the rest of your code, I'll assume PS2_KB_CMD is 0x64 and PS2_KB_DATA is 0x60.

Code: Select all

	while(inb(PS2_KB_CMD) & 0x1)
		inb(PS2_KB_DATA);
If there is a fault with the keyboard controller, this may become an infinite loop.

Code: Select all

	outb(PS2_KB_CMD,0xAA);
	if(inb(PS2_KB_DATA) != 0x55)
	{
Keyboard controller command 0xAA may take a long time to execute, and it may completely reset the keyboard controller to its power-on defaults. You must wait for the keyboard controller to respond, and you may also need to reconfigure it (e.g. to disable translation and set the "system flag").

Code: Select all

	outb(PS2_KB_CMD,0xAB);
	if(inb(PS2_KB_DATA) != 0x00)
	{
Again, you need to wait for the keyboard controller to respond.

Code: Select all

	outb(PS2_KB_CMD,0xAE);
Seriously. Old keyboard controllers are slow. You have to wait.

Code: Select all

	outb(PS2_KB_CMD,0xF0);
This reboots the computer, assuming the keyboard controller is ready to accept this command.

Code: Select all

	outb(PS2_KB_DATA,0x02);
This is not a documented keyboard command. The keyboard may misbehave after you send this.

Code: Select all

	outb(PS2_KB_CMD,0x20);
	uint8_t cfg = (inb(PS2_KB_DATA) | 1) & ~0x10;
	// Set config
	outb(PS2_KB_CMD,0x60);
	outb(PS2_KB_DATA,cfg);
You can probably guess what I'm going to say here: not enough waiting. Also, it's a race condition, since you're enabling IRQ1 before you install an IRQ1 handler.

It looks like you might be confusing the keyboard controller with the keyboard. Both can accept and respond to commands, but sending commands to the keyboard is different from sending commands to the keyboard controller. You should finish initializing your keyboard controller, installing the IRQ handler(s), and enabling the IRQ(s) before you enable the keyboard port and start initializing the keyboard.
User avatar
zvoncika
Posts: 13
Joined: Wed Aug 16, 2017 12:38 am
Location: Wonderland

Re: Setting the Scan Code set

Post by zvoncika »

How long should I wait?
Talk is cheap, show me the code.
User avatar
zvoncika
Posts: 13
Joined: Wed Aug 16, 2017 12:38 am
Location: Wonderland

Re: Setting the Scan Code set

Post by zvoncika »

Should I have a temporary IRQ handler that I'll use while I, configure my PS/2 controller?
Talk is cheap, show me the code.
isaacwoods
Member
Member
Posts: 47
Joined: Sun Sep 06, 2015 5:40 am

Re: Setting the Scan Code set

Post by isaacwoods »

The PS/2 controller tells you when it's ready to be issued commands and whatnot. This is what I use:

Code: Select all

  /*
   * Bit 0 of the status register must be SET before attempting to read data from port 0x60
   * Bit 1 of the status register must be CLEAR before attempting to write data to port 0x60
   */
  #define WAIT_FOR_READ()   while ((inb(PS2_COMMAND) & 1u) == 0u) asm volatile("rep nop");
  #define WAIT_FOR_WRITE()  while ((inb(PS2_COMMAND) & 2u) != 0u) asm volatile("rep nop");
User avatar
zvoncika
Posts: 13
Joined: Wed Aug 16, 2017 12:38 am
Location: Wonderland

Re: Setting the Scan Code set

Post by zvoncika »

Huh, thanks!
Really appreciate all the help you guys give me [-o<
Talk is cheap, show me the code.
Post Reply