qemu_pci_serial device locking/sync
This commit is contained in:
@ -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;
|
||||
@ -63,6 +70,10 @@ int32_t qemu_pci_serial_dev_sendready(struct Dev *dev, uint8_t *buffer, size_t l
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
|
||||
return E_DEVLOCKED;
|
||||
}
|
||||
|
||||
return _serial_sendready(qpsd->iobase);
|
||||
}
|
||||
|
||||
@ -71,17 +82,76 @@ int32_t qemu_pci_serial_dev_recvb(struct Dev *dev, uint8_t *buffer, size_t len,
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
PciDev dev = pci_getdev(0x1B36, 0x0002, -1);
|
||||
if (!dev.bits) {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
typedef struct {
|
||||
uint32_t _magic;
|
||||
uint16_t iobase;
|
||||
int lockstate;
|
||||
} QemuPciSerialDev;
|
||||
|
||||
void pci_qemu_pci_serial_init(void);
|
||||
|
||||
@ -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)))
|
||||
|
||||
Reference in New Issue
Block a user