mirror of
https://github.com/akuker/RASCSI.git
synced 2024-06-12 15:29:35 +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:
|
steps:
|
||||||
- name: Install cross compile toolchain
|
- 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
|
- 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
|
- name: make standard
|
||||||
run: make all DEBUG=1 CONNECT_TYPE=STANDARD
|
run: make all DEBUG=1 CONNECT_TYPE=STANDARD
|
||||||
working-directory: ./src/raspberrypi
|
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
|
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
rasctl(1), scsidump(1)
|
rasctl(1), scsimon(1)
|
||||||
|
|
||||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
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
|
!! ------ 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
|
NAME
|
||||||
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
|
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
|
||||||
|
@ -13,10 +13,9 @@ SYNOPSIS
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins.
|
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)
|
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:
|
||||||
after the ID or HD idnetifier specifies the ID number for that device. For SCSI: The ID is limited from 0-7.
|
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‐
|
||||||
However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered
|
puters.
|
||||||
rare and only used on very early Sharp X68000 computers.
|
|
||||||
|
|
||||||
RaSCSI will determin the type of device based upon the file extension of the FILE argument.
|
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)
|
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:
|
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
|
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
|
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‐
|
||||||
process is using port 6868, RaSCSI will terminate, since it is likely another instance of RaSCSI. Once
|
stance of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used to send commands.
|
||||||
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.
|
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
|
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
rasctl(1), scsidump(1)
|
rasctl(1), scsimon(1)
|
||||||
|
|
||||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
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
|
rasctl -i 0 -f HDIIMAGE0.HDS
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
rascsi(1)
|
rascsi(1) scsimon(1)
|
||||||
|
|
||||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
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
|
!! ------ 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
|
NAME
|
||||||
rasctl - Sends management commands to the rascsi process
|
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]
|
rasctl -l | -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the sta‐
|
rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices.
|
||||||
tus of the devices.
|
|
||||||
|
|
||||||
Either the -i or -l option should be specified at one time. Not both.
|
Either the -i or -l option should be specified at one time. Not both.
|
||||||
|
|
||||||
You do NOT need root privileges to use rasctl.
|
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
|
Note: The command and type arguments are case insensitive. Only the first letter of the command/type are evaluated by the tool.
|
||||||
evaluated by the tool.
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-l List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
|
-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)
|
-i ID ID is the SCSI ID that you want to control. (0-7)
|
||||||
|
|
||||||
-u UNIT
|
-u UNIT
|
||||||
Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI
|
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)
|
||||||
devices on a shared SCSI controller. (This is not common)
|
|
||||||
|
|
||||||
-c CMD Command is the operation being requested. options are:
|
-c CMD Command is the operation being requested. options are:
|
||||||
attach: attach disk
|
attach: attach disk
|
||||||
|
@ -40,8 +37,7 @@ OPTIONS
|
||||||
When the command is omited, rasctl will default to the 'attach' command
|
When the command is omited, rasctl will default to the 'attach' command
|
||||||
|
|
||||||
-t TYPE
|
-t TYPE
|
||||||
Specifies the type of disk. If this disagrees with the file extension of the specified image, the 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:
|
||||||
argument is ignored. Available drive types are:
|
|
||||||
hd: Hard disk (SCSI or SASI)
|
hd: Hard disk (SCSI or SASI)
|
||||||
mo: Magneto-Optical disk)
|
mo: Magneto-Optical disk)
|
||||||
cd: CD-ROM
|
cd: CD-ROM
|
||||||
|
@ -61,13 +57,12 @@ EXAMPLES
|
||||||
| 0 | 1 | SCHD | /home/pi/harddisk.hda
|
| 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
|
Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image "HDIIMAGE0.HDS".
|
||||||
"HDIIMAGE0.HDS".
|
|
||||||
rasctl -i 0 -f HDIIMAGE0.HDS
|
rasctl -i 0 -f HDIIMAGE0.HDS
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
rascsi(1)
|
rascsi(1) scsimon(1)
|
||||||
|
|
||||||
Full documentation is available at: <https://www.github.com/akuker/RASCSI/wiki/>
|
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
|
*.cbp
|
||||||
*.layout
|
*.layout
|
||||||
*.log
|
*.log
|
||||||
|
*.vcd
|
||||||
rascsi
|
rascsi
|
||||||
scsimon
|
scsimon
|
||||||
rasctl
|
rasctl
|
||||||
|
|
|
@ -38,8 +38,8 @@ CXXFLAGS += -std=c++14 -iquote . -MD -MP
|
||||||
## STANDARD or FULLSPEC. The default is STANDARD
|
## STANDARD or FULLSPEC. The default is STANDARD
|
||||||
## * THIS IS TYPICALLY THE ONLY COMPILE OPTION YOU
|
## * THIS IS TYPICALLY THE ONLY COMPILE OPTION YOU
|
||||||
## * NEED TO SPECIFY
|
## * NEED TO SPECIFY
|
||||||
# If its not specified, build for STANDARD configuration
|
# If its not specified, build for FULLSPEC configuration
|
||||||
CONNECT_TYPE ?= STANDARD
|
CONNECT_TYPE ?= FULLSPEC
|
||||||
|
|
||||||
ifdef CONNECT_TYPE
|
ifdef CONNECT_TYPE
|
||||||
CFLAGS += -DCONNECT_TYPE_$(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)
|
#BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON)
|
||||||
# Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed
|
# 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!
|
# 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 = \
|
SRC_RASCSI = \
|
||||||
rascsi.cpp \
|
rascsi.cpp \
|
||||||
|
@ -83,6 +82,16 @@ SRC_RASCSI = \
|
||||||
SRC_RASCSI += $(shell find ./controllers -name '*.cpp')
|
SRC_RASCSI += $(shell find ./controllers -name '*.cpp')
|
||||||
SRC_RASCSI += $(shell find ./devices -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 = \
|
SRC_RASCTL = \
|
||||||
rasctl.cpp
|
rasctl.cpp
|
||||||
# rasctl_command.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_SASIDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SASIDUMP:%.cpp=%.o)))
|
||||||
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.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_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)
|
# 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_RASCSI) $(OBJ_RASCTL))
|
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_SCSIMON))
|
||||||
-include $(ALL_DEPS)
|
-include $(ALL_DEPS)
|
||||||
|
|
||||||
$(OBJDIR) $(BINDIR):
|
$(OBJDIR) $(BINDIR):
|
||||||
|
@ -137,21 +146,21 @@ $(OBJDIR)/%.o: %.cpp | $(OBJDIR)
|
||||||
all: $(BIN_ALL) docs
|
all: $(BIN_ALL) docs
|
||||||
ALL: all
|
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)
|
$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) | $(BINDIR)
|
||||||
$(CXX) -o $@ $(OBJ_RASCSI) -lpthread
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread
|
||||||
|
|
||||||
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) $(BINDIR)
|
$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) | $(BINDIR)
|
||||||
$(CXX) -o $@ $(OBJ_RASCTL)
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL)
|
||||||
|
|
||||||
$(RASDUMP): $(OBJ_RASDUMP) $(BINDIR)
|
$(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) | $(BINDIR)
|
||||||
$(CXX) -o $@ $(OBJ_RASDUMP)
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP)
|
||||||
|
|
||||||
$(SASIDUMP): $(OBJ_SASIDUMP) $(BINDIR)
|
$(BINDIR)/$(SASIDUMP): $(OBJ_SASIDUMP) | $(BINDIR)
|
||||||
$(CXX) -o $@ $(OBJ_SASIDUMP)
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SASIDUMP)
|
||||||
|
|
||||||
$(SCSIMON): $(OBJ_SCSIMON) $(BINDIR)
|
$(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) | $(BINDIR)
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread
|
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread
|
||||||
|
|
||||||
## clean : Remove all of the object files, intermediate
|
## clean : Remove all of the object files, intermediate
|
||||||
|
@ -180,7 +189,7 @@ run:
|
||||||
## * sudo systemctl enable rascsi
|
## * sudo systemctl enable rascsi
|
||||||
## * sudo systemctl start rascsi
|
## * sudo systemctl start rascsi
|
||||||
.PHONY: install
|
.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!"
|
@echo "-- Done installing!"
|
||||||
|
|
||||||
$(USR_LOCAL_BIN)% : $(BINDIR)/%
|
$(USR_LOCAL_BIN)% : $(BINDIR)/%
|
||||||
|
|
|
@ -296,7 +296,7 @@ BUS::phase_t FASTCALL SASIDEV::Process()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get bus information
|
// 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
|
// For the monitor tool, we shouldn't need to reset. We're just logging information
|
||||||
// Reset
|
// Reset
|
||||||
|
@ -927,7 +927,7 @@ void FASTCALL SASIDEV::Error()
|
||||||
ASSERT(this);
|
ASSERT(this);
|
||||||
|
|
||||||
// Get bus information
|
// Get bus information
|
||||||
ctrl.bus->Aquire();
|
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||||
|
|
||||||
// Reset check
|
// Reset check
|
||||||
if (ctrl.bus->GetRST()) {
|
if (ctrl.bus->GetRST()) {
|
||||||
|
|
|
@ -76,7 +76,7 @@ BUS::phase_t FASTCALL SCSIDEV::Process()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get bus information
|
// Get bus information
|
||||||
ctrl.bus->Aquire();
|
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
if (ctrl.bus->GetRST()) {
|
if (ctrl.bus->GetRST()) {
|
||||||
|
@ -488,7 +488,7 @@ void FASTCALL SCSIDEV::Error()
|
||||||
ASSERT(this);
|
ASSERT(this);
|
||||||
|
|
||||||
// Get bus information
|
// Get bus information
|
||||||
ctrl.bus->Aquire();
|
((GPIOBUS*)ctrl.bus)->Aquire();
|
||||||
|
|
||||||
// Reset check
|
// Reset check
|
||||||
if (ctrl.bus->GetRST()) {
|
if (ctrl.bus->GetRST()) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "xm6.h"
|
#include "xm6.h"
|
||||||
#include "gpiobus.h"
|
#include "gpiobus.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#ifndef BAREMETAL
|
#ifndef BAREMETAL
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -65,7 +66,7 @@ DWORD bcm_host_get_peripheral_address(void)
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
size_t len = sizeof(buf);
|
size_t len = sizeof(buf);
|
||||||
DWORD address;
|
DWORD address;
|
||||||
|
|
||||||
if (sysctlbyname("hw.model", buf, &len, NULL, 0) ||
|
if (sysctlbyname("hw.model", buf, &len, NULL, 0) ||
|
||||||
strstr(buf, "ARM1176JZ-S") != buf) {
|
strstr(buf, "ARM1176JZ-S") != buf) {
|
||||||
// Failed to get CPU model || Not BCM2835
|
// Failed to get CPU model || Not BCM2835
|
||||||
|
@ -88,7 +89,7 @@ extern uint32_t RPi_IO_Base_Addr;
|
||||||
// Core frequency
|
// Core frequency
|
||||||
extern uint32_t RPi_Core_Freq;
|
extern uint32_t RPi_Core_Freq;
|
||||||
|
|
||||||
#ifdef USE_SEL_EVENT_ENABLE
|
#ifdef USE_SEL_EVENT_ENABLE
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Interrupt control function
|
// Interrupt control function
|
||||||
|
@ -173,7 +174,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
|
||||||
// Open /dev/mem
|
// Open /dev/mem
|
||||||
fd = open("/dev/mem", O_RDWR | O_SYNC);
|
fd = open("/dev/mem", O_RDWR | O_SYNC);
|
||||||
if (fd == -1) {
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +296,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
|
||||||
// GPIO chip open
|
// GPIO chip open
|
||||||
fd = open("/dev/gpiochip0", 0);
|
fd = open("/dev/gpiochip0", 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
LOGERROR("Unable to open /dev/gpiochip0. Is RaSCSI already running?")
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +312,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode)
|
||||||
|
|
||||||
//Get event request
|
//Get event request
|
||||||
if (ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &selevreq) == -1) {
|
if (ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &selevreq) == -1) {
|
||||||
|
LOGERROR("Unable to register event request. Is RaSCSI already running?")
|
||||||
close(fd);
|
close(fd);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -522,27 +525,6 @@ void FASTCALL GPIOBUS::Reset()
|
||||||
#endif // ifdef __x86_64__ || __X86__
|
#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
|
// ENB signal setting
|
||||||
|
@ -668,6 +650,26 @@ void FASTCALL GPIOBUS::SetACK(BOOL ast)
|
||||||
SetSignal(PIN_ACK, 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
|
// Get RST signal
|
||||||
|
@ -1173,7 +1175,7 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already waiting for REQ assertion
|
// Already waiting for REQ assertion
|
||||||
|
|
||||||
// Assert the ACK signal
|
// Assert the ACK signal
|
||||||
SetSignal(PIN_ACK, ON);
|
SetSignal(PIN_ACK, ON);
|
||||||
|
|
||||||
|
@ -1233,7 +1235,7 @@ int FASTCALL GPIOBUS::PollSelectEvent()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
read(selevreq.fd, &gpev, sizeof(gpev));
|
(void)read(selevreq.fd, &gpev, sizeof(gpev));
|
||||||
#endif // BAREMETAL
|
#endif // BAREMETAL
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1417,7 +1419,7 @@ void FASTCALL GPIOBUS::SetMode(int pin, int mode)
|
||||||
gpio[index] = data;
|
gpio[index] = data;
|
||||||
gpfsel[index] = data;
|
gpfsel[index] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Get input signal value
|
// Get input signal value
|
||||||
|
@ -1427,7 +1429,7 @@ BOOL FASTCALL GPIOBUS::GetSignal(int pin)
|
||||||
{
|
{
|
||||||
return (signals >> pin) & 1;
|
return (signals >> pin) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Set output signal value
|
// Set output signal value
|
||||||
|
@ -1645,6 +1647,39 @@ void FASTCALL GPIOBUS::DrvConfig(DWORD drive)
|
||||||
pads[PAD_0_27] = (0xFFFFFFF8 & data) | drive | 0x5a000000;
|
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
|
// System timer address
|
||||||
|
|
|
@ -276,6 +276,26 @@
|
||||||
#define PIN_SEL 23 // SEL
|
#define PIN_SEL 23 // SEL
|
||||||
#endif
|
#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)
|
// Constant declarations(GPIO)
|
||||||
|
@ -434,8 +454,28 @@ public:
|
||||||
void FASTCALL Cleanup();
|
void FASTCALL Cleanup();
|
||||||
// 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);
|
void FASTCALL SetENB(BOOL ast);
|
||||||
// Set ENB signal
|
// Set ENB signal
|
||||||
|
@ -460,6 +500,11 @@ public:
|
||||||
void FASTCALL SetACK(BOOL ast);
|
void FASTCALL SetACK(BOOL ast);
|
||||||
// Set ACK signal
|
// Set ACK signal
|
||||||
|
|
||||||
|
BOOL FASTCALL GetACT();
|
||||||
|
// Get ACT signal
|
||||||
|
void FASTCALL SetACT(BOOL ast);
|
||||||
|
// Set ACT signal
|
||||||
|
|
||||||
BOOL FASTCALL GetRST();
|
BOOL FASTCALL GetRST();
|
||||||
// Get RST signal
|
// Get RST signal
|
||||||
void FASTCALL SetRST(BOOL ast);
|
void FASTCALL SetRST(BOOL ast);
|
||||||
|
@ -498,6 +543,9 @@ public:
|
||||||
int FASTCALL SendHandShake(BYTE *buf, int count);
|
int FASTCALL SendHandShake(BYTE *buf, int count);
|
||||||
// Data transmission handshake
|
// Data transmission handshake
|
||||||
|
|
||||||
|
static BUS::phase_t FASTCALL GetPhaseRaw(DWORD raw_data);
|
||||||
|
// Get the phase based on raw data
|
||||||
|
|
||||||
#ifdef USE_SEL_EVENT_ENABLE
|
#ifdef USE_SEL_EVENT_ENABLE
|
||||||
// SEL signal interrupt
|
// SEL signal interrupt
|
||||||
int FASTCALL PollSelectEvent();
|
int FASTCALL PollSelectEvent();
|
||||||
|
|
|
@ -5,13 +5,37 @@
|
||||||
//
|
//
|
||||||
// Powered by XM6 TypeG Technology.
|
// Powered by XM6 TypeG Technology.
|
||||||
// Copyright (C) 2016-2020 GIMONS
|
// Copyright (C) 2016-2020 GIMONS
|
||||||
// [ ログ ]
|
// Copyright (C) 2020 akuker
|
||||||
|
// [ Logging utilities ]
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#if !defined(log_h)
|
#if !defined(log_h)
|
||||||
#define 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/scsidev_ctrl.h"
|
||||||
#include "controllers/sasidev_ctrl.h"
|
#include "controllers/sasidev_ctrl.h"
|
||||||
#include "gpiobus.h"
|
#include "gpiobus.h"
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -1064,6 +1064,8 @@ int main(int argc, char* argv[])
|
||||||
struct sched_param schparam;
|
struct sched_param schparam;
|
||||||
#endif // BAREMETAL
|
#endif // BAREMETAL
|
||||||
|
|
||||||
|
spdlog::set_level(spdlog::level::trace);
|
||||||
|
LOGTRACE("Entering the function %s with %d arguments", __PRETTY_FUNCTION__, argc);
|
||||||
// Output the Banner
|
// Output the Banner
|
||||||
Banner(argc, argv);
|
Banner(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -41,18 +41,58 @@ BUS::phase_t FASTCALL BUS::GetPhase()
|
||||||
return GetPhase(mci);
|
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
|
// 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] = {
|
const BUS::phase_t BUS::phase_table[8] = {
|
||||||
dataout,
|
// | MSG|C/D|I/O |
|
||||||
datain,
|
dataout, // | 0 | 0 | 0 |
|
||||||
command,
|
datain, // | 0 | 0 | 1 |
|
||||||
status,
|
command, // | 0 | 1 | 0 |
|
||||||
reserved,
|
status, // | 0 | 1 | 1 |
|
||||||
reserved,
|
reserved, // | 1 | 0 | 0 |
|
||||||
msgout,
|
reserved, // | 1 | 0 | 1 |
|
||||||
msgin
|
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;
|
virtual BOOL FASTCALL GetBSY() = 0;
|
||||||
// BSYシグナル取得
|
// BSYシグナル取得
|
||||||
|
@ -125,6 +131,8 @@ public:
|
||||||
private:
|
private:
|
||||||
static const phase_t phase_table[8];
|
static const phase_t phase_table[8];
|
||||||
// フェーズテーブル
|
// フェーズテーブル
|
||||||
|
|
||||||
|
static const char* phase_str_table[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // scsi_h
|
#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…
Reference in New Issue
Block a user