mirror of
https://github.com/akuker/RASCSI.git
synced 2025-02-21 07:29:28 +00:00
* #7 Re-merge scsimon functionality with latest master. The old scsimon branch was waaaaay too out of date * #7 Re-merge scsimon functionality with latest master. The old scsimon branch was waaaaay too out of date * Added libspdlog-dev as a required package * Cleanup from master re-base * Updated to use GCC version 8, to match the raspberry pi Co-authored-by: akuker <akuker@gmail.com>
This commit is contained in:
parent
3ddeac6180
commit
1118c344cc
11
.github/workflows/c-cpp.yml
vendored
11
.github/workflows/c-cpp.yml
vendored
@ -9,9 +9,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Install cross compile toolchain
|
||||
run: sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf binutils-arm-linux-gnueabihf
|
||||
run: sudo apt-get install gcc-8-arm-linux-gnueabihf g++-8-arm-linux-gnueabihf binutils-arm-linux-gnueabihf libspdlog-dev
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: dump arm gcc version
|
||||
run: arm-linux-gnueabihf-gcc -v
|
||||
working-directory: ./src/raspberrypi
|
||||
|
||||
- name: dump native gcc version
|
||||
run: gcc -v
|
||||
working-directory: ./src/raspberrypi
|
||||
|
||||
|
||||
- name: make standard
|
||||
run: make all DEBUG=1 CONNECT_TYPE=STANDARD
|
||||
working-directory: ./src/raspberrypi
|
||||
|
@ -57,6 +57,6 @@ To create an empty, 100MB HD image, use the following command:
|
||||
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||
|
||||
.SH SEE ALSO
|
||||
rasctl(1), scsidump(1)
|
||||
rasctl(1), scsimon(1)
|
||||
|
||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
||||
|
@ -2,7 +2,7 @@
|
||||
!! ------ The native file is rascsi.1. Re-run 'make docs' after updating
|
||||
|
||||
|
||||
rascsi(1) General Commands Manual rascsi(1)
|
||||
rascsi(1) General Commands Manual rascsi(1)
|
||||
|
||||
NAME
|
||||
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
|
||||
@ -13,10 +13,9 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins.
|
||||
|
||||
In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. The number (n)
|
||||
after the ID or HD idnetifier specifies the ID number for that device. For SCSI: The ID is limited from 0-7.
|
||||
However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered
|
||||
rare and only used on very early Sharp X68000 computers.
|
||||
In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. The number (n) after the ID or HD idnetifier specifies the ID number for that device. For SCSI:
|
||||
The ID is limited from 0-7. However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered rare and only used on very early Sharp X68000 com‐
|
||||
puters.
|
||||
|
||||
RaSCSI will determin the type of device based upon the file extension of the FILE argument.
|
||||
hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used with X68000)
|
||||
@ -31,9 +30,8 @@ DESCRIPTION
|
||||
For example, if you want to specify an Apple-compatible HD image on ID 0, you can use the following command:
|
||||
sudo rascsi -ID0 /path/to/drive/hdimage.hda
|
||||
|
||||
Once RaSCSI starts, it will open a socket (port 6868) to allow external management commands. If another
|
||||
process is using port 6868, RaSCSI will terminate, since it is likely another instance of RaSCSI. Once
|
||||
RaSCSI has initialized, the rasctl utility can be used to send commands.
|
||||
Once RaSCSI starts, it will open a socket (port 6868) to allow external management commands. If another process is using port 6868, RaSCSI will terminate, since it is likely another in‐
|
||||
stance of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used to send commands.
|
||||
|
||||
To quit RaSCSI, press Control + C. If it is running in the background, you can kill it using an INT signal.
|
||||
|
||||
@ -61,8 +59,8 @@ EXAMPLES
|
||||
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||
|
||||
SEE ALSO
|
||||
rasctl(1), scsidump(1)
|
||||
rasctl(1), scsimon(1)
|
||||
|
||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
||||
|
||||
rascsi(1)
|
||||
rascsi(1)
|
||||
|
@ -66,6 +66,6 @@ Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the cont
|
||||
rasctl -i 0 -f HDIIMAGE0.HDS
|
||||
|
||||
.SH SEE ALSO
|
||||
rascsi(1)
|
||||
rascsi(1) scsimon(1)
|
||||
|
||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
||||
|
@ -2,7 +2,7 @@
|
||||
!! ------ The native file is rasctl.1. Re-run 'make docs' after updating
|
||||
|
||||
|
||||
rascsi(1) General Commands Manual rascsi(1)
|
||||
rascsi(1) General Commands Manual rascsi(1)
|
||||
|
||||
NAME
|
||||
rasctl - Sends management commands to the rascsi process
|
||||
@ -11,15 +11,13 @@ SYNOPSIS
|
||||
rasctl -l | -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE]
|
||||
|
||||
DESCRIPTION
|
||||
rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the sta‐
|
||||
tus of the devices.
|
||||
rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices.
|
||||
|
||||
Either the -i or -l option should be specified at one time. Not both.
|
||||
|
||||
You do NOT need root privileges to use rasctl.
|
||||
|
||||
Note: The command and type arguments are case insensitive. Only the first letter of the command/type are
|
||||
evaluated by the tool.
|
||||
Note: The command and type arguments are case insensitive. Only the first letter of the command/type are evaluated by the tool.
|
||||
|
||||
OPTIONS
|
||||
-l List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
|
||||
@ -27,8 +25,7 @@ OPTIONS
|
||||
-i ID ID is the SCSI ID that you want to control. (0-7)
|
||||
|
||||
-u UNIT
|
||||
Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI
|
||||
devices on a shared SCSI controller. (This is not common)
|
||||
Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI devices on a shared SCSI controller. (This is not common)
|
||||
|
||||
-c CMD Command is the operation being requested. options are:
|
||||
attach: attach disk
|
||||
@ -40,8 +37,7 @@ OPTIONS
|
||||
When the command is omited, rasctl will default to the 'attach' command
|
||||
|
||||
-t TYPE
|
||||
Specifies the type of disk. If this disagrees with the file extension of the specified image, the TYPE
|
||||
argument is ignored. Available drive types are:
|
||||
Specifies the type of disk. If this disagrees with the file extension of the specified image, the TYPE argument is ignored. Available drive types are:
|
||||
hd: Hard disk (SCSI or SASI)
|
||||
mo: Magneto-Optical disk)
|
||||
cd: CD-ROM
|
||||
@ -61,13 +57,12 @@ EXAMPLES
|
||||
| 0 | 1 | SCHD | /home/pi/harddisk.hda
|
||||
+----+----+------+-------------------------------------
|
||||
|
||||
Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image
|
||||
"HDIIMAGE0.HDS".
|
||||
Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image "HDIIMAGE0.HDS".
|
||||
rasctl -i 0 -f HDIIMAGE0.HDS
|
||||
|
||||
SEE ALSO
|
||||
rascsi(1)
|
||||
rascsi(1) scsimon(1)
|
||||
|
||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
||||
|
||||
rascsi(1)
|
||||
rascsi(1)
|
||||
|
27
doc/scsimon.1
Normal file
27
doc/scsimon.1
Normal file
@ -0,0 +1,27 @@
|
||||
.TH scsimon 1
|
||||
.SH NAME
|
||||
scsimon \- Acts as a data capture tool for all traffic on the SCSI bus. Data is stored in a Value Change Dump (VCD) file.
|
||||
.SH SYNOPSIS
|
||||
.B scsimon
|
||||
.SH DESCRIPTION
|
||||
.B scsimon
|
||||
Monitors all of the traffic on the SCSI bus, using a RaSCSI device. The data is cached in memory while the tool is running. A circular buffer is used so that only the most recent 1,000,000 transactions are stored. The tool will continue to run until the user presses CTRL-C, or the process receives a SIGINT signal.
|
||||
.PP
|
||||
The logged data is stored in a file called "log.vcd" in the current working directory from where scsimon was launched.
|
||||
|
||||
Currently, scsimon doesn't accept any agruments.
|
||||
|
||||
To quit scsimon, press Control + C.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
None
|
||||
|
||||
.SH EXAMPLES
|
||||
Launch scsimon to capture all SCSI traffic available to the RaSCSI hardware:
|
||||
scsimon
|
||||
|
||||
.SH SEE ALSO
|
||||
rasctl(1), rascsi(1)
|
||||
|
||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
35
doc/scsimon_man_page.txt
Normal file
35
doc/scsimon_man_page.txt
Normal file
@ -0,0 +1,35 @@
|
||||
!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!
|
||||
!! ------ The native file is scsimon.1. Re-run 'make docs' after updating
|
||||
|
||||
|
||||
scsimon(1) General Commands Manual scsimon(1)
|
||||
|
||||
NAME
|
||||
scsimon - Acts as a data capture tool for all traffic on the SCSI bus. Data is stored in a Value Change Dump (VCD) file.
|
||||
|
||||
SYNOPSIS
|
||||
scsimon
|
||||
|
||||
DESCRIPTION
|
||||
scsimon Monitors all of the traffic on the SCSI bus, using a RaSCSI device. The data is cached in memory while the tool is running. A circular buffer is used so that only the most recent 1,000,000
|
||||
transactions are stored. The tool will continue to run until the user presses CTRL-C, or the process receives a SIGINT signal.
|
||||
|
||||
The logged data is stored in a file called "log.vcd" in the current working directory from where scsimon was launched.
|
||||
|
||||
Currently, scsimon doesn't accept any agruments.
|
||||
|
||||
To quit scsimon, press Control + C.
|
||||
|
||||
OPTIONS
|
||||
None
|
||||
|
||||
EXAMPLES
|
||||
Launch scsimon to capture all SCSI traffic available to the RaSCSI hardware:
|
||||
scsimon
|
||||
|
||||
SEE ALSO
|
||||
rasctl(1), rascsi(1)
|
||||
|
||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
||||
|
||||
scsimon(1)
|
1
src/raspberrypi/.gitignore
vendored
1
src/raspberrypi/.gitignore
vendored
@ -4,6 +4,7 @@
|
||||
*.cbp
|
||||
*.layout
|
||||
*.log
|
||||
*.vcd
|
||||
rascsi
|
||||
scsimon
|
||||
rasctl
|
||||
|
@ -38,8 +38,8 @@ CXXFLAGS += -std=c++14 -iquote . -MD -MP
|
||||
## STANDARD or FULLSPEC. The default is STANDARD
|
||||
## * THIS IS TYPICALLY THE ONLY COMPILE OPTION YOU
|
||||
## * NEED TO SPECIFY
|
||||
# If its not specified, build for STANDARD configuration
|
||||
CONNECT_TYPE ?= STANDARD
|
||||
# If its not specified, build for FULLSPEC configuration
|
||||
CONNECT_TYPE ?= FULLSPEC
|
||||
|
||||
ifdef CONNECT_TYPE
|
||||
CFLAGS += -DCONNECT_TYPE_$(CONNECT_TYPE)
|
||||
@ -67,8 +67,7 @@ BINDIR := ./bin/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]')
|
||||
#BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON)
|
||||
# Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed
|
||||
# for my specific use case. If you need them - add them back in!
|
||||
BIN_ALL = $(BINDIR)/$(RASCSI) $(BINDIR)/$(RASCTL)
|
||||
|
||||
BIN_ALL = $(BINDIR)/$(RASCSI) $(BINDIR)/$(RASCTL) $(BINDIR)/$(SCSIMON)
|
||||
|
||||
SRC_RASCSI = \
|
||||
rascsi.cpp \
|
||||
@ -83,6 +82,16 @@ SRC_RASCSI = \
|
||||
SRC_RASCSI += $(shell find ./controllers -name '*.cpp')
|
||||
SRC_RASCSI += $(shell find ./devices -name '*.cpp')
|
||||
|
||||
SRC_SCSIMON = \
|
||||
scsimon.cpp \
|
||||
scsi.cpp \
|
||||
gpiobus.cpp \
|
||||
filepath.cpp \
|
||||
fileio.cpp
|
||||
SRC_SCSIMON += $(shell find ./controllers -name '*.cpp')
|
||||
SRC_SCSIMON += $(shell find ./devices -name '*.cpp')
|
||||
|
||||
|
||||
SRC_RASCTL = \
|
||||
rasctl.cpp
|
||||
# rasctl_command.cpp
|
||||
@ -113,12 +122,12 @@ OBJ_RASDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASDUMP:%.cpp=%.o)))
|
||||
OBJ_SASIDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SASIDUMP:%.cpp=%.o)))
|
||||
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
|
||||
#OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON)
|
||||
OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP)
|
||||
OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON)
|
||||
|
||||
|
||||
# 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
|
||||
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI) $(OBJ_RASCTL))
|
||||
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_SCSIMON))
|
||||
-include $(ALL_DEPS)
|
||||
|
||||
$(OBJDIR) $(BINDIR):
|
||||
@ -137,21 +146,21 @@ $(OBJDIR)/%.o: %.cpp | $(OBJDIR)
|
||||
all: $(BIN_ALL) docs
|
||||
ALL: all
|
||||
|
||||
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt
|
||||
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(DOC_DIR)/scsimon_man_page.txt
|
||||
|
||||
$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) | $(BINDIR)
|
||||
$(CXX) -o $@ $(OBJ_RASCSI) -lpthread
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread
|
||||
|
||||
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) $(BINDIR)
|
||||
$(CXX) -o $@ $(OBJ_RASCTL)
|
||||
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) | $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL)
|
||||
|
||||
$(RASDUMP): $(OBJ_RASDUMP) $(BINDIR)
|
||||
$(CXX) -o $@ $(OBJ_RASDUMP)
|
||||
$(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) | $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP)
|
||||
|
||||
$(SASIDUMP): $(OBJ_SASIDUMP) $(BINDIR)
|
||||
$(CXX) -o $@ $(OBJ_SASIDUMP)
|
||||
$(BINDIR)/$(SASIDUMP): $(OBJ_SASIDUMP) | $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SASIDUMP)
|
||||
|
||||
$(SCSIMON): $(OBJ_SCSIMON) $(BINDIR)
|
||||
$(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) | $(BINDIR)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread
|
||||
|
||||
## clean : Remove all of the object files, intermediate
|
||||
@ -180,7 +189,7 @@ run:
|
||||
## * sudo systemctl enable rascsi
|
||||
## * sudo systemctl start rascsi
|
||||
.PHONY: install
|
||||
install: $(MAN_PAGE_DIR)/rascsi.1 $(MAN_PAGE_DIR)/rasctl.1 $(USR_LOCAL_BIN)/$(RASCTL) $(USR_LOCAL_BIN)/$(RASCSI) $(SYSTEMD_CONF) $(RSYSLOG_CONF) $(RSYSLOG_LOG)
|
||||
install: $(MAN_PAGE_DIR)/rascsi.1 $(MAN_PAGE_DIR)/rasctl.1 $(MAN_PAGE_DIR)/scsimon.1 $(USR_LOCAL_BIN)/$(RASCTL) $(USR_LOCAL_BIN)/$(RASCSI) $(USR_LOCAL_BIN)/$(SCSIMON) $(SYSTEMD_CONF) $(RSYSLOG_CONF) $(RSYSLOG_LOG)
|
||||
@echo "-- Done installing!"
|
||||
|
||||
$(USR_LOCAL_BIN)% : $(BINDIR)/%
|
||||
|
@ -296,7 +296,7 @@ BUS::phase_t FASTCALL SASIDEV::Process()
|
||||
}
|
||||
|
||||
// Get bus information
|
||||
ctrl.bus->Aquire();
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
|
||||
// For the monitor tool, we shouldn't need to reset. We're just logging information
|
||||
// Reset
|
||||
@ -927,7 +927,7 @@ void FASTCALL SASIDEV::Error()
|
||||
ASSERT(this);
|
||||
|
||||
// Get bus information
|
||||
ctrl.bus->Aquire();
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
|
||||
// Reset check
|
||||
if (ctrl.bus->GetRST()) {
|
||||
|
@ -76,7 +76,7 @@ BUS::phase_t FASTCALL SCSIDEV::Process()
|
||||
}
|
||||
|
||||
// Get bus information
|
||||
ctrl.bus->Aquire();
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
|
||||
// Reset
|
||||
if (ctrl.bus->GetRST()) {
|
||||
@ -488,7 +488,7 @@ void FASTCALL SCSIDEV::Error()
|
||||
ASSERT(this);
|
||||
|
||||
// Get bus information
|
||||
ctrl.bus->Aquire();
|
||||
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||
|
||||
// Reset check
|
||||
if (ctrl.bus->GetRST()) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "os.h"
|
||||
#include "xm6.h"
|
||||
#include "gpiobus.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef BAREMETAL
|
||||
#ifdef __linux__
|
||||
@ -65,7 +66,7 @@ DWORD bcm_host_get_peripheral_address(void)
|
||||
char buf[1024];
|
||||
size_t len = sizeof(buf);
|
||||
DWORD address;
|
||||
|
||||
|
||||
if (sysctlbyname("hw.model", buf, &len, NULL, 0) ||
|
||||
strstr(buf, "ARM1176JZ-S") != buf) {
|
||||
// Failed to get CPU model || Not BCM2835
|
||||
@ -88,7 +89,7 @@ extern uint32_t RPi_IO_Base_Addr;
|
||||
// Core frequency
|
||||
extern uint32_t RPi_Core_Freq;
|
||||
|
||||
#ifdef USE_SEL_EVENT_ENABLE
|
||||
#ifdef USE_SEL_EVENT_ENABLE
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Interrupt control function
|
||||
@ -173,7 +174,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
|
||||
// Open /dev/mem
|
||||
fd = open("/dev/mem", O_RDWR | O_SYNC);
|
||||
if (fd == -1) {
|
||||
printf("Error: Unable to open /dev/mem. Are you running as root?\n");
|
||||
LOGERROR("Error: Unable to open /dev/mem. Are you running as root?");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -295,6 +296,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
|
||||
// GPIO chip open
|
||||
fd = open("/dev/gpiochip0", 0);
|
||||
if (fd == -1) {
|
||||
LOGERROR("Unable to open /dev/gpiochip0. Is RaSCSI already running?")
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -310,6 +312,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
|
||||
|
||||
//Get event request
|
||||
if (ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &selevreq) == -1) {
|
||||
LOGERROR("Unable to register event request. Is RaSCSI already running?")
|
||||
close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
@ -522,27 +525,6 @@ void FASTCALL GPIOBUS::Reset()
|
||||
#endif // ifdef __x86_64__ || __X86__
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Bus signal acquisition
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
DWORD FASTCALL GPIOBUS::Aquire()
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__X86__)
|
||||
return 0;
|
||||
#else
|
||||
signals = *level;
|
||||
|
||||
#if SIGNAL_CONTROL_MODE < 2
|
||||
// Invert if negative logic (internal processing is unified to positive logic)
|
||||
signals = ~signals;
|
||||
#endif // SIGNAL_CONTROL_MODE
|
||||
|
||||
return signals;
|
||||
#endif // ifdef __x86_64__ || __X86__
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ENB signal setting
|
||||
@ -668,6 +650,26 @@ void FASTCALL GPIOBUS::SetACK(BOOL ast)
|
||||
SetSignal(PIN_ACK, ast);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get ACK signal
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BOOL FASTCALL GPIOBUS::GetACT()
|
||||
{
|
||||
return GetSignal(PIN_ACT);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Set ACK signal
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FASTCALL GPIOBUS::SetACT(BOOL ast)
|
||||
{
|
||||
SetSignal(PIN_ACT, ast);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get RST signal
|
||||
@ -1173,7 +1175,7 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count)
|
||||
}
|
||||
|
||||
// Already waiting for REQ assertion
|
||||
|
||||
|
||||
// Assert the ACK signal
|
||||
SetSignal(PIN_ACK, ON);
|
||||
|
||||
@ -1233,7 +1235,7 @@ int FASTCALL GPIOBUS::PollSelectEvent()
|
||||
return -1;
|
||||
}
|
||||
|
||||
read(selevreq.fd, &gpev, sizeof(gpev));
|
||||
(void)read(selevreq.fd, &gpev, sizeof(gpev));
|
||||
#endif // BAREMETAL
|
||||
|
||||
return 0;
|
||||
@ -1417,7 +1419,7 @@ void FASTCALL GPIOBUS::SetMode(int pin, int mode)
|
||||
gpio[index] = data;
|
||||
gpfsel[index] = data;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Get input signal value
|
||||
@ -1427,7 +1429,7 @@ BOOL FASTCALL GPIOBUS::GetSignal(int pin)
|
||||
{
|
||||
return (signals >> pin) & 1;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Set output signal value
|
||||
@ -1645,6 +1647,39 @@ void FASTCALL GPIOBUS::DrvConfig(DWORD drive)
|
||||
pads[PAD_0_27] = (0xFFFFFFF8 & data) | drive | 0x5a000000;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Generic Phase Acquisition (Doesn't read GPIO)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BUS::phase_t FASTCALL GPIOBUS::GetPhaseRaw(DWORD raw_data)
|
||||
{
|
||||
DWORD mci;
|
||||
|
||||
// Selection Phase
|
||||
if (GetPinRaw(raw_data, PIN_SEL))
|
||||
{
|
||||
if(GetPinRaw(raw_data, PIN_IO)){
|
||||
return BUS::reselection;
|
||||
}else{
|
||||
return BUS::selection;
|
||||
}
|
||||
}
|
||||
|
||||
// Bus busy phase
|
||||
if (!GetPinRaw(raw_data, PIN_BSY)) {
|
||||
return BUS::busfree;
|
||||
}
|
||||
|
||||
// Get target phase from bus signal line
|
||||
mci = GetPinRaw(raw_data, PIN_MSG) ? 0x04 : 0x00;
|
||||
mci |= GetPinRaw(raw_data, PIN_CD) ? 0x02 : 0x00;
|
||||
mci |= GetPinRaw(raw_data, PIN_IO) ? 0x01 : 0x00;
|
||||
return GetPhase(mci);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// System timer address
|
||||
|
@ -276,6 +276,26 @@
|
||||
#define PIN_SEL 23 // SEL
|
||||
#endif
|
||||
|
||||
#define ALL_SCSI_PINS \
|
||||
((1<<PIN_DT0)|\
|
||||
(1<<PIN_DT1)|\
|
||||
(1<<PIN_DT2)|\
|
||||
(1<<PIN_DT3)|\
|
||||
(1<<PIN_DT4)|\
|
||||
(1<<PIN_DT5)|\
|
||||
(1<<PIN_DT6)|\
|
||||
(1<<PIN_DT7)|\
|
||||
(1<<PIN_DP)|\
|
||||
(1<<PIN_ATN)|\
|
||||
(1<<PIN_RST)|\
|
||||
(1<<PIN_ACK)|\
|
||||
(1<<PIN_REQ)|\
|
||||
(1<<PIN_MSG)|\
|
||||
(1<<PIN_CD)|\
|
||||
(1<<PIN_IO)|\
|
||||
(1<<PIN_BSY)|\
|
||||
(1<<PIN_SEL))
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Constant declarations(GPIO)
|
||||
@ -434,8 +454,28 @@ public:
|
||||
void FASTCALL Cleanup();
|
||||
// Cleanup
|
||||
|
||||
DWORD FASTCALL Aquire();
|
||||
// Signal acquisition
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Bus signal acquisition
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
inline DWORD Aquire()
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__X86__)
|
||||
// Only used for development/debugging purposes. Isn't really applicable
|
||||
// to any real-world RaSCSI application
|
||||
return 0;
|
||||
#else
|
||||
signals = *level;
|
||||
|
||||
#if SIGNAL_CONTROL_MODE < 2
|
||||
// Invert if negative logic (internal processing is unified to positive logic)
|
||||
signals = ~signals;
|
||||
#endif // SIGNAL_CONTROL_MODE
|
||||
|
||||
return signals;
|
||||
#endif // ifdef __x86_64__ || __X86__
|
||||
}
|
||||
|
||||
void FASTCALL SetENB(BOOL ast);
|
||||
// Set ENB signal
|
||||
@ -460,6 +500,11 @@ public:
|
||||
void FASTCALL SetACK(BOOL ast);
|
||||
// Set ACK signal
|
||||
|
||||
BOOL FASTCALL GetACT();
|
||||
// Get ACT signal
|
||||
void FASTCALL SetACT(BOOL ast);
|
||||
// Set ACT signal
|
||||
|
||||
BOOL FASTCALL GetRST();
|
||||
// Get RST signal
|
||||
void FASTCALL SetRST(BOOL ast);
|
||||
@ -498,6 +543,9 @@ public:
|
||||
int FASTCALL SendHandShake(BYTE *buf, int count);
|
||||
// Data transmission handshake
|
||||
|
||||
static BUS::phase_t FASTCALL GetPhaseRaw(DWORD raw_data);
|
||||
// Get the phase based on raw data
|
||||
|
||||
#ifdef USE_SEL_EVENT_ENABLE
|
||||
// SEL signal interrupt
|
||||
int FASTCALL PollSelectEvent();
|
||||
|
@ -5,13 +5,37 @@
|
||||
//
|
||||
// Powered by XM6 TypeG Technology.
|
||||
// Copyright (C) 2016-2020 GIMONS
|
||||
// [ ログ ]
|
||||
// Copyright (C) 2020 akuker
|
||||
// [ Logging utilities ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#if !defined(log_h)
|
||||
#define log_h
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
#define SPDLOGWRAPPER(loglevel, ...)\
|
||||
do{ char buf[256]; \
|
||||
snprintf(buf, sizeof(buf),__VA_ARGS__); \
|
||||
spdlog::log(loglevel,buf);}while(0);
|
||||
|
||||
#ifndef DEBUG
|
||||
// If we're doing a non-debug build, we want to skip the overhead of
|
||||
// formatting the string, then calling the logger
|
||||
#define LOGTRACE(...) ((void)0)
|
||||
#define LOGDEBUG(...) ((void)0)
|
||||
#else
|
||||
#define LOGTRACE(...) SPDLOGWRAPPER(spdlog::level::trace, __VA_ARGS__)
|
||||
#define LOGDEBUG(...) SPDLOGWRAPPER(spdlog::level::debug, __VA_ARGS__)
|
||||
#endif
|
||||
#define LOGINFO(...) SPDLOGWRAPPER(spdlog::level::info, __VA_ARGS__)
|
||||
#define LOGWARN(...) SPDLOGWRAPPER(spdlog::level::warn, __VA_ARGS__)
|
||||
#define LOGERROR(...) SPDLOGWRAPPER(spdlog::level::err, __VA_ARGS__)
|
||||
#define LOGCRITICAL(...) SPDLOGWRAPPER(spdlog::level::critical, __VA_ARGS__)
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// ログ
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "controllers/scsidev_ctrl.h"
|
||||
#include "controllers/sasidev_ctrl.h"
|
||||
#include "gpiobus.h"
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
@ -1064,6 +1064,8 @@ int main(int argc, char* argv[])
|
||||
struct sched_param schparam;
|
||||
#endif // BAREMETAL
|
||||
|
||||
spdlog::set_level(spdlog::level::trace);
|
||||
LOGTRACE("Entering the function %s with %d arguments", __PRETTY_FUNCTION__, argc);
|
||||
// Output the Banner
|
||||
Banner(argc, argv);
|
||||
|
||||
|
@ -41,18 +41,58 @@ BUS::phase_t FASTCALL BUS::GetPhase()
|
||||
return GetPhase(mci);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Determine Phase String phase enum
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const char* FASTCALL BUS::GetPhaseStrRaw(phase_t current_phase){
|
||||
if(current_phase <= phase_t::reserved){
|
||||
return phase_str_table[current_phase];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "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 BUS::phase_t BUS::phase_table[8] = {
|
||||
dataout,
|
||||
datain,
|
||||
command,
|
||||
status,
|
||||
reserved,
|
||||
reserved,
|
||||
msgout,
|
||||
msgin
|
||||
// | MSG|C/D|I/O |
|
||||
dataout, // | 0 | 0 | 0 |
|
||||
datain, // | 0 | 0 | 1 |
|
||||
command, // | 0 | 1 | 0 |
|
||||
status, // | 0 | 1 | 1 |
|
||||
reserved, // | 1 | 0 | 0 |
|
||||
reserved, // | 1 | 0 | 1 |
|
||||
msgout, // | 1 | 1 | 0 |
|
||||
msgin // | 1 | 1 | 1 |
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Phase Table
|
||||
// This MUST be kept in sync with the phase_t enum type!
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
const char* BUS::phase_str_table[] = {
|
||||
"busfree",
|
||||
"arbitration",
|
||||
"selection",
|
||||
"reselection",
|
||||
"command",
|
||||
"execute",
|
||||
"datain",
|
||||
"dataout",
|
||||
"status",
|
||||
"msgin",
|
||||
"msgout",
|
||||
"reserved"
|
||||
};
|
||||
|
@ -60,8 +60,14 @@ public:
|
||||
}
|
||||
// フェーズ取得
|
||||
|
||||
virtual DWORD FASTCALL Aquire() = 0;
|
||||
// 信号取り込み
|
||||
static const char* FASTCALL GetPhaseStrRaw(phase_t current_phase);
|
||||
// Get the string phase name, based upon the raw data
|
||||
|
||||
// Extract as specific pin field from a raw data capture
|
||||
static inline DWORD GetPinRaw(DWORD raw_data, DWORD pin_num)
|
||||
{
|
||||
return ((raw_data >> pin_num) & 1);
|
||||
}
|
||||
|
||||
virtual BOOL FASTCALL GetBSY() = 0;
|
||||
// BSYシグナル取得
|
||||
@ -125,6 +131,8 @@ public:
|
||||
private:
|
||||
static const phase_t phase_table[8];
|
||||
// フェーズテーブル
|
||||
|
||||
static const char* phase_str_table[];
|
||||
};
|
||||
|
||||
#endif // scsi_h
|
||||
|
420
src/raspberrypi/scsimon.cpp
Normal file
420
src/raspberrypi/scsimon.cpp
Normal file
@ -0,0 +1,420 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// SCSI Target Emulator RaSCSI (*^..^*)
|
||||
// for Raspberry Pi
|
||||
//
|
||||
// Powered by XM6 TypeG Technology.
|
||||
// Copyright (C) 2016-2020 GIMONS
|
||||
// [ RaSCSI main ]
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "os.h"
|
||||
#include "xm6.h"
|
||||
#include "filepath.h"
|
||||
#include "fileio.h"
|
||||
#include "devices/disk.h"
|
||||
#include "log.h"
|
||||
#include "gpiobus.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Constant declarations
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#define MAX_BUFF_SIZE 1000000
|
||||
|
||||
// Symbol definition for the VCD file
|
||||
// These are just arbitrary symbols. They can be anything allowed by the VCD file format,
|
||||
// as long as they're consistently used.
|
||||
#define SYMBOL_PIN_DAT '#'
|
||||
#define SYMBOL_PIN_ATN '+'
|
||||
#define SYMBOL_PIN_RST '$'
|
||||
#define SYMBOL_PIN_ACK '%'
|
||||
#define SYMBOL_PIN_REQ '^'
|
||||
#define SYMBOL_PIN_MSG '&'
|
||||
#define SYMBOL_PIN_CD '*'
|
||||
#define SYMBOL_PIN_IO '('
|
||||
#define SYMBOL_PIN_BSY ')'
|
||||
#define SYMBOL_PIN_SEL '-'
|
||||
#define SYMBOL_PIN_PHASE '='
|
||||
|
||||
// We'll use position 0 in the prev_value array to store the previous phase
|
||||
#define PIN_PHASE 0
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Variable declarations
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static BYTE prev_value[32] = {0xFF};
|
||||
static volatile BOOL running; // Running flag
|
||||
static volatile BOOL active; // Processing flag
|
||||
GPIOBUS *bus; // GPIO Bus
|
||||
typedef struct data_capture{
|
||||
DWORD data;
|
||||
timeval timestamp;
|
||||
} data_capture_t;
|
||||
|
||||
data_capture data_buffer[MAX_BUFF_SIZE];
|
||||
int data_idx = 0;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Signal Processing
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void KillHandler(int sig)
|
||||
{
|
||||
// Stop instruction
|
||||
running = FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Banner Output
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Banner(int argc, char* argv[])
|
||||
{
|
||||
LOGINFO("SCSI Monitor Capture Tool - part of RaSCSI(*^..^*) ");
|
||||
LOGINFO("version %01d.%01d%01d(%s, %s)",
|
||||
(int)((VERSION >> 8) & 0xf),
|
||||
(int)((VERSION >> 4) & 0xf),
|
||||
(int)((VERSION ) & 0xf),
|
||||
__DATE__,
|
||||
__TIME__);
|
||||
LOGINFO("Powered by XM6 TypeG Technology ");
|
||||
LOGINFO("Copyright (C) 2016-2020 GIMONS");
|
||||
LOGINFO("Copyright (C) 2020 akuker");
|
||||
LOGINFO("Connect type : %s", CONNECT_DESC);
|
||||
LOGINFO(" log.vcd - Value Change Dump file that can be opened with GTKWave");
|
||||
|
||||
if ((argc > 1 && strcmp(argv[1], "-h") == 0) ||
|
||||
(argc > 1 && strcmp(argv[1], "--help") == 0)){
|
||||
LOGINFO("Usage: %s ...", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINFO(" ");
|
||||
LOGINFO("Current running & collecting data. Press CTRL-C to stop.")
|
||||
LOGINFO(" ");
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
BOOL Init()
|
||||
{
|
||||
// Interrupt handler settings
|
||||
if (signal(SIGINT, KillHandler) == SIG_ERR) {
|
||||
return FALSE;
|
||||
}
|
||||
if (signal(SIGHUP, KillHandler) == SIG_ERR) {
|
||||
return FALSE;
|
||||
}
|
||||
if (signal(SIGTERM, KillHandler) == SIG_ERR) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// GPIOBUS creation
|
||||
bus = new GPIOBUS();
|
||||
|
||||
// GPIO Initialization
|
||||
if (!bus->Init()) {
|
||||
LOGERROR("Unable to intiailize the GPIO bus. Exiting....");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Bus Reset
|
||||
bus->Reset();
|
||||
|
||||
// Other
|
||||
running = FALSE;
|
||||
active = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL get_pin_value(DWORD data, int pin)
|
||||
{
|
||||
return (data >> pin) & 1;
|
||||
}
|
||||
|
||||
BYTE get_data_field(DWORD data)
|
||||
{
|
||||
DWORD data_out;
|
||||
data_out =
|
||||
((data >> (PIN_DT0 - 0)) & (1 << 0)) |
|
||||
((data >> (PIN_DT1 - 1)) & (1 << 1)) |
|
||||
((data >> (PIN_DT2 - 2)) & (1 << 2)) |
|
||||
((data >> (PIN_DT3 - 3)) & (1 << 3)) |
|
||||
((data >> (PIN_DT4 - 4)) & (1 << 4)) |
|
||||
((data >> (PIN_DT5 - 5)) & (1 << 5)) |
|
||||
((data >> (PIN_DT6 - 6)) & (1 << 6)) |
|
||||
((data >> (PIN_DT7 - 7)) & (1 << 7));
|
||||
|
||||
return (BYTE)data_out;
|
||||
}
|
||||
|
||||
void vcd_output_if_changed_phase(FILE *fp, DWORD data, int pin, char symbol)
|
||||
{
|
||||
BUS::phase_t new_value = GPIOBUS::GetPhaseRaw(data);
|
||||
if(prev_value[pin] != new_value)
|
||||
{
|
||||
prev_value[pin] = new_value;
|
||||
fprintf(fp, "s%s %c\n", GPIOBUS::GetPhaseStrRaw(new_value), symbol);
|
||||
}
|
||||
}
|
||||
|
||||
void vcd_output_if_changed_bool(FILE *fp, DWORD data, int pin, char symbol)
|
||||
{
|
||||
BOOL new_value = get_pin_value(data,pin);
|
||||
if(prev_value[pin] != new_value)
|
||||
{
|
||||
prev_value[pin] = new_value;
|
||||
fprintf(fp, "%d%c\n", new_value, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
void vcd_output_if_changed_byte(FILE *fp, DWORD data, int pin, char symbol)
|
||||
{
|
||||
BYTE new_value = get_data_field(data);
|
||||
if(prev_value[pin] != new_value)
|
||||
{
|
||||
prev_value[pin] = new_value;
|
||||
fprintf(fp, "b%d%d%d%d%d%d%d%d %c\n",
|
||||
get_pin_value(data,PIN_DT0),
|
||||
get_pin_value(data,PIN_DT1),
|
||||
get_pin_value(data,PIN_DT2),
|
||||
get_pin_value(data,PIN_DT3),
|
||||
get_pin_value(data,PIN_DT4),
|
||||
get_pin_value(data,PIN_DT5),
|
||||
get_pin_value(data,PIN_DT6),
|
||||
get_pin_value(data,PIN_DT7), symbol);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void create_value_change_dump()
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
int i = 0;
|
||||
timeval time_diff;
|
||||
char timestamp[256];
|
||||
FILE *fp;
|
||||
timeval start_time = data_buffer[0].timestamp;
|
||||
LOGINFO("Creating Value Change Dump file (log.vcd)\n");
|
||||
fp = fopen("log.vcd","w");
|
||||
|
||||
// Get the current time
|
||||
time (&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
strftime (timestamp,sizeof(timestamp),"%d-%m-%Y %H-%M-%S",timeinfo);
|
||||
|
||||
fprintf(fp, "$date\n");
|
||||
fprintf(fp, "%s\n", timestamp);
|
||||
fprintf(fp, "$end\n");
|
||||
fprintf(fp, "$version\n");
|
||||
fprintf(fp, " VCD generator tool version info text.\n");
|
||||
fprintf(fp, "$end\n");
|
||||
fprintf(fp, "$comment\n");
|
||||
fprintf(fp, " Any comment text.\n");
|
||||
fprintf(fp, "$end\n");
|
||||
fprintf(fp, "$timescale 1 us $end\n");
|
||||
fprintf(fp, "$scope module logic $end\n");
|
||||
fprintf(fp, "$var wire 1 %c BSY $end\n", SYMBOL_PIN_BSY);
|
||||
fprintf(fp, "$var wire 1 %c SEL $end\n", SYMBOL_PIN_SEL);
|
||||
fprintf(fp, "$var wire 1 %c CD $end\n", SYMBOL_PIN_CD);
|
||||
fprintf(fp, "$var wire 1 %c IO $end\n", SYMBOL_PIN_IO);
|
||||
fprintf(fp, "$var wire 1 %c MSG $end\n", SYMBOL_PIN_MSG);
|
||||
fprintf(fp, "$var wire 1 %c REQ $end\n", SYMBOL_PIN_REQ);
|
||||
fprintf(fp, "$var wire 1 %c ACK $end\n", SYMBOL_PIN_ACK);
|
||||
fprintf(fp, "$var wire 1 %c ATN $end\n", SYMBOL_PIN_ATN);
|
||||
fprintf(fp, "$var wire 1 %c RST $end\n", SYMBOL_PIN_RST);
|
||||
fprintf(fp, "$var wire 8 %c data $end\n", SYMBOL_PIN_DAT);
|
||||
fprintf(fp, "$var string 1 %c phase $end\n", SYMBOL_PIN_PHASE);
|
||||
fprintf(fp, "$upscope $end\n");
|
||||
fprintf(fp, "$enddefinitions $end\n");
|
||||
|
||||
// Initial values - default to zeros
|
||||
fprintf(fp, "$dumpvars\n");
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_BSY);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_SEL);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_CD);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_IO);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_MSG);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_REQ);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_ACK);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_ATN);
|
||||
fprintf(fp, "0%c\n", SYMBOL_PIN_RST);
|
||||
fprintf(fp, "b00000000 %c\n", SYMBOL_PIN_DAT);
|
||||
fprintf(fp, "$end\n");
|
||||
|
||||
while(i < data_idx)
|
||||
{
|
||||
timersub(&(data_buffer[i].timestamp), &start_time, &time_diff);
|
||||
fprintf(fp, "#%ld\n",((time_diff.tv_sec*1000000) + time_diff.tv_usec));
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_BSY, SYMBOL_PIN_BSY);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_SEL, SYMBOL_PIN_SEL);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_CD, SYMBOL_PIN_CD);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_IO, SYMBOL_PIN_IO);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_MSG, SYMBOL_PIN_MSG);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_REQ, SYMBOL_PIN_REQ);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_ACK, SYMBOL_PIN_ACK);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_ATN, SYMBOL_PIN_ATN);
|
||||
vcd_output_if_changed_bool(fp, data_buffer[i].data, PIN_RST, SYMBOL_PIN_RST);
|
||||
vcd_output_if_changed_byte(fp, data_buffer[i].data, PIN_DT0, SYMBOL_PIN_DAT);
|
||||
vcd_output_if_changed_phase(fp, data_buffer[i].data, PIN_PHASE, SYMBOL_PIN_PHASE);
|
||||
i++;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Cleanup
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Cleanup()
|
||||
{
|
||||
|
||||
LOGINFO("Stoping data collection....\n");
|
||||
create_value_change_dump();
|
||||
|
||||
// Cleanup the Bus
|
||||
bus->Cleanup();
|
||||
|
||||
// Discard the GPIOBUS object
|
||||
delete bus;
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Reset
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void Reset()
|
||||
{
|
||||
// Reset the bus
|
||||
bus->Reset();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Pin the thread to a specific CPU
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void FixCpu(int cpu)
|
||||
{
|
||||
cpu_set_t cpuset;
|
||||
int cpus;
|
||||
|
||||
// Get the number of CPUs
|
||||
CPU_ZERO(&cpuset);
|
||||
sched_getaffinity(0, sizeof(cpu_set_t), &cpuset);
|
||||
cpus = CPU_COUNT(&cpuset);
|
||||
|
||||
// Set the thread affinity
|
||||
if (cpu < cpus) {
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(cpu, &cpuset);
|
||||
sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static DWORD high_bits = 0x0;
|
||||
static DWORD low_bits = 0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Main processing
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef DEBUG
|
||||
DWORD prev_high = high_bits;
|
||||
DWORD prev_low = low_bits;
|
||||
#endif
|
||||
DWORD prev_sample = 0xFFFFFFFF;
|
||||
DWORD this_sample = 0;
|
||||
int ret;
|
||||
struct sched_param schparam;
|
||||
|
||||
spdlog::set_level(spdlog::level::trace);
|
||||
spdlog::set_pattern("%^[%l]%$ %v");
|
||||
// Output the Banner
|
||||
Banner(argc, argv);
|
||||
memset(data_buffer,0,sizeof(data_buffer));
|
||||
|
||||
// Initialize
|
||||
ret = 0;
|
||||
if (!Init()) {
|
||||
ret = EPERM;
|
||||
goto init_exit;
|
||||
}
|
||||
|
||||
// Reset
|
||||
Reset();
|
||||
|
||||
// Set the affinity to a specific processor core
|
||||
FixCpu(3);
|
||||
|
||||
// Scheduling policy setting (highest priority)
|
||||
schparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
sched_setscheduler(0, SCHED_FIFO, &schparam);
|
||||
|
||||
// Start execution
|
||||
running = TRUE;
|
||||
bus->SetACT(FALSE);
|
||||
|
||||
LOGDEBUG("ALL_SCSI_PINS %08X\n",ALL_SCSI_PINS);
|
||||
// Main Loop
|
||||
while (running) {
|
||||
// Work initialization
|
||||
this_sample = (bus->Aquire() & ALL_SCSI_PINS);
|
||||
|
||||
if(this_sample != prev_sample)
|
||||
{
|
||||
|
||||
#ifdef DEBUG
|
||||
// This is intended to be a debug check to see if every pin is set
|
||||
// high and low at some point.
|
||||
high_bits |= this_sample;
|
||||
low_bits &= this_sample;
|
||||
if ((high_bits != prev_high) || (low_bits != prev_low))
|
||||
{
|
||||
LOGDEBUG(" %08lX %08lX\n",high_bits, low_bits);
|
||||
}
|
||||
prev_high = high_bits;
|
||||
prev_low = low_bits;
|
||||
#endif
|
||||
data_buffer[data_idx].data = this_sample;
|
||||
(void)gettimeofday(&(data_buffer[data_idx].timestamp), NULL);
|
||||
data_idx = (data_idx + 1) % MAX_BUFF_SIZE;
|
||||
prev_sample = this_sample;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
Cleanup();
|
||||
|
||||
init_exit:
|
||||
exit(ret);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user