#include #include #include "kprintf.h" #include "syscall.h" #include "errors.h" #include "spinlock/spinlock.h" #include "proc/proc.h" #include "sysdefs/devctl.h" #include "util/util.h" #include "hshtb.h" #include "dev/dev.h" int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1) { uint64_t *devh = (uint64_t *)devh1; uint64_t cmd = cmd1; int32_t ret = E_OK; spinlock_acquire(&PROCS.spinlock); Proc *proc = PROCS.current; spinlock_release(&PROCS.spinlock); switch (cmd) { case DEVCTL_GET_HANDLE: { char *ident = (char *)buffer1; 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; } } break; default: { 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]((uint8_t *)buffer1, (size_t)len1, (void *)extra1); spinlock_release(&dev->spinlock); } break; } done: return ret; }