mirror of
https://github.com/akuker/RASCSI.git
synced 2024-06-09 11:29:31 +00:00
172 lines
4.5 KiB
C++
172 lines
4.5 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// SCSI Target Emulator PiSCSI for Raspberry Pi
|
|
//
|
|
// Copyright (C) 2023 akuker
|
|
//
|
|
// [ SCSI Bus Emulator ]
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
#include "scsisim_core.h"
|
|
#include "hal/data_sample_raspberry.h"
|
|
#include "shared/log.h"
|
|
#include "shared/piscsi_util.h"
|
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
|
|
|
#include "scsisim_defs.h"
|
|
#include <iostream>
|
|
#include <signal.h>
|
|
#include <sys/mman.h>
|
|
|
|
#if defined CONNECT_TYPE_STANDARD
|
|
#include "hal/connection_type/connection_standard.h"
|
|
#elif defined CONNECT_TYPE_FULLSPEC
|
|
#include "hal/connection_type/connection_fullspec.h"
|
|
#elif defined CONNECT_TYPE_AIBOM
|
|
#include "hal/connection_type/connection_aibom.h"
|
|
#elif defined CONNECT_TYPE_GAMERNIUM
|
|
#include "hal/connection_type/connection_gamernium.h"
|
|
#else
|
|
#include "hal/connection_type/connection_gamernium.h"
|
|
#endif
|
|
|
|
using namespace std;
|
|
using namespace spdlog;
|
|
|
|
string current_log_level = "unknown"; // Some versions of spdlog do not support get_log_level()
|
|
|
|
static ScsiSim* scsi_sim;
|
|
|
|
void ScsiSim::Banner(const vector<char*>& args) const
|
|
{
|
|
cout << piscsi_util::Banner("(SCSI Bus Simulator)");
|
|
cout << "Connection type: " << CONNECT_DESC << '\n' << flush;
|
|
|
|
if ((args.size() > 1 && strcmp(args[1], "-h") == 0) || (args.size() > 1 && strcmp(args[1], "--help") == 0)) {
|
|
cout << "\nUsage: " << args[0] << " [-L log_level] ...\n\n";
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ScsiSim::TerminationHandler(int signum)
|
|
{
|
|
(void)signum;
|
|
// scsi_sim->TeardownSharedMemory();
|
|
scsi_sim->running = false;
|
|
// exit(signum);
|
|
}
|
|
|
|
bool ScsiSim::ParseArgument(const vector<char*>& args)
|
|
{
|
|
string name;
|
|
string log_level;
|
|
|
|
const char* locale = setlocale(LC_MESSAGES, "");
|
|
if (locale == nullptr || !strcmp(locale, "C")) {
|
|
locale = "en";
|
|
}
|
|
|
|
opterr = 1;
|
|
int opt;
|
|
|
|
while ((opt = getopt(static_cast<int>(args.size()), args.data(), "-L:t")) != -1) {
|
|
switch (opt) {
|
|
case 'L':
|
|
log_level = optarg;
|
|
continue;
|
|
case 't':
|
|
test_mode = true;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
if (optopt) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!log_level.empty()) {
|
|
piscsi_log_level::set_log_level(log_level);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int ScsiSim::run(const vector<char*>& args)
|
|
{
|
|
running = true;
|
|
scsi_sim = this;
|
|
|
|
// added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.
|
|
setvbuf(stdout, nullptr, _IONBF, 0);
|
|
|
|
// Output the Banner
|
|
Banner(args);
|
|
|
|
// Create a thread-safe stdout logger to process the log messages
|
|
const auto logger = stdout_color_mt("scsisim stdout logger");
|
|
set_level(level::info);
|
|
current_log_level = "info";
|
|
|
|
vector<string> error_list;
|
|
|
|
if (!ParseArgument(args)) {
|
|
return -1;
|
|
}
|
|
|
|
// We just want to run the test client. After we're done, we can
|
|
// return.
|
|
if (test_mode) {
|
|
TestClient();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
// Signal handler to detach all devices on a KILL or TERM signal
|
|
struct sigaction termination_handler;
|
|
termination_handler.sa_handler = TerminationHandler;
|
|
sigemptyset(&termination_handler.sa_mask);
|
|
termination_handler.sa_flags = 0;
|
|
sigaction(SIGINT, &termination_handler, nullptr);
|
|
sigaction(SIGTERM, &termination_handler, nullptr);
|
|
|
|
signals = make_unique<SharedMemory>(SHARED_MEM_NAME, true);
|
|
|
|
uint32_t prev_value = signals->get();
|
|
int dot_counter = 0;
|
|
int char_counter = 0;
|
|
while (running) {
|
|
if (enable_debug) {
|
|
uint32_t new_value = signals->get();
|
|
|
|
// Note, this won't necessarily print ever data change. It will
|
|
// just give an indication of activity
|
|
PrintDifferences(DataSample_Raspberry(new_value), DataSample_Raspberry(prev_value));
|
|
|
|
prev_value = new_value;
|
|
|
|
if (++dot_counter > 100) {
|
|
if (char_counter == 0) {
|
|
std::cout << "\r/" << flush;
|
|
|
|
} else if (char_counter == 1) {
|
|
std::cout << "\r-" << flush;
|
|
|
|
} else if (char_counter == 2) {
|
|
std::cout << "\r\\" << flush;
|
|
|
|
} else if (char_counter == 3) {
|
|
std::cout << "\r|" << flush;
|
|
}
|
|
char_counter = (char_counter + 1) % 4;
|
|
dot_counter = 0;
|
|
}
|
|
}
|
|
usleep(1000);
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|