diff --git a/bus.cpp b/bus.cpp index 3af1f5f..5d73884 100644 --- a/bus.cpp +++ b/bus.cpp @@ -62,7 +62,10 @@ json_t *bus::serialize() const if (c) json_object_set(j_out, "cpu", c->serialize()); - // TODO: rl02, rk05, tm11 + if (rl02_) + json_object_set(j_out, "rl02", rl02_->serialize()); + + // TODO: rk05, tm11 return j_out; } @@ -103,7 +106,13 @@ bus *bus::deserialize(const json_t *const j, console *const cnsl, std::atomic_ui b->add_cpu(cpu_); } - // TODO: rl02, rk05, tm11 + temp = json_object_get(j, "rl02"); + if (temp) { + rl02 *rl02_ = rl02::deserialize(temp, b); + b->add_rl02(rl02_); + } + + // TODO: rk05, tm11 return b; } diff --git a/disk_backend.cpp b/disk_backend.cpp index 54dfc37..1b4de50 100644 --- a/disk_backend.cpp +++ b/disk_backend.cpp @@ -1,7 +1,10 @@ -// (C) 2018-2023 by Folkert van Heusden +// (C) 2018-2024 by Folkert van Heusden // Released under MIT license #include "disk_backend.h" +#include "disk_backend_file.h" +#include "disk_backend_nbd.h" + disk_backend::disk_backend() { @@ -10,3 +13,20 @@ disk_backend::disk_backend() disk_backend::~disk_backend() { } + +#if IS_POSIX +disk_backend *disk_backend::deserialize(const json_t *const j) +{ + std::string type = json_string_value(json_object_get(j, "disk-backend-type")); + + if (type == "file") + return disk_backend_file::deserialize(j); + + if (type == "nbd") + return disk_backend_nbd::deserialize(j); + + // should not be reached + + return nullptr; +} +#endif diff --git a/disk_backend.h b/disk_backend.h index e8754c8..141c2d8 100644 --- a/disk_backend.h +++ b/disk_backend.h @@ -1,4 +1,4 @@ -// (C) 2018-2023 by Folkert van Heusden +// (C) 2018-2024 by Folkert van Heusden // Released under MIT license #pragma once @@ -6,6 +6,8 @@ #include #include +#include "gen.h" + class disk_backend { @@ -13,6 +15,11 @@ public: disk_backend(); virtual ~disk_backend(); +#if IS_POSIX + virtual json_t *serialize() const = 0; + static disk_backend *deserialize(const json_t *const j); +#endif + virtual bool begin() = 0; virtual bool read(const off_t offset, const size_t n, uint8_t *const target) = 0; diff --git a/disk_backend_file.cpp b/disk_backend_file.cpp index 328075a..127faa3 100644 --- a/disk_backend_file.cpp +++ b/disk_backend_file.cpp @@ -19,6 +19,26 @@ disk_backend_file::~disk_backend_file() close(fd); } +#if IS_POSIX +json_t *disk_backend_file::serialize() const +{ + json_t *j = json_object(); + + json_object_set(j, "disk-backend-type", json_string("file")); + + // TODO store checksum of backend + json_object_set(j, "filename", json_string(filename.c_str())); + + return j; +} + +disk_backend_file *disk_backend_file::deserialize(const json_t *const j) +{ + // TODO verify checksum of backend + return new disk_backend_file(json_string_value(json_object_get(j, "filename"))); +} +#endif + bool disk_backend_file::begin() { fd = open(filename.c_str(), O_RDWR); diff --git a/disk_backend_file.h b/disk_backend_file.h index 652c81d..d02ef0d 100644 --- a/disk_backend_file.h +++ b/disk_backend_file.h @@ -1,4 +1,4 @@ -// (C) 2018-2023 by Folkert van Heusden +// (C) 2018-2024 by Folkert van Heusden // Released under MIT license #include @@ -17,6 +17,11 @@ public: disk_backend_file(const std::string & filename); virtual ~disk_backend_file(); +#if IS_POSIX + json_t *serialize() const override; + static disk_backend_file *deserialize(const json_t *const j); +#endif + bool begin() override; bool read(const off_t offset, const size_t n, uint8_t *const target) override; diff --git a/disk_backend_nbd.cpp b/disk_backend_nbd.cpp index 7e3c7fd..6f85c00 100644 --- a/disk_backend_nbd.cpp +++ b/disk_backend_nbd.cpp @@ -47,6 +47,27 @@ disk_backend_nbd::~disk_backend_nbd() close(fd); } +#if IS_POSIX +json_t *disk_backend_nbd::serialize() const +{ + json_t *j = json_object(); + + json_object_set(j, "disk-backend-type", json_string("nbd")); + + // TODO store checksum of backend + json_object_set(j, "host", json_string(host.c_str())); + json_object_set(j, "port", json_integer(port)); + + return j; +} + +disk_backend_nbd *disk_backend_nbd::deserialize(const json_t *const j) +{ + // TODO verify checksum of backend + return new disk_backend_nbd(json_string_value(json_object_get(j, "host")), json_integer_value(json_object_get(j, "port"))); +} +#endif + bool disk_backend_nbd::begin() { if (!connect(false)) { diff --git a/disk_backend_nbd.h b/disk_backend_nbd.h index 70f65aa..b6679a8 100644 --- a/disk_backend_nbd.h +++ b/disk_backend_nbd.h @@ -5,6 +5,7 @@ #include #include "disk_backend.h" +#include "gen.h" class disk_backend_nbd : public disk_backend @@ -20,6 +21,11 @@ public: disk_backend_nbd(const std::string & host, const unsigned port); virtual ~disk_backend_nbd(); +#if IS_POSIX + json_t *serialize() const override; + static disk_backend_nbd *deserialize(const json_t *const j); +#endif + bool begin() override; bool read(const off_t offset, const size_t n, uint8_t *const target) override; diff --git a/rl02.cpp b/rl02.cpp index f34a562..25b57af 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -31,10 +31,10 @@ static const char * const commands[] = { "read data w/o header check" }; -rl02::rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) : +rl02::rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity) : b(b), - disk_read_acitivity(disk_read_acitivity), - disk_write_acitivity(disk_write_acitivity) + disk_read_activity (disk_read_activity), + disk_write_activity(disk_write_activity) { fhs = files; @@ -58,6 +58,54 @@ void rl02::reset() sector = 0; } +#if IS_POSIX +json_t *rl02::serialize() const +{ + json_t *j = json_object(); + + json_t *j_backends = json_array(); + for(auto & dbe: fhs) + json_array_append(j_backends, dbe->serialize()); + + json_object_set(j, "backends", j_backends); + + for(int regnr=0; regnr<4; regnr++) + json_object_set(j, format("register-%d", regnr).c_str(), json_integer(registers[regnr])); + + for(int mprnr=0; mprnr<3; mprnr++) + json_object_set(j, format("mpr-%d", mprnr).c_str(), json_integer(mpr[mprnr])); + + json_object_set(j, "track", json_integer(track)); + json_object_set(j, "head", json_integer(head)); + json_object_set(j, "sector", json_integer(sector)); + + return j; +} + +rl02 *rl02::deserialize(const json_t *const j, bus *const b) +{ + std::vector backends; + + json_t *j_backends = json_object_get(j, "backends"); + for(size_t i=0; iregisters[regnr] = json_integer_value(json_object_get(j, format("register-%d", regnr).c_str())); + + for(int mprnr=0; mprnr<3; mprnr++) + r->mpr[mprnr] = json_integer_value(json_object_get(j, format("mpr-%d", mprnr).c_str())); + + r->track = json_integer_value(json_object_get(j, "track" )); + r->head = json_integer_value(json_object_get(j, "head" )); + r->sector = json_integer_value(json_object_get(j, "sector")); + + return r; +} +#endif + uint8_t rl02::readByte(const uint16_t addr) { uint16_t v = readWord(addr & ~1); @@ -152,8 +200,6 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) bool do_int = false; - *disk_read_acitivity = true; - if (size_t(device) >= fhs.size()) { DOLOG(info, false, "RL02: PDP11/70 is accessing a not-attached virtual disk %d", device); @@ -194,6 +240,9 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) do_int = true; } else if (command == 5) { // write data + if (disk_write_activity) + *disk_write_activity = true; + uint32_t memory_address = get_bus_address(); uint32_t count = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; @@ -247,8 +296,14 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) } do_int = true; + + if (disk_write_activity) + *disk_write_activity = false; } else if (command == 6 || command == 7) { // read data / read data without header check + if (disk_read_activity) + *disk_read_activity = true; + uint32_t memory_address = get_bus_address(); uint32_t count = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; @@ -305,6 +360,9 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) } do_int = true; + + if (disk_read_activity) + *disk_read_activity = false; } else { DOLOG(warning, false, "RL02: command %d not implemented", command); @@ -317,7 +375,5 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) b->getCpu()->queue_interrupt(5, 0160); } } - - *disk_read_acitivity = false; } } diff --git a/rl02.h b/rl02.h index 64bc4d6..4a9858e 100644 --- a/rl02.h +++ b/rl02.h @@ -11,6 +11,7 @@ #include "device.h" #include "disk_backend.h" +#include "gen.h" #define RL02_CSR 0174400 // control status register @@ -38,8 +39,8 @@ private: uint16_t mpr[3]; std::vector fhs; - std::atomic_bool *const disk_read_acitivity { nullptr }; - std::atomic_bool *const disk_write_acitivity { nullptr }; + std::atomic_bool *const disk_read_activity { nullptr }; + std::atomic_bool *const disk_write_activity { nullptr }; uint32_t get_bus_address() const; void update_bus_address(const uint32_t a); @@ -47,11 +48,16 @@ private: uint32_t calc_offset() const; public: - rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity); + rl02(const std::vector & files, bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity); virtual ~rl02(); void reset() override; +#if IS_POSIX + json_t *serialize() const; + static rl02 *deserialize(const json_t *const j, bus *const b); +#endif + uint8_t readByte(const uint16_t addr) override; uint16_t readWord(const uint16_t addr) override;