diff --git a/CMakeLists.txt b/CMakeLists.txt index b5fb3cc..81e40e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,10 @@ add_custom_target(run -drive file=os.img,format=raw -serial stdio -device isa-debug-exit,iobase=0xf4,iosize=0x04 + -netdev user,id=net0 + -device virtio-net-pci,netdev=net0 + -audiodev pa,id=speaker + -machine pcspk-audiodev=speaker -d int -D qemu.log DEPENDS os) diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 776b7f5..5d9468e 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -12,7 +12,11 @@ set(COMPILE_OPTIONS add_library(drivers OBJECT src/arch/x86_64/drivers/keyboard/keyboard.c - src/arch/x86_64/drivers/timer/timer.c + src/arch/x86_64/drivers/mouse/mouse.c + src/arch/x86_64/drivers/pci/pci.c + src/arch/x86_64/drivers/speaker/speaker.c + src/arch/x86_64/drivers/timer/apic.c + src/arch/x86_64/drivers/timer/pit.c src/arch/x86_64/klib/trap.c ) diff --git a/kernel/src/arch/x86_64/acpi/acpi.c b/kernel/src/arch/x86_64/acpi/acpi.c index 51e06a1..3b8343c 100644 --- a/kernel/src/arch/x86_64/acpi/acpi.c +++ b/kernel/src/arch/x86_64/acpi/acpi.c @@ -68,6 +68,16 @@ bool rsdt_map(void) { return verify_mapping(rsdt); } +static bool rsdt_entry_verify(void *entry) { + uint8_t sum = 0; + struct description_header *header = (struct description_header *) entry; + uint8_t *addr = (uint8_t *) entry; + for (size_t i = 0; i < header->length; i++) { + sum += addr[i]; + } + return !sum; +} + bool rsdt_verify(void) { uint8_t sum = 0; for (size_t i = 0; i < rsdt->length; i++) { @@ -84,19 +94,18 @@ static size_t rsdt_get_entry_count(void) { static struct madt *madt = NULL; -bool madt_find(void) { +static void *rsdt_get_entry(char *signature) { size_t length = rsdt_get_entry_count(); for (size_t i = 0; i < length; i++) { struct description_header *description_header = kmap_page((void *) (uint64_t) rsdt->entry[i], PAGE_PRESENT); - if (!memcmp(description_header->signature, MADT_SIGNATURE, 4)) { - madt = (struct madt *) (uint64_t) rsdt->entry[i]; - return true; + if (!memcmp(description_header->signature, signature, 4)) { + return (struct madt *) (uint64_t) rsdt->entry[i]; } } - return false; + return NULL; } bool madt_map(void) { @@ -113,6 +122,12 @@ bool madt_verify(void) { return !sum; } + +bool madt_find(void) { + madt = rsdt_get_entry(MADT_SIGNATURE); + return madt != NULL; +} + uint32_t madt_get_lapic_address(void) { return madt->local_interrupt_controller_address; } @@ -121,6 +136,8 @@ static struct madt_entry **madt_entries = NULL; static size_t max_madt_entries = 0; size_t ioapic_count_entries(void) { + if (madt_entries != NULL) return max_madt_entries; + // all entries are after madt struct madt_entry *madt_entry = (struct madt_entry *) ((uint8_t *) madt + sizeof(struct madt)); @@ -146,3 +163,42 @@ size_t ioapic_count_entries(void) { struct madt_entry **get_madt_entries(void) { return madt_entries; } + +#define MCFG_SIGNATURE "MCFG" + +static struct mcfg *mcfg = NULL; + +bool mcfg_find(void) { + mcfg = rsdt_get_entry(MCFG_SIGNATURE); + return mcfg != NULL; +} + +bool mcfg_verify(void) { + return rsdt_entry_verify(mcfg); +} + +bool mcfg_map(void) { + mcfg = kmap_page(mcfg, PAGE_PRESENT); + return verify_mapping(mcfg); +} + +static struct mcfg_entry **mcfg_entries = NULL; +static size_t max_mcfg_entries = 0; + +size_t mcfg_count_entries(void) { + if (mcfg_entries != NULL) return max_madt_entries; + + struct mcfg_entry *mcfg_entry = + (struct mcfg_entry *) ((uint8_t *) mcfg + sizeof(struct mcfg)); + + uint8_t *end = (uint8_t *) mcfg + mcfg->length; + max_mcfg_entries = (end - (uint8_t *) mcfg_entry) / sizeof(struct mcfg_entry); + + mcfg_entries = kmalloc(sizeof(*mcfg_entries) * max_mcfg_entries); + + for (size_t i = 0; (uint8_t *) mcfg_entry < end; i++) { + mcfg_entries[i] = mcfg_entry; + mcfg_entry = (struct mcfg_entry *) ((uint8_t *) mcfg_entry + sizeof(struct mcfg_entry)); + } + return max_madt_entries; +} diff --git a/kernel/src/arch/x86_64/acpi/acpi.h b/kernel/src/arch/x86_64/acpi/acpi.h index b88d6b8..5cde896 100644 --- a/kernel/src/arch/x86_64/acpi/acpi.h +++ b/kernel/src/arch/x86_64/acpi/acpi.h @@ -67,6 +67,23 @@ struct madt_entry_apicio { uint32_t global_system_interrupt_base; } __attribute__((packed)); +struct mcfg_entry { + uint64_t address; + // PCI segment group number + uint16_t pci_group; + uint8_t start_PCI_bus; + uint8_t end_PCI_bus; + uint32_t reserved; +} __attribute__((packed)); + +// from here: https://wiki.osdev.org/PCI_Express +// not specified in ACPI spec (probs needs to find it in pcie spec) +struct mcfg { + DESCRIPTION_HEADER + uint8_t reserved[8]; + struct mcfg_entry data[]; +} __attribute__((packed)); + // Finds the rsdp and sets the address bool rsdp_find(void); @@ -102,3 +119,15 @@ size_t ioapic_count_entries(void); // Returns a array of addresses to madts struct madt_entry **get_madt_entries(void); + +// Finds the mcfg +bool mcfg_find(void); + +// Verifies the mcfg +bool mcfg_verify(void); + +// Maps the mcfg to a virtual memory address +bool mcfg_map(void); + +// Counts the entries of the mcfg +size_t mcfg_count_entries(void); diff --git a/kernel/src/arch/x86_64/apic/lapic.c b/kernel/src/arch/x86_64/apic/lapic.c index e083c2d..eb95fc8 100644 --- a/kernel/src/arch/x86_64/apic/lapic.c +++ b/kernel/src/arch/x86_64/apic/lapic.c @@ -2,7 +2,6 @@ #include "../cpu/cpuid.h" #include "../cpu/msr.h" -#include "../memory/paging.h" #include "../serial/serial.h" #define IA32_APIC_BASE_MSR 0x1B @@ -39,8 +38,6 @@ static uintptr_t cpu_get_apic_base(void) { // todo: read from acpi to figure out ioapicbase // todo: since its not guaranteed to be same in all systems -#define BASE_LAPIC 0xFEE00000 - void write_reg(void *lapicbase, uint32_t reg, uint32_t value) { uint32_t volatile *lapic = (uint32_t volatile *) lapicbase; lapic[reg] = value; @@ -51,6 +48,8 @@ uint32_t read_reg(void *lapicbase, uint32_t reg) { return lapic[reg]; } +#define BASE_LAPIC 0xFEE00000 + #define PIC1 0x20 /* IO base address for master PIC */ #define PIC2 0xA0 /* IO base address for slave PIC */ #define PIC1_DATA (PIC1 + 1) @@ -77,19 +76,6 @@ void send_apic_eoi(void) { *(uint32_t volatile *) ((uint64_t) lapic + 0xB0) = 0; } -// Refer to Intel IA-32 Volume 3 12.5.4 APIC Timer -void init_apic_timer(uint32_t initial_count, uint8_t vector) { - // be divisble by 1 (every 10ms) (Figure 12-10) - *(uint32_t volatile *) ((uint64_t) lapic + 0x3E0) = 1011; - // set initial count (Figure 12-11) - *(uint32_t volatile *) ((uint64_t) lapic + 0x380) = initial_count; -// Refer to 12.5.1 (Timer mode and vector in Figure 12-8) -// 0 = one shot, 1 = periodic, 2 = TSC-deadline -#define APIC_TIMER_MODE 0 - *(uint32_t volatile *) ((uint64_t) lapic + 0x320) = - vector | (APIC_TIMER_MODE << 17); -} - -uint32_t get_apic_timer_current(void) { - return *(uint32_t volatile *) ((uint64_t) lapic + 0x390); +void *apic_get_address(void) { + return lapic; } diff --git a/kernel/src/arch/x86_64/apic/lapic.h b/kernel/src/arch/x86_64/apic/lapic.h index 4b89871..e4a0e21 100644 --- a/kernel/src/arch/x86_64/apic/lapic.h +++ b/kernel/src/arch/x86_64/apic/lapic.h @@ -3,6 +3,8 @@ #include #include +#include "../memory/paging.h" + // Checks whether apic is supported bool apic_is_supported(void); @@ -24,8 +26,5 @@ void write_reg(void *ioapicaddr, uint32_t reg, uint32_t value); // Signal end of interrupt to apic void send_apic_eoi(void); -// Initialises the apic timer -void init_apic_timer(uint32_t initial_count, uint8_t vector); - -// Get the current count of apic timer -uint32_t get_apic_timer_current(void); +// Get apic address +void *apic_get_address(void); diff --git a/kernel/src/arch/x86_64/cpu/idt.c b/kernel/src/arch/x86_64/cpu/idt.c index cc93867..3c6abc2 100644 --- a/kernel/src/arch/x86_64/cpu/idt.c +++ b/kernel/src/arch/x86_64/cpu/idt.c @@ -15,8 +15,8 @@ static uint16_t idt_segment_descriptor(uint16_t index) { return ((index & 0xFFF) << 3); } -void setup_interrupt_gate(uint32_t irq, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist) { - struct interrupt_descriptor *interrupt_descriptor = &interrupt_descriptors[irq]; +void setup_interrupt_gate(uint32_t vector, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist) { + struct interrupt_descriptor *interrupt_descriptor = &interrupt_descriptors[vector]; // present bit must be set for descriptor to be valid interrupt_descriptor->type_attributes |= 1 << 15; diff --git a/kernel/src/arch/x86_64/cpu/idt.h b/kernel/src/arch/x86_64/cpu/idt.h index bed760e..c2f1d9c 100644 --- a/kernel/src/arch/x86_64/cpu/idt.h +++ b/kernel/src/arch/x86_64/cpu/idt.h @@ -24,6 +24,6 @@ enum gate_type { TRAP_64_GATE = 0xF }; -void setup_interrupt_gate(uint32_t irq, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist); +void setup_interrupt_gate(uint32_t vector, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist); void load_idt(void); diff --git a/kernel/src/arch/x86_64/drivers/keyboard/keyboard.c b/kernel/src/arch/x86_64/drivers/keyboard/keyboard.c index abbc827..fa17abd 100644 --- a/kernel/src/arch/x86_64/drivers/keyboard/keyboard.c +++ b/kernel/src/arch/x86_64/drivers/keyboard/keyboard.c @@ -1,13 +1,206 @@ #include "keyboard.h" #include "../../../../io.h" +#include "../../apic/ioapic.h" #include "../../apic/lapic.h" +#include "../../cpu/idt.h" +#include "../../klib/klib.h" #include "../../serial/serial.h" -__attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame) { +#include + +#define DATA_PORT 0x60 +#define STATUS_REGISTER 0x64 +#define COMMAND_REGISTER STATUS_REGISTER + +#define SET_LEDS 0xED + +// clang-format off +enum scan_set_one { + // todo: abbreviate names + S1_ESC = 1, S1_1, S1_2, S1_3, S1_4, + S1_5, S1_6, S1_7, S1_8, S1_9, + S1_0, S1_MINUS, S1_EQUAL, S1_BACKSPACE, S1_TAB, + S1_Q, S1_W, S1_E, S1_R, S1_T, + S1_Y, S1_U, S1_I, S1_O, S1_P, S1_LEFT_BRACKET, + S1_RIGHT_BRACKET, S1_ENTER, S1_LEFT_CTRL, S1_A, S1_S, + S1_D, S1_F, S1_G, S1_H, S1_J, + S1_K, S1_L, S1_SEMI, S1_SINGLE_QUOTE, S1_BACK_TICK, + S1_LEFT_SHIFT, S1_LEFT_SLASH, S1_Z, S1_X, S1_C, + S1_V, S1_B, S1_N, S1_M, S1_COMMA, + S1_DOT, S1_RIGHT_SLASH, S1_RIGHT_SHIFT, S1_KEYPAD_STAR, + S1_LEFT_ALT, S1_SPACE, S1_CAPSLOCK, S1_F1, S1_F2, + S1_F3, S1_F4, S1_F5, S1_F6, S1_F7, + S1_F8, S1_F9, S1_F10, S1_NUMLOCK, S1_SCROLLLOCK, + S1_KEYPAD_7, S1_KEYPAD_8, S1_KEYPAD_9, S1_KEYPAD_MINUS, + S1_KEYPAD_4, S1_KEYPAD_5, S1_KEYPAD_6, S1_KEYPAD_PLUS, + S1_KEYPAD_1, S1_KEYPAD_2, S1_KEYPAD_3, S1_KEYPAD_0, + S1_KEYPAD_DOT, S1_F11, S1_F12, + // RELEASED + // todo: make a map for each key held down + S1_ESC_RELEASED = 0x81, + S1_1_RELEASED, S1_2_RELEASED, S1_3_RELEASED, S1_4_RELEASED, + S1_5_RELEASED, S1_6_RELEASED, S1_7_RELEASED, S1_8_RELEASED, + S1_9_RELEASED, S1_0_RELEASED, S1_MINUS_RELEASED, S1_EQUALS_RELEASED, + S1_BACKSPACE_RELEASED, S1_TAB_RELEASED, S1_Q_RELEASED, S1_W_RELEASED, + S1_E_RELEASED, S1_R_RELEASED, S1_T_RELEASED, S1_Y_RELEASED, S1_U_RELEASED, + S1_I_RELEASED, S1_O_RELEASED, S1_P_RELEASED, S1_LEFT_BRACKET_RELEASED, + S1_RIGHT_BRACKET_RELEASED, S1_ENTER_RELEASED, S1_LEFT_CTRL_RELEASED, S1_A_RELEASED, + S1_S_RELEASED, S1_D_RELEASED, S1_F_RELEASED, S1_G_RELEASED, S1_H_RELEASED, + S1_J_RELEASED, S1_K_RELEASED, S1_L_RELEASED, S1_SEMI_RELEASED, S1_SINGLE_QUOTE_RELEASED, + S1_BACK_TICK_RELEASED, S1_LEFT_SHIFT_RELEASED, S1_LEFT_SLASH_RELEASED, S1_Z_RELEASED, + S1_X_RELEASED, S1_C_RELEASED, S1_V_RELEASED, S1_B_RELEASED, S1_N_RELEASED, + S1_M_RELEASED, S1_COMMA_RELEASED, S1_DOT_RELEASED, S1_RIGHT_SLASH_RELEASED, + S1_RIGHT_SHIFT_RELEASED, S1_KEYPAD_STAR_RELEASED, S1_LEFT_ALT_RELEASED, S1_SPACE_RELEASED, + S1_CAPSLOCK_RELEASED, S1_F1_RELEASED, S1_F2_RELEASED, S1_F3_RELEASED, S1_F4_RELEASED, + S1_F5_RELEASED, S1_F6_RELEASED, S1_F7_RELEASED, S1_F8_RELEASED, S1_F9_RELEASED, + S1_F10_RELEASED, S1_NUMLOCK_RELEASED, S1_SCROLLLOCK_RELEASED, S1_KEYPAD_7_RELEASED, + S1_KEYPAD_8_RELEASED, S1_KEYPAD_9_RELEASED, S1_KEYPAD_MINUS_RELEASED, + S1_KEYPAD_4_RELEASED, S1_KEYPAD_5_RELEASED, S1_KEYPAD_6_RELEASED, S1_KEYPAD_PLUS_RELEASED, + S1_KEYPAD_1_RELEASED, S1_KEYPAD_2_RELEASED, S1_KEYPAD_3_RELEASED, S1_KEYPAD_0_RELEASED, + S1_KEYPAD_DOT_RELEASED, S1_F11_RELEASED, S1_F12_RELEASED +}; +// clang-format on + +#define MAX_BUFFER_SIZE 512 +static char buffer[MAX_BUFFER_SIZE]; +static volatile size_t buffer_pos = 0; + +static __attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame); + +static uint8_t keyboard_code_set_1(const uint8_t data); +static uint8_t keyboard_shift_conversion(uint8_t data); + +static bool caps_lock = false; +static bool shift_pressed = false; + +// TODO: use acpi to check if 8042 ps/2 controller is supported +// todo: poll for keyboard status +// todo: check keyboard type (1, 2, 3) + +void keyboard_init(void *ioapic) { + // Disable any devices connected to ps/2 ports + //outb(0x64, 0xAD); + //outb(0x64, 0xA7); + // todo: do the steps specified by osdev later + + int apic_id = apic_get_id(); + ioapic_set_redirect((uintptr_t *) ioapic, 1, 0x21, apic_id); + setup_interrupt_gate(0x21, keyboard_handler, INTERRUPT_64_GATE, 0, 0); +} + +// Keycodes from: https://wiki.osdev.org/PS/2_Keyboard +// CODE SET 1 +// ! for some reason 2,3,4 in qemu r different keys +static uint8_t keyboard_code_set_1(const uint8_t data) { + if (data >= S1_1 && data <= S1_BACKSPACE) { + return "1234567890-=\b"[data - S1_1]; + } else if (data >= S1_Q && data <= S1_ENTER) { + return "QWERTYUIOP[]\n"[data - S1_Q]; + } else if (data >= S1_A && data <= S1_BACK_TICK) { + return "ASDFGHJKL;'`"[data - S1_A]; + } else if (data >= S1_LEFT_SLASH && data <= S1_RIGHT_SLASH) { + return "\\ZXCVBNM,./"[data - S1_LEFT_SLASH]; + } else if (data >= S1_KEYPAD_7 && data <= S1_KEYPAD_DOT) { + return "789-456+1230."[data - S1_KEYPAD_7]; + } else if (data == S1_SPACE) { + return ' '; + } else if (data == S1_KEYPAD_STAR) { + return '*'; + } else if (data == S1_CAPSLOCK) { + caps_lock = !caps_lock; + // enable caps lock LED + if (caps_lock) { + outb(DATA_PORT, SET_LEDS); + ksleep(5); + outb(DATA_PORT, 1 << 2); + } else { + outb(DATA_PORT, SET_LEDS); + ksleep(5); + outb(DATA_PORT, 0x0); + } + } else if (data == S1_LEFT_SHIFT || data == S1_RIGHT_SHIFT) { + shift_pressed = true; + } else if (data == S1_LEFT_SHIFT_RELEASED || data == S1_RIGHT_SHIFT_RELEASED) { + shift_pressed = false; + } + + return data; +} + +// TODO: have switch for different code sets +static char keyboard_convert_code(char data) { + return keyboard_code_set_1(data); +} + +// ! figure out how to make it pause/wait for getchar(); + +// todo: WRITE A FRONTEND FUNCTION FOR KLIB +char getc(void) { + while (!buffer_pos) { + __builtin_ia32_pause(); + } + char data = buffer[--buffer_pos]; + putc(data); + return data; +} + +size_t getstr(char *str, size_t len) { + size_t i = 0; + while (i < len) { + char data = getc(); + if (data == '\n') return i; + if (data == '\b') { + i--; + continue; + } + str[i] = data; + i++; + } + return i; +} + +static uint8_t keyboard_shift_conversion(uint8_t data) { + if (!shift_pressed) return data; + + // Inverse because of caps lock + if (data >= 'A' && data <= 'Z') return data + 32; + if (data >= 'a' && data <= 'z') return data - 32; + + if (data >= '0' && data <= '9') return ")!@#$%^&*("[data - '0']; + + switch (data) { + case '[': + return '{'; + case ']': + return '}'; + case '-': + return '_'; + case '=': + return '+'; + case '\\': + return '|'; + case ';': + return ':'; + case ',': + return '<'; + case '.': + return '>'; + default: + return data; + } +} + +static void keyboard_handler(struct interrupt_frame *frame) { // Consume a key, not doing this will only let // the interrupt trigger once - inb(0x60); - puts("Keyboard pressed"); + uint8_t data = keyboard_code_set_1(inb(DATA_PORT)); + if (data >= 'A' && data <= 'Z' && !caps_lock) data += 32; + data = keyboard_shift_conversion(data); + if ((data >= ' ' && data <= '~') || data == '\b' || data == '\t' || data == '\n') buffer[buffer_pos++] = data; + // ! minor bug: could loop over and getc wont be able to get the prev 512 chars + buffer_pos %= MAX_BUFFER_SIZE; + //if (data >= ' ' && data <= '~') + // krintf("Keyboard pressed %c %d\n", data, buffer_pos); send_apic_eoi(); } diff --git a/kernel/src/arch/x86_64/drivers/keyboard/keyboard.h b/kernel/src/arch/x86_64/drivers/keyboard/keyboard.h index 2f0e0a6..3de0258 100644 --- a/kernel/src/arch/x86_64/drivers/keyboard/keyboard.h +++ b/kernel/src/arch/x86_64/drivers/keyboard/keyboard.h @@ -1,6 +1,15 @@ #pragma once +#include + struct interrupt_frame; -// Keyboard Handler -void keyboard_handler(struct interrupt_frame *frame); +// Initialise the keyboard driver +void keyboard_init(void *ioapic); + +char getc(void); + +size_t getstr(char *str, size_t len); + +// Keyboard handler +static void keyboard_handler(struct interrupt_frame *frame); diff --git a/kernel/src/arch/x86_64/drivers/mouse/mouse.c b/kernel/src/arch/x86_64/drivers/mouse/mouse.c new file mode 100644 index 0000000..5a3d09e --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/mouse/mouse.c @@ -0,0 +1,122 @@ +#include "mouse.h" + + +#include "../../../../io.h" +#include "../../apic/ioapic.h" +#include "../../apic/lapic.h" +#include "../../cpu/idt.h" +#include "../../klib/klib.h" +#include "../../serial/serial.h" + +#define DATA_PORT 0x60 +#define STATUS_REGISTER 0x64 +#define COMMAND_REGISTER STATUS_REGISTER + + +#define MOUSE_COMMAND 0xD4 +#define MOUSE_BIT 0x20 +#define GET_COMPAQ_STATUS_BYTE 0x20 + +static bool right_button = false; +static bool left_button = false; +static bool middle_button = false; +static bool x_sign = false; +static bool y_sign = false; +static uint8_t x_movement = 0; +static uint8_t y_movement = 0; + +static __attribute__((interrupt)) void mouse_handler(struct interrupt_frame *frame); +static void wait_mouse(bool is_output); + +void mouse_init(void* ioapic) { + // enable mouse + wait_mouse(true); + outb(COMMAND_REGISTER, 0xA8); + + // enable aux port to generate irq 12 (according to osdev) + wait_mouse(true); + outb(COMMAND_REGISTER, GET_COMPAQ_STATUS_BYTE); + + wait_mouse(false); + uint8_t status = inb(STATUS_REGISTER); + status |= 0x10; // Enable IRQ12 + status ^= ~0x20;// Disable mouse clock + + // todo: bundle wait_mouse and outb/inb into one function + + // update status with compaq byte + wait_mouse(true); + outb(COMMAND_REGISTER, 0x60); + wait_mouse(true); + outb(DATA_PORT, status); + + // set defaults for mouse + wait_mouse(true); + outb(COMMAND_REGISTER, MOUSE_COMMAND); + wait_mouse(true); + outb(DATA_PORT, 0xF6); + + // enable packet streaming + wait_mouse(true); + outb(COMMAND_REGISTER, MOUSE_COMMAND); + wait_mouse(true); + outb(DATA_PORT, 0xF4); + + int apic_id = apic_get_id(); + ioapic_set_redirect((uintptr_t *) ioapic, 12, 0x22, apic_id); + setup_interrupt_gate(0x22, mouse_handler, INTERRUPT_64_GATE, 0, 0); +} + + +// See: https://wiki.osdev.org/Mouse_Input#Waiting_to_Send_Bytes_to_Port_0x60_and_0x64 +static void wait_mouse(bool is_output) { + if (is_output) { + while (inb(STATUS_REGISTER) & 0x2) { + __builtin_ia32_pause(); + } + } else { + while (!(inb(DATA_PORT) & 0x1)) { + __builtin_ia32_pause(); + } + } +} + +static void mouse_handler(struct interrupt_frame *frame) { + uint8_t status = inb(STATUS_REGISTER); + puts("Mouse interrupt\n"); + size_t nth_byte = 0; + + while (status & MOUSE_BIT) { + uint8_t data = inb(DATA_PORT); + switch (nth_byte) { + case 0: + right_button = data & 0x1; + left_button = data & 0x2; + middle_button = data & 0x4; + x_sign = data & 0x10; + y_sign = data & 0x20; + break; + case 1: + x_movement = data; + break; + case 2: + y_movement = data; + break; + } + nth_byte++; + nth_byte %= 3; + krintf( + "Mouse info\n" + "right button: %d\n" + "left button: %d\n" + "middle button: %d\n" + "x sign: %d\n" + "y sign: %d\n" + "x movement: %d\n" + "y movement: %d\n", + right_button, left_button, middle_button, x_sign, y_sign, x_movement, y_movement); + status = inb(STATUS_REGISTER); + } + puts("Finished mouse interrupt\n"); + send_apic_eoi(); +} diff --git a/kernel/src/arch/x86_64/drivers/mouse/mouse.h b/kernel/src/arch/x86_64/drivers/mouse/mouse.h new file mode 100644 index 0000000..e5bedc7 --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/mouse/mouse.h @@ -0,0 +1,3 @@ +#pragma once + +void mouse_init(void* ioapic); diff --git a/kernel/src/arch/x86_64/drivers/pci/pci.c b/kernel/src/arch/x86_64/drivers/pci/pci.c new file mode 100644 index 0000000..ce8f24a --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/pci/pci.c @@ -0,0 +1,76 @@ +#include "pci.h" + +#include + +#include "../../klib/klib.h" +#include "../../serial/serial.h" + +#include "../../../../io.h" + +#define CONFIG_ADDRESS 0xCF8 +#define CONFIG_DATA 0xCFC + +static struct common_header *devices = NULL; +static size_t i = 0; + +// todo: support PCIE once I figure out a way +// todo: to enable pcie in qemu + +// ! THIS ASSUMES WE ARE USING MECHANISM 1 +// ! MECHANISM 2 is deprecated + +// See: https://wiki.osdev.org/PCI +uint32_t pci_config_readl(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { + uint32_t address = 0; + address |= bus << 16; + address |= slot << 11; + address |= func << 8; + address |= offset & 0xFC; + address |= 1 << 31; + outl(CONFIG_ADDRESS, address); + return inl(CONFIG_DATA); +} + +struct common_header pci_get_config(uint8_t bus, uint8_t slot, uint8_t func) { + struct common_header header = {0}; + + // abuses little endian + ((uint32_t *) &header)[offsetof(struct common_header, vendor_ID) / sizeof(uint32_t)] = + pci_config_readl(bus, slot, func, 0x0); + ((uint32_t *) &header)[offsetof(struct common_header, command) / sizeof(uint32_t)] = + pci_config_readl(bus, slot, func, 0x4); + ((uint32_t *) &header)[offsetof(struct common_header, revision_ID) / sizeof(uint32_t)] = + pci_config_readl(bus, slot, func, 0x8); + ((uint32_t *) &header)[offsetof(struct common_header, cache_line_size) / sizeof(uint32_t)] = + pci_config_readl(bus, slot, func, 0xC); + + return header; +} + +void pci_check_slot(uint8_t bus, uint8_t slot) { + // todo: expand upon this + for (size_t func = 0; func < 8; func++) { + struct common_header header = pci_get_config(bus, slot, func); + if (header.vendor_ID == 0xFFFF) return; + if ((header.header_type & 0x80) == 0) + if (func != 0) continue; + + krintf("Found device at bus %d slot %d function %d\n" + "Vendor ID: %d, Device ID: %d\n", + bus, slot, func, + header.vendor_ID, header.device_ID); + devices[i++] = header; + } +} + +void pci_scan(void) { + // bruteforce method - hopefully we dont have more than 32 devices connected + // todo: have a method to figure out how many devices are connected + devices = kmalloc(32 * sizeof(struct common_header)); + for (size_t bus = 0; bus < 256; bus++) { + for (size_t slot = 0; slot < 32; slot++) { + pci_check_slot(bus, slot); + } + } + i = 0; +} diff --git a/kernel/src/arch/x86_64/drivers/pci/pci.h b/kernel/src/arch/x86_64/drivers/pci/pci.h new file mode 100644 index 0000000..9e14042 --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/pci/pci.h @@ -0,0 +1,109 @@ +#pragma once + +#include +#include + +#define COMMON_HEADER \ + uint16_t vendor_ID; \ + uint16_t device_ID; \ + uint16_t command; \ + uint16_t status; \ + uint8_t revision_ID; \ + uint8_t prog_IF; \ + uint8_t subclass; \ + uint8_t class_code; \ + uint8_t cache_line_size; \ + uint8_t latency_timer; \ + uint8_t header_type; \ + uint8_t BIST; + + +struct common_header { + COMMON_HEADER + // uint8_t data[]; +} __attribute__((packed)); + +struct device_header { + COMMON_HEADER + uint32_t base_addresses[6]; + uint32_t cardbus_cis_pointer; + uint16_t subsystem_vendor_ID; + uint16_t subsystem_device_ID; + uint32_t expansion_rom_address; + uint8_t capabilities_pointer; + uint8_t reserved0; + uint16_t reserved1; + uint32_t reserved2; + uint8_t interrupt_line; + uint8_t interrupt_pin; + uint8_t min_grant; + uint8_t max_latency; +} __attribute__((packed)); + +// pci to pci +struct pci_bridge_header { + COMMON_HEADER + uint32_t base_addresses[2]; + uint8_t primary_bus_number; + uint8_t secondary_bus_number; + uint8_t subordinate_bus_number; + uint8_t secondary_latency_timer; + uint8_t io_base; + uint8_t io_limit; + uint8_t secondary_status; + uint16_t memory_base; + uint16_t memory_limit; + uint16_t prefetchable_memory_base; + uint16_t prefetchable_memory_limit; + uint32_t prefetchable_memory_base_upper; + uint32_t prefetchable_memory_limit_upper; + uint16_t io_base_upper; + uint16_t io_limit_upper; + uint8_t capabilities_pointer; + uint8_t reserved0; + uint16_t reserved1; + uint32_t expansion_ROM_base_address; + uint8_t interrupt_line; + uint8_t interrupt_pin; + uint16_t bridge_control; +} __attribute__((packed)); + +// pci to cardbus +struct cardbus_bridge_header { + COMMON_HEADER + uint32_t base_address; + uint8_t offset_capabilities_list; + uint8_t reserved0; + uint16_t secondary_status; + uint8_t pci_bus_number; + uint8_t cardbus_bus_number; + uint8_t subordinate_bus_number; + uint8_t cardbus_latency_timer; + uint32_t memory_base_address0; + uint32_t memory_limit0; + uint32_t memory_base_address1; + uint32_t memory_limit1; + uint32_t io_base_address0; + uint32_t io_limit0; + uint32_t io_base_address1; + uint32_t io_limit1; + uint8_t interrupt_line; + uint8_t interrupt_pin; + uint16_t bridge_control; + uint16_t subsystem_device_ID; + uint16_t subsystem_vendor_ID; + // 16 bit pc card + uint32_t legacy_mode_base_address; +} __attribute__((packed)); + +uint32_t pci_config_readl(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset); + +void pci_scan(void); + +struct common_header pci_get_config(uint8_t bus, uint8_t slot, uint8_t func); + +void pci_check_slot(uint8_t bus, uint8_t slot); + +void pci_init(void); + +bool pci_msi_supported(void); diff --git a/kernel/src/arch/x86_64/drivers/speaker/speaker.c b/kernel/src/arch/x86_64/drivers/speaker/speaker.c new file mode 100644 index 0000000..4fbe170 --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/speaker/speaker.c @@ -0,0 +1,39 @@ +#include + +#include "../../serial/serial.h" + +#include "../../klib/klib.h" + +// frequency of PIT oscillator +#define FREQUENCY_BASE 1193182 +#define SPEAKER_PORT 0x61 + +// todo: cleanup code - make function to communicate to channel 2 for pit +#define CHANNEL_0_PORT 0x40 +#define CHANNEL_1_PORT 0x41 +#define CHANNEL_2_PORT 0x42 +#define MODE_COMMAND_REGISTER 0x43 + +static void speaker_play_sound(uint32_t frequency) { + uint32_t div = FREQUENCY_BASE / frequency; + + + outb(MODE_COMMAND_REGISTER, 0b10110110); + + outb(CHANNEL_2_PORT, div & 0xFF); + outb(CHANNEL_2_PORT, (div >> 8) & 0xFF); + + // bit 0 = use PIT + // bit 1 = out position + outb(SPEAKER_PORT, inb(SPEAKER_PORT) | 0x3); +} + +static void speaker_no_sound(void) { + outb(SPEAKER_PORT, inb(SPEAKER_PORT) & ~0x3); +} + +void beep(uint32_t frequency) { + speaker_play_sound(frequency); + ksleep(1000000); + speaker_no_sound(); +} diff --git a/kernel/src/arch/x86_64/drivers/speaker/speaker.h b/kernel/src/arch/x86_64/drivers/speaker/speaker.h new file mode 100644 index 0000000..ed7edec --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/speaker/speaker.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +// Play a beep +void beep(uint32_t frequency); diff --git a/kernel/src/arch/x86_64/drivers/timer/apic.c b/kernel/src/arch/x86_64/drivers/timer/apic.c new file mode 100644 index 0000000..3c5108f --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/timer/apic.c @@ -0,0 +1,35 @@ +#include "timer.h" + +#include "../../apic/lapic.h" + +static uint32_t timer_ticks = 0; + +// Refer to Intel IA-32 Volume 3 12.5.4 APIC Timer +void apic_timer_init(uint32_t initial_count, uint8_t vector) { + void *lapic = apic_get_address(); + // be divisble by 1 (every 10ms) (Figure 12-10) + *(uint32_t volatile *) ((uint64_t) lapic + 0x3E0) = 1011; + // set initial count (Figure 12-11) + *(uint32_t volatile *) ((uint64_t) lapic + 0x380) = initial_count; +// Refer to 12.5.1 (Timer mode and vector in Figure 12-8) +// 0 = one shot, 1 = periodic, 2 = TSC-deadline +#define APIC_TIMER_MODE 0 + *(uint32_t volatile *) ((uint64_t) lapic + 0x320) = + vector | (APIC_TIMER_MODE << 17); +} + +// returns time left from countdown iirc +uint32_t apic_timer_get_current(void) { + void *lapic = apic_get_address(); + return *(uint32_t volatile *) ((uint64_t) lapic + 0x390); +} + + +uint32_t apic_timer_get_ticks(void) { + return timer_ticks; +} + +__attribute__((interrupt)) void apic_timer_handler(struct interrupt_frame *frame) { + timer_ticks++; + send_apic_eoi(); +} diff --git a/kernel/src/arch/x86_64/drivers/timer/pit.c b/kernel/src/arch/x86_64/drivers/timer/pit.c new file mode 100644 index 0000000..4b91484 --- /dev/null +++ b/kernel/src/arch/x86_64/drivers/timer/pit.c @@ -0,0 +1,103 @@ +#include "timer.h" + +#include "../../apic/ioapic.h" +#include "../../apic/lapic.h" +#include "../../serial/serial.h" + +#include "../../../../io.h" + +// frequency of PIT oscillator (rounded up) +#define FREQUENCY_BASE 1193182 + +// frequency used by cga video controller - according to osdev +#define VIDEO_FREQUENCY 3579545 + +static uint32_t timer_fractions = 0; +static uint32_t system_timer_fractions = 0; + +static uint32_t timer_ms = 0; +static uint32_t system_timer_ms = 0; + +static uint32_t timer_frequency = 0; + +// todo: consider multithreaded +static uint32_t timer_countdown = 0; + +#define CHANNEL_0_PORT 0x40 +#define CHANNEL_1_PORT 0x41 +#define CHANNEL_2_PORT 0x42 +#define MODE_COMMAND_REGISTER 0x43 + + +static uint32_t round_frequency(uint32_t frequency) { + // round it + uint32_t quotient = VIDEO_FREQUENCY / frequency; + uint32_t remainder = VIDEO_FREQUENCY % frequency; + if (remainder >= VIDEO_FREQUENCY / 2) { + quotient++; + } + + remainder = quotient % 3; + quotient /= 3; + + if (remainder >= 3 / 2) { + quotient++; + } + + return quotient; +} + +// ! investigate why it triple faults when cli and sti +// From: https://wiki.osdev.org/Programmable_Interval_Timer +void pit_init(uint32_t frequency) { + + uint32_t reload_value; + if (frequency >= FREQUENCY_BASE) { + reload_value = FREQUENCY_BASE; + } else if (frequency <= 18) { + reload_value = 0x10000; + } else { + reload_value = round_frequency(frequency); + } + + timer_frequency = round_frequency(frequency); + + // time in ms * 2^32 = reload_value * 3000 * (2^42) / 3579545 / (2^10) + +#define MULTIPLIER (3000 * (2ul << 42) / 3579545) + uint64_t quotient = (reload_value * MULTIPLIER) << 10; + + timer_ms = (quotient >> 32) & 0xFFFFFFFF; + timer_fractions = quotient & 0xFFFFFFFF; + + // operating mode: rate generator + outb(MODE_COMMAND_REGISTER, 0b00110100); + + + // 16 bits total + + // program the pit + outb(CHANNEL_0_PORT, reload_value & 0xFF); + outb(CHANNEL_0_PORT, (reload_value >> 8) & 0xFF); + +} + +uint32_t timer_get_actual_frequency(void) { + return timer_frequency; +} + +void pleep(uint32_t millis) { + timer_countdown = millis; + while (timer_countdown > 0) { + __builtin_ia32_pause(); + } +} + +// ! currently not working +__attribute__((interrupt)) void pit_handler(struct interrupt_frame *frame) { + system_timer_fractions += timer_fractions; + puts("TIMER ACTIVATED\n"); + system_timer_ms += timer_ms; + if (timer_countdown > 0) timer_countdown -= timer_ms; + send_apic_eoi(); +} diff --git a/kernel/src/arch/x86_64/drivers/timer/timer.c b/kernel/src/arch/x86_64/drivers/timer/timer.c deleted file mode 100644 index 1b4bc31..0000000 --- a/kernel/src/arch/x86_64/drivers/timer/timer.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "timer.h" - -#include "../../apic/lapic.h" - -static int timer_ticks = 0; - -uint32_t get_timer_ticks(void) { - return timer_ticks; -} - -__attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame) { - send_apic_eoi(); -} diff --git a/kernel/src/arch/x86_64/drivers/timer/timer.h b/kernel/src/arch/x86_64/drivers/timer/timer.h index ece4711..9fc0678 100644 --- a/kernel/src/arch/x86_64/drivers/timer/timer.h +++ b/kernel/src/arch/x86_64/drivers/timer/timer.h @@ -3,9 +3,24 @@ #include // Returns the timer -uint32_t get_timer_ticks(void); +uint32_t apic_timer_get_ticks(void); struct interrupt_frame; // Timer handler -void timer_handler(struct interrupt_frame *frame); +void apic_timer_handler(struct interrupt_frame *frame); + +// Initialises the apic timer +void apic_timer_init(uint32_t initial_count, uint8_t vector); + +// Get the current count of apic timer +uint32_t apic_timer_get_current(void); + +void pit_handler(struct interrupt_frame *frame); + +void pit_init(uint32_t frequency); + +uint32_t timer_get_actual_frequency(void); + +// Sleep but from PIT timer +void pleep(uint32_t millis); diff --git a/kernel/src/arch/x86_64/klib/klib.c b/kernel/src/arch/x86_64/klib/klib.c index d144e9a..97c4342 100644 --- a/kernel/src/arch/x86_64/klib/klib.c +++ b/kernel/src/arch/x86_64/klib/klib.c @@ -1,10 +1,10 @@ #include "klib.h" -#include "../apic/lapic.h" +#include "../drivers/timer/timer.h" void ksleep(int ticks) { - init_apic_timer(ticks, 0x20); - while (get_apic_timer_current()); + apic_timer_init(ticks, 0x20); + while (apic_timer_get_current()); } _Noreturn void _die(void) { diff --git a/kernel/src/arch/x86_64/serial/serial.c b/kernel/src/arch/x86_64/serial/serial.c index d06ca72..083518a 100644 --- a/kernel/src/arch/x86_64/serial/serial.c +++ b/kernel/src/arch/x86_64/serial/serial.c @@ -8,8 +8,18 @@ void outw(uint16_t port, uint16_t value) { asm volatile("outw %w0, %w1" : : "a"(value), "Nd"(port) : "memory"); } +void outl(uint16_t port, uint32_t value) { + asm volatile("outl %d0, %d1" : : "a"(value), "Nd"(port) : "memory"); +} + uint8_t inb(uint16_t port) { uint8_t value; asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port) : "memory"); return value; } + +uint32_t inl(uint16_t port) { + uint32_t value; + asm volatile("inl %d1, %d0" : "=a"(value) : "Nd"(port) : "memory"); + return value; +} diff --git a/kernel/src/arch/x86_64/serial/serial.h b/kernel/src/arch/x86_64/serial/serial.h index 1b612a4..65209d5 100644 --- a/kernel/src/arch/x86_64/serial/serial.h +++ b/kernel/src/arch/x86_64/serial/serial.h @@ -8,5 +8,11 @@ void outb(uint16_t port, uint8_t value); // Writes a word to the serial port void outw(uint16_t port, uint16_t value); +// Writes a long to the serial port +void outl(uint16_t port, uint32_t value); + // Reads a byte from the serial port uint8_t inb(uint16_t port); + +// Reads a long from the serial port +uint32_t inl(uint16_t port); diff --git a/kernel/src/arch/x86_64/vga/vga.c b/kernel/src/arch/x86_64/vga/vga.c index c54ac5a..4c03c48 100644 --- a/kernel/src/arch/x86_64/vga/vga.c +++ b/kernel/src/arch/x86_64/vga/vga.c @@ -1,6 +1,7 @@ #include "vga.h" #include "../klib/klib.h" +#include "../serial/serial.h" #include #include @@ -69,6 +70,18 @@ void vga_putchar(char c) { terminal_row = 0; break; } + case '\b': { + if (terminal_row == 0 && terminal_column == 0) return; + + terminal_column--; + if (terminal_column < 0) { + terminal_column = VGA_WIDTH - 1; + terminal_row--; + } + + terminal_putentryat('\0', terminal_color, terminal_column, terminal_row); + break; + } case 0x20 ... 0x7E: { terminal_putentryat(c, terminal_color, terminal_column, terminal_row); @@ -86,6 +99,7 @@ void vga_putchar(char c) { break; } } + vga_cursor_update(terminal_column, terminal_row); } void vga_write_string(const char *data) { @@ -93,3 +107,53 @@ void vga_write_string(const char *data) { vga_putchar(*data++); } } + +// Found names here: http://www.osdever.net/FreeVGA/vga/crtcreg.htm +#define CURSOR_ADDRESS_REGISTER 0x3D4 +#define CURSOR_INDEX_REGISTER 0x3D5 + +// Cursor address +#define CURSOR_START 0x0A +#define CURSOR_END 0x0B + +#define CURSOR_LOCATION_HIGH 0x0E +#define CURSOR_LOCATION_LOW 0x0F + +void vga_cursor_enable(size_t start, size_t end) { + // Writes to CURSOR_ADDRESS_REGISTER first + // to specify address + + // start determines start of cursor height + // end determines end of cursor height + + outb(CURSOR_ADDRESS_REGISTER, CURSOR_START); + // retain bits 6 and 7 because they are reserved. + outb(CURSOR_INDEX_REGISTER, inb(CURSOR_INDEX_REGISTER) & 0xC0 | (uint8_t) (start & 0x3F)); + + outb(CURSOR_ADDRESS_REGISTER, CURSOR_END); + // retain bits 5, 6, 7 because they are reserved. + outb(CURSOR_INDEX_REGISTER, inb(CURSOR_INDEX_REGISTER) & 0xE0 | (uint8_t) (end & 0x1f)); +} + +void vga_cursor_disable(void) { + outb(CURSOR_ADDRESS_REGISTER, CURSOR_START); + // set 5th bit to 1 to disable + outb(CURSOR_INDEX_REGISTER, inb(CURSOR_INDEX_REGISTER) & 0xC0 | 0x20); +} + +void vga_cursor_update(size_t x, size_t y) { + // todo: ensure 8 bits + uint16_t pos = y * VGA_WIDTH + x; + outb(CURSOR_ADDRESS_REGISTER, CURSOR_LOCATION_LOW); + outb(CURSOR_INDEX_REGISTER, (uint8_t) (pos & 0xFF)); + outb(CURSOR_ADDRESS_REGISTER, CURSOR_LOCATION_HIGH); + outb(CURSOR_INDEX_REGISTER, (uint8_t) ((pos >> 8) & 0xFF)); +} + +uint16_t vga_cursor_position(void) { + uint16_t pos = 0; + outb(CURSOR_ADDRESS_REGISTER, CURSOR_LOCATION_LOW); + pos |= inb(CURSOR_INDEX_REGISTER); + outb(CURSOR_ADDRESS_REGISTER, CURSOR_LOCATION_HIGH); + pos |= inb(CURSOR_INDEX_REGISTER); +} diff --git a/kernel/src/arch/x86_64/vga/vga.h b/kernel/src/arch/x86_64/vga/vga.h index ff7a2d0..9d6d231 100644 --- a/kernel/src/arch/x86_64/vga/vga.h +++ b/kernel/src/arch/x86_64/vga/vga.h @@ -36,3 +36,12 @@ void vga_putchar(char c); // Prints a null-terminated string void vga_write_string(const char *data); + +// Enables text cursor +void vga_cursor_enable(size_t start, size_t end); + +// Disables text cursor +void vga_cursor_disable(void); + +// Updates text cursor +void vga_cursor_update(size_t x, size_t y); diff --git a/kernel/src/kernel_main.c b/kernel/src/kernel_main.c index d96bea1..9d36345 100644 --- a/kernel/src/kernel_main.c +++ b/kernel/src/kernel_main.c @@ -9,6 +9,9 @@ #include "arch/x86_64/cpu/idt.h" #include "arch/x86_64/cpu/msr.h" #include "arch/x86_64/drivers/keyboard/keyboard.h" +#include "arch/x86_64/drivers/mouse/mouse.h" +#include "arch/x86_64/drivers/pci/pci.h" +#include "arch/x86_64/drivers/speaker/speaker.h" #include "arch/x86_64/drivers/timer/timer.h" #include "arch/x86_64/klib/klib.h" #include "arch/x86_64/memory/paging.h" @@ -47,6 +50,22 @@ _Noreturn void user_main(void) { } } +/* int melody[] = { + 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000, 1050, 1100}; +*/ +int melody[] = { + 250, 250, 450, 250, 550, 150, 100, 50, 100, 200, 100}; + +void play_startup() { + int length = sizeof(melody) / sizeof(melody[0]); + for (int i = 0; i < length; i++) { + krintf("Playing %d ", melody[i]); + beep(melody[i]); + ksleep(276447232 / 5); + } + putc('\n'); +} + /* * The entry point after the bootloader finishes setting up x86 32-bit protected * mode. @@ -100,23 +119,48 @@ void kernel_main(struct boot_parameters parameters) { outw(0xf4, 0x10); _die(); #else + puts("Enter a character: "); + char c = getc(); + krintf("Char: %c\n", c); + + + // ear candy + for (int i = 1000; i < 100000; i += 1000) { + beep(i); + ksleep(100000); + } + + + puts("Enter a string: "); + char *str = kmalloc(10); + str[getstr(str, 9)] = '\0'; + play_startup(); + krintf("String: %s\n", str); + free(str); + + pci_scan(); + puts("Finished scanning for PCI devices\n"); + getc(); + char message[] = "X Hello world!\n"; - for (size_t i = 0; i < 1; i++) { + for (size_t i = 0; i < 5; i++) { message[0] = '0' + i; i = (i + 1) % 10; // ! DONT USE FLOATS - THEY DONT WORK FOR SOME REASON krintf("%sThe number is: %d, ticks: %d, entry count: %d\n", message, 5, - get_timer_ticks(), parameters.address_ranges); + apic_timer_get_ticks(), parameters.address_ranges); vga_set_color(1 + (i % 6), VGA_COLOR_BLACK); //memmap_print_entries(parameters.address_range_count, // parameters.address_ranges); // - ksleep(276447232); + pleep(3000); + + //ksleep(276447232); } enter_usermode(user_main); #endif @@ -176,6 +220,16 @@ static void read_acpi(void) { krintf("APICIO address: %x\n", apicio_entry->ioapic_address); } } + + // Currently I don't know how to get pcie + // working with the qemu so we are falling back to pci + /* + if (!mcfg_find()) { + puts("Could not find mcfg\n"); + _die(); + } + puts("Found mcfg\n"); + */ } static void setup_idt(void) { @@ -183,20 +237,23 @@ static void setup_idt(void) { int apic_id = apic_get_id(); krintf("APIC ID: %d\n", apic_id); - // system timer - ioapic_set_redirect(ioapic, 0, 0x20, apic_id); - // keyboard - ioapic_set_redirect(ioapic, 1, 0x21, apic_id); - for (size_t vector = 0; vector < 32; vector++) { setup_interrupt_gate(vector, exception_handler, INTERRUPT_64_GATE, 0, 0); } // we have interrupt after 31 since 0-31 are reserved for errors - setup_interrupt_gate(0x20, timer_handler, INTERRUPT_64_GATE, 0, 0); - setup_interrupt_gate(0x21, keyboard_handler, INTERRUPT_64_GATE, 0, 0); - setup_interrupt_gate(0x80, trap, TRAP_64_GATE, 3, 1); + setup_interrupt_gate(0x20, apic_timer_handler, INTERRUPT_64_GATE, 0, 0); + //setup_interrupt_gate(0x21, keyboard_handler, INTERRUPT_64_GATE, 0, 0); + + // PIT + ioapic_set_redirect(ioapic, 0, 0x23, apic_id); + pit_init(3200); + setup_interrupt_gate(0x23, pit_handler, INTERRUPT_64_GATE, 0, 0); + + setup_interrupt_gate(0x80, trap, TRAP_64_GATE, 3, 1); + keyboard_init(ioapic); + mouse_init(ioapic); load_idt(); }