Issue #7 - implement a scsi monitor function for RaSCSI to log SCSI traffic (#46)

* #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:
akuker 2020-10-19 07:31:06 -05:00 committed by GitHub
parent 3ddeac6180
commit 1118c344cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 739 additions and 88 deletions

View File

@ -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

View File

@ -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/>

View File

@ -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)

View File

@ -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/>

View File

@ -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
View 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
View 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)

View File

@ -4,6 +4,7 @@
*.cbp *.cbp
*.layout *.layout
*.log *.log
*.vcd
rascsi rascsi
scsimon scsimon
rasctl rasctl

View File

@ -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)/%

View File

@ -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()) {

View File

@ -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()) {

View File

@ -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

View File

@ -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();

View File

@ -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__)
//=========================================================================== //===========================================================================
// //
// ログ // ログ

View File

@ -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);

View File

@ -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"
}; };

View File

@ -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
View 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);
}