quinn-os/syscalls.c
2017-10-08 11:10:14 +10:00

276 lines
6.8 KiB
C

#include "schedule.h"
#include "syscalls.h"
#include "interrupts.h"
#include "vfs.h"
#include "gui.h"
#include "rtc.h"
#include "execve.h"
#include "memory.h"
#include "ether.h"
#include "socket.h"
extern struct task_t *current_task;
extern unsigned long timer_ticks;
struct window_req_t {
int x;
int y;
char name[128];
int width;
int height;
unsigned int flags;
char *icon;
};
struct window_blit_req_t {
int wh;
int x;
int y;
int w;
int h;
char *bmp;
};
struct socket_rcv_t {
char *buffer;
int len;
unsigned int *addr;
};
void sys_exit(struct regs *r) {
unsigned int *status;
unsigned int *wait_return;
unsigned int *u;
int i;
current_task->timetorun = 0;
current_task->state = TASK_ZOMBIE;
current_task->exit_status = r->ebx;
current_task->zombie_ttl = 5;
if (current_task->parent_task != (void *)0) {
if (current_task->parent_task->state == TASK_WAITING) {
wait_return = (unsigned int *)(current_task->parent_task->esp + 44);
status = (unsigned int *)(current_task->parent_task->esp + 32);
*wait_return = current_task->pid;
*status = current_task->exit_status;
current_task->parent_task->state = TASK_RUNNING;
current_task->state = TASK_FINISHED;
}
}
schedule(r);
}
int sys_fork(struct regs *r) {
struct task_t *new_task = sched_new_task();
unsigned int *stack_setup = (unsigned int *)new_task->esp;
*--stack_setup = r->ss;
*--stack_setup = r->useresp;
*--stack_setup = r->eflags;
*--stack_setup = r->cs;
*--stack_setup = r->eip;
*--stack_setup = 0;
*--stack_setup = 0;
*--stack_setup = 0; //EAX
*--stack_setup = r->ecx; //ECX
*--stack_setup = r->edx; //EDX
*--stack_setup = r->ebx; //EBX
*--stack_setup = 0; //Just an offset, no value
*--stack_setup = r->ebp; //EBP
*--stack_setup = r->esi; //ESI
*--stack_setup = r->edi; //EDI
*--stack_setup = r->ds; //DS
*--stack_setup = r->es; //ES
*--stack_setup = r->fs; //FS
*--stack_setup = r->gs; //GS
new_task->esp = (unsigned int)stack_setup;
new_task->state = TASK_RUNNING;
return new_task->pid;
}
void syscall_isr(struct regs *r) {
switch (r->eax) {
case SYS_EXIT:
sys_exit(r);
break;
case SYS_FORK:
r->eax = sys_fork(r);
break;
case SYS_CLOSE:
vfs_close_file(r->ebx);
break;
case SYS_GETPID:
r->eax = current_task->pid;
break;
case SYS_READ:
r->eax = vfs_read_file((int)r->ebx, (char *)r->ecx, (int) r->edx);
break;
case SYS_OPEN:
r->eax = vfs_open_file((char *)r->ebx, (int)r->ecx, (int)r->edx);
break;
case SYS_WRITE:
r->eax = vfs_write_file((int)r->ebx, (char *)r->ecx, r->edx);
break;
case SYS_ISATTY:
if (current_task->filehandles[(int)r->ebx].device != (void *)0) {
r->eax = (current_task->filehandles[(int)r->ebx].device->device == 0 ? 1 : 0);
} else {
r->eax = 0;
}
break;
case SYS_SBRK:
r->eax = mem_usr_sbrk((int)r->ebx);
break;
case SYS_LSEEK:
r->eax = vfs_lseek((int)r->ebx, (unsigned long long)r->ecx, (int)r->edx);
break;
case SYS_EXECVE:
r->eax = execve(r, (char *)r->ebx, (char **)r->ecx, (char **)r->edx);
break;
case SYS_SELECTDEV:
r->eax = vfs_select_device((char *)r->ebx);
break;
case SYS_GETDENTS:
r->eax = vfs_getdents((int)r->ebx, (char *)r->ecx, (int)r->edx);
break;
case SYS_STAT:
r->eax = vfs_stat((char *)r->ebx, (struct stat*)r->ecx);
break;
case SYS_FSTAT:
r->eax = vfs_fstat((int)r->ebx, (struct stat *)r->ecx);
break;
case SYS_UNLINK:
r->eax = vfs_unlink((char *)r->ebx);
break;
case SYS_WAIT:
wait(r);
break;
case SYS_GETTIME:
r->eax = rtc_get_time();
break;
case SYS_MKDIR:
r->eax = vfs_mkdir((char *)r->ebx);
break;
case SYS_CHDIR:
r->eax = vfs_change_directory((char *)r->ebx);
break;
case SYS_WINDOW_REQ:
{
struct window_req_t *req = (struct window_req_t *)r->ebx;
r->eax = gui_add_window((void *)0, req->name, req->x, req->y, req->width, req->height, req->icon, req->flags, (void *)0);
}
break;
case SYS_WINDOW_BLIT:
{
struct window_blit_req_t *req = (struct window_blit_req_t *)r->ebx;
r->eax = gui_blit(req->wh, req->x, req->y, req->w, req->h, req->bmp);
}
break;
case SYS_WINDOW_INPUT:
{
struct window_update_req *req = (struct window_update_req *)r->ecx;
r->eax = gui_req_input((int)r->ebx, req);
}
break;
case SYS_WINDOW_WALLPAPER:
{
r->eax = gui_set_wallpaper((char *)r->ecx, (int)r->ebx);
}
break;
case SYS_WINDOW_DESTROY:
gui_destroy_window((int)r->ebx, current_task);
break;
case SYS_WINDOW_CAPTION:
r->eax = gui_change_window_caption((int)r->ebx, (char *)r->ecx);
break;
case SYS_YIELD:
yield(r);
break;
case SYS_SEM_NEW:
sched_sem_new((unsigned char)r->ebx);
break;
case SYS_SEM_FREE:
sched_sem_free((unsigned int)r->ebx);
break;
case SYS_SEM_SIG:
sched_sem_signal((unsigned int)r->ebx, (unsigned char)r->ecx);
break;
case SYS_SEM_WAIT:
sched_sem_wait(r, (unsigned int)r->ebx, (int)r->ecx);
break;
case SYS_ETHER_UP:
r->eax = ether_enable((int)r->ebx, (unsigned int)r->ecx, (unsigned int)r->edx);
break;
case SYS_ETHER_DFGW:
r->eax = ether_add_default_gw((int)r->ebx, (unsigned int)r->ecx);
break;
case SYS_SOCK_OPEN:
r->eax = (unsigned int)socket_open((unsigned char)r->ebx);
break;
case SYS_SOCK_CONNECT:
r->eax = (unsigned int)socket_connect((struct socket_t *)r->ebx, (unsigned int)r->ecx, (unsigned short)r->edx);
break;
case SYS_SOCK_STATUS:
r->eax = socket_status((struct socket_t *)r->ebx);
break;
case SYS_SOCK_CLOSE:
socket_close((struct socket_t *)r->ebx);
break;
case SYS_SOCK_READ:
r->eax = socket_read((struct socket_t *)r->ebx, (char *)r->ecx, r->edx);
if (r->eax == -1) {
schedule(r);
}
break;
case SYS_SOCK_WRITE:
r->eax = socket_write((struct socket_t*)r->ebx, (unsigned char*)r->ecx, r->edx);
break;
case SYS_SOCK_LISTEN:
r->eax = socket_listen((struct socket_t *)r->ebx, (unsigned int)r->ecx, (unsigned short)r->edx);
break;
case SYS_SOCK_ACCEPT:
r->eax = (unsigned int)socket_accept((struct socket_t *)r->ebx, (struct inet_addr *)r->ecx);
if (r->eax == (void *)0) {
schedule(r);
}
break;
case SYS_MEM_INFO:
r->eax = mem_get_info((struct mem_info *)r->ebx);
break;
case SYS_PIPE:
r->eax = vfs_pipe((int *)r->ebx);
break;
case SYS_DUP:
r->eax = vfs_dup((int)r->ebx);
break;
case SYS_SOCK_BIND:
r->eax = (unsigned int)socket_bind((struct socket_t *)r->ebx, (unsigned int)r->ecx, (unsigned short)r->edx);
break;
case SYS_SOCK_RECV_FROM:
{
struct socket_rcv_t *srecv = (struct socket_recv_t *)r->ecx;
r->eax = (unsigned int)socket_recv_from((struct socket_t *)r->ebx, srecv->buffer, srecv->len, srecv->addr);
}
break;
case SYS_GET_TICKS:
r->eax = timer_ticks;
break;
}
}
void init_syscalls() {
irq_install_handler(0x10, syscall_isr, 0);
}