From 0b034e25560ec3d5c73d0d2ced8632eecbbaff8f Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 2 Jun 2017 09:38:38 +0200 Subject: some work on keyboard initialization --- doc/LINKS.TODO | 3 ++ src/Makefile | 4 +- src/kernel.c | 1 + src/keyboard.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++-- src/stage1_functions.asm | 2 +- 5 files changed, 99 insertions(+), 7 deletions(-) diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO index 53cc093..daf9016 100644 --- a/doc/LINKS.TODO +++ b/doc/LINKS.TODO @@ -43,4 +43,7 @@ http://wiki.osdev.org/8259_PIC keyboard: http://wiki.osdev.org/"8042"_PS/2_Controller +https://www.lowlevel.eu/wiki/Keyboard_Controller +PIT: +http://wiki.osdev.org/Programmable_Interval_Timer diff --git a/src/Makefile b/src/Makefile index 14aa939..d72f5aa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,10 +13,10 @@ all: image.bin kernel.sym # + M * 512 (M is currently 7) = 3144 for kernel.bin # + 1 * 512 = 512 for magic.bin # (M + N + 1 is the number of sectors to be read in stage 2, as stage 1 -# loads only the first sector, so adapt NOF_LOAD_SECTORS to 20) +# loads only the first sector, so adapt NOF_LOAD_SECTORS to 21) image.bin: boot.bin kernel.bin magic.bin cat boot.bin kernel.bin > image.tmp - truncate -s 10240 image.tmp + truncate -s 10752 image.tmp cat image.tmp magic.bin > image.bin boot.bin: boot.asm boot_gdt.asm stage1_functions.asm stage2_functions.asm stage2_switch_mode.asm stage2_a20.asm diff --git a/src/kernel.c b/src/kernel.c index 732151e..d4dba01 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -36,6 +36,7 @@ void entry( void ) interrupt_t interrupt; interrupts_init( &interrupt ); + puts( "Initializing PS/2 keyboard" ); keyboard_t keyboard; keyboard_init( &keyboard ); interrupt_handler_t keyboard_interrupt_handler; 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 + #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; } diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm index 8953b9c..46fbc74 100644 --- a/src/stage1_functions.asm +++ b/src/stage1_functions.asm @@ -2,7 +2,7 @@ ; 3 * 512 for bootloader stage2 and the kernel code ; (note: the first sector gets loaded by the BIOS, so ; subtract 1 here!) -NOF_LOAD_SECTORS equ 20 +NOF_LOAD_SECTORS equ 21 ; IN bx: begin of memory area to dump ; IN ax: number of words to dump -- cgit v1.2.3-54-g00ecf