diff options
Diffstat (limited to 'src/keyboard.c')
-rw-r--r-- | src/keyboard.c | 96 |
1 files changed, 92 insertions, 4 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index f89332c..c591c6a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,7 +1,62 @@ +#include <stdbool.h> + #include "keyboard.h" #include "stdio.h" +// status register on command port (read) +#define STATUS_REG_OUTPUT_BUF_FULL 0x01 +#define STATUS_REG_INPUT_BUF_FULL 0x02 + +// generic PS/2 commands +#define COMMAND_GET_STATE 0x20 +#define COMMAND_SET_STATE 0x60 +#define COMMAND_DISABLE_PORT1 0xAD +#define COMMAND_ENABLE_PORT1 0xAE + +// keyboard specific commands, PSAUX1 +#define KBD_COMMAND_SET_LEDS 0xED +#define KBD_SET_SCANCODE 0xF0 +#define KBD_ACTIVATE 0xF4 + +#define STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT1 0x01 +#define STATUS_CONTROL_CONFIG_CLOCK_PORT1 0x10 + +// keyboard LED status codes +#define KBD_LED_SCROLL_LOCK_ON 0x01 +#define KBD_LED_NUM_LOCK_ON 0x02 +#define KBD_LED_CAPS_LOCK_ON 0x04 +#define KBD_LED_ALL_OFF 0x00 +#define KBD_LED_ALL_ON KBD_LED_SCROLL_LOCK_ON | KBD_LED_NUM_LOCK_ON | KBD_LED_CAPS_LOCK_ON + +// keyboard scan codes +#define KBD_SCANCODE_1 0x01 +#define KBD_SCANCODE_2 0x02 +#define KBD_SCANCODE_3 0x03 + +static bool has_data( keyboard_t *keyboard ) +{ + return ( port8_read( &keyboard->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) == STATUS_REG_OUTPUT_BUF_FULL; +} + +static uint8_t read_data( keyboard_t *keyboard ) +{ + while( ( port8_read( &keyboard->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) == 0 ) { } + return port8_read( &keyboard->data_port ); +} + +static void send_command( keyboard_t *keyboard, uint8_t command ) +{ + while( port8_read( &keyboard->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { } + port8_write( &keyboard->command_port, command ); +} + +static void write_data( keyboard_t *keyboard, uint8_t data ) +{ + while( port8_read( &keyboard->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { } + port8_write( &keyboard->data_port, data ); +} + void keyboard_init( keyboard_t *keyboard ) { memset( keyboard, 0, sizeof( keyboard_t ) ); @@ -9,14 +64,47 @@ void keyboard_init( keyboard_t *keyboard ) port8_init( &keyboard->command_port, 0x64 ); port8_init( &keyboard->data_port, 0x60 ); + // first switch off port 1 + send_command( keyboard, COMMAND_DISABLE_PORT1 ); + + // consume character pressed before executing the kernel + while( port8_read( &keyboard->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) { + port8_read( &keyboard->data_port ); + } + + // enable port 1 + send_command( keyboard, COMMAND_ENABLE_PORT1 ); + + // enable interrupts for port 1 + send_command( keyboard, COMMAND_GET_STATE ); + uint8_t status = read_data( keyboard ); + status |= STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT1; + status &= ~STATUS_CONTROL_CONFIG_CLOCK_PORT1; + send_command( keyboard, COMMAND_SET_STATE ); + write_data( keyboard, status ); + + // disable all LEDs on keyboard + //~ send_command( keyboard, KBD_COMMAND_SET_LEDS ); + //~ write_data( keyboard, KBD_LED_ALL_ON ); + + // set scan code + //~ send_command( keyboard, KBD_SET_SCANCODE ); + //~ write_data( keyboard, KBD_SCANCODE_2 ); + + // activate keyboard + //~ send_command( keyboard, KBD_ACTIVATE ); } - + uint32_t keyboard_handle_interrupt( interrupt_handler_t *handler, uint32_t esp ) { keyboard_t *keyboard = (keyboard_t *)handler->driver; - uint8_t key = port8_read( &keyboard->data_port ); - printf( "KBD 0x%X ", key ); - + if( has_data( keyboard ) ) { + uint8_t scancode = read_data( keyboard ); + printf( "KBD 0x%X ", scancode ); + } else { + printf( "SPURIOUS KBD INTERRUPT " ); + } + return esp; } |