mirror of
https://github.com/akuker/RASCSI.git
synced 2024-09-27 15:57:52 +00:00
added primary/secondary logic for shared mem
This commit is contained in:
parent
119a33fc61
commit
0bd201ea64
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ¤t, const DataSample &previous);
|
||||
void TestClient();
|
||||
|
||||
bool enable_debug = false;
|
||||
|
||||
unique_ptr<SharedMemory> signals;
|
||||
|
||||
uint32_t prev_data;
|
||||
|
||||
bool running;
|
||||
|
||||
bool test_mode = false;
|
||||
};
|
||||
|
100
cpp/scsisim/scsisim_debug.cpp
Normal file
100
cpp/scsisim/scsisim_debug.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user