Basic discrete I/O seems to be partially working

This commit is contained in:
Tony Kuker 2022-10-30 17:50:49 -05:00
parent 245098be07
commit 61966a577b
14 changed files with 1215 additions and 414 deletions

3
cpp/.gitignore vendored
View File

@ -7,6 +7,8 @@
*.vcd
*.json
*.html
*.d
*.o
rascsi.dat
obj
bin
@ -16,3 +18,4 @@ coverage
.project
.cproject
.settings
settings.json

View File

@ -1,45 +0,0 @@
{
"files.associations": {
"cstddef": "cpp",
"array": "cpp",
"chrono": "cpp",
"functional": "cpp",
"istream": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"cstdint": "cpp",
"stdexcept": "cpp",
"deque": "cpp",
"vector": "cpp",
"compare": "cpp",
"cwchar": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"limits": "cpp",
"new": "cpp",
"string": "cpp",
"string_view": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"concepts": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwctype": "cpp",
"map": "cpp",
"exception": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"memory": "cpp",
"numbers": "cpp",
"streambuf": "cpp",
"system_error": "cpp",
"typeinfo": "cpp"
}
}

View File

@ -60,7 +60,7 @@ RASDUMP = rasdump
SCSIMON = scsimon
RASCSI_TEST = rascsi_test
REGISTERS_TEST = registers
GPIO_TEST = gpiotest
SCSILOOP = scsiloop
SYSTEMD_CONF = /etc/systemd/system/rascsi.service
RSYSLOG_CONF = /etc/rsyslog.d/rascsi.conf
@ -80,7 +80,8 @@ BIN_ALL = \
$(BINDIR)/$(RASCSI) \
$(BINDIR)/$(RASCTL) \
$(BINDIR)/$(SCSIMON) \
$(BINDIR)/$(RASDUMP)
$(BINDIR)/$(RASDUMP) \
$(BINDIR)/$(SCSILOOP)
SRC_PROTOC = \
rascsi_interface.proto
@ -89,6 +90,7 @@ SRC_PROTOBUF = \
rascsi_interface.pb.cpp
SRC_SHARED = \
list_devices.cpp \
rascsi_version.cpp \
rasutil.cpp \
protobuf_util.cpp \
@ -123,12 +125,14 @@ SRC_RASDUMP += $(shell find ./hal -name '*.cpp')
SRC_RASCSI_TEST = $(shell find ./test -name '*.cpp')
SRC_GPIO_TEST = \
scsi.cpp \
gpiotest.cpp
SRC_GPIO_TEST += $(shell find ./hal -name '*.cpp')
SRC_SCSILOOP= \
scsiloop.cpp \
bus.cpp \
rasutil.cpp \
rascsi_version.cpp
SRC_SCSILOOP += $(shell find ./hal -name '*.cpp')
vpath %.h ./ ./controllers ./devices ./monitor ./hal ./hal/boards ./hal/pi_defs ./rascsi ./rasctl ../BPI-WiringPi2/wiringPi/
vpath %.h ./ ./controllers ./devices ./monitor ./hal ./hal/boards ./hal/pi_defs ./rascsi ./rasctl
vpath %.cpp ./ ./controllers ./devices ./monitor ./test ./hal ./hal/boards ./hal/pi_defs ./rascsi ./rasctl
vpath %.o ./$(OBJDIR)
vpath ./$(BINDIR)
@ -140,18 +144,16 @@ OBJ_RASCTL_CORE := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCTL_CORE:%.cpp=%.o))
OBJ_RASCTL := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCTL:%.cpp=%.o)))
OBJ_RASDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASDUMP:%.cpp=%.o)))
OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
OBJ_SCSILOOP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSILOOP:%.cpp=%.o)))
OBJ_RASCSI_TEST := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCSI_TEST:%.cpp=%.o)))
OBJ_SHARED := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SHARED:%.cpp=%.o)))
OBJ_PROTOBUF := $(addprefix $(OBJDIR)/,$(notdir $(SRC_PROTOBUF:%.cpp=%.o)))
OBJ_GPIO_TEST := $(addprefix $(OBJDIR)/,$(notdir $(SRC_GPIO_TEST:%.cpp=%.o)))
GEN_PROTOBUF := $(SRC_PROTOBUF) rascsi_interface.pb.h
LIB_BPI_WIRINGPI := $(OBJDIR)/libwiringPi.a
# The following will include all of the auto-generated dependency files (*.d)
# if they exist. This will trigger a rebuild of a source file if a header changes
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_SCSIMON) $(OBJ_RASCSI_TEST))
ALL_DEPS := $(patsubst %.o,%.d,$(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_SCSIMON) $(OBJ_SCSILOOP) $(OBJ_RASCSI_TEST))
-include $(ALL_DEPS)
$(OBJDIR) $(BINDIR):
@ -194,39 +196,39 @@ docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(DOC_DIR)/s
$(SRC_SHARED) $(SRC_RASCSI_CORE) $(SRC_RASCTL_CORE): $(OBJ_PROTOBUF)
$(BINDIR)/$(RASCSI): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(LIB_BPI_WIRINGPI) | $(BINDIR)
$(BINDIR)/$(RASCSI): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCSI) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(LIB_BPI_WIRINGPI) -lpthread -lpcap -lprotobuf -lstdc++fs
$(BINDIR)/$(RASCTL): $(SRC_PROTOBUF) $(OBJ_RASCTL_CORE) $(OBJ_RASCTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(LIB_BPI_WIRINGPI) | $(BINDIR)
$(BINDIR)/$(RASCTL): $(SRC_PROTOBUF) $(OBJ_RASCTL_CORE) $(OBJ_RASCTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL_CORE) $(OBJ_RASCTL) $(OBJ_SHARED) $(OBJ_PROTOBUF) -lpthread -lprotobuf
$(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) $(LIB_BPI_WIRINGPI) | $(BINDIR)
$(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP) $(LIB_BPI_WIRINGPI) -lpthread
$(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) $(LIB_BPI_WIRINGPI) | $(BINDIR)
$(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) $(LIB_BPI_WIRINGPI) -lpthread
$(BINDIR)/$(RASCSI_TEST): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI_TEST) $(OBJ_RASCTL_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(LIB_BPI_WIRINGPI) | $(BINDIR)
$(BINDIR)/$(RASCSI_TEST): $(SRC_PROTOBUF) $(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI_TEST) $(OBJ_RASCTL_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI_CORE) $(OBJ_RASCTL_CORE) $(OBJ_RASCSI_TEST) $(OBJ_SHARED) $(OBJ_PROTOBUF) $(LIB_BPI_WIRINGPI) -lpthread -lpcap -lprotobuf -lstdc++fs -lgmock -lgtest
$(BINDIR)/$(GPIO_TEST): $(OBJ_GPIO_TEST) $(LIB_BPI_WIRINGPI) | $(BINDIR)
echo $(OBJ_GPIO_TEST)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_GPIO_TEST) $(LIB_BPI_WIRINGPI) -lpthread
$(BINDIR)/$(SCSILOOP): $(SRC_PROTOBUF) $(OBJ_SCSILOOP) | $(BINDIR)
echo SCSILOOP SRC: $(SRC_SCSILOOP)
echo SCSILOOP OBJ: $(OBJ_SCSILOOP)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSILOOP) -lpthread
# Phony rules for building individual utilities
.PHONY: $(RASCSI) $(RASCTL) $(RASDUMP) $(SCSIMON) $(GPIO_TEST)
.PHONY: $(RASCSI) $(RASCTL) $(RASDUMP) $(SCSIMON) $(SCSILOOP)
$(RASCSI) : $(BINDIR)/$(RASCSI)
$(RASCTL) : $(BINDIR)/$(RASCTL)
$(RASDUMP) : $(BINDIR)/$(RASDUMP)
$(SCSIMON) : $(BINDIR)/$(SCSIMON)
$(GPIO_TEST) : $(BINDIR)/$(GPIO_TEST)
$(SCSILOOP) : $(BINDIR)/$(SCSILOOP)
## clean : Remove all of the object files, intermediate
## compiler files and executable files
.PHONY: clean
clean:
make -j1 -C ../BPI-WiringPi2/wiringPi/ clean
rm -rf $(OBJDIR) $(BINDIR) $(GEN_PROTOBUF) $(COVERAGE_DIR) $(COVERAGE_FILE)
## install : Copies all of the man pages to the correct location
@ -286,12 +288,6 @@ $(MAN_PAGE_DIR)/:
echo "-- Creating directory $@"
mkdir -p $@
$(LIB_BPI_WIRINGPI) : | $(OBJDIR)
make -j1 -C ../BPI-WiringPi2/wiringPi/ static CC=$(CC) AR=$(AR) RANLIB=$(RANLIB)
cp ../BPI-WiringPi2/wiringPi/libwiringPi.a $@
## help : Lists information about how to use the makefile
# The help rule is based upon the approach from:
# https://swcarpentry.github.io/make-novice/08-self-doc/index.html

4
cpp/build_and_copy.sh Executable file
View File

@ -0,0 +1,4 @@
#/bin/sh
clear
make scsiloop CROSS_COMPILE=arm-linux-gnueabihf- -j8
scp ./bin/fullspec/* akuker@10.0.1.116:/home/akuker/

View File

@ -1,260 +0,0 @@
// Kernel module to access cycle count registers:
// https://matthewarcus.wordpress.com/2018/01/27/using-the-cycle-counter-registers-on-the-raspberry-pi-3/
//https://mindplusplus.wordpress.com/2013/05/21/accessing-the-raspberry-pis-1mhz-timer/
// Reading register from user space:
// https://stackoverflow.com/questions/59749160/reading-from-register-of-allwinner-h3-arm-processor
// Maybe kernel patch>
//https://yhbt.net/lore/all/20140707085858.GG16262@lukather/T/
//
// Access the Raspberry Pi System Timer registers directly.
//
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include "hal/sbc_version.h"
#include "hal/systimer.h"
#include <sched.h>
#include <string>
#include "common.h"
#include "log.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "hal/gpiobus.h"
#include "hal/gpiobus_factory.h"
using namespace std;
using namespace spdlog;
bool InitBus()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
SBC_Version::Init();
return true;
}
void test_timer();
void test_gpio();
//---------------------------------------------------------------------------
//
// Pin the thread to a specific CPU
//
//---------------------------------------------------------------------------
void FixCpu(int cpu)
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
// Get the number of CPUs
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
sched_getaffinity(0, sizeof(cpu_set_t), &cpuset);
int 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);
}
}
string current_log_level = "";
bool SetLogLevel(const string& log_level)
{
if (log_level == "trace") {
set_level(level::trace);
}
else if (log_level == "debug") {
set_level(level::debug);
}
else if (log_level == "info") {
set_level(level::info);
}
else if (log_level == "warn") {
set_level(level::warn);
}
else if (log_level == "err") {
set_level(level::err);
}
else if (log_level == "critical") {
set_level(level::critical);
}
else if (log_level == "off") {
set_level(level::off);
}
else {
return false;
}
current_log_level = log_level;
LOGINFO("Set log level to '%s'", current_log_level.c_str())
return true;
}
void TerminationHandler(int signum)
{
// Cleanup();
exit(signum);
}
#include "wiringPi.h"
void blink(){
printf("Simple Blink\n");
wiringPiSetup();
for(int i=0; i<20; i++){
pinMode(i,OUTPUT);
}
for(int i=0; i<20; i++){
for(int pin=0; pin<20; pin++){
printf("Setting pin %d high\n", pin);
digitalWrite(pin, HIGH);
delay(100);
}
for(int pin=0; pin<20; pin++){
printf("Setting pin %d low\n", pin);
digitalWrite(pin, LOW);
delay(100);
}
}
}
//---------------------------------------------------------------------------
//
// Main processing
//
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
// added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.
setvbuf(stdout, nullptr, _IONBF, 0);
if(argc > 1){
SetLogLevel(argv[1]);
}else{
SetLogLevel("trace");
}
// Create a thread-safe stdout logger to process the log messages
auto logger = spdlog::stdout_color_mt("rascsi stdout logger");
// Signal handler to detach all devices on a KILL or TERM signal
struct sigaction termination_handler;
termination_handler.sa_handler = TerminationHandler;
sigemptyset(&termination_handler.sa_mask);
termination_handler.sa_flags = 0;
sigaction(SIGINT, &termination_handler, nullptr);
sigaction(SIGTERM, &termination_handler, nullptr);
if (!InitBus()) {
return EPERM;
}
// blink();
// test_timer();
test_gpio();
}
void test_gpio(){
// Force the system timer to initialize
SysTimer::instance().SleepNsec(0);
auto gpio_bus = GPIOBUS_Factory::Create();
gpio_bus->Init(TARGET);
printf("----------- Done with init()\n");
printf("----------- Done with init()\n");
printf("----------- Done with init()\n");
printf("----------- Done with init()\n");
for(int i = 0; i< 10; i++){
LOGTRACE("%s Blink on", __PRETTY_FUNCTION__);
// gpio_bus->SetSignal(gpio_bus->PIN_ACT, true);
sleep(1);
LOGTRACE("%s Blink off", __PRETTY_FUNCTION__);
// gpio_bus->SetSignal(gpio_bus->PIN_ACT, false);
sleep(1);
}
//gpio_bus->SetDirectionOut();
LOGTRACE("%s Data 0x00", __PRETTY_FUNCTION__);
gpio_bus->SetDAT(0x0);
sleep(1);
LOGTRACE("%s Data 0xFF", __PRETTY_FUNCTION__);
gpio_bus->SetDAT(0xFF);
sleep(1);
LOGTRACE("%s Data 0xAA", __PRETTY_FUNCTION__);
gpio_bus->SetDAT(0xAA);
sleep(1);
LOGTRACE("%s Data 0x55", __PRETTY_FUNCTION__);
gpio_bus->SetDAT(0x55);
}
void test_timer(){
uint32_t before = SysTimer::instance().GetTimerLow();
sleep(1);
uint32_t after = SysTimer::instance().GetTimerLow();
LOGINFO("first sample: %d %08X", (before - after), (after - before));
uint64_t sum = 0;
int count = 0;
for(int i=0; i < 100; i++){
before = SysTimer::instance().GetTimerLow();
usleep(1000);
after = SysTimer::instance().GetTimerLow();
sum += (after - before);
count ++;
}
LOGINFO("usleep() Average %d", (uint32_t)(sum / count));
sum = 0;
count = 0;
for(int i=0; i < 100; i++){
before = SysTimer::instance().GetTimerLow();
SysTimer::instance().SleepUsec(1000);
after = SysTimer::instance().GetTimerLow();
sum += (after - before);
count ++;
}
LOGINFO("usleep() Average %d", (uint32_t)(sum / count));
before = SysTimer::instance().GetTimerLow();
SysTimer::instance().SleepNsec(1000000);
after = SysTimer::instance().GetTimerLow();
LOGINFO("SysTimer::instance().SleepNSec: %d (expected ~1000)", (uint32_t)(after - before));
}

View File

@ -93,7 +93,7 @@ bool GPIOBUS::Init(mode_e mode, board_type::rascsi_board_type_e rascsi_type)
board = make_shared<board_type::Rascsi_Board_Type>(board_type::board_definition_standard);
break;
}
board = make_shared<board_type::Rascsi_Board_Type>(board_type::board_definition_aibom);
LOGINFO("Detected board type: %s", board->connect_desc.c_str());
// Save operation mode
actmode = mode;
@ -121,24 +121,20 @@ bool GPIOBUS::Init(mode_e mode, board_type::rascsi_board_type_e rascsi_type)
}
// The GPIO hardware needs to be initialized before calling this function.
void GPIOBUS::InitializeGpio(){
// Set pull up/pull down
void GPIOBUS::InitializeGpio()
{
// Set pull up/pull down
LOGTRACE("%s Set pull up/down....", __PRETTY_FUNCTION__);
board_type::gpio_pull_up_down_e pullmode ;
if (board->signal_control_mode == 0)
{
board_type::gpio_pull_up_down_e pullmode;
if (board->signal_control_mode == 0) {
// #if SIGNAL_CONTROL_MODE == 0
LOGTRACE("%s GPIO_PULLNONE", __PRETTY_FUNCTION__);
pullmode = board_type::gpio_pull_up_down_e::GPIO_PULLNONE;
}
else if (board->signal_control_mode == 1)
{
} else if (board->signal_control_mode == 1) {
// #elif SIGNAL_CONTROL_MODE == 1
LOGTRACE("%s GPIO_PULLUP", __PRETTY_FUNCTION__);
pullmode = board_type::gpio_pull_up_down_e ::GPIO_PULLUP;
}
else
{
} else {
// #else
LOGTRACE("%s GPIO_PULLDOWN", __PRETTY_FUNCTION__);
pullmode = board_type::gpio_pull_up_down_e ::GPIO_PULLDOWN;
@ -170,7 +166,6 @@ void GPIOBUS::InitializeGpio(){
// This is used to show that the application is running
PinSetSignal(board->pin_enb, board->EnbOff());
PinConfig(board->pin_enb, board_type::gpio_direction_e::GPIO_OUTPUT);
}
void GPIOBUS::Cleanup()
@ -284,8 +279,9 @@ void GPIOBUS::Reset()
SetMode(board->pin_dp, board_type::gpio_direction_e::GPIO_OUTPUT);
}
// Initialize all signals
signals = 0;
// Re-read all signals
Acquire();
// signals = 0;
#endif // ifdef __x86_64__ || __X86__
}
@ -1116,3 +1112,11 @@ int GPIOBUS::GetCommandByteCount(BYTE opcode)
return 6;
}
}
const string GPIOBUS::GetConnectDesc()
{
if (board == nullptr) {
return "unknown";
}
return board->connect_desc;
}

View File

@ -43,7 +43,7 @@
// #else
// #error Invalid connection type or none specified
// #endif
#define ENABLE_GPIO_TRACE
#ifdef ENABLE_GPIO_TRACE
#define GPIO_FUNCTION_TRACE LOGTRACE("%s", __PRETTY_FUNCTION__)
#else
@ -352,10 +352,7 @@ class GPIOBUS : public BUS
static int GetCommandByteCount(BYTE opcode);
const string GetConnectDesc()
{
return board->connect_desc;
}
const string GetConnectDesc();
#ifdef USE_SEL_EVENT_ENABLE
// SEL signal interrupt
@ -365,7 +362,11 @@ class GPIOBUS : public BUS
// Clear SEL signal event
#endif // USE_SEL_EVENT_ENABLE
protected:
// TODO: THIS SHOULD BE PROTECTED
static vector<board_type::pi_physical_pin_e> SignalTable; // signal table
// TODO: RESTORE THIS TO PROTECTED!!!
// protected:
// SCSI I/O signal control
virtual void MakeTable() = 0;
// Create work data
@ -397,13 +398,13 @@ class GPIOBUS : public BUS
mode_e actmode = mode_e::TARGET; // Operation mode
shared_ptr<board_type::Rascsi_Board_Type> board;
shared_ptr<board_type::Rascsi_Board_Type> board = nullptr;
#if !defined(__x86_64__) && !defined(__X86__)
uint32_t baseaddr = 0; // Base address
#endif
static vector<board_type::pi_physical_pin_e> SignalTable; // signal table
#ifdef USE_SEL_EVENT_ENABLE
struct gpioevent_request selevreq = {}; // SEL signal event request
@ -442,7 +443,7 @@ class GPIOBUS : public BUS
array<uint32_t, 4> gpfsel; // GPFSEL0-4 backup values
uint32_t signals = 0; // All bus signals
#if SIGNAL_CONTROL_MODE == 0
array<array<uint32_t, 256>, 3> tblDatMsk; // Data mask table

View File

@ -39,6 +39,7 @@
#include "hal/gpiobus.h"
#include "hal/gpiobus_allwinner.h"
#include "hal/pi_defs/bpi-gpio.h"
#include "hal/systimer.h"
#include "log.h"
extern int wiringPiMode;
@ -146,12 +147,42 @@ GPIOBUS_Allwinner::BpiBoardsType GPIOBUS_Allwinner::bpiboard[] = {
{NULL, 0, 0, 1, 2, 5, 0, NULL, NULL, NULL},
};
std::vector<int> gpio_banks;
bool GPIOBUS_Allwinner::Init(mode_e mode, board_type::rascsi_board_type_e rascsi_type)
{
GPIOBUS::Init(mode, rascsi_type);
SysTimer::Init();
// Hard-coding to banana pi m2 plus for now
phys_to_gpio_map = make_shared<Banana_Pi_Gpio_Mapping>(banana_pi_m2p_map);
sunxi_setup();
for (auto const &pair : phys_to_gpio_map->phys_to_gpio_map) {
LOGDEBUG("{ %d, : %d}", (int)pair.first, pair.second)
int phys_pin = (int)pair.first;
if (phys_pin < 0) {
continue;
}
int gpio_num = pair.second;
int gpio_bank = GPIO_BANK(gpio_num);
if (std::find(gpio_banks.begin(), gpio_banks.end(), gpio_bank) != gpio_banks.end()) {
LOGTRACE("Duplicate bank: %d", gpio_bank)
} else {
LOGDEBUG("New bank: %d", gpio_bank);
gpio_banks.push_back(gpio_bank);
}
}
for (auto const &pair : phys_to_gpio_map->phys_to_gpio_map) {
LOGDEBUG("{ %d, : %d}", (int)pair.first, pair.second)
}
if (int result = sunxi_setup(); result != SETUP_OK) {
return false;
}
// wiringPiSetup();
// wiringPiMode = WPI_MODE_GPIO;
@ -293,32 +324,35 @@ BYTE GPIOBUS_Allwinner::GetDAT()
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
// LOGDEBUG("0:%02X 1:%02X 2:%02X 3:%02X 4:%02X 5:%02X 6:%02X 7:%02X P:%02X", GetSignal(PIN_DT0),
// GetSignal(PIN_DT1),GetSignal(PIN_DT2),GetSignal(PIN_DT3),GetSignal(PIN_DT4),GetSignal(PIN_DT5),GetSignal(PIN_DT6),GetSignal(PIN_DT7),GetSignal(PIN_DP));
// // TODO: This is crazy inefficient...
// DWORD data =
// ((GetSignal(PIN_DT0) ? 0x01: 0x00)<< 0) |
// ((GetSignal(PIN_DT1) ? 0x01: 0x00)<< 1) |
// ((GetSignal(PIN_DT2) ? 0x01: 0x00)<< 2) |
// ((GetSignal(PIN_DT3) ? 0x01: 0x00)<< 3) |
// ((GetSignal(PIN_DT4) ? 0x01: 0x00)<< 0) |
// ((GetSignal(PIN_DT5) ? 0x01: 0x00)<< 5) |
// ((GetSignal(PIN_DT6) ? 0x01: 0x00)<< 6) |
// ((GetSignal(PIN_DT7) ? 0x01: 0x00)<< 7);
// TODO: This is crazy inefficient...
DWORD data = ((GetSignal(board->pin_dt0) ? 0x01 : 0x00) << 0) | ((GetSignal(board->pin_dt1) ? 0x01 : 0x00) << 1) |
((GetSignal(board->pin_dt2) ? 0x01 : 0x00) << 2) | ((GetSignal(board->pin_dt3) ? 0x01 : 0x00) << 3) |
((GetSignal(board->pin_dt4) ? 0x01 : 0x00) << 0) | ((GetSignal(board->pin_dt5) ? 0x01 : 0x00) << 5) |
((GetSignal(board->pin_dt6) ? 0x01 : 0x00) << 6) | ((GetSignal(board->pin_dt7) ? 0x01 : 0x00) << 7);
// return (BYTE)data;
return 0;
return (BYTE)data;
// return 0;
}
void GPIOBUS_Allwinner::SetDAT(BYTE dat)
{
// TODO: This is crazy inefficient...
// SetSignal(PIN_DT0, dat & (1 << 0));
// SetSignal(PIN_DT1, dat & (1 << 1));
// SetSignal(PIN_DT2, dat & (1 << 2));
// SetSignal(PIN_DT3, dat & (1 << 3));
// SetSignal(PIN_DT4, dat & (1 << 4));
// SetSignal(PIN_DT5, dat & (1 << 5));
// SetSignal(PIN_DT6, dat & (1 << 6));
// SetSignal(PIN_DT7, dat & (1 << 7));
PinSetSignal(board->pin_dt0, (dat & (1 << 0)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt1, (dat & (1 << 1)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt2, (dat & (1 << 2)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt3, (dat & (1 << 3)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt4, (dat & (1 << 4)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt5, (dat & (1 << 5)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt6, (dat & (1 << 6)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
PinSetSignal(board->pin_dt7, (dat & (1 << 7)) != 0 ? board_type::gpio_high_low_e::GPIO_STATE_HIGH
: board_type::gpio_high_low_e::GPIO_STATE_LOW);
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
}
@ -329,12 +363,17 @@ void GPIOBUS_Allwinner::MakeTable(void)
void GPIOBUS_Allwinner::SetControl(board_type::pi_physical_pin_e pin, board_type::gpio_high_low_e ast)
{
GPIO_FUNCTION_TRACE
if ((int)pin < 0) {
return;
}
GPIOBUS_Allwinner::SetSignal(pin, ast);
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
// LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
}
void GPIOBUS_Allwinner::SetMode(board_type::pi_physical_pin_e pin, board_type::gpio_direction_e mode)
{
GPIO_FUNCTION_TRACE
int gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
int sunxi_gpio_direction = (mode == board_type::gpio_direction_e::GPIO_INPUT) ? INPUT : OUTPUT;
@ -349,10 +388,12 @@ void GPIOBUS_Allwinner::SetMode(board_type::pi_physical_pin_e pin, board_type::g
// LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
}
bool GPIOBUS_Allwinner::GetSignal(board_type::pi_physical_pin_e pin)
bool GPIOBUS_Allwinner::GetSignal(board_type::pi_physical_pin_e pin) const
{
GPIO_FUNCTION_TRACE
int gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
int sunxi_gpio_state = sunxi_input_gpio(gpio_num);
LOGDEBUG("%s GPIO %d is set to %d", __PRETTY_FUNCTION__, gpio_num, sunxi_gpio_state);
if (sunxi_gpio_state == HIGH) {
return true;
@ -364,8 +405,12 @@ bool GPIOBUS_Allwinner::GetSignal(board_type::pi_physical_pin_e pin)
void GPIOBUS_Allwinner::SetSignal(board_type::pi_physical_pin_e pin, board_type::gpio_high_low_e ast)
{
GPIO_FUNCTION_TRACE
LOGTRACE("pin(%d) ast(%d)", (int)pin, (int)ast)
int gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
int sunxi_gpio_state = (ast == board_type::gpio_high_low_e::GPIO_STATE_HIGH) ? HIGH : LOW;
LOGTRACE("gpio(%d) sunxi_state(%d)", gpio_num, sunxi_gpio_state)
sunxi_output_gpio(gpio_num, sunxi_gpio_state);
// LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
// digitalWrite(pin, ast);
@ -418,9 +463,16 @@ void GPIOBUS_Allwinner::EnableIRQ()
void GPIOBUS_Allwinner::PinConfig(board_type::pi_physical_pin_e pin, board_type::gpio_direction_e mode)
{
int gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
int sunxi_gpio_state = (mode == board_type::gpio_direction_e::GPIO_INPUT) ? INPUT : OUTPUT;
sunxi_output_gpio(gpio_num, sunxi_gpio_state);
GPIO_FUNCTION_TRACE
int gpio_num = 0;
try {
gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
} catch (const std::out_of_range &e) {
LOGERROR("%s %d is not a valid pin", __PRETTY_FUNCTION__, (int)pin);
}
int sunxi_direction = (mode == board_type::gpio_direction_e::GPIO_INPUT) ? INPUT : OUTPUT;
sunxi_setup_gpio(gpio_num, sunxi_direction, -1);
// sunxi_output_gpio(gpio_num, sunxi_gpio_state);
// if(mode == board_type::gpio_high_low_e::GPIO_INPUT){
// pinMode(pin, INPUT);
@ -432,6 +484,7 @@ void GPIOBUS_Allwinner::PinConfig(board_type::pi_physical_pin_e pin, board_type:
void GPIOBUS_Allwinner::PullConfig(board_type::pi_physical_pin_e pin, board_type::gpio_pull_up_down_e mode)
{
GPIO_FUNCTION_TRACE
// Note: this will throw an exception if an invalid pin is specified
int gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
@ -449,12 +502,18 @@ void GPIOBUS_Allwinner::PullConfig(board_type::pi_physical_pin_e pin, board_type
LOGERROR("%s INVALID PIN MODE", __PRETTY_FUNCTION__);
return;
}
LOGERROR("%s not implemented!!", __PRETTY_FUNCTION__)
}
void GPIOBUS_Allwinner::PinSetSignal(board_type::pi_physical_pin_e pin, board_type::gpio_high_low_e ast)
{
int gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
GPIO_FUNCTION_TRACE
int gpio_num = -1;
try {
gpio_num = phys_to_gpio_map->phys_to_gpio_map.at(pin);
} catch (const std::out_of_range &e) {
LOGERROR("%s %d is not a valid pin", __PRETTY_FUNCTION__, (int)pin);
exit(1);
}
int sunxi_gpio_state = (ast == board_type::gpio_high_low_e::GPIO_STATE_HIGH) ? HIGH : LOW;
sunxi_output_gpio(gpio_num, sunxi_gpio_state);
@ -470,7 +529,8 @@ void GPIOBUS_Allwinner::DrvConfig(DWORD drive)
uint32_t GPIOBUS_Allwinner::Acquire()
{
LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
(void)sunxi_capture_all_gpio();
// LOGWARN("%s NOT IMPLEMENTED", __PRETTY_FUNCTION__)
// Only used for development/debugging purposes. Isn't really applicable
// to any real-world RaSCSI application
return 0;
@ -480,8 +540,10 @@ uint32_t GPIOBUS_Allwinner::Acquire()
uint32_t GPIOBUS_Allwinner::sunxi_readl(volatile uint32_t *addr)
{
GPIO_FUNCTION_TRACE
#ifndef __arm__
(void)addr;
(void)
addr;
return 0;
#else
printf("sunxi_readl\n");
@ -495,8 +557,10 @@ uint32_t GPIOBUS_Allwinner::sunxi_readl(volatile uint32_t *addr)
void GPIOBUS_Allwinner::sunxi_writel(volatile uint32_t *addr, uint32_t val)
{
GPIO_FUNCTION_TRACE
#ifndef __arm__
(void)addr;
(void)
addr;
(void)val;
return;
#else
@ -509,6 +573,7 @@ void GPIOBUS_Allwinner::sunxi_writel(volatile uint32_t *addr, uint32_t val)
int GPIOBUS_Allwinner::sunxi_setup(void)
{
GPIO_FUNCTION_TRACE
#ifndef __arm__
return SETUP_MMAP_FAIL;
#else
@ -525,27 +590,40 @@ int GPIOBUS_Allwinner::sunxi_setup(void)
printf("enter to sunxi_setup\n");
// mmap the GPIO memory registers
if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0)
if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
LOGERROR("Error: Unable to open /dev/mem. Are you running as root?")
LOGDEBUG("errno: [%08X] %s", errno, strerror(errno));
return SETUP_DEVMEM_FAIL;
}
if ((gpio_mem = (uint8_t *)malloc(BLOCK_SIZE + (PAGE_SIZE - 1))) == NULL)
return SETUP_MALLOC_FAIL;
if ((gpio_mem = (uint8_t *)malloc(BLOCK_SIZE + (PAGE_SIZE - 1))) == NULL) {
LOGERROR("Error: Unable to allocate gpio memory. Are you running as root?")
LOGDEBUG("errno: [%08X] %s", errno, strerror(errno));
return SETUP_DEVMEM_FAIL;
}
if ((uint32_t)gpio_mem % PAGE_SIZE)
gpio_mem += PAGE_SIZE - ((uint32_t)gpio_mem % PAGE_SIZE);
gpio_map = (uint32_t *)mmap((caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, mem_fd,
SUNXI_GPIO_BASE);
pio_map = gpio_map + (SUNXI_GPIO_REG_OFFSET >> 2);
// printf("gpio_mem[%x] gpio_map[%x] pio_map[%x]\n", gpio_mem, gpio_map, pio_map);
if ((void *)gpio_map == MAP_FAILED) {
LOGERROR("Error: Unable to map gpio memory. Are you running as root?")
LOGDEBUG("errno: [%08X] %s", errno, strerror(errno));
return SETUP_MMAP_FAIL;
}
pio_map = gpio_map + (SUNXI_GPIO_REG_OFFSET >> 2);
LOGTRACE("gpio_mem[%p] gpio_map[%p] pio_map[%p]", gpio_mem, gpio_map, pio_map)
// R_PIO GPIO LMN
r_gpio_map =
(uint32_t *)mmap((caddr_t)0, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, SUNXI_R_GPIO_BASE);
r_pio_map = r_gpio_map + (SUNXI_R_GPIO_REG_OFFSET >> 2);
// printf("r_gpio_map[%x] r_pio_map[%x]\n", r_gpio_map, r_pio_map);
if ((int32_t)gpio_map < 0)
if ((void *)r_gpio_map == MAP_FAILED) {
LOGERROR("Error: Unable to map r_gpio memory. Are you running as root?")
LOGDEBUG("errno: [%08X] %s", errno, strerror(errno));
return SETUP_MMAP_FAIL;
}
r_pio_map = r_gpio_map + (SUNXI_R_GPIO_REG_OFFSET >> 2);
LOGTRACE("r_gpio_map[%p] r_pio_map[%p]", r_gpio_map, r_pio_map)
return SETUP_OK;
#endif
@ -553,8 +631,10 @@ int GPIOBUS_Allwinner::sunxi_setup(void)
void GPIOBUS_Allwinner::sunxi_set_pullupdn(int gpio, int pud)
{
GPIO_FUNCTION_TRACE
#ifndef __arm__
(void)gpio;
(void)
gpio;
(void)pud;
return;
#else
@ -562,7 +642,7 @@ void GPIOBUS_Allwinner::sunxi_set_pullupdn(int gpio, int pud)
int bank = GPIO_BANK(gpio); // gpio >> 5
int index = GPIO_PUL_INDEX(gpio); // (gpio & 0x1f) >> 4
int offset = GPIO_PUL_OFFSET(gpio); // (gpio) & 0x0F) << 1
printf("sunxi_set_pullupdn\n");
LOGDEBUG("%s gpio(%d) bank(%d) index(%d) offset(%d)", __PRETTY_FUNCTION__, gpio, bank, index, offset)
sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
/* DK, for PL and PM */
@ -580,8 +660,10 @@ void GPIOBUS_Allwinner::sunxi_set_pullupdn(int gpio, int pud)
void GPIOBUS_Allwinner::sunxi_setup_gpio(int gpio, int direction, int pud)
{
GPIO_FUNCTION_TRACE
#ifndef __arm__
(void)gpio;
(void)
gpio;
(void)direction;
(void)pud;
return;
@ -590,7 +672,8 @@ void GPIOBUS_Allwinner::sunxi_setup_gpio(int gpio, int direction, int pud)
int bank = GPIO_BANK(gpio); // gpio >> 5
int index = GPIO_CFG_INDEX(gpio); // (gpio & 0x1F) >> 3
int offset = GPIO_CFG_OFFSET(gpio); // ((gpio & 0x1F) & 0x7) << 2
printf("sunxi_setup_gpio\n");
LOGDEBUG("%s gpio(%d) bank(%d) index(%d) offset(%d)", __PRETTY_FUNCTION__, gpio, bank, index, offset)
sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
/* DK, for PL and PM */
if (bank >= 11) {
@ -609,7 +692,7 @@ void GPIOBUS_Allwinner::sunxi_setup_gpio(int gpio, int direction, int pud)
regval |= (1 << offset);
*(&pio->CFG[0] + index) = regval;
} else {
printf("line:%dgpio number error\n", __LINE__);
LOGERROR("line:%dgpio number error\n", __LINE__);
}
#endif
}
@ -617,11 +700,12 @@ void GPIOBUS_Allwinner::sunxi_setup_gpio(int gpio, int direction, int pud)
// Contribution by Eric Ptak <trouch@trouch.com>
int GPIOBUS_Allwinner::sunxi_gpio_function(int gpio)
{
GPIO_FUNCTION_TRACE
uint32_t regval = 0;
int bank = GPIO_BANK(gpio); // gpio >> 5
int index = GPIO_CFG_INDEX(gpio); // (gpio & 0x1F) >> 3
int offset = GPIO_CFG_OFFSET(gpio); // ((gpio & 0x1F) & 0x7) << 2
printf("sunxi_gpio_function\n");
sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
/* DK, for PL and PM */
if (bank >= 11) {
@ -637,13 +721,18 @@ int GPIOBUS_Allwinner::sunxi_gpio_function(int gpio)
void GPIOBUS_Allwinner::sunxi_output_gpio(int gpio, int value)
{
GPIO_FUNCTION_TRACE
int bank = GPIO_BANK(gpio); // gpio >> 5
int num = GPIO_NUM(gpio); // gpio & 0x1F
printf("gpio(%d) bank(%d) num(%d)\n", gpio, bank, num);
LOGDEBUG("%s gpio(%d) bank(%d) num(%d) value(%d)", __PRETTY_FUNCTION__, gpio, bank, num, value)
LOGTRACE("pio_map: %p", pio_map)
LOGTRACE("pio_map->gpio_bank: %p", &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[0])
sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
LOGTRACE("pio: %p", pio)
/* DK, for PL and PM */
if (bank >= 11) {
LOGTRACE("bank > 11");
bank -= 11;
pio = &((sunxi_gpio_reg_t *)r_pio_map)->gpio_bank[bank];
}
@ -654,13 +743,14 @@ void GPIOBUS_Allwinner::sunxi_output_gpio(int gpio, int value)
*(&pio->DAT) |= (1 << num);
}
int GPIOBUS_Allwinner::sunxi_input_gpio(int gpio)
int GPIOBUS_Allwinner::sunxi_input_gpio(int gpio) const
{
GPIO_FUNCTION_TRACE
uint32_t regval = 0;
int bank = GPIO_BANK(gpio); // gpio >> 5
int num = GPIO_NUM(gpio); // gpio & 0x1F
printf("gpio(%d) bank(%d) num(%d)\n", gpio, bank, num);
LOGDEBUG("%s gpio(%d) bank(%d) num(%d)", __PRETTY_FUNCTION__, gpio, bank, num);
sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
/* DK, for PL and PM */
if (bank >= 11) {
@ -674,8 +764,46 @@ int GPIOBUS_Allwinner::sunxi_input_gpio(int gpio)
return regval;
}
uint32_t GPIOBUS_Allwinner::sunxi_capture_all_gpio()
{
GPIO_FUNCTION_TRACE
uint32_t value = 0;
for (auto bank : gpio_banks) {
sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
/* DK, for PL and PM */
if (bank >= 11) {
pio = &((sunxi_gpio_reg_t *)r_pio_map)->gpio_bank[(bank - 11)];
}
uint32_t regval = *(&pio->DAT);
signals[bank] = regval;
LOGDEBUG("Bank %d value %08X", bank, regval);
}
return value;
// uint32_t regval = 0;
// int bank = GPIO_BANK(gpio); // gpio >> 5
// int num = GPIO_NUM(gpio); // gpio & 0x1F
// printf("gpio(%d) bank(%d) num(%d)\n", gpio, bank, num);
// sunxi_gpio_t *pio = &((sunxi_gpio_reg_t *)pio_map)->gpio_bank[bank];
// /* DK, for PL and PM */
// if (bank >= 11) {
// bank -= 11;
// pio = &((sunxi_gpio_reg_t *)r_pio_map)->gpio_bank[bank];
// }
// regval = *(&pio->DAT);
// regval = regval >> num;
// regval &= 1;
// return regval;
}
int GPIOBUS_Allwinner::bpi_piGpioLayout(void)
{
GPIO_FUNCTION_TRACE
FILE *bpiFd;
char buffer[1024];
char hardware[1024];
@ -764,6 +892,7 @@ int GPIOBUS_Allwinner::bpi_piGpioLayout(void)
void GPIOBUS_Allwinner::set_pullupdn(int gpio, int pud)
{
GPIO_FUNCTION_TRACE
int clk_offset = PULLUPDNCLK_OFFSET + (gpio / 32);
int shift = (gpio % 32);
@ -789,6 +918,7 @@ void GPIOBUS_Allwinner::set_pullupdn(int gpio, int pud)
void GPIOBUS_Allwinner::short_wait(void)
{
GPIO_FUNCTION_TRACE
int i;
for (i = 0; i < 150; i++) { // wait 150 cycles

View File

@ -47,7 +47,8 @@ class GPIOBUS_Allwinner : public GPIOBUS
// Get DAT signal
void SetDAT(BYTE dat) override;
// Set DAT signal
protected:
// TODO: Restore these back to protected
// protected:
// SCSI I/O signal control
void MakeTable() override;
// Create work data
@ -55,8 +56,7 @@ class GPIOBUS_Allwinner : public GPIOBUS
// Set Control Signal
void SetMode(board_type::pi_physical_pin_e pin, board_type::gpio_direction_e mode) override;
// Set SCSI I/O mode
bool GetSignal(board_type::pi_physical_pin_e pin);
bool GetSignal(board_type::pi_physical_pin_e pin) const override {(void)pin;return true;}
bool GetSignal(board_type::pi_physical_pin_e pin) const override;
// Get SCSI input signal value
void SetSignal(board_type::pi_physical_pin_e pin, board_type::gpio_high_low_e ast) override;
@ -123,7 +123,7 @@ int bpi_piGpioLayout (void);
array<uint32_t, 4> gpfsel; // GPFSEL0-4 backup values
uint32_t signals = 0; // All bus signals
array<uint32_t, 12> signals = {0}; // All bus signals
#ifdef USE_SEL_EVENT_ENABLE
struct gpioevent_request selevreq = {}; // SEL signal event request
@ -153,7 +153,7 @@ void sunxi_writel(volatile uint32_t *addr, uint32_t val);
int sunxi_gpio_function(int gpio);
void sunxi_output_gpio(int gpio, int value);
int sunxi_input_gpio(int gpio);
int sunxi_input_gpio(int gpio) const;
int bpi_found = -1;
@ -204,7 +204,7 @@ typedef struct sunxi_gpio_reg {
volatile uint32_t *r_gpio_map;
uint8_t* gpio_mmap_reg;
uint32_t sunxi_capture_all_gpio();
void set_pullupdn(int gpio, int pud);
// These definitions are from c_gpio.c and should be removed at some point!!

View File

@ -50,7 +50,8 @@ class GPIOBUS_Raspberry final : public GPIOBUS
// Get DAT signal
void SetDAT(BYTE dat) override;
// Set DAT signal
private:
// TODO: Restore this back to private
// private:
// SCSI I/O signal control
void MakeTable() override;
// Create work data

View File

@ -9,7 +9,7 @@
//---------------------------------------------------------------------------
#include "rascsi_version.h"
#include "rasutil.h"
#include "list_devices.h"
#include <sstream>
using namespace std;

View File

@ -20,6 +20,7 @@
#include "hal/gpiobus_factory.h"
#include "hal/sbc_version.h"
#include "hal/systimer.h"
#include "list_devices.h"
#include "rascsi_version.h"
#include "rascsi_exceptions.h"
#include "protobuf_serializer.h"

View File

@ -7,6 +7,7 @@
//
//---------------------------------------------------------------------------
#include "list_devices.h"
#include "rascsi_interface.pb.h"
#include "rasutil.h"
#include "rasctl_display.h"

965
cpp/scsiloop.cpp Normal file
View File

@ -0,0 +1,965 @@
// Kernel module to access cycle count registers:
// https://matthewarcus.wordpress.com/2018/01/27/using-the-cycle-counter-registers-on-the-raspberry-pi-3/
// https://mindplusplus.wordpress.com/2013/05/21/accessing-the-raspberry-pis-1mhz-timer/
// Reading register from user space:
// https://stackoverflow.com/questions/59749160/reading-from-register-of-allwinner-h3-arm-processor
// Maybe kernel patch>
// https://yhbt.net/lore/all/20140707085858.GG16262@lukather/T/
//
// Access the Raspberry Pi System Timer registers directly.
//
#include "hal/sbc_version.h"
#include "hal/systimer.h"
#include "rascsi_version.h"
#include "rasutil.h"
#include <fcntl.h>
#include <iostream>
#include <memory>
#include <ostream>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/mman.h>
#include <unistd.h>
// #include "common.h"
#include "log.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"
#include "hal/gpiobus.h"
#include "hal/gpiobus_factory.h"
using namespace std;
using namespace spdlog;
//---------------------------------------------------------------------------
//
// Constant declarations
//
//---------------------------------------------------------------------------
static const int DEFAULT_PORT = 6868;
static const char COMPONENT_SEPARATOR = ':';
//---------------------------------------------------------------------------
//
// Variable declarations
//
//---------------------------------------------------------------------------
static volatile bool active; // Processing flag
// RascsiService service;
shared_ptr<GPIOBUS> bus;
string current_log_level = "debug"; // Some versions of spdlog do not support get_log_level()
string access_token;
// DeviceFactory device_factory;
// shared_ptr<ControllerManager> controller_manager;
// RascsiImage rascsi_image;
// shared_ptr<RascsiResponse> rascsi_response;
// shared_ptr<RascsiExecutor> executor;
// const ProtobufSerializer serializer;
string connection_type = "hard-coded fullspec";
void Banner(int argc, char *argv[])
{
cout << ras_util::Banner("Reloaded");
cout << "Connect type: " << connection_type << '\n' << flush;
if ((argc > 1 && strcmp(argv[1], "-h") == 0) || (argc > 1 && strcmp(argv[1], "--help") == 0)) {
cout << "\nUsage: " << argv[0] << " [-idn[:m] FILE] ...\n\n";
cout << " n is SCSI device ID (0-7).\n";
cout << " m is the optional logical unit (LUN) (0-31).\n";
cout << " FILE is a disk image file, \"daynaport\", \"bridge\", \"printer\" or \"services\".\n\n";
cout << " Image type is detected based on file extension if no explicit type is specified.\n";
cout << " hd1 : SCSI-1 HD image (Non-removable generic SCSI-1 HD image)\n";
cout << " hds : SCSI HD image (Non-removable generic SCSI HD image)\n";
cout << " hdr : SCSI HD image (Removable generic HD image)\n";
cout << " hda : SCSI HD image (Apple compatible image)\n";
cout << " hdn : SCSI HD image (NEC compatible image)\n";
cout << " hdi : SCSI HD image (Anex86 HD image)\n";
cout << " nhd : SCSI HD image (T98Next HD image)\n";
cout << " mos : SCSI MO image (MO image)\n";
cout << " iso : SCSI CD image (ISO 9660 image)\n" << flush;
exit(EXIT_SUCCESS);
}
}
bool InitBus()
{
#ifdef USE_SEL_EVENT_ENABLE
SBC_Version::Init();
#endif
// GPIOBUS creation
bus = GPIOBUS_Factory::Create();
// controller_manager = make_shared<ControllerManager>(bus);
// rascsi_response = make_shared<RascsiResponse>(device_factory, *controller_manager, ScsiController::LUN_MAX);
// executor = make_shared<RascsiExecutor>(*rascsi_response, rascsi_image, device_factory, *controller_manager);
// GPIO Initialization
if (!bus->Init(BUS::mode_e::TARGET, board_type::rascsi_board_type_e::BOARD_TYPE_FULLSPEC)) {
return false;
}
bus->Reset();
return true;
}
void Cleanup()
{
// executor->DetachAll();
// service.Cleanup();
bus->Cleanup();
}
void Reset()
{
// controller_manager->ResetAllControllers();
bus->Reset();
}
// bool InitBus()
// {
// LOGTRACE("%s", __PRETTY_FUNCTION__);
// SBC_Version::Init();
// return true;
// }
void test_timer();
void test_gpio();
void run_loopback_test();
void set_dtd_out();
void set_dtd_in();
void set_ind_out();
void set_ind_in();
void set_tad_out();
void set_tad_in();
//---------------------------------------------------------------------------
//
// Pin the thread to a specific CPU
//
//---------------------------------------------------------------------------
void FixCpu(int cpu)
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
// Get the number of CPUs
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
sched_getaffinity(0, sizeof(cpu_set_t), &cpuset);
int 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);
}
}
bool SetLogLevel(const string &log_level)
{
cout << "log level " << endl;
if (log_level == "trace") {
set_level(level::trace);
} else if (log_level == "debug") {
set_level(level::debug);
} else if (log_level == "info") {
set_level(level::info);
} else if (log_level == "warn") {
set_level(level::warn);
} else if (log_level == "err") {
set_level(level::err);
} else if (log_level == "critical") {
set_level(level::critical);
} else if (log_level == "off") {
set_level(level::off);
} else {
return false;
}
current_log_level = log_level;
LOGINFO("Set log level to '%s'", current_log_level.c_str())
return true;
}
void TerminationHandler(int signum)
{
// Cleanup();
exit(signum);
}
#include "wiringPi.h"
void blink()
{
printf("Simple Blink\n");
// wiringPiSetup();
// for(int i=0; i<20; i++){
// pinMode(i,OUTPUT);
// }
// for(int i=0; i<20; i++){
// for(int pin=0; pin<20; pin++){
// printf("Setting pin %d high\n", pin);
// digitalWrite(pin, HIGH);
// delay(100);
// }
// for(int pin=0; pin<20; pin++){
// printf("Setting pin %d low\n", pin);
// digitalWrite(pin, LOW);
// delay(100);
// }
// }
}
bool ParseArgument(int argc, char *argv[])
{
// PbCommand command;
// int id = -1;
// int unit = -1;
// PbDeviceType type = UNDEFINED;
// int block_size = 0;
string name;
string log_level;
const char *locale = setlocale(LC_MESSAGES, "");
if (locale == nullptr || !strcmp(locale, "C")) {
locale = "en";
}
opterr = 1;
int opt;
while ((opt = getopt(argc, argv, "-Iib:d:n:p:r:t:z:D:F:L:P:R:")) != -1) {
switch (opt) {
// // The two options below are kind of a compound option with two letters
// case 'i':
// case 'I':
// id = -1;
// unit = -1;
// continue;
// case 'd':
// case 'D': {
// if (!ProcessId(optarg, id, unit)) {
// return false;
// }
// continue;
// }
// case 'b': {
// if (!GetAsInt(optarg, block_size)) {
// cerr << "Invalid block size " << optarg << endl;
// return false;
// }
// continue;
// }
case 'z':
locale = optarg;
continue;
// case 'F': {
// if (const string result = rascsi_image.SetDefaultFolder(optarg); !result.empty()) {
// cerr << result << endl;
// return false;
// }
// continue;
// }
case 'L':
log_level = optarg;
continue;
// case 'R':
// int depth;
// if (!GetAsInt(optarg, depth) || depth < 0) {
// cerr << "Invalid image file scan depth " << optarg << endl;
// return false;
// }
// rascsi_image.SetDepth(depth);
// continue;
case 'n':
name = optarg;
continue;
// case 'p':
// if (!GetAsInt(optarg, port) || port <= 0 || port > 65535) {
// cerr << "Invalid port " << optarg << ", port must be between 1 and 65535" << endl;
// return false;
// }
// continue;
// case 'P':
// if (!ReadAccessToken(optarg)) {
// return false;
// }
// continue;
// case 'r': {
// string error = executor->SetReservedIds(optarg);
// if (!error.empty()) {
// cerr << error << endl;
// return false;
// }
// }
// continue;
// case 't': {
// string t = optarg;
// transform(t.begin(), t.end(), t.begin(), ::toupper);
// if (!PbDeviceType_Parse(t, &type)) {
// cerr << "Illegal device type '" << optarg << "'" << endl;
// return false;
// }
// }
// continue;
case 1:
// Encountered filename
break;
default:
return false;
}
if (optopt) {
return false;
}
// // Set up the device data
// PbDeviceDefinition *device = command.add_devices();
// device->set_id(id);
// device->set_unit(unit);
// device->set_type(type);
// device->set_block_size(block_size);
// ParseParameters(*device, optarg);
// if (size_t separator_pos = name.find(COMPONENT_SEPARATOR); separator_pos != string::npos) {
// device->set_vendor(name.substr(0, separator_pos));
// name = name.substr(separator_pos + 1);
// separator_pos = name.find(COMPONENT_SEPARATOR);
// if (separator_pos != string::npos) {
// device->set_product(name.substr(0, separator_pos));
// device->set_revision(name.substr(separator_pos + 1));
// }
// else {
// device->set_product(name);
// }
// }
// else {
// device->set_vendor(name);
// }
// id = -1;
// type = UNDEFINED;
// block_size = 0;
// name = "";
}
if (!log_level.empty()) {
SetLogLevel(log_level);
}
// // Attach all specified devices
// command.set_operation(ATTACH);
// if (CommandContext context(locale); !executor->ProcessCmd(context, command)) {
// return false;
// }
// // Display and log the device list
// PbServerInfo server_info;
// rascsi_response->GetDevices(server_info, rascsi_image.GetDefaultFolder());
// const list<PbDevice>& devices = { server_info.devices_info().devices().begin(),
// server_info.devices_info().devices().end() }; const string device_list = ListDevices(devices);
// LogDevices(device_list);
// cout << device_list << flush;
return true;
}
void tony_test();
void print_all();
int main(int argc, char *argv[])
{
// added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.
setvbuf(stdout, nullptr, _IONBF, 0);
// Output the Banner
Banner(argc, argv);
// ParseArgument() requires the bus to have been initialized first, which requires the root user.
// The -v option should be available for any user, which requires special handling.
for (int i = 1; i < argc; i++) {
if (!strcasecmp(argv[i], "-v")) {
cout << rascsi_get_version_string() << endl;
return 0;
}
}
// executor->SetLogLevel(current_log_level);
// Create a thread-safe stdout logger to process the log messages
const auto logger = stdout_color_mt("rascsi stdout logger");
set_level(level::trace);
if (!InitBus()) {
return EPERM;
}
if (!ParseArgument(argc, argv)) {
Cleanup();
return -1;
}
// Signal handler to detach all devices on a KILL or TERM signal
struct sigaction termination_handler;
termination_handler.sa_handler = TerminationHandler;
sigemptyset(&termination_handler.sa_mask);
termination_handler.sa_flags = 0;
sigaction(SIGINT, &termination_handler, nullptr);
sigaction(SIGTERM, &termination_handler, nullptr);
// Reset
Reset();
// Set the affinity to a specific processor core
FixCpu(3);
#ifdef USE_SEL_EVENT_ENABLE
sched_param schparam;
// Scheduling policy setting (highest priority)
schparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &schparam);
#else
cout << "Note: No RaSCSI hardware support, only client interface calls are supported" << endl;
#endif
LOGWARN("THIS WILL DO SOMETHING SOMEDAY");
LOGDEBUG("DTD OUT %d = %d", (int)bus->board->pin_dtd, (int)bus->board->DtdOut());
LOGDEBUG("DTD IN %d = %d", (int)bus->board->pin_dtd, (int)bus->board->DtdIn());
LOGDEBUG("IND OUT %d = %d", (int)bus->board->pin_ind, (int)bus->board->IndOut());
LOGDEBUG("IND IN %d = %d", (int)bus->board->pin_ind, (int)bus->board->IndIn());
LOGDEBUG("TAD OUT %d = %d", (int)bus->board->pin_tad, (int)bus->board->TadOut());
LOGDEBUG("TAD IN %d = %d", (int)bus->board->pin_tad, (int)bus->board->TadIn());
bus->PullConfig(bus->board->pin_dtd, board_type::gpio_pull_up_down_e::GPIO_PULLUP);
bus->PullConfig(bus->board->pin_ind, board_type::gpio_pull_up_down_e::GPIO_PULLUP);
bus->PullConfig(bus->board->pin_tad, board_type::gpio_pull_up_down_e::GPIO_PULLUP);
bus->PinConfig(bus->board->pin_dtd, board_type::gpio_direction_e::GPIO_OUTPUT);
bus->PinConfig(bus->board->pin_ind, board_type::gpio_direction_e::GPIO_OUTPUT);
bus->PinConfig(bus->board->pin_tad, board_type::gpio_direction_e::GPIO_OUTPUT);
bus->PinConfig(bus->board->pin_ack, board_type::gpio_direction_e::GPIO_OUTPUT);
int delay_time = 10000;
(void)delay_time;
set_tad_out();
set_dtd_out();
set_ind_out();
// for (int i = 0; i < 10; i++) {
// bus->SetACK(true);
// usleep(delay_time);
// bus->SetACK(false);
// usleep(delay_time);
// }
run_loopback_test();
return 0;
tony_test();
LOGDEBUG("bus->Acquire(): %08X", bus->Acquire());
SysTimer::SleepUsec(1000);
LOGDEBUG("IO True");
bus->SetIO(true);
SysTimer::SleepUsec(1000);
LOGDEBUG("bus->Acquire(): %08X", bus->Acquire());
LOGDEBUG("IO False");
bus->SetIO(false);
SysTimer::SleepUsec(1000);
LOGDEBUG("bus->Acquire(): %08X", bus->Acquire());
return 0;
}
// //---------------------------------------------------------------------------
// //
// // Main processing
// //
// //---------------------------------------------------------------------------
// int main(int argc, char* argv[])
// {
// // added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits.
// setvbuf(stdout, nullptr, _IONBF, 0);
// if(argc > 1){
// SetLogLevel(argv[1]);
// }else{
// SetLogLevel("trace");
// }
// // Create a thread-safe stdout logger to process the log messages
// auto logger = spdlog::stdout_color_mt("rascsi stdout logger");
// // Signal handler to detach all devices on a KILL or TERM signal
// struct sigaction termination_handler;
// termination_handler.sa_handler = TerminationHandler;
// sigemptyset(&termination_handler.sa_mask);
// termination_handler.sa_flags = 0;
// sigaction(SIGINT, &termination_handler, nullptr);
// sigaction(SIGTERM, &termination_handler, nullptr);
// if (!InitBus()) {
// return EPERM;
// }
// // blink();
// // test_timer();
// test_gpio();
// }
void test_timer()
{
uint32_t before = SysTimer::GetTimerLow();
sleep(1);
uint32_t after = SysTimer::GetTimerLow();
LOGINFO("first sample: %d %08X", (before - after), (after - before));
uint64_t sum = 0;
int count = 0;
for (int i = 0; i < 100; i++) {
before = SysTimer::GetTimerLow();
usleep(1000);
after = SysTimer::GetTimerLow();
sum += (after - before);
count++;
}
LOGINFO("usleep() Average %d", (uint32_t)(sum / count));
sum = 0;
count = 0;
for (int i = 0; i < 100; i++) {
before = SysTimer::GetTimerLow();
SysTimer::SleepUsec(1000);
after = SysTimer::GetTimerLow();
sum += (after - before);
count++;
}
LOGINFO("usleep() Average %d", (uint32_t)(sum / count));
before = SysTimer::GetTimerLow();
SysTimer::SleepNsec(1000000);
after = SysTimer::GetTimerLow();
LOGINFO("SysTimer::SleepNSec: %d (expected ~1000)", (uint32_t)(after - before));
}
void tony_test()
{
LOGWARN("Set everything to HIGH OUTPUT with PULLUP");
for (auto phys_pin : bus->SignalTable) {
LOGTRACE("%s GPIO_PULLUP", __PRETTY_FUNCTION__);
bus->PullConfig(phys_pin, board_type::gpio_pull_up_down_e::GPIO_PULLUP);
bus->PinConfig(phys_pin, board_type::gpio_direction_e::GPIO_OUTPUT);
bus->PinSetSignal(phys_pin, board_type::gpio_high_low_e::GPIO_STATE_HIGH);
SysTimer::SleepUsec(10000);
}
// SysTimer::SleepUsec(1000);
usleep(1000000);
LOGWARN("Set everything to LOW OUTPUT with PULLUP");
for (auto phys_pin : bus->SignalTable) {
LOGTRACE("%s GPIO_PULLUP", __PRETTY_FUNCTION__);
bus->PullConfig(phys_pin, board_type::gpio_pull_up_down_e::GPIO_PULLUP);
bus->PinConfig(phys_pin, board_type::gpio_direction_e::GPIO_OUTPUT);
bus->PinSetSignal(phys_pin, board_type::gpio_high_low_e::GPIO_STATE_LOW);
SysTimer::SleepUsec(10000);
}
usleep(1000000);
LOGWARN("Set everything to INPUT");
for (auto phys_pin : bus->SignalTable) {
LOGTRACE("%s GPIO_PULLUP", __PRETTY_FUNCTION__);
bus->PullConfig(phys_pin, board_type::gpio_pull_up_down_e::GPIO_PULLUP);
bus->PinConfig(phys_pin, board_type::gpio_direction_e::GPIO_INPUT);
bus->PinSetSignal(phys_pin, board_type::gpio_high_low_e::GPIO_STATE_LOW);
SysTimer::SleepUsec(10000);
}
usleep(1000000);
}
struct loopback_connections_struct {
board_type::pi_physical_pin_e this_pin;
board_type::pi_physical_pin_e connected_pin;
board_type::pi_physical_pin_e dir_ctrl_pin;
};
typedef loopback_connections_struct loopback_connection;
std::map<board_type::pi_physical_pin_e, string> pin_name_lookup;
std::vector<loopback_connection> loopback_conn_table;
// This needs to run AFTER GPIOBUS has been initialized. Otherwise, we don't know what type of board
// we're using
void init_loopback()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
shared_ptr<board_type::Rascsi_Board_Type> board_table = bus->board;
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt0, .connected_pin = board_table->pin_ack, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt1, .connected_pin = board_table->pin_sel, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt2, .connected_pin = board_table->pin_atn, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt3, .connected_pin = board_table->pin_rst, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt4, .connected_pin = board_table->pin_cd, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt5, .connected_pin = board_table->pin_io, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt6, .connected_pin = board_table->pin_msg, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dt7, .connected_pin = board_table->pin_req, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_dp, .connected_pin = board_table->pin_bsy, .dir_ctrl_pin = board_table->pin_dtd});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_atn, .connected_pin = board_table->pin_dt2, .dir_ctrl_pin = board_table->pin_ind});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_rst, .connected_pin = board_table->pin_dt3, .dir_ctrl_pin = board_table->pin_ind});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_ack, .connected_pin = board_table->pin_dt0, .dir_ctrl_pin = board_table->pin_ind});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_req, .connected_pin = board_table->pin_dt7, .dir_ctrl_pin = board_table->pin_tad});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_msg, .connected_pin = board_table->pin_dt6, .dir_ctrl_pin = board_table->pin_tad});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_cd, .connected_pin = board_table->pin_dt4, .dir_ctrl_pin = board_table->pin_tad});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_io, .connected_pin = board_table->pin_dt5, .dir_ctrl_pin = board_table->pin_tad});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_bsy, .connected_pin = board_table->pin_dp, .dir_ctrl_pin = board_table->pin_tad});
loopback_conn_table.push_back(loopback_connection{
.this_pin = board_table->pin_sel, .connected_pin = board_table->pin_dt1, .dir_ctrl_pin = board_table->pin_ind});
pin_name_lookup[board_table->pin_dt0] = " d0";
pin_name_lookup[board_table->pin_dt1] = " d1";
pin_name_lookup[board_table->pin_dt2] = " d2";
pin_name_lookup[board_table->pin_dt3] = " d3";
pin_name_lookup[board_table->pin_dt4] = " d4";
pin_name_lookup[board_table->pin_dt5] = " d5";
pin_name_lookup[board_table->pin_dt6] = " d6";
pin_name_lookup[board_table->pin_dt7] = " d7";
pin_name_lookup[board_table->pin_dp] = " dp";
pin_name_lookup[board_table->pin_atn] = "atn";
pin_name_lookup[board_table->pin_rst] = "rst";
pin_name_lookup[board_table->pin_ack] = "ack";
pin_name_lookup[board_table->pin_req] = "req";
pin_name_lookup[board_table->pin_msg] = "msg";
pin_name_lookup[board_table->pin_cd] = " cd";
pin_name_lookup[board_table->pin_io] = " io";
pin_name_lookup[board_table->pin_bsy] = "bsy";
pin_name_lookup[board_table->pin_sel] = "sel";
pin_name_lookup[board_table->pin_ind] = "ind";
pin_name_lookup[board_table->pin_tad] = "tad";
pin_name_lookup[board_table->pin_dtd] = "dtd";
pin_name_lookup[board_type::pi_physical_pin_e::PI_PHYS_PIN_NONE] = "NONE";
}
// Debug function that just dumps the status of all of the scsi signals to the console
void print_all()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
for (auto cur_gpio : loopback_conn_table) {
LOGDEBUG("%s %2d = %s %2d", pin_name_lookup.at(cur_gpio.this_pin).c_str(), (int)cur_gpio.this_pin,
pin_name_lookup.at(cur_gpio.connected_pin).c_str(), (int)cur_gpio.connected_pin)
}
}
// Set transceivers IC1 and IC2 to OUTPUT
void set_dtd_out()
{
LOGDEBUG("DTD OUT %d = %d", (int)bus->board->pin_dtd, (int)bus->board->DtdOut());
bus->PinSetSignal(bus->board->pin_dtd, bus->board->DtdOut());
// gpio.output(rascsi_dtd_gpio,gpio.LOW)
}
// Set transceivers IC1 and IC2 to INPUT
void set_dtd_in()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
LOGDEBUG("DTD IN %d = %d", (int)bus->board->pin_dtd, (int)bus->board->DtdIn());
bus->PinSetSignal(bus->board->pin_dtd, bus->board->DtdIn());
// gpio.output(rascsi_dtd_gpio,gpio.HIGH)
}
// Set transceiver IC4 to OUTPUT
void set_ind_out()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
LOGDEBUG("IND OUT %d = %d", (int)bus->board->pin_ind, (int)bus->board->IndOut());
bus->PinSetSignal(bus->board->pin_ind, bus->board->IndOut());
// gpio.output(rascsi_ind_gpio,gpio.HIGH)
}
// Set transceiver IC4 to INPUT
void set_ind_in()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
LOGDEBUG("IND IN %d = %d", (int)bus->board->pin_ind, (int)bus->board->IndIn());
bus->PinSetSignal(bus->board->pin_ind, bus->board->IndIn());
// gpio.output(rascsi_ind_gpio,gpio.LOW)
}
// Set transceiver IC3 to OUTPUT
void set_tad_out()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
LOGDEBUG("TAD OUT %d = %d", (int)bus->board->pin_tad, (int)bus->board->TadOut());
bus->PinSetSignal(bus->board->pin_tad, bus->board->TadOut());
// gpio.output(rascsi_tad_gpio,gpio.HIGH)
}
// Set transceiver IC3 to INPUT
void set_tad_in()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
LOGDEBUG("TAD IN %d = %d", (int)bus->board->pin_tad, (int)bus->board->TadIn());
bus->PinSetSignal(bus->board->pin_tad, bus->board->TadIn());
// gpio.output(rascsi_tad_gpio,gpio.LOW)
}
// Set the specified transciever to an OUTPUT. All of the other transceivers
// will be set to inputs. If a non-existent direction gpio is specified, this
// will set all of the transceivers to inputs.
void set_output_channel(board_type::pi_physical_pin_e out_gpio)
{
LOGTRACE("%s tad: %d dtd: %d ind: %d", bus->board->connect_desc.c_str(), (int)bus->board->pin_tad,
(int)bus->board->pin_dtd, (int)bus->board->pin_ind);
if (out_gpio == bus->board->pin_tad)
set_tad_out();
else
set_tad_in();
if (out_gpio == bus->board->pin_dtd)
set_dtd_out();
else
set_dtd_in();
if (out_gpio == bus->board->pin_ind)
set_ind_out();
else
set_ind_in();
}
// Initialize the GPIO library, set all of the gpios associated with SCSI signals to outputs and set
// all of the direction control gpios to outputs
void loopback_setup()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
// gpio.setmode(gpio.BOARD)
// gpio.setwarnings(False)
for (loopback_connection cur_gpio : loopback_conn_table) {
if (cur_gpio.this_pin == board_type::pi_physical_pin_e::PI_PHYS_PIN_NONE) {
continue;
}
bus->PinConfig(cur_gpio.this_pin, board_type::gpio_direction_e::GPIO_OUTPUT);
bus->PullConfig(cur_gpio.this_pin, board_type::gpio_pull_up_down_e::GPIO_PULLNONE);
// gpio.setup(cur_gpio['gpio_num'], gpio.OUT, initial=gpio.HIGH)
}
// Setup direction control
// gpio.setup(rascsi_ind_gpio, gpio.OUT) gpio.setup(rascsi_tad_gpio, gpio.OUT) gpio.setup(rascsi_dtd_gpio, gpio.OUT)
if (bus->board->pin_ind != board_type::pi_physical_pin_e::PI_PHYS_PIN_NONE) {
bus->PinConfig(bus->board->pin_ind, board_type::gpio_direction_e::GPIO_OUTPUT);
}
if (bus->board->pin_tad != board_type::pi_physical_pin_e::PI_PHYS_PIN_NONE) {
bus->PinConfig(bus->board->pin_tad, board_type::gpio_direction_e::GPIO_OUTPUT);
}
if (bus->board->pin_dtd != board_type::pi_physical_pin_e::PI_PHYS_PIN_NONE) {
bus->PinConfig(bus->board->pin_dtd, board_type::gpio_direction_e::GPIO_OUTPUT);
}
}
// Main test procedure.This will execute for each of the SCSI pins to make sure its connected
// properly.
int test_gpio_pin(loopback_connection &gpio_rec)
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
(void)gpio_rec;
int err_count = 0;
int sleep_time = 1000000;
LOGDEBUG("dir ctrl pin: %d", (int)gpio_rec.dir_ctrl_pin);
set_output_channel(gpio_rec.dir_ctrl_pin);
usleep(sleep_time);
// Set all GPIOs high (initialize to a known state)
for (auto cur_gpio : loopback_conn_table) {
bus->PinSetSignal(cur_gpio.this_pin, board_type::gpio_high_low_e::GPIO_STATE_HIGH);
}
usleep(sleep_time);
bus->Acquire();
// ############################################
// # set the test gpio low
// gpio.output(gpio_rec['gpio_num'], gpio.LOW)
LOGTRACE("PinSetSignal %d", (int)gpio_rec.this_pin);
bus->PinSetSignal(gpio_rec.this_pin, board_type::gpio_high_low_e::GPIO_STATE_LOW);
// time.sleep(pin_settle_delay)
LOGINFO("Sleep");
usleep(sleep_time);
LOGINFO("Done");
LOGTRACE("Acquire");
bus->Acquire();
// # loop through all of the gpios
for (auto cur_gpio : loopback_conn_table) {
// all of the gpios should be high except for the test gpio and the connected gpio
LOGTRACE("calling bus->GetSignal(%d)", (int)cur_gpio.this_pin);
auto cur_val = bus->GetSignal(cur_gpio.this_pin);
LOGDEBUG("%d [%s] is %d", (int)cur_gpio.this_pin, pin_name_lookup.at(cur_gpio.this_pin).c_str(), (int)cur_val);
if (cur_gpio.this_pin == gpio_rec.this_pin) {
if (cur_val != false) {
LOGERROR("Test commanded GPIO %d [%s] to be low, but it did not respond", (int)cur_gpio.this_pin,
pin_name_lookup.at(cur_gpio.this_pin).c_str())
err_count++;
}
} else if (cur_gpio.this_pin == gpio_rec.connected_pin) {
if (cur_val != false) {
LOGERROR("GPIO %d [%s] should be driven low, but %d [%s] did not affect it", (int)cur_gpio.this_pin,
pin_name_lookup.at(cur_gpio.this_pin).c_str(), (int)cur_gpio.connected_pin,
pin_name_lookup.at(cur_gpio.connected_pin).c_str());
err_count++;
}
} else {
if (cur_val != true) {
LOGERROR("GPIO %d [%s] was incorrectly pulled low, when it shouldn't be", (int)cur_gpio.this_pin,
pin_name_lookup.at(cur_gpio.this_pin).c_str())
err_count++;
}
}
}
exit(1);
// if(cur_val != gpio.HIGH):
// print("Error: GPIO " + scsi_signals[gpio_rec['gpio_num']] + " incorrectly pulled " +
// scsi_signals[cur_gpio] + " LOW, when it shouldn't have") err_count = err_count+1
// ############################################
// # set the transceivers to input
// set_output_channel(rascsi_none)
// time.sleep(pin_settle_delay)
// # loop through all of the gpios
// for cur_gpio in scsi_signals:
// # all of the gpios should be high except for the test gpio
// cur_val = gpio.input(cur_gpio)
// if( cur_gpio == gpio_rec['gpio_num']):
// if(cur_val != gpio.LOW):
// print("Error: Test commanded GPIO " + scsi_signals[gpio_rec['gpio_num']] + " to be
// low, but it did not respond") err_count = err_count+1
// else:
// if(cur_val != gpio.HIGH):
// print("Error: GPIO " + scsi_signals[gpio_rec['gpio_num']] + " incorrectly pulled " +
// scsi_signals[cur_gpio] + " LOW, when it shouldn't have") err_count = err_count+1
// # Set the transceiver back to output
// set_output_channel(gpio_rec['dir_ctrl'])
// #############################################
// # set the test gpio high
// gpio.output(gpio_rec['gpio_num'], gpio.HIGH)
// time.sleep(pin_settle_delay)
// # loop through all of the gpios
// for cur_gpio in scsi_signals:
// # all of the gpios should be high
// cur_val = gpio.input(cur_gpio)
// if( cur_gpio == gpio_rec['gpio_num']):
// if(cur_val != gpio.HIGH):
// print("Error: Test commanded GPIO " + scsi_signals[gpio_rec['gpio_num']] + " to be
// high, but it did not respond") err_count = err_count+1
// else:
// if(cur_val != gpio.HIGH):
// print("Error: GPIO " + scsi_signals[gpio_rec['gpio_num']] + " incorrectly pulled " +
// scsi_signals[cur_gpio] + " LOW, when it shouldn't have") err_count = err_count+1
return err_count;
}
void run_loopback_test()
{
LOGTRACE("%s", __PRETTY_FUNCTION__);
init_loopback();
loopback_setup();
LOGWARN("DONE WITH LOOPBACK_SETUP()");
print_all();
LOGWARN("---------------------------------------------------");
set_output_channel(bus->board->pin_dtd);
for(int j = 0; j<5; j++){
for(uint8_t i = 0; i< 0xFF; i++){
bus->SetDAT(i);
usleep(100000);
}
}
loopback_connection ack;
ack.this_pin = bus->board->pin_ack;
ack.connected_pin = bus->board->pin_dt0;
ack.dir_ctrl_pin = bus->board->pin_ind;
test_gpio_pin(ack);
for (auto cur_gpio : loopback_conn_table) {
LOGINFO("Testing GPIO %d [%s]..................................", (int)cur_gpio.this_pin,
pin_name_lookup.at(cur_gpio.this_pin).c_str());
test_gpio_pin(cur_gpio);
}
}