mirror of
https://github.com/akuker/RASCSI.git
synced 2024-06-09 11:29:31 +00:00
basic shared mem communication
This commit is contained in:
parent
33cd41b205
commit
4ec6424446
24
cpp/Makefile
24
cpp/Makefile
|
@ -59,6 +59,7 @@ SCSIDUMP = scsidump
|
||||||
SCSIMON = scsimon
|
SCSIMON = scsimon
|
||||||
PISCSI_TEST = piscsi_test
|
PISCSI_TEST = piscsi_test
|
||||||
SCSILOOP = scsiloop
|
SCSILOOP = scsiloop
|
||||||
|
SCSISIM = scsisim
|
||||||
|
|
||||||
SYSTEMD_CONF = /etc/systemd/system/piscsi.service
|
SYSTEMD_CONF = /etc/systemd/system/piscsi.service
|
||||||
RSYSLOG_CONF = /etc/rsyslog.d/piscsi.conf
|
RSYSLOG_CONF = /etc/rsyslog.d/piscsi.conf
|
||||||
|
@ -79,7 +80,8 @@ BIN_ALL = \
|
||||||
$(BINDIR)/$(SCSICTL) \
|
$(BINDIR)/$(SCSICTL) \
|
||||||
$(BINDIR)/$(SCSIMON) \
|
$(BINDIR)/$(SCSIMON) \
|
||||||
$(BINDIR)/$(SCSIDUMP) \
|
$(BINDIR)/$(SCSIDUMP) \
|
||||||
$(BINDIR)/$(SCSILOOP)
|
$(BINDIR)/$(SCSILOOP) \
|
||||||
|
$(BINDIR)/$(SCSISIM)
|
||||||
|
|
||||||
SRC_PROTOC = piscsi_interface.proto
|
SRC_PROTOC = piscsi_interface.proto
|
||||||
|
|
||||||
|
@ -91,7 +93,8 @@ SRC_PROTOBUF = \
|
||||||
|
|
||||||
SRC_SHARED = \
|
SRC_SHARED = \
|
||||||
shared/piscsi_version.cpp \
|
shared/piscsi_version.cpp \
|
||||||
shared/piscsi_util.cpp
|
shared/piscsi_util.cpp \
|
||||||
|
shared/shared_memory.cpp
|
||||||
|
|
||||||
SRC_PISCSI_CORE = $(shell find ./piscsi -name '*.cpp')
|
SRC_PISCSI_CORE = $(shell find ./piscsi -name '*.cpp')
|
||||||
SRC_PISCSI_CORE += $(shell find ./controllers -name '*.cpp')
|
SRC_PISCSI_CORE += $(shell find ./controllers -name '*.cpp')
|
||||||
|
@ -120,12 +123,15 @@ SRC_SCSILOOP = scsiloop.cpp
|
||||||
SRC_SCSILOOP += $(shell find ./scsiloop -name '*.cpp')
|
SRC_SCSILOOP += $(shell find ./scsiloop -name '*.cpp')
|
||||||
SRC_SCSILOOP += $(shell find ./hal -name '*.cpp')
|
SRC_SCSILOOP += $(shell find ./hal -name '*.cpp')
|
||||||
|
|
||||||
|
SRC_SCSISIM = scsisim.cpp
|
||||||
|
SRC_SCSISIM += $(shell find ./scsisim -name '*.cpp')
|
||||||
|
|
||||||
vpath %.h ./ ./shared ./controllers ./devices ./monitor ./hal \
|
vpath %.h ./ ./shared ./controllers ./devices ./monitor ./hal \
|
||||||
./hal/boards ./hal/pi_defs ./piscsi ./scsictl ./scsidump \
|
./hal/boards ./hal/pi_defs ./piscsi ./scsictl ./scsidump \
|
||||||
./scsiloop
|
./scsiloop ./scsisim
|
||||||
vpath %.cpp ./ ./shared ./controllers ./devices ./monitor ./hal \
|
vpath %.cpp ./ ./shared ./controllers ./devices ./monitor ./hal \
|
||||||
./hal/boards ./hal/pi_defs ./piscsi ./scsictl ./scsidump \
|
./hal/boards ./hal/pi_defs ./piscsi ./scsictl ./scsidump \
|
||||||
./scsiloop ./test
|
./scsiloop ./scsisim ./test
|
||||||
vpath %.o ./$(OBJDIR)
|
vpath %.o ./$(OBJDIR)
|
||||||
vpath ./$(BINDIR)
|
vpath ./$(BINDIR)
|
||||||
|
|
||||||
|
@ -138,6 +144,7 @@ OBJ_SCSIDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIDUMP:%.cpp=%.o)))
|
||||||
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
|
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
|
||||||
OBJ_PISCSI_TEST := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PISCSI_TEST:%.cpp=%.o)))
|
OBJ_PISCSI_TEST := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PISCSI_TEST:%.cpp=%.o)))
|
||||||
OBJ_SCSILOOP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSILOOP:%.cpp=%.o)))
|
OBJ_SCSILOOP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSILOOP:%.cpp=%.o)))
|
||||||
|
OBJ_SCSISIM := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSISIM:%.cpp=%.o)))
|
||||||
OBJ_SHARED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SHARED:%.cpp=%.o)))
|
OBJ_SHARED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SHARED:%.cpp=%.o)))
|
||||||
OBJ_PROTOBUF := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PROTOBUF:%.cpp=%.o)))
|
OBJ_PROTOBUF := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PROTOBUF:%.cpp=%.o)))
|
||||||
OBJ_GENERATED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_GENERATED:%.cpp=%.o)))
|
OBJ_GENERATED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_GENERATED:%.cpp=%.o)))
|
||||||
|
@ -151,7 +158,7 @@ TEST_WRAPS = -Wl,--wrap=fopen64
|
||||||
|
|
||||||
# The following will include all of the auto-generated dependency files (*.d)
|
# The following will include all of the auto-generated dependency files (*.d)
|
||||||
# if they exist. This will trigger a rebuild of a source file if a header changes
|
# if they exist. This will trigger a rebuild of a source file if a header changes
|
||||||
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_PISCSI_CORE) $(OBJ_SCSICTL_CORE) $(OBJ_PISCSI) $(OBJ_SCSICTL) $(OBJ_SCSIDUMP) $(OBJ_SCSIMON) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_PISCSI_TEST) $(OBJ_SCSILOOP))
|
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_PISCSI_CORE) $(OBJ_SCSICTL_CORE) $(OBJ_PISCSI) $(OBJ_SCSICTL) $(OBJ_SCSIDUMP) $(OBJ_SCSIMON) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(OBJ_PISCSI_TEST) $(OBJ_SCSILOOP) $(OBJ_SCSISIM))
|
||||||
-include $(ALL_DEPS)
|
-include $(ALL_DEPS)
|
||||||
|
|
||||||
$(OBJDIR) $(BINDIR):
|
$(OBJDIR) $(BINDIR):
|
||||||
|
@ -216,14 +223,18 @@ $(BINDIR)/$(PISCSI_TEST): $(SRC_GENERATED) $(OBJ_PISCSI_CORE) $(OBJ_SCSICTL_CORE
|
||||||
$(BINDIR)/$(SCSILOOP): $(OBJ_SHARED) $(OBJ_SCSILOOP) | $(BINDIR)
|
$(BINDIR)/$(SCSILOOP): $(OBJ_SHARED) $(OBJ_SCSILOOP) | $(BINDIR)
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SHARED) $(OBJ_SCSILOOP)
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SHARED) $(OBJ_SCSILOOP)
|
||||||
|
|
||||||
|
$(BINDIR)/$(SCSISIM): $(OBJ_SHARED) $(OBJ_SCSISIM) | $(BINDIR)
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SHARED) $(OBJ_SCSISIM)
|
||||||
|
|
||||||
# Phony rules for building individual utilities
|
# Phony rules for building individual utilities
|
||||||
.PHONY: $(PISCSI) $(SCSICTL) $(SCSIDUMP) $(SCSIMON) $(PISCSI_TEST) $(SCSILOOP)
|
.PHONY: $(PISCSI) $(SCSICTL) $(SCSIDUMP) $(SCSIMON) $(PISCSI_TEST) $(SCSILOOP) $(SCSISIM)
|
||||||
$(PISCSI) : $(BINDIR)/$(PISCSI)
|
$(PISCSI) : $(BINDIR)/$(PISCSI)
|
||||||
$(SCSICTL) : $(BINDIR)/$(SCSICTL)
|
$(SCSICTL) : $(BINDIR)/$(SCSICTL)
|
||||||
$(SCSIDUMP) : $(BINDIR)/$(SCSIDUMP)
|
$(SCSIDUMP) : $(BINDIR)/$(SCSIDUMP)
|
||||||
$(SCSIMON) : $(BINDIR)/$(SCSIMON)
|
$(SCSIMON) : $(BINDIR)/$(SCSIMON)
|
||||||
$(PISCSI_TEST): $(BINDIR)/$(PISCSI_TEST)
|
$(PISCSI_TEST): $(BINDIR)/$(PISCSI_TEST)
|
||||||
$(SCSILOOP) : $(BINDIR)/$(SCSILOOP)
|
$(SCSILOOP) : $(BINDIR)/$(SCSILOOP)
|
||||||
|
$(SCSISIM) : $(BINDIR)/$(SCSISIM)
|
||||||
|
|
||||||
## clean : Remove all of the object files, intermediate
|
## clean : Remove all of the object files, intermediate
|
||||||
## compiler files and executable files
|
## compiler files and executable files
|
||||||
|
@ -255,6 +266,7 @@ install: \
|
||||||
$(USR_LOCAL_BIN)/$(SCSIMON) \
|
$(USR_LOCAL_BIN)/$(SCSIMON) \
|
||||||
$(USR_LOCAL_BIN)/$(SCSILOOP) \
|
$(USR_LOCAL_BIN)/$(SCSILOOP) \
|
||||||
$(USR_LOCAL_BIN)/$(SCSIDUMP) \
|
$(USR_LOCAL_BIN)/$(SCSIDUMP) \
|
||||||
|
$(USR_LOCAL_BIN)/$(SCSISIM) \
|
||||||
$(SYSTEMD_CONF) \
|
$(SYSTEMD_CONF) \
|
||||||
$(RSYSLOG_CONF) \
|
$(RSYSLOG_CONF) \
|
||||||
$(RSYSLOG_LOG)
|
$(RSYSLOG_LOG)
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "scsisim/scsisim_defs.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
bool GPIOBUS_Virtual::Init(mode_e mode)
|
bool GPIOBUS_Virtual::Init(mode_e mode)
|
||||||
|
@ -30,33 +32,7 @@ bool GPIOBUS_Virtual::Init(mode_e mode)
|
||||||
GPIO_FUNCTION_TRACE
|
GPIO_FUNCTION_TRACE
|
||||||
GPIOBUS::Init(mode);
|
GPIOBUS::Init(mode);
|
||||||
|
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
signals = make_unique<SharedMemory>(SHARED_MEM_NAME);
|
||||||
// Create a shared memory region that can be accessed as a virtual "SCSI bus"
|
|
||||||
// mutual exclusion semaphore, mutex_sem with an initial value 0.
|
|
||||||
if ((mutex_sem = sem_open(SHARED_MEM_MUTEX_NAME.c_str(), O_CREAT, 0660, 0)) == SEM_FAILED) {
|
|
||||||
LOGERROR("Unable to open shared memory semaphore %s. Are you running as root?", SHARED_MEM_MUTEX_NAME.c_str());
|
|
||||||
}
|
|
||||||
// Get shared memory
|
|
||||||
if ((fd_shm = shm_open(SHARED_MEM_NAME.c_str(), O_RDWR | O_CREAT | O_EXCL, 0660)) == -1) {
|
|
||||||
LOGERROR("Unable to open shared memory %s. Are you running as root?", SHARED_MEM_NAME.c_str());
|
|
||||||
sem_close(mutex_sem);
|
|
||||||
}
|
|
||||||
if (ftruncate(fd_shm, sizeof(uint32_t)) == -1) {
|
|
||||||
LOGERROR("Unable to read shared memory");
|
|
||||||
sem_close(mutex_sem);
|
|
||||||
shm_unlink(SHARED_MEM_NAME.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals = static_cast<uint32_t *>(mmap(NULL, sizeof(uint32_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0));
|
|
||||||
if (static_cast<void *>(signals) == MAP_FAILED) {
|
|
||||||
LOGERROR("Unabled to map shared memory");
|
|
||||||
sem_close(mutex_sem);
|
|
||||||
shm_unlink(SHARED_MEM_NAME.c_str());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
signals = make_shared<uint32_t>(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -81,12 +57,6 @@ void GPIOBUS_Virtual::Cleanup()
|
||||||
PinConfig(pin, GPIO_INPUT);
|
PinConfig(pin, GPIO_INPUT);
|
||||||
PullConfig(pin, GPIO_PULLNONE);
|
PullConfig(pin, GPIO_PULLNONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
munmap(static_cast<void *>(signals), sizeof(uint32_t));
|
|
||||||
shm_unlink(SHARED_MEM_NAME.c_str());
|
|
||||||
sem_close(mutex_sem);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPIOBUS_Virtual::Reset()
|
void GPIOBUS_Virtual::Reset()
|
||||||
|
@ -456,20 +426,7 @@ bool GPIOBUS_Virtual::GetSignal(int hw_pin) const
|
||||||
{
|
{
|
||||||
GPIO_FUNCTION_TRACE
|
GPIO_FUNCTION_TRACE
|
||||||
|
|
||||||
uint32_t signal_value = 0;
|
uint32_t signal_value = signals->get();
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
if (sem_wait(mutex_sem) == -1) {
|
|
||||||
LOGERROR("Unable to lock the shared memory")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
signal_value = *signals;
|
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
if (sem_post(mutex_sem) == -1) {
|
|
||||||
LOGERROR("Unable to release the shared memory")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (signal_value >> hw_pin) & 1;
|
return (signal_value >> hw_pin) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,25 +466,7 @@ void GPIOBUS_Virtual::PinSetSignal(int hw_pin, bool ast)
|
||||||
if (hw_pin < 0) {
|
if (hw_pin < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
signals->set_bit(hw_pin, (int)ast);
|
||||||
if (sem_wait(mutex_sem) == -1) {
|
|
||||||
LOGERROR("Unable to lock the shared memory")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ast) {
|
|
||||||
// Set the "gpio" bit
|
|
||||||
*signals |= 0x1 << hw_pin;
|
|
||||||
} else {
|
|
||||||
// Clear the "gpio" bit
|
|
||||||
*signals ^= ~(0x1 << hw_pin);
|
|
||||||
}
|
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
if (sem_post(mutex_sem) == -1) {
|
|
||||||
LOGERROR("Unable to release the shared memory")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -545,20 +484,6 @@ uint32_t GPIOBUS_Virtual::Acquire()
|
||||||
{
|
{
|
||||||
GPIO_FUNCTION_TRACE;
|
GPIO_FUNCTION_TRACE;
|
||||||
|
|
||||||
uint32_t signal_value = 0;
|
uint32_t signal_value = signals->get();
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
if (sem_wait(mutex_sem) == -1) {
|
|
||||||
LOGERROR("Unable to lock the shared memory")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
signal_value = *signals;
|
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
if (sem_post(mutex_sem) == -1) {
|
|
||||||
LOGERROR("Unable to release the shared memory")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return signal_value;
|
return signal_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "hal/gpiobus.h"
|
#include "hal/gpiobus.h"
|
||||||
#include "shared/log.h"
|
#include "shared/log.h"
|
||||||
#include "shared/scsi.h"
|
#include "shared/scsi.h"
|
||||||
|
#include "shared/shared_memory.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
@ -148,7 +149,7 @@ class GPIOBUS_Virtual final : public GPIOBUS
|
||||||
void PullConfig(int pin, int mode) override
|
void PullConfig(int pin, int mode) override
|
||||||
{
|
{
|
||||||
(void)mode; // Put these in opposite order so Sonar doesn't complain
|
(void)mode; // Put these in opposite order so Sonar doesn't complain
|
||||||
(void)pin; // That PinConfig and PullConfig are identical
|
(void)pin; // That PinConfig and PullConfig are identical
|
||||||
}
|
}
|
||||||
// GPIO pin pull up/down resistor setting
|
// GPIO pin pull up/down resistor setting
|
||||||
void PinSetSignal(int pin, bool ast) override;
|
void PinSetSignal(int pin, bool ast) override;
|
||||||
|
@ -157,18 +158,10 @@ class GPIOBUS_Virtual final : public GPIOBUS
|
||||||
// Set GPIO drive strength
|
// Set GPIO drive strength
|
||||||
|
|
||||||
array<int, 19> SignalTable;
|
array<int, 19> SignalTable;
|
||||||
shared_ptr<uint32_t> signals; // All bus signals
|
unique_ptr<SharedMemory> signals;
|
||||||
|
|
||||||
unique_ptr<DataSample> GetSample(uint64_t timestamp) override
|
unique_ptr<DataSample> GetSample(uint64_t timestamp) override
|
||||||
{
|
{
|
||||||
return make_unique<DataSample_Raspberry>(*signals, timestamp);
|
return make_unique<DataSample_Raspberry>(signals->get(), timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHARED_MEMORY_GPIO
|
|
||||||
inline static const string SHARED_MEM_MUTEX_NAME = "/sem-mutex";
|
|
||||||
inline static const string SHARED_MEM_NAME = "/posix-shared-mem-example";
|
|
||||||
|
|
||||||
sem_t *mutex_sem, *buffer_count_sem, *spool_signal_sem;
|
|
||||||
int fd_shm, fd_log;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "hal/systimer.h"
|
#include "hal/systimer.h"
|
||||||
#include "hal/systimer_allwinner.h"
|
#include "hal/systimer_allwinner.h"
|
||||||
|
#include "hal/systimer_linux.h"
|
||||||
#include "hal/systimer_raspberry.h"
|
#include "hal/systimer_raspberry.h"
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
@ -38,6 +39,8 @@ void SysTimer::Init()
|
||||||
} else if (SBC_Version::IsBananaPi()) {
|
} else if (SBC_Version::IsBananaPi()) {
|
||||||
systimer_ptr = make_unique<SysTimer_AllWinner>();
|
systimer_ptr = make_unique<SysTimer_AllWinner>();
|
||||||
is_allwinnner = true;
|
is_allwinnner = true;
|
||||||
|
} else {
|
||||||
|
systimer_ptr = make_unique<SysTimer_Linux>();
|
||||||
}
|
}
|
||||||
systimer_ptr->Init();
|
systimer_ptr->Init();
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
92
cpp/hal/systimer_linux.cpp
Normal file
92
cpp/hal/systimer_linux.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator PiSCSI
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 akuker
|
||||||
|
//
|
||||||
|
// [ High resolution timer for the Allwinner series of SoC's]
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "hal/systimer_linux.h"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include "hal/gpiobus.h"
|
||||||
|
|
||||||
|
#include "shared/log.h"
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Initialize the system timer
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void SysTimer_Linux::Init()
|
||||||
|
{
|
||||||
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
int result = clock_getres(CLOCK_PROCESS_CPUTIME_ID, &timer_resolution);
|
||||||
|
LOGINFO("CPU resolution is: %lu (result: %d)", timer_resolution.tv_nsec, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SysTimer_Linux::GetTimerLow()
|
||||||
|
{
|
||||||
|
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SysTimer_Linux::GetTimerHigh()
|
||||||
|
{
|
||||||
|
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__);
|
||||||
|
return (uint32_t)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Sleep in nanoseconds
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void SysTimer_Linux::SleepNsec(uint32_t nsec)
|
||||||
|
{
|
||||||
|
(void)nsec;
|
||||||
|
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
// // If time is less than one HS timer clock tick, don't do anything
|
||||||
|
// if (nsec < 20) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // The HS timer receives a 200MHz clock input, which equates to
|
||||||
|
// // one clock tick every 5 ns.
|
||||||
|
// auto clockticks = (uint32_t)std::ceil(nsec / 5);
|
||||||
|
|
||||||
|
// uint32_t enter_time = hsitimer_regs->hs_tmr_curnt_lo_reg;
|
||||||
|
|
||||||
|
// // TODO: NEED TO HANDLE COUNTER OVERFLOW
|
||||||
|
// LOGTRACE("%s entertime: %08X ns: %d clockticks: %d", __PRETTY_FUNCTION__, enter_time, nsec, clockticks)
|
||||||
|
// while ((enter_time - hsitimer_regs->hs_tmr_curnt_lo_reg) < clockticks)
|
||||||
|
// ;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Sleep in microseconds
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void SysTimer_Linux::SleepUsec(uint32_t usec)
|
||||||
|
{
|
||||||
|
(void)usec;
|
||||||
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||||
|
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
// // If time is 0, don't do anything
|
||||||
|
// if (usec == 0) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uint32_t enter_time = GetTimerLow();
|
||||||
|
// while ((GetTimerLow() - enter_time) < usec)
|
||||||
|
// ;
|
||||||
|
}
|
42
cpp/hal/systimer_linux.h
Normal file
42
cpp/hal/systimer_linux.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator PiSCSI
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 akuker
|
||||||
|
//
|
||||||
|
// [ OS-based timer for simulation purposes ]
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "systimer.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// System timer
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
class SysTimer_Linux : public PlatformSpecificTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Default constructor
|
||||||
|
SysTimer_Linux() = default;
|
||||||
|
// Default destructor
|
||||||
|
~SysTimer_Linux() override = default;
|
||||||
|
// Initialization
|
||||||
|
void Init() override;
|
||||||
|
// Get system timer low byte
|
||||||
|
uint32_t GetTimerLow() override;
|
||||||
|
// Get system timer high byte
|
||||||
|
uint32_t GetTimerHigh() override;
|
||||||
|
// Sleep for N nanoseconds
|
||||||
|
void SleepNsec(uint32_t nsec) override;
|
||||||
|
// Sleep for N microseconds
|
||||||
|
void SleepUsec(uint32_t usec) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct timespec timer_resolution;
|
||||||
|
};
|
|
@ -120,7 +120,7 @@ void ScsiDump::ParseArguments(const vector<char*>& args)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
set_level(level::debug);
|
set_level(level::trace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
|
@ -266,6 +266,7 @@ void ScsiDump::RequestSense()
|
||||||
|
|
||||||
void ScsiDump::Inquiry()
|
void ScsiDump::Inquiry()
|
||||||
{
|
{
|
||||||
|
LOGTRACE("%s", __PRETTY_FUNCTION__)
|
||||||
vector<uint8_t> cdb(6);
|
vector<uint8_t> cdb(6);
|
||||||
cdb[4] = 0xff;
|
cdb[4] = 0xff;
|
||||||
Command(scsi_command::eCmdInquiry, cdb);
|
Command(scsi_command::eCmdInquiry, cdb);
|
||||||
|
@ -403,10 +404,10 @@ int ScsiDump::run(const vector<char*>& args)
|
||||||
try {
|
try {
|
||||||
ParseArguments(args);
|
ParseArguments(args);
|
||||||
|
|
||||||
#ifndef USE_SEL_EVENT_ENABLE
|
// #ifndef USE_SEL_EVENT_ENABLE
|
||||||
cerr << "Error: No PiSCSI hardware support" << endl;
|
// cerr << "Error: No PiSCSI hardware support" << endl;
|
||||||
return EXIT_FAILURE;
|
// return EXIT_FAILURE;
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
return DumpRestore();
|
return DumpRestore();
|
||||||
} catch (const parser_exception& e) {
|
} catch (const parser_exception& e) {
|
||||||
|
|
21
cpp/scsisim.cpp
Normal file
21
cpp/scsisim.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator PiSCSI
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 akuker
|
||||||
|
//
|
||||||
|
// Simulate a virtual SCSI bus via shared memory on the local host.
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "scsisim/scsisim_core.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const vector<char *> args(argv, argv + argc);
|
||||||
|
|
||||||
|
return ScsiSim().run(args);
|
||||||
|
}
|
174
cpp/scsisim/scsisim_core.cpp
Normal file
174
cpp/scsisim/scsisim_core.cpp
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// 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 "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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScsiSim::SetLogLevel(const string& log_level)
|
||||||
|
{
|
||||||
|
if (log_level == "trace") {
|
||||||
|
set_level(level::trace);
|
||||||
|
enable_debug = true;
|
||||||
|
} else if (log_level == "debug") {
|
||||||
|
set_level(level::debug);
|
||||||
|
enable_debug = true;
|
||||||
|
} else if (log_level == "info") {
|
||||||
|
set_level(level::info);
|
||||||
|
} else if (log_level == "warn") {
|
||||||
|
set_level(level::warn);
|
||||||
|
} else if (log_level == "err") {
|
||||||
|
set_level(level::err);
|
||||||
|
} else if (log_level == "critical") {
|
||||||
|
set_level(level::critical);
|
||||||
|
} else if (log_level == "off") {
|
||||||
|
set_level(level::off);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_log_level = log_level;
|
||||||
|
|
||||||
|
LOGINFO("Set log level to '%s'", current_log_level.c_str())
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'L':
|
||||||
|
log_level = optarg;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optopt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!log_level.empty()) {
|
||||||
|
SetLogLevel(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
uint32_t prev_value = -1;
|
||||||
|
int dot_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
|
||||||
|
if (new_value != prev_value) {
|
||||||
|
LOGTRACE("%s Value changed to %08X", __PRETTY_FUNCTION__, new_value);
|
||||||
|
prev_value = new_value;
|
||||||
|
}
|
||||||
|
if(++dot_counter > 1000){
|
||||||
|
printf(".");
|
||||||
|
dot_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
41
cpp/scsisim/scsisim_core.h
Normal file
41
cpp/scsisim/scsisim_core.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator PiSCSI
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 akuker
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "shared/shared_memory.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class ScsiSim
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScsiSim() = default;
|
||||||
|
~ScsiSim() = default;
|
||||||
|
|
||||||
|
int run(const vector<char*>& args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Banner(const vector<char*>&) const;
|
||||||
|
static void TerminationHandler(int signum);
|
||||||
|
bool ParseArgument(const vector<char*>&);
|
||||||
|
bool SetLogLevel(const string&);
|
||||||
|
|
||||||
|
int InitSharedMemory();
|
||||||
|
void TeardownSharedMemory();
|
||||||
|
|
||||||
|
bool enable_debug = false;
|
||||||
|
|
||||||
|
unique_ptr<SharedMemory> signals;
|
||||||
|
|
||||||
|
bool running;
|
||||||
|
};
|
18
cpp/scsisim/scsisim_defs.h
Normal file
18
cpp/scsisim/scsisim_defs.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator PiSCSI for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 akuker
|
||||||
|
//
|
||||||
|
// [ SCSI Bus Emulator Common Definitions]
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const string SHARED_MEM_MUTEX_NAME = "/piscsi-sem-mutex";
|
||||||
|
const string SHARED_MEM_NAME = "/piscsi-shared-mem";
|
104
cpp/shared/shared_memory.cpp
Normal file
104
cpp/shared/shared_memory.cpp
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#include "shared_memory.h"
|
||||||
|
#include "shared/log.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
// template <class T> void SharedMemory<T>::teardown(){
|
||||||
|
SharedMemory::~SharedMemory()
|
||||||
|
{
|
||||||
|
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||||
|
if (m_mem != nullptr) {
|
||||||
|
if (munmap(m_mem, m_size) == 0) {
|
||||||
|
LOGTRACE("munmap successful");
|
||||||
|
} else {
|
||||||
|
LOGWARN("munmap NOT successful ERROR!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGTRACE("%s Unlinking shared memory", __PRETTY_FUNCTION__);
|
||||||
|
if (shm_unlink(m_name.c_str()) == 0) {
|
||||||
|
LOGTRACE("shm_unlink success");
|
||||||
|
} else {
|
||||||
|
LOGWARN("shm_unlink failed!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <class T> SharedMemory<T>::~SharedMemory()
|
||||||
|
// // SharedMemory::~SharedMemory()
|
||||||
|
// {
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// template <class T> SharedMemory<T>::SharedMemory(SharedMemory::RoleEnum role, std::string region_name) :
|
||||||
|
// // m_role(role), m_size(sizeof(T))
|
||||||
|
// SharedMemory::SharedMemory(SharedMemory::RoleEnum role, std::string region_name)
|
||||||
|
// : m_role(role), m_size(sizeof(uint32_t))
|
||||||
|
// {
|
||||||
|
// (void)role;
|
||||||
|
// (void)region_name;
|
||||||
|
// }
|
||||||
|
// template <class T> SharedMemory<T>::SharedMemory(SharedMemory::RoleEnum role, std::string region_name) :
|
||||||
|
// m_role(role), m_size(sizeof(T))
|
||||||
|
SharedMemory::SharedMemory(std::string region_name) : m_size(sizeof(uint32_t)), m_name(region_name)
|
||||||
|
{
|
||||||
|
// if(m_role == RoleEnum::Controller){
|
||||||
|
// m_mutex_sem = sem_open(SHARED_MEM_MUTEX_NAME.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// m_mutex_sem = sem_open(SHARED_MEM_MUTEX_NAME.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
|
||||||
|
|
||||||
|
// }
|
||||||
|
// // Create a shared memory region that can be accessed as a virtual "SCSI bus"
|
||||||
|
// // mutual exclusion semaphore, mutex_sem with an initial value 0.
|
||||||
|
// if ( == SEM_FAILED) {
|
||||||
|
// LOGERROR("Unable to open shared memory semaphore %s. Is scsisim already running?",
|
||||||
|
// SHARED_MEM_MUTEX_NAME.c_str());
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
// LOGTRACE("%s Successfully created mutex %s", __PRETTY_FUNCTION__, SHARED_MEM_MUTEX_NAME.c_str())
|
||||||
|
|
||||||
|
// sem_post(mutex_sem);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
LOGERROR("Unable to open shared memory %s. Is scsisim already running?", region_name.c_str());
|
||||||
|
sem_close(m_mutex_sem);
|
||||||
|
}
|
||||||
|
LOGTRACE("%s Successfully created shared memory %s", __PRETTY_FUNCTION__, region_name.c_str())
|
||||||
|
|
||||||
|
// Extend the shared memory, since its default size is zero
|
||||||
|
if (ftruncate(m_fd_shared_mem, sizeof(lockable_data_t)) == -1) {
|
||||||
|
LOGERROR("Unable to expand shared memory");
|
||||||
|
sem_close(m_mutex_sem);
|
||||||
|
shm_unlink(region_name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOGINFO("%s Shared memory region expanded to %d bytes", __PRETTY_FUNCTION__, static_cast<int>(sizeof(uint32_t)))
|
||||||
|
|
||||||
|
// signals.Reset(NULL, sizeof(uint32_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
|
||||||
|
|
||||||
|
shared_mem =
|
||||||
|
(lockable_data_t*)mmap(NULL, sizeof(lockable_data_t), PROT_READ | PROT_WRITE, MAP_SHARED, m_fd_shared_mem, 0);
|
||||||
|
if (shared_mem == MAP_FAILED) {
|
||||||
|
LOGERROR("Unabled to map shared memory");
|
||||||
|
sem_close(m_mutex_sem);
|
||||||
|
shm_unlink(region_name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGINFO("%s Shared memory region successfully memory mapped", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
// *signals.mem() = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <class T > SharedMemory<T>::~SharedMemory() {
|
||||||
|
|
||||||
|
// // template <typename T>
|
||||||
|
// // shared_ptr<SharedMemory<T>> SharedMemory::Create(SharedMemory::Role role){
|
||||||
|
|
||||||
|
// // mem_ = mmap(start, size, prot, flags, fd, offset);
|
||||||
|
// // size_ = size;
|
||||||
|
|
||||||
|
// }
|
117
cpp/shared/shared_memory.h
Normal file
117
cpp/shared/shared_memory.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// SCSI Target Emulator PiSCSI
|
||||||
|
// for Raspberry Pi
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 akuker
|
||||||
|
// Portions of this file Copyright (C) 2018 Intel Corporation
|
||||||
|
// (MIT licensed)
|
||||||
|
// https://github.com/nodejs/node/blob/main/src/large_pages/node_large_page.h
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <shared_mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
// template <class T> class SharedMemory
|
||||||
|
class SharedMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum RoleEnum { Controller, User };
|
||||||
|
SharedMemory() = default;
|
||||||
|
// SharedMemory(RoleEnum, std::string);
|
||||||
|
SharedMemory(std::string);
|
||||||
|
|
||||||
|
// static shared_ptr<SharedMemory<T>> Create(RoleEnum);
|
||||||
|
|
||||||
|
~SharedMemory();
|
||||||
|
|
||||||
|
// // inline bool operator==(T* rhs) const
|
||||||
|
// inline bool operator==(uint32_t* rhs) const
|
||||||
|
// {
|
||||||
|
// return mem_ == (void*)rhs;
|
||||||
|
// }
|
||||||
|
// // inline T* mem() const
|
||||||
|
// inline uint32_t* mem() const
|
||||||
|
// {
|
||||||
|
// return (uint32_t*)mem_;
|
||||||
|
// }
|
||||||
|
// // inline T read() const
|
||||||
|
// inline uint32_t read() const
|
||||||
|
// {
|
||||||
|
// return *mem();
|
||||||
|
// }
|
||||||
|
// SharedMemory(const SharedMemory&) = delete;
|
||||||
|
// SharedMemory(SharedMemory&&) = delete;
|
||||||
|
// void operator=(const SharedMemory&) = delete;
|
||||||
|
// void operator=(const SharedMemory&&) = delete;
|
||||||
|
|
||||||
|
// inline bool IsValid()
|
||||||
|
// {
|
||||||
|
// return ((mem_ != nullptr) && (mem_ != MAP_FAILED));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void teardown();
|
||||||
|
|
||||||
|
// Multiple threads/readers can read the counter's value at the same time.
|
||||||
|
// T get() const {
|
||||||
|
uint32_t get() const{
|
||||||
|
std::shared_lock lock(shared_mem->mutex_);
|
||||||
|
return shared_mem->value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only one thread/writer can increment/write the counter's value.
|
||||||
|
// void set(T new_val) {
|
||||||
|
void set(uint32_t new_val) {
|
||||||
|
std::unique_lock lock(shared_mem->mutex_);
|
||||||
|
shared_mem->value_ = new_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_bit(int bit_num, int value)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(shared_mem->mutex_);
|
||||||
|
if (value) {
|
||||||
|
// Set bit
|
||||||
|
shared_mem->value_ |= (1 << bit_num);
|
||||||
|
} else {
|
||||||
|
// Clear bit
|
||||||
|
shared_mem->value_ &= ~(1 << bit_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only one thread/writer can reset/write the counter's value.
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
std::unique_lock lock(shared_mem->mutex_);
|
||||||
|
shared_mem->value_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef struct lockable_data {
|
||||||
|
mutable std::shared_mutex mutex_;
|
||||||
|
// T value_;
|
||||||
|
uint32_t value_;
|
||||||
|
} lockable_data_t;
|
||||||
|
// typedef lockable_data_t struct lockable_data_struct;
|
||||||
|
|
||||||
|
// explicit SharedMemory()
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
lockable_data_t* shared_mem;
|
||||||
|
|
||||||
|
// SharedMemory::RoleEnum m_role;
|
||||||
|
size_t m_size = 0;
|
||||||
|
void* m_mem = nullptr;
|
||||||
|
// void* mem_;
|
||||||
|
sem_t* m_mutex_sem;
|
||||||
|
int m_fd_shared_mem;
|
||||||
|
std::string m_name;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user