RL02 serialization

This commit is contained in:
folkert van heusden 2024-04-25 20:04:27 +02:00
parent 859577479f
commit 4eb557cbc5
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1
9 changed files with 165 additions and 15 deletions

13
bus.cpp
View file

@ -62,7 +62,10 @@ json_t *bus::serialize() const
if (c) if (c)
json_object_set(j_out, "cpu", c->serialize()); 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; 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_); 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; return b;
} }

View file

@ -1,7 +1,10 @@
// (C) 2018-2023 by Folkert van Heusden // (C) 2018-2024 by Folkert van Heusden
// Released under MIT license // Released under MIT license
#include "disk_backend.h" #include "disk_backend.h"
#include "disk_backend_file.h"
#include "disk_backend_nbd.h"
disk_backend::disk_backend() disk_backend::disk_backend()
{ {
@ -10,3 +13,20 @@ disk_backend::disk_backend()
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

View file

@ -1,4 +1,4 @@
// (C) 2018-2023 by Folkert van Heusden // (C) 2018-2024 by Folkert van Heusden
// Released under MIT license // Released under MIT license
#pragma once #pragma once
@ -6,6 +6,8 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "gen.h"
class disk_backend class disk_backend
{ {
@ -13,6 +15,11 @@ public:
disk_backend(); disk_backend();
virtual ~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 begin() = 0;
virtual bool read(const off_t offset, const size_t n, uint8_t *const target) = 0; virtual bool read(const off_t offset, const size_t n, uint8_t *const target) = 0;

View file

@ -19,6 +19,26 @@ disk_backend_file::~disk_backend_file()
close(fd); 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() bool disk_backend_file::begin()
{ {
fd = open(filename.c_str(), O_RDWR); fd = open(filename.c_str(), O_RDWR);

View file

@ -1,4 +1,4 @@
// (C) 2018-2023 by Folkert van Heusden // (C) 2018-2024 by Folkert van Heusden
// Released under MIT license // Released under MIT license
#include <string> #include <string>
@ -17,6 +17,11 @@ public:
disk_backend_file(const std::string & filename); disk_backend_file(const std::string & filename);
virtual ~disk_backend_file(); 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 begin() override;
bool read(const off_t offset, const size_t n, uint8_t *const target) override; bool read(const off_t offset, const size_t n, uint8_t *const target) override;

View file

@ -47,6 +47,27 @@ disk_backend_nbd::~disk_backend_nbd()
close(fd); 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() bool disk_backend_nbd::begin()
{ {
if (!connect(false)) { if (!connect(false)) {

View file

@ -5,6 +5,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "disk_backend.h" #include "disk_backend.h"
#include "gen.h"
class disk_backend_nbd : public disk_backend class disk_backend_nbd : public disk_backend
@ -20,6 +21,11 @@ public:
disk_backend_nbd(const std::string & host, const unsigned port); disk_backend_nbd(const std::string & host, const unsigned port);
virtual ~disk_backend_nbd(); 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 begin() override;
bool read(const off_t offset, const size_t n, uint8_t *const target) override; bool read(const off_t offset, const size_t n, uint8_t *const target) override;

View file

@ -31,10 +31,10 @@ static const char * const commands[] = {
"read data w/o header check" "read data w/o header check"
}; };
rl02::rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity) : rl02::rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity) :
b(b), b(b),
disk_read_acitivity(disk_read_acitivity), disk_read_activity (disk_read_activity),
disk_write_acitivity(disk_write_acitivity) disk_write_activity(disk_write_activity)
{ {
fhs = files; fhs = files;
@ -58,6 +58,54 @@ void rl02::reset()
sector = 0; 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<disk_backend *> backends;
json_t *j_backends = json_object_get(j, "backends");
for(size_t i=0; i<json_array_size(j_backends); i++)
backends.push_back(disk_backend::deserialize(json_array_get(j_backends, i)));
rl02 *r = new rl02(backends, b, nullptr, nullptr);
for(int regnr=0; regnr<4; regnr++)
r->registers[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) uint8_t rl02::readByte(const uint16_t addr)
{ {
uint16_t v = readWord(addr & ~1); uint16_t v = readWord(addr & ~1);
@ -152,8 +200,6 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
bool do_int = false; bool do_int = false;
*disk_read_acitivity = true;
if (size_t(device) >= fhs.size()) { if (size_t(device) >= fhs.size()) {
DOLOG(info, false, "RL02: PDP11/70 is accessing a not-attached virtual disk %d", device); 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; do_int = true;
} }
else if (command == 5) { // write data else if (command == 5) { // write data
if (disk_write_activity)
*disk_write_activity = true;
uint32_t memory_address = get_bus_address(); uint32_t memory_address = get_bus_address();
uint32_t count = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; 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; do_int = true;
if (disk_write_activity)
*disk_write_activity = false;
} }
else if (command == 6 || command == 7) { // read data / read data without header check 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 memory_address = get_bus_address();
uint32_t count = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; 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; do_int = true;
if (disk_read_activity)
*disk_read_activity = false;
} }
else { else {
DOLOG(warning, false, "RL02: command %d not implemented", command); 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); b->getCpu()->queue_interrupt(5, 0160);
} }
} }
*disk_read_acitivity = false;
} }
} }

12
rl02.h
View file

@ -11,6 +11,7 @@
#include "device.h" #include "device.h"
#include "disk_backend.h" #include "disk_backend.h"
#include "gen.h"
#define RL02_CSR 0174400 // control status register #define RL02_CSR 0174400 // control status register
@ -38,8 +39,8 @@ private:
uint16_t mpr[3]; uint16_t mpr[3];
std::vector<disk_backend *> fhs; std::vector<disk_backend *> fhs;
std::atomic_bool *const disk_read_acitivity { nullptr }; std::atomic_bool *const disk_read_activity { nullptr };
std::atomic_bool *const disk_write_acitivity { nullptr }; std::atomic_bool *const disk_write_activity { nullptr };
uint32_t get_bus_address() const; uint32_t get_bus_address() const;
void update_bus_address(const uint32_t a); void update_bus_address(const uint32_t a);
@ -47,11 +48,16 @@ private:
uint32_t calc_offset() const; uint32_t calc_offset() const;
public: public:
rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity); rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_activity, std::atomic_bool *const disk_write_activity);
virtual ~rl02(); virtual ~rl02();
void reset() override; 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; uint8_t readByte(const uint16_t addr) override;
uint16_t readWord(const uint16_t addr) override; uint16_t readWord(const uint16_t addr) override;