mirror of
https://github.com/akuker/RASCSI.git
synced 2026-04-24 07:16:46 +00:00
Improved testability of rascsi/rasctl/scsimon/rasdump, eliminated global fields (#960)
* Moved rascsi/rasctl/scsimon/rasdump.cpp to classes (for better testability) * Moved bus.* to hal folder * Removed some global variables * Fixed code redundancies
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// X68000 EMULATOR "XM6"
|
||||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
// Copyright (C) 2022 Uwe Seimet
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get the number of bytes for a command
|
||||
// TODO Add the byte count to the enum value/command name mapping and remove the comparisons
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int BUS::GetCommandByteCount(uint8_t opcode)
|
||||
{
|
||||
if (opcode == 0x88 || opcode == 0x8A || opcode == 0x8F || opcode == 0x91 || opcode == 0x9E || opcode == 0x9F) {
|
||||
return 16;
|
||||
} else if (opcode == 0xA0) {
|
||||
return 12;
|
||||
} else if (opcode >= 0x20 && opcode <= 0x7D) {
|
||||
return 10;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Phase Acquisition
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BUS::phase_t BUS::GetPhase()
|
||||
{
|
||||
// Selection Phase
|
||||
if (GetSEL()) {
|
||||
return phase_t::selection;
|
||||
}
|
||||
|
||||
// Bus busy phase
|
||||
if (!GetBSY()) {
|
||||
return phase_t::busfree;
|
||||
}
|
||||
|
||||
// Get target phase from bus signal line
|
||||
int mci = GetMSG() ? 0b100 : 0b000;
|
||||
mci |= GetCD() ? 0b010 : 0b000;
|
||||
mci |= GetIO() ? 0b001 : 0b000;
|
||||
return GetPhase(mci);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Determine Phase String phase enum
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const char* BUS::GetPhaseStrRaw(phase_t current_phase) {
|
||||
const auto& it = phase_str_mapping.find(current_phase);
|
||||
return it != phase_str_mapping.end() ? it->second : "INVALID";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Phase Table
|
||||
// Reference Table 8: https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-06.html
|
||||
// This determines the phase based upon the Msg, C/D and I/O signals.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const array<BUS::phase_t, 8> BUS::phase_table = {
|
||||
// | MSG|C/D|I/O |
|
||||
phase_t::dataout, // | 0 | 0 | 0 |
|
||||
phase_t::datain, // | 0 | 0 | 1 |
|
||||
phase_t::command, // | 0 | 1 | 0 |
|
||||
phase_t::status, // | 0 | 1 | 1 |
|
||||
phase_t::reserved, // | 1 | 0 | 0 |
|
||||
phase_t::reserved, // | 1 | 0 | 1 |
|
||||
phase_t::msgout, // | 1 | 1 | 0 |
|
||||
phase_t::msgin // | 1 | 1 | 1 |
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Phase string to phase mapping
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const unordered_map<BUS::phase_t, const char*> BUS::phase_str_mapping = {
|
||||
{ phase_t::busfree, "busfree" },
|
||||
{ phase_t::arbitration, "arbitration" },
|
||||
{ phase_t::selection, "selection" },
|
||||
{ phase_t::reselection, "reselection" },
|
||||
{ phase_t::command, "command" },
|
||||
{ phase_t::datain, "datain" },
|
||||
{ phase_t::dataout, "dataout" },
|
||||
{ phase_t::status, "status" },
|
||||
{ phase_t::msgin, "msgin" },
|
||||
{ phase_t::msgout, "msgout" },
|
||||
{ phase_t::reserved, "reserved" }
|
||||
};
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// X68000 EMULATOR "XM6"
|
||||
//
|
||||
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
||||
// Copyright (C) 2014-2020 GIMONS
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scsi.h"
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BUS
|
||||
{
|
||||
public:
|
||||
// Operation modes definition
|
||||
enum class mode_e {
|
||||
TARGET = 0,
|
||||
INITIATOR = 1,
|
||||
MONITOR = 2,
|
||||
};
|
||||
|
||||
// Phase definitions
|
||||
enum class phase_t : int {
|
||||
busfree,
|
||||
arbitration,
|
||||
selection,
|
||||
reselection,
|
||||
command,
|
||||
datain,
|
||||
dataout,
|
||||
status,
|
||||
msgin,
|
||||
msgout,
|
||||
reserved
|
||||
};
|
||||
|
||||
BUS() = default;
|
||||
virtual ~BUS() = default;
|
||||
|
||||
static int GetCommandByteCount(uint8_t);
|
||||
|
||||
virtual bool Init(mode_e mode) = 0;
|
||||
virtual void Reset() = 0;
|
||||
virtual void Cleanup() = 0;
|
||||
phase_t GetPhase();
|
||||
|
||||
static phase_t GetPhase(int mci)
|
||||
{
|
||||
return phase_table[mci];
|
||||
}
|
||||
|
||||
// Get the string phase name, based upon the raw data
|
||||
static const char* GetPhaseStrRaw(phase_t current_phase);
|
||||
|
||||
// Extract as specific pin field from a raw data capture
|
||||
static inline uint32_t GetPinRaw(uint32_t raw_data, uint32_t pin_num)
|
||||
{
|
||||
return ((raw_data >> pin_num) & 1);
|
||||
}
|
||||
|
||||
virtual bool GetBSY() const = 0;
|
||||
virtual void SetBSY(bool ast) = 0;
|
||||
|
||||
virtual bool GetSEL() const = 0;
|
||||
virtual void SetSEL(bool ast) = 0;
|
||||
|
||||
virtual bool GetATN() const = 0;
|
||||
virtual void SetATN(bool ast) = 0;
|
||||
|
||||
virtual bool GetACK() const = 0;
|
||||
virtual void SetACK(bool ast) = 0;
|
||||
|
||||
virtual bool GetRST() const = 0;
|
||||
virtual void SetRST(bool ast) = 0;
|
||||
|
||||
virtual bool GetMSG() const = 0;
|
||||
virtual void SetMSG(bool ast) = 0;
|
||||
|
||||
virtual bool GetCD() const = 0;
|
||||
virtual void SetCD(bool ast) = 0;
|
||||
|
||||
virtual bool GetIO() = 0;
|
||||
virtual void SetIO(bool ast) = 0;
|
||||
|
||||
virtual bool GetREQ() const = 0;
|
||||
virtual void SetREQ(bool ast) = 0;
|
||||
|
||||
virtual uint8_t GetDAT() = 0;
|
||||
virtual void SetDAT(uint8_t dat) = 0;
|
||||
virtual bool GetDP() const = 0; // Get parity signal
|
||||
|
||||
virtual uint32_t Acquire() = 0;
|
||||
virtual int CommandHandShake(uint8_t *buf) = 0;
|
||||
virtual int ReceiveHandShake(uint8_t *buf, int count) = 0;
|
||||
virtual int SendHandShake(uint8_t *buf, int count, int delay_after_bytes) = 0;
|
||||
|
||||
virtual bool GetSignal(int pin) const = 0;
|
||||
// Get SCSI input signal value
|
||||
virtual void SetSignal(int pin, bool ast) = 0;
|
||||
// Set SCSI output signal value
|
||||
static const int SEND_NO_DELAY = -1;
|
||||
// Passed into SendHandShake when we don't want to delay
|
||||
private:
|
||||
static const array<phase_t, 8> phase_table;
|
||||
|
||||
static const unordered_map<phase_t, const char *> phase_str_mapping;
|
||||
};
|
||||
@@ -35,7 +35,7 @@ const std::string SBC_Version::m_str_unknown_sbc = "Unknown SBC";
|
||||
// "Raspberry Pi 4 Model B" will match with both of the following:
|
||||
// - Raspberry Pi 4 Model B Rev 1.4
|
||||
// - Raspberry Pi 4 Model B Rev 1.3
|
||||
const std::map<std::string, SBC_Version::sbc_version_type> SBC_Version::m_proc_device_tree_mapping = {
|
||||
const std::map<std::string, SBC_Version::sbc_version_type, std::less<>> SBC_Version::m_proc_device_tree_mapping = {
|
||||
{"Raspberry Pi 1 Model ", sbc_version_type::sbc_raspberry_pi_1},
|
||||
{"Raspberry Pi 2 Model ", sbc_version_type::sbc_raspberry_pi_2_3},
|
||||
{"Raspberry Pi 3 Model ", sbc_version_type::sbc_raspberry_pi_2_3},
|
||||
@@ -212,4 +212,4 @@ uint32_t SBC_Version::GetPeripheralAddress(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,7 @@ class SBC_Version
|
||||
static const std::string m_str_bananapi_m4;
|
||||
static const std::string m_str_unknown_sbc;
|
||||
|
||||
static const std::map<std::string, sbc_version_type> m_proc_device_tree_mapping;
|
||||
static const std::map<std::string, sbc_version_type, std::less<>> m_proc_device_tree_mapping;
|
||||
|
||||
static const std::string m_device_tree_model_path;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user