added primary/secondary logic for shared mem

This commit is contained in:
Tony Kuker 2023-02-02 20:35:54 -06:00
parent 119a33fc61
commit 0bd201ea64
8 changed files with 194 additions and 45 deletions

View File

@ -100,6 +100,9 @@ class DataSample_Raspberry final : public DataSample
DataSample_Raspberry(const uint32_t in_data, const uint64_t in_timestamp) : DataSample{in_timestamp}, data{in_data}
{
}
DataSample_Raspberry(const uint32_t in_data) : DataSample{0}, data{in_data}
{
}
DataSample_Raspberry() = default;
~DataSample_Raspberry() override = default;

View File

@ -32,31 +32,23 @@ bool GPIOBUS_Virtual::Init(mode_e mode)
GPIO_FUNCTION_TRACE
GPIOBUS::Init(mode);
LOGTRACE("%s Setting up shared memory", __PRETTY_FUNCTION__)
signals = make_unique<SharedMemory>(SHARED_MEM_NAME);
if(!signals->is_valid()){
LOGWARN("Unable to setup shared memory. Do you have scsisim running? Are you running as root?")
}else
{
LOGINFO("Successfully mapped shared memory")
}
return true;
}
void GPIOBUS_Virtual::Cleanup()
{
// Set control signals
PinSetSignal(PIN_ENB, OFF);
PinSetSignal(PIN_ACT, OFF);
PinSetSignal(PIN_TAD, OFF);
PinSetSignal(PIN_IND, OFF);
PinSetSignal(PIN_DTD, OFF);
PinConfig(PIN_ACT, GPIO_INPUT);
PinConfig(PIN_TAD, GPIO_INPUT);
PinConfig(PIN_IND, GPIO_INPUT);
PinConfig(PIN_DTD, GPIO_INPUT);
LOGTRACE("%s", __PRETTY_FUNCTION__)
// Initialize all signals
for (int i = 0; SignalTable[i] >= 0; i++) {
int pin = SignalTable[i];
PinSetSignal(pin, OFF);
PinConfig(pin, GPIO_INPUT);
PullConfig(pin, GPIO_PULLNONE);
}
}
void GPIOBUS_Virtual::Reset()

View File

@ -38,7 +38,9 @@ using namespace piscsi_util;
void ScsiDump::CleanUp()
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
if (bus != nullptr) {
LOGTRACE("%s trying bus cleanup", __PRETTY_FUNCTION__)
bus->Cleanup();
}
}
@ -198,6 +200,7 @@ void ScsiDump::Command(scsi_command cmd, vector<uint8_t>& cdb) const
void ScsiDump::DataIn(int length)
{
LOGTRACE("%s length: %d", __PRETTY_FUNCTION__, length)
WaitPhase(phase_t::datain);
if (!bus->ReceiveHandShake(buffer.data(), length)) {
@ -207,6 +210,8 @@ void ScsiDump::DataIn(int length)
void ScsiDump::DataOut(int length)
{
LOGTRACE("%s length: %d", __PRETTY_FUNCTION__, length)
WaitPhase(phase_t::dataout);
if (!bus->SendHandShake(buffer.data(), length, BUS::SEND_NO_DELAY)) {
@ -216,6 +221,8 @@ void ScsiDump::DataOut(int length)
void ScsiDump::Status() const
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
WaitPhase(phase_t::status);
if (array<uint8_t, 256> buf; bus->ReceiveHandShake(buf.data(), 1) != 1) {
@ -225,6 +232,8 @@ void ScsiDump::Status() const
void ScsiDump::MessageIn() const
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
WaitPhase(phase_t::msgin);
if (array<uint8_t, 256> buf; bus->ReceiveHandShake(buf.data(), 1) != 1) {
@ -239,6 +248,8 @@ void ScsiDump::BusFree() const
void ScsiDump::TestUnitReady() const
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
vector<uint8_t> cdb(6);
Command(scsi_command::eCmdTestUnitReady, cdb);
@ -251,6 +262,8 @@ void ScsiDump::TestUnitReady() const
void ScsiDump::RequestSense()
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
vector<uint8_t> cdb(6);
cdb[4] = 0xff;
Command(scsi_command::eCmdRequestSense, cdb);
@ -282,6 +295,8 @@ void ScsiDump::Inquiry()
pair<uint64_t, uint32_t> ScsiDump::ReadCapacity()
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
vector<uint8_t> cdb(10);
Command(scsi_command::eCmdReadCapacity10, cdb);
@ -330,6 +345,8 @@ pair<uint64_t, uint32_t> ScsiDump::ReadCapacity()
void ScsiDump::Read10(uint32_t bstart, uint32_t blength, uint32_t length)
{
LOGTRACE("%s start:%d blen:%d len:%d", __PRETTY_FUNCTION__, bstart, blength, length)
vector<uint8_t> cdb(10);
cdb[2] = (uint8_t)(bstart >> 24);
cdb[3] = (uint8_t)(bstart >> 16);
@ -350,6 +367,8 @@ void ScsiDump::Read10(uint32_t bstart, uint32_t blength, uint32_t length)
void ScsiDump::Write10(uint32_t bstart, uint32_t blength, uint32_t length)
{
LOGTRACE("%s start:%d blen:%d len:%d", __PRETTY_FUNCTION__, bstart, blength, length)
vector<uint8_t> cdb(10);
cdb[2] = (uint8_t)(bstart >> 24);
cdb[3] = (uint8_t)(bstart >> 16);
@ -370,6 +389,7 @@ void ScsiDump::Write10(uint32_t bstart, uint32_t blength, uint32_t length)
void ScsiDump::WaitForBusy() const
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
// Wait for busy for up to 2 s
int count = 10000;
do {
@ -404,18 +424,18 @@ int ScsiDump::run(const vector<char*>& args)
try {
ParseArguments(args);
// #ifndef USE_SEL_EVENT_ENABLE
// cerr << "Error: No PiSCSI hardware support" << endl;
// return EXIT_FAILURE;
// #endif
// #ifndef USE_SEL_EVENT_ENABLE
// cerr << "Error: No PiSCSI hardware support" << endl;
// return EXIT_FAILURE;
// #endif
return DumpRestore();
} catch (const parser_exception& e) {
cerr << "Error: " << e.what() << endl;
CleanUp();
// CleanUp();
return EXIT_FAILURE;
// return EXIT_FAILURE;
}
CleanUp();
@ -425,6 +445,8 @@ int ScsiDump::run(const vector<char*>& args)
int ScsiDump::DumpRestore()
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
const auto inq_info = GetDeviceInfo();
fstream fs;
@ -524,6 +546,7 @@ int ScsiDump::DumpRestore()
ScsiDump::inquiry_info_t ScsiDump::GetDeviceInfo()
{
LOGTRACE("%s", __PRETTY_FUNCTION__)
// Assert RST for 1 ms
bus->SetRST(true);
const timespec ts = {.tv_sec = 0, .tv_nsec = 1000 * 1000};

View File

@ -11,6 +11,7 @@
#include "shared/log.h"
#include "shared/piscsi_util.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "hal/data_sample_raspberry.h"
#include "scsisim_defs.h"
#include <iostream>
@ -97,12 +98,14 @@ bool ScsiSim::ParseArgument(const vector<char*>& args)
opterr = 1;
int opt;
while ((opt = getopt(static_cast<int>(args.size()), args.data(), "-L:")) != -1) {
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;
}
@ -141,6 +144,13 @@ int ScsiSim::run(const vector<char*>& 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;
@ -149,26 +159,30 @@ int ScsiSim::run(const vector<char*>& args)
sigaction(SIGINT, &termination_handler, nullptr);
sigaction(SIGTERM, &termination_handler, nullptr);
signals = make_unique<SharedMemory>(SHARED_MEM_NAME);
signals = make_unique<SharedMemory>(SHARED_MEM_NAME, true);
uint32_t prev_value = -1;
uint32_t prev_value = signals->get();
int dot_counter = 0;
while (running) {
if (enable_debug) {
uint32_t new_value = signals->get();
PrintDifferences(DataSample_Raspberry(new_value), DataSample_Raspberry(prev_value));
// Note, this won't necessarily print ever data change. It will
// just give an indication of activity
if (new_value != prev_value) {
LOGTRACE("%s Value changed to %08X", __PRETTY_FUNCTION__, new_value);
prev_value = new_value;
}
prev_value = new_value;
if(++dot_counter > 1000){
printf(".");
dot_counter = 0;
}
}
}
usleep(1000);
}
return 0;
return EXIT_SUCCESS;
}

View File

@ -13,6 +13,7 @@
#include <vector>
#include "shared/shared_memory.h"
#include "hal/data_sample.h"
using namespace std;
@ -33,9 +34,16 @@ class ScsiSim
int InitSharedMemory();
void TeardownSharedMemory();
void PrintDifferences(const DataSample &current, const DataSample &previous);
void TestClient();
bool enable_debug = false;
unique_ptr<SharedMemory> signals;
uint32_t prev_data;
bool running;
bool test_mode = false;
};

View File

@ -0,0 +1,100 @@
//---------------------------------------------------------------------------
//
// SCSI Target Emulator PiSCSI for Raspberry Pi
//
// Copyright (C) 2023 akuker
//
// [ SCSI Bus Emulator ]
//
//---------------------------------------------------------------------------
#include "scsisim_core.h"
#include "shared/log.h"
#include "shared/piscsi_util.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "hal/gpiobus_factory.h"
#include "hal/data_sample.h"
#include "scsisim_defs.h"
#include <iomanip>
#include <iostream>
#include <signal.h>
#include <sstream>
#include <sys/mman.h>
void ScsiSim::PrintDifferences(const DataSample& current, const DataSample& previous)
{
if (current.GetRawCapture() != previous.GetRawCapture()) {
stringstream s;
s << "Data changed: <";
// << setfill('0') << setw(2) << hex << GetBuffer()[0];
// logger.Trace(s.str());
if (current.GetDAT() != previous.GetDAT()) {
s << "DAT(" << setw(2) << hex << (int)current.GetDAT() << ") ";
}
if (current.GetBSY() != previous.GetBSY()) {
s << "BSY(" << current.GetBSY() << ") ";
}
if (current.GetSEL() != previous.GetSEL()) {
s << "SEL(" << current.GetSEL() << ") ";
}
if (current.GetATN() != previous.GetATN()) {
s << "ATN(" << current.GetATN() << ") ";
}
if (current.GetACK() != previous.GetACK()) {
s << "ACK(" << current.GetACK() << ") ";
}
if (current.GetRST() != previous.GetRST()) {
s << "RST(" << current.GetRST() << ") ";
}
if (current.GetMSG() != previous.GetMSG()) {
s << "MSG(" << current.GetMSG() << ") ";
};
if (current.GetCD() != previous.GetCD()) {
s << "CD(" << current.GetCD() << ") ";
}
if (current.GetIO() != previous.GetIO()) {
s << "IO(" << current.GetIO() << ") ";
}
if (current.GetREQ() != previous.GetREQ()) {
s << "REQ(" << current.GetREQ() << ") ";
}
if (current.GetACT() != previous.GetACT()) {
s << "ACT(" << current.GetACT() << ") ";
}
s << ">" << flush;
LOGTRACE("%s", s.str().c_str());
}
}
void ScsiSim::TestClient(){
LOGINFO("TESTING!!!")
int sleep_time = 10000;
unique_ptr<BUS> bus = GPIOBUS_Factory::Create(BUS::mode_e::INITIATOR);
LOGINFO("bus->SetBSY"); bus->SetBSY(1); usleep(sleep_time); bus->SetBSY(0); usleep(sleep_time);
LOGINFO("bus->SetSEL"); bus->SetSEL(1); usleep(sleep_time); bus->SetSEL(0); usleep(sleep_time);
LOGINFO("bus->SetATN"); bus->SetATN(1); usleep(sleep_time); bus->SetATN(0); usleep(sleep_time);
LOGINFO("bus->SetACK"); bus->SetACK(1); usleep(sleep_time); bus->SetACK(0); usleep(sleep_time);
LOGINFO("bus->SetRST"); bus->SetRST(1); usleep(sleep_time); bus->SetRST(0); usleep(sleep_time);
LOGINFO("bus->SetMSG"); bus->SetMSG(1); usleep(sleep_time); bus->SetMSG(0); usleep(sleep_time);
LOGINFO("bus->SetCD"); bus->SetCD(1); usleep(sleep_time); bus->SetCD(0); usleep(sleep_time);
LOGINFO("bus->SetIO"); bus->SetIO(1); usleep(sleep_time); bus->SetIO(0); usleep(sleep_time);
LOGINFO("bus->SetREQ"); bus->SetREQ(1); usleep(sleep_time); bus->SetREQ(0); usleep(sleep_time);
LOGINFO("bus->SetACT"); bus->SetACT(1); usleep(sleep_time); bus->SetACT(0); usleep(sleep_time);
for(uint32_t i = 0; i <= 0xFF; i++){
LOGINFO("bus->SetDAT(%02X)", i); bus->SetDAT((uint8_t)i); usleep(sleep_time); bus->SetDAT(0); usleep(sleep_time);
}
// LOGINFO("bus->SetDAT(0x01)"); bus->SetDAT(1); usleep(sleep_time); bus->SetDAT(0); usleep(sleep_time);
// LOGINFO("bus->SetDAT(0xFF)"); bus->SetDAT(1); usleep(sleep_time); bus->SetDAT(0); usleep(sleep_time);
if (bus != nullptr) {
LOGTRACE("%s trying bus cleanup", __PRETTY_FUNCTION__)
bus->Cleanup();
}
}

View File

@ -10,12 +10,17 @@
#include <fcntl.h>
#include <sys/stat.h>
SharedMemory::SharedMemory(std::string region_name) : m_valid(true), m_name(region_name)
SharedMemory::SharedMemory(std::string region_name, bool is_primary)
: m_valid(true), m_primary(is_primary), m_name(region_name)
{
LOGINFO("%s Opening shared memory %s", __PRETTY_FUNCTION__, region_name.c_str())
// Get shared memory
int mode = S_IRWXU | S_IRWXG;
if ((m_fd_shared_mem = shm_open(region_name.c_str(), O_RDWR | O_CREAT | O_TRUNC, mode)) == -1) {
int mode = S_IRWXU | S_IRWXG;
int oflag = O_RDWR | O_TRUNC;
if (is_primary) {
oflag |= O_CREAT;
}
if ((m_fd_shared_mem = shm_open(region_name.c_str(), oflag, mode)) == -1) {
LOGERROR("Unable to open shared memory %s. Is scsisim already running?", region_name.c_str());
m_valid = false;
return;
@ -42,21 +47,20 @@ SharedMemory::SharedMemory(std::string region_name) : m_valid(true), m_name(regi
LOGINFO("%s Shared memory region successfully memory mapped", __PRETTY_FUNCTION__)
}
// Note: The normal logging functions can not be used here. The logger objects
// may have been freed by the time we get to this point
SharedMemory::~SharedMemory()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
// printf("%s", __PRETTY_FUNCTION__);
if (m_shared_mem != nullptr) {
if (munmap(m_shared_mem, sizeof(lockable_data_t)) == 0) {
LOGTRACE("munmap successful");
} else {
LOGWARN("munmap NOT successful ERROR!!!");
if (munmap(m_shared_mem, sizeof(lockable_data_t)) != 0) {
printf("WARNING: munmap NOT successful!\n");
}
}
LOGTRACE("%s Unlinking shared memory", __PRETTY_FUNCTION__);
if (shm_unlink(m_name.c_str()) == 0) {
LOGTRACE("shm_unlink success");
} else {
LOGWARN("shm_unlink failed!!!");
if (m_primary) {
// printf("%s Unlinking shared memory", __PRETTY_FUNCTION__);
if (shm_unlink(m_name.c_str()) != 0) {
printf("WARNING: shm_unlink failed!!!\n");
}
}
}

View File

@ -21,7 +21,7 @@
class SharedMemory
{
public:
SharedMemory(std::string);
SharedMemory(std::string, bool is_primary=false);
~SharedMemory();
inline uint32_t get() const
@ -48,6 +48,10 @@ class SharedMemory
}
}
inline bool is_valid(){
return m_valid;
}
private:
typedef struct lockable_data {
mutable std::shared_mutex mutex_;
@ -57,6 +61,7 @@ class SharedMemory
lockable_data_t* m_shared_mem;
bool m_valid;
bool m_primary;
int m_fd_shared_mem;
std::string m_name;
};