diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/acpi/acpi.c | 221 | ||||
-rw-r--r-- | src/kernel/acpi/acpi.h | 10 | ||||
-rw-r--r-- | src/kernel/apm/apm.asm | 37 | ||||
-rw-r--r-- | src/kernel/apm/apm.c | 5 | ||||
-rw-r--r-- | src/kernel/apm/apm.h | 10 | ||||
-rw-r--r-- | src/kernel/boot.asm | 4 | ||||
-rw-r--r-- | src/kernel/commands/command.c | 6 | ||||
-rw-r--r-- | src/kernel/graphics/vesa.c | 3 | ||||
-rw-r--r-- | src/kernel/graphics/vga.c | 16 | ||||
-rw-r--r-- | src/kernel/input/ps2/keyboard.c | 2 | ||||
-rw-r--r-- | src/kernel/input/ps2/mouse.c | 26 | ||||
-rw-r--r-- | src/kernel/interrupts/irq.c | 24 | ||||
-rw-r--r-- | src/kernel/io/io.c | 36 | ||||
-rw-r--r-- | src/kernel/io/io.h | 12 | ||||
-rw-r--r-- | src/kernel/kernel.c | 3 | ||||
-rw-r--r-- | src/kernel/sound/frequency.c | 14 | ||||
-rw-r--r-- | src/kernel/timer/timer.c | 8 |
17 files changed, 314 insertions, 123 deletions
diff --git a/src/kernel/acpi/acpi.c b/src/kernel/acpi/acpi.c new file mode 100644 index 0000000..e307a6f --- /dev/null +++ b/src/kernel/acpi/acpi.c @@ -0,0 +1,221 @@ +#include "../graphics/graphics.h" +#include "../io/io.h" +#include "../lib/lib.h" +#include "../timer/timer.h" +#include <stddef.h> + +uint32_t *SMI_CMD; +char ACPI_ENABLE; +char ACPI_DISABLE; +uint32_t *PM1a_CNT; +uint32_t *PM1b_CNT; +int SLP_TYPa; +int SLP_TYPb; +int SLP_EN; +int SCI_EN; +char PM1_CNT_LEN; + +struct RSDPtr { + char Signature[8]; + char CheckSum; + char OemID[6]; + char Revision; + uint32_t *RsdtAddress; +}; + +struct FACP { + char Signature[4]; + uint32_t Length; + char unneded1[40 - 8]; + uint32_t *DSDT; + char unneded2[48 - 44]; + uint32_t *SMI_CMD; + char ACPI_ENABLE; + char ACPI_DISABLE; + char unneded3[64 - 54]; + uint32_t *PM1a_CNT_BLK; + uint32_t *PM1b_CNT_BLK; + char unneded4[89 - 72]; + char PM1_CNT_LEN; +}; + +unsigned int *acpi_check_rsd_ptr(unsigned int *ptr) { + char *sig = "RSD PTR "; + struct RSDPtr *rsdp = (struct RSDPtr *) ptr; + char *bptr; + char check = 0; + int i; + + if (memory_compare(sig, rsdp, 8) == 0) { + bptr = (char *) ptr; + for (i = 0; i < sizeof(struct RSDPtr); i++) { + check += *bptr; + bptr++; + } + + if (check == 0) { + return (unsigned int *) rsdp->RsdtAddress; + } + } + + return NULL; +} + +unsigned int *acpi_get_rsd_ptr() { + unsigned int *addr; + unsigned int *rsdp; + + for (addr = (unsigned int *) 0x000E0000; (int) addr < 0x00100000; addr += 0x10 / sizeof(addr)) { + rsdp = acpi_check_rsd_ptr(addr); + if (rsdp != NULL) + return rsdp; + } + + int ebda = *((short *) 0x40E); + ebda = ebda * 0x10 & 0x000FFFFF; + + for (addr = (unsigned int *) ebda; (int) addr < ebda + 1024; addr += 0x10 / sizeof(addr)) { + rsdp = acpi_check_rsd_ptr(addr); + if (rsdp != NULL) + return rsdp; + } + + return NULL; +} + +int acpi_check_header(unsigned int *ptr, char *sig) { + if (memory_compare(ptr, sig, 4) == 0) { + char *checkPtr = (char *) ptr; + int len = *(ptr + 1); + char check = 0; + while (0 < len--) { + check += *checkPtr; + checkPtr++; + } + if (check == 0) + return 0; + } + return -1; +} + +int acpi_enable() { + if ((receive_w((unsigned int) PM1a_CNT) & SCI_EN) == 0) { + if (SMI_CMD != 0 && ACPI_ENABLE != 0) { + send_b((unsigned int) SMI_CMD, ACPI_ENABLE); // Enable ACPI + // Try 3s until ACPI is enabled + int i; + for (i = 0; i < 300; i++) { + if ((receive_w((unsigned int) PM1a_CNT) & SCI_EN) == 1) + break; + timer_wait(1); + } + if (PM1b_CNT != 0) + for (; i < 300; i++) { + if ((receive_w((unsigned int) PM1b_CNT) & SCI_EN) == 1) + break; + timer_wait(1); + } + if (i < 300) { + return 0; // Successfully enabled ACPI + } else { + return -1; // ACPI couldn't be enabled + } + } else { + return -1; // ACPI is not supported + } + } else { + return 0; // ACPI was already enabled + } +} + +int acpi_install() { + unsigned int *ptr = acpi_get_rsd_ptr(); + + if (ptr != NULL && acpi_check_header(ptr, "RSDT") == 0) { + int entrys = *(ptr + 1); + entrys = (entrys - 36) / 4; + ptr += 36 / 4; + + while (0 < entrys--) { + if (acpi_check_header((unsigned int *) *ptr, "FACP") == 0) { + entrys = -2; + struct FACP *facp = (struct FACP *) *ptr; + if (acpi_check_header((unsigned int *) facp->DSDT, "DSDT") == 0) { + char *S5Addr = (char *) facp->DSDT + 36; + int dsdtLength = *(facp->DSDT + 1) - 36; + while (0 < dsdtLength--) { + if (memory_compare(S5Addr, "_S5_", 4) == 0) + break; + S5Addr++; + } + if (dsdtLength > 0) { + if ((*(S5Addr - 1) == 0x08 || (*(S5Addr - 2) == 0x08 && *(S5Addr - 1) == '\\')) && + *(S5Addr + 4) == 0x12) { + S5Addr += 5; + S5Addr += ((*S5Addr & 0xC0) >> 6) + 2; + + if (*S5Addr == 0x0A) + S5Addr++; + SLP_TYPa = *(S5Addr) << 10; + S5Addr++; + + if (*S5Addr == 0x0A) + S5Addr++; + SLP_TYPb = *(S5Addr) << 10; + + SMI_CMD = facp->SMI_CMD; + + ACPI_ENABLE = facp->ACPI_ENABLE; + ACPI_DISABLE = facp->ACPI_DISABLE; + + PM1a_CNT = facp->PM1a_CNT_BLK; + PM1b_CNT = facp->PM1b_CNT_BLK; + + PM1_CNT_LEN = facp->PM1_CNT_LEN; + + SLP_EN = 1 << 13; + SCI_EN = 1; + + return 0; + } // Else: \_S5 parse error + } // Else: \_S5 not present + } // Else: DSDT invalid + } + ptr++; + } // Else: no valid FACP present + } // Else: No ACPI available + return -1; +} + +void acpi_poweroff() { + acpi_install(); + acpi_enable(); + + if (SCI_EN == 0) { + terminal_write_line("ACPI shutdown is not supported"); + return; + } + + // Send shutdown command + send_w((unsigned int) PM1a_CNT, SLP_TYPa | SLP_EN); + if (PM1b_CNT != 0) + send_w((unsigned int) PM1b_CNT, SLP_TYPb | SLP_EN); + else { + send_w(0xB004, 0x2000); // Bochs + send_w(0x604, 0x2000); // QEMU + send_w(0x4004, 0x3400); // VirtualBox + } + + terminal_write_line("Shutdown failed"); +} + +void reboot() { + asm volatile ("cli"); + uint8_t good = 0x02; + while (good & 0x02) + good = receive_b(0x64); + send_b(0x64, 0xFE); + loop: + asm volatile ("hlt"); + goto loop; +} diff --git a/src/kernel/acpi/acpi.h b/src/kernel/acpi/acpi.h new file mode 100644 index 0000000..6db7e72 --- /dev/null +++ b/src/kernel/acpi/acpi.h @@ -0,0 +1,10 @@ +#ifndef MELVIX_ACPI_H +#define MELVIX_ACPI_H + +int acpi_install(); + +void reboot(); + +void acpi_poweroff(); + +#endif diff --git a/src/kernel/apm/apm.asm b/src/kernel/apm/apm.asm deleted file mode 100644 index e39cc84..0000000 --- a/src/kernel/apm/apm.asm +++ /dev/null @@ -1,37 +0,0 @@ -global apm_check -global apm_connect -global apm_poweroff -global apm_sleep - -extern apm_error - -apm_check: - mov ah,53h - mov al,00h - xor bx,bx - int 15h - jc apm_error - ret - -apm_connect: - mov ah, 53h - mov al, 03h - xor bx, bx - int 15h - jc apm_error - -apm_poweroff: - mov ah, 53h - mov al, 07h - mov bx, 0001h - mov cx, 03h - int 15h - jc apm_error - -apm_sleep: - mov ah, 53h - mov al, 07h - mov bx, 0001h - mov cx, 01h - int 15h - jc apm_error
\ No newline at end of file diff --git a/src/kernel/apm/apm.c b/src/kernel/apm/apm.c deleted file mode 100644 index ce25da8..0000000 --- a/src/kernel/apm/apm.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "../graphics/graphics.h" - -void apm_error() { - terminal_write_line("APM has errors."); -}
\ No newline at end of file diff --git a/src/kernel/apm/apm.h b/src/kernel/apm/apm.h deleted file mode 100644 index 38deb3d..0000000 --- a/src/kernel/apm/apm.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef MELVIX_APM_H -#define MELVIX_APM_H - -extern void apm_poweroff(); - -extern void apm_sleep(); - -void apm_error(); - -#endif diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm index 4dccebb..5ee93f0 100644 --- a/src/kernel/boot.asm +++ b/src/kernel/boot.asm @@ -42,9 +42,7 @@ stublet: %include "src/kernel/interrupts/irq.asm" -%include "src/kernel/apm/apm.asm" - -%include "src/kernel/graphics/vesa.asm" +; %include "src/kernel/graphics/vesa.asm" ; Store the stack SECTION .bss diff --git a/src/kernel/commands/command.c b/src/kernel/commands/command.c index 2aeae73..c673b44 100644 --- a/src/kernel/commands/command.c +++ b/src/kernel/commands/command.c @@ -1,7 +1,7 @@ #include "../graphics/graphics.h" #include "../lib/lib.h" #include "../io/io.h" -#include "../apm/apm.h" +#include "../acpi/acpi.h" int32_t starts_with(const char *a, const char *b) { size_t length_pre = strlen(b); @@ -17,9 +17,9 @@ void exec_command(char *command) { else if (starts_with(command, "ping")) terminal_write_line("pong!"); else if (starts_with(command, "shutdown")) - apm_poweroff(); + acpi_poweroff(); else if (starts_with(command, "zzz")) - apm_sleep(); + terminal_write_line("Not implemented"); else if (starts_with(command, "reboot")) reboot(); else diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index b178645..0a121e5 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -1,7 +1,6 @@ #include "graphics.h" -extern char *find_mode(); void vesa_init() { - terminal_write_line(find_mode()); + terminal_write_line("Init"); }
\ No newline at end of file diff --git a/src/kernel/graphics/vga.c b/src/kernel/graphics/vga.c index 86c00ff..a72ea91 100644 --- a/src/kernel/graphics/vga.c +++ b/src/kernel/graphics/vga.c @@ -53,18 +53,18 @@ void terminal_clear() { } void terminal_enable_cursor(uint8_t cursor_start, uint8_t cursor_end) { - send(0x3D4, 0x0A); - send(0x3D5, (receive(0x3D5) & 0xC0) | cursor_start); - send(0x3D4, 0x0B); - send(0x3D5, (receive(0x3D5) & 0xE0) | cursor_end); + send_b(0x3D4, 0x0A); + send_b(0x3D5, (receive_b(0x3D5) & 0xC0) | cursor_start); + send_b(0x3D4, 0x0B); + send_b(0x3D5, (receive_b(0x3D5) & 0xE0) | cursor_end); } void terminal_update_cursor(void) { unsigned temp = terminal_row * VGA_WIDTH + terminal_column; - send(0x3D4, 14); - send(0x3D5, temp >> 8); - send(0x3D4, 15); - send(0x3D5, temp); + send_b(0x3D4, 14); + send_b(0x3D5, temp >> 8); + send_b(0x3D4, 15); + send_b(0x3D5, temp); } void terminal_initialize(void) { diff --git a/src/kernel/input/ps2/keyboard.c b/src/kernel/input/ps2/keyboard.c index ae17675..c40f1f5 100644 --- a/src/kernel/input/ps2/keyboard.c +++ b/src/kernel/input/ps2/keyboard.c @@ -35,7 +35,7 @@ unsigned char keymap[128] = { void keyboard_handler(struct regs *r) { unsigned char scan_code; - scan_code = receive(0x60); + scan_code = receive_b(0x60); if (scan_code & 0x80) { // Release diff --git a/src/kernel/input/ps2/mouse.c b/src/kernel/input/ps2/mouse.c index 49c5a6c..54d8a3c 100644 --- a/src/kernel/input/ps2/mouse.c +++ b/src/kernel/input/ps2/mouse.c @@ -12,15 +12,15 @@ int mm_n[3] = {0, 0, 0,}; void mouse_handler(struct regs *a_r) { switch (mouse_cycle) { case 0: - mouse_byte[0] = receive(0x60); + mouse_byte[0] = receive_b(0x60); mouse_cycle++; break; case 1: - mouse_byte[1] = receive(0x60); + mouse_byte[1] = receive_b(0x60); mouse_cycle++; break; case 2: - mouse_byte[2] = receive(0x60); + mouse_byte[2] = receive_b(0x60); mouse_x = mouse_byte[1]; mouse_y = mouse_byte[2]; mouse_but_1 = (mouse_byte[0] % 2); @@ -42,14 +42,14 @@ inline void mouse_wait(char a_type) { unsigned int _time_out = 100000; if (a_type == 0) { while (_time_out--) { - if ((receive(0x64) & 1) == 1) { + if ((receive_b(0x64) & 1) == 1) { return; } } return; } else { while (_time_out--) { - if ((receive(0x64) & 2) == 0) { + if ((receive_b(0x64) & 2) == 0) { return; } } @@ -59,14 +59,14 @@ inline void mouse_wait(char a_type) { inline void mouse_write(char a_write) { mouse_wait(1); - send(0x64, 0xD4); + send_b(0x64, 0xD4); mouse_wait(1); - send(0x60, a_write); + send_b(0x60, a_write); } char mouse_read() { mouse_wait(0); - return receive(0x60); + return receive_b(0x60); } void mouse_install() { @@ -74,17 +74,17 @@ void mouse_install() { // Enable auxiliary mouse device mouse_wait(1); - send(0x64, 0xA8); + send_b(0x64, 0xA8); // Enable interrupts mouse_wait(1); - send(0x64, 0x20); + send_b(0x64, 0x20); mouse_wait(0); - _status = (receive(0x60) | 2); + _status = (receive_b(0x60) | 2); mouse_wait(1); - send(0x64, 0x60); + send_b(0x64, 0x60); mouse_wait(1); - send(0x60, _status); + send_b(0x60, _status); // Use default settings mouse_write(0xF6); diff --git a/src/kernel/interrupts/irq.c b/src/kernel/interrupts/irq.c index cf9e1fe..834b192 100644 --- a/src/kernel/interrupts/irq.c +++ b/src/kernel/interrupts/irq.c @@ -56,16 +56,16 @@ int irq_is_installed(int irq) { // Remap IRQs for protected mode compatibility via the PIC void irq_remap(void) { - send(0x20, 0x11); - send(0xA0, 0x11); - send(0x21, 0x20); - send(0xA1, 0x28); - send(0x21, 0x04); - send(0xA1, 0x02); - send(0x21, 0x01); - send(0xA1, 0x01); - send(0x21, 0x0); - send(0xA1, 0x0); + send_b(0x20, 0x11); + send_b(0xA0, 0x11); + send_b(0x21, 0x20); + send_b(0xA1, 0x28); + send_b(0x21, 0x04); + send_b(0xA1, 0x02); + send_b(0x21, 0x01); + send_b(0xA1, 0x01); + send_b(0x21, 0x0); + send_b(0xA1, 0x0); } // Map ISRs to the correct entries in the IDT @@ -101,9 +101,9 @@ void irq_handler(struct regs *r) { // Send end of interrupt to second (slave) IRQ controller if (r->int_no >= 40) { - send(0xA0, 0x20); + send_b(0xA0, 0x20); } // Send end of interrupt to master interrupt controller - send(0x20, 0x20); + send_b(0x20, 0x20); } diff --git a/src/kernel/io/io.c b/src/kernel/io/io.c index 7bddb13..74776ee 100644 --- a/src/kernel/io/io.c +++ b/src/kernel/io/io.c @@ -1,21 +1,31 @@ #include <stdint.h> -unsigned char receive(unsigned short port) { +uint8_t receive_b(uint16_t port) { unsigned char value; - __asm__ __volatile__ ("inb %1, %0" : "=a" (value) : "dN" (port)); + asm volatile ("inb %1, %0" : "=a"(value) : "Nd"(port)); return value; } -void send(unsigned short port, unsigned char data) { - __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data)); +uint16_t receive_w(uint16_t port) { + unsigned char value; + asm volatile("inb %1,%0" : "=a"(value) : "Nd"(port)); // TODO: Fix inw error + return value; +} + +uint32_t receive_l(uint16_t port) { + unsigned char value; + asm volatile ("inb %1, %0" : "=a"(value) : "Nd"(port)); + return value; } -void reboot() { - uint8_t good = 0x02; - while (good & 0x02) - good = receive(0x64); - send(0x64, 0xFE); - loop: - asm volatile ("hlt"); - goto loop; -}
\ No newline at end of file +void send_b(uint16_t port, uint8_t data) { + asm volatile ("outb %0, %1"::"a" (data), "Nd"(port)); +} + +void send_w(uint16_t port, uint16_t data) { + asm volatile ("outw %0, %1"::"a" (data), "Nd"(port)); +} + +void send_l(uint16_t port, uint32_t data) { + asm volatile ("outl %0, %1"::"a" (data), "Nd"(port)); +} diff --git a/src/kernel/io/io.h b/src/kernel/io/io.h index e00a5f0..22776ee 100644 --- a/src/kernel/io/io.h +++ b/src/kernel/io/io.h @@ -3,10 +3,16 @@ #include <stdint.h> -unsigned char receive(unsigned short port); +uint8_t receive_b(uint16_t port); -void send(unsigned short port, unsigned char data); +uint16_t receive_w(uint16_t port); -void reboot(); +uint32_t receive_l(uint16_t port); + +void send_b(uint16_t port, uint8_t data); + +void send_w(uint16_t port, uint16_t data); + +void send_l(uint16_t port, uint32_t data); #endif diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index fb180ae..4ef53c0 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -6,13 +6,12 @@ #include "sound/sound.h" void kernel_main(void) { + asm volatile ("sti"); gdt_install(); idt_install(); isrs_install(); irq_install(); - __asm__ __volatile__ ("sti"); - terminal_initialize(); vesa_init(); terminal_write_string("Melvix loaded successfully!\n"); diff --git a/src/kernel/sound/frequency.c b/src/kernel/sound/frequency.c index 6d02690..fdc32e4 100644 --- a/src/kernel/sound/frequency.c +++ b/src/kernel/sound/frequency.c @@ -7,20 +7,20 @@ static void play_sound(uint32_t frequency) { uint8_t tmp; divided = 1193180 / frequency; - send(0x43, 0xb6); - send(0x42, (uint8_t) (divided)); - send(0x42, (uint8_t) (divided >> 8)); + send_b(0x43, 0xb6); + send_b(0x42, (uint8_t) (divided)); + send_b(0x42, (uint8_t) (divided >> 8)); - tmp = receive(0x61); + tmp = receive_b(0x61); if (tmp != (tmp | 3)) { - send(0x61, tmp | 3); + send_b(0x61, tmp | 3); } } static void shut_up() { - uint8_t tmp = receive(0x61) & 0xFC; + uint8_t tmp = receive_b(0x61) & 0xFC; - send(0x61, tmp); + send_b(0x61, tmp); } //Make a beep diff --git a/src/kernel/timer/timer.c b/src/kernel/timer/timer.c index 38f5be6..45b254e 100644 --- a/src/kernel/timer/timer.c +++ b/src/kernel/timer/timer.c @@ -5,9 +5,9 @@ volatile unsigned int timer_ticks = 0; void timer_phase(int hz) { int divisor = 1193180 / hz; - send(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD - send(0x40, divisor & 0xFF); - send(0x40, divisor >> 8); + send_b(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD + send_b(0x40, divisor & 0xFF); + send_b(0x40, divisor >> 8); } // Executed 100 times per second @@ -21,7 +21,7 @@ void timer_wait(int ticks) { eticks = timer_ticks + ticks; while (timer_ticks < eticks) { - __asm__ __volatile__ ("sti//hlt//cli"); + asm volatile ("sti//hlt//cli"); } } |