Add keypress detection
This commit is contained in:
27
Makefile
27
Makefile
@@ -8,6 +8,7 @@ all: myos.iso
|
||||
SOURCE_DIR := src
|
||||
BUILD_DIR := build
|
||||
|
||||
|
||||
CONTAINER_CMD := podman run -v "$(shell pwd)":"/scratch" \
|
||||
--workdir="/scratch" \
|
||||
--network=none \
|
||||
@@ -20,7 +21,7 @@ LD := $(CONTAINER_CMD) i686-elf-ld
|
||||
AS := $(CONTAINER_CMD) i686-elf-as
|
||||
AR := $(CONTAINER_CMD) i686-elf-ar
|
||||
|
||||
C_SOURCES := $(shell find $(SOURCE_DIR) -name '*.c')
|
||||
C_SOURCES := $(shell find $(SOURCE_DIR) ! -name 'test_*' -name '*.c')
|
||||
ASM_SOURCES := $(shell find $(SOURCE_DIR) -name '*.S')
|
||||
OBJECTS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.S=.o))
|
||||
DEPENDS := $(patsubst $(SOURCE_DIR)/%, $(BUILD_DIR)/%, $(C_SOURCES:.c=.d))
|
||||
@@ -60,7 +61,6 @@ $(BUILD_DIR)/kernel/interrupts.o: $(SOURCE_DIR)/kernel/interrupts.c Makefile
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -c $(CFLAGS) -mgeneral-regs-only -mno-red-zone $< -o $@
|
||||
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c Makefile
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
@@ -69,3 +69,26 @@ $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.S Makefile
|
||||
@mkdir -p $(@D)
|
||||
$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
###################
|
||||
# TESTS #
|
||||
###################
|
||||
|
||||
TEST_SOURCE_DIR := $(SOURCE_DIR)/test
|
||||
TEST_BUILD_DIR := $(BUILD_DIR)/test
|
||||
|
||||
TEST_SOURCES := $(shell find $(TEST_SOURCE_DIR) -name 'test_*.c')
|
||||
TEST_DEPENDS := $(patsubst $(TEST_SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=.d))
|
||||
TEST_OUTPUT := $(patsubst $(TEST_SOURCE_DIR)/%, $(TEST_BUILD_DIR)/%, $(TEST_SOURCES:.c=))
|
||||
|
||||
$(info TEST_SOURCES is $(TEST_SOURCES))
|
||||
$(info TEST_OUTPUT is $(TEST_OUTPUT))
|
||||
|
||||
tests: $(TEST_OUTPUT)
|
||||
|
||||
-include $(TEST_DEPENDS)
|
||||
|
||||
$(TEST_BUILD_DIR)/test_%: $(TEST_SOURCE_DIR)/test_%.c $(SOURCE_DIR)/lib/%.c | Makefile
|
||||
@mkdir -p $(@D)
|
||||
gcc -O1 -fsanitize=address,undefined -Wall -Wextra -Werror -g3 -std=c2x -D_FORTIFY_SOURCE=2 -I$(SOURCE_DIR)/include -o $@ $^
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#include "ps2-keyboard.h"
|
||||
|
||||
const struct str ps2_cmd_str[PS2CMD_COUNT] = {
|
||||
const struct str ps2_cmd_str[] = {
|
||||
[PS2CMD_SET_LEDS ] = str_attach("PS2CMD_SET_LEDS"),
|
||||
[PS2CMD_ECHO ] = str_attach("PS2CMD_ECHO"),
|
||||
[PS2CMD_GET_SCAN ] = str_attach("PS2CMD_GET_SCAN"),
|
||||
@@ -21,7 +21,7 @@ const struct str ps2_cmd_str[PS2CMD_COUNT] = {
|
||||
[PS2CMD_RESEND_RESET_AND_SELF_TEST] = str_attach("PS2CMD_RESEND_RESET_AND_SELF_TEST"),
|
||||
};
|
||||
|
||||
const struct str ps2_response_str[PS2RESPONSE_COUNT] = {
|
||||
const struct str ps2_response_str[] = {
|
||||
[PS2RESPONSE_ERROR_1 ] = str_attach("PS2RESPONSE_ERROR_1"),
|
||||
[PS2RESPONSE_ERROR_2 ] = str_attach("PS2RESPONSE_ERROR_2"),
|
||||
[PS2RESPONSE_SELF_TEST_PASSED ] = str_attach("PS2RESPONSE_SELF_TEST_PASSED"),
|
||||
@@ -32,4 +32,178 @@ const struct str ps2_response_str[PS2RESPONSE_COUNT] = {
|
||||
[PS2RESPONSE_RESEND ] = str_attach("PS2RESPONSE_RESEND"),
|
||||
};
|
||||
|
||||
const struct str ps2_key_str[] = {
|
||||
[KEY_EXTENDED ] = str_attach("KEY_EXTENDED (PRESSED)"),
|
||||
[KEY_ESCAPE ] = str_attach("KEY_ESCAPE (PRESSED)"),
|
||||
[KEY_1 ] = str_attach("KEY_1 (PRESSED)"),
|
||||
[KEY_2 ] = str_attach("KEY_2 (PRESSED)"),
|
||||
[KEY_3 ] = str_attach("KEY_3 (PRESSED)"),
|
||||
[KEY_4 ] = str_attach("KEY_4 (PRESSED)"),
|
||||
[KEY_5 ] = str_attach("KEY_5 (PRESSED)"),
|
||||
[KEY_6 ] = str_attach("KEY_6 (PRESSED)"),
|
||||
[KEY_7 ] = str_attach("KEY_7 (PRESSED)"),
|
||||
[KEY_8 ] = str_attach("KEY_8 (PRESSED)"),
|
||||
[KEY_9 ] = str_attach("KEY_9 (PRESSED)"),
|
||||
[KEY_0 ] = str_attach("KEY_0 (PRESSED)"),
|
||||
[KEY_MINUS ] = str_attach("KEY_MINUS (PRESSED)"),
|
||||
[KEY_EQUALS ] = str_attach("KEY_EQUALS (PRESSED)"),
|
||||
[KEY_BACKSPACE ] = str_attach("KEY_BACKSPACE (PRESSED)"),
|
||||
[KEY_TAB ] = str_attach("KEY_TAB (PRESSED)"),
|
||||
[KEY_Q ] = str_attach("KEY_Q (PRESSED)"),
|
||||
[KEY_W ] = str_attach("KEY_W (PRESSED)"),
|
||||
[KEY_E ] = str_attach("KEY_E (PRESSED)"),
|
||||
[KEY_R ] = str_attach("KEY_R (PRESSED)"),
|
||||
[KEY_T ] = str_attach("KEY_T (PRESSED)"),
|
||||
[KEY_Y ] = str_attach("KEY_Y (PRESSED)"),
|
||||
[KEY_U ] = str_attach("KEY_U (PRESSED)"),
|
||||
[KEY_I ] = str_attach("KEY_I (PRESSED)"),
|
||||
[KEY_O ] = str_attach("KEY_O (PRESSED)"),
|
||||
[KEY_P ] = str_attach("KEY_P (PRESSED)"),
|
||||
[KEY_SQUARE_BRACKET_LEFT ] = str_attach("KEY_SQUARE_BRACKET_LEFT (PRESSED)"),
|
||||
[KEY_SQUARE_BRACKET_RIGHT] = str_attach("KEY_SQUARE_BRACKET_RIGHT (PRESSED)"),
|
||||
[KEY_ENTER ] = str_attach("KEY_ENTER (PRESSED)"),
|
||||
[KEY_LEFT_CONTROL ] = str_attach("KEY_LEFT_CONTROL (PRESSED)"),
|
||||
[KEY_A ] = str_attach("KEY_A (PRESSED)"),
|
||||
[KEY_S ] = str_attach("KEY_S (PRESSED)"),
|
||||
[KEY_D ] = str_attach("KEY_D (PRESSED)"),
|
||||
[KEY_F ] = str_attach("KEY_F (PRESSED)"),
|
||||
[KEY_G ] = str_attach("KEY_G (PRESSED)"),
|
||||
[KEY_H ] = str_attach("KEY_H (PRESSED)"),
|
||||
[KEY_J ] = str_attach("KEY_J (PRESSED)"),
|
||||
[KEY_K ] = str_attach("KEY_K (PRESSED)"),
|
||||
[KEY_L ] = str_attach("KEY_L (PRESSED)"),
|
||||
[KEY_SEMICOLON ] = str_attach("KEY_SEMICOLON (PRESSED)"),
|
||||
[KEY_SINGLE_QUOTE ] = str_attach("KEY_SINGLE_QUOTE (PRESSED)"),
|
||||
[KEY_BACKTICK ] = str_attach("KEY_BACKTICK (PRESSED)"),
|
||||
[KEY_LEFT_SHIFT ] = str_attach("KEY_LEFT_SHIFT (PRESSED)"),
|
||||
[KEY_BACKSLASH ] = str_attach("KEY_BACKSLASH (PRESSED)"),
|
||||
[KEY_Z ] = str_attach("KEY_Z (PRESSED)"),
|
||||
[KEY_X ] = str_attach("KEY_X (PRESSED)"),
|
||||
[KEY_C ] = str_attach("KEY_C (PRESSED)"),
|
||||
[KEY_V ] = str_attach("KEY_V (PRESSED)"),
|
||||
[KEY_B ] = str_attach("KEY_B (PRESSED)"),
|
||||
[KEY_N ] = str_attach("KEY_N (PRESSED)"),
|
||||
[KEY_M ] = str_attach("KEY_M (PRESSED)"),
|
||||
[KEY_COMMA ] = str_attach("KEY_COMMA (PRESSED)"),
|
||||
[KEY_DOT ] = str_attach("KEY_DOT (PRESSED)"),
|
||||
[KEY_FORWARD_SLASH ] = str_attach("KEY_FORWARD_SLASH (PRESSED)"),
|
||||
[KEY_RIGHT_SHIFT ] = str_attach("KEY_RIGHT_SHIFT (PRESSED)"),
|
||||
[KEY_KEYPAD_ASTERISK ] = str_attach("KEY_KEYPAD_ASTERISK (PRESSED)"),
|
||||
[KEY_LEFT_ALT ] = str_attach("KEY_LEFT_ALT (PRESSED)"),
|
||||
[KEY_SPACE ] = str_attach("KEY_SPACE (PRESSED)"),
|
||||
[KEY_CAPSLOCK ] = str_attach("KEY_CAPSLOCK (PRESSED)"),
|
||||
[KEY_F1 ] = str_attach("KEY_F1 (PRESSED)"),
|
||||
[KEY_F2 ] = str_attach("KEY_F2 (PRESSED)"),
|
||||
[KEY_F3 ] = str_attach("KEY_F3 (PRESSED)"),
|
||||
[KEY_F4 ] = str_attach("KEY_F4 (PRESSED)"),
|
||||
[KEY_F5 ] = str_attach("KEY_F5 (PRESSED)"),
|
||||
[KEY_F6 ] = str_attach("KEY_F6 (PRESSED)"),
|
||||
[KEY_F7 ] = str_attach("KEY_F7 (PRESSED)"),
|
||||
[KEY_F8 ] = str_attach("KEY_F8 (PRESSED)"),
|
||||
[KEY_F9 ] = str_attach("KEY_F9 (PRESSED)"),
|
||||
[KEY_F10 ] = str_attach("KEY_F10 (PRESSED)"),
|
||||
[KEY_NUMBERLOCK ] = str_attach("KEY_NUMBERLOCK (PRESSED)"),
|
||||
[KEY_SCROLLLOCK ] = str_attach("KEY_SCROLLLOCK (PRESSED)"),
|
||||
[KEY_KEYPAD_7 ] = str_attach("KEY_KEYPAD_7 (PRESSED)"),
|
||||
[KEY_KEYPAD_8 ] = str_attach("KEY_KEYPAD_8 (PRESSED)"),
|
||||
[KEY_KEYPAD_9 ] = str_attach("KEY_KEYPAD_9 (PRESSED)"),
|
||||
[KEY_KEYPAD_MINUS ] = str_attach("KEY_KEYPAD_MINUS (PRESSED)"),
|
||||
[KEY_KEYPAD_4 ] = str_attach("KEY_KEYPAD_4 (PRESSED)"),
|
||||
[KEY_KEYPAD_5 ] = str_attach("KEY_KEYPAD_5 (PRESSED)"),
|
||||
[KEY_KEYPAD_6 ] = str_attach("KEY_KEYPAD_6 (PRESSED)"),
|
||||
[KEY_KEYPAD_PLUS ] = str_attach("KEY_KEYPAD_PLUS (PRESSED)"),
|
||||
[KEY_KEYPAD_1 ] = str_attach("KEY_KEYPAD_1 (PRESSED)"),
|
||||
[KEY_KEYPAD_2 ] = str_attach("KEY_KEYPAD_2 (PRESSED)"),
|
||||
[KEY_KEYPAD_3 ] = str_attach("KEY_KEYPAD_3 (PRESSED)"),
|
||||
[KEY_KEYPAD_0 ] = str_attach("KEY_KEYPAD_0 (PRESSED)"),
|
||||
[KEY_KEYPAD_DOT ] = str_attach("KEY_KEYPAD_DOT (PRESSED)"),
|
||||
[KEY_F11 ] = str_attach("KEY_F11 (PRESSED)"),
|
||||
[KEY_F12 ] = str_attach("KEY_F12 (PRESSED)"),
|
||||
|
||||
[KEY_RELEASED | KEY_ESCAPE ] = str_attach("KEY_ESCAPE (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_1 ] = str_attach("KEY_1 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_2 ] = str_attach("KEY_2 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_3 ] = str_attach("KEY_3 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_4 ] = str_attach("KEY_4 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_5 ] = str_attach("KEY_5 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_6 ] = str_attach("KEY_6 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_7 ] = str_attach("KEY_7 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_8 ] = str_attach("KEY_8 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_9 ] = str_attach("KEY_9 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_0 ] = str_attach("KEY_0 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_MINUS ] = str_attach("KEY_MINUS (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_EQUALS ] = str_attach("KEY_EQUALS (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_BACKSPACE ] = str_attach("KEY_BACKSPACE (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_TAB ] = str_attach("KEY_TAB (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_Q ] = str_attach("KEY_Q (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_W ] = str_attach("KEY_W (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_E ] = str_attach("KEY_E (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_R ] = str_attach("KEY_R (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_T ] = str_attach("KEY_T (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_Y ] = str_attach("KEY_Y (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_U ] = str_attach("KEY_U (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_I ] = str_attach("KEY_I (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_O ] = str_attach("KEY_O (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_P ] = str_attach("KEY_P (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_SQUARE_BRACKET_LEFT ] = str_attach("KEY_SQUARE_BRACKET_LEFT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_SQUARE_BRACKET_RIGHT] = str_attach("KEY_SQUARE_BRACKET_RIGHT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_ENTER ] = str_attach("KEY_ENTER (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_LEFT_CONTROL ] = str_attach("KEY_LEFT_CONTROL (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_A ] = str_attach("KEY_A (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_S ] = str_attach("KEY_S (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_D ] = str_attach("KEY_D (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F ] = str_attach("KEY_F (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_G ] = str_attach("KEY_G (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_H ] = str_attach("KEY_H (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_J ] = str_attach("KEY_J (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_K ] = str_attach("KEY_K (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_L ] = str_attach("KEY_L (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_SEMICOLON ] = str_attach("KEY_SEMICOLON (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_SINGLE_QUOTE ] = str_attach("KEY_SINGLE_QUOTE (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_BACKTICK ] = str_attach("KEY_BACKTICK (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_LEFT_SHIFT ] = str_attach("KEY_LEFT_SHIFT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_BACKSLASH ] = str_attach("KEY_BACKSLASH (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_Z ] = str_attach("KEY_Z (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_X ] = str_attach("KEY_X (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_C ] = str_attach("KEY_C (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_V ] = str_attach("KEY_V (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_B ] = str_attach("KEY_B (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_N ] = str_attach("KEY_N (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_M ] = str_attach("KEY_M (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_COMMA ] = str_attach("KEY_COMMA (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_DOT ] = str_attach("KEY_DOT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_FORWARD_SLASH ] = str_attach("KEY_FORWARD_SLASH (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_RIGHT_SHIFT ] = str_attach("KEY_RIGHT_SHIFT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_ASTERISK ] = str_attach("KEY_KEYPAD_ASTERISK (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_LEFT_ALT ] = str_attach("KEY_LEFT_ALT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_SPACE ] = str_attach("KEY_SPACE (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_CAPSLOCK ] = str_attach("KEY_CAPSLOCK (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F1 ] = str_attach("KEY_F1 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F2 ] = str_attach("KEY_F2 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F3 ] = str_attach("KEY_F3 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F4 ] = str_attach("KEY_F4 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F5 ] = str_attach("KEY_F5 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F6 ] = str_attach("KEY_F6 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F7 ] = str_attach("KEY_F7 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F8 ] = str_attach("KEY_F8 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F9 ] = str_attach("KEY_F9 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F10 ] = str_attach("KEY_F10 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_NUMBERLOCK ] = str_attach("KEY_NUMBERLOCK (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_SCROLLLOCK ] = str_attach("KEY_SCROLLLOCK (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_7 ] = str_attach("KEY_KEYPAD_7 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_8 ] = str_attach("KEY_KEYPAD_8 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_9 ] = str_attach("KEY_KEYPAD_9 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_MINUS ] = str_attach("KEY_KEYPAD_MINUS (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_4 ] = str_attach("KEY_KEYPAD_4 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_5 ] = str_attach("KEY_KEYPAD_5 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_6 ] = str_attach("KEY_KEYPAD_6 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_PLUS ] = str_attach("KEY_KEYPAD_PLUS (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_1 ] = str_attach("KEY_KEYPAD_1 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_2 ] = str_attach("KEY_KEYPAD_2 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_3 ] = str_attach("KEY_KEYPAD_3 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_0 ] = str_attach("KEY_KEYPAD_0 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_KEYPAD_DOT ] = str_attach("KEY_KEYPAD_DOT (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F11 ] = str_attach("KEY_F11 (RELEASED)"),
|
||||
[KEY_RELEASED | KEY_F12 ] = str_attach("KEY_F12 (RELEASED)"),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "str.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* commands that the system sends to the keyboard */
|
||||
enum ps2_cmd {
|
||||
enum ps2_cmd : uint8_t {
|
||||
/* Set LEDs */
|
||||
PS2CMD_SET_LEDS = 0xED,
|
||||
|
||||
@@ -55,12 +56,11 @@ enum ps2_cmd {
|
||||
|
||||
/* Reset and start self-test */
|
||||
PS2CMD_RESEND_RESET_AND_SELF_TEST = 0xFF,
|
||||
|
||||
PS2CMD_COUNT,
|
||||
};
|
||||
extern const struct str ps2_cmd_str[];
|
||||
|
||||
/* commands that the keyboard sends to the system */
|
||||
enum ps2_response {
|
||||
enum ps2_response : uint8_t {
|
||||
|
||||
/* Self test passed (sent after "0xFF (reset)" command or keyboard power up) */
|
||||
PS2RESPONSE_SELF_TEST_PASSED = 0xAA,
|
||||
@@ -81,11 +81,141 @@ enum ps2_response {
|
||||
/* Key detection error or internal buffer overrun */
|
||||
PS2RESPONSE_ERROR_1 = 0x00,
|
||||
PS2RESPONSE_ERROR_2 = 0xFF,
|
||||
};
|
||||
extern const struct str ps2_response_str[];
|
||||
|
||||
PS2RESPONSE_COUNT,
|
||||
enum ps2_keys {
|
||||
KEY_RELEASED = 0x80,
|
||||
KEY_EXTENDED = 0xE0,
|
||||
|
||||
KEY_ESCAPE = 0x01,
|
||||
KEY_1 = 0x02,
|
||||
KEY_2 = 0x03,
|
||||
KEY_3 = 0x04,
|
||||
KEY_4 = 0x05,
|
||||
KEY_5 = 0x06,
|
||||
KEY_6 = 0x07,
|
||||
KEY_7 = 0x08,
|
||||
KEY_8 = 0x09,
|
||||
KEY_9 = 0x0A,
|
||||
KEY_0 = 0x0B,
|
||||
KEY_MINUS = 0x0C,
|
||||
KEY_EQUALS = 0x0D,
|
||||
KEY_BACKSPACE = 0x0E,
|
||||
KEY_TAB = 0x0F,
|
||||
KEY_Q = 0x10,
|
||||
KEY_W = 0x11,
|
||||
KEY_E = 0x12,
|
||||
KEY_R = 0x13,
|
||||
KEY_T = 0x14,
|
||||
KEY_Y = 0x15,
|
||||
KEY_U = 0x16,
|
||||
KEY_I = 0x17,
|
||||
KEY_O = 0x18,
|
||||
KEY_P = 0x19,
|
||||
KEY_SQUARE_BRACKET_LEFT = 0x1A,
|
||||
KEY_SQUARE_BRACKET_RIGHT = 0x1B,
|
||||
KEY_ENTER = 0x1C,
|
||||
KEY_LEFT_CONTROL = 0x1D,
|
||||
KEY_A = 0x1E,
|
||||
KEY_S = 0x1F,
|
||||
KEY_D = 0x20,
|
||||
KEY_F = 0x21,
|
||||
KEY_G = 0x22,
|
||||
KEY_H = 0x23,
|
||||
KEY_J = 0x24,
|
||||
KEY_K = 0x25,
|
||||
KEY_L = 0x26,
|
||||
KEY_SEMICOLON = 0x27,
|
||||
KEY_SINGLE_QUOTE = 0x28,
|
||||
KEY_BACKTICK = 0x29,
|
||||
KEY_LEFT_SHIFT = 0x2A,
|
||||
KEY_BACKSLASH = 0x2B,
|
||||
KEY_Z = 0x2C,
|
||||
KEY_X = 0x2D,
|
||||
KEY_C = 0x2E,
|
||||
KEY_V = 0x2F,
|
||||
KEY_B = 0x30,
|
||||
KEY_N = 0x31,
|
||||
KEY_M = 0x32,
|
||||
KEY_COMMA = 0x33,
|
||||
KEY_DOT = 0x34,
|
||||
KEY_FORWARD_SLASH = 0x35,
|
||||
KEY_RIGHT_SHIFT = 0x36,
|
||||
KEY_KEYPAD_ASTERISK = 0x37,
|
||||
KEY_LEFT_ALT = 0x38,
|
||||
KEY_SPACE = 0x39,
|
||||
KEY_CAPSLOCK = 0x3A,
|
||||
KEY_F1 = 0x3B,
|
||||
KEY_F2 = 0x3C,
|
||||
KEY_F3 = 0x3D,
|
||||
KEY_F4 = 0x3E,
|
||||
KEY_F5 = 0x3F,
|
||||
KEY_F6 = 0x40,
|
||||
KEY_F7 = 0x41,
|
||||
KEY_F8 = 0x42,
|
||||
KEY_F9 = 0x43,
|
||||
KEY_F10 = 0x44,
|
||||
KEY_NUMBERLOCK = 0x45,
|
||||
KEY_SCROLLLOCK = 0x46,
|
||||
KEY_KEYPAD_7 = 0x47,
|
||||
KEY_KEYPAD_8 = 0x48,
|
||||
KEY_KEYPAD_9 = 0x49,
|
||||
KEY_KEYPAD_MINUS = 0x4A,
|
||||
KEY_KEYPAD_4 = 0x4B,
|
||||
KEY_KEYPAD_5 = 0x4C,
|
||||
KEY_KEYPAD_6 = 0x4D,
|
||||
KEY_KEYPAD_PLUS = 0x4E,
|
||||
KEY_KEYPAD_1 = 0x4F,
|
||||
KEY_KEYPAD_2 = 0x50,
|
||||
KEY_KEYPAD_3 = 0x51,
|
||||
KEY_KEYPAD_0 = 0x52,
|
||||
KEY_KEYPAD_DOT = 0x53,
|
||||
KEY_F11 = 0x57,
|
||||
KEY_F12 = 0x58,
|
||||
};
|
||||
extern const struct str ps2_key_str[];
|
||||
|
||||
enum ps2_extended_key : uint8_t {
|
||||
KEY_E_MULTIMEDIA_PREV_TRACK = 0x10,
|
||||
KEY_E_MULTIMEDIA_NEXT_TRACK = 0x19,
|
||||
KEY_E_KEYPAD_ENTER = 0x1C,
|
||||
KEY_E_RIGHT_CONTROL = 0x1D,
|
||||
KEY_E_MULTIMEDIA_MUTE = 0x20,
|
||||
KEY_E_MULTIMEDIA_CALCULATOR = 0x21,
|
||||
KEY_E_MULTIMEDIA_PLAY = 0x22,
|
||||
KEY_E_MULTIMEDIA_STOP = 0x24,
|
||||
KEY_E_MULTIMEDIA_VOLUME_DOWN = 0x2E,
|
||||
KEY_E_MULTIMEDIA_VOLUME_UP = 0x30,
|
||||
KEY_E_MULTIMEDIA_WWW_HOME = 0x32,
|
||||
KEY_E_KEYPAD_FORWARD_SLASH = 0x35,
|
||||
KEY_E_RIGHT_ALT = 0x38,
|
||||
KEY_E_HOME = 0x47,
|
||||
KEY_E_CURSOR_UP = 0x48,
|
||||
KEY_E_PAGE_UP = 0x49,
|
||||
KEY_E_CURSOR_LEFT = 0x4B,
|
||||
KEY_E_CURSOR_RIGHT = 0x4D,
|
||||
KEY_E_END = 0x4F,
|
||||
KEY_E_CURSOR_DOWN = 0x50,
|
||||
KEY_E_PAGE_DOWN = 0x51,
|
||||
KEY_E_DELETE = 0x53,
|
||||
KEY_E_LEFT_GUI = 0x5B,
|
||||
KEY_E_RIGHT_GUI = 0x5C,
|
||||
KEY_E_APPS = 0x5D,
|
||||
KEY_E_ACPI_SLEEP = 0x5F,
|
||||
KEY_E_ACPI_WAKE = 0x63,
|
||||
KEY_E_MULTIMEDIA_WWW_SEARCH = 0x65,
|
||||
KEY_E_MULTIMEDIA_WWW_REFRESH = 0x67,
|
||||
KEY_E_MULTIMEDIA_WWW_STOP = 0x68,
|
||||
KEY_E_MULTIMEDIA_WWW_FORWARD = 0x69,
|
||||
KEY_E_MULTIMEDIA_MY_COMPUTER = 0x6B,
|
||||
KEY_E_MULTIMEDIA_EMAIL = 0x6C,
|
||||
KEY_E_MULTIMEDIA_MEDIA_SELECT = 0x6D,
|
||||
/* TODO: implement these:
|
||||
0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 pause pressed
|
||||
0x2A, 0xE0, 0x37 print screen pressed
|
||||
0xB7, 0xE0, 0xAA print screen released
|
||||
*/
|
||||
};
|
||||
|
||||
extern const struct str ps2_cmd_str[PS2CMD_COUNT];
|
||||
|
||||
extern const struct str ps2_response_str[PS2RESPONSE_COUNT];
|
||||
|
||||
|
||||
22
src/include/ring_buffer.h
Normal file
22
src/include/ring_buffer.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
constexpr size_t RING_BUFFER_MAX = 1024;
|
||||
|
||||
struct ring_buffer {
|
||||
size_t head;
|
||||
size_t tail;
|
||||
size_t len;
|
||||
size_t entry_size;
|
||||
uint8_t data[RING_BUFFER_MAX];
|
||||
};
|
||||
|
||||
#define make_ring_buffer(type) (struct ring_buffer){.entry_size = sizeof(type)}
|
||||
|
||||
size_t ring_buffer_remaining(struct ring_buffer* q);
|
||||
|
||||
bool ring_buffer_push(struct ring_buffer* q, const void* data);
|
||||
|
||||
bool ring_buffer_get(struct ring_buffer* q, void* out);
|
||||
@@ -4,7 +4,9 @@
|
||||
#include "interrupts.h"
|
||||
#include "kernel_state.h"
|
||||
|
||||
#define EXCEPTION_DEPTH_MAX 5
|
||||
#include "pic.h"
|
||||
|
||||
#define EXCEPTION_DEPTH_MAX 3
|
||||
|
||||
struct __attribute__((packed)) interrupt_frame {
|
||||
uword_t ip;
|
||||
@@ -31,6 +33,25 @@ static void print_interrupt_frame(struct interrupt_frame* f)
|
||||
f->ss);
|
||||
}
|
||||
|
||||
/* not an interrupt/exception, but called by exception stubs */
|
||||
__attribute__((noreturn))
|
||||
static void panic_exception_not_implemented(struct interrupt_frame* frame, int exception_no)
|
||||
{
|
||||
terminal_set_color(VGA_COLOR_WHITE, VGA_COLOR_RED);
|
||||
printf(str_attach("non-implemented exception {i32} occurred\n"), exception_no);
|
||||
struct str name = idt_desc_index_str[exception_no];
|
||||
if (name.len != 0) {
|
||||
printf(str_attach("exception name: {str})\n"), name);
|
||||
}
|
||||
if (frame != NULL) {
|
||||
print_interrupt_frame(frame);
|
||||
} else {
|
||||
printf(str_attach("(no interrupt frame)n"));
|
||||
}
|
||||
__asm__ volatile("cli; hlt");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptions
|
||||
* ==========
|
||||
@@ -89,18 +110,6 @@ void exception_handler_page_fault(struct interrupt_frame* frame, int err)
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
__attribute__((interrupt, noreturn))
|
||||
void exception_default(struct interrupt_frame* frame)
|
||||
{
|
||||
(void)frame;
|
||||
if (kernel.nested_exception_counter++ > EXCEPTION_DEPTH_MAX) {
|
||||
panic(str_attach("fatal: too many nested exceptions\n"));
|
||||
}
|
||||
panic(str_attach("non-implemented exception occured"));
|
||||
|
||||
kernel.nested_exception_counter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupts
|
||||
* ==========
|
||||
@@ -129,16 +138,320 @@ void interrupt_handler_1(struct interrupt_frame* frame)
|
||||
kernel.nested_exception_counter = 0;
|
||||
}
|
||||
|
||||
__attribute__((interrupt))
|
||||
void interrupt_handler_userspace_exit(struct interrupt_frame* frame)
|
||||
/*
|
||||
* IRQs
|
||||
* ====
|
||||
* */
|
||||
static void irq_stub(struct interrupt_frame* frame, int line)
|
||||
{
|
||||
(void)frame;
|
||||
(void)line;
|
||||
if (kernel.nested_exception_counter++ > EXCEPTION_DEPTH_MAX) {
|
||||
panic(str_attach("fatal: too many nested exceptions\n"));
|
||||
}
|
||||
(void)frame;
|
||||
printf(str_attach("interrupt_handler_userspace_exit called!\n"));
|
||||
|
||||
//printf(str_attach("irq handler {i32} called!\n"), line);
|
||||
outb(PIC1_COMMAND, OCW2_EOI);
|
||||
kernel.nested_exception_counter = 0;
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void irq_handler_0(struct interrupt_frame* frame) { irq_stub(frame, 0); }
|
||||
|
||||
/* IRQ1 - keyboard controller */
|
||||
#include "ps2-keyboard.h"
|
||||
__attribute__((interrupt)) void irq_handler_1(struct interrupt_frame* frame)
|
||||
{
|
||||
/* TODO: move keyboard logic to a separate compilation unit */
|
||||
(void)frame;
|
||||
uint8_t key = inb(PIC_KEYBOARD);
|
||||
|
||||
bool released = key & KEY_RELEASED;
|
||||
|
||||
printf(str_attach("key {str}\n"), ps2_key_str[key]);
|
||||
outb(PIC1_COMMAND, OCW2_EOI);
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void irq_handler_2(struct interrupt_frame* frame) { irq_stub(frame, 2); }
|
||||
__attribute__((interrupt)) void irq_handler_3(struct interrupt_frame* frame) { irq_stub(frame, 3); }
|
||||
__attribute__((interrupt)) void irq_handler_4(struct interrupt_frame* frame) { irq_stub(frame, 4); }
|
||||
__attribute__((interrupt)) void irq_handler_5(struct interrupt_frame* frame) { irq_stub(frame, 5); }
|
||||
__attribute__((interrupt)) void irq_handler_6(struct interrupt_frame* frame) { irq_stub(frame, 6); }
|
||||
__attribute__((interrupt)) void irq_handler_7(struct interrupt_frame* frame) { irq_stub(frame, 7); }
|
||||
__attribute__((interrupt)) void irq_handler_8(struct interrupt_frame* frame) { irq_stub(frame, 8); }
|
||||
__attribute__((interrupt)) void irq_handler_9(struct interrupt_frame* frame) { irq_stub(frame, 9); }
|
||||
__attribute__((interrupt)) void irq_handler_10(struct interrupt_frame* frame) { irq_stub(frame, 10); }
|
||||
__attribute__((interrupt)) void irq_handler_11(struct interrupt_frame* frame) { irq_stub(frame, 11); }
|
||||
__attribute__((interrupt)) void irq_handler_12(struct interrupt_frame* frame) { irq_stub(frame, 12); }
|
||||
__attribute__((interrupt)) void irq_handler_13(struct interrupt_frame* frame) { irq_stub(frame, 13); }
|
||||
__attribute__((interrupt)) void irq_handler_14(struct interrupt_frame* frame) { irq_stub(frame, 14); }
|
||||
__attribute__((interrupt)) void irq_handler_15(struct interrupt_frame* frame) { irq_stub(frame, 15); }
|
||||
|
||||
|
||||
/**
|
||||
* Exception Stubs
|
||||
* ===============
|
||||
*/
|
||||
|
||||
#define DEFINE_EXCEPTION_STUB(n) \
|
||||
__attribute__((interrupt, noreturn)) \
|
||||
void EXCEPTION_STUB(n)(struct interrupt_frame* frame) \
|
||||
{ \
|
||||
panic_exception_not_implemented(frame, n); \
|
||||
}
|
||||
|
||||
DEFINE_EXCEPTION_STUB(0)
|
||||
DEFINE_EXCEPTION_STUB(1)
|
||||
DEFINE_EXCEPTION_STUB(2)
|
||||
DEFINE_EXCEPTION_STUB(3)
|
||||
DEFINE_EXCEPTION_STUB(4)
|
||||
DEFINE_EXCEPTION_STUB(5)
|
||||
DEFINE_EXCEPTION_STUB(6)
|
||||
DEFINE_EXCEPTION_STUB(7)
|
||||
DEFINE_EXCEPTION_STUB(8)
|
||||
DEFINE_EXCEPTION_STUB(9)
|
||||
DEFINE_EXCEPTION_STUB(10)
|
||||
DEFINE_EXCEPTION_STUB(11)
|
||||
DEFINE_EXCEPTION_STUB(12)
|
||||
DEFINE_EXCEPTION_STUB(13)
|
||||
DEFINE_EXCEPTION_STUB(14)
|
||||
DEFINE_EXCEPTION_STUB(15)
|
||||
DEFINE_EXCEPTION_STUB(16)
|
||||
DEFINE_EXCEPTION_STUB(17)
|
||||
DEFINE_EXCEPTION_STUB(18)
|
||||
DEFINE_EXCEPTION_STUB(19)
|
||||
DEFINE_EXCEPTION_STUB(20)
|
||||
DEFINE_EXCEPTION_STUB(21)
|
||||
DEFINE_EXCEPTION_STUB(22)
|
||||
DEFINE_EXCEPTION_STUB(23)
|
||||
DEFINE_EXCEPTION_STUB(24)
|
||||
DEFINE_EXCEPTION_STUB(25)
|
||||
DEFINE_EXCEPTION_STUB(26)
|
||||
DEFINE_EXCEPTION_STUB(27)
|
||||
DEFINE_EXCEPTION_STUB(28)
|
||||
DEFINE_EXCEPTION_STUB(29)
|
||||
DEFINE_EXCEPTION_STUB(30)
|
||||
DEFINE_EXCEPTION_STUB(31)
|
||||
DEFINE_EXCEPTION_STUB(32)
|
||||
DEFINE_EXCEPTION_STUB(33)
|
||||
DEFINE_EXCEPTION_STUB(34)
|
||||
DEFINE_EXCEPTION_STUB(35)
|
||||
DEFINE_EXCEPTION_STUB(36)
|
||||
DEFINE_EXCEPTION_STUB(37)
|
||||
DEFINE_EXCEPTION_STUB(38)
|
||||
DEFINE_EXCEPTION_STUB(39)
|
||||
DEFINE_EXCEPTION_STUB(40)
|
||||
DEFINE_EXCEPTION_STUB(41)
|
||||
DEFINE_EXCEPTION_STUB(42)
|
||||
DEFINE_EXCEPTION_STUB(43)
|
||||
DEFINE_EXCEPTION_STUB(44)
|
||||
DEFINE_EXCEPTION_STUB(45)
|
||||
DEFINE_EXCEPTION_STUB(46)
|
||||
DEFINE_EXCEPTION_STUB(47)
|
||||
DEFINE_EXCEPTION_STUB(48)
|
||||
DEFINE_EXCEPTION_STUB(49)
|
||||
DEFINE_EXCEPTION_STUB(50)
|
||||
DEFINE_EXCEPTION_STUB(51)
|
||||
DEFINE_EXCEPTION_STUB(52)
|
||||
DEFINE_EXCEPTION_STUB(53)
|
||||
DEFINE_EXCEPTION_STUB(54)
|
||||
DEFINE_EXCEPTION_STUB(55)
|
||||
DEFINE_EXCEPTION_STUB(56)
|
||||
DEFINE_EXCEPTION_STUB(57)
|
||||
DEFINE_EXCEPTION_STUB(58)
|
||||
DEFINE_EXCEPTION_STUB(59)
|
||||
DEFINE_EXCEPTION_STUB(60)
|
||||
DEFINE_EXCEPTION_STUB(61)
|
||||
DEFINE_EXCEPTION_STUB(62)
|
||||
DEFINE_EXCEPTION_STUB(63)
|
||||
DEFINE_EXCEPTION_STUB(64)
|
||||
DEFINE_EXCEPTION_STUB(65)
|
||||
DEFINE_EXCEPTION_STUB(66)
|
||||
DEFINE_EXCEPTION_STUB(67)
|
||||
DEFINE_EXCEPTION_STUB(68)
|
||||
DEFINE_EXCEPTION_STUB(69)
|
||||
DEFINE_EXCEPTION_STUB(70)
|
||||
DEFINE_EXCEPTION_STUB(71)
|
||||
DEFINE_EXCEPTION_STUB(72)
|
||||
DEFINE_EXCEPTION_STUB(73)
|
||||
DEFINE_EXCEPTION_STUB(74)
|
||||
DEFINE_EXCEPTION_STUB(75)
|
||||
DEFINE_EXCEPTION_STUB(76)
|
||||
DEFINE_EXCEPTION_STUB(77)
|
||||
DEFINE_EXCEPTION_STUB(78)
|
||||
DEFINE_EXCEPTION_STUB(79)
|
||||
DEFINE_EXCEPTION_STUB(80)
|
||||
DEFINE_EXCEPTION_STUB(81)
|
||||
DEFINE_EXCEPTION_STUB(82)
|
||||
DEFINE_EXCEPTION_STUB(83)
|
||||
DEFINE_EXCEPTION_STUB(84)
|
||||
DEFINE_EXCEPTION_STUB(85)
|
||||
DEFINE_EXCEPTION_STUB(86)
|
||||
DEFINE_EXCEPTION_STUB(87)
|
||||
DEFINE_EXCEPTION_STUB(88)
|
||||
DEFINE_EXCEPTION_STUB(89)
|
||||
DEFINE_EXCEPTION_STUB(90)
|
||||
DEFINE_EXCEPTION_STUB(91)
|
||||
DEFINE_EXCEPTION_STUB(92)
|
||||
DEFINE_EXCEPTION_STUB(93)
|
||||
DEFINE_EXCEPTION_STUB(94)
|
||||
DEFINE_EXCEPTION_STUB(95)
|
||||
DEFINE_EXCEPTION_STUB(96)
|
||||
DEFINE_EXCEPTION_STUB(97)
|
||||
DEFINE_EXCEPTION_STUB(98)
|
||||
DEFINE_EXCEPTION_STUB(99)
|
||||
DEFINE_EXCEPTION_STUB(100)
|
||||
DEFINE_EXCEPTION_STUB(101)
|
||||
DEFINE_EXCEPTION_STUB(102)
|
||||
DEFINE_EXCEPTION_STUB(103)
|
||||
DEFINE_EXCEPTION_STUB(104)
|
||||
DEFINE_EXCEPTION_STUB(105)
|
||||
DEFINE_EXCEPTION_STUB(106)
|
||||
DEFINE_EXCEPTION_STUB(107)
|
||||
DEFINE_EXCEPTION_STUB(108)
|
||||
DEFINE_EXCEPTION_STUB(109)
|
||||
DEFINE_EXCEPTION_STUB(110)
|
||||
DEFINE_EXCEPTION_STUB(111)
|
||||
DEFINE_EXCEPTION_STUB(112)
|
||||
DEFINE_EXCEPTION_STUB(113)
|
||||
DEFINE_EXCEPTION_STUB(114)
|
||||
DEFINE_EXCEPTION_STUB(115)
|
||||
DEFINE_EXCEPTION_STUB(116)
|
||||
DEFINE_EXCEPTION_STUB(117)
|
||||
DEFINE_EXCEPTION_STUB(118)
|
||||
DEFINE_EXCEPTION_STUB(119)
|
||||
DEFINE_EXCEPTION_STUB(120)
|
||||
DEFINE_EXCEPTION_STUB(121)
|
||||
DEFINE_EXCEPTION_STUB(122)
|
||||
DEFINE_EXCEPTION_STUB(123)
|
||||
DEFINE_EXCEPTION_STUB(124)
|
||||
DEFINE_EXCEPTION_STUB(125)
|
||||
DEFINE_EXCEPTION_STUB(126)
|
||||
DEFINE_EXCEPTION_STUB(127)
|
||||
DEFINE_EXCEPTION_STUB(128)
|
||||
DEFINE_EXCEPTION_STUB(129)
|
||||
DEFINE_EXCEPTION_STUB(130)
|
||||
DEFINE_EXCEPTION_STUB(131)
|
||||
DEFINE_EXCEPTION_STUB(132)
|
||||
DEFINE_EXCEPTION_STUB(133)
|
||||
DEFINE_EXCEPTION_STUB(134)
|
||||
DEFINE_EXCEPTION_STUB(135)
|
||||
DEFINE_EXCEPTION_STUB(136)
|
||||
DEFINE_EXCEPTION_STUB(137)
|
||||
DEFINE_EXCEPTION_STUB(138)
|
||||
DEFINE_EXCEPTION_STUB(139)
|
||||
DEFINE_EXCEPTION_STUB(140)
|
||||
DEFINE_EXCEPTION_STUB(141)
|
||||
DEFINE_EXCEPTION_STUB(142)
|
||||
DEFINE_EXCEPTION_STUB(143)
|
||||
DEFINE_EXCEPTION_STUB(144)
|
||||
DEFINE_EXCEPTION_STUB(145)
|
||||
DEFINE_EXCEPTION_STUB(146)
|
||||
DEFINE_EXCEPTION_STUB(147)
|
||||
DEFINE_EXCEPTION_STUB(148)
|
||||
DEFINE_EXCEPTION_STUB(149)
|
||||
DEFINE_EXCEPTION_STUB(150)
|
||||
DEFINE_EXCEPTION_STUB(151)
|
||||
DEFINE_EXCEPTION_STUB(152)
|
||||
DEFINE_EXCEPTION_STUB(153)
|
||||
DEFINE_EXCEPTION_STUB(154)
|
||||
DEFINE_EXCEPTION_STUB(155)
|
||||
DEFINE_EXCEPTION_STUB(156)
|
||||
DEFINE_EXCEPTION_STUB(157)
|
||||
DEFINE_EXCEPTION_STUB(158)
|
||||
DEFINE_EXCEPTION_STUB(159)
|
||||
DEFINE_EXCEPTION_STUB(160)
|
||||
DEFINE_EXCEPTION_STUB(161)
|
||||
DEFINE_EXCEPTION_STUB(162)
|
||||
DEFINE_EXCEPTION_STUB(163)
|
||||
DEFINE_EXCEPTION_STUB(164)
|
||||
DEFINE_EXCEPTION_STUB(165)
|
||||
DEFINE_EXCEPTION_STUB(166)
|
||||
DEFINE_EXCEPTION_STUB(167)
|
||||
DEFINE_EXCEPTION_STUB(168)
|
||||
DEFINE_EXCEPTION_STUB(169)
|
||||
DEFINE_EXCEPTION_STUB(170)
|
||||
DEFINE_EXCEPTION_STUB(171)
|
||||
DEFINE_EXCEPTION_STUB(172)
|
||||
DEFINE_EXCEPTION_STUB(173)
|
||||
DEFINE_EXCEPTION_STUB(174)
|
||||
DEFINE_EXCEPTION_STUB(175)
|
||||
DEFINE_EXCEPTION_STUB(176)
|
||||
DEFINE_EXCEPTION_STUB(177)
|
||||
DEFINE_EXCEPTION_STUB(178)
|
||||
DEFINE_EXCEPTION_STUB(179)
|
||||
DEFINE_EXCEPTION_STUB(180)
|
||||
DEFINE_EXCEPTION_STUB(181)
|
||||
DEFINE_EXCEPTION_STUB(182)
|
||||
DEFINE_EXCEPTION_STUB(183)
|
||||
DEFINE_EXCEPTION_STUB(184)
|
||||
DEFINE_EXCEPTION_STUB(185)
|
||||
DEFINE_EXCEPTION_STUB(186)
|
||||
DEFINE_EXCEPTION_STUB(187)
|
||||
DEFINE_EXCEPTION_STUB(188)
|
||||
DEFINE_EXCEPTION_STUB(189)
|
||||
DEFINE_EXCEPTION_STUB(190)
|
||||
DEFINE_EXCEPTION_STUB(191)
|
||||
DEFINE_EXCEPTION_STUB(192)
|
||||
DEFINE_EXCEPTION_STUB(193)
|
||||
DEFINE_EXCEPTION_STUB(194)
|
||||
DEFINE_EXCEPTION_STUB(195)
|
||||
DEFINE_EXCEPTION_STUB(196)
|
||||
DEFINE_EXCEPTION_STUB(197)
|
||||
DEFINE_EXCEPTION_STUB(198)
|
||||
DEFINE_EXCEPTION_STUB(199)
|
||||
DEFINE_EXCEPTION_STUB(200)
|
||||
DEFINE_EXCEPTION_STUB(201)
|
||||
DEFINE_EXCEPTION_STUB(202)
|
||||
DEFINE_EXCEPTION_STUB(203)
|
||||
DEFINE_EXCEPTION_STUB(204)
|
||||
DEFINE_EXCEPTION_STUB(205)
|
||||
DEFINE_EXCEPTION_STUB(206)
|
||||
DEFINE_EXCEPTION_STUB(207)
|
||||
DEFINE_EXCEPTION_STUB(208)
|
||||
DEFINE_EXCEPTION_STUB(209)
|
||||
DEFINE_EXCEPTION_STUB(210)
|
||||
DEFINE_EXCEPTION_STUB(211)
|
||||
DEFINE_EXCEPTION_STUB(212)
|
||||
DEFINE_EXCEPTION_STUB(213)
|
||||
DEFINE_EXCEPTION_STUB(214)
|
||||
DEFINE_EXCEPTION_STUB(215)
|
||||
DEFINE_EXCEPTION_STUB(216)
|
||||
DEFINE_EXCEPTION_STUB(217)
|
||||
DEFINE_EXCEPTION_STUB(218)
|
||||
DEFINE_EXCEPTION_STUB(219)
|
||||
DEFINE_EXCEPTION_STUB(220)
|
||||
DEFINE_EXCEPTION_STUB(221)
|
||||
DEFINE_EXCEPTION_STUB(222)
|
||||
DEFINE_EXCEPTION_STUB(223)
|
||||
DEFINE_EXCEPTION_STUB(224)
|
||||
DEFINE_EXCEPTION_STUB(225)
|
||||
DEFINE_EXCEPTION_STUB(226)
|
||||
DEFINE_EXCEPTION_STUB(227)
|
||||
DEFINE_EXCEPTION_STUB(228)
|
||||
DEFINE_EXCEPTION_STUB(229)
|
||||
DEFINE_EXCEPTION_STUB(230)
|
||||
DEFINE_EXCEPTION_STUB(231)
|
||||
DEFINE_EXCEPTION_STUB(232)
|
||||
DEFINE_EXCEPTION_STUB(233)
|
||||
DEFINE_EXCEPTION_STUB(234)
|
||||
DEFINE_EXCEPTION_STUB(235)
|
||||
DEFINE_EXCEPTION_STUB(236)
|
||||
DEFINE_EXCEPTION_STUB(237)
|
||||
DEFINE_EXCEPTION_STUB(238)
|
||||
DEFINE_EXCEPTION_STUB(239)
|
||||
DEFINE_EXCEPTION_STUB(240)
|
||||
DEFINE_EXCEPTION_STUB(241)
|
||||
DEFINE_EXCEPTION_STUB(242)
|
||||
DEFINE_EXCEPTION_STUB(243)
|
||||
DEFINE_EXCEPTION_STUB(244)
|
||||
DEFINE_EXCEPTION_STUB(245)
|
||||
DEFINE_EXCEPTION_STUB(246)
|
||||
DEFINE_EXCEPTION_STUB(247)
|
||||
DEFINE_EXCEPTION_STUB(248)
|
||||
DEFINE_EXCEPTION_STUB(249)
|
||||
DEFINE_EXCEPTION_STUB(250)
|
||||
DEFINE_EXCEPTION_STUB(251)
|
||||
DEFINE_EXCEPTION_STUB(252)
|
||||
DEFINE_EXCEPTION_STUB(253)
|
||||
DEFINE_EXCEPTION_STUB(254)
|
||||
DEFINE_EXCEPTION_STUB(255)
|
||||
|
||||
@@ -10,6 +10,9 @@ struct __attribute__((packed)) interrupt_frame {
|
||||
uword_t ss;
|
||||
};
|
||||
|
||||
/*
|
||||
* Exceptions
|
||||
* ==========*/
|
||||
__attribute__((interrupt, noreturn))
|
||||
void exception_handler_div_by_zero(struct interrupt_frame* frame);
|
||||
|
||||
@@ -22,12 +25,318 @@ void exception_handler_double_fault(struct interrupt_frame* frame);
|
||||
__attribute__((interrupt, noreturn))
|
||||
void exception_default(struct interrupt_frame* frame);
|
||||
|
||||
/**
|
||||
* Interrupts
|
||||
* ==========
|
||||
*/
|
||||
__attribute__((interrupt, noreturn))
|
||||
void interrupt_default(struct interrupt_frame* frame);
|
||||
|
||||
__attribute__((interrupt))
|
||||
void interrupt_handler_1(struct interrupt_frame* frame);
|
||||
|
||||
__attribute__((interrupt))
|
||||
void interrupt_handler_userspace_exit(struct interrupt_frame* frame);
|
||||
/**
|
||||
* IRQs
|
||||
* ====
|
||||
*/
|
||||
__attribute__((interrupt)) void irq_handler_0(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_1(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_2(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_3(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_4(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_5(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_6(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_7(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_8(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_9(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_10(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_11(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_12(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_13(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_14(struct interrupt_frame*);
|
||||
__attribute__((interrupt)) void irq_handler_15(struct interrupt_frame*);
|
||||
|
||||
|
||||
/*
|
||||
* Exception and interrupt stubs
|
||||
* =============================
|
||||
* Everything below this line is a horrible compile time crime.
|
||||
* */
|
||||
|
||||
|
||||
#include "idt.h"
|
||||
#include "kernel_state.h"
|
||||
|
||||
/* This function is a horrible crime */
|
||||
static void idt_init_stubs(struct idt_gate_descriptor idt[]) {
|
||||
#define EXCEPTION_STUB(n) exception_stub_##n
|
||||
|
||||
#define DESC(func) \
|
||||
idt_encode_descriptor( \
|
||||
func, \
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0), \
|
||||
IDT_DPL_3, \
|
||||
IDT_GATE_TYPE_TRAP32)
|
||||
|
||||
#define DECLARE_EXCEPTION_STUB(n) \
|
||||
__attribute__((interrupt)) void EXCEPTION_STUB(n)(struct interrupt_frame*); \
|
||||
idt[n] = DESC(EXCEPTION_STUB(n))
|
||||
DECLARE_EXCEPTION_STUB(0);
|
||||
DECLARE_EXCEPTION_STUB(1);
|
||||
DECLARE_EXCEPTION_STUB(2);
|
||||
DECLARE_EXCEPTION_STUB(3);
|
||||
DECLARE_EXCEPTION_STUB(4);
|
||||
DECLARE_EXCEPTION_STUB(5);
|
||||
DECLARE_EXCEPTION_STUB(6);
|
||||
DECLARE_EXCEPTION_STUB(7);
|
||||
DECLARE_EXCEPTION_STUB(8);
|
||||
DECLARE_EXCEPTION_STUB(9);
|
||||
DECLARE_EXCEPTION_STUB(10);
|
||||
DECLARE_EXCEPTION_STUB(11);
|
||||
DECLARE_EXCEPTION_STUB(12);
|
||||
DECLARE_EXCEPTION_STUB(13);
|
||||
DECLARE_EXCEPTION_STUB(14);
|
||||
DECLARE_EXCEPTION_STUB(15);
|
||||
DECLARE_EXCEPTION_STUB(16);
|
||||
DECLARE_EXCEPTION_STUB(17);
|
||||
DECLARE_EXCEPTION_STUB(18);
|
||||
DECLARE_EXCEPTION_STUB(19);
|
||||
DECLARE_EXCEPTION_STUB(20);
|
||||
DECLARE_EXCEPTION_STUB(21);
|
||||
DECLARE_EXCEPTION_STUB(22);
|
||||
DECLARE_EXCEPTION_STUB(23);
|
||||
DECLARE_EXCEPTION_STUB(24);
|
||||
DECLARE_EXCEPTION_STUB(25);
|
||||
DECLARE_EXCEPTION_STUB(26);
|
||||
DECLARE_EXCEPTION_STUB(27);
|
||||
DECLARE_EXCEPTION_STUB(28);
|
||||
DECLARE_EXCEPTION_STUB(29);
|
||||
DECLARE_EXCEPTION_STUB(30);
|
||||
DECLARE_EXCEPTION_STUB(31);
|
||||
DECLARE_EXCEPTION_STUB(32);
|
||||
DECLARE_EXCEPTION_STUB(33);
|
||||
DECLARE_EXCEPTION_STUB(34);
|
||||
DECLARE_EXCEPTION_STUB(35);
|
||||
DECLARE_EXCEPTION_STUB(36);
|
||||
DECLARE_EXCEPTION_STUB(37);
|
||||
DECLARE_EXCEPTION_STUB(38);
|
||||
DECLARE_EXCEPTION_STUB(39);
|
||||
DECLARE_EXCEPTION_STUB(40);
|
||||
DECLARE_EXCEPTION_STUB(41);
|
||||
DECLARE_EXCEPTION_STUB(42);
|
||||
DECLARE_EXCEPTION_STUB(43);
|
||||
DECLARE_EXCEPTION_STUB(44);
|
||||
DECLARE_EXCEPTION_STUB(45);
|
||||
DECLARE_EXCEPTION_STUB(46);
|
||||
DECLARE_EXCEPTION_STUB(47);
|
||||
DECLARE_EXCEPTION_STUB(48);
|
||||
DECLARE_EXCEPTION_STUB(49);
|
||||
DECLARE_EXCEPTION_STUB(50);
|
||||
DECLARE_EXCEPTION_STUB(51);
|
||||
DECLARE_EXCEPTION_STUB(52);
|
||||
DECLARE_EXCEPTION_STUB(53);
|
||||
DECLARE_EXCEPTION_STUB(54);
|
||||
DECLARE_EXCEPTION_STUB(55);
|
||||
DECLARE_EXCEPTION_STUB(56);
|
||||
DECLARE_EXCEPTION_STUB(57);
|
||||
DECLARE_EXCEPTION_STUB(58);
|
||||
DECLARE_EXCEPTION_STUB(59);
|
||||
DECLARE_EXCEPTION_STUB(60);
|
||||
DECLARE_EXCEPTION_STUB(61);
|
||||
DECLARE_EXCEPTION_STUB(62);
|
||||
DECLARE_EXCEPTION_STUB(63);
|
||||
DECLARE_EXCEPTION_STUB(64);
|
||||
DECLARE_EXCEPTION_STUB(65);
|
||||
DECLARE_EXCEPTION_STUB(66);
|
||||
DECLARE_EXCEPTION_STUB(67);
|
||||
DECLARE_EXCEPTION_STUB(68);
|
||||
DECLARE_EXCEPTION_STUB(69);
|
||||
DECLARE_EXCEPTION_STUB(70);
|
||||
DECLARE_EXCEPTION_STUB(71);
|
||||
DECLARE_EXCEPTION_STUB(72);
|
||||
DECLARE_EXCEPTION_STUB(73);
|
||||
DECLARE_EXCEPTION_STUB(74);
|
||||
DECLARE_EXCEPTION_STUB(75);
|
||||
DECLARE_EXCEPTION_STUB(76);
|
||||
DECLARE_EXCEPTION_STUB(77);
|
||||
DECLARE_EXCEPTION_STUB(78);
|
||||
DECLARE_EXCEPTION_STUB(79);
|
||||
DECLARE_EXCEPTION_STUB(80);
|
||||
DECLARE_EXCEPTION_STUB(81);
|
||||
DECLARE_EXCEPTION_STUB(82);
|
||||
DECLARE_EXCEPTION_STUB(83);
|
||||
DECLARE_EXCEPTION_STUB(84);
|
||||
DECLARE_EXCEPTION_STUB(85);
|
||||
DECLARE_EXCEPTION_STUB(86);
|
||||
DECLARE_EXCEPTION_STUB(87);
|
||||
DECLARE_EXCEPTION_STUB(88);
|
||||
DECLARE_EXCEPTION_STUB(89);
|
||||
DECLARE_EXCEPTION_STUB(90);
|
||||
DECLARE_EXCEPTION_STUB(91);
|
||||
DECLARE_EXCEPTION_STUB(92);
|
||||
DECLARE_EXCEPTION_STUB(93);
|
||||
DECLARE_EXCEPTION_STUB(94);
|
||||
DECLARE_EXCEPTION_STUB(95);
|
||||
DECLARE_EXCEPTION_STUB(96);
|
||||
DECLARE_EXCEPTION_STUB(97);
|
||||
DECLARE_EXCEPTION_STUB(98);
|
||||
DECLARE_EXCEPTION_STUB(99);
|
||||
DECLARE_EXCEPTION_STUB(100);
|
||||
DECLARE_EXCEPTION_STUB(101);
|
||||
DECLARE_EXCEPTION_STUB(102);
|
||||
DECLARE_EXCEPTION_STUB(103);
|
||||
DECLARE_EXCEPTION_STUB(104);
|
||||
DECLARE_EXCEPTION_STUB(105);
|
||||
DECLARE_EXCEPTION_STUB(106);
|
||||
DECLARE_EXCEPTION_STUB(107);
|
||||
DECLARE_EXCEPTION_STUB(108);
|
||||
DECLARE_EXCEPTION_STUB(109);
|
||||
DECLARE_EXCEPTION_STUB(110);
|
||||
DECLARE_EXCEPTION_STUB(111);
|
||||
DECLARE_EXCEPTION_STUB(112);
|
||||
DECLARE_EXCEPTION_STUB(113);
|
||||
DECLARE_EXCEPTION_STUB(114);
|
||||
DECLARE_EXCEPTION_STUB(115);
|
||||
DECLARE_EXCEPTION_STUB(116);
|
||||
DECLARE_EXCEPTION_STUB(117);
|
||||
DECLARE_EXCEPTION_STUB(118);
|
||||
DECLARE_EXCEPTION_STUB(119);
|
||||
DECLARE_EXCEPTION_STUB(120);
|
||||
DECLARE_EXCEPTION_STUB(121);
|
||||
DECLARE_EXCEPTION_STUB(122);
|
||||
DECLARE_EXCEPTION_STUB(123);
|
||||
DECLARE_EXCEPTION_STUB(124);
|
||||
DECLARE_EXCEPTION_STUB(125);
|
||||
DECLARE_EXCEPTION_STUB(126);
|
||||
DECLARE_EXCEPTION_STUB(127);
|
||||
DECLARE_EXCEPTION_STUB(128);
|
||||
DECLARE_EXCEPTION_STUB(129);
|
||||
DECLARE_EXCEPTION_STUB(130);
|
||||
DECLARE_EXCEPTION_STUB(131);
|
||||
DECLARE_EXCEPTION_STUB(132);
|
||||
DECLARE_EXCEPTION_STUB(133);
|
||||
DECLARE_EXCEPTION_STUB(134);
|
||||
DECLARE_EXCEPTION_STUB(135);
|
||||
DECLARE_EXCEPTION_STUB(136);
|
||||
DECLARE_EXCEPTION_STUB(137);
|
||||
DECLARE_EXCEPTION_STUB(138);
|
||||
DECLARE_EXCEPTION_STUB(139);
|
||||
DECLARE_EXCEPTION_STUB(140);
|
||||
DECLARE_EXCEPTION_STUB(141);
|
||||
DECLARE_EXCEPTION_STUB(142);
|
||||
DECLARE_EXCEPTION_STUB(143);
|
||||
DECLARE_EXCEPTION_STUB(144);
|
||||
DECLARE_EXCEPTION_STUB(145);
|
||||
DECLARE_EXCEPTION_STUB(146);
|
||||
DECLARE_EXCEPTION_STUB(147);
|
||||
DECLARE_EXCEPTION_STUB(148);
|
||||
DECLARE_EXCEPTION_STUB(149);
|
||||
DECLARE_EXCEPTION_STUB(150);
|
||||
DECLARE_EXCEPTION_STUB(151);
|
||||
DECLARE_EXCEPTION_STUB(152);
|
||||
DECLARE_EXCEPTION_STUB(153);
|
||||
DECLARE_EXCEPTION_STUB(154);
|
||||
DECLARE_EXCEPTION_STUB(155);
|
||||
DECLARE_EXCEPTION_STUB(156);
|
||||
DECLARE_EXCEPTION_STUB(157);
|
||||
DECLARE_EXCEPTION_STUB(158);
|
||||
DECLARE_EXCEPTION_STUB(159);
|
||||
DECLARE_EXCEPTION_STUB(160);
|
||||
DECLARE_EXCEPTION_STUB(161);
|
||||
DECLARE_EXCEPTION_STUB(162);
|
||||
DECLARE_EXCEPTION_STUB(163);
|
||||
DECLARE_EXCEPTION_STUB(164);
|
||||
DECLARE_EXCEPTION_STUB(165);
|
||||
DECLARE_EXCEPTION_STUB(166);
|
||||
DECLARE_EXCEPTION_STUB(167);
|
||||
DECLARE_EXCEPTION_STUB(168);
|
||||
DECLARE_EXCEPTION_STUB(169);
|
||||
DECLARE_EXCEPTION_STUB(170);
|
||||
DECLARE_EXCEPTION_STUB(171);
|
||||
DECLARE_EXCEPTION_STUB(172);
|
||||
DECLARE_EXCEPTION_STUB(173);
|
||||
DECLARE_EXCEPTION_STUB(174);
|
||||
DECLARE_EXCEPTION_STUB(175);
|
||||
DECLARE_EXCEPTION_STUB(176);
|
||||
DECLARE_EXCEPTION_STUB(177);
|
||||
DECLARE_EXCEPTION_STUB(178);
|
||||
DECLARE_EXCEPTION_STUB(179);
|
||||
DECLARE_EXCEPTION_STUB(180);
|
||||
DECLARE_EXCEPTION_STUB(181);
|
||||
DECLARE_EXCEPTION_STUB(182);
|
||||
DECLARE_EXCEPTION_STUB(183);
|
||||
DECLARE_EXCEPTION_STUB(184);
|
||||
DECLARE_EXCEPTION_STUB(185);
|
||||
DECLARE_EXCEPTION_STUB(186);
|
||||
DECLARE_EXCEPTION_STUB(187);
|
||||
DECLARE_EXCEPTION_STUB(188);
|
||||
DECLARE_EXCEPTION_STUB(189);
|
||||
DECLARE_EXCEPTION_STUB(190);
|
||||
DECLARE_EXCEPTION_STUB(191);
|
||||
DECLARE_EXCEPTION_STUB(192);
|
||||
DECLARE_EXCEPTION_STUB(193);
|
||||
DECLARE_EXCEPTION_STUB(194);
|
||||
DECLARE_EXCEPTION_STUB(195);
|
||||
DECLARE_EXCEPTION_STUB(196);
|
||||
DECLARE_EXCEPTION_STUB(197);
|
||||
DECLARE_EXCEPTION_STUB(198);
|
||||
DECLARE_EXCEPTION_STUB(199);
|
||||
DECLARE_EXCEPTION_STUB(200);
|
||||
DECLARE_EXCEPTION_STUB(201);
|
||||
DECLARE_EXCEPTION_STUB(202);
|
||||
DECLARE_EXCEPTION_STUB(203);
|
||||
DECLARE_EXCEPTION_STUB(204);
|
||||
DECLARE_EXCEPTION_STUB(205);
|
||||
DECLARE_EXCEPTION_STUB(206);
|
||||
DECLARE_EXCEPTION_STUB(207);
|
||||
DECLARE_EXCEPTION_STUB(208);
|
||||
DECLARE_EXCEPTION_STUB(209);
|
||||
DECLARE_EXCEPTION_STUB(210);
|
||||
DECLARE_EXCEPTION_STUB(211);
|
||||
DECLARE_EXCEPTION_STUB(212);
|
||||
DECLARE_EXCEPTION_STUB(213);
|
||||
DECLARE_EXCEPTION_STUB(214);
|
||||
DECLARE_EXCEPTION_STUB(215);
|
||||
DECLARE_EXCEPTION_STUB(216);
|
||||
DECLARE_EXCEPTION_STUB(217);
|
||||
DECLARE_EXCEPTION_STUB(218);
|
||||
DECLARE_EXCEPTION_STUB(219);
|
||||
DECLARE_EXCEPTION_STUB(220);
|
||||
DECLARE_EXCEPTION_STUB(221);
|
||||
DECLARE_EXCEPTION_STUB(222);
|
||||
DECLARE_EXCEPTION_STUB(223);
|
||||
DECLARE_EXCEPTION_STUB(224);
|
||||
DECLARE_EXCEPTION_STUB(225);
|
||||
DECLARE_EXCEPTION_STUB(226);
|
||||
DECLARE_EXCEPTION_STUB(227);
|
||||
DECLARE_EXCEPTION_STUB(228);
|
||||
DECLARE_EXCEPTION_STUB(229);
|
||||
DECLARE_EXCEPTION_STUB(230);
|
||||
DECLARE_EXCEPTION_STUB(231);
|
||||
DECLARE_EXCEPTION_STUB(232);
|
||||
DECLARE_EXCEPTION_STUB(233);
|
||||
DECLARE_EXCEPTION_STUB(234);
|
||||
DECLARE_EXCEPTION_STUB(235);
|
||||
DECLARE_EXCEPTION_STUB(236);
|
||||
DECLARE_EXCEPTION_STUB(237);
|
||||
DECLARE_EXCEPTION_STUB(238);
|
||||
DECLARE_EXCEPTION_STUB(239);
|
||||
DECLARE_EXCEPTION_STUB(240);
|
||||
DECLARE_EXCEPTION_STUB(241);
|
||||
DECLARE_EXCEPTION_STUB(242);
|
||||
DECLARE_EXCEPTION_STUB(243);
|
||||
DECLARE_EXCEPTION_STUB(244);
|
||||
DECLARE_EXCEPTION_STUB(245);
|
||||
DECLARE_EXCEPTION_STUB(246);
|
||||
DECLARE_EXCEPTION_STUB(247);
|
||||
DECLARE_EXCEPTION_STUB(248);
|
||||
DECLARE_EXCEPTION_STUB(249);
|
||||
DECLARE_EXCEPTION_STUB(250);
|
||||
DECLARE_EXCEPTION_STUB(251);
|
||||
DECLARE_EXCEPTION_STUB(252);
|
||||
DECLARE_EXCEPTION_STUB(253);
|
||||
DECLARE_EXCEPTION_STUB(254);
|
||||
DECLARE_EXCEPTION_STUB(255);
|
||||
#undef DESC
|
||||
#undef DECLARE_EXCEPTION_STUB
|
||||
}
|
||||
|
||||
@@ -8,29 +8,17 @@
|
||||
#include "interrupts.h"
|
||||
#include "types.h"
|
||||
#include "kernel_state.h"
|
||||
#include "pic.h"
|
||||
|
||||
// Future user-space
|
||||
#include "libc.h"
|
||||
#include "tty.h"
|
||||
#include "str.h"
|
||||
|
||||
static void pic_disable()
|
||||
{
|
||||
__asm__ volatile ("outb %0, %1"
|
||||
:
|
||||
: "a"((uint8_t)0xff), "Nd"((uint16_t)0x21)
|
||||
: "memory");
|
||||
__asm__ volatile ("outb %0, %1"
|
||||
:
|
||||
: "a"((uint8_t)0xff), "Nd"((uint16_t)0xA1)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static void user_mode_code(void*)
|
||||
{
|
||||
printf(str_attach("hello from user-space before interrupt :)\n"));
|
||||
__asm__ volatile ("int $0x80");
|
||||
__asm__ volatile ("int $0x81");
|
||||
//__asm__ volatile ("int $0x80");
|
||||
//while (1) /* busy loop */;
|
||||
|
||||
#if 0
|
||||
@@ -82,8 +70,9 @@ void kernel_main(void)
|
||||
{
|
||||
__asm__ volatile("cli");
|
||||
|
||||
_Static_assert(sizeof(kernel.gdt) == 0x30);
|
||||
|
||||
/* Set up the GDT
|
||||
* ============== */
|
||||
kernel.gdt[SEGMENT_NULL] = gdt_encode_entry((struct gdt_entry_content){0});
|
||||
|
||||
/* kernel */
|
||||
@@ -140,86 +129,80 @@ void kernel_main(void)
|
||||
| GDT_ACCESS_PRESENT,
|
||||
.flags = 0});
|
||||
|
||||
/* Setup the TSS */
|
||||
memset(&kernel.tss, 0, sizeof kernel.tss);
|
||||
kernel.tss.ss0 = segment(SEGMENT_KERNEL_DATA, SEGMENT_GDT, 0);
|
||||
#if 1
|
||||
static uint8_t kernel_stack[1024];
|
||||
kernel.tss.esp0 = (uint32_t)kernel_stack;
|
||||
#else
|
||||
kernel.tss.esp0 = 0;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/* Setup the IDT */
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
kernel.idt[i] = idt_encode_descriptor(
|
||||
exception_default,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_TRAP32);
|
||||
}
|
||||
for (size_t i = 32; i < IDT_COUNT; i++) {
|
||||
kernel.idt[i] = idt_encode_descriptor(
|
||||
interrupt_default,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_INTERRUPT32);
|
||||
}
|
||||
|
||||
kernel.idt[0x0] = idt_encode_descriptor(
|
||||
exception_handler_div_by_zero,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_TRAP32
|
||||
);
|
||||
|
||||
kernel.idt[0x8] = idt_encode_descriptor(
|
||||
exception_handler_double_fault,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_TRAP32
|
||||
);
|
||||
|
||||
kernel.idt[0xD] = idt_encode_descriptor(
|
||||
exception_handler_general_protection_fault,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_TRAP32
|
||||
);
|
||||
|
||||
// Interrupts
|
||||
kernel.idt[0x80] = idt_encode_descriptor(
|
||||
interrupt_handler_1,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_INTERRUPT32
|
||||
);
|
||||
|
||||
kernel.idt[0x81] = idt_encode_descriptor(
|
||||
interrupt_handler_userspace_exit,
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0),
|
||||
IDT_DPL_3,
|
||||
IDT_GATE_TYPE_INTERRUPT32
|
||||
);
|
||||
#endif
|
||||
|
||||
/* Flush the gdt and tss */
|
||||
gdt_load(kernel.gdt,
|
||||
sizeof kernel.gdt,
|
||||
segment(SEGMENT_KERNEL_DATA, SEGMENT_GDT, 0),
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0));
|
||||
|
||||
/*
|
||||
* Setup the TSS
|
||||
* ============= */
|
||||
static uint8_t kernel_stack[KERNEL_STACK_SIZE];
|
||||
kernel.tss.ss0 = segment(SEGMENT_KERNEL_DATA, SEGMENT_GDT, 0);
|
||||
kernel.tss.esp0 = (uint32_t)kernel_stack;
|
||||
tss_load(segment(SEGMENT_TASK_STATE, SEGMENT_GDT, 0));
|
||||
|
||||
/**
|
||||
* Setup the IDT
|
||||
* ============= */
|
||||
#define m_idt_default(func, type) \
|
||||
idt_encode_descriptor( \
|
||||
func, \
|
||||
segment(SEGMENT_KERNEL_CODE, SEGMENT_GDT, 0), \
|
||||
IDT_DPL_3, \
|
||||
type)
|
||||
|
||||
#define mtrap(func) m_idt_default(func, IDT_GATE_TYPE_TRAP32);
|
||||
#define mint(func) m_idt_default(func, IDT_GATE_TYPE_INTERRUPT32);
|
||||
|
||||
idt_init_stubs(kernel.idt);
|
||||
|
||||
/* Exceptions */
|
||||
kernel.idt[IDT_DESC_EXCEPTION_DIVISION_ERROR] = mtrap(exception_handler_div_by_zero);
|
||||
kernel.idt[IDT_DESC_EXCEPTION_DOUBLE_FAULT] = mtrap(exception_handler_double_fault);
|
||||
kernel.idt[IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT] = mtrap(exception_handler_general_protection_fault);
|
||||
|
||||
/* IRQs */
|
||||
kernel.idt[IDT_DESC_PIC1 + 0] = mint(irq_handler_0);
|
||||
kernel.idt[IDT_DESC_PIC1 + 1] = mint(irq_handler_1);
|
||||
kernel.idt[IDT_DESC_PIC1 + 2] = mint(irq_handler_2);
|
||||
kernel.idt[IDT_DESC_PIC1 + 3] = mint(irq_handler_3);
|
||||
kernel.idt[IDT_DESC_PIC1 + 4] = mint(irq_handler_4);
|
||||
kernel.idt[IDT_DESC_PIC1 + 5] = mint(irq_handler_5);
|
||||
kernel.idt[IDT_DESC_PIC1 + 6] = mint(irq_handler_6);
|
||||
kernel.idt[IDT_DESC_PIC1 + 7] = mint(irq_handler_7);
|
||||
|
||||
kernel.idt[IDT_DESC_PIC2 + 0] = mint(irq_handler_8);
|
||||
kernel.idt[IDT_DESC_PIC2 + 1] = mint(irq_handler_9);
|
||||
kernel.idt[IDT_DESC_PIC2 + 2] = mint(irq_handler_10);
|
||||
kernel.idt[IDT_DESC_PIC2 + 3] = mint(irq_handler_11);
|
||||
kernel.idt[IDT_DESC_PIC2 + 4] = mint(irq_handler_12);
|
||||
kernel.idt[IDT_DESC_PIC2 + 5] = mint(irq_handler_13);
|
||||
kernel.idt[IDT_DESC_PIC2 + 6] = mint(irq_handler_14);
|
||||
kernel.idt[IDT_DESC_PIC2 + 7] = mint(irq_handler_15);
|
||||
|
||||
/* Interrupts */
|
||||
kernel.idt[IDT_DESC_INTERRUPT_SYSCALL] = mint(interrupt_handler_1);
|
||||
#undef mtrap
|
||||
#undef mint
|
||||
#undef m_idt_default
|
||||
|
||||
idt_load(kernel.idt, sizeof kernel.idt);
|
||||
|
||||
/**
|
||||
* PIC setup
|
||||
* =========
|
||||
*/
|
||||
|
||||
//irq_set_mask(0xff); /* Disable all IRQs */
|
||||
pic8259_remap(IDT_DESC_PIC1, IDT_DESC_PIC2);
|
||||
|
||||
/* enable interrupts */
|
||||
__asm__ volatile("sti");
|
||||
|
||||
/* Finally go to ring 3 */
|
||||
printf(str_attach("hello from kernel space!\n"));
|
||||
|
||||
pic_disable(); // temporary duct-tape
|
||||
|
||||
/* Finally go to ring 3 */
|
||||
ring3_mode(segment(SEGMENT_USER_DATA, SEGMENT_GDT, 3),
|
||||
segment(SEGMENT_USER_CODE, SEGMENT_GDT, 3),
|
||||
user_mode_code);
|
||||
|
||||
@@ -12,7 +12,34 @@ const struct str gdt_segment_index_str[SEGMENT_COUNT] = {
|
||||
[SEGMENT_TASK_STATE ] = str_attach("SEGMENT_TASK_STATE"),
|
||||
};
|
||||
|
||||
const struct str idt_index_str[IDT_COUNT] = {
|
||||
const struct str idt_desc_index_str[IDT_DESC_COUNT] = {
|
||||
[IDT_DESC_EXCEPTION_DIVISION_ERROR ] = str_attach("IDT_DESC_EXCEPTION_DIVISION_ERROR"),
|
||||
[IDT_DESC_EXCEPTION_DEBUG ] = str_attach("IDT_DESC_EXCEPTION_DEBUG"),
|
||||
[IDT_DESC_EXCEPTION_NON_MASKABLE ] = str_attach("IDT_DESC_EXCEPTION_NON_MASKABLE"),
|
||||
[IDT_DESC_EXCEPTION_BREAKPOINT ] = str_attach("IDT_DESC_EXCEPTION_BREAKPOINT"),
|
||||
[IDT_DESC_EXCEPTION_OVERFLOW ] = str_attach("IDT_DESC_EXCEPTION_OVERFLOW"),
|
||||
[IDT_DESC_EXCEPTION_BOUND_RANGE_EXCEEDED ] = str_attach("IDT_DESC_EXCEPTION_BOUND_RANGE_EXCEEDED"),
|
||||
[IDT_DESC_EXCEPTION_INVALID_OPCODE ] = str_attach("IDT_DESC_EXCEPTION_INVALID_OPCODE"),
|
||||
[IDT_DESC_EXCEPTION_DEVICE_NOT_AVAILABLE ] = str_attach("IDT_DESC_EXCEPTION_DEVICE_NOT_AVAILABLE"),
|
||||
[IDT_DESC_EXCEPTION_DOUBLE_FAULT ] = str_attach("IDT_DESC_EXCEPTION_DOUBLE_FAULT"),
|
||||
[IDT_DESC_EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN] = str_attach("IDT_DESC_EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN"),
|
||||
[IDT_DESC_EXCEPTION_INVALID_TSS ] = str_attach("IDT_DESC_EXCEPTION_INVALID_TSS"),
|
||||
[IDT_DESC_EXCEPTION_SEGMENT_NOT_PRESENT ] = str_attach("IDT_DESC_EXCEPTION_SEGMENT_NOT_PRESENT"),
|
||||
[IDT_DESC_EXCEPTION_STACK_SEGMENTATION_FAULT ] = str_attach("IDT_DESC_EXCEPTION_STACK_SEGMENTATION_FAULT"),
|
||||
[IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT ] = str_attach("IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT"),
|
||||
[IDT_DESC_EXCEPTION_PAGE_FAULT ] = str_attach("IDT_DESC_EXCEPTION_PAGE_FAULT"),
|
||||
[IDT_DESC_EXCEPTION_X87_FLOATING_POINT ] = str_attach("IDT_DESC_EXCEPTION_X87_FLOATING_POINT"),
|
||||
[IDT_DESC_EXCEPTION_ALIGNMENT_CHECK ] = str_attach("IDT_DESC_EXCEPTION_ALIGNMENT_CHECK"),
|
||||
[IDT_DESC_EXCEPTION_MACHINE_CHECK ] = str_attach("IDT_DESC_EXCEPTION_MACHINE_CHECK"),
|
||||
[IDT_DESC_EXCEPTION_SIMD_FLOATING_POINT ] = str_attach("IDT_DESC_EXCEPTION_SIMD_FLOATING_POINT"),
|
||||
[IDT_DESC_EXCEPTION_VIRTUALIZATION ] = str_attach("IDT_DESC_EXCEPTION_VIRTUALIZATION"),
|
||||
[IDT_DESC_EXCEPTION_CONTROL_PROTECTION ] = str_attach("IDT_DESC_EXCEPTION_CONTROL_PROTECTION"),
|
||||
[IDT_DESC_EXCEPTION_HYPERVISOR_INJECTION ] = str_attach("IDT_DESC_EXCEPTION_HYPERVISOR_INJECTION"),
|
||||
[IDT_DESC_EXCEPTION_VMM_COMMUNICATION ] = str_attach("IDT_DESC_EXCEPTION_VMM_COMMUNICATION"),
|
||||
[IDT_DESC_EXCEPTION_SECURITY ] = str_attach("IDT_DESC_EXCEPTION_SECURITY"),
|
||||
[IDT_DESC_PIC1 ] = str_attach("IDT_DESC_IRQ_MASTER"),
|
||||
[IDT_DESC_PIC2 ] = str_attach("IDT_DESC_IRQ_SLAVE"),
|
||||
[IDT_DESC_INTERRUPT_SYSCALL ] = str_attach("IDT_DESC_INTERRUPT_SYSCALL"),
|
||||
};
|
||||
|
||||
struct kernel_state kernel = { 0 };
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "idt.h"
|
||||
#include "gdt.h"
|
||||
|
||||
/*
|
||||
* Constants for the GDT
|
||||
* */
|
||||
enum gdt_segment_index : size_t {
|
||||
SEGMENT_NULL,
|
||||
SEGMENT_KERNEL_CODE,
|
||||
@@ -17,18 +20,65 @@ enum gdt_segment_index : size_t {
|
||||
};
|
||||
extern const struct str gdt_segment_index_str[SEGMENT_COUNT]; // reverse lookup enum -> str
|
||||
|
||||
enum idt_index : size_t {
|
||||
IDT_COUNT = 256
|
||||
/**
|
||||
* Constants for the TSS
|
||||
*/
|
||||
constexpr size_t KERNEL_STACK_SIZE = 1024;
|
||||
|
||||
/*
|
||||
* Constants for IDT descriptors
|
||||
* */
|
||||
static constexpr size_t IDT_EXCEPTION_COUNT = 32;
|
||||
static constexpr size_t IDT_IRQ_MASTER_COUNT = 8;
|
||||
static constexpr size_t IDT_IRQ_SLAVE_COUNT = 8;
|
||||
|
||||
enum idt_desc_index : size_t {
|
||||
/* Exceptions */
|
||||
IDT_DESC_EXCEPTION_DIVISION_ERROR = 0,
|
||||
IDT_DESC_EXCEPTION_DEBUG = 1,
|
||||
IDT_DESC_EXCEPTION_NON_MASKABLE = 2,
|
||||
IDT_DESC_EXCEPTION_BREAKPOINT = 3,
|
||||
IDT_DESC_EXCEPTION_OVERFLOW = 4,
|
||||
IDT_DESC_EXCEPTION_BOUND_RANGE_EXCEEDED = 5,
|
||||
IDT_DESC_EXCEPTION_INVALID_OPCODE = 6,
|
||||
IDT_DESC_EXCEPTION_DEVICE_NOT_AVAILABLE = 7,
|
||||
IDT_DESC_EXCEPTION_DOUBLE_FAULT = 8,
|
||||
IDT_DESC_EXCEPTION_COPROCESSOR_SEGMENT_OVERRUN = 9,
|
||||
IDT_DESC_EXCEPTION_INVALID_TSS = 10,
|
||||
IDT_DESC_EXCEPTION_SEGMENT_NOT_PRESENT = 11,
|
||||
IDT_DESC_EXCEPTION_STACK_SEGMENTATION_FAULT = 12,
|
||||
IDT_DESC_EXCEPTION_GENERAL_PROTECTION_FAULT = 13,
|
||||
IDT_DESC_EXCEPTION_PAGE_FAULT = 14,
|
||||
/* 15 is reserved */
|
||||
IDT_DESC_EXCEPTION_X87_FLOATING_POINT = 16,
|
||||
IDT_DESC_EXCEPTION_ALIGNMENT_CHECK = 17,
|
||||
IDT_DESC_EXCEPTION_MACHINE_CHECK = 18,
|
||||
IDT_DESC_EXCEPTION_SIMD_FLOATING_POINT = 19,
|
||||
IDT_DESC_EXCEPTION_VIRTUALIZATION = 20,
|
||||
IDT_DESC_EXCEPTION_CONTROL_PROTECTION = 21,
|
||||
/* 21 to 27 are reserved */
|
||||
IDT_DESC_EXCEPTION_HYPERVISOR_INJECTION = 28,
|
||||
IDT_DESC_EXCEPTION_VMM_COMMUNICATION = 29,
|
||||
IDT_DESC_EXCEPTION_SECURITY = 30,
|
||||
/* 31 is reserved */
|
||||
|
||||
/* IRQ offsets */
|
||||
IDT_DESC_PIC1 = 32,
|
||||
IDT_DESC_PIC2 = IDT_DESC_PIC1 + 8,
|
||||
|
||||
IDT_DESC_INTERRUPT_SYSCALL = 128,
|
||||
|
||||
IDT_DESC_COUNT = 256,
|
||||
};
|
||||
extern const struct str idt_index_str[IDT_COUNT]; // reverse lookup enum -> str
|
||||
|
||||
constexpr size_t BACKTRACE_MAX = 256;
|
||||
extern const struct str idt_desc_index_str[IDT_DESC_COUNT]; // reverse lookup enum -> str
|
||||
|
||||
/**
|
||||
* The global kernel state object
|
||||
*/
|
||||
struct kernel_state {
|
||||
struct tss tss;
|
||||
struct gdt_table_entry gdt[SEGMENT_COUNT];
|
||||
struct idt_gate_descriptor idt[IDT_COUNT];
|
||||
struct idt_gate_descriptor idt[IDT_DESC_COUNT];
|
||||
int nested_exception_counter;
|
||||
};
|
||||
|
||||
extern struct kernel_state kernel;
|
||||
|
||||
91
src/kernel/pic.c
Normal file
91
src/kernel/pic.c
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
#include "pic.h"
|
||||
|
||||
void pic8259_remap(int offset1, int offset2)
|
||||
{
|
||||
/* ICW1: restart PIC1 and PIC2 with
|
||||
- icw4
|
||||
- cascade
|
||||
- 8 bit interval
|
||||
- edge triggered mode
|
||||
*/
|
||||
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||
|
||||
/* ICW2: Send new offsets */
|
||||
outb(PIC1_DATA, offset1);
|
||||
outb(PIC2_DATA, offset2);
|
||||
|
||||
/* ICW2 and ICW3: Setup cascading */
|
||||
outb(PIC1_DATA, 1<<2); /* tell master PIC that IR input 2 has a slave */
|
||||
outb(PIC2_DATA, 2); /* set ID of slave PIC */
|
||||
|
||||
/* ICW4: 8086/88 mode */
|
||||
outb(PIC1_DATA, ICW4_8086);
|
||||
outb(PIC2_DATA, ICW4_8086);
|
||||
}
|
||||
|
||||
static inline void irq_set(enum pic8259_port port, uint8_t mask)
|
||||
{
|
||||
outb(port, inb(port) | mask);
|
||||
}
|
||||
|
||||
static inline void irq_clear(enum pic8259_port port, uint8_t mask)
|
||||
{
|
||||
outb(port, inb(port) & ~(mask));
|
||||
}
|
||||
|
||||
void pic8259_set_irq_mask(uint16_t mask)
|
||||
{
|
||||
const uint8_t pic1_mask = mask & 0xF;
|
||||
mask >>= 8;
|
||||
const uint8_t pic2_mask = mask & 0xF;
|
||||
|
||||
if (pic1_mask) {
|
||||
irq_set(PIC1_DATA, pic1_mask);
|
||||
}
|
||||
if (pic2_mask) {
|
||||
irq_set(PIC2_DATA, pic2_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void pic8259_clear_irq_mask(uint16_t mask)
|
||||
{
|
||||
const uint8_t pic1_mask = mask & 0xF;
|
||||
mask >>= 8;
|
||||
const uint8_t pic2_mask = mask & 0xF;
|
||||
|
||||
if (pic1_mask) {
|
||||
irq_clear(PIC1_DATA, pic1_mask);
|
||||
}
|
||||
if (pic2_mask) {
|
||||
irq_clear(PIC2_DATA, pic2_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* https://wiki.osdev.org/8259_PIC#ISR_and_IRR
|
||||
* ===========================================
|
||||
* */
|
||||
static uint16_t get_irq_reg(int ocw3)
|
||||
{
|
||||
/* OCW3 to PIC CMD to get the register values. PIC2 is chained, and
|
||||
represents IRQs 8-15. PIC1 is IRQs 0-7, with 2 being the chain */
|
||||
outb(PIC1_COMMAND, ocw3);
|
||||
outb(PIC2_COMMAND, ocw3);
|
||||
return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
|
||||
}
|
||||
|
||||
/* Returns the combined value of the cascaded PICs irq request register */
|
||||
uint16_t pic8259_get_irr(void)
|
||||
{
|
||||
return get_irq_reg(OCW3_READ_IRR);
|
||||
}
|
||||
|
||||
/* Returns the combined value of the cascaded PICs in-service register */
|
||||
uint16_t pic8259_get_isr(void)
|
||||
{
|
||||
return get_irq_reg(OCW3_READ_ISR);
|
||||
}
|
||||
|
||||
/* =========================================== */
|
||||
171
src/kernel/pic.h
Normal file
171
src/kernel/pic.h
Normal file
@@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "str.h"
|
||||
|
||||
enum pic8259_port : uint16_t {
|
||||
PIC1_COMMAND = 0x20,
|
||||
PIC1_DATA = 0x21,
|
||||
|
||||
PIC2_COMMAND = 0xA0,
|
||||
PIC2_DATA = 0xA1,
|
||||
|
||||
PIC_KEYBOARD = 0x60,
|
||||
};
|
||||
|
||||
static const struct str pic8259_port_str[] = {
|
||||
[PIC1_COMMAND ] = str_attach("PIC1_COMMAND"),
|
||||
[PIC1_DATA ] = str_attach("PIC1_DATA"),
|
||||
[PIC2_COMMAND ] = str_attach("PIC2_COMMAND"),
|
||||
[PIC2_DATA ] = str_attach("PIC2_DATA"),
|
||||
};
|
||||
|
||||
|
||||
enum irq : uint16_t {
|
||||
IRQ_SYSTEM_TIMER = 0,
|
||||
IRQ_KEYBOARD_CONTROLLER = 1,
|
||||
IRQ_SERIAL_COM2 = 3,
|
||||
IRQ_SERIAL_COM1 = 4,
|
||||
IRQ_LINE_PRINT_TERMINAL_2 = 5,
|
||||
IRQ_FLOPPY_CONTROLLER = 6,
|
||||
IRQ_LINE_PRINT_TERMINAL_1 = 7,
|
||||
IRQ_RTC_TIMER = 8,
|
||||
IRQ_ACPI = 9,
|
||||
IRQ_MOUSE_CONTROLLER = 12,
|
||||
IRQ_MATH_COPROCESSOR = 13,
|
||||
IRQ_ATA_CHANNEL_1 = 14,
|
||||
IRQ_ATA_CHANNEL_2 = 15,
|
||||
};
|
||||
|
||||
static const struct str irq_str[] = {
|
||||
[IRQ_SYSTEM_TIMER ] = str_attach("IRQ_SYSTEM_TIMER"),
|
||||
[IRQ_KEYBOARD_CONTROLLER ] = str_attach("IRQ_KEYBOARD_CONTROLLER"),
|
||||
[IRQ_SERIAL_COM2 ] = str_attach("IRQ_SERIAL_COM2"),
|
||||
[IRQ_SERIAL_COM1 ] = str_attach("IRQ_SERIAL_COM1"),
|
||||
[IRQ_LINE_PRINT_TERMINAL_2] = str_attach("IRQ_LINE_PRINT_TERMINAL_2"),
|
||||
[IRQ_FLOPPY_CONTROLLER ] = str_attach("IRQ_FLOPPY_CONTROLLER"),
|
||||
[IRQ_LINE_PRINT_TERMINAL_1] = str_attach("IRQ_LINE_PRINT_TERMINAL_1"),
|
||||
[IRQ_RTC_TIMER ] = str_attach("IRQ_RTC_TIMER"),
|
||||
[IRQ_ACPI ] = str_attach("IRQ_ACPI"),
|
||||
[IRQ_MOUSE_CONTROLLER ] = str_attach("IRQ_MOUSE_CONTROLLER"),
|
||||
[IRQ_MATH_COPROCESSOR ] = str_attach("IRQ_MATH_COPROCESSOR"),
|
||||
[IRQ_ATA_CHANNEL_1 ] = str_attach("IRQ_ATA_CHANNEL_1"),
|
||||
[IRQ_ATA_CHANNEL_2 ] = str_attach("IRQ_ATA_CHANNEL_2"),
|
||||
};
|
||||
|
||||
/**
|
||||
Initialization Command Words
|
||||
=======================
|
||||
From the Intel manuals:
|
||||
https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf
|
||||
https://web.archive.org/web/20240606163819/https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf
|
||||
|
||||
> Whenever a command is issued with A0 = 0 and D4 = 1, this is interpreted
|
||||
> as Initialization Command Word 1 (ICW1) CW1 starts the intiitalization
|
||||
> sequence during which the following automatically occur:
|
||||
> a. The edge sense circuit is reset, which means that following
|
||||
> initialization, an interrupt request (IR) input must make a
|
||||
> low-to-high transistion to generate an interrupt.
|
||||
> b. The Interrupt Mask Register is cleared.
|
||||
> c. IR7 input is assigned priority 7.
|
||||
> d. The slave mode address is set to 7.
|
||||
> e. Special Mask Mode is cleared and Status Read is set to IRR
|
||||
> f. If IC4 = 0, then all functions selected in ICW4 are set to zero.
|
||||
> (Non-Buffered mode*, no Auto-EOI, MCS-80, 85 system).
|
||||
> [*]: Master/Slave in ICW4 is only used in the buffered mode
|
||||
*/
|
||||
enum icw1 : uint8_t {
|
||||
ICW1_ICW4 = 1<<0, /* 1: ICW4 Needed
|
||||
0: ICW4 Not needed */
|
||||
|
||||
ICW1_SINGLE = 1<<1, /* 1: Single
|
||||
0: Cascade mode */
|
||||
|
||||
ICW1_INTERVAL4 = 1<<2, /* Call Address Interval:
|
||||
1: interval of 4
|
||||
0: interval of 8 */
|
||||
|
||||
ICW1_LEVEL = 1<<3, /* 1: Level triggered mode
|
||||
0: Edge triggered mode */
|
||||
|
||||
ICW1_INIT = 1<<4, /* Must be present */
|
||||
};
|
||||
|
||||
enum icw4 : uint8_t {
|
||||
ICW4_8086 = 1<<0, /* 1: 8086/88 mode
|
||||
0: MCS-80/85 mode */
|
||||
|
||||
ICW4_AUTO = 1<<1, /* 1: Auto EOI
|
||||
0: Normal EOI */
|
||||
|
||||
ICW4_BUF1 = 0b11<<2, /* Buffered mode master */
|
||||
|
||||
ICW4_BUF2 = 0b10<<2, /* Buffered mode slave */
|
||||
|
||||
ICW4_SFNM = 1<<4, /* 1: Special fully nested mode
|
||||
0: Not special fully nested mode */
|
||||
};
|
||||
|
||||
/* OCW2 */
|
||||
enum ocw2_command : uint8_t {
|
||||
OCW2_EOI = 1<<5,
|
||||
OCW2_SPECIFIC = 1<<6,
|
||||
OCW2_ROTATE = 1<<7,
|
||||
|
||||
/* Determines the interrupt level acted upon when the specific flag is set */
|
||||
OCW2_IR_LEVEL_0 = 0,
|
||||
OCW2_IR_LEVEL_1 = 1,
|
||||
OCW2_IR_LEVEL_2 = 2,
|
||||
OCW2_IR_LEVEL_3 = 3,
|
||||
OCW2_IR_LEVEL_4 = 4,
|
||||
OCW2_IR_LEVEL_5 = 5,
|
||||
OCW2_IR_LEVEL_6 = 6,
|
||||
OCW2_IR_LEVEL_7 = 7,
|
||||
};
|
||||
|
||||
/* OCW3 */
|
||||
enum ocw3_bits : uint8_t {
|
||||
OCW3_BIT_RIS = (1<<0),
|
||||
OCW3_BIT_RR = (1<<1),
|
||||
OCW3_BIT_P = (1<<2),
|
||||
/* bit 3 and 4 must be 0b01 for OCW3 to be selected */
|
||||
OCW3_BIT_SMM = (1<<5),
|
||||
OCW3_BIT_ESMM = (1<<6),
|
||||
};
|
||||
|
||||
enum ocw3_command : uint8_t {
|
||||
OCW3_READ_ISR = (1<<3) | OCW3_BIT_RR | OCW3_BIT_RIS,
|
||||
OCW3_READ_IRR = (1<<3) | OCW3_BIT_RR,
|
||||
OCW3_POLL = (1<<3) | OCW3_BIT_P,
|
||||
OCW3_RESET_SPECIAL_MASK = (1<<3) | OCW3_BIT_SMM,
|
||||
OCW3_SET_SPECIAL_MASK = (1<<3) | OCW3_BIT_ESMM | OCW3_BIT_SMM,
|
||||
};
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t signal)
|
||||
{
|
||||
__asm__ volatile ("outb %[signal], %[port]"
|
||||
:
|
||||
: [signal] "a" (signal),
|
||||
[port] "Nd" (port)
|
||||
: "memory");
|
||||
#ifdef ADD_IO_WAIT
|
||||
/* do an I/O operation on an unused port to wait 1-4 microseconds */
|
||||
outb(0x80, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t ret;
|
||||
__asm__ volatile ( "inb %w1, %b0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(port)
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pic8259_remap(int offset1, int offset2);
|
||||
|
||||
void pic8259_set_irq_mask(uint16_t mask);
|
||||
|
||||
void pic8259_clear_irq_mask(uint16_t mask);
|
||||
@@ -77,7 +77,7 @@ static int print_i32(struct printf_state* s, int padding, char pad_char)
|
||||
{
|
||||
padding = padding ? padding : 0;
|
||||
pad_char = pad_char ? pad_char : ' ';
|
||||
long n = va_arg(s->ap, int32_t);
|
||||
uint32_t n = va_arg(s->ap, int32_t);
|
||||
return print_long(n, str_attach("0123456789"), true, padding, pad_char);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ static int print_u32(struct printf_state* s, int padding, char pad_char)
|
||||
{
|
||||
padding = padding ? padding : 0;
|
||||
pad_char = pad_char ? pad_char : ' ';
|
||||
unsigned long n = va_arg(s->ap, uint32_t);
|
||||
uint32_t n = va_arg(s->ap, uint32_t);
|
||||
return print_long(n, str_attach("0123456789"), false, padding, pad_char);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ static int print_x32(struct printf_state* s, int padding, char pad_char)
|
||||
{
|
||||
padding = padding ? padding : 0;
|
||||
pad_char = pad_char ? pad_char : '0';
|
||||
unsigned long n = va_arg(s->ap, uint32_t);
|
||||
uint32_t n = va_arg(s->ap, uint32_t);
|
||||
struct str alphabet = str_attach("0123456789abcdef");
|
||||
return print_long(n, alphabet, false, padding, pad_char);
|
||||
}
|
||||
@@ -102,7 +102,7 @@ static int print_b32(struct printf_state* s, int padding, char pad_char)
|
||||
{
|
||||
padding = padding ? padding : 32;
|
||||
pad_char = pad_char ? pad_char : '0';
|
||||
unsigned long n = va_arg(s->ap, uint32_t);
|
||||
uint32_t n = va_arg(s->ap, uint32_t);
|
||||
struct str alphabet = str_attach("01");
|
||||
return print_long(n, alphabet, false, padding, pad_char);
|
||||
}
|
||||
@@ -119,7 +119,19 @@ static int print_str(struct printf_state* s, int padding, char pad_char)
|
||||
return str.len;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmultichar"
|
||||
static int print_char(struct printf_state* s)
|
||||
{
|
||||
// char is promoted to int when passed through va_arg
|
||||
const int ch = va_arg(s->ap, int);
|
||||
|
||||
if (ch >= 32 && ch < 127) {
|
||||
terminal_putchar(ch);
|
||||
return 1;
|
||||
} else {
|
||||
return print_long(ch, str_attach("0123456789abcdef"), false, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_format_cmd(struct printf_state* s)
|
||||
{
|
||||
int c;
|
||||
@@ -137,16 +149,21 @@ static int parse_format_cmd(struct printf_state* s)
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmultichar"
|
||||
switch (cmd) {
|
||||
// 16 bit types are promoted to 32 bit by va_arg(...) anyways
|
||||
case 'int':
|
||||
case 'i16':
|
||||
case 'i32':
|
||||
return print_i32(s, pad, pad_char);
|
||||
|
||||
case 'uint':
|
||||
case 'u16':
|
||||
case 'u32':
|
||||
return print_u32(s, pad, pad_char);
|
||||
|
||||
case 'hex':
|
||||
case 'x16':
|
||||
case 'x32':
|
||||
return print_x32(s, pad, pad_char);
|
||||
@@ -154,9 +171,13 @@ static int parse_format_cmd(struct printf_state* s)
|
||||
case 'str':
|
||||
return print_str(s, pad, pad_char);
|
||||
|
||||
case 'char':
|
||||
return print_char(s);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
int printf(struct str format, ...)
|
||||
|
||||
35
src/lib/ring_buffer.c
Normal file
35
src/lib/ring_buffer.c
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
#include "ring_buffer.h"
|
||||
|
||||
size_t ring_buffer_remaining(struct ring_buffer* q)
|
||||
{
|
||||
return (RING_BUFFER_MAX - q->len) / q->entry_size;
|
||||
}
|
||||
|
||||
bool ring_buffer_push(struct ring_buffer* q, const void* data)
|
||||
{
|
||||
if (q->len + q->entry_size > RING_BUFFER_MAX) {
|
||||
return false;
|
||||
}
|
||||
q->len += q->entry_size;
|
||||
for (size_t i = 0; i < q->entry_size; i++) {
|
||||
q->data[q->tail] = ((uint8_t*)data)[i];
|
||||
q->tail += 1;
|
||||
q->tail %= RING_BUFFER_MAX;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ring_buffer_get(struct ring_buffer* q, void* out)
|
||||
{
|
||||
if (q->len == 0) {
|
||||
return false;
|
||||
}
|
||||
q->len -= q->entry_size;
|
||||
for (size_t i = 0; i < q->entry_size; i++) {
|
||||
((uint8_t*)out)[i] = q->data[q->head];
|
||||
q->head += 1;
|
||||
q->head %= RING_BUFFER_MAX;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
176
src/test/test_ring_buffer.c
Normal file
176
src/test/test_ring_buffer.c
Normal file
@@ -0,0 +1,176 @@
|
||||
|
||||
#include "ring_buffer.h"
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
struct myObj {
|
||||
int32_t a;
|
||||
int32_t b;
|
||||
};
|
||||
|
||||
static int g_status = EXIT_SUCCESS;
|
||||
static int test_no = 0;
|
||||
static bool test_ongoing = false;
|
||||
|
||||
#define test_begin(name) _test_begin(name, __LINE__)
|
||||
static void _test_begin(const char* name, int line)
|
||||
{
|
||||
(void)line; // unused for now
|
||||
assert(!test_ongoing);
|
||||
test_ongoing = true;
|
||||
printf("\n#%i - %s:\n", test_no, name);
|
||||
test_no += 1;
|
||||
}
|
||||
|
||||
static void test_ok(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
printf("OK: ");
|
||||
vprintf(format, ap);
|
||||
printf("\n");
|
||||
va_end(ap);
|
||||
test_ongoing = false;
|
||||
}
|
||||
|
||||
static void test_fail(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
printf("FAIL: ");
|
||||
vprintf(format, ap);
|
||||
printf("\n");
|
||||
va_end(ap);
|
||||
g_status = EXIT_FAILURE;
|
||||
test_ongoing = false;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct ring_buffer q = make_ring_buffer(struct myObj);
|
||||
|
||||
test_begin("entry_size");
|
||||
{
|
||||
if (q.entry_size != sizeof (struct myObj)) {
|
||||
test_fail("wrong entry_size");
|
||||
} else {
|
||||
test_ok("entry_size is %zu", q.entry_size);
|
||||
}
|
||||
}
|
||||
|
||||
test_begin("ring_buffer_remaining");
|
||||
size_t max_items = ring_buffer_remaining(&q); // used later
|
||||
{
|
||||
if (max_items != RING_BUFFER_MAX / sizeof(struct myObj)) {
|
||||
test_fail("unexpected ring_buffer_remaining()");
|
||||
} else {
|
||||
test_ok("ring_buffer_remaining() is %zu", max_items);
|
||||
}
|
||||
}
|
||||
|
||||
test_begin("ring_buffer_push");
|
||||
{
|
||||
bool ok = true;
|
||||
size_t remaining = ring_buffer_remaining(&q);
|
||||
for (size_t i = 0; i < remaining; i++) {
|
||||
if (ring_buffer_push(&q, &(struct myObj){i, i}) == false) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
test_fail("expected ring_buffer push to work");
|
||||
} else {
|
||||
test_ok("successfully pushed %zu times", remaining);
|
||||
}
|
||||
}
|
||||
|
||||
test_begin("ring_buffer_push on full ring buffer");
|
||||
{
|
||||
if (ring_buffer_push(&q, &(struct myObj){}) == true) {
|
||||
test_fail("ring buffer should be full by now, ring_buffer_remaining is %zu", ring_buffer_remaining(&q));
|
||||
} else {
|
||||
test_ok("correctly failed to push when ring buffer is full");
|
||||
}
|
||||
}
|
||||
|
||||
test_begin("ring_buffer_get");
|
||||
{
|
||||
for (size_t i = 0; i < max_items; i++) {
|
||||
struct myObj o;
|
||||
bool ok = ring_buffer_get(&q, &o);
|
||||
|
||||
if (!ok) {
|
||||
test_fail("ring_buffer_get() didn't fetch when buffer had data");
|
||||
goto end_test;
|
||||
}
|
||||
|
||||
if (o.a != (int32_t)i
|
||||
|| o.b != (int32_t)i
|
||||
){
|
||||
test_fail("ring_buffer_get() retrived faulty data {%i, %i}", o.a, o.b);
|
||||
goto end_test;
|
||||
}
|
||||
}
|
||||
test_ok("ring_buffer_get() works");
|
||||
|
||||
end_test:
|
||||
}
|
||||
|
||||
test_begin("ring_buffer_get on empty ring buffer");
|
||||
{
|
||||
struct myObj o;
|
||||
bool ok = ring_buffer_get(&q, &o);
|
||||
if (ok) {
|
||||
test_fail("ring_buffer_get() on empty ring buffer succeeded, got {%i, %i}", o.a, o.b);
|
||||
} else {
|
||||
test_ok("ring_buffer_get() on empty ring buffer didn't succeed");
|
||||
}
|
||||
}
|
||||
|
||||
test_begin("stress test");
|
||||
{
|
||||
struct ring_buffer rb = make_ring_buffer(struct myObj);
|
||||
bool fail = false;
|
||||
|
||||
for (volatile size_t i = 0; i < RING_BUFFER_MAX * 10; i++) {
|
||||
bool ok;
|
||||
struct myObj before = {i, i};
|
||||
struct myObj after = {-1, -1};
|
||||
|
||||
ok = ring_buffer_push(&rb, &before);
|
||||
if (!ok) {
|
||||
test_fail("failed to push during stress-test");
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ok = ring_buffer_get(&rb, &after);
|
||||
if (!ok) {
|
||||
test_fail("failed to get during stress-test");
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (before.a != after.a || before.b != after.b) {
|
||||
test_fail("data got damaged in queue");
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!fail) {
|
||||
test_ok("stress test succeeded");
|
||||
}
|
||||
}
|
||||
|
||||
if (g_status == EXIT_SUCCESS) {
|
||||
printf("\nAll tests succeeded\n");
|
||||
} else {
|
||||
printf("\nOne or more tests failed\n");
|
||||
}
|
||||
|
||||
return g_status;
|
||||
}
|
||||
Reference in New Issue
Block a user