summaryrefslogtreecommitdiff
path: root/src/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keyboard.c')
-rw-r--r--src/keyboard.c96
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;
}