#include "./syscall.h" #include "../drivers/ps2/ps2.h" #include "../io/io.h" #include "../pci/pci.h" #include "../scheduler/scheduler.h" #ifdef ARCH_I386 #include "../../arch/i386/syscall.h" #endif enum syscall_type_d { SYSCALL_yield, SYSCALL_getc, SYSCALL_exit, SYSCALL_lspci, SYSCALL_lsproc, SYSCALL_powerctl }; void powerctl(uint32_t power_mode) { // TODO: Add reboot mode when ACPI is done INVOKE_SYSCALL(SYSCALL_powerctl); } void yield() { INVOKE_SYSCALL(SYSCALL_yield); } char getc() { INVOKE_SYSCALL(SYSCALL_getc); char result; __asm__ volatile("movb %%al, %0" : "=r"(result)); return result; } uint32_t lspci(struct pci_device *devlist, uint32_t len) { int result = 0; __asm__ volatile("movl %0, %%ebx" : : "r"((uint32_t)devlist) : "%ebx"); __asm__ volatile("movl %0, %%ecx" : : "r"(len) : "%ecx"); INVOKE_SYSCALL(SYSCALL_lspci); __asm__ volatile("movl %%eax, %k0" : "=r"(result)); return result; } uint32_t lsproc(struct task_struct *proclist, uint32_t len) { int result = 0; __asm__ volatile("movl %0, %%ebx" : : "r"((uint32_t)proclist) : "%ebx"); __asm__ volatile("movl %0, %%ecx" : : "r"(len) : "%ecx"); INVOKE_SYSCALL(SYSCALL_lsproc); __asm__ volatile("movl %%eax, %k0" : "=r"(result)); return result; } void __syscall_powerctl() { // TODO: Implement properly printf_nolock("Attempting shutdown using hypervisor-specific methods."); printf_nolock("ACPI is not yet supported."); outw(0x604, 0x2000); outw(0x4004, 0x3400); outw(0x600, 0x34); outw(0xB004, 0x2000); } void __syscall_yield(struct regs *r) { // for now, just reschedule // TODO: reset PIT timer so // next process doesn't get an // unreasonably small quantum schedule(r); } void syscall(struct regs *r) { int syscall_no = r->eax; switch (syscall_no) { case SYSCALL_powerctl: { __syscall_powerctl(); break; }; case SYSCALL_yield: { __syscall_yield(r); break; }; case SYSCALL_getc: { process_table[current_pid].state = TASKSTATE_blocked; for (uint32_t i = 0; i < MAX_PROCESSES; i++) { if (!ps2_waiters[i].alloc) { ps2_waiters[i].alloc = 1; ps2_waiters[i].pid = current_pid; break; } } __syscall_yield(r); break; }; case SYSCALL_lspci: { uint32_t len = r->ecx; len = len < pci_devices_count ? len : pci_devices_count; struct pci_device *devlist = (struct pci_device *)r->ebx; for (uint32_t i = 0; i < len; ++i) { devlist[i] = pci_devices_list[i]; } r->eax = len; break; }; case SYSCALL_lsproc: { uint32_t len = r->ecx; struct task_struct *proclist = (struct task_struct *)r->ebx; uint32_t i = 0, j = 0; for (; i < len; ++i, ++j) { for (; j < MAX_PROCESSES && process_table[j].state == TASKSTATE_unused; ++j) { } if (j == MAX_PROCESSES) break; proclist[i] = process_table[j]; } r->eax = i; break; }; case SYSCALL_exit: { process_table[current_pid].state = TASKSTATE_unused; __syscall_yield(r); break; }; } }