show device state

This commit is contained in:
folkert van heusden 2024-05-10 20:15:55 +02:00
parent e883822ccc
commit bd0304c5e2
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1
20 changed files with 182 additions and 98 deletions

View file

@ -130,6 +130,13 @@ bus *bus::deserialize(const json_t *const j, console *const cnsl, std::atomic_ui
} }
#endif #endif
void bus::show_state(console *const cnsl) const
{
cnsl->put_string_lf(format("Microprogram break register: %06o", microprogram_break_register));
cnsl->put_string_lf(format("Console switches: %06o", console_switches));
cnsl->put_string_lf(format("Console LEDs: %06o", console_leds));
}
void bus::set_memory_size(const int n_pages) void bus::set_memory_size(const int n_pages)
{ {
uint32_t n_bytes = n_pages * 8192l; uint32_t n_bytes = n_pages * 8192l;

15
bus.h
View file

@ -9,6 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include "gen.h" #include "gen.h"
#include "device.h"
#include "dc11.h" #include "dc11.h"
#include "mmu.h" #include "mmu.h"
#include "rk05.h" #include "rk05.h"
@ -56,7 +57,7 @@ typedef struct {
bool is_psw; bool is_psw;
} write_rc_t; } write_rc_t;
class bus class bus: public device
{ {
private: private:
cpu *c { nullptr }; cpu *c { nullptr };
@ -86,6 +87,8 @@ public:
void reset(); void reset();
void init(); // invoked by 'RESET' command void init(); // invoked by 'RESET' command
void show_state(console *const cnsl) const override;
void set_console_switches(const uint16_t new_state) { console_switches = new_state; } void set_console_switches(const uint16_t new_state) { console_switches = new_state; }
void set_console_switch(const int bit, const bool state) { console_switches &= ~(1 << bit); console_switches |= state << bit; } void set_console_switch(const int bit, const bool state) { console_switches &= ~(1 << bit); console_switches |= state << bit; }
uint16_t get_console_switches() { return console_switches; } uint16_t get_console_switches() { return console_switches; }
@ -115,16 +118,18 @@ public:
tm_11 *getTM11() { return tm11; } tm_11 *getTM11() { return tm11; }
uint16_t read(const uint16_t a, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only=false, const d_i_space_t s = i_space); uint16_t read(const uint16_t a, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool peek_only=false, const d_i_space_t s = i_space);
uint16_t read_byte(const uint16_t a) { return read(a, wm_byte, rm_cur); } uint8_t read_byte(const uint16_t a) override { return read(a, wm_byte, rm_cur); }
uint16_t read_word(const uint16_t a, const d_i_space_t s = i_space); uint16_t read_word(const uint16_t a, const d_i_space_t s);
uint16_t read_word(const uint16_t a) override { return read_word(a, i_space); }
uint16_t peekWord(const uint16_t a); uint16_t peekWord(const uint16_t a);
uint8_t readUnibusByte(const uint32_t a); uint8_t readUnibusByte(const uint32_t a);
uint16_t readPhysical(const uint32_t a); uint16_t readPhysical(const uint32_t a);
write_rc_t write(const uint16_t a, const word_mode_t word_mode, uint16_t value, const rm_selection_t mode_selection, const d_i_space_t s = i_space); write_rc_t write(const uint16_t a, const word_mode_t word_mode, uint16_t value, const rm_selection_t mode_selection, const d_i_space_t s = i_space);
void writeUnibusByte(const uint32_t a, const uint8_t value); void writeUnibusByte(const uint32_t a, const uint8_t value);
void write_byte(const uint16_t a, const uint8_t value) { write(a, wm_byte, value, rm_cur); } void write_byte(const uint16_t a, const uint8_t value) override { write(a, wm_byte, value, rm_cur); }
void write_word(const uint16_t a, const uint16_t value, const d_i_space_t s = i_space); void write_word(const uint16_t a, const uint16_t value, const d_i_space_t s);
void write_word(const uint16_t a, const uint16_t value) override { write_word(a, value, i_space); }
void writePhysical(const uint32_t a, const uint16_t value); void writePhysical(const uint32_t a, const uint16_t value);
bool is_psw(const uint16_t addr, const int run_mode, const d_i_space_t space) const; bool is_psw(const uint16_t addr, const int run_mode, const d_i_space_t space) const;

View file

@ -1,6 +1,7 @@
// (C) 2018-2023 by Folkert van Heusden // (C) 2018-2024 by Folkert van Heusden
// Released under MIT license // Released under MIT license
#include <cassert>
#include <chrono> #include <chrono>
#include <optional> #include <optional>
#include <stdarg.h> #include <stdarg.h>

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,16 +6,17 @@
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include <optional> #include <optional>
#include <string>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include "bus.h"
#if defined(_WIN32) #if defined(_WIN32)
#include "win32.h" #include "win32.h"
#endif #endif
class bus;
class console class console
{ {
private: private:

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 <poll.h> #include <poll.h>
@ -6,6 +6,7 @@
#include <ncurses.h> #include <ncurses.h>
#include <unistd.h> #include <unistd.h>
#include "bus.h"
#include "console_ncurses.h" #include "console_ncurses.h"
#include "cpu.h" #include "cpu.h"
#include "error.h" #include "error.h"

View file

@ -115,6 +115,28 @@ dc11::~dc11()
#endif #endif
} }
void dc11::show_state(console *const cnsl) const
{
for(int i=0; i<4; i++) {
cnsl->put_string_lf(format("* LINE %d", i + 1));
if (i == serial_line) {
cnsl->put_string_lf(format(" Serial thread running: %s", serial_thread_running ? "true": "false" ));
cnsl->put_string_lf(format(" Serial enabled: %s", serial_enabled ? "true": "false" ));
}
else {
if (pfds[dc11_n_lines + i].fd != INVALID_SOCKET)
cnsl->put_string_lf(" Connected to: " + get_endpoint_name(pfds[dc11_n_lines + i].fd));
}
std::unique_lock<std::mutex> lck(input_lock[i]);
cnsl->put_string_lf(format(" Characters in buffer: %zu", recv_buffers[i].size()));
cnsl->put_string_lf(format(" RX interrupt enabled: %s", is_rx_interrupt_enabled(i) ? "true": "false" ));
cnsl->put_string_lf(format(" TX interrupt enabled: %s", is_tx_interrupt_enabled(i) ? "true": "false" ));
}
}
void dc11::trigger_interrupt(const int line_nr, const bool is_tx) void dc11::trigger_interrupt(const int line_nr, const bool is_tx)
{ {
TRACE("DC11: interrupt for line %d, %s", line_nr, is_tx ? "TX" : "RX"); TRACE("DC11: interrupt for line %d, %s", line_nr, is_tx ? "TX" : "RX");
@ -423,12 +445,12 @@ void dc11::reset()
{ {
} }
bool dc11::is_rx_interrupt_enabled(const int line_nr) bool dc11::is_rx_interrupt_enabled(const int line_nr) const
{ {
return !!(registers[line_nr * 4 + 0] & 64); return !!(registers[line_nr * 4 + 0] & 64);
} }
bool dc11::is_tx_interrupt_enabled(const int line_nr) bool dc11::is_tx_interrupt_enabled(const int line_nr) const
{ {
return !!(registers[line_nr * 4 + 2] & 64); return !!(registers[line_nr * 4 + 2] & 64);
} }

9
dc11.h
View file

@ -48,7 +48,7 @@ private:
pollfd *pfds { nullptr }; pollfd *pfds { nullptr };
#endif #endif
std::vector<char> recv_buffers[dc11_n_lines]; std::vector<char> recv_buffers[dc11_n_lines];
std::mutex input_lock[dc11_n_lines]; mutable std::mutex input_lock[dc11_n_lines];
std::atomic_bool serial_thread_running { false }; std::atomic_bool serial_thread_running { false };
bool serial_enabled { false }; bool serial_enabled { false };
#if IS_POSIX #if IS_POSIX
@ -57,8 +57,8 @@ private:
#endif #endif
void trigger_interrupt(const int line_nr, const bool is_tx); void trigger_interrupt(const int line_nr, const bool is_tx);
bool is_rx_interrupt_enabled(const int line_nr); bool is_rx_interrupt_enabled(const int line_nr) const;
bool is_tx_interrupt_enabled(const int line_nr); bool is_tx_interrupt_enabled(const int line_nr) const;
public: public:
dc11(const int base_port, bus *const b); dc11(const int base_port, bus *const b);
@ -70,6 +70,9 @@ public:
#endif #endif
void reset(); void reset();
void show_state(console *const cnsl) const override;
#if defined(ESP32) #if defined(ESP32)
void set_serial(const int bitrate, const int rx, const int tx); void set_serial(const int bitrate, const int rx, const int tx);
void serial_handler(); void serial_handler();

View file

@ -436,77 +436,6 @@ std::map<std::string, std::string> split(const std::vector<std::string> & kv_arr
return out; return out;
} }
void dump_par_pdr(console *const cnsl, bus *const b, const uint16_t pdrs, const uint16_t pars, const std::string & name, const int state, const std::optional<int> & selection)
{
if (state == 0 || state == 2)
cnsl->put_string_lf(name);
else
cnsl->put_string_lf(format("%s DISABLED", name.c_str()));
cnsl->put_string_lf(" PAR PDR LEN");
for(int i=0; i<8; i++) {
if (selection.has_value() && i != selection.value())
continue;
uint16_t par_value = b->read(pars + i * 2, wm_word, rm_cur, true);
uint16_t pdr_value = b->read(pdrs + i * 2, wm_word, rm_cur, true);
uint16_t pdr_len = (((pdr_value >> 8) & 127) + 1) * 64;
cnsl->put_string_lf(format("%d] %06o %08o %06o %04o D%d A%d", i, par_value, par_value * 64, pdr_value, pdr_len, !!(pdr_value & 8), pdr_value & 7));
}
}
void dump_memory_contents(console *const cnsl, bus *const b, const uint16_t read_addr)
{
cnsl->put_string_lf(format("\tMOV #%06o,R0", read_addr));
cnsl->put_string_lf(format("\tMOV #%06o,(R0)", b->read(read_addr, wm_word, rm_cur, true)));
}
void dump_range_as_instructions(console *const cnsl, bus *const b, const uint16_t base)
{
for(int i=0; i<8; i++)
dump_memory_contents(cnsl, b, base + i * 2);
}
void mmu_dump(console *const cnsl, bus *const b, const bool verbose)
{
uint16_t mmr0 = b->getMMU()->getMMR0();
uint16_t mmr1 = b->getMMU()->getMMR1();
uint16_t mmr2 = b->getMMU()->getMMR2();
uint16_t mmr3 = b->getMMU()->getMMR3();
cnsl->put_string_lf(mmr0 & 1 ? "MMU enabled" : "MMU NOT enabled");
cnsl->put_string_lf(format("MMR0: %06o", mmr0));
cnsl->put_string_lf(format("MMR1: %06o", mmr1));
cnsl->put_string_lf(format("MMR2: %06o", mmr2));
cnsl->put_string_lf(format("MMR3: %06o", mmr3));
dump_par_pdr(cnsl, b, ADDR_PDR_SV_START, ADDR_PAR_SV_START, "supervisor i-space", 0, { });
dump_par_pdr(cnsl, b, ADDR_PDR_SV_START + 020, ADDR_PAR_SV_START + 020, "supervisor d-space", 1 + (!!(mmr3 & 2)), { });
dump_par_pdr(cnsl, b, ADDR_PDR_K_START, ADDR_PAR_K_START, "kernel i-space", 0, { });
dump_par_pdr(cnsl, b, ADDR_PDR_K_START + 020, ADDR_PAR_K_START + 020, "kernel d-space", 1 + (!!(mmr3 & 4)), { });
dump_par_pdr(cnsl, b, ADDR_PDR_U_START, ADDR_PAR_U_START, "user i-space", 0, { });
dump_par_pdr(cnsl, b, ADDR_PDR_U_START + 020, ADDR_PAR_U_START + 020, "user d-space", 1 + (!!(mmr3 & 1)), { });
if (verbose) {
dump_range_as_instructions(cnsl, b, ADDR_PDR_SV_START); // sv i
dump_range_as_instructions(cnsl, b, ADDR_PDR_SV_START + 020); // sv d
dump_range_as_instructions(cnsl, b, ADDR_PDR_K_START); // k i
dump_range_as_instructions(cnsl, b, ADDR_PDR_K_START + 020); // k d
dump_range_as_instructions(cnsl, b, ADDR_PDR_U_START); // u i
dump_range_as_instructions(cnsl, b, ADDR_PDR_U_START + 020); // u d
dump_memory_contents(cnsl, b, ADDR_MMR0);
dump_memory_contents(cnsl, b, ADDR_MMR1);
dump_memory_contents(cnsl, b, ADDR_MMR2);
dump_memory_contents(cnsl, b, ADDR_MMR3);
}
}
const char *trap_action_to_str(const trap_action_t ta) const char *trap_action_to_str(const trap_action_t ta)
{ {
if (ta == T_PROCEED) if (ta == T_PROCEED)
@ -534,16 +463,16 @@ void mmu_resolve(console *const cnsl, bus *const b, const uint16_t va)
uint16_t mmr3 = b->getMMU()->getMMR3(); uint16_t mmr3 = b->getMMU()->getMMR3();
if (run_mode == 0) { if (run_mode == 0) {
dump_par_pdr(cnsl, b, ADDR_PDR_K_START, ADDR_PAR_K_START, "kernel i-space", 0, data.apf); b->getMMU()->dump_par_pdr(cnsl, 1, false, "supervisor i-space", 0, data.apf);
dump_par_pdr(cnsl, b, ADDR_PDR_K_START + 020, ADDR_PAR_K_START + 020, "kernel d-space", 1 + (!!(mmr3 & 4)), data.apf); b->getMMU()->dump_par_pdr(cnsl, 1, true, "supervisor d-space", 1 + (!!(mmr3 & 4)), data.apf);
} }
else if (run_mode == 1) { else if (run_mode == 1) {
dump_par_pdr(cnsl, b, ADDR_PDR_SV_START, ADDR_PAR_SV_START, "supervisor i-space", 0, data.apf); b->getMMU()->dump_par_pdr(cnsl, 0, false, "kernel i-space", 0, data.apf);
dump_par_pdr(cnsl, b, ADDR_PDR_SV_START + 020, ADDR_PAR_SV_START + 020, "supervisor d-space", 1 + (!!(mmr3 & 4)), data.apf); b->getMMU()->dump_par_pdr(cnsl, 0, true, "kernel d-space", 1 + (!!(mmr3 & 4)), data.apf);
} }
else if (run_mode == 3) { else if (run_mode == 3) {
dump_par_pdr(cnsl, b, ADDR_PDR_U_START, ADDR_PAR_U_START, "user i-space", 0, data.apf); b->getMMU()->dump_par_pdr(cnsl, 3, false, "user i-space", 0, data.apf);
dump_par_pdr(cnsl, b, ADDR_PDR_U_START + 020, ADDR_PAR_U_START + 020, "user d-space", 1 + (!!(mmr3 & 4)), data.apf); b->getMMU()->dump_par_pdr(cnsl, 3, true, "user d-space", 1 + (!!(mmr3 & 4)), data.apf);
} }
for(int i=0; i<2; i++) { for(int i=0; i<2; i++) {
@ -790,8 +719,19 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
continue; continue;
} }
else if (parts[0] == "mmudump") { else if (parts[0] == "state") {
mmu_dump(cnsl, b, parts.size() == 2 && parts[1] == "-v"); if (parts[1] == "rl02")
b->getRL02()->show_state(cnsl);
else if (parts[1] == "mmu")
b->getMMU() ->show_state(cnsl);
else if (parts[1] == "rk05")
b->getRK05()->show_state(cnsl);
else if (parts[1] == "dc11")
b->getDC11()->show_state(cnsl);
else if (parts[1] == "tm11")
b->getTM11()->show_state(cnsl);
else
cnsl->put_string_lf(format("Device \"%s\" is not known", parts[1].c_str()));
continue; continue;
} }
@ -1072,7 +1012,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
"strace x - start tracing from address - invoke without address to disable", "strace x - start tracing from address - invoke without address to disable",
"trl x - set trace run-level (0...3), empty for all", "trl x - set trace run-level (0...3), empty for all",
"regdump - dump register contents", "regdump - dump register contents",
"mmudump - dump MMU settings (PARs/PDRs)", "state x - dump state of a device: rl02, rk05, mmu, tm11 or dc11",
"mmures x - resolve a virtual address", "mmures x - resolve a virtual address",
"qi - show queued interrupts", "qi - show queued interrupts",
"setpc x - set PC to value", "setpc x - set PC to value",

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "console.h"
class device class device
{ {
@ -12,6 +13,8 @@ public:
virtual void reset() = 0; virtual void reset() = 0;
virtual void show_state(console *const cnsl) const = 0;
virtual uint8_t read_byte(const uint16_t addr) = 0; virtual uint8_t read_byte(const uint16_t addr) = 0;
virtual uint16_t read_word(const uint16_t addr) = 0; virtual uint16_t read_word(const uint16_t addr) = 0;

View file

@ -138,8 +138,8 @@ void set_boot_loader(bus *const b, const bootloader_t which)
bl = rl02_code; bl = rl02_code;
} }
for(int i=0; i<size; i++) for(uint16_t i=0; i<size; i++)
b->write_word(offset + i * 2, bl[i]); b->write_word(uint16_t(offset + i * 2), bl[i]);
c->setRegister(7, start); c->setRegister(7, start);
} }

40
mmu.cpp
View file

@ -30,6 +30,46 @@ void mmu::reset()
CPUERR = MMR0 = MMR1 = MMR2 = MMR3 = PIR = CSR = 0; CPUERR = MMR0 = MMR1 = MMR2 = MMR3 = PIR = CSR = 0;
} }
void mmu::dump_par_pdr(console *const cnsl, const int run_mode, const bool d, const std::string & name, const int state, const std::optional<int> & selection) const
{
if (state == 0 || state == 2)
cnsl->put_string_lf(name);
else
cnsl->put_string_lf(format("%s DISABLED", name.c_str()));
cnsl->put_string_lf(" PAR PDR LEN");
for(int i=0; i<8; i++) {
if (selection.has_value() && i != selection.value())
continue;
uint16_t par_value = pages[run_mode][d][i].par;
uint16_t pdr_value = pages[run_mode][d][i].pdr;
uint16_t pdr_len = (((pdr_value >> 8) & 127) + 1) * 64;
cnsl->put_string_lf(format("%d] %06o %08o %06o %04o D%d A%d", i, par_value, par_value * 64, pdr_value, pdr_len, !!(pdr_value & 8), pdr_value & 7));
}
}
void mmu::show_state(console *const cnsl) const
{
cnsl->put_string_lf(MMR0 & 1 ? "MMU enabled" : "MMU NOT enabled");
cnsl->put_string_lf(format("MMR0: %06o", MMR0));
cnsl->put_string_lf(format("MMR1: %06o", MMR1));
cnsl->put_string_lf(format("MMR2: %06o", MMR2));
cnsl->put_string_lf(format("MMR3: %06o", MMR3));
dump_par_pdr(cnsl, 1, false, "supervisor i-space", 0, { });
dump_par_pdr(cnsl, 1, true, "supervisor d-space", 1 + (!!(MMR3 & 2)), { });
dump_par_pdr(cnsl, 0, false, "kernel i-space", 0, { });
dump_par_pdr(cnsl, 0, true, "kernel d-space", 1 + (!!(MMR3 & 2)), { });
dump_par_pdr(cnsl, 3, false, "user i-space", 0, { });
dump_par_pdr(cnsl, 3, true, "user d-space", 1 + (!!(MMR3 & 2)), { });
}
uint16_t mmu::read_pdr(const uint32_t a, const int run_mode) uint16_t mmu::read_pdr(const uint32_t a, const int run_mode)
{ {
int page = (a >> 1) & 7; int page = (a >> 1) & 7;

3
mmu.h
View file

@ -77,6 +77,9 @@ public:
void reset() override; void reset() override;
void dump_par_pdr(console *const cnsl, const int run_mode, const bool d, const std::string & name, const int state, const std::optional<int> & selection) const;
void show_state(console *const cnsl) const override;
bool is_enabled() const { return MMR0 & 1; } bool is_enabled() const { return MMR0 & 1; }
bool is_locked() const { return !!(MMR0 & 0160000); } bool is_locked() const { return !!(MMR0 & 0160000); }

View file

@ -46,6 +46,17 @@ void rk05::reset()
memset(registers, 0x00, sizeof registers); memset(registers, 0x00, sizeof registers);
} }
void rk05::show_state(console *const cnsl) const
{
cnsl->put_string_lf(format("DS : %06o", registers[0]));
cnsl->put_string_lf(format("ERROR : %06o", registers[1]));
cnsl->put_string_lf(format("CS : %06o", registers[2]));
cnsl->put_string_lf(format("WC : %06o", registers[3]));
cnsl->put_string_lf(format("BA : %06o", registers[4]));
cnsl->put_string_lf(format("DA : %06o", registers[5]));
cnsl->put_string_lf(format("DATABUF: %06o", registers[6]));
}
uint8_t rk05::read_byte(const uint16_t addr) uint8_t rk05::read_byte(const uint16_t addr)
{ {
uint16_t v = read_word(addr & ~1); uint16_t v = read_word(addr & ~1);

2
rk05.h
View file

@ -46,6 +46,8 @@ public:
void begin() override; void begin() override;
void reset() override; void reset() override;
void show_state(console *const cnsl) const override;
#if IS_POSIX #if IS_POSIX
json_t *serialize() const; json_t *serialize() const;
static rk05 *deserialize(const json_t *const j, bus *const b); static rk05 *deserialize(const json_t *const j, bus *const b);

View file

@ -60,6 +60,18 @@ void rl02::reset()
sector = 0; sector = 0;
} }
void rl02::show_state(console *const cnsl) const
{
cnsl->put_string_lf(format("CSR: %06o", registers[0]));
cnsl->put_string_lf(format("BAR: %06o", registers[1]));
cnsl->put_string_lf(format("DAR: %06o", registers[2]));
cnsl->put_string_lf(format("MPR: %06o / %06o / %06o", mpr[0], mpr[1], mpr[2]));
cnsl->put_string_lf(format("track : %d", track ));
cnsl->put_string_lf(format("head : %d", head ));
cnsl->put_string_lf(format("sector: %d", sector));
}
#if IS_POSIX #if IS_POSIX
json_t *rl02::serialize() const json_t *rl02::serialize() const
{ {

2
rl02.h
View file

@ -53,6 +53,8 @@ public:
void begin() override; void begin() override;
void reset() override; void reset() override;
void show_state(console *const cnsl) const override;
#if IS_POSIX #if IS_POSIX
json_t *serialize() const; json_t *serialize() const;
static rl02 *deserialize(const json_t *const j, bus *const b); static rl02 *deserialize(const json_t *const j, bus *const b);

View file

@ -43,6 +43,18 @@ void tm_11::load(const std::string & file)
reset(); reset();
} }
void tm_11::show_state(console *const cnsl) const
{
cnsl->put_string_lf(format("MTS : %06o", registers[0]));
cnsl->put_string_lf(format("MTC : %06o", registers[1]));
cnsl->put_string_lf(format("MTBRC : %06o", registers[2]));
cnsl->put_string_lf(format("MTCMA : %06o", registers[3]));
cnsl->put_string_lf(format("MTD : %06o", registers[4]));
cnsl->put_string_lf(format("MTRD : %06o", registers[5]));
cnsl->put_string_lf(format("offset: %d", offset ));
cnsl->put_string_lf(format("tape file: %s", tape_file.c_str()));
}
void tm_11::reset() void tm_11::reset()
{ {
memset(registers, 0x00, sizeof registers ); memset(registers, 0x00, sizeof registers );

View file

@ -41,6 +41,8 @@ public:
void reset() override; void reset() override;
void show_state(console *const cnsl) const override;
uint8_t read_byte(const uint16_t addr) override; uint8_t read_byte(const uint16_t addr) override;
uint16_t read_word(const uint16_t addr) override; uint16_t read_word(const uint16_t addr) override;

View file

@ -11,6 +11,7 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <winsock2.h> #include <winsock2.h>
#else #else
#include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -257,3 +258,18 @@ void set_nodelay(const int fd)
#endif #endif
DOLOG(warning, true, "Cannot disable nagle algorithm"); DOLOG(warning, true, "Cannot disable nagle algorithm");
} }
std::string get_endpoint_name(const int fd)
{
char host[64] { "?" };
char serv[32] { "?" };
sockaddr_in6 addr { 0 };
socklen_t addr_len = sizeof addr;
if (getpeername(fd, reinterpret_cast<sockaddr *>(&addr), &addr_len) == -1)
return format("FAILED TO FIND NAME OF %d: %s", fd, strerror(errno));
getnameinfo(reinterpret_cast<sockaddr *>(&addr), addr_len, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);
return std::string(host) + "." + std::string(serv);
}

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 <stdint.h> #include <stdint.h>
@ -27,3 +27,4 @@ ssize_t READ(int fd, char *whereto, size_t len);
void update_word(uint16_t *const w, const bool msb, const uint8_t v); void update_word(uint16_t *const w, const bool msb, const uint8_t v);
void set_nodelay(const int fd); void set_nodelay(const int fd);
std::string get_endpoint_name(const int fd);