From a623c0ab675a4463ab4e5c6c2614c7c5976e22e0 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 18 Apr 2024 14:33:33 +0200 Subject: [PATCH 1/4] RL02: read header --- rl02.cpp | 77 ++++++++++++++++++++++++++++++++++++++------------------ rl02.h | 3 ++- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/rl02.cpp b/rl02.cpp index cc0dd24..5c10a6d 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -20,6 +20,17 @@ static const char * const regnames[] = { "multipurpose " }; +static const char * const commands[] = { + "no-op", + "write check", + "get status", + "seek", + "read header", + "write data", + "read data", + "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) : b(b), disk_read_acitivity(disk_read_acitivity), @@ -70,13 +81,15 @@ uint16_t rl02::readWord(const uint16_t addr) if (addr == RL02_MPR) { // multi purpose register value = mpr[0]; - memcpy(&mpr[0], &mpr[1], sizeof(mpr[0]) * 2); + mpr[0] = mpr[1]; + mpr[1] = mpr[2]; + mpr[2] = 0; } else { value = registers[reg]; } - DOLOG(debug, false, "RL02 read %s/%o: %06o", regnames[reg], addr, value); + DOLOG(debug, false, "RL02 read \"%s\"/%o: %06o", regnames[reg], addr, value); return value; } @@ -110,17 +123,22 @@ void rl02::update_bus_address(const uint32_t a) registers[(RL02_CSR - RL02_BASE) / 2] |= ((a >> 16) & 3) << 4; } -uint32_t rl02::calcOffset() const +uint32_t rl02::calc_offset() const { return (rl02_sectors_per_track * track * 2 + head * rl02_sectors_per_track + sector) * rl02_bytes_per_sector; } +void rl02::update_dar() +{ + registers[(RL02_DAR - RL02_BASE) / 2] = (sector & 63) | (head << 6) | (track << 7); +} + void rl02::writeWord(const uint16_t addr, uint16_t v) { - DOLOG(debug, false, "RL02 write %06o: %06o", addr, v); - const int reg = (addr - RL02_BASE) / 2; + DOLOG(debug, false, "RL02 write \"%s\"/%06o: %06o", regnames[reg], addr, v); + registers[reg] = v; if (addr == RL02_CSR) { // control status @@ -128,7 +146,7 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) const bool do_exec = !(v & 128); - DOLOG(debug, false, "RL02 set command %d, exec: %d", command, do_exec); + DOLOG(debug, false, "RL02 set command %d, exec: %d (%s)", command, do_exec, commands[command]); int device = 0; // TODO @@ -142,33 +160,31 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) else if (command == 3) { // seek uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2]; - int cylinder_count = (((temp >> 7) & 255) + 1) * (temp & 4 ? 1 : -1); + int cylinder_count = (temp >> 7) * (temp & 4 ? 1 : -1); - int32_t new_track = 0; // when bit 4 is set, a reset is performed + int16_t new_track = track + cylinder_count; - if ((temp & 8) == 0) { - new_track = track + cylinder_count; - - if (new_track < 0) - new_track = 0; - else if (new_track >= rl02_track_count) - new_track = rl02_track_count; - } + if (new_track < 0) + new_track = 0; + else if (new_track >= rl02_track_count) + new_track = rl02_track_count - 1; DOLOG(debug, false, "RL02: seek from cylinder %d to %d (distance: %d, DAR: %06o)", track, new_track, cylinder_count, temp); track = new_track; + update_dar(); + do_int = true; } else if (command == 4) { // read header + mpr[0] = (sector & 63) | (head << 6) | (track << 7); + mpr[1] = 0; // zero + mpr[2] = 0; // TODO: CRC + + do_int = true; } else if (command == 6 || command == 7) { // read data / read data without header check - uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2]; - sector = temp & 63; - head = !!(temp & 64); - track = temp >> 7; - - uint32_t temp_disk_offset = calcOffset(); + uint32_t temp_disk_offset = calc_offset(); uint32_t memory_address = get_bus_address(); @@ -176,18 +192,24 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct) [cylinder: %d, head: %d, sector: %d]", count, temp_disk_offset, memory_address, track, head, sector); + update_dar(); + while(count > 0) { uint32_t cur = std::min(uint32_t(sizeof xfer_buffer), count); if (!fhs.at(device)->read(temp_disk_offset, cur, xfer_buffer)) { - DOLOG(ll_error, true, "RL02 read error %s", strerror(errno)); + DOLOG(ll_error, true, "RL02 read error %s, disk offset %u, read size %u, cylinder %d, head %d, sector %d", strerror(errno), temp_disk_offset, cur, track, head, sector); break; } - for(uint32_t i=0; iwriteUnibusByte(memory_address, xfer_buffer[i]); + for(uint32_t i=0; iwriteUnibusByte(memory_address++, xfer_buffer[i++]); + b->writeUnibusByte(memory_address++, xfer_buffer[i++]); update_bus_address(memory_address); + + (*reinterpret_cast(®isters[(RL02_MPR - RL02_BASE) / 2]))++; } temp_disk_offset += cur; @@ -205,8 +227,13 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) track++; } } + + update_dar(); } + if (registers[(RL02_MPR - RL02_BASE) / 2]) + DOLOG(warning, false, "RL02: unexpected MPR value after read (%06o)", registers[(RL02_MPR - RL02_BASE) / 2]); + do_int = true; } diff --git a/rl02.h b/rl02.h index 3e6089a..5d9fb1a 100644 --- a/rl02.h +++ b/rl02.h @@ -42,7 +42,8 @@ private: uint32_t get_bus_address() const; void update_bus_address(const uint32_t a); - uint32_t calcOffset() const; + void update_dar(); + 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); From caf07d060313e6050a0ceca7ace67ad58ff173aa Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 18 Apr 2024 21:06:20 +0200 Subject: [PATCH 2/4] DAR from read-command is valid as well --- rl02.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rl02.cpp b/rl02.cpp index 5c10a6d..001c8d8 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -181,6 +181,8 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) mpr[1] = 0; // zero mpr[2] = 0; // TODO: CRC + DOLOG(debug, false, "RL02 read header [cylinder: %d, head: %d, sector: %d] %06o", track, head, sector, mpr[0]); + do_int = true; } else if (command == 6 || command == 7) { // read data / read data without header check @@ -190,6 +192,11 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) uint32_t count = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; + uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2]; + + sector = temp & 63; + head = (temp >> 6) & 1; + track = temp >> 7; DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct) [cylinder: %d, head: %d, sector: %d]", count, temp_disk_offset, memory_address, track, head, sector); update_dar(); From 39c5fc44f2cafa24d9a8f8b431c01b9b1d916c13 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 18 Apr 2024 22:03:47 +0200 Subject: [PATCH 3/4] calc_offset AFTER s/h/t calculation --- rl02.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rl02.cpp b/rl02.cpp index 001c8d8..c06fd6f 100644 --- a/rl02.cpp +++ b/rl02.cpp @@ -186,8 +186,6 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) do_int = true; } else if (command == 6 || command == 7) { // read data / read data without header check - uint32_t temp_disk_offset = calc_offset(); - uint32_t memory_address = get_bus_address(); uint32_t count = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2; @@ -197,6 +195,9 @@ void rl02::writeWord(const uint16_t addr, uint16_t v) sector = temp & 63; head = (temp >> 6) & 1; track = temp >> 7; + + uint32_t temp_disk_offset = calc_offset(); + DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct) [cylinder: %d, head: %d, sector: %d]", count, temp_disk_offset, memory_address, track, head, sector); update_dar(); From 66e4197bffaf43102150703b7a6d56c000760f53 Mon Sep 17 00:00:00 2001 From: folkert van heusden Date: Thu, 18 Apr 2024 22:14:59 +0200 Subject: [PATCH 4/4] -S now sets the ram size from the command line --- main.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 2cde331..98198fa 100644 --- a/main.cpp +++ b/main.cpp @@ -305,6 +305,7 @@ void help() printf("-b enable bootloader (builtin)\n"); printf("-n ncurses UI\n"); printf("-d enable debugger\n"); + printf("-S x set ram size (in number of 8 kB pages)\n"); printf("-s x,y set console switche state: set bit x (0...15) to y (0/1)\n"); printf("-t enable tracing (disassemble to stderr, requires -d as well)\n"); printf("-l x log to file x\n"); @@ -363,12 +364,14 @@ int main(int argc, char *argv[]) disk_backend *temp_d = nullptr; + std::optional set_ram_size; + std::string validate_json; bool metrics = false; int opt = -1; - while((opt = getopt(argc, argv, "hMT:Br:R:p:ndtL:bl:s:Q:N:J:X")) != -1) + while((opt = getopt(argc, argv, "hMT:Br:R:p:ndtL:bl:s:Q:N:J:XS:")) != -1) { switch(opt) { case 'h': @@ -478,6 +481,10 @@ int main(int argc, char *argv[]) logfile = optarg; break; + case 'S': + set_ram_size = std::stoi(optarg); + break; + default: fprintf(stderr, "-%c is not understood\n", opt); return 1; @@ -493,6 +500,9 @@ int main(int argc, char *argv[]) bus *b = new bus(); + if (set_ram_size.has_value()) + b->set_memory_size(set_ram_size.value()); + b->set_console_switches(console_switches); cpu *c = new cpu(b, &event);