diff --git a/arch/x86/traps.c b/arch/x86/traps.c index 72899039..6e3993b6 100644 --- a/arch/x86/traps.c +++ b/arch/x86/traps.c @@ -24,9 +24,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include #include #include -#include #include #include #include diff --git a/common/kernel.c b/common/kernel.c index a1eb1cee..ad191154 100644 --- a/common/kernel.c +++ b/common/kernel.c @@ -68,5 +68,5 @@ void kernel_main(void) { printk("All tasks done.\n"); while (1) - cpu_relax(); + echo_loop(); } diff --git a/common/setup.c b/common/setup.c index fcb38401..b0e9fced 100644 --- a/common/setup.c +++ b/common/setup.c @@ -27,8 +27,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/drivers/keyboard.c b/drivers/keyboard.c index e27ea004..2e0ab9c9 100644 --- a/drivers/keyboard.c +++ b/drivers/keyboard.c @@ -35,8 +35,96 @@ static struct { unsigned init; } keyboard_state; -void init_keyboard(void) { - outb(PIC1_PORT_DATA, KEYBOARD_IRQ_UNMASK); /* unmask keyboard irq */ +void init_keyboard() { + printk("Initializing keyboard driver\n"); + + /* Disable devices */ + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_0); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_1); + + /* Flush output buffer */ + while (inb(KEYBOARD_PORT_DATA) & KEYBOARD_STATUS_OUT_FULL) + ; /* discard leftover bytes */ + + /* Controller configuration */ + char current_status; + int dual_channel; + + /* Read controller config */ + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_READ_CONFIGURATION); + current_status = inb(KEYBOARD_PORT_DATA); + + dual_channel = !!(current_status & (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1)); + printk("Current PS/2 status before: %x\n", current_status); + /* Disable IRQs and translation */ + current_status = current_status & + ~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT) & + ~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT) & + ~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION); + /* Write controller config */ + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION); + outb(KEYBOARD_PORT_DATA, current_status); + + printk("Current PS/2 status after mods: %x\n", current_status); + printk("PS/2 dual channel? %d\n", dual_channel); + + /* Controller self test */ + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_SELF_TEST); + if (inb(KEYBOARD_PORT_DATA) != KEYBOARD_RES_SELF_TEST) { + printk("Self test did not succed\n"); + return; + } + + /* Determine whether second channel exists */ + if (dual_channel) { + printk("Enabling second PS/2 port\n"); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_READ_CONFIGURATION); + current_status = inb(KEYBOARD_PORT_DATA); + dual_channel = + (current_status & (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1)) == 0; + } + if (dual_channel) + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_1); + + /* Interface tests */ + int port1, port2 = 0; + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_0); + port1 = inb(KEYBOARD_PORT_DATA) == 0; + if (dual_channel) { + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_1); + port2 = inb(KEYBOARD_PORT_DATA) == 0; + } + + printk("Port1 available? %d - port2 available? %d\n", port1, port2); + if (!port1 && !port2) { + printk("No available PS/2 working ports\n"); + return; + } + + /* Enable devices */ + if (port1) { + printk("Keyboard: enabling first channel\n"); + current_status = current_status | + (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT) | + (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1) | + (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION); + outb(KEYBOARD_PORT_DATA, current_status); + + pic_enable_irq(PIC1_DEVICE_SEL, KEYBOARD_IRQ); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_0); + } + else { + printk("Keyboard: enabling second channel\n"); + current_status = + current_status | (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION); + outb(KEYBOARD_PORT_DATA, current_status); + + pic_enable_irq(PIC1_DEVICE_SEL, KEYBOARD_IRQ_2); + outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1); + } memset(&keyboard_state, 0, sizeof(keyboard_state)); } diff --git a/include/drivers/keyboard.h b/include/drivers/keyboard.h index 739240fd..16ceca16 100644 --- a/include/drivers/keyboard.h +++ b/include/drivers/keyboard.h @@ -30,16 +30,48 @@ #define KEYBOARD_PORT_CMD 0x64 /* keyboard command port */ #define KEYBOARD_PORT_DATA 0x60 /* keyboard data port */ -#define KEYBOARD_IRQ0_OFFSET (PIC_IRQ0_OFFSET + 1) /* keyboard irq offset */ -#define KEYBOARD_IRQ_UNMASK (~2) /* mask with keyboard irq enabled, others disabled */ +#define KEYBOARD_IRQ 0x01 +#define KEYBOARD_IRQ_2 0x04 /* Second port */ +#define KEYBOARD_IRQ0_OFFSET \ + (PIC_IRQ0_OFFSET + KEYBOARD_IRQ) /* keyboard first channel irq offset */ +#define KEYBOARD_2_IRQ0_OFFSET (PIC_IRQ0_OFFSET + KEYBOARD_IRQ_2) -#define KEYBOARD_STATUS_OUT_FULL 1 /* bit set when the keyboard buffer is full */ +#define KEYBOARD_STATUS_OUT_FULL 0x01 /* bit set when the keyboard buffer is full */ + +enum { + KEYBOARD_CMD_WRITE_CONFIGURATION = 0x60, /* Write configuration byte */ + KEYBOARD_CMD_READ_CONFIGURATION = 0x20, /* Read configuration byte */ + KEYBOARD_CMD_SELF_TEST = 0xAA, + KEYBOARD_CMD_TEST_PORT_0 = 0xAB, + KEYBOARD_CMD_TEST_PORT_1 = 0xA9, + KEYBOARD_CMD_DISABLE_PORT_0 = 0xAD, + KEYBOARD_CMD_DISABLE_PORT_1 = 0xA7, + KEYBOARD_CMD_ENABLE_PORT_0 = 0xAE, + KEYBOARD_CMD_ENABLE_PORT_1 = 0xA8, +} keyboard_cmd; +typedef enum keyboard_cmd keyboard_cmd_t; + +enum { + KEYBOARD_RES_SELF_TEST = 0x55, +} keyboard_res; + +enum { + KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT, + KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT, + KEYBOARD_CONTROLLER_CONFIG_BIT_SYS_FLAG, + KEYBOARD_CONTROLLER_CONFIG_BIT_ZERO, + KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_0, + KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1, + KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION, + KEYBOARD_CONTROLLER_CONFIG_BIT_ZERO_, +} keyboard_controller_config_byte; +typedef enum keyboard_controller_config_byte keyboard_controller_config_byte_t; #define KEY_BUF 80 /* size of internal input buffer */ #define SCAN_RELEASE_MASK 0x80 /* bit set on key release */ -#define KEY_NULL 0x0 /* no key */ +#define KEY_NULL 0x00 /* no key */ /* scan codes */ #define SCAN_NULL 0x0 @@ -76,7 +108,7 @@ #define SCAN_INS 0x52 #define SCAN_DEL 0x53 -void init_keyboard(void); +void init_keyboard(); void keyboard_interrupt_handler(void); unsigned int keyboard_process_keys(void);