volatile stuff

This commit is contained in:
2025-07-12 19:22:49 +02:00
parent 863e04f19e
commit aa8bdfb88c
7 changed files with 220 additions and 6 deletions

View File

@@ -142,6 +142,11 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu
}
}
nn_lock(&eeprom->ctx, eeprom->lock);
if(eeprom->table.isReadonly(eeprom->table.userdata)) {
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_setCError(computer, "readonly");
return;
}
eeprom->table.set(eeprom->table.userdata, buf, len);
nn_unlock(&eeprom->ctx, eeprom->lock);
@@ -187,6 +192,11 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c
return;
}
nn_lock(&eeprom->ctx, eeprom->lock);
if(eeprom->table.isReadonly(eeprom->table.userdata)) {
nn_unlock(&eeprom->ctx, eeprom->lock);
nn_setCError(computer, "readonly");
return;
}
eeprom->table.setData(eeprom->table.userdata, buf, len);
nn_unlock(&eeprom->ctx, eeprom->lock);
@@ -255,7 +265,7 @@ void nn_loadEepromTable(nn_universe *universe) {
nn_defineMethod(eepromTable, "getChecksum", true, (void *)nn_eeprom_getChecksum, NULL, "getChecksum(): string - Returns a checksum of the data on the EEPROM.");
}
nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom) {
nn_component *nn_addEEPROM(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom) {
nn_componentTable *eepromTable = nn_queryUserdata(nn_getUniverse(computer), "NN:EEPROM");
return nn_newComponent(computer, address, slot, eepromTable, eeprom);

View File

@@ -0,0 +1,74 @@
#include "../neonucleus.h"
// TODO: make it allocate lazily
typedef struct nn_vdrive {
nn_Context ctx;
char *buffer;
nn_size_t sectorSize;
nn_size_t capacity;
char label[NN_LABEL_SIZE];
nn_size_t labelLen;
} nn_vdrive;
static void nni_vdrive_deinit(nn_vdrive *vdrive) {
nn_Alloc a = vdrive->ctx.allocator;
nn_dealloc(&a, vdrive->buffer, vdrive->capacity);
nn_dealloc(&a, vdrive, sizeof(nn_vdrive));
}
static void nni_vdrive_getLabel(nn_vdrive *vdrive, char *buf, nn_size_t *buflen) {
nn_memcpy(buf, vdrive->label, vdrive->labelLen);
*buflen = vdrive->labelLen;
}
static nn_size_t nni_vdrive_setLabel(nn_vdrive *vdrive, const char *buf, nn_size_t buflen) {
if(buflen > NN_LABEL_SIZE) buflen = NN_LABEL_SIZE;
nn_memcpy(vdrive->label, buf, buflen);
vdrive->labelLen = buflen;
return buflen;
}
static void nni_vdrive_readSector(nn_vdrive *vdrive, int sector, char *buf) {
nn_memcpy(buf, vdrive->buffer + (sector - 1) * vdrive->sectorSize, vdrive->sectorSize);
}
static void nni_vdrive_writeSector(nn_vdrive *vdrive, int sector, const char *buf) {
nn_memcpy(vdrive->buffer + (sector - 1) * vdrive->sectorSize, buf, vdrive->sectorSize);
}
nn_drive *nn_volatileDrive(nn_Context *context, nn_vdriveOptions opts, nn_driveControl control) {
nn_Alloc *alloc = &context->allocator;
char *buffer = nn_alloc(alloc, opts.capacity);
if(buffer == NULL) return NULL;
nn_vdrive *drive = nn_alloc(alloc, sizeof(nn_vdrive));
if(drive == NULL) {
nn_dealloc(alloc, buffer, opts.capacity);
return NULL;
}
drive->ctx = *context;
drive->buffer = buffer;
drive->sectorSize = opts.sectorSize;
drive->capacity = opts.capacity;
nn_memcpy(drive->label, opts.label, opts.labelLen);
drive->labelLen = opts.labelLen;
if(opts.data == NULL) {
nn_memset(buffer, 0, opts.capacity);
} else {
nn_memcpy(buffer, opts.data, opts.capacity);
}
nn_driveTable table = {
.userdata = drive,
.deinit = (void *)nni_vdrive_deinit,
.getLabel = (void *)nni_vdrive_getLabel,
.setLabel = (void *)nni_vdrive_setLabel,
.readSector = (void *)nni_vdrive_readSector,
.writeSector = (void *)nni_vdrive_writeSector,
.sectorSize = opts.sectorSize,
.platterCount = opts.platterCount,
.capacity = opts.capacity,
};
return nn_newDrive(context, table, control);
}

View File

@@ -0,0 +1,98 @@
#include "../neonucleus.h"
typedef struct nn_veeprom {
nn_Context ctx;
char *code;
nn_size_t codeLen;
nn_size_t codeSize;
char *data;
nn_size_t dataLen;
nn_size_t dataSize;
char label[NN_LABEL_SIZE];
nn_size_t labelLen;
nn_bool_t isReadOnly;
} nn_veeprom;
static void nni_veeprom_deinit(nn_veeprom *veeprom) {
nn_Alloc a = veeprom->ctx.allocator;
nn_dealloc(&a, veeprom->code, veeprom->codeSize);
nn_dealloc(&a, veeprom->data, veeprom->dataSize);
nn_dealloc(&a, veeprom, sizeof(nn_veeprom));
}
static void nni_veeprom_getLabel(nn_veeprom *veeprom, char *buf, nn_size_t *buflen) {
nn_memcpy(buf, veeprom->label, veeprom->labelLen);
*buflen = veeprom->labelLen;
}
static nn_size_t nni_veeprom_setLabel(nn_veeprom *veeprom, const char *buf, nn_size_t buflen) {
if(buflen > NN_LABEL_SIZE) buflen = NN_LABEL_SIZE;
nn_memcpy(veeprom->label, buf, buflen);
veeprom->labelLen = buflen;
return buflen;
}
static nn_size_t nni_veeprom_get(nn_veeprom *veeprom, char *buf) {
nn_memcpy(buf, veeprom->code, veeprom->codeLen);
return veeprom->codeLen;
}
static void nni_veeprom_set(nn_veeprom *veeprom, const char *buf, nn_size_t len) {
nn_memcpy(veeprom->code, buf, len);
veeprom->codeLen = len;
}
static nn_size_t nni_veeprom_getData(nn_veeprom *veeprom, char *buf) {
nn_memcpy(buf, veeprom->data, veeprom->dataLen);
return veeprom->dataLen;
}
static void nni_veeprom_setData(nn_veeprom *veeprom, const char *buf, nn_size_t len) {
nn_memcpy(veeprom->data, buf, len);
veeprom->dataLen = len;
}
static nn_bool_t nni_veeprom_isReadonly(nn_veeprom *eeprom) {
return eeprom->isReadOnly;
}
static void nni_veeprom_makeReadonly(nn_veeprom *eeprom) {
eeprom->isReadOnly = true;
}
nn_eeprom *nn_volatileEEPROM(nn_Context *context, nn_veepromOptions opts, nn_eepromControl control) {
nn_Alloc *a = &context->allocator;
// TODO: handle OOM
nn_veeprom *veeprom = nn_alloc(a, sizeof(nn_veeprom));
veeprom->ctx = *context;
veeprom->codeSize = opts.size;
veeprom->code = nn_alloc(a, veeprom->codeSize);
veeprom->codeLen = opts.len;
veeprom->dataSize = opts.dataSize;
veeprom->data = nn_alloc(a, veeprom->dataSize);
veeprom->dataLen = opts.dataLen;
veeprom->isReadOnly = opts.isReadOnly;
veeprom->labelLen = opts.labelLen;
nn_memcpy(veeprom->label, opts.label, veeprom->labelLen);
nn_memcpy(veeprom->code, opts.code, veeprom->codeLen);
nn_memcpy(veeprom->data, opts.data, veeprom->dataLen);
nn_eepromTable table = {
.userdata = veeprom,
.deinit = (void *)nni_veeprom_deinit,
.size = opts.size,
.dataSize = opts.dataSize,
.getLabel = (void *)nni_veeprom_getLabel,
.setLabel = (void *)nni_veeprom_setLabel,
.get = (void *)nni_veeprom_get,
.set = (void *)nni_veeprom_set,
.getData = (void *)nni_veeprom_getData,
.setData = (void *)nni_veeprom_setData,
.isReadonly = (void *)nni_veeprom_isReadonly,
.makeReadonly = (void *)nni_veeprom_makeReadonly,
};
return nn_newEEPROM(context, table, control);
}