Page 1 of 1

keyboard

Posted: Fri Nov 23, 2018 3:50 pm
by drnono
I'm trying to write a keyboard driver. Some device commands get sent to bochs, as I can see from the console, but none of them get a response at the 0x60 data port. The data port only seems to respond to PS2 commands.

Code: Select all

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>


enum PS2_CONTROLLER
{
	PS2_DATA_PORT  = 0x60,
	PS2_STATUS_REGISTER = 0x64,
	PS2_COMMAND_REGISTER = 0x64,

	// status register
	PS2_OUTPUT_BUFFER_STATUS = 0b1,	// Must be set before reading 0x60 (0=empty, 1=full)
	PS2_INPUT_BUFFER_STATUS = 0b10,	// must be clear before writing 0x60 (0=empty, 1=full)

	//READ_BYTE = 0x20;	// response is Controller Configuration Byte
	//WRITE_BYTE = 0x60;
	// command port
	PS2_READ_CONTROLLER_OUTPUT = 0xd0,
	PS2_WRITE_CONTROLLER_OUTPUT = 0xd1,  // check if output buffer is empty first
	DISABLE_PS2_0 = 0xa7,
	ENABLE_PS2_0 = 0xa8,
	TEST_PS2_0 = 0xa9,
	TEST_PS2_CONTROLLER = 0xaa,
	TEST_PS2_1 = 0xaB,
	DISABLE_PS2_1 = 0xad,
	ENABLE_PS2_1 = 0xae,

	// device commands ? keyboard  ==> data port
	PS2_IDENTIFY_DEVICE = 0xf2,
	PS2_ENABLE_SCANNING = 0xf4,  // 0xfa=ACK, 0xfe=RESEND
	PS2_DISABLE_SCANNING = 0xf5,
	PS2_RESET_SELF_TEST = 0xff // 0xaa=pass

};

void kmain()
{
	print_char('C', 25, 79,0);

	//disable interrupts
	outb( PS2_COMMAND_REGISTER, 0x20);
	wait();
	uint8_t y = inb(0x60);
	outb( PS2_COMMAND_REGISTER,0x60);
	wait();
	outb( PS2_DATA_PORT, (y & 0b10111100) );   // disable interrups
	wait();
	
	outb( PS2_COMMAND_REGISTER, ENABLE_PS2_0 );
	wait();
	outb( PS2_COMMAND_REGISTER, ENABLE_PS2_1 );
	wait();
	outb( PS2_DATA_PORT, 0xf6 );        // set default params
	wait();
	outb( PS2_DATA_PORT, PS2_ENABLE_SCANNING );
	wait();
	outb( PS2_DATA_PORT, PS2_IDENTIFY_DEVICE );
	wait();
	print_byte(inb(PS2_DATA_PORT),20,0,1);
	wait();
	print_byte(inb(PS2_DATA_PORT),20,0,2);


	// see if key codes are being sent on port 0x60
	uint8_t volatile value;
	while (1)
	{
		wait();
		value = inb(0x60);
		print_byte(value, 25,0,0);
		wait();
	}


	asm("cli");
	while (1) { asm("hlt"); }
}

Re: keyboard

Posted: Sat Nov 24, 2018 2:23 am
by Octocontrabass
How long are you waiting in wait()? If it's too short, you may never see the key presses/releases displayed on the screen before they're replaced by zero.

Why do you try to read the keyboard ID with scanning enabled? It may confuse Bochs, since no real OS ever does that. (It may also confuse real hardware!)

Re: keyboard

Posted: Sat Nov 24, 2018 10:14 am
by drnono
I'm using the wait() from https://wiki.osdev.org/Inline_Assembly/Examples

It seems that I only get a response from the data port 0x60 when I send PS2 controller commands and not device commands - it's like they're being ignored. The data port is stuck at the values of response from controller commands like self test and port test even when I read from the data port in an infinite loop and mash the keyboard.

This ...

Code: Select all

outb( PS2_DATA_PORT, PS2_DISABLE_SCANNING );
wait();
outb( PS2_DATA_PORT, PS2_IDENTIFY_DEVICE );

while ( (inb ( PS2_STATUS_REGISTER ) & PS2_OUTPUT_BUFFER_STATUS) != 0b1 ) { wait(); }
just gets stuck in a loop - status register doesn't change !?

Re: keyboard

Posted: Sun Nov 25, 2018 9:04 am
by Octocontrabass
drnono wrote:I'm using the wait() from https://wiki.osdev.org/Inline_Assembly/Examples
Which one? The first one is only effective on CPUs predating the original Pentium!

On Bochs, such waits should be unnecessary anyway, since it doesn't emulate a keyboard controller with any level of accuracy.
drnono wrote:It seems that I only get a response from the data port 0x60 when I send PS2 controller commands and not device commands - it's like they're being ignored. The data port is stuck at the values of response from controller commands like self test and port test even when I read from the data port in an infinite loop and mash the keyboard.
Odd. I don't see anything in your code that would cause that. Have you tried enabling debug messages for the keyboard device in Bochs? The source code shows quite a few messages that might help you figure out what's wrong.

Re: keyboard

Posted: Sun Nov 25, 2018 1:15 pm
by MichaelPetch
Some off the wall thought. I hope you aren't building your kernel as 64-bit code and running it in 32-bit protected mode.

Re: keyboard

Posted: Tue Nov 27, 2018 11:57 am
by drnono
I tried a similar while loop to scan the CMOS timer and that also fails to show any changes in the loop.

Code: Select all

   
uint8_t volatile value;
uint8_t volatile i;  

outb(0x70),0;   // read seconds from 0x71
while (1)
{
      value = inb(0x71);
      print_byte(value, 20,0,0); // only prints 1 value
      print_char(i,20,3,0);  // print all the ascii - works
      i++;
}
   
I can loop read as above from the CMOS and from the keyboard from assembly and debian - it works.

Re: keyboard

Posted: Tue Nov 27, 2018 12:11 pm
by eryjus
drnono wrote:

Code: Select all

   
outb(0x70),0;   // read seconds from 0x71
I assume this is a typo pasting to the forum....

Have you checked your inb() and outb() code?

Re: keyboard

Posted: Tue Nov 27, 2018 12:40 pm
by drnono
Thanks, got it fixed now. It was inb, outb functions