feature (PS/2): implemented a basic ps/2 keyboard driver and TTY
This commit is contained in:
parent
aa5ca306ca
commit
2b8a39feac
|
@ -0,0 +1,21 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#ifndef NOX_CONTROLLER_H
|
||||
#define NOX_CONTROLLER_H
|
||||
|
||||
#include "utils/stdtypes.h"
|
||||
|
||||
#define PS2_CONTROLLER_DATA_PORT 0x60
|
||||
#define PS2_CONTROLLER_STATUS_PORT 0x64
|
||||
#define PS2_CONTROLLER_COMMAND_PORT 0x64
|
||||
|
||||
#define PS2_CONTROLLER_TIMEOUT 0xFFFFFF
|
||||
|
||||
void ps2_controller_init ();
|
||||
uint8_t ps2_controller_command (uint8_t command);
|
||||
uint8_t ps2_controller_command_with_data (uint8_t command, uint8_t data);
|
||||
bool ps2_controller_wait_until_ready_for_input ();
|
||||
bool ps2_controller_wait_until_ready_for_output ();
|
||||
uint8_t ps2_controller_read_data ();
|
||||
|
||||
#endif //NOX_CONTROLLER_H
|
|
@ -0,0 +1,39 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#ifndef NOX_KEYBOARD_H
|
||||
#define NOX_KEYBOARD_H
|
||||
|
||||
#include "utils/stdtypes.h"
|
||||
#include "utils/string.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
PS2_KEYBOARD_COMMAND_SET_LEDS = 0xED,
|
||||
PS2_KEYBOARD_COMMAND_ECHO = 0xEE,
|
||||
PS2_KEYBOARD_COMMAND_SET_SCANCODE_SET = 0xF0,
|
||||
PS2_KEYBOARD_COMMAND_IDENTIFY = 0xF2,
|
||||
PS2_KEYBOARD_COMMAND_SET_TYPEMATIC = 0xF3,
|
||||
PS2_KEYBOARD_COMMAND_ENABLE_SCAN = 0xF4,
|
||||
PS2_KEYBOARD_COMMAND_DISABLE_SCAN = 0xF5,
|
||||
PS2_KEYBOARD_COMMAND_SET_DEFAULT_PARAMS = 0xF6,
|
||||
PS2_KEYBOARD_COMMAND_RESEND_LAST_BYTE = 0xFE,
|
||||
PS2_KEYBOARD_COMMAND_SELF_TEST = 0xFF
|
||||
} ps2_keyboard_command_E;
|
||||
|
||||
typedef enum {
|
||||
PS2_KEYBOARD_RESPONSE_KEY_DETECTION_ERROR_1 = 0x00,
|
||||
PS2_KEYBOARD_RESPONSE_SELF_TEST_PASSED = 0xAA,
|
||||
PS2_KEYBOARD_RESPONSE_ECHO = 0xEE,
|
||||
PS2_KEYBOARD_RESPONSE_ACKNOWLEDGED = 0xFA,
|
||||
PS2_KEYBOARD_RESPONSE_SELF_TEST_FAILED_1 = 0xFC,
|
||||
PS2_KEYBOARD_RESPONSE_SELF_TEST_FAILED_2 = 0xFD,
|
||||
PS2_KEYBOARD_RESPONSE_RESEND = 0xFE,
|
||||
PS2_KEYBOARD_RESPONSE_KEY_DETECTION_ERROR_2 = 0xFF
|
||||
} ps2_keyboard_response_E;
|
||||
|
||||
uint8_t ps2_keyboard_command (ps2_keyboard_command_E command, uint8_t data);
|
||||
void ps2_keyboard_init ();
|
||||
void ps2_keyboard_read ();
|
||||
string_t ps2_keyboard_command_to_string (ps2_keyboard_command_E command);
|
||||
|
||||
#endif //NOX_KEYBOARD_H
|
|
@ -0,0 +1,34 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#ifndef NOX_SCANCODES_H
|
||||
#define NOX_SCANCODES_H
|
||||
|
||||
#define PS2_SCANCODE_SET_1_ESCAPE 0x01
|
||||
#define PS2_SCANCODE_SET_1_BACKSPACE 0x0E
|
||||
#define PS2_SCANCODE_SET_1_TABULATOR 0x0F
|
||||
#define PS2_SCANCODE_SET_1_RETURN 0x1C
|
||||
#define PS2_SCANCODE_SET_1_SHIFT_LEFT 0x2A
|
||||
#define PS2_SCANCODE_SET_1_SHIFT_RIGHT 0x36
|
||||
#define PS2_SCANCODE_SET_1_ALT_LEFT 0x38
|
||||
#define PS2_SCANCODE_SET_1_SPACE 0x39
|
||||
#define PS2_SCANCODE_SET_1_CAPSLOCK 0x3A
|
||||
#define PS2_SCANCODE_SET_1_NUMLOCK 0x45
|
||||
#define PS2_SCANCODE_SET_1_SCROLLLOCK 0x46
|
||||
#define PS2_SCANCODE_SET_1_F1 0x3B
|
||||
#define PS2_SCANCODE_SET_1_F2 0x3C
|
||||
#define PS2_SCANCODE_SET_1_F3 0x3D
|
||||
#define PS2_SCANCODE_SET_1_F4 0x3E
|
||||
#define PS2_SCANCODE_SET_1_F5 0x3F
|
||||
#define PS2_SCANCODE_SET_1_F6 0x40
|
||||
#define PS2_SCANCODE_SET_1_F7 0x41
|
||||
#define PS2_SCANCODE_SET_1_F8 0x42
|
||||
#define PS2_SCANCODE_SET_1_F9 0x43
|
||||
#define PS2_SCANCODE_SET_1_F10 0x44
|
||||
#define PS2_SCANCODE_SET_1_F11 0x57
|
||||
#define PS2_SCANCODE_SET_1_F12 0x58
|
||||
|
||||
|
||||
#define PS2_SCANCODE_SET_1_RELEASE 0x80
|
||||
#define PS2_SCANCODE_SET_1_MODIFIER 0xE0
|
||||
|
||||
#endif //NOX_SCANCODES_H
|
|
@ -0,0 +1,26 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#ifndef NOXOS_TTY_H
|
||||
#define NOXOS_TTY_H
|
||||
|
||||
#include "drivers/graphics/renderer.h"
|
||||
#include "utils/stream.h"
|
||||
|
||||
#define TTY_STD_STREAM_SIZE 0x800 // 2048 bytes
|
||||
|
||||
typedef struct {
|
||||
graphics_buffer_T* graphics_buffer;
|
||||
stream_T* stream;
|
||||
position_T cursor;
|
||||
color_argb_T color;
|
||||
} tty_T;
|
||||
|
||||
void tty_init ();
|
||||
tty_T* tty_get_active ();
|
||||
|
||||
tty_T* tty_alloc (uint32_t stream_size);
|
||||
void tty_destruct (tty_T* tty);
|
||||
void tty_update (tty_T* tty);
|
||||
uint32_t tty_write (tty_T* tty, string_t string);
|
||||
|
||||
#endif //NOXOS_TTY_H
|
|
@ -16,6 +16,7 @@
|
|||
#include "drivers/acpi/acpi.h"
|
||||
#include "drivers/pci.h"
|
||||
#include "drivers/ps2/controller.h"
|
||||
#include "drivers/tty.h"
|
||||
#include "proc/scheduler.h"
|
||||
|
||||
void limine_terminal_print(boot_info_T* boot_info, string_t string) {
|
||||
|
@ -37,7 +38,7 @@ void kernel_init(boot_info_T* boot_info) {
|
|||
memory_allocator_init((void*)MEM_REGION_KERNEL_HEAP);
|
||||
|
||||
graphics_renderer_init(boot_info);
|
||||
graphical_log_init();
|
||||
// graphical_log_init();
|
||||
|
||||
vfs_init(boot_info);
|
||||
|
||||
|
@ -50,6 +51,8 @@ void kernel_init(boot_info_T* boot_info) {
|
|||
ps2_controller_init();
|
||||
|
||||
scheduler_init(boot_info);
|
||||
|
||||
tty_init();
|
||||
}
|
||||
|
||||
void kmain(boot_info_T boot_info) {
|
||||
|
@ -61,7 +64,5 @@ void kmain(boot_info_T boot_info) {
|
|||
|
||||
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
|
||||
|
||||
pci_device_T* ahci_controller = pci_manager_find_device(PCI_CLASS_MASS_STORAGE_CONTROLLER, PCI_SUBCLASS_SERIAL_ATA_CONTROLLER, 1);
|
||||
|
||||
CORE_HALT_FOREVER
|
||||
}
|
||||
|
|
|
@ -104,6 +104,17 @@ position_T graphics_buffer_draw_string(graphics_buffer_T* graphics_buffer, uint3
|
|||
pos.x = 0;
|
||||
break;
|
||||
}
|
||||
case '\b': {
|
||||
if (pos.x >= g_renderer.font.width) {
|
||||
pos.x -= g_renderer.font.width;
|
||||
} else if (pos.y >= g_renderer.font.height) {
|
||||
pos.y -= g_renderer.font.height;
|
||||
pos.x = FLOOR_TO(graphics_buffer->width, g_renderer.font.width) - g_renderer.font.width;
|
||||
} else break;
|
||||
|
||||
graphics_buffer_draw_char(graphics_buffer, pos.x, pos.y, color, ' ');
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (pos.x + g_renderer.font.width >= graphics_buffer->width) {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#include "drivers/ps2/controller.h"
|
||||
#include "drivers/ps2/keyboard.h"
|
||||
#include "drivers/acpi/fadt.h"
|
||||
#include "utils/io.h"
|
||||
#include "utils/logger.h"
|
||||
#include "boot/config.h"
|
||||
|
||||
void ps2_controller_init() {
|
||||
if (g_sysconfig->ps2_acpi_validation) {
|
||||
if (!(g_acpi_table_fadt->ia_boot_architecture_flags & (1 << 1))) {
|
||||
log(LOG_ERROR, "<PS2> ps2 controller initialization failed (ps2 controller not set in fadt boot flags)");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log(LOG_WARNING, "<PS2> skipping ps2 controller existence acpi check (disabled by sysconfig)");
|
||||
}
|
||||
|
||||
ps2_keyboard_init();
|
||||
}
|
||||
|
||||
uint8_t ps2_controller_command(uint8_t command) {
|
||||
io_out_byte(PS2_CONTROLLER_COMMAND_PORT, command);
|
||||
if (!ps2_controller_wait_until_ready_for_output()) {
|
||||
return 0;
|
||||
}
|
||||
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
||||
}
|
||||
|
||||
uint8_t ps2_controller_command_with_data(uint8_t command, uint8_t data) {
|
||||
io_out_byte(PS2_CONTROLLER_COMMAND_PORT, command);
|
||||
if (!ps2_controller_wait_until_ready_for_input()) {
|
||||
return 0;
|
||||
}
|
||||
io_out_byte(PS2_CONTROLLER_DATA_PORT, data);
|
||||
if (!ps2_controller_wait_until_ready_for_output()) {
|
||||
return 0;
|
||||
}
|
||||
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
||||
}
|
||||
|
||||
bool ps2_controller_wait_until_ready_for_input() {
|
||||
uint32_t timeout = 0;
|
||||
while (io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000010) {
|
||||
if (timeout > PS2_CONTROLLER_TIMEOUT) {
|
||||
log(LOG_WARNING, "<PS2 Controller> Controller not ready for input (timeout)");
|
||||
return false;
|
||||
}
|
||||
timeout++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ps2_controller_wait_until_ready_for_output() {
|
||||
uint32_t timeout = 0;
|
||||
log(LOG_DEBUG, "status register: 0b%.8b", io_in_byte(PS2_CONTROLLER_STATUS_PORT));
|
||||
while (!(io_in_byte(PS2_CONTROLLER_STATUS_PORT) & 0b00000001)) {
|
||||
if (timeout > PS2_CONTROLLER_TIMEOUT) {
|
||||
log(LOG_WARNING, "<PS2 Controller> Controller not ready for output (timeout)");
|
||||
return false;
|
||||
}
|
||||
timeout++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t ps2_controller_read_data() {
|
||||
return io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#include "drivers/ps2/keyboard.h"
|
||||
#include "drivers/ps2/scancodes.h"
|
||||
#include "drivers/ps2/controller.h"
|
||||
#include "drivers/tty.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/io.h"
|
||||
#include "platform/interrupts.h"
|
||||
|
||||
char scancode_set_1[] = " 1234567890-= qwertyuiop[] asdfghjkl;'` \\zxcvbnm,./ * 789-456+1230.";
|
||||
bool shift_enabled = false;
|
||||
bool extended_key = false;
|
||||
|
||||
uint8_t ps2_keyboard_command(ps2_keyboard_command_E command, uint8_t data) {
|
||||
uint8_t response = PS2_KEYBOARD_RESPONSE_RESEND;
|
||||
uint8_t tries = 0;
|
||||
|
||||
while (response == PS2_KEYBOARD_RESPONSE_RESEND) {
|
||||
response = ps2_controller_command(command);
|
||||
log(LOG_DEBUG, "<PS2> '%s' + 0x%xb -> 0x%xb", ps2_keyboard_command_to_string(command), data, response);
|
||||
tries++;
|
||||
|
||||
if (tries >= 3) {
|
||||
log(LOG_WARNING, "<PS2> Command %s not supported by keyboard (to many resend responses)", ps2_keyboard_command_to_string(command));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void ps2_keyboard_init() {
|
||||
|
||||
// uint8_t data = ps2_keyboard_command(PS2_KEYBOARD_COMMAND_ECHO, 0);
|
||||
// log(LOG_DEBUG, "response: 0x%xb", data);
|
||||
|
||||
io_in_byte(PS2_CONTROLLER_DATA_PORT);
|
||||
|
||||
pic_unmask_irq(IRQ_KEYBOARD);
|
||||
}
|
||||
|
||||
void ps2_keyboard_read() {
|
||||
uint8_t scancode = ps2_controller_read_data();
|
||||
char chr;
|
||||
|
||||
if (extended_key) {
|
||||
extended_key = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (scancode == PS2_SCANCODE_SET_1_MODIFIER) {
|
||||
extended_key = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (scancode >= PS2_SCANCODE_SET_1_RELEASE) {
|
||||
scancode -= PS2_SCANCODE_SET_1_RELEASE;
|
||||
switch (scancode) {
|
||||
case PS2_SCANCODE_SET_1_SHIFT_LEFT:
|
||||
case PS2_SCANCODE_SET_1_SHIFT_RIGHT: {
|
||||
shift_enabled = !shift_enabled;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (scancode) {
|
||||
case PS2_SCANCODE_SET_1_ESCAPE:
|
||||
case PS2_SCANCODE_SET_1_TABULATOR:
|
||||
case PS2_SCANCODE_SET_1_ALT_LEFT:
|
||||
case PS2_SCANCODE_SET_1_NUMLOCK:
|
||||
case PS2_SCANCODE_SET_1_SCROLLLOCK:
|
||||
case PS2_SCANCODE_SET_1_F1:
|
||||
case PS2_SCANCODE_SET_1_F2:
|
||||
case PS2_SCANCODE_SET_1_F3:
|
||||
case PS2_SCANCODE_SET_1_F4:
|
||||
case PS2_SCANCODE_SET_1_F5:
|
||||
case PS2_SCANCODE_SET_1_F6:
|
||||
case PS2_SCANCODE_SET_1_F7:
|
||||
case PS2_SCANCODE_SET_1_F8:
|
||||
case PS2_SCANCODE_SET_1_F9:
|
||||
case PS2_SCANCODE_SET_1_F10:
|
||||
case PS2_SCANCODE_SET_1_F11:
|
||||
case PS2_SCANCODE_SET_1_F12: {
|
||||
log(LOG_WARNING, "special keys aren't implemented yet");
|
||||
return;
|
||||
}
|
||||
|
||||
case PS2_SCANCODE_SET_1_BACKSPACE: {
|
||||
chr = '\b';
|
||||
break;
|
||||
}
|
||||
|
||||
case PS2_SCANCODE_SET_1_SPACE: {
|
||||
chr = ' ';
|
||||
break;
|
||||
}
|
||||
|
||||
case PS2_SCANCODE_SET_1_RETURN: {
|
||||
chr = '\n';
|
||||
break;
|
||||
}
|
||||
|
||||
case PS2_SCANCODE_SET_1_SHIFT_LEFT:
|
||||
case PS2_SCANCODE_SET_1_SHIFT_RIGHT:
|
||||
case PS2_SCANCODE_SET_1_CAPSLOCK: {
|
||||
shift_enabled = !shift_enabled;
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
chr = scancode_set_1[scancode];
|
||||
if (shift_enabled) {
|
||||
if (string_is_char_lowercase(chr)) chr -= 32;
|
||||
else if (string_is_char_uppercase(chr)) chr += 32;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[2];
|
||||
buffer[0] = chr;
|
||||
buffer[1] = '\0';
|
||||
|
||||
tty_write(tty_get_active(), buffer);
|
||||
}
|
||||
|
||||
string_t ps2_keyboard_command_to_string(ps2_keyboard_command_E command) {
|
||||
switch (command) {
|
||||
case PS2_KEYBOARD_COMMAND_SET_LEDS: {
|
||||
return "Set LEDs";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_ECHO: {
|
||||
return "Echo";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_SET_SCANCODE_SET: {
|
||||
return "Get/Set Scancode Set";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_IDENTIFY: {
|
||||
return "Identify";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_SET_TYPEMATIC: {
|
||||
return "Set Typematic";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_ENABLE_SCAN: {
|
||||
return "Enable Scan";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_DISABLE_SCAN: {
|
||||
return "Disable Scan";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_SET_DEFAULT_PARAMS: {
|
||||
return "Set Default Parameter";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_RESEND_LAST_BYTE: {
|
||||
return "Resend Last Byte";
|
||||
}
|
||||
case PS2_KEYBOARD_COMMAND_SELF_TEST: {
|
||||
return "Self Test";
|
||||
}
|
||||
default: {
|
||||
return "Invalid Command";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#include "drivers/tty.h"
|
||||
#include "utils/memory.h"
|
||||
|
||||
// this global state tty is just a placeholder
|
||||
tty_T* g_tty;
|
||||
|
||||
void tty_init() {
|
||||
g_tty = tty_alloc(TTY_STD_STREAM_SIZE);
|
||||
}
|
||||
|
||||
tty_T* tty_get_active() {
|
||||
return g_tty;
|
||||
}
|
||||
|
||||
tty_T* tty_alloc(uint32_t stream_size) {
|
||||
tty_T* tty = memory_allocate(sizeof(tty_T));
|
||||
|
||||
tty->graphics_buffer = graphics_buffer_request(0, 0, graphics_renderer_get_width(), graphics_renderer_get_height(), GRAPHICS_BUFFER_STANDARD);
|
||||
tty->stream = stream_alloc(stream_size);
|
||||
tty->cursor.x = 0;
|
||||
tty->cursor.y = 0;
|
||||
tty->color = g_color_palette[COLOR_PAL_GREY_LIGHT];
|
||||
|
||||
return tty;
|
||||
}
|
||||
|
||||
void tty_destruct(tty_T* tty) {
|
||||
graphics_buffer_destruct(tty->graphics_buffer);
|
||||
stream_destruct(tty->stream);
|
||||
|
||||
memory_free(tty);
|
||||
}
|
||||
|
||||
void tty_update(tty_T* tty) {
|
||||
char buffer[256];
|
||||
uint32_t read_bytes = 255;
|
||||
while (read_bytes == 255) {
|
||||
read_bytes = stream_read(tty->stream, buffer, 255);
|
||||
buffer[read_bytes] = '\0';
|
||||
tty->cursor = graphics_buffer_draw_string(tty->graphics_buffer, tty->cursor.x, tty->cursor.y, tty->color, buffer);
|
||||
}
|
||||
|
||||
graphics_renderer_update();
|
||||
}
|
||||
|
||||
uint32_t tty_write(tty_T* tty, string_t string) {
|
||||
uint32_t num = stream_write(tty->stream, (void*)string, string_length(string));
|
||||
|
||||
tty_update(tty);
|
||||
|
||||
return num;
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include "utils/logger.h"
|
||||
#include "utils/io.h"
|
||||
#include "proc/scheduler.h"
|
||||
#include "drivers/ps2/keyboard.h"
|
||||
|
||||
idt_register_T g_idt_register;
|
||||
uint8_t g_handling_interrupt;
|
||||
|
@ -225,6 +226,10 @@ cpu_state_T* irq_handle(cpu_state_T* state, pic_irq_E irq) {
|
|||
// log(LOG_DEBUG, "PIT -> Tick");
|
||||
break;
|
||||
}
|
||||
case IRQ_KEYBOARD: {
|
||||
ps2_keyboard_read();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
log(LOG_WARNING, "Unhandled IRQ");
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue