#include #include #include "kprintf.h" #include "syscall.h" #include "errors.h" #include "spinlock/spinlock.h" #include "proc/proc.h" #include "sysdefs/dev.h" #include "util/util.h" #include "hshtb.h" #include "dev/dev.h" int32_t SYSCALL2(sys_dev_gethandle, dev1, devname1) { uint64_t *devh = (uint64_t *)dev1; int32_t ret = E_OK; spinlock_acquire(&PROCS.spinlock); Proc *proc = NULL; LL_FINDPROP(PROCS.procs, proc, pid, _caller_pid); spinlock_release(&PROCS.spinlock); char *ident = (char *)devname1; if (ident == NULL) { ret = E_INVALIDARGUMENT; goto done; } spinlock_acquire(&DEVTABLE.spinlock); Dev *founddev; HSHTB_GET(DEVTABLE.devs, ident, ident, founddev); spinlock_release(&DEVTABLE.spinlock); if (founddev == NULL) { ret = E_NOENTRY; goto done; } bool found = false; for (size_t i = 0; i < PROC_DEVHANDLES_MAX; i++) { if (proc->devs[i] == NULL) { found = true; proc->devs[i] = founddev; *devh = i; break; } } if (!found) { ret = E_NOMEMORY; goto done; } done: return ret; } int32_t SYSCALL0(sys_dev_listsize) { int32_t ret = E_OK; size_t n = 0; spinlock_acquire(&DEVTABLE.spinlock); for (size_t i = 0; i < LEN(DEVTABLE.devs); i++) { if (DEVTABLE.devs[i]._hshtbstate == HSHTB_TAKEN) { n++; } } spinlock_release(&DEVTABLE.spinlock); ret = n; return ret; } int32_t SYSCALL2(sys_dev_stat, devstat1, idx1) { int32_t ret = E_OK; DevStat *devstat = (DevStat *)devstat1; size_t idx = (size_t)idx1; if (devstat == NULL) { ret = E_INVALIDARGUMENT; goto done; } devstat->present = false; spinlock_acquire(&DEVTABLE.spinlock); for (size_t i = 0; i < LEN(DEVTABLE.devs); i++) { if (i == idx && DEVTABLE.devs[i]._hshtbstate == HSHTB_TAKEN) { Dev *dev = &DEVTABLE.devs[i]; hal_memcpy(devstat->name, dev->ident, sizeof(dev->ident)); for (size_t j = 0; j < DEV_FNS_MAX; j++) { if (dev->fns[j] != NULL) { devstat->nfns++; } } devstat->present = true; break; } } spinlock_release(&DEVTABLE.spinlock); done: return ret; } int32_t SYSCALL4(sys_dev_cmd, dev1, cmd1, argbuf1, len1) { uint64_t *devh = (uint64_t *)dev1; uint64_t cmd = cmd1; int32_t ret = E_OK; spinlock_acquire(&PROCS.spinlock); Proc *proc = NULL; LL_FINDPROP(PROCS.procs, proc, pid, _caller_pid); spinlock_release(&PROCS.spinlock); if (devh == NULL) { ret = E_INVALIDARGUMENT; goto done; } if (cmd >= DEV_FNS_MAX) { ret = E_INVALIDARGUMENT; goto done; } Dev *dev = proc->devs[*devh]; if (dev == NULL) { ret = E_NOENTRY; goto done; } spinlock_acquire(&dev->spinlock); ret = dev->fns[cmd](dev, (uint8_t *)argbuf1, (size_t)len1, _caller_pid); spinlock_release(&dev->spinlock); done: return ret; } int32_t SYSCALL1(sys_dev_delhandle, dev1) { uint64_t *devh = (uint64_t *)dev1; int32_t ret = E_OK; if (devh == NULL) { return E_NOMEMORY; } spinlock_acquire(&PROCS.spinlock); Proc *proc = NULL; LL_FINDPROP(PROCS.procs, proc, pid, _caller_pid); spinlock_release(&PROCS.spinlock); proc->devs[*devh] = NULL; return ret; }