CeDOS - Commit 0ccf28fa

Implemented low-level keyboard driver
Celina Sophie Kalus
Fri, 19 Jan 2018 18:57:57 +0100
6 files changed, 120 insertions(+), 13 deletions(-)
M include/cedos/pic.hinclude/cedos/pic.h

@@ -16,6 +16,9 @@ #define PIC2_OFFSET 0x28

#define PIC_END_OF_INTERRUPT 0x20 +#define PIC1_IRQ(n) (PIC1_OFFSET + n) +#define PIC2_IRQ(n) (PIC2_OFFSET + n) + /*! * Moves irqs to appropriate addresses and enables all PIC interrupts * \return 1 on success, 0 on fail
M kernel/core.ckernel/core.c

@@ -132,6 +132,9 @@ } else if (state == STATE_ARGUMENT && *fmt == 's') {

const char* string = va_arg(args, const char*); while (*string) { core_con->write_c(*string++); } state = STATE_DEFAULT; + } else if (state == STATE_ARGUMENT && *fmt == 'c') { + core_con->write_c(va_arg(args, int)); + state = STATE_DEFAULT; } else if (state == STATE_ARGUMENT && *fmt == '%') { core_con->write_c('%'); state = STATE_DEFAULT;
M kernel/drivers/ps2_keyboard.ckernel/drivers/ps2_keyboard.c

@@ -1,7 +1,26 @@

#include "cedos/drivers/keyboard.h" #include "cedos/interrupts.h" #include "cedos/pic.h" +#include "cedos/core.h" +#include "cedos/sched/sched.h" #include "assembly.h" + +#define PS2_DATA 0x60 +#define PS2_COMMAND 0x64 + +#define PS2_READ_CONF 0x20 +#define PS2_WRTE_CONF 0x60 + +#define PS2_DISABLE_A 0xAD +#define PS2_DISABLE_B 0xA7 + +#define PS2_ENABLE_A 0xAE +#define PS2_ENABLE_B 0xA8 + +#define PS2_SUCCESS 0xFA +#define PS2_FAILURE 0xFC + +#define BUFFER_LENGTH (128) /*! * Initializes the PS/2 keyboard.

@@ -13,7 +32,7 @@ /*!

* Reads a single character from the PS/2 keyboard * \return A single char corresponding to a key press. */ -uint8_t ps2_kb_read(void); +uint32_t ps2_kb_read(void); //! PS/2 keyboard driver (default driver) KB_DRIVER ps2_kb = {

@@ -22,14 +41,65 @@ ps2_kb_init,

ps2_kb_read }; +uint8_t buffer[BUFFER_LENGTH]; +uint32_t buffer_head, buffer_tail; + +__attribute__((always_inline)) inline void buffer_enqueue(uint8_t value) { + buffer[buffer_head] = value; + buffer_head = (buffer_head + 1) % BUFFER_LENGTH; + if (buffer_head == buffer_tail) { + buffer_tail = (buffer_tail + 1) % BUFFER_LENGTH; + } +} + +__attribute__((always_inline)) inline uint8_t buffer_dequeue(void) { + uint8_t res = buffer[buffer_tail]; + buffer_tail = (buffer_tail + 1) % BUFFER_LENGTH; + return res; +} + +__attribute__((always_inline)) inline int buffer_empty(void) { + return (buffer_head == buffer_tail); +} + __attribute__((interrupt)) void keyboard_int_handler(INTERRUPT_FRAME *frame) { + while (inb(PS2_COMMAND) & 0x01) { + nop(); nop(); nop(); nop(); + buffer_enqueue(inb(PS2_DATA)); + nop(); nop(); nop(); nop(); + } + pic1_eoi(); } int ps2_kb_init(void) { + // clear incoming data + inb(PS2_DATA); + + nop(); nop(); nop(); nop(); + + // get keyboard configuration + outb(PS2_READ_CONF, PS2_COMMAND); + nop(); nop(); nop(); nop(); + uint8_t conf = inb(PS2_DATA); + + // set keyboard configuration + conf = (conf | 0x01) & 0x75; + outb(PS2_WRTE_CONF, PS2_COMMAND); + nop(); nop(); nop(); nop(); + outb(conf, PS2_DATA); + + install_interrupt(PIC1_IRQ(0x01), keyboard_int_handler, 0x08, INT_GATE); + + pic_unmask_interrupt(0x01); + return 1; } -uint8_t ps2_kb_read(void) { - return 0; +uint32_t ps2_kb_read(void) { + while (buffer_empty()) { + sched_yield(); + } + + return buffer_dequeue(); }
M kernel/main.ckernel/main.c

@@ -1,4 +1,5 @@

#include "cedos/drivers/console.h" +#include "cedos/drivers/keyboard.h" #include "cedos/sched/sched.h" #include "cedos/sched/process.h"

@@ -44,6 +45,11 @@

printk("Initializing scheduler..."); sched_init(); printk("done.\n"); + + printk("Initializing keyboard..."); + ps2_kb.init(); + printk("done.\n"); + printk("Initialization finished.\n--------------\n");

@@ -114,10 +120,26 @@ while (1) { hlt(); }

} int sysinit(void) { - sched_exec(create_empty_page_dir(), fibonacci, "fibonacci"); - sched_exec(create_empty_page_dir(), node, "node"); - while (get_process_count() < 5) { sched_yield(); } - tasktree(1); + uint8_t scancode = 0; + + printk("PRESS ENTER\n"); + + while (scancode != 0x1C) { + scancode = ps2_kb.read(); + printk("%c", scancode); + } + + printk("THANKS\n"); + + while (1) { + printk("x"); + hlt(); + } + + //sched_exec(create_empty_page_dir(), fibonacci, "fibonacci"); + //sched_exec(create_empty_page_dir(), node, "node"); + //while (get_process_count() < 5) { sched_yield(); } + //tasktree(1); printk("Terminating.\n"); }
M kernel/sched/sched.ckernel/sched/sched.c

@@ -87,7 +87,12 @@

// select next process current_pid = next_schedule(current_pid); - //printk("%i", current_pid); + // unblock all blocked processes + for (PROCESS *p = get_first_process(); p != NULL; p = p->next) { + if (p->state == PSTATE_BLOCKED) { + p->state = PSTATE_READY; + } + } // prepare to return to process PROCESS* next = get_process(current_pid);

@@ -124,7 +129,7 @@ extern void* sched_interrupt;

int sched_init(void) { // install scheduler interrupt - install_interrupt(0x20, &sched_interrupt, 0x08, INT_GATE); + install_interrupt(PIC1_IRQ(0x00), &sched_interrupt, 0x08, INT_GATE); current_pid = 0;

@@ -135,7 +140,11 @@ return 1;

} void sched_yield(void) { - + PROCESS *current = get_process(current_pid); + if (current != NULL && current->state != PSTATE_TERMINATED) { + current->state = PSTATE_BLOCKED; + } + INT(0x20); }
M kernel/sched/sched_strats.ckernel/sched/sched_strats.c

@@ -5,13 +5,13 @@

PROCESS_ID next_schedule(PROCESS_ID current) { PROCESS* process = get_process(current); - if (process != NULL && process->next != NULL) { + if (process != NULL && process->next != NULL && process->state == PSTATE_READY) { return process->next->id; } else { PROCESS *first = get_first_process(); - if (first != NULL && first->id != 0) { + if (first != NULL && first->id != 0 && first->state == PSTATE_READY) { return first->id; - } else if (first != NULL && first->next != NULL) { + } else if (first != NULL && first->next != NULL && first->next->state == PSTATE_READY) { return first->next->id; } else { return 0;