diff --git a/kernel/pci/qemu_pci_serial/qemu_pci_serial.c b/kernel/pci/qemu_pci_serial/qemu_pci_serial.c index e33f651..af20cfc 100644 --- a/kernel/pci/qemu_pci_serial/qemu_pci_serial.c +++ b/kernel/pci/qemu_pci_serial/qemu_pci_serial.c @@ -6,6 +6,8 @@ #include "sysdefs/dev.h" #include "util/util.h" #include "dev/dev.h" +#include "cjob/cjob.h" +#include "proc/proc.h" #include "errors.h" #include "hshtb.h" #include "kprintf.h" @@ -53,6 +55,11 @@ int32_t qemu_pci_serial_dev_sendb(struct Dev *dev, uint8_t *buffer, size_t len, (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; + + if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) { + return E_DEVLOCKED; + } + _serial_sendb(qpsd->iobase, buffer[0]); return E_OK; @@ -62,6 +69,10 @@ int32_t qemu_pci_serial_dev_sendready(struct Dev *dev, uint8_t *buffer, size_t l (void)buffer; (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; + + if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) { + return E_DEVLOCKED; + } return _serial_sendready(qpsd->iobase); } @@ -70,16 +81,75 @@ int32_t qemu_pci_serial_dev_recvb(struct Dev *dev, uint8_t *buffer, size_t len, (void)buffer; (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; + + if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) { + return E_DEVLOCKED; + } return _serial_recvb(qpsd->iobase); } int32_t qemu_pci_serial_dev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { - (void)dev; (void)buffer; (void)len; (void)pid; + (void)buffer; (void)len; (void)pid; + + QemuPciSerialDev *qpsd = dev->extra; + + if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) { + return E_DEVLOCKED; + } + + return _serial_recvready(qpsd->iobase); +} + +int32_t qemu_pci_serial_dev_lock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { + (void)buffer; (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; - return _serial_recvready(qpsd->iobase); + if (qpsd->lockstate == (int)pid) { + return E_OK; + } + + if (qpsd->lockstate == -1) { + qpsd->lockstate = (int)pid; + return E_OK; + } + return E_DEVLOCKED; +} + +int32_t qemu_pci_serial_dev_unlock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { + (void)buffer; (void)len; (void)pid; + + QemuPciSerialDev *qpsd = dev->extra; + + if (qpsd->lockstate == (int)pid) { + qpsd->lockstate = -1; + return E_OK; + } + return E_DEVNOTYOURLOCK; +} + +void pci_qemu_pci_serial_gc_cjob(void *arg) { + Dev *dev = arg; + + QemuPciSerialDev *qpsd; + + spinlock_acquire(&dev->spinlock); + qpsd = dev->extra; + uint64_t pid = qpsd->lockstate; + spinlock_release(&dev->spinlock); + + Proc *proc = NULL; + spinlock_acquire(&PROCS.spinlock); + LL_FINDPROP(PROCS.procs, proc, pid, pid); + spinlock_release(&PROCS.spinlock); + + if (proc == NULL) { + spinlock_acquire(&dev->spinlock); + qpsd = dev->extra; + qpsd->lockstate = -1; + spinlock_release(&dev->spinlock); + } } void pci_qemu_pci_serial_init(void) { @@ -97,6 +167,7 @@ void pci_qemu_pci_serial_init(void) { QEMU_PCI_SERIAL_DEV._magic = QEMU_PCI_SERIAL_MAGIC; QEMU_PCI_SERIAL_DEV.iobase = iobase; + QEMU_PCI_SERIAL_DEV.lockstate = -1; Dev *serialdev = NULL; HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev); @@ -104,8 +175,13 @@ void pci_qemu_pci_serial_init(void) { serialdev->fns[1] = &qemu_pci_serial_dev_sendready; serialdev->fns[2] = &qemu_pci_serial_dev_recvb; serialdev->fns[3] = &qemu_pci_serial_dev_recvready; + serialdev->fns[4] = &qemu_pci_serial_dev_lock; + serialdev->fns[5] = &qemu_pci_serial_dev_unlock; spinlock_init(&serialdev->spinlock); serialdev->extra = &QEMU_PCI_SERIAL_DEV; + + cjob_register(&pci_qemu_pci_serial_gc_cjob, serialdev); + _serial_init(QEMU_PCI_SERIAL_DEV.iobase); } diff --git a/kernel/pci/qemu_pci_serial/qemu_pci_serial.h b/kernel/pci/qemu_pci_serial/qemu_pci_serial.h index 1dcb872..765c0c3 100644 --- a/kernel/pci/qemu_pci_serial/qemu_pci_serial.h +++ b/kernel/pci/qemu_pci_serial/qemu_pci_serial.h @@ -9,6 +9,7 @@ typedef struct { uint32_t _magic; uint16_t iobase; + int lockstate; } QemuPciSerialDev; void pci_qemu_pci_serial_init(void); diff --git a/share/errors.h b/share/errors.h index 3ce76ae..373eed9 100644 --- a/share/errors.h +++ b/share/errors.h @@ -17,6 +17,8 @@ #define E_SPAWNERROR -13 #define E_NOTYET -14 #define E_MOUNTERR -15 +#define E_DEVLOCKED -16 +#define E_DEVNOTYOURLOCK -17 #if !defined(__ASSEMBLER__) @@ -38,6 +40,8 @@ static const char *_ERROR_STRINGS[] = { "Process spawn error", "Data isn't ready yet", "File system mount error", + "This device is locked", + "Device is hasn't been locked by this process", }; #define ERRSTRING_INDEX(ioh) ((size_t)((ioh) < 0 ? (ioh) * (-1) : (ioh)))