#include #include #include #include using namespace hilbert::kernel; struct [[gnu::packed]] exception_info_t { uint64_t rax; uint64_t rbx; uint64_t rcx; uint64_t rdx; uint64_t rdi; uint64_t rsi; uint64_t rbp; uint64_t rsp; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t cr2; uint64_t cr3; uint64_t rip; uint64_t rflags; uint64_t error; uint8_t has_error;//0 or 1 uint8_t exception_number; }; extern exception_info_t exception_info; static inline void print_reg(const char *regname, uint64_t value) { serial_putstr(" "); serial_putstr(regname); serial_putstr(" = 0x"); serial_puthex<16>(value); serial_putchar('\n'); } extern "C" [[noreturn]] void print_exception() { //so exception_info's type is known by gdb exception_info_t the_exception_info = exception_info; (void)the_exception_info; serial_putstr("exception 0x"); serial_puthex<2>(exception_info.exception_number); serial_putchar('\n'); if (exception_info.has_error) print_reg("error code", exception_info.error); print_reg("rflags", exception_info.rflags); print_reg("rip", exception_info.rip); print_reg("cr2", exception_info.cr2); print_reg("cr3", exception_info.cr3); print_reg("rax", exception_info.rax); print_reg("rbx", exception_info.rbx); print_reg("rcx", exception_info.rcx); print_reg("rdx", exception_info.rdx); print_reg("rdi", exception_info.rdi); print_reg("rsi", exception_info.rsi); print_reg("rbp", exception_info.rbp); print_reg("rsp", exception_info.rsp); print_reg("r8 ", exception_info.r8 ); print_reg("r9 ", exception_info.r9 ); print_reg("r10", exception_info.r10); print_reg("r11", exception_info.r11); print_reg("r12", exception_info.r12); print_reg("r13", exception_info.r13); print_reg("r14", exception_info.r14); print_reg("r15", exception_info.r15); if (application::running_thread != 0) { serial_putstr("running app = "); serial_putstr(application::running_thread->owner->name); } panic(0xba40bb); } static uint32_t current_flags = 0; #define SETBIT(field, bit, cond) \ field = (cond) ? (field | (bit)) : (field & ~(bit)); static void got_key(uint32_t key) { input::input_queue->insert({ .keyboard = current_flags | key, .is_mouse = false}); input::notify_waiting(); if (key == (input::BREAK | 0x77)) current_flags ^= input::NUM_LOCK; else if (key == (input::BREAK | 0x58)) current_flags ^= input::CAPS_LOCK; else if ((key & 0xff) == 0xa7) SETBIT(current_flags, input::RIGHT_WIN, !(key & input::BREAK)) else if ((key & 0xff) == 0x9f) SETBIT(current_flags, input::LEFT_WIN, !(key & input::BREAK)) else if ((key & 0xff) == 0x91) SETBIT(current_flags, input::RIGHT_ALT, !(key & input::BREAK)) else if ((key & 0xff) == 0x11) SETBIT(current_flags, input::LEFT_ALT, !(key & input::BREAK)) else if ((key & 0xff) == 0x94) SETBIT(current_flags, input::RIGHT_CTRL, !(key & input::BREAK)) else if ((key & 0xff) == 0x14) SETBIT(current_flags, input::LEFT_CTRL, !(key & input::BREAK)) else if ((key & 0xff) == 0x59) SETBIT(current_flags, input::RIGHT_SHIFT, !(key & input::BREAK)) else if ((key & 0xff) == 0x12) SETBIT(current_flags, input::LEFT_SHIFT, !(key & input::BREAK)) } static uint8_t key_so_far[8]; static uint8_t key_so_far_len = 0; extern "C" void on_keyboard_interrupt(uint8_t byte) { key_so_far[key_so_far_len++] = byte; if (key_so_far_len == 1) { if (byte != 0xe0 && byte != 0xe1 && byte != 0xf0) { got_key(byte); key_so_far_len = 0; } } else if (key_so_far_len == 2) { if (key_so_far[0] == 0xe0 && byte != 0xf0 && byte != 0x12) { got_key(byte | 0x80); key_so_far_len = 0; } else if (key_so_far[0] == 0xf0) { got_key(input::BREAK | byte); key_so_far_len = 0; } } else if (key_so_far_len == 3) { if (key_so_far[0] == 0xe0 && key_so_far[1] == 0xf0 && byte != 0x7c) { got_key(input::BREAK | byte | 0x80); key_so_far_len = 0; } } else if (key_so_far_len == 4) { if (key_so_far[0] == 0xe0 && key_so_far[1] == 0x12 && key_so_far[2] == 0xe0 && byte == 0x7c) { got_key(0xe0); key_so_far_len = 0; } } else if (key_so_far_len == 6) { if (key_so_far[0] == 0xe0 && key_so_far[1] == 0xf0 && key_so_far[2] == 0x7c && key_so_far[3] == 0xe0 && key_so_far[4] == 0xf0 && byte == 0x12) { got_key(input::BREAK | 0xe0); key_so_far_len = 0; } } else if (key_so_far_len == 8) { if (key_so_far[0] == 0xe1 && key_so_far[1] == 0x14 && key_so_far[2] == 0x77 && key_so_far[3] == 0xe1 && key_so_far[2] == 0xf0 && key_so_far[3] == 0x14 && key_so_far[4] == 0xf0 && byte == 0x77) { got_key(0xe1); got_key(input::BREAK | 0xe1); } key_so_far_len = 0; } } static uint8_t mouse_packet_so_far[3]; static uint8_t mouse_packet_so_far_len = 0; extern "C" void on_mouse_interrupt(uint8_t byte) { if (mouse_packet_so_far_len == 0 && byte == 0xfa) //dirty hack return; mouse_packet_so_far[mouse_packet_so_far_len++] = byte; if (mouse_packet_so_far_len < 3) return; mouse_packet_so_far_len = 0; int16_t x_change = mouse_packet_so_far[1]; int16_t y_change = -(int16_t)mouse_packet_so_far[2]; if (mouse_packet_so_far[0] & 0x10) x_change -= 0x100; if (mouse_packet_so_far[0] & 0x20) y_change += 0x100; input::input_packet packet = { .mouse = { .x_change = x_change, .y_change = y_change, .buttons = (input::buttons_t)(mouse_packet_so_far[0] & 7) }, .is_mouse = true }; if (input::input_queue->count > 0 && input::input_queue->last_inserted().is_mouse && input::input_queue->last_inserted().mouse.buttons == packet.mouse.buttons) { input::input_queue->last_inserted().mouse.x_change += packet.mouse.x_change; input::input_queue->last_inserted().mouse.y_change += packet.mouse.y_change; } else input::input_queue->insert(packet); input::notify_waiting(); }