From efa01e1e10c3f377dd387d0b02c4d9c57dd8ffae Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 13:34:29 -0500 Subject: [PATCH 01/12] Basic data capture works --- src/raspberrypi/disk.cpp | 103 ++++---- src/raspberrypi/gpiobus.cpp | 173 +++++++------ src/raspberrypi/gpiobus.h | 2 + src/raspberrypi/log.h | 4 + src/raspberrypi/rascsi.cpp | 475 +++++++++++++++++++++++++++++------- 5 files changed, 551 insertions(+), 206 deletions(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index d1b9467..c616e18 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -43,7 +43,14 @@ // Disk // //=========================================================================== -//#define DISK_LOG +#ifndef DISK_LOG +#define DISK_LOG +#endif // DISK_LOG +#ifndef RASCSI +#define RASCSI +#endif // RASCSI + + #ifdef RASCSI #define BENDER_SIGNATURE "RaSCSI" @@ -6324,9 +6331,7 @@ BUS::phase_t FASTCALL SASIDEV::Process() // For the monitor tool, we shouldn't need to reset. We're just logging information // Reset if (ctrl.bus->GetRST()) { -#if defined(DISK_LOG) spdlog::info( "RESET signal received"); -#endif // DISK_LOG // Reset the controller Reset(); @@ -6394,19 +6399,17 @@ void FASTCALL SASIDEV::BusFree() // Phase change if (ctrl.phase != BUS::busfree) { -#if defined(DISK_LOG) spdlog::info( "Bus free phase"); -#endif // DISK_LOG // Phase Setting ctrl.phase = BUS::busfree; - // Set Signal lines - ctrl.bus->SetREQ(FALSE); - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(FALSE); - ctrl.bus->SetIO(FALSE); - ctrl.bus->SetBSY(FALSE); +////////////// // Set Signal lines +////////////// ctrl.bus->SetREQ(FALSE); +////////////// ctrl.bus->SetMSG(FALSE); +////////////// ctrl.bus->SetCD(FALSE); +////////////// ctrl.bus->SetIO(FALSE); +////////////// ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -6444,16 +6447,16 @@ void FASTCALL SASIDEV::Selection() return; } -#if defined(DISK_LOG) - spdlog::info( - "Selection Phase ID=%d (with device)", ctrl.id); -#endif // DISK_LOG + // Wait for this monitor target to assert the selection + // before moving on to the selection phase. + if(ctrl.bus->GetBSY()) + { + // Phase change + ctrl.phase = BUS::selection; + spdlog::trace( + "[ID %d] Selection Phase (with device)", ctrl.id); + } - // Phase change - ctrl.phase = BUS::selection; - - // Raiase BSY and respond - ctrl.bus->SetBSY(TRUE); return; } @@ -6481,16 +6484,24 @@ void FASTCALL SASIDEV::Command() if (ctrl.phase != BUS::command) { #if defined(DISK_LOG) - spdlog::info( "Command Phase"); + spdlog::trace( "[ID %d] Moving to command Phase", ctrl.id); #endif // DISK_LOG // Phase Setting ctrl.phase = BUS::command; - // Signal line operated by the target - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(TRUE); - ctrl.bus->SetIO(FALSE); +////////// // Signal line operated by the target +////////// ctrl.bus->SetMSG(FALSE); +////////// ctrl.bus->SetCD(TRUE); +////////// ctrl.bus->SetIO(FALSE); + + // Wait until target sets the following condition: + // MSG = FALSE + // CD = TRUE + // IO = FALSE + if (ctrl.bus->GetMSG() || !ctrl.bus->GetCD() || ctrl.bus->GetIO()) { + return; + } // Data transfer is 6 bytes x 1 block ctrl.offset = 0; @@ -7903,7 +7914,7 @@ void FASTCALL SASIDEV::FlushUnit() } } -#ifdef DISK_LOG +#if 0 //--------------------------------------------------------------------------- // // Get the current phase as a string @@ -8016,9 +8027,7 @@ BUS::phase_t FASTCALL SCSIDEV::Process() // Reset if (ctrl.bus->GetRST()) { -#if defined(DISK_LOG) - spdlog::info( "RESET信号受信"); -#endif // DISK_LOG + spdlog::info( "RESET phase"); // Reset the controller Reset(); @@ -8028,6 +8037,7 @@ BUS::phase_t FASTCALL SCSIDEV::Process() return ctrl.phase; } +// spdlog::trace("ID {} in phase {}",ctrl.id,ctrl.phase); // Phase processing switch (ctrl.phase) { // Bus free phase @@ -8104,12 +8114,13 @@ void FASTCALL SCSIDEV::BusFree() // Phase setting ctrl.phase = BUS::busfree; - // Signal line - ctrl.bus->SetREQ(FALSE); - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(FALSE); - ctrl.bus->SetIO(FALSE); - ctrl.bus->SetBSY(FALSE); +////////// // Signal line +// We shouldn't be setting ANYTHING +////////// ctrl.bus->SetREQ(FALSE); +////////// ctrl.bus->SetMSG(FALSE); +////////// ctrl.bus->SetCD(FALSE); +////////// ctrl.bus->SetIO(FALSE); +////////// ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -8142,24 +8153,30 @@ void FASTCALL SCSIDEV::Selection() // invalid if IDs do not match id = 1 << ctrl.id; if ((ctrl.bus->GetDAT() & id) == 0) { + spdlog::trace("[ID {}] ID doesn't match {}",ctrl.id,id); return; } // End if there is no valid unit if (!HasUnit()) { + spdlog::trace("[ID {}] No unit attached",ctrl.id); return; } -#if defined(DISK_LOG) - spdlog::info( - "Selection Phase ID=%d (with device)", ctrl.id); -#endif // DISK_LOG + ctrl.phase = BUS::selection; - // Phase setting - ctrl.phase = BUS::selection; + // Wait for this monitor target to assert the selection + // before moving on to the selection phase. + if(ctrl.bus->GetBSY()) + { + // Phase change + spdlog::trace( + "[ID {} Selection Phase (with device)", ctrl.id); + } + else{ + spdlog::trace("[ID {}] Selection phase", ctrl.id); + } - // Raise BSY and respond - ctrl.bus->SetBSY(TRUE); return; } diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp index 31d6acf..1c6c163 100644 --- a/src/raspberrypi/gpiobus.cpp +++ b/src/raspberrypi/gpiobus.cpp @@ -65,7 +65,7 @@ DWORD bcm_host_get_peripheral_address(void) char buf[1024]; size_t len = sizeof(buf); DWORD address; - + if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf) { // Failed to get CPU model || Not BCM2835 @@ -88,7 +88,7 @@ extern uint32_t RPi_IO_Base_Addr; // Core frequency extern uint32_t RPi_Core_Freq; -#ifdef USE_SEL_EVENT_ENABLE +#ifdef USE_SEL_EVENT_ENABLE //--------------------------------------------------------------------------- // // Interrupt control function @@ -460,6 +460,7 @@ void FASTCALL GPIOBUS::Reset() SetMode(PIN_SEL, IN); SetMode(PIN_ATN, IN); SetMode(PIN_ACK, IN); + printf("ACK is set to IN\n"); SetMode(PIN_RST, IN); // Set data bus signals to input @@ -488,6 +489,7 @@ void FASTCALL GPIOBUS::Reset() SetControl(PIN_IND, IND_OUT); SetMode(PIN_SEL, OUT); SetMode(PIN_ATN, OUT); + printf("ACK is set to OUT\n"); SetMode(PIN_ACK, OUT); SetMode(PIN_RST, OUT); @@ -508,6 +510,8 @@ void FASTCALL GPIOBUS::Reset() signals = 0; } +static DWORD high_bits = 0x0; +static DWORD low_bits = 0xFFFFFFFF; //--------------------------------------------------------------------------- // // Bus signal acquisition @@ -517,11 +521,22 @@ DWORD FASTCALL GPIOBUS::Aquire() { signals = *level; + DWORD prev_high = high_bits; + DWORD prev_low = low_bits; + + high_bits |= signals; + low_bits &= signals; + + if ((high_bits != prev_high) || (low_bits != prev_low)) + { + printf(" %08lX %08lX\n",high_bits, low_bits); + } + #if SIGNAL_CONTROL_MODE < 2 // Invert if negative logic (internal processing is unified to positive logic) signals = ~signals; #endif // SIGNAL_CONTROL_MODE - + return signals; } @@ -552,36 +567,36 @@ BOOL FASTCALL GPIOBUS::GetBSY() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetBSY(BOOL ast) { - // Set BSY signal - SetSignal(PIN_BSY, ast); - - if (actmode == TARGET) { - if (ast) { - // Turn on ACTIVE signal - SetControl(PIN_ACT, ACT_ON); - - // Set Target signal to output - SetControl(PIN_TAD, TAD_OUT); - - SetMode(PIN_BSY, OUT); - SetMode(PIN_MSG, OUT); - SetMode(PIN_CD, OUT); - SetMode(PIN_REQ, OUT); - SetMode(PIN_IO, OUT); - } else { - // Turn off the ACTIVE signal - SetControl(PIN_ACT, ACT_OFF); - - // Set the target signal to input - SetControl(PIN_TAD, TAD_IN); - - SetMode(PIN_BSY, IN); - SetMode(PIN_MSG, IN); - SetMode(PIN_CD, IN); - SetMode(PIN_REQ, IN); - SetMode(PIN_IO, IN); - } - } +// // Set BSY signal +// SetSignal(PIN_BSY, ast); +// +// if (actmode == TARGET) { +// if (ast) { +// // Turn on ACTIVE signal +// SetControl(PIN_ACT, ACT_ON); +// +// // Set Target signal to output +// SetControl(PIN_TAD, TAD_OUT); +// +// SetMode(PIN_BSY, OUT); +// SetMode(PIN_MSG, OUT); +// SetMode(PIN_CD, OUT); +// SetMode(PIN_REQ, OUT); +// SetMode(PIN_IO, OUT); +// } else { +// // Turn off the ACTIVE signal +// SetControl(PIN_ACT, ACT_OFF); +// +// // Set the target signal to input +// SetControl(PIN_TAD, TAD_IN); +// +// SetMode(PIN_BSY, IN); +// SetMode(PIN_MSG, IN); +// SetMode(PIN_CD, IN); +// SetMode(PIN_REQ, IN); +// SetMode(PIN_IO, IN); +// } +// } } //--------------------------------------------------------------------------- @@ -601,13 +616,13 @@ BOOL FASTCALL GPIOBUS::GetSEL() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetSEL(BOOL ast) { - if (actmode == INITIATOR && ast) { - // Turn on ACTIVE signal - SetControl(PIN_ACT, ACT_ON); - } - - // Set SEL signal - SetSignal(PIN_SEL, ast); +// if (actmode == INITIATOR && ast) { +// // Turn on ACTIVE signal +// SetControl(PIN_ACT, ACT_ON); +// } +// +// // Set SEL signal +// SetSignal(PIN_SEL, ast); } //--------------------------------------------------------------------------- @@ -627,7 +642,7 @@ BOOL FASTCALL GPIOBUS::GetATN() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetATN(BOOL ast) { - SetSignal(PIN_ATN, ast); +// SetSignal(PIN_ATN, ast); } //--------------------------------------------------------------------------- @@ -647,7 +662,7 @@ BOOL FASTCALL GPIOBUS::GetACK() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetACK(BOOL ast) { - SetSignal(PIN_ACK, ast); + //SetSignal(PIN_ACK, ast); } //--------------------------------------------------------------------------- @@ -667,7 +682,7 @@ BOOL FASTCALL GPIOBUS::GetRST() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetRST(BOOL ast) { - SetSignal(PIN_RST, ast); + //SetSignal(PIN_RST, ast); } //--------------------------------------------------------------------------- @@ -687,7 +702,7 @@ BOOL FASTCALL GPIOBUS::GetMSG() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetMSG(BOOL ast) { - SetSignal(PIN_MSG, ast); + //SetSignal(PIN_MSG, ast); } //--------------------------------------------------------------------------- @@ -707,7 +722,7 @@ BOOL FASTCALL GPIOBUS::GetCD() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetCD(BOOL ast) { - SetSignal(PIN_CD, ast); + //SetSignal(PIN_CD, ast); } //--------------------------------------------------------------------------- @@ -805,7 +820,7 @@ BOOL FASTCALL GPIOBUS::GetREQ() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetREQ(BOOL ast) { - SetSignal(PIN_REQ, ast); +// SetSignal(PIN_REQ, ast); } //--------------------------------------------------------------------------- @@ -839,36 +854,36 @@ BYTE FASTCALL GPIOBUS::GetDAT() void FASTCALL GPIOBUS::SetDAT(BYTE dat) { // Write to port -#if SIGNAL_CONTROL_MODE == 0 - DWORD fsel; - - fsel = gpfsel[0]; - fsel &= tblDatMsk[0][dat]; - fsel |= tblDatSet[0][dat]; - if (fsel != gpfsel[0]) { - gpfsel[0] = fsel; - gpio[GPIO_FSEL_0] = fsel; - } - - fsel = gpfsel[1]; - fsel &= tblDatMsk[1][dat]; - fsel |= tblDatSet[1][dat]; - if (fsel != gpfsel[1]) { - gpfsel[1] = fsel; - gpio[GPIO_FSEL_1] = fsel; - } - - fsel = gpfsel[2]; - fsel &= tblDatMsk[2][dat]; - fsel |= tblDatSet[2][dat]; - if (fsel != gpfsel[2]) { - gpfsel[2] = fsel; - gpio[GPIO_FSEL_2] = fsel; - } -#else - gpio[GPIO_CLR_0] = tblDatMsk[dat]; - gpio[GPIO_SET_0] = tblDatSet[dat]; -#endif // SIGNAL_CONTROL_MODE +//#if SIGNAL_CONTROL_MODE == 0 +// DWORD fsel; +// +// fsel = gpfsel[0]; +// fsel &= tblDatMsk[0][dat]; +// fsel |= tblDatSet[0][dat]; +// if (fsel != gpfsel[0]) { +// gpfsel[0] = fsel; +// gpio[GPIO_FSEL_0] = fsel; +// } +// +// fsel = gpfsel[1]; +// fsel &= tblDatMsk[1][dat]; +// fsel |= tblDatSet[1][dat]; +// if (fsel != gpfsel[1]) { +// gpfsel[1] = fsel; +// gpio[GPIO_FSEL_1] = fsel; +// } +// +// fsel = gpfsel[2]; +// fsel &= tblDatMsk[2][dat]; +// fsel |= tblDatSet[2][dat]; +// if (fsel != gpfsel[2]) { +// gpfsel[2] = fsel; +// gpio[GPIO_FSEL_2] = fsel; +// } +//#else +// gpio[GPIO_CLR_0] = tblDatMsk[dat]; +// gpio[GPIO_SET_0] = tblDatSet[dat]; +//#endif // SIGNAL_CONTROL_MODE } //--------------------------------------------------------------------------- @@ -1155,7 +1170,7 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count) } // Already waiting for REQ assertion - + // Assert the ACK signal SetSignal(PIN_ACK, ON); @@ -1399,7 +1414,7 @@ void FASTCALL GPIOBUS::SetMode(int pin, int mode) gpio[index] = data; gpfsel[index] = data; } - + //--------------------------------------------------------------------------- // // Get input signal value @@ -1409,7 +1424,7 @@ BOOL FASTCALL GPIOBUS::GetSignal(int pin) { return (signals >> pin) & 1; } - + //--------------------------------------------------------------------------- // // Set output signal value diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h index 340c958..2ee34ff 100644 --- a/src/raspberrypi/gpiobus.h +++ b/src/raspberrypi/gpiobus.h @@ -480,6 +480,8 @@ public: void FASTCALL SetIO(BOOL ast); // Set IO signal + void FASTCALL SetAct(BOOL ast) { PinSetSignal(PIN_ACT, ast);} + BOOL FASTCALL GetREQ(); // Get REQ signal void FASTCALL SetREQ(BOOL ast); diff --git a/src/raspberrypi/log.h b/src/raspberrypi/log.h index 617a747..179b13d 100644 --- a/src/raspberrypi/log.h +++ b/src/raspberrypi/log.h @@ -12,6 +12,10 @@ #if !defined(log_h) #define log_h + +#define LOGINFO(...) \ + do{char buf[256]; snprintf(buf, 256,__VA_ARGS__); spdlog::info(buf);}while(0) + //=========================================================================== // // ログ diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 16221d2..1aca3f6 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -16,6 +16,8 @@ #include "disk.h" #include "gpiobus.h" #include "spdlog/spdlog.h" +//#include +#include //--------------------------------------------------------------------------- // @@ -47,6 +49,23 @@ int monsocket; // Monitor Socket pthread_t monthread; // Monitor Thread static void *MonThread(void *param); #endif // BAREMETAL +typedef struct data_capture{ + DWORD data; + timeval timestamp; +} data_capture_t; + + +#define MAX_BUFF_SIZE 1000000 + +data_capture data_buffer[MAX_BUFF_SIZE]; +int data_idx = 0; + + + +#define SECONDS_1 (1000 * 1000) +#define SECONDS_3 (3 * 1000 * 1000) +#define WAIT_FOR_EQUAL(x,y,timeout) { DWORD now = SysTimer::GetTimerLow(); while ((SysTimer::GetTimerLow() - now) < timeout) { bus->Aquire();if (x == y) {break;}}} + #ifndef BAREMETAL //--------------------------------------------------------------------------- @@ -181,6 +200,149 @@ BOOL Init() return TRUE; } +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND -1 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD -1 // DATA DIRECTION + +// Control signal output logic +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI signal pin assignment +#define PIN_DT0 10 // Data 0 +#define PIN_DT1 11 // Data 1 +#define PIN_DT2 12 // Data 2 +#define PIN_DT3 13 // Data 3 +#define PIN_DT4 14 // Data 4 +#define PIN_DT5 15 // Data 5 +#define PIN_DT6 16 // Data 6 +#define PIN_DT7 17 // Data 7 +#define PIN_DP 18 // Data parity +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL + + +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; +} + + +int pin_nums[] = {PIN_BSY,PIN_SEL,PIN_CD,PIN_IO,PIN_MSG,PIN_REQ,PIN_ACK,PIN_ATN,PIN_RST,PIN_DT0}; + +char* pin_names[] = {"BSY","SEL","CD","IO","MSG","REQ","ACK","ATN","RST","DAT"}; + + +void dump_data() +{ + char outstr[1024]; + int i = 0; + timeval time_diff; + FILE *fp; + timeval start_time = data_buffer[0].timestamp; + fp = fopen("log.txt","w"); + + + fprintf(fp, "idx\traw\ttimestamp\tBSY\tSEL\tC/D\tI/O\tMSG\tREQ\tACK\tATN\tRST\tData..\n"); + + while(i < data_idx) + { + timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); + //timediff = difftime(data_buffer[i].timestamp, start_time); + fprintf(fp, "%d\t%08lX\t%d:%d\t",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_BSY)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_SEL)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_CD)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_IO)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_MSG)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_REQ)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ACK)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ATN)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_RST)); + fprintf(fp, "%02X\t", get_data_field(data_buffer[i].data)); + fprintf(fp, "\n"); + i++; + } + fclose(fp); + + + i=0; + printf("Creating timing_drawer.txt\n"); + fp = fopen("timing_drawer.txt","w"); + while(i < data_idx) + { + timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); + //timediff = difftime(data_buffer[i].timestamp, start_time); + fprintf(fp, "TIME=%d:%d;", time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "BSY=%d;", get_pin_value(data_buffer[i].data, PIN_BSY)); + fprintf(fp, "SEL=%d;", get_pin_value(data_buffer[i].data, PIN_SEL)); + fprintf(fp, "CD=%d;", get_pin_value(data_buffer[i].data, PIN_CD)); + fprintf(fp, "IO=%d;", get_pin_value(data_buffer[i].data, PIN_IO)); + fprintf(fp, "MSG=%d;", get_pin_value(data_buffer[i].data, PIN_MSG)); + fprintf(fp, "REQ=%d;", get_pin_value(data_buffer[i].data, PIN_REQ)); + fprintf(fp, "ACK=%d;", get_pin_value(data_buffer[i].data, PIN_ACK)); + fprintf(fp, "ATN=%d;", get_pin_value(data_buffer[i].data, PIN_ATN)); + fprintf(fp, "RST=%d;", get_pin_value(data_buffer[i].data, PIN_RST)); + fprintf(fp, "DATA=%02X.", get_data_field(data_buffer[i].data)); + fprintf(fp, "\n"); + i++; + } + fclose(fp); + + + +// +// fp = fopen("log2.txt","w"); +// +// for(int pin=0; pin < ARRAY_SIZE(pin_names); pin++) +// { +// i=0; +// while(i < data_idx) +// { +// char this_point = ((get_pin_value(data_buffer[i].data), pin_nums[pin]) == TRUE) ? "-", "_"; +// fprintf(fp, this_point) +// } +// +// +// +// +// } + + + + +} + + + //--------------------------------------------------------------------------- // // Cleanup @@ -190,6 +352,14 @@ void Cleanup() { int i; + printf("In cleanup....\n"); + + + + dump_data(); + + + // Delete the disks for (i = 0; i < CtrlMax * UnitNum; i++) { if (disk[i]) { @@ -971,6 +1141,8 @@ next: } #endif // BAREMETAL + + //--------------------------------------------------------------------------- // // Main processing @@ -986,20 +1158,23 @@ int startrascsi(void) int main(int argc, char* argv[]) { #endif // BAREMETAL - int i; + DWORD prev_sample = 0xFFFFFFFF; + DWORD this_sample = 0; + //int i; int ret; - int actid; - DWORD now; - BUS::phase_t phase; - BYTE data; +// int actid; + //DWORD now; + //BUS::phase_t phase; +// BYTE data; #ifndef BAREMETAL struct sched_param schparam; #endif // BAREMETAL spdlog::set_level(spdlog::level::trace); - spdlog::trace("Entering the function with %d arguments", argc); + spdlog::trace("Entering the function with {0:x}{1:X} arguments", argc,20); // Output the Banner Banner(argc, argv); + memset(data_buffer,0,sizeof(data_buffer)); // Initialize ret = 0; @@ -1040,103 +1215,235 @@ int main(int argc, char* argv[]) // Start execution running = TRUE; + bus->SetAct(FALSE); + + + spdlog::trace("Going into running mode {}", 1); // Main Loop while (running) { // Work initialization - actid = -1; - phase = BUS::busfree; + this_sample = bus->Aquire(); -#ifdef USE_SEL_EVENT_ENABLE - // SEL signal polling - if (bus->PollSelectEvent() < 0) { - // Stop on interrupt - if (errno == EINTR) { - break; - } - continue; + if(this_sample != prev_sample) + { + //printf("%d Sample %08lX\n", data_idx, this_sample); + 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; } - // Get the bus - bus->Aquire(); -#else - bus->Aquire(); - if (!bus->GetSEL()) { -#if !defined(BAREMETAL) - usleep(0); -#endif // !BAREMETAL - continue; - } -#endif // USE_SEL_EVENT_ENABLE - // Wait until BSY is released as there is a possibility for the - // initiator to assert it while setting the ID (for up to 3 seconds) - if (bus->GetBSY()) { - now = SysTimer::GetTimerLow(); - while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { - bus->Aquire(); - if (!bus->GetBSY()) { - break; - } - } - } - // Stop because it the bus is busy or another device responded - if (bus->GetBSY() || !bus->GetSEL()) { - continue; - } - // Notify all controllers - data = bus->GetDAT(); - for (i = 0; i < CtrlMax; i++) { - if (!ctrl[i] || (data & (1 << i)) == 0) { - continue; - } - // Find the target that has moved to the selection phase - if (ctrl[i]->Process() == BUS::selection) { - // Get the target ID - actid = i; - // Bus Selection phase - phase = BUS::selection; - break; - } - } - // Return to bus monitoring if the selection phase has not started - if (phase != BUS::selection) { - continue; - } - // Start target device - active = TRUE; -#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) - // Scheduling policy setting (highest priority) - schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - sched_setscheduler(0, SCHED_FIFO, &schparam); -#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL - // Loop until the bus is free - while (running) { - // Target drive - phase = ctrl[actid]->Process(); - // End when the bus is free - if (phase == BUS::busfree) { - break; - } - } -#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) - // Set the scheduling priority back to normal - schparam.sched_priority = 0; - sched_setscheduler(0, SCHED_OTHER, &schparam); -#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL - // End the target travel - active = FALSE; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + continue; +//////// +//////// // Target sending data +//////// if(!bus->GetIO() && bus->GetREQ() && bus->GetACK()) +//////// { +//////// BYTE data = bus->GetDAT(); +//////// printf("+%02X ",data); +//////// +//////// +//////// +//////// DWORD now = SysTimer::GetTimerLow(); +//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) +//////// { +//////// bus->Aquire(); +//////// if (bus->GetACK() == FALSE) { +//////// break; +//////// } +//////// } +//////// +//////// if(bus->GetACK() != FALSE) +//////// { +//////// spdlog::warn("got an invalid req/ack sequence for target sending data"); +//////// } +//////// } +//////// +//////// +//////// +//////// if(bus->GetIO() && bus->GetREQ() && !bus->GetACK()) +//////// { +//////// BYTE data = bus->GetDAT(); +//////// printf("-%02X ",data); +//////// +//////// +//////// DWORD now = SysTimer::GetTimerLow(); +//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) +//////// { +//////// bus->Aquire(); +//////// if (bus->GetREQ() == FALSE) { +//////// break; +//////// } +//////// } +//////// +//////// if(bus->GetREQ() != TRUE) +//////// { +//////// spdlog::warn("REQ didn't de-assert when I wanted it to."); +//////// } +//////// +//////// +//////// } +//////// +//////// continue; +//////// +//////// // Wait until BSY is released as there is a possibility for the +//////// // initiator to assert it while setting the ID (for up to 3 seconds) +//////// if (bus->GetSEL() ) { +//////// BYTE data = bus->GetDAT(); +//////// printf("SEL is asserted. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); +//////// now = SysTimer::GetTimerLow(); +//////// while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { +//////// bus->Aquire(); +//////// if (!bus->GetSEL()) { +//////// printf("SEL is clear. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); +//////// break; +//////// } +//////// } +//////// } +//////// else{ +//////// +//////// continue; +//////// } +////////// spdlog::trace("Busy: {}",bus->GetBSY()); +//////// +//////// +//////// // For monitor mode, we just want to make sure the initiator +//////// // released the BSY signal within 3 seconds. If it hasn't +//////// // the initiator is misbehaving +////////// if (bus->GetBSY()) { +////////// spdlog::warn("The initiator (%d) did not release the BSY signal after 3 seconds", bus->GetDAT()); +////////// continue; +////////// } +//////// +////////////////////// +////////////////////// // Stop because it the bus is busy or another device responded +////////////////////// if (bus->GetBSY() || !bus->GetSEL()) { +////////////////////// continue; +////////////////////// } +// +// // Notify all controllers +// data = bus->GetDAT(); +//// spdlog::trace("Data is {x}",data); +// for (i = 0; i < CtrlMax; i++) { +// if (!ctrl[i] || (data & (1 << i)) == 0) { +// continue; +// } +//// spdlog::trace("Found an active controller! Let's do some selection {}", i); +// // Find the target that has moved to the selection phase +// if (ctrl[i]->Process() == BUS::selection) { +// // Get the target ID +// actid = i; +// +// // Bus Selection phase +// phase = BUS::selection; +// break; +// } +// } +// +// // Return to bus monitoring if the selection phase has not started +// if (phase != BUS::selection) { +// continue; +// } +// +// // Start target device +// active = TRUE; +// spdlog::trace("Found a target device {} ID:{}",actid, ctrl[actid]->GetID()); +// +//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) +// // Scheduling policy setting (highest priority) +// schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); +// sched_setscheduler(0, SCHED_FIFO, &schparam); +//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL +// +// // Loop until the bus is free +// while (running) { +// // Target drive +// phase = ctrl[actid]->Process(); +// +// // End when the bus is free +// if (phase == BUS::busfree) { +// break; +// } +// } +// +//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) +// // Set the scheduling priority back to normal +// schparam.sched_priority = 0; +// sched_setscheduler(0, SCHED_OTHER, &schparam); +//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL +// +// // End the target travel +// active = FALSE; } err_exit: From 18870e49f20be57ed41183c027c606412f3fceb5 Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 13:35:14 -0500 Subject: [PATCH 02/12] Python script for formatting the output data --- src/raspberrypi/convert_data.py | 64 +++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/raspberrypi/convert_data.py diff --git a/src/raspberrypi/convert_data.py b/src/raspberrypi/convert_data.py new file mode 100644 index 0000000..7d3d77b --- /dev/null +++ b/src/raspberrypi/convert_data.py @@ -0,0 +1,64 @@ +#!/usr/bin/python + +import sys + +outfile = open('data.json', 'w') +infile = open('timing_drawer.txt','r') + +firstline = infile.readline() + +num_columns = len(firstline.split(";")) + +# Skip the time field +field_num = 1 + +while (field_num < num_columns): + var = firstline.split(";") + var2 = var[field_num].split("=") + field_name = var2[0] + infile.seek(0) + print(" {name: '" + field_name + "', wave: '", file=outfile, end='') + prev_val = '' + if (field_name == "DATA"): + for line in infile: + value_pair = line.split(";")[field_num] + z = value_pair.split("=")[1].strip().replace(".","") + if(z == prev_val): + out = '.' + prev_val = z + elif (z == '00'): + out = '0' + else: + out = '1' + print(out, file=outfile, end='') + prev_val = z + print("', data: [", file=outfile, end='') + infile.seek(0) + for line in infile: + value_pair = line.split(";")[field_num] + z = value_pair.split("=")[1].strip().replace(".","") + if(z == prev_val): + continue + print("'" + z + "', ", file=outfile, end='') + prev_val = z + print("]},", file=outfile) + else: + for line in infile: + value_pair = line.split(";")[field_num] + z = value_pair.split("=")[1] + if(z == prev_val): + z = '.' + else: + prev_val = z + print(z, file=outfile, end='') + + print("'},", file=outfile) + + field_num = field_num + 1 + + + + +outfile.close() + + From f3037b628592a6bc91ae4869cc0288d6ec0d59af Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 15:01:24 -0500 Subject: [PATCH 03/12] Move monitor function to scsishark file --- src/raspberrypi/Makefile | 30 +- src/raspberrypi/scsishark.cpp | 1459 +++++++++++++++++++++++++++++++++ 2 files changed, 1479 insertions(+), 10 deletions(-) create mode 100644 src/raspberrypi/scsishark.cpp diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index 71c0f07..a5e7266 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -28,7 +28,7 @@ RASCSI = rascsi RASCTL = rasctl RASDUMP = rasdump SASIDUMP = sasidump -SCSIMON = scsimon +SCSISHARK = scsishark USR_LOCAL_BIN = /usr/local/bin MAN_PAGE_DIR = /usr/share/man/man1 @@ -37,7 +37,7 @@ DOC_DIR = ../../doc #BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON) # Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed # for my specific use case. If you need them - add them back in! -BIN_ALL = $(RASCSI) $(RASCTL) +BIN_ALL = $(RASCSI) $(RASCTL) $(SCSISHARK) SRC_RASCSI = \ @@ -50,6 +50,16 @@ SRC_RASCSI = \ filepath.cpp \ fileio.cpp +SRC_SCSISHARK = \ + scsishark.cpp \ + scsi.cpp \ + disk.cpp \ + gpiobus.cpp \ + ctapdriver.cpp \ + cfilesystem.cpp \ + filepath.cpp \ + fileio.cpp + SRC_RASCTL = \ rasctl.cpp @@ -71,9 +81,9 @@ OBJ_RASCSI := $(SRC_RASCSI:%.cpp=%.o) OBJ_RASCTL := $(SRC_RASCTL:%.cpp=%.o) OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=%.o) OBJ_SASIDUMP := $(SRC_SASIDUMP:%.cpp=%.o) -OBJ_SCSIMON := $(SRC_SCSIMON:%.cpp=%.o) +OBJ_SCSISHARK := $(SRC_SCSISHARK:%.cpp=%.o) #OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON) -OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) +OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSISHARK) %.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ @@ -88,19 +98,19 @@ ALL: all docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(RASCSI): $(OBJ_RASCSI) - $(CXX) -o $@ $(OBJ_RASCSI) -lpthread + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread $(RASCTL): $(OBJ_RASCTL) - $(CXX) -o $@ $(OBJ_RASCTL) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL) $(RASDUMP): $(OBJ_RASDUMP) - $(CXX) -o $@ $(OBJ_RASDUMP) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP) $(SASIDUMP): $(OBJ_SASIDUMP) - $(CXX) -o $@ $(OBJ_SASIDUMP) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_SASIDUMP) -$(SCSIMON): $(OBJ_SCSIMON) - $(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread +$(SCSISHARK): $(OBJ_SCSISHARK) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSISHARK) -lpthread clean: rm -f $(OBJ_ALL) $(BIN_ALL) diff --git a/src/raspberrypi/scsishark.cpp b/src/raspberrypi/scsishark.cpp new file mode 100644 index 0000000..1aca3f6 --- /dev/null +++ b/src/raspberrypi/scsishark.cpp @@ -0,0 +1,1459 @@ +//--------------------------------------------------------------------------- +// +// 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 "disk.h" +#include "gpiobus.h" +#include "spdlog/spdlog.h" +//#include +#include + +//--------------------------------------------------------------------------- +// +// Constant declarations +// +//--------------------------------------------------------------------------- +#define CtrlMax 8 // Maximum number of SCSI controllers +#define UnitNum 2 // Number of units around controller +#ifdef BAREMETAL +#define FPRT(fp, ...) printf( __VA_ARGS__ ) +#else +#define FPRT(fp, ...) fprintf(fp, __VA_ARGS__ ) +#endif // BAREMETAL + +//--------------------------------------------------------------------------- +// +// Variable declarations +// +//--------------------------------------------------------------------------- +static volatile BOOL running; // Running flag +static volatile BOOL active; // Processing flag +SASIDEV *ctrl[CtrlMax]; // Controller +Disk *disk[CtrlMax * UnitNum]; // Disk +GPIOBUS *bus; // GPIO Bus +#ifdef BAREMETAL +FATFS fatfs; // FatFS +#else +int monsocket; // Monitor Socket +pthread_t monthread; // Monitor Thread +static void *MonThread(void *param); +#endif // BAREMETAL +typedef struct data_capture{ + DWORD data; + timeval timestamp; +} data_capture_t; + + +#define MAX_BUFF_SIZE 1000000 + +data_capture data_buffer[MAX_BUFF_SIZE]; +int data_idx = 0; + + + +#define SECONDS_1 (1000 * 1000) +#define SECONDS_3 (3 * 1000 * 1000) +#define WAIT_FOR_EQUAL(x,y,timeout) { DWORD now = SysTimer::GetTimerLow(); while ((SysTimer::GetTimerLow() - now) < timeout) { bus->Aquire();if (x == y) {break;}}} + + +#ifndef BAREMETAL +//--------------------------------------------------------------------------- +// +// Signal Processing +// +//--------------------------------------------------------------------------- +void KillHandler(int sig) +{ + // Stop instruction + running = FALSE; +} +#endif // BAREMETAL + +//--------------------------------------------------------------------------- +// +// Banner Output +// +//--------------------------------------------------------------------------- +void Banner(int argc, char* argv[]) +{ + FPRT(stdout,"SCSI Target Emulator RaSCSI(*^..^*) "); + FPRT(stdout,"version %01d.%01d%01d(%s, %s)\n", + (int)((VERSION >> 8) & 0xf), + (int)((VERSION >> 4) & 0xf), + (int)((VERSION ) & 0xf), + __DATE__, + __TIME__); + FPRT(stdout,"Powered by XM6 TypeG Technology / "); + FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n"); + FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); + + if ((argc > 1 && strcmp(argv[1], "-h") == 0) || + (argc > 1 && strcmp(argv[1], "--help") == 0)){ + FPRT(stdout,"\n"); + FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); + FPRT(stdout," n is SCSI identification number(0-7).\n"); + FPRT(stdout," FILE is disk image file.\n\n"); + FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]); + FPRT(stdout," n is X68000 SASI HD number(0-15).\n"); + FPRT(stdout," FILE is disk image file.\n\n"); + FPRT(stdout," Image type is detected based on file extension.\n"); + FPRT(stdout," hdf : SASI HD image(XM6 SASI HD image)\n"); + FPRT(stdout," hds : SCSI HD image(XM6 SCSI HD image)\n"); + FPRT(stdout," hdn : SCSI HD image(NEC GENUINE)\n"); + FPRT(stdout," hdi : SCSI HD image(Anex86 HD image)\n"); + FPRT(stdout," nhd : SCSI HD image(T98Next HD image)\n"); + FPRT(stdout," hda : SCSI HD image(APPLE GENUINE)\n"); + FPRT(stdout," mos : SCSI MO image(XM6 SCSI MO image)\n"); + FPRT(stdout," iso : SCSI CD image(ISO 9660 image)\n"); + +#ifndef BAREMETAL + exit(0); +#endif // BAREMETAL + } +} + +//--------------------------------------------------------------------------- +// +// Initialization +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + int i; + +#ifndef BAREMETAL + struct sockaddr_in server; + int yes; + + // Create socket for monitor + monsocket = socket(PF_INET, SOCK_STREAM, 0); + memset(&server, 0, sizeof(server)); + server.sin_family = PF_INET; + server.sin_port = htons(6868); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + // allow address reuse + yes = 1; + if (setsockopt( + monsocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0){ + return FALSE; + } + + // Bind + if (bind(monsocket, (struct sockaddr *)&server, + sizeof(struct sockaddr_in)) < 0) { + FPRT(stderr, "Error : Already running?\n"); + return FALSE; + } + + // Create Monitor Thread + pthread_create(&monthread, NULL, MonThread, NULL); + + // 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; + } +#endif // BAREMETAL + + // GPIOBUS creation + bus = new GPIOBUS(); + + // GPIO Initialization + if (!bus->Init()) { + return FALSE; + } + + // Bus Reset + bus->Reset(); + + // Controller initialization + for (i = 0; i < CtrlMax; i++) { + ctrl[i] = NULL; + } + + // Disk Initialization + for (i = 0; i < CtrlMax; i++) { + disk[i] = NULL; + } + + // Other + running = FALSE; + active = FALSE; + + return TRUE; +} + +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND -1 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD -1 // DATA DIRECTION + +// Control signal output logic +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI signal pin assignment +#define PIN_DT0 10 // Data 0 +#define PIN_DT1 11 // Data 1 +#define PIN_DT2 12 // Data 2 +#define PIN_DT3 13 // Data 3 +#define PIN_DT4 14 // Data 4 +#define PIN_DT5 15 // Data 5 +#define PIN_DT6 16 // Data 6 +#define PIN_DT7 17 // Data 7 +#define PIN_DP 18 // Data parity +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL + + +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; +} + + +int pin_nums[] = {PIN_BSY,PIN_SEL,PIN_CD,PIN_IO,PIN_MSG,PIN_REQ,PIN_ACK,PIN_ATN,PIN_RST,PIN_DT0}; + +char* pin_names[] = {"BSY","SEL","CD","IO","MSG","REQ","ACK","ATN","RST","DAT"}; + + +void dump_data() +{ + char outstr[1024]; + int i = 0; + timeval time_diff; + FILE *fp; + timeval start_time = data_buffer[0].timestamp; + fp = fopen("log.txt","w"); + + + fprintf(fp, "idx\traw\ttimestamp\tBSY\tSEL\tC/D\tI/O\tMSG\tREQ\tACK\tATN\tRST\tData..\n"); + + while(i < data_idx) + { + timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); + //timediff = difftime(data_buffer[i].timestamp, start_time); + fprintf(fp, "%d\t%08lX\t%d:%d\t",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_BSY)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_SEL)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_CD)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_IO)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_MSG)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_REQ)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ACK)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ATN)); + fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_RST)); + fprintf(fp, "%02X\t", get_data_field(data_buffer[i].data)); + fprintf(fp, "\n"); + i++; + } + fclose(fp); + + + i=0; + printf("Creating timing_drawer.txt\n"); + fp = fopen("timing_drawer.txt","w"); + while(i < data_idx) + { + timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); + //timediff = difftime(data_buffer[i].timestamp, start_time); + fprintf(fp, "TIME=%d:%d;", time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "BSY=%d;", get_pin_value(data_buffer[i].data, PIN_BSY)); + fprintf(fp, "SEL=%d;", get_pin_value(data_buffer[i].data, PIN_SEL)); + fprintf(fp, "CD=%d;", get_pin_value(data_buffer[i].data, PIN_CD)); + fprintf(fp, "IO=%d;", get_pin_value(data_buffer[i].data, PIN_IO)); + fprintf(fp, "MSG=%d;", get_pin_value(data_buffer[i].data, PIN_MSG)); + fprintf(fp, "REQ=%d;", get_pin_value(data_buffer[i].data, PIN_REQ)); + fprintf(fp, "ACK=%d;", get_pin_value(data_buffer[i].data, PIN_ACK)); + fprintf(fp, "ATN=%d;", get_pin_value(data_buffer[i].data, PIN_ATN)); + fprintf(fp, "RST=%d;", get_pin_value(data_buffer[i].data, PIN_RST)); + fprintf(fp, "DATA=%02X.", get_data_field(data_buffer[i].data)); + fprintf(fp, "\n"); + i++; + } + fclose(fp); + + + +// +// fp = fopen("log2.txt","w"); +// +// for(int pin=0; pin < ARRAY_SIZE(pin_names); pin++) +// { +// i=0; +// while(i < data_idx) +// { +// char this_point = ((get_pin_value(data_buffer[i].data), pin_nums[pin]) == TRUE) ? "-", "_"; +// fprintf(fp, this_point) +// } +// +// +// +// +// } + + + + +} + + + +//--------------------------------------------------------------------------- +// +// Cleanup +// +//--------------------------------------------------------------------------- +void Cleanup() +{ + int i; + + printf("In cleanup....\n"); + + + + dump_data(); + + + + // Delete the disks + for (i = 0; i < CtrlMax * UnitNum; i++) { + if (disk[i]) { + delete disk[i]; + disk[i] = NULL; + } + } + + // Delete the Controllers + for (i = 0; i < CtrlMax; i++) { + if (ctrl[i]) { + delete ctrl[i]; + ctrl[i] = NULL; + } + } + + // Cleanup the Bus + bus->Cleanup(); + + // Discard the GPIOBUS object + delete bus; + +#ifndef BAREMETAL + // Close the monitor socket + if (monsocket >= 0) { + close(monsocket); + } +#endif // BAREMETAL +} + +//--------------------------------------------------------------------------- +// +// Reset +// +//--------------------------------------------------------------------------- +void Reset() +{ + int i; + + // Reset all of the controllers + for (i = 0; i < CtrlMax; i++) { + if (ctrl[i]) { + ctrl[i]->Reset(); + } + } + + // Reset the bus + bus->Reset(); +} + +//--------------------------------------------------------------------------- +// +// List Devices +// +//--------------------------------------------------------------------------- +void ListDevice(FILE *fp) +{ + int i; + int id; + int un; + Disk *pUnit; + Filepath filepath; + BOOL find; + char type[5]; + + find = FALSE; + type[4] = 0; + for (i = 0; i < CtrlMax * UnitNum; i++) { + // Initialize ID and unit number + id = i / UnitNum; + un = i % UnitNum; + pUnit = disk[i]; + + // skip if unit does not exist or null disk + if (pUnit == NULL || pUnit->IsNULL()) { + continue; + } + + // Output the header + if (!find) { + FPRT(fp, "\n"); + FPRT(fp, "+----+----+------+-------------------------------------\n"); + FPRT(fp, "| ID | UN | TYPE | DEVICE STATUS\n"); + FPRT(fp, "+----+----+------+-------------------------------------\n"); + find = TRUE; + } + + // ID,UNIT,Type,Device Status + type[0] = (char)(pUnit->GetID() >> 24); + type[1] = (char)(pUnit->GetID() >> 16); + type[2] = (char)(pUnit->GetID() >> 8); + type[3] = (char)(pUnit->GetID()); + FPRT(fp, "| %d | %d | %s | ", id, un, type); + + // mount status output + if (pUnit->GetID() == MAKEID('S', 'C', 'B', 'R')) { + FPRT(fp, "%s", "HOST BRIDGE"); + } else { + pUnit->GetPath(filepath); + FPRT(fp, "%s", + (pUnit->IsRemovable() && !pUnit->IsReady()) ? + "NO MEDIA" : filepath.GetPath()); + } + + // Write protection status + if (pUnit->IsRemovable() && pUnit->IsReady() && pUnit->IsWriteP()) { + FPRT(fp, "(WRITEPROTECT)"); + } + + // Goto the next line + FPRT(fp, "\n"); + } + + // If there is no controller, find will be null + if (!find) { + FPRT(fp, "No device is installed.\n"); + return; + } + + FPRT(fp, "+----+----+------+-------------------------------------\n"); +} + +//--------------------------------------------------------------------------- +// +// Controller Mapping +// +//--------------------------------------------------------------------------- +void MapControler(FILE *fp, Disk **map) +{ + int i; + int j; + int unitno; + int sasi_num; + int scsi_num; + + // Replace the changed unit + for (i = 0; i < CtrlMax; i++) { + for (j = 0; j < UnitNum; j++) { + unitno = i * UnitNum + j; + if (disk[unitno] != map[unitno]) { + // Check if the original unit exists + if (disk[unitno]) { + // Disconnect it from the controller + if (ctrl[i]) { + ctrl[i]->SetUnit(j, NULL); + } + + // Free the Unit + delete disk[unitno]; + } + + // Setup a new unit + disk[unitno] = map[unitno]; + } + } + } + + // Reconfigure all of the controllers + for (i = 0; i < CtrlMax; i++) { + // Examine the unit configuration + sasi_num = 0; + scsi_num = 0; + for (j = 0; j < UnitNum; j++) { + unitno = i * UnitNum + j; + // branch by unit type + if (disk[unitno]) { + if (disk[unitno]->IsSASI()) { + // Drive is SASI, so increment SASI count + sasi_num++; + } else { + // Drive is SCSI, so increment SCSI count + scsi_num++; + } + } + + // Remove the unit + if (ctrl[i]) { + ctrl[i]->SetUnit(j, NULL); + } + } + + // If there are no units connected + if (sasi_num == 0 && scsi_num == 0) { + if (ctrl[i]) { + delete ctrl[i]; + ctrl[i] = NULL; + continue; + } + } + + // Mixture of SCSI and SASI + if (sasi_num > 0 && scsi_num > 0) { + FPRT(fp, "Error : SASI and SCSI can't be mixed\n"); + continue; + } + + if (sasi_num > 0) { + // Only SASI Unit(s) + + // Release the controller if it is not SASI + if (ctrl[i] && !ctrl[i]->IsSASI()) { + delete ctrl[i]; + ctrl[i] = NULL; + } + + // Create a new SASI controller + if (!ctrl[i]) { + ctrl[i] = new SASIDEV(); + ctrl[i]->Connect(i, bus); + } + } else { + // Only SCSI Unit(s) + + // Release the controller if it is not SCSI + if (ctrl[i] && !ctrl[i]->IsSCSI()) { + delete ctrl[i]; + ctrl[i] = NULL; + } + + // Create a new SCSI controller + if (!ctrl[i]) { + ctrl[i] = new SCSIDEV(); + ctrl[i]->Connect(i, bus); + } + } + + // connect all units + for (j = 0; j < UnitNum; j++) { + unitno = i * UnitNum + j; + if (disk[unitno]) { + // Add the unit connection + ctrl[i]->SetUnit(j, disk[unitno]); + } + } + } +} + +//--------------------------------------------------------------------------- +// +// Command Processing +// +//--------------------------------------------------------------------------- +BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file) +{ + Disk *map[CtrlMax * UnitNum]; + int len; + char *ext; + Filepath filepath; + Disk *pUnit; + + // Copy the Unit List + memcpy(map, disk, sizeof(disk)); + + // Check the Controller Number + if (id < 0 || id >= CtrlMax) { + FPRT(fp, "Error : Invalid ID\n"); + return FALSE; + } + + // Check the Unit Number + if (un < 0 || un >= UnitNum) { + FPRT(fp, "Error : Invalid unit number\n"); + return FALSE; + } + + // Connect Command + if (cmd == 0) { // ATTACH + // Distinguish between SASI and SCSI + ext = NULL; + pUnit = NULL; + if (type == 0) { + // Passed the check + if (!file) { + return FALSE; + } + + // Check that command is at least 5 characters long + len = strlen(file); + if (len < 5) { + return FALSE; + } + + // Check the extension + if (file[len - 4] != '.') { + return FALSE; + } + + // If the extension is not SASI type, replace with SCSI + ext = &file[len - 3]; + if (xstrcasecmp(ext, "hdf") != 0) { + type = 1; + } + } + + // Create a new drive, based upon type + switch (type) { + case 0: // HDF + pUnit = new SASIHD(); + break; + case 1: // HDS/HDN/HDI/NHD/HDA + if (ext == NULL) { + break; + } + if (xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0) { + pUnit = new SCSIHD_NEC(); + } else if (xstrcasecmp(ext, "hda") == 0) { + pUnit = new SCSIHD_APPLE(); + } else { + pUnit = new SCSIHD(); + } + break; + case 2: // MO + pUnit = new SCSIMO(); + break; + case 3: // CD + pUnit = new SCSICD(); + break; + case 4: // BRIDGE + pUnit = new SCSIBR(); + break; + default: + FPRT(fp, "Error : Invalid device type\n"); + return FALSE; + } + + // drive checks files + if (type <= 1 || (type <= 3 && xstrcasecmp(file, "-") != 0)) { + // Set the Path + filepath.SetPath(file); + + // Open the file path + if (!pUnit->Open(filepath)) { + FPRT(fp, "Error : File open error [%s]\n", file); + delete pUnit; + return FALSE; + } + } + + // Set the cache to write-through + pUnit->SetCacheWB(FALSE); + + // Replace with the newly created unit + map[id * UnitNum + un] = pUnit; + + // Re-map the controller + MapControler(fp, map); + return TRUE; + } + + // Is this a valid command? + if (cmd > 4) { + FPRT(fp, "Error : Invalid command\n"); + return FALSE; + } + + // Does the controller exist? + if (ctrl[id] == NULL) { + FPRT(fp, "Error : No such device\n"); + return FALSE; + } + + // Does the unit exist? + pUnit = disk[id * UnitNum + un]; + if (pUnit == NULL) { + FPRT(fp, "Error : No such device\n"); + return FALSE; + } + + // Disconnect Command + if (cmd == 1) { // DETACH + // Free the existing unit + map[id * UnitNum + un] = NULL; + + // Re-map the controller + MapControler(fp, map); + return TRUE; + } + + // Valid only for MO or CD + if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O') && + pUnit->GetID() != MAKEID('S', 'C', 'C', 'D')) { + FPRT(fp, "Error : Operation denied(Deveice isn't removable)\n"); + return FALSE; + } + + switch (cmd) { + case 2: // INSERT + // Set the file path + filepath.SetPath(file); + + // Open the file + if (!pUnit->Open(filepath)) { + FPRT(fp, "Error : File open error [%s]\n", file); + return FALSE; + } + break; + + case 3: // EJECT + pUnit->Eject(TRUE); + break; + + case 4: // PROTECT + if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O')) { + FPRT(fp, "Error : Operation denied(Deveice isn't MO)\n"); + return FALSE; + } + pUnit->WriteP(!pUnit->IsWriteP()); + break; + default: + ASSERT(FALSE); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// Argument Parsing +// +//--------------------------------------------------------------------------- +BOOL ParseArgument(int argc, char* argv[]) +{ +#ifdef BAREMETAL + FRESULT fr; + FIL fp; + char line[512]; +#else + int i; +#endif // BAREMETAL + int id; + int un; + int type; + char *argID; + char *argPath; + int len; + char *ext; + +#ifdef BAREMETAL + // Mount the SD card + fr = f_mount(&fatfs, "", 1); + if (fr != FR_OK) { + FPRT(stderr, "Error : SD card mount failed.\n"); + return FALSE; + } + + // If there is no setting file, the processing is interrupted + fr = f_open(&fp, "rascsi.ini", FA_READ); + if (fr != FR_OK) { + return FALSE; + } +#else + // If the ID and path are not specified, the processing is interrupted + if (argc < 3) { + return TRUE; + } + i = 1; + argc--; +#endif // BAREMETAL + + // Start Decoding + + while (TRUE) { +#ifdef BAREMETAL + // Get one Line + memset(line, 0x00, sizeof(line)); + if (f_gets(line, sizeof(line) -1, &fp) == NULL) { + break; + } + + // Delete the CR/LF + len = strlen(line); + while (len > 0) { + if (line[len - 1] != '\r' && line[len - 1] != '\n') { + break; + } + line[len - 1] = '\0'; + len--; + } +#else + if (argc < 2) { + break; + } + + argc -= 2; +#endif // BAREMETAL + + // Get the ID and Path +#ifdef BAREMETAL + argID = &line[0]; + argPath = &line[4]; + line[3] = '\0'; + + // Check if the line is an empty string + if (argID[0] == '\0' || argPath[0] == '\0') { + continue; + } +#else + argID = argv[i++]; + argPath = argv[i++]; + + // Check if the argument is invalid + if (argID[0] != '-') { + FPRT(stderr, + "Error : Invalid argument(-IDn or -HDn) [%s]\n", argID); + goto parse_error; + } + argID++; +#endif // BAREMETAL + + if (strlen(argID) == 3 && xstrncasecmp(argID, "id", 2) == 0) { + // ID or ID Format + + // Check that the ID number is valid (0-7) + if (argID[2] < '0' || argID[2] > '7') { + FPRT(stderr, + "Error : Invalid argument(IDn n=0-7) [%c]\n", argID[2]); + goto parse_error; + } + + // The ID unit is good + id = argID[2] - '0'; + un = 0; + } else if (xstrncasecmp(argID, "hd", 2) == 0) { + // HD or HD format + + if (strlen(argID) == 3) { + // Check that the HD number is valid (0-9) + if (argID[2] < '0' || argID[2] > '9') { + FPRT(stderr, + "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); + goto parse_error; + } + + // ID was confirmed + id = (argID[2] - '0') / UnitNum; + un = (argID[2] - '0') % UnitNum; + } else if (strlen(argID) == 4) { + // Check that the HD number is valid (10-15) + if (argID[2] != '1' || argID[3] < '0' || argID[3] > '5') { + FPRT(stderr, + "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); + goto parse_error; + } + + // The ID unit is good - create the id and unit number + id = ((argID[3] - '0') + 10) / UnitNum; + un = ((argID[3] - '0') + 10) % UnitNum; +#ifdef BAREMETAL + argPath++; +#endif // BAREMETAL + } else { + FPRT(stderr, + "Error : Invalid argument(IDn or HDn) [%s]\n", argID); + goto parse_error; + } + } else { + FPRT(stderr, + "Error : Invalid argument(IDn or HDn) [%s]\n", argID); + goto parse_error; + } + + // Skip if there is already an active device + if (disk[id * UnitNum + un] && + !disk[id * UnitNum + un]->IsNULL()) { + continue; + } + + // Initialize device type + type = -1; + + // Check ethernet and host bridge + if (xstrcasecmp(argPath, "bridge") == 0) { + type = 4; + } else { + // Check the path length + len = strlen(argPath); + if (len < 5) { + FPRT(stderr, + "Error : Invalid argument(File path is short) [%s]\n", + argPath); + goto parse_error; + } + + // Does the file have an extension? + if (argPath[len - 4] != '.') { + FPRT(stderr, + "Error : Invalid argument(No extension) [%s]\n", argPath); + goto parse_error; + } + + // Figure out what the type is + ext = &argPath[len - 3]; + if (xstrcasecmp(ext, "hdf") == 0 || + xstrcasecmp(ext, "hds") == 0 || + xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 || + xstrcasecmp(ext, "hda") == 0) { + // HD(SASI/SCSI) + type = 0; + } else if (strcasecmp(ext, "mos") == 0) { + // MO + type = 2; + } else if (strcasecmp(ext, "iso") == 0) { + // CD + type = 3; + } else { + // Cannot determine the file type + FPRT(stderr, + "Error : Invalid argument(file type) [%s]\n", ext); + goto parse_error; + } + } + + // Execute the command + if (!ProcessCmd(stderr, id, un, 0, type, argPath)) { + goto parse_error; + } + } + +#ifdef BAREMETAL + // Close the configuration file + f_close(&fp); +#endif // BAREMETAL + + // Display the device list + ListDevice(stdout); + + return TRUE; + +parse_error: + +#ifdef BAREMETAL + // Close the configuration file + f_close(&fp); +#endif // BAREMETAL + + return FALSE; +} + +#ifndef BAREMETAL +//--------------------------------------------------------------------------- +// +// 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); + } +} + +//--------------------------------------------------------------------------- +// +// Monitor Thread +// +//--------------------------------------------------------------------------- +static void *MonThread(void *param) +{ + struct sched_param schedparam; + struct sockaddr_in client; + socklen_t len; + int fd; + FILE *fp; + char buf[BUFSIZ]; + char *p; + int i; + char *argv[5]; + int id; + int un; + int cmd; + int type; + char *file; + + // Scheduler Settings + schedparam.sched_priority = 0; + sched_setscheduler(0, SCHED_IDLE, &schedparam); + + // Set the affinity to a specific processor core + FixCpu(2); + + // Wait for the execution to start + while (!running) { + usleep(1); + } + + // Setup the monitor socket to receive commands + listen(monsocket, 1); + + while (1) { + // Wait for connection + memset(&client, 0, sizeof(client)); + len = sizeof(client); + fd = accept(monsocket, (struct sockaddr*)&client, &len); + if (fd < 0) { + break; + } + + // Fetch the command + fp = fdopen(fd, "r+"); + p = fgets(buf, BUFSIZ, fp); + + // Failed to get the command + if (!p) { + goto next; + } + + // Remove the newline character + p[strlen(p) - 1] = 0; + + // List all of the devices + if (xstrncasecmp(p, "list", 4) == 0) { + ListDevice(fp); + goto next; + } + + // Parameter separation + argv[0] = p; + for (i = 1; i < 5; i++) { + // Skip parameter values + while (*p && (*p != ' ')) { + p++; + } + + // Replace spaces with null characters + while (*p && (*p == ' ')) { + *p++ = 0; + } + + // The parameters were lost + if (!*p) { + break; + } + + // Recognized as a parameter + argv[i] = p; + } + + // Failed to get all parameters + if (i < 5) { + goto next; + } + + // ID, unit, command, type, file + id = atoi(argv[0]); + un = atoi(argv[1]); + cmd = atoi(argv[2]); + type = atoi(argv[3]); + file = argv[4]; + + // Wait until we becom idle + while (active) { + usleep(500 * 1000); + } + + // Execute the command + ProcessCmd(fp, id, un, cmd, type, file); + +next: + // Release the connection + fclose(fp); + close(fd); + } + + return NULL; +} +#endif // BAREMETAL + + + +//--------------------------------------------------------------------------- +// +// Main processing +// +//--------------------------------------------------------------------------- +#ifdef BAREMETAL +extern "C" +int startrascsi(void) +{ + int argc = 0; + char** argv = NULL; +#else +int main(int argc, char* argv[]) +{ +#endif // BAREMETAL + DWORD prev_sample = 0xFFFFFFFF; + DWORD this_sample = 0; + //int i; + int ret; +// int actid; + //DWORD now; + //BUS::phase_t phase; +// BYTE data; +#ifndef BAREMETAL + struct sched_param schparam; +#endif // BAREMETAL + + spdlog::set_level(spdlog::level::trace); + spdlog::trace("Entering the function with {0:x}{1:X} arguments", argc,20); + // 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(); + +#ifdef BAREMETAL + // BUSY assert (to hold the host side) + bus->SetBSY(TRUE); +#endif + + // Argument parsing + if (!ParseArgument(argc, argv)) { + ret = EINVAL; + goto err_exit; + } + +#ifdef BAREMETAL + // Release the busy signal + bus->SetBSY(FALSE); +#endif + +#ifndef BAREMETAL + // Set the affinity to a specific processor core + FixCpu(3); + +#ifdef USE_SEL_EVENT_ENABLE + // Scheduling policy setting (highest priority) + schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + sched_setscheduler(0, SCHED_FIFO, &schparam); +#endif // USE_SEL_EVENT_ENABLE +#endif // BAREMETAL + + // Start execution + running = TRUE; + bus->SetAct(FALSE); + + + + spdlog::trace("Going into running mode {}", 1); + // Main Loop + while (running) { + // Work initialization + this_sample = bus->Aquire(); + + if(this_sample != prev_sample) + { + //printf("%d Sample %08lX\n", data_idx, this_sample); + 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; +//////// +//////// // Target sending data +//////// if(!bus->GetIO() && bus->GetREQ() && bus->GetACK()) +//////// { +//////// BYTE data = bus->GetDAT(); +//////// printf("+%02X ",data); +//////// +//////// +//////// +//////// DWORD now = SysTimer::GetTimerLow(); +//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) +//////// { +//////// bus->Aquire(); +//////// if (bus->GetACK() == FALSE) { +//////// break; +//////// } +//////// } +//////// +//////// if(bus->GetACK() != FALSE) +//////// { +//////// spdlog::warn("got an invalid req/ack sequence for target sending data"); +//////// } +//////// } +//////// +//////// +//////// +//////// if(bus->GetIO() && bus->GetREQ() && !bus->GetACK()) +//////// { +//////// BYTE data = bus->GetDAT(); +//////// printf("-%02X ",data); +//////// +//////// +//////// DWORD now = SysTimer::GetTimerLow(); +//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) +//////// { +//////// bus->Aquire(); +//////// if (bus->GetREQ() == FALSE) { +//////// break; +//////// } +//////// } +//////// +//////// if(bus->GetREQ() != TRUE) +//////// { +//////// spdlog::warn("REQ didn't de-assert when I wanted it to."); +//////// } +//////// +//////// +//////// } +//////// +//////// continue; +//////// +//////// // Wait until BSY is released as there is a possibility for the +//////// // initiator to assert it while setting the ID (for up to 3 seconds) +//////// if (bus->GetSEL() ) { +//////// BYTE data = bus->GetDAT(); +//////// printf("SEL is asserted. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); +//////// now = SysTimer::GetTimerLow(); +//////// while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { +//////// bus->Aquire(); +//////// if (!bus->GetSEL()) { +//////// printf("SEL is clear. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); +//////// break; +//////// } +//////// } +//////// } +//////// else{ +//////// +//////// continue; +//////// } +////////// spdlog::trace("Busy: {}",bus->GetBSY()); +//////// +//////// +//////// // For monitor mode, we just want to make sure the initiator +//////// // released the BSY signal within 3 seconds. If it hasn't +//////// // the initiator is misbehaving +////////// if (bus->GetBSY()) { +////////// spdlog::warn("The initiator (%d) did not release the BSY signal after 3 seconds", bus->GetDAT()); +////////// continue; +////////// } +//////// +////////////////////// +////////////////////// // Stop because it the bus is busy or another device responded +////////////////////// if (bus->GetBSY() || !bus->GetSEL()) { +////////////////////// continue; +////////////////////// } +// +// // Notify all controllers +// data = bus->GetDAT(); +//// spdlog::trace("Data is {x}",data); +// for (i = 0; i < CtrlMax; i++) { +// if (!ctrl[i] || (data & (1 << i)) == 0) { +// continue; +// } +//// spdlog::trace("Found an active controller! Let's do some selection {}", i); +// // Find the target that has moved to the selection phase +// if (ctrl[i]->Process() == BUS::selection) { +// // Get the target ID +// actid = i; +// +// // Bus Selection phase +// phase = BUS::selection; +// break; +// } +// } +// +// // Return to bus monitoring if the selection phase has not started +// if (phase != BUS::selection) { +// continue; +// } +// +// // Start target device +// active = TRUE; +// spdlog::trace("Found a target device {} ID:{}",actid, ctrl[actid]->GetID()); +// +//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) +// // Scheduling policy setting (highest priority) +// schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); +// sched_setscheduler(0, SCHED_FIFO, &schparam); +//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL +// +// // Loop until the bus is free +// while (running) { +// // Target drive +// phase = ctrl[actid]->Process(); +// +// // End when the bus is free +// if (phase == BUS::busfree) { +// break; +// } +// } +// +//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) +// // Set the scheduling priority back to normal +// schparam.sched_priority = 0; +// sched_setscheduler(0, SCHED_OTHER, &schparam); +//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL +// +// // End the target travel +// active = FALSE; + } + +err_exit: + // Cleanup + Cleanup(); + +init_exit: +#if !defined(BAREMETAL) + exit(ret); +#else + return ret; +#endif // BAREMETAL +} From f610c7f2848eb837b2dd3d531ffb2d6a227a2ba3 Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 15:29:27 -0500 Subject: [PATCH 04/12] Changed gpiobus back to a common version. Restored rascsi.cpp to original version --- src/raspberrypi/gpiobus.cpp | 221 +++++++++------ src/raspberrypi/gpiobus.h | 5 + src/raspberrypi/rascsi.cpp | 501 +++++++--------------------------- src/raspberrypi/scsishark.cpp | 28 +- 4 files changed, 255 insertions(+), 500 deletions(-) diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp index 1c6c163..538c59d 100644 --- a/src/raspberrypi/gpiobus.cpp +++ b/src/raspberrypi/gpiobus.cpp @@ -460,7 +460,6 @@ void FASTCALL GPIOBUS::Reset() SetMode(PIN_SEL, IN); SetMode(PIN_ATN, IN); SetMode(PIN_ACK, IN); - printf("ACK is set to IN\n"); SetMode(PIN_RST, IN); // Set data bus signals to input @@ -489,7 +488,6 @@ void FASTCALL GPIOBUS::Reset() SetControl(PIN_IND, IND_OUT); SetMode(PIN_SEL, OUT); SetMode(PIN_ATN, OUT); - printf("ACK is set to OUT\n"); SetMode(PIN_ACK, OUT); SetMode(PIN_RST, OUT); @@ -510,8 +508,6 @@ void FASTCALL GPIOBUS::Reset() signals = 0; } -static DWORD high_bits = 0x0; -static DWORD low_bits = 0xFFFFFFFF; //--------------------------------------------------------------------------- // // Bus signal acquisition @@ -521,17 +517,6 @@ DWORD FASTCALL GPIOBUS::Aquire() { signals = *level; - DWORD prev_high = high_bits; - DWORD prev_low = low_bits; - - high_bits |= signals; - low_bits &= signals; - - if ((high_bits != prev_high) || (low_bits != prev_low)) - { - printf(" %08lX %08lX\n",high_bits, low_bits); - } - #if SIGNAL_CONTROL_MODE < 2 // Invert if negative logic (internal processing is unified to positive logic) signals = ~signals; @@ -567,36 +552,40 @@ BOOL FASTCALL GPIOBUS::GetBSY() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetBSY(BOOL ast) { -// // Set BSY signal -// SetSignal(PIN_BSY, ast); -// -// if (actmode == TARGET) { -// if (ast) { -// // Turn on ACTIVE signal -// SetControl(PIN_ACT, ACT_ON); -// -// // Set Target signal to output -// SetControl(PIN_TAD, TAD_OUT); -// -// SetMode(PIN_BSY, OUT); -// SetMode(PIN_MSG, OUT); -// SetMode(PIN_CD, OUT); -// SetMode(PIN_REQ, OUT); -// SetMode(PIN_IO, OUT); -// } else { -// // Turn off the ACTIVE signal -// SetControl(PIN_ACT, ACT_OFF); -// -// // Set the target signal to input -// SetControl(PIN_TAD, TAD_IN); -// -// SetMode(PIN_BSY, IN); -// SetMode(PIN_MSG, IN); -// SetMode(PIN_CD, IN); -// SetMode(PIN_REQ, IN); -// SetMode(PIN_IO, IN); -// } -// } + if(actmode == MONITOR){ + return; + } + + // Set BSY signal + SetSignal(PIN_BSY, ast); + + if (actmode == TARGET) { + if (ast) { + // Turn on ACTIVE signal + SetControl(PIN_ACT, ACT_ON); + + // Set Target signal to output + SetControl(PIN_TAD, TAD_OUT); + + SetMode(PIN_BSY, OUT); + SetMode(PIN_MSG, OUT); + SetMode(PIN_CD, OUT); + SetMode(PIN_REQ, OUT); + SetMode(PIN_IO, OUT); + } else { + // Turn off the ACTIVE signal + SetControl(PIN_ACT, ACT_OFF); + + // Set the target signal to input + SetControl(PIN_TAD, TAD_IN); + + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + } + } } //--------------------------------------------------------------------------- @@ -616,13 +605,17 @@ BOOL FASTCALL GPIOBUS::GetSEL() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetSEL(BOOL ast) { -// if (actmode == INITIATOR && ast) { -// // Turn on ACTIVE signal -// SetControl(PIN_ACT, ACT_ON); -// } -// -// // Set SEL signal -// SetSignal(PIN_SEL, ast); + if(actmode == MONITOR){ + return; + } + + if (actmode == INITIATOR && ast) { + // Turn on ACTIVE signal + SetControl(PIN_ACT, ACT_ON); + } + + // Set SEL signal + SetSignal(PIN_SEL, ast); } //--------------------------------------------------------------------------- @@ -642,7 +635,11 @@ BOOL FASTCALL GPIOBUS::GetATN() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetATN(BOOL ast) { -// SetSignal(PIN_ATN, ast); + if(actmode == MONITOR){ + return; + } + + SetSignal(PIN_ATN, ast); } //--------------------------------------------------------------------------- @@ -662,7 +659,31 @@ BOOL FASTCALL GPIOBUS::GetACK() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetACK(BOOL ast) { - //SetSignal(PIN_ACK, ast); + if(actmode == MONITOR){ + return; + } + + 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); } //--------------------------------------------------------------------------- @@ -682,7 +703,11 @@ BOOL FASTCALL GPIOBUS::GetRST() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetRST(BOOL ast) { - //SetSignal(PIN_RST, ast); + if(actmode == MONITOR){ + return; + } + + SetSignal(PIN_RST, ast); } //--------------------------------------------------------------------------- @@ -702,7 +727,11 @@ BOOL FASTCALL GPIOBUS::GetMSG() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetMSG(BOOL ast) { - //SetSignal(PIN_MSG, ast); + if(actmode == MONITOR){ + return; + } + + SetSignal(PIN_MSG, ast); } //--------------------------------------------------------------------------- @@ -722,7 +751,11 @@ BOOL FASTCALL GPIOBUS::GetCD() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetCD(BOOL ast) { - //SetSignal(PIN_CD, ast); + if(actmode == MONITOR){ + return; + } + + SetSignal(PIN_CD, ast); } //--------------------------------------------------------------------------- @@ -772,6 +805,10 @@ BOOL FASTCALL GPIOBUS::GetIO() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetIO(BOOL ast) { + if(actmode == MONITOR){ + return; + } + SetSignal(PIN_IO, ast); if (actmode == TARGET) { @@ -820,7 +857,11 @@ BOOL FASTCALL GPIOBUS::GetREQ() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetREQ(BOOL ast) { -// SetSignal(PIN_REQ, ast); + if(actmode == MONITOR){ + return; + } + + SetSignal(PIN_REQ, ast); } //--------------------------------------------------------------------------- @@ -853,37 +894,41 @@ BYTE FASTCALL GPIOBUS::GetDAT() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetDAT(BYTE dat) { + if(actmode == MONITOR){ + return; + } + // Write to port -//#if SIGNAL_CONTROL_MODE == 0 -// DWORD fsel; -// -// fsel = gpfsel[0]; -// fsel &= tblDatMsk[0][dat]; -// fsel |= tblDatSet[0][dat]; -// if (fsel != gpfsel[0]) { -// gpfsel[0] = fsel; -// gpio[GPIO_FSEL_0] = fsel; -// } -// -// fsel = gpfsel[1]; -// fsel &= tblDatMsk[1][dat]; -// fsel |= tblDatSet[1][dat]; -// if (fsel != gpfsel[1]) { -// gpfsel[1] = fsel; -// gpio[GPIO_FSEL_1] = fsel; -// } -// -// fsel = gpfsel[2]; -// fsel &= tblDatMsk[2][dat]; -// fsel |= tblDatSet[2][dat]; -// if (fsel != gpfsel[2]) { -// gpfsel[2] = fsel; -// gpio[GPIO_FSEL_2] = fsel; -// } -//#else -// gpio[GPIO_CLR_0] = tblDatMsk[dat]; -// gpio[GPIO_SET_0] = tblDatSet[dat]; -//#endif // SIGNAL_CONTROL_MODE +#if SIGNAL_CONTROL_MODE == 0 + DWORD fsel; + + fsel = gpfsel[0]; + fsel &= tblDatMsk[0][dat]; + fsel |= tblDatSet[0][dat]; + if (fsel != gpfsel[0]) { + gpfsel[0] = fsel; + gpio[GPIO_FSEL_0] = fsel; + } + + fsel = gpfsel[1]; + fsel &= tblDatMsk[1][dat]; + fsel |= tblDatSet[1][dat]; + if (fsel != gpfsel[1]) { + gpfsel[1] = fsel; + gpio[GPIO_FSEL_1] = fsel; + } + + fsel = gpfsel[2]; + fsel &= tblDatMsk[2][dat]; + fsel |= tblDatSet[2][dat]; + if (fsel != gpfsel[2]) { + gpfsel[2] = fsel; + gpio[GPIO_FSEL_2] = fsel; + } +#else + gpio[GPIO_CLR_0] = tblDatMsk[dat]; + gpio[GPIO_SET_0] = tblDatSet[dat]; +#endif // SIGNAL_CONTROL_MODE } //--------------------------------------------------------------------------- diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h index 2ee34ff..3792af4 100644 --- a/src/raspberrypi/gpiobus.h +++ b/src/raspberrypi/gpiobus.h @@ -460,6 +460,11 @@ public: void FASTCALL SetACK(BOOL ast); // Set ACK signal + BOOL FASTCALL GetACT(); + // Get ACT signal + void FASTCALL SetACT(BOOL ast); + // Set ACT signal + BOOL FASTCALL GetRST(); // Get RST signal void FASTCALL SetRST(BOOL ast); diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 1aca3f6..cfa3d65 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -15,9 +15,6 @@ #include "fileio.h" #include "disk.h" #include "gpiobus.h" -#include "spdlog/spdlog.h" -//#include -#include //--------------------------------------------------------------------------- // @@ -49,23 +46,6 @@ int monsocket; // Monitor Socket pthread_t monthread; // Monitor Thread static void *MonThread(void *param); #endif // BAREMETAL -typedef struct data_capture{ - DWORD data; - timeval timestamp; -} data_capture_t; - - -#define MAX_BUFF_SIZE 1000000 - -data_capture data_buffer[MAX_BUFF_SIZE]; -int data_idx = 0; - - - -#define SECONDS_1 (1000 * 1000) -#define SECONDS_3 (3 * 1000 * 1000) -#define WAIT_FOR_EQUAL(x,y,timeout) { DWORD now = SysTimer::GetTimerLow(); while ((SysTimer::GetTimerLow() - now) < timeout) { bus->Aquire();if (x == y) {break;}}} - #ifndef BAREMETAL //--------------------------------------------------------------------------- @@ -200,149 +180,6 @@ BOOL Init() return TRUE; } -#define PIN_ACT 4 // ACTIVE -#define PIN_ENB 5 // ENABLE -#define PIN_IND -1 // INITIATOR CTRL DIRECTION -#define PIN_TAD -1 // TARGET CTRL DIRECTION -#define PIN_DTD -1 // DATA DIRECTION - -// Control signal output logic -#define ACT_ON TRUE // ACTIVE SIGNAL ON -#define ENB_ON TRUE // ENABLE SIGNAL ON -#define IND_IN FALSE // INITIATOR SIGNAL INPUT -#define TAD_IN FALSE // TARGET SIGNAL INPUT -#define DTD_IN TRUE // DATA SIGNAL INPUT - -// SCSI signal pin assignment -#define PIN_DT0 10 // Data 0 -#define PIN_DT1 11 // Data 1 -#define PIN_DT2 12 // Data 2 -#define PIN_DT3 13 // Data 3 -#define PIN_DT4 14 // Data 4 -#define PIN_DT5 15 // Data 5 -#define PIN_DT6 16 // Data 6 -#define PIN_DT7 17 // Data 7 -#define PIN_DP 18 // Data parity -#define PIN_ATN 19 // ATN -#define PIN_RST 20 // RST -#define PIN_ACK 21 // ACK -#define PIN_REQ 22 // REQ -#define PIN_MSG 23 // MSG -#define PIN_CD 24 // CD -#define PIN_IO 25 // IO -#define PIN_BSY 26 // BSY -#define PIN_SEL 27 // SEL - - -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; -} - - -int pin_nums[] = {PIN_BSY,PIN_SEL,PIN_CD,PIN_IO,PIN_MSG,PIN_REQ,PIN_ACK,PIN_ATN,PIN_RST,PIN_DT0}; - -char* pin_names[] = {"BSY","SEL","CD","IO","MSG","REQ","ACK","ATN","RST","DAT"}; - - -void dump_data() -{ - char outstr[1024]; - int i = 0; - timeval time_diff; - FILE *fp; - timeval start_time = data_buffer[0].timestamp; - fp = fopen("log.txt","w"); - - - fprintf(fp, "idx\traw\ttimestamp\tBSY\tSEL\tC/D\tI/O\tMSG\tREQ\tACK\tATN\tRST\tData..\n"); - - while(i < data_idx) - { - timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); - //timediff = difftime(data_buffer[i].timestamp, start_time); - fprintf(fp, "%d\t%08lX\t%d:%d\t",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_BSY)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_SEL)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_CD)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_IO)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_MSG)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_REQ)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ACK)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ATN)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_RST)); - fprintf(fp, "%02X\t", get_data_field(data_buffer[i].data)); - fprintf(fp, "\n"); - i++; - } - fclose(fp); - - - i=0; - printf("Creating timing_drawer.txt\n"); - fp = fopen("timing_drawer.txt","w"); - while(i < data_idx) - { - timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); - //timediff = difftime(data_buffer[i].timestamp, start_time); - fprintf(fp, "TIME=%d:%d;", time_diff.tv_sec, time_diff.tv_usec); - fprintf(fp, "BSY=%d;", get_pin_value(data_buffer[i].data, PIN_BSY)); - fprintf(fp, "SEL=%d;", get_pin_value(data_buffer[i].data, PIN_SEL)); - fprintf(fp, "CD=%d;", get_pin_value(data_buffer[i].data, PIN_CD)); - fprintf(fp, "IO=%d;", get_pin_value(data_buffer[i].data, PIN_IO)); - fprintf(fp, "MSG=%d;", get_pin_value(data_buffer[i].data, PIN_MSG)); - fprintf(fp, "REQ=%d;", get_pin_value(data_buffer[i].data, PIN_REQ)); - fprintf(fp, "ACK=%d;", get_pin_value(data_buffer[i].data, PIN_ACK)); - fprintf(fp, "ATN=%d;", get_pin_value(data_buffer[i].data, PIN_ATN)); - fprintf(fp, "RST=%d;", get_pin_value(data_buffer[i].data, PIN_RST)); - fprintf(fp, "DATA=%02X.", get_data_field(data_buffer[i].data)); - fprintf(fp, "\n"); - i++; - } - fclose(fp); - - - -// -// fp = fopen("log2.txt","w"); -// -// for(int pin=0; pin < ARRAY_SIZE(pin_names); pin++) -// { -// i=0; -// while(i < data_idx) -// { -// char this_point = ((get_pin_value(data_buffer[i].data), pin_nums[pin]) == TRUE) ? "-", "_"; -// fprintf(fp, this_point) -// } -// -// -// -// -// } - - - - -} - - - //--------------------------------------------------------------------------- // // Cleanup @@ -352,14 +189,6 @@ void Cleanup() { int i; - printf("In cleanup....\n"); - - - - dump_data(); - - - // Delete the disks for (i = 0; i < CtrlMax * UnitNum; i++) { if (disk[i]) { @@ -1141,8 +970,6 @@ next: } #endif // BAREMETAL - - //--------------------------------------------------------------------------- // // Main processing @@ -1158,23 +985,18 @@ int startrascsi(void) int main(int argc, char* argv[]) { #endif // BAREMETAL - DWORD prev_sample = 0xFFFFFFFF; - DWORD this_sample = 0; - //int i; + int i; int ret; -// int actid; - //DWORD now; - //BUS::phase_t phase; -// BYTE data; + int actid; + DWORD now; + BUS::phase_t phase; + BYTE data; #ifndef BAREMETAL struct sched_param schparam; #endif // BAREMETAL - spdlog::set_level(spdlog::level::trace); - spdlog::trace("Entering the function with {0:x}{1:X} arguments", argc,20); // Output the Banner Banner(argc, argv); - memset(data_buffer,0,sizeof(data_buffer)); // Initialize ret = 0; @@ -1215,235 +1037,103 @@ int main(int argc, char* argv[]) // Start execution running = TRUE; - bus->SetAct(FALSE); - - - spdlog::trace("Going into running mode {}", 1); // Main Loop while (running) { // Work initialization - this_sample = bus->Aquire(); + actid = -1; + phase = BUS::busfree; - if(this_sample != prev_sample) - { - //printf("%d Sample %08lX\n", data_idx, this_sample); - 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; +#ifdef USE_SEL_EVENT_ENABLE + // SEL signal polling + if (bus->PollSelectEvent() < 0) { + // Stop on interrupt + if (errno == EINTR) { + break; + } + continue; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - continue; -//////// -//////// // Target sending data -//////// if(!bus->GetIO() && bus->GetREQ() && bus->GetACK()) -//////// { -//////// BYTE data = bus->GetDAT(); -//////// printf("+%02X ",data); -//////// -//////// -//////// -//////// DWORD now = SysTimer::GetTimerLow(); -//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) -//////// { -//////// bus->Aquire(); -//////// if (bus->GetACK() == FALSE) { -//////// break; -//////// } -//////// } -//////// -//////// if(bus->GetACK() != FALSE) -//////// { -//////// spdlog::warn("got an invalid req/ack sequence for target sending data"); -//////// } -//////// } -//////// -//////// -//////// -//////// if(bus->GetIO() && bus->GetREQ() && !bus->GetACK()) -//////// { -//////// BYTE data = bus->GetDAT(); -//////// printf("-%02X ",data); -//////// -//////// -//////// DWORD now = SysTimer::GetTimerLow(); -//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) -//////// { -//////// bus->Aquire(); -//////// if (bus->GetREQ() == FALSE) { -//////// break; -//////// } -//////// } -//////// -//////// if(bus->GetREQ() != TRUE) -//////// { -//////// spdlog::warn("REQ didn't de-assert when I wanted it to."); -//////// } -//////// -//////// -//////// } -//////// -//////// continue; -//////// -//////// // Wait until BSY is released as there is a possibility for the -//////// // initiator to assert it while setting the ID (for up to 3 seconds) -//////// if (bus->GetSEL() ) { -//////// BYTE data = bus->GetDAT(); -//////// printf("SEL is asserted. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); -//////// now = SysTimer::GetTimerLow(); -//////// while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { -//////// bus->Aquire(); -//////// if (!bus->GetSEL()) { -//////// printf("SEL is clear. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); -//////// break; -//////// } -//////// } -//////// } -//////// else{ -//////// -//////// continue; -//////// } -////////// spdlog::trace("Busy: {}",bus->GetBSY()); -//////// -//////// -//////// // For monitor mode, we just want to make sure the initiator -//////// // released the BSY signal within 3 seconds. If it hasn't -//////// // the initiator is misbehaving -////////// if (bus->GetBSY()) { -////////// spdlog::warn("The initiator (%d) did not release the BSY signal after 3 seconds", bus->GetDAT()); -////////// continue; -////////// } -//////// -////////////////////// -////////////////////// // Stop because it the bus is busy or another device responded -////////////////////// if (bus->GetBSY() || !bus->GetSEL()) { -////////////////////// continue; -////////////////////// } -// -// // Notify all controllers -// data = bus->GetDAT(); -//// spdlog::trace("Data is {x}",data); -// for (i = 0; i < CtrlMax; i++) { -// if (!ctrl[i] || (data & (1 << i)) == 0) { -// continue; -// } -//// spdlog::trace("Found an active controller! Let's do some selection {}", i); -// // Find the target that has moved to the selection phase -// if (ctrl[i]->Process() == BUS::selection) { -// // Get the target ID -// actid = i; -// -// // Bus Selection phase -// phase = BUS::selection; -// break; -// } -// } -// -// // Return to bus monitoring if the selection phase has not started -// if (phase != BUS::selection) { -// continue; -// } -// -// // Start target device -// active = TRUE; -// spdlog::trace("Found a target device {} ID:{}",actid, ctrl[actid]->GetID()); -// -//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) -// // Scheduling policy setting (highest priority) -// schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); -// sched_setscheduler(0, SCHED_FIFO, &schparam); -//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL -// -// // Loop until the bus is free -// while (running) { -// // Target drive -// phase = ctrl[actid]->Process(); -// -// // End when the bus is free -// if (phase == BUS::busfree) { -// break; -// } -// } -// -//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) -// // Set the scheduling priority back to normal -// schparam.sched_priority = 0; -// sched_setscheduler(0, SCHED_OTHER, &schparam); -//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL -// -// // End the target travel -// active = FALSE; + // Get the bus + bus->Aquire(); +#else + bus->Aquire(); + if (!bus->GetSEL()) { +#if !defined(BAREMETAL) + usleep(0); +#endif // !BAREMETAL + continue; + } +#endif // USE_SEL_EVENT_ENABLE + + // Wait until BSY is released as there is a possibility for the + // initiator to assert it while setting the ID (for up to 3 seconds) + if (bus->GetBSY()) { + now = SysTimer::GetTimerLow(); + while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { + bus->Aquire(); + if (!bus->GetBSY()) { + break; + } + } + } + + // Stop because it the bus is busy or another device responded + if (bus->GetBSY() || !bus->GetSEL()) { + continue; + } + + // Notify all controllers + data = bus->GetDAT(); + for (i = 0; i < CtrlMax; i++) { + if (!ctrl[i] || (data & (1 << i)) == 0) { + continue; + } + + // Find the target that has moved to the selection phase + if (ctrl[i]->Process() == BUS::selection) { + // Get the target ID + actid = i; + + // Bus Selection phase + phase = BUS::selection; + break; + } + } + + // Return to bus monitoring if the selection phase has not started + if (phase != BUS::selection) { + continue; + } + + // Start target device + active = TRUE; + +#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) + // Scheduling policy setting (highest priority) + schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + sched_setscheduler(0, SCHED_FIFO, &schparam); +#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL + + // Loop until the bus is free + while (running) { + // Target drive + phase = ctrl[actid]->Process(); + + // End when the bus is free + if (phase == BUS::busfree) { + break; + } + } + +#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) + // Set the scheduling priority back to normal + schparam.sched_priority = 0; + sched_setscheduler(0, SCHED_OTHER, &schparam); +#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL + + // End the target travel + active = FALSE; } err_exit: @@ -1457,3 +1147,4 @@ init_exit: return ret; #endif // BAREMETAL } + diff --git a/src/raspberrypi/scsishark.cpp b/src/raspberrypi/scsishark.cpp index 1aca3f6..561f6d2 100644 --- a/src/raspberrypi/scsishark.cpp +++ b/src/raspberrypi/scsishark.cpp @@ -258,12 +258,11 @@ BYTE get_data_field(DWORD data) int pin_nums[] = {PIN_BSY,PIN_SEL,PIN_CD,PIN_IO,PIN_MSG,PIN_REQ,PIN_ACK,PIN_ATN,PIN_RST,PIN_DT0}; -char* pin_names[] = {"BSY","SEL","CD","IO","MSG","REQ","ACK","ATN","RST","DAT"}; +std::string pin_names[] = {"BSY","SEL","CD","IO","MSG","REQ","ACK","ATN","RST","DAT"}; void dump_data() { - char outstr[1024]; int i = 0; timeval time_diff; FILE *fp; @@ -277,7 +276,7 @@ void dump_data() { timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); //timediff = difftime(data_buffer[i].timestamp, start_time); - fprintf(fp, "%d\t%08lX\t%d:%d\t",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "%d\t%08lX\t%ld:%ld\t",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_BSY)); fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_SEL)); fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_CD)); @@ -301,7 +300,7 @@ void dump_data() { timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); //timediff = difftime(data_buffer[i].timestamp, start_time); - fprintf(fp, "TIME=%d:%d;", time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "TIME=%ld:%ld;", time_diff.tv_sec, time_diff.tv_usec); fprintf(fp, "BSY=%d;", get_pin_value(data_buffer[i].data, PIN_BSY)); fprintf(fp, "SEL=%d;", get_pin_value(data_buffer[i].data, PIN_SEL)); fprintf(fp, "CD=%d;", get_pin_value(data_buffer[i].data, PIN_CD)); @@ -1141,6 +1140,8 @@ next: } #endif // BAREMETAL +static DWORD high_bits = 0x0; +static DWORD low_bits = 0xFFFFFFFF; //--------------------------------------------------------------------------- @@ -1158,6 +1159,8 @@ int startrascsi(void) int main(int argc, char* argv[]) { #endif // BAREMETAL + DWORD prev_high = high_bits; + DWORD prev_low = low_bits; DWORD prev_sample = 0xFFFFFFFF; DWORD this_sample = 0; //int i; @@ -1215,9 +1218,7 @@ int main(int argc, char* argv[]) // Start execution running = TRUE; - bus->SetAct(FALSE); - - + bus->SetACT(FALSE); spdlog::trace("Going into running mode {}", 1); // Main Loop @@ -1227,6 +1228,19 @@ int main(int argc, char* argv[]) if(this_sample != prev_sample) { + + // 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)) + { + printf(" %08lX %08lX\n",high_bits, low_bits); + } + prev_high = high_bits; + prev_low = low_bits; + //printf("%d Sample %08lX\n", data_idx, this_sample); data_buffer[data_idx].data = this_sample; (void)gettimeofday(&(data_buffer[data_idx].timestamp), NULL); From 4b8877af56420f23aa882f9f68d9b79ec4440ab1 Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 15:33:45 -0500 Subject: [PATCH 05/12] Restore common version of this file --- src/raspberrypi/disk.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index c616e18..cda94ef 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -6404,12 +6404,12 @@ void FASTCALL SASIDEV::BusFree() // Phase Setting ctrl.phase = BUS::busfree; -////////////// // Set Signal lines -////////////// ctrl.bus->SetREQ(FALSE); -////////////// ctrl.bus->SetMSG(FALSE); -////////////// ctrl.bus->SetCD(FALSE); -////////////// ctrl.bus->SetIO(FALSE); -////////////// ctrl.bus->SetBSY(FALSE); + // Set Signal lines + ctrl.bus->SetREQ(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -6490,10 +6490,10 @@ void FASTCALL SASIDEV::Command() // Phase Setting ctrl.phase = BUS::command; -////////// // Signal line operated by the target -////////// ctrl.bus->SetMSG(FALSE); -////////// ctrl.bus->SetCD(TRUE); -////////// ctrl.bus->SetIO(FALSE); + // Signal line operated by the target + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); // Wait until target sets the following condition: // MSG = FALSE @@ -8114,13 +8114,12 @@ void FASTCALL SCSIDEV::BusFree() // Phase setting ctrl.phase = BUS::busfree; -////////// // Signal line -// We shouldn't be setting ANYTHING -////////// ctrl.bus->SetREQ(FALSE); -////////// ctrl.bus->SetMSG(FALSE); -////////// ctrl.bus->SetCD(FALSE); -////////// ctrl.bus->SetIO(FALSE); -////////// ctrl.bus->SetBSY(FALSE); + // Signal line + ctrl.bus->SetREQ(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; From 64b5c3d0f6a7523d85a75f82db5495842ead282c Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 17:59:52 -0500 Subject: [PATCH 06/12] Fix formatting to match WaveDrom --- src/raspberrypi/convert_data.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/raspberrypi/convert_data.py b/src/raspberrypi/convert_data.py index 7d3d77b..a57d1a5 100644 --- a/src/raspberrypi/convert_data.py +++ b/src/raspberrypi/convert_data.py @@ -4,7 +4,8 @@ import sys outfile = open('data.json', 'w') infile = open('timing_drawer.txt','r') - + +print("{signal: [", file=outfile) firstline = infile.readline() num_columns = len(firstline.split(";")) @@ -29,7 +30,7 @@ while (field_num < num_columns): elif (z == '00'): out = '0' else: - out = '1' + out = '2' print(out, file=outfile, end='') prev_val = z print("', data: [", file=outfile, end='') @@ -52,11 +53,11 @@ while (field_num < num_columns): prev_val = z print(z, file=outfile, end='') - print("'},", file=outfile) + print("'},", file=outfile) field_num = field_num + 1 - +print("]}", file=outfile) outfile.close() From da3d0ea49437bd76905d8ec528be467ac5d17ea3 Mon Sep 17 00:00:00 2001 From: akuker Date: Sat, 18 Jul 2020 18:00:17 -0500 Subject: [PATCH 07/12] Ignore non-SCSI pins --- src/raspberrypi/gpiobus.h | 20 ++++++++++++++++++++ src/raspberrypi/scsishark.cpp | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h index 3792af4..3e1b844 100644 --- a/src/raspberrypi/gpiobus.h +++ b/src/raspberrypi/gpiobus.h @@ -140,6 +140,26 @@ #define PIN_IO 25 // IO #define PIN_BSY 26 // BSY #define PIN_SEL 27 // SEL + +#define ALL_SCSI_PINS \ + ((1<SetACT(FALSE); spdlog::trace("Going into running mode {}", 1); + printf("ALL_SCSI_PINS %08X\n",ALL_SCSI_PINS); // Main Loop while (running) { // Work initialization - this_sample = bus->Aquire(); + this_sample = (bus->Aquire() & ALL_SCSI_PINS); if(this_sample != prev_sample) { From 1cc05072af8b16728d9ab2f95f124943418d2308 Mon Sep 17 00:00:00 2001 From: akuker Date: Sun, 19 Jul 2020 00:22:35 -0500 Subject: [PATCH 08/12] scsishark works to capture data from the scsi bus. The VCD file can be opened with GTKWave --- src/raspberrypi/Makefile | 2 + src/raspberrypi/scsishark.cpp | 1311 ++++----------------------------- 2 files changed, 144 insertions(+), 1169 deletions(-) diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index a5e7266..6f6785b 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -132,3 +132,5 @@ $(DOC_DIR)/%_man_page.txt : $(DOC_DIR)/%.1 .PHONY: Debug Debug: all +.PHONY: Debug-scsishark +Debug-scsishark: $(SCSISHARK) diff --git a/src/raspberrypi/scsishark.cpp b/src/raspberrypi/scsishark.cpp index eb23257..2c67575 100644 --- a/src/raspberrypi/scsishark.cpp +++ b/src/raspberrypi/scsishark.cpp @@ -5,7 +5,7 @@ // // Powered by XM6 TypeG Technology. // Copyright (C) 2016-2020 GIMONS -// [ RaSCSI main ] +// [ SCSI Shark main] // //--------------------------------------------------------------------------- @@ -16,7 +16,6 @@ #include "disk.h" #include "gpiobus.h" #include "spdlog/spdlog.h" -//#include #include //--------------------------------------------------------------------------- @@ -24,31 +23,17 @@ // Constant declarations // //--------------------------------------------------------------------------- -#define CtrlMax 8 // Maximum number of SCSI controllers -#define UnitNum 2 // Number of units around controller -#ifdef BAREMETAL -#define FPRT(fp, ...) printf( __VA_ARGS__ ) -#else #define FPRT(fp, ...) fprintf(fp, __VA_ARGS__ ) -#endif // BAREMETAL //--------------------------------------------------------------------------- // // Variable declarations // //--------------------------------------------------------------------------- +static BYTE prev_value[32] = {0xFF}; static volatile BOOL running; // Running flag static volatile BOOL active; // Processing flag -SASIDEV *ctrl[CtrlMax]; // Controller -Disk *disk[CtrlMax * UnitNum]; // Disk GPIOBUS *bus; // GPIO Bus -#ifdef BAREMETAL -FATFS fatfs; // FatFS -#else -int monsocket; // Monitor Socket -pthread_t monthread; // Monitor Thread -static void *MonThread(void *param); -#endif // BAREMETAL typedef struct data_capture{ DWORD data; timeval timestamp; @@ -60,14 +45,21 @@ typedef struct data_capture{ data_capture data_buffer[MAX_BUFF_SIZE]; int data_idx = 0; +// 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 SECONDS_1 (1000 * 1000) -#define SECONDS_3 (3 * 1000 * 1000) -#define WAIT_FOR_EQUAL(x,y,timeout) { DWORD now = SysTimer::GetTimerLow(); while ((SysTimer::GetTimerLow() - now) < timeout) { bus->Aquire();if (x == y) {break;}}} - - -#ifndef BAREMETAL //--------------------------------------------------------------------------- // // Signal Processing @@ -78,7 +70,6 @@ void KillHandler(int sig) // Stop instruction running = FALSE; } -#endif // BAREMETAL //--------------------------------------------------------------------------- // @@ -87,7 +78,7 @@ void KillHandler(int sig) //--------------------------------------------------------------------------- void Banner(int argc, char* argv[]) { - FPRT(stdout,"SCSI Target Emulator RaSCSI(*^..^*) "); + FPRT(stdout,"SCSI Shark Capture Tool - part of RaSCSI(*^..^*) "); FPRT(stdout,"version %01d.%01d%01d(%s, %s)\n", (int)((VERSION >> 8) & 0xf), (int)((VERSION >> 4) & 0xf), @@ -96,30 +87,19 @@ void Banner(int argc, char* argv[]) __TIME__); FPRT(stdout,"Powered by XM6 TypeG Technology / "); FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n"); + FPRT(stdout,"Copyright (C) 2020 akuker\n"); FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); + FPRT(stdout,"\nPress CTRL-C to stop collecting data.\n"); + FPRT(stdout," log.csv - CSV listing of the data collected\n"); + FPRT(stdout," log.vcd - Value Change Dump file that can be opened with GTKWave\n"); + if ((argc > 1 && strcmp(argv[1], "-h") == 0) || (argc > 1 && strcmp(argv[1], "--help") == 0)){ FPRT(stdout,"\n"); - FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); - FPRT(stdout," n is SCSI identification number(0-7).\n"); - FPRT(stdout," FILE is disk image file.\n\n"); - FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]); - FPRT(stdout," n is X68000 SASI HD number(0-15).\n"); - FPRT(stdout," FILE is disk image file.\n\n"); - FPRT(stdout," Image type is detected based on file extension.\n"); - FPRT(stdout," hdf : SASI HD image(XM6 SASI HD image)\n"); - FPRT(stdout," hds : SCSI HD image(XM6 SCSI HD image)\n"); - FPRT(stdout," hdn : SCSI HD image(NEC GENUINE)\n"); - FPRT(stdout," hdi : SCSI HD image(Anex86 HD image)\n"); - FPRT(stdout," nhd : SCSI HD image(T98Next HD image)\n"); - FPRT(stdout," hda : SCSI HD image(APPLE GENUINE)\n"); - FPRT(stdout," mos : SCSI MO image(XM6 SCSI MO image)\n"); - FPRT(stdout," iso : SCSI CD image(ISO 9660 image)\n"); + FPRT(stdout,"Usage: %s ...\n\n", argv[0]); -#ifndef BAREMETAL exit(0); -#endif // BAREMETAL } } @@ -130,36 +110,6 @@ void Banner(int argc, char* argv[]) //--------------------------------------------------------------------------- BOOL Init() { - int i; - -#ifndef BAREMETAL - struct sockaddr_in server; - int yes; - - // Create socket for monitor - monsocket = socket(PF_INET, SOCK_STREAM, 0); - memset(&server, 0, sizeof(server)); - server.sin_family = PF_INET; - server.sin_port = htons(6868); - server.sin_addr.s_addr = htonl(INADDR_ANY); - - // allow address reuse - yes = 1; - if (setsockopt( - monsocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0){ - return FALSE; - } - - // Bind - if (bind(monsocket, (struct sockaddr *)&server, - sizeof(struct sockaddr_in)) < 0) { - FPRT(stderr, "Error : Already running?\n"); - return FALSE; - } - - // Create Monitor Thread - pthread_create(&monthread, NULL, MonThread, NULL); - // Interrupt handler settings if (signal(SIGINT, KillHandler) == SIG_ERR) { return FALSE; @@ -170,7 +120,6 @@ BOOL Init() if (signal(SIGTERM, KillHandler) == SIG_ERR) { return FALSE; } -#endif // BAREMETAL // GPIOBUS creation bus = new GPIOBUS(); @@ -183,16 +132,6 @@ BOOL Init() // Bus Reset bus->Reset(); - // Controller initialization - for (i = 0; i < CtrlMax; i++) { - ctrl[i] = NULL; - } - - // Disk Initialization - for (i = 0; i < CtrlMax; i++) { - disk[i] = NULL; - } - // Other running = FALSE; active = FALSE; @@ -200,40 +139,6 @@ BOOL Init() return TRUE; } -#define PIN_ACT 4 // ACTIVE -#define PIN_ENB 5 // ENABLE -#define PIN_IND -1 // INITIATOR CTRL DIRECTION -#define PIN_TAD -1 // TARGET CTRL DIRECTION -#define PIN_DTD -1 // DATA DIRECTION - -// Control signal output logic -#define ACT_ON TRUE // ACTIVE SIGNAL ON -#define ENB_ON TRUE // ENABLE SIGNAL ON -#define IND_IN FALSE // INITIATOR SIGNAL INPUT -#define TAD_IN FALSE // TARGET SIGNAL INPUT -#define DTD_IN TRUE // DATA SIGNAL INPUT - -// SCSI signal pin assignment -#define PIN_DT0 10 // Data 0 -#define PIN_DT1 11 // Data 1 -#define PIN_DT2 12 // Data 2 -#define PIN_DT3 13 // Data 3 -#define PIN_DT4 14 // Data 4 -#define PIN_DT5 15 // Data 5 -#define PIN_DT6 16 // Data 6 -#define PIN_DT7 17 // Data 7 -#define PIN_DP 18 // Data parity -#define PIN_ATN 19 // ATN -#define PIN_RST 20 // RST -#define PIN_ACK 21 // ACK -#define PIN_REQ 22 // REQ -#define PIN_MSG 23 // MSG -#define PIN_CD 24 // CD -#define PIN_IO 25 // IO -#define PIN_BSY 26 // BSY -#define PIN_SEL 27 // SEL - - BOOL get_pin_value(DWORD data, int pin) { return (data >> pin) & 1; @@ -256,88 +161,141 @@ BYTE get_data_field(DWORD data) } -int pin_nums[] = {PIN_BSY,PIN_SEL,PIN_CD,PIN_IO,PIN_MSG,PIN_REQ,PIN_ACK,PIN_ATN,PIN_RST,PIN_DT0}; +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); + } +} -std::string pin_names[] = {"BSY","SEL","CD","IO","MSG","REQ","ACK","ATN","RST","DAT"}; +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 dump_data() +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; + printf("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, "$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); + i++; + } + fclose(fp); +} + + + +void create_comma_separated_file() { int i = 0; timeval time_diff; FILE *fp; timeval start_time = data_buffer[0].timestamp; - fp = fopen("log.txt","w"); + printf("Creating log.csv\n"); + fp = fopen("log.csv","w"); - fprintf(fp, "idx\traw\ttimestamp\tBSY\tSEL\tC/D\tI/O\tMSG\tREQ\tACK\tATN\tRST\tData..\n"); + fprintf(fp, "idx,raw,timestamp,BSY,SEL,C/D,I/O,MSG,,REQ,ACK,ATN,RST,Data\n"); while(i < data_idx) { timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); - //timediff = difftime(data_buffer[i].timestamp, start_time); - fprintf(fp, "%d\t%08lX\t%ld:%ld\t",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_BSY)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_SEL)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_CD)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_IO)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_MSG)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_REQ)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ACK)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_ATN)); - fprintf(fp, "%d\t", get_pin_value(data_buffer[i].data, PIN_RST)); - fprintf(fp, "%02X\t", get_data_field(data_buffer[i].data)); + fprintf(fp, "%d,%08lX,%ld.%ld,",data_idx, data_buffer[i].data, time_diff.tv_sec, time_diff.tv_usec); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_BSY)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_SEL)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_CD)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_IO)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_MSG)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_REQ)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_ACK)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_ATN)); + fprintf(fp, "%d,", get_pin_value(data_buffer[i].data, PIN_RST)); + fprintf(fp, "%02X,", get_data_field(data_buffer[i].data)); fprintf(fp, "\n"); i++; } fclose(fp); - - - i=0; - printf("Creating timing_drawer.txt\n"); - fp = fopen("timing_drawer.txt","w"); - while(i < data_idx) - { - timersub(&(data_buffer[i].timestamp), &start_time, &time_diff); - //timediff = difftime(data_buffer[i].timestamp, start_time); - fprintf(fp, "TIME=%ld:%ld;", time_diff.tv_sec, time_diff.tv_usec); - fprintf(fp, "BSY=%d;", get_pin_value(data_buffer[i].data, PIN_BSY)); - fprintf(fp, "SEL=%d;", get_pin_value(data_buffer[i].data, PIN_SEL)); - fprintf(fp, "CD=%d;", get_pin_value(data_buffer[i].data, PIN_CD)); - fprintf(fp, "IO=%d;", get_pin_value(data_buffer[i].data, PIN_IO)); - fprintf(fp, "MSG=%d;", get_pin_value(data_buffer[i].data, PIN_MSG)); - fprintf(fp, "REQ=%d;", get_pin_value(data_buffer[i].data, PIN_REQ)); - fprintf(fp, "ACK=%d;", get_pin_value(data_buffer[i].data, PIN_ACK)); - fprintf(fp, "ATN=%d;", get_pin_value(data_buffer[i].data, PIN_ATN)); - fprintf(fp, "RST=%d;", get_pin_value(data_buffer[i].data, PIN_RST)); - fprintf(fp, "DATA=%02X.", get_data_field(data_buffer[i].data)); - fprintf(fp, "\n"); - i++; - } - fclose(fp); - - - -// -// fp = fopen("log2.txt","w"); -// -// for(int pin=0; pin < ARRAY_SIZE(pin_names); pin++) -// { -// i=0; -// while(i < data_idx) -// { -// char this_point = ((get_pin_value(data_buffer[i].data), pin_nums[pin]) == TRUE) ? "-", "_"; -// fprintf(fp, this_point) -// } -// -// -// -// -// } - - - - } @@ -349,31 +307,10 @@ void dump_data() //--------------------------------------------------------------------------- void Cleanup() { - int i; printf("In cleanup....\n"); - - - - dump_data(); - - - - // Delete the disks - for (i = 0; i < CtrlMax * UnitNum; i++) { - if (disk[i]) { - delete disk[i]; - disk[i] = NULL; - } - } - - // Delete the Controllers - for (i = 0; i < CtrlMax; i++) { - if (ctrl[i]) { - delete ctrl[i]; - ctrl[i] = NULL; - } - } + create_comma_separated_file(); + create_value_change_dump(); // Cleanup the Bus bus->Cleanup(); @@ -381,12 +318,6 @@ void Cleanup() // Discard the GPIOBUS object delete bus; -#ifndef BAREMETAL - // Close the monitor socket - if (monsocket >= 0) { - close(monsocket); - } -#endif // BAREMETAL } //--------------------------------------------------------------------------- @@ -396,611 +327,10 @@ void Cleanup() //--------------------------------------------------------------------------- void Reset() { - int i; - - // Reset all of the controllers - for (i = 0; i < CtrlMax; i++) { - if (ctrl[i]) { - ctrl[i]->Reset(); - } - } - // Reset the bus bus->Reset(); } -//--------------------------------------------------------------------------- -// -// List Devices -// -//--------------------------------------------------------------------------- -void ListDevice(FILE *fp) -{ - int i; - int id; - int un; - Disk *pUnit; - Filepath filepath; - BOOL find; - char type[5]; - - find = FALSE; - type[4] = 0; - for (i = 0; i < CtrlMax * UnitNum; i++) { - // Initialize ID and unit number - id = i / UnitNum; - un = i % UnitNum; - pUnit = disk[i]; - - // skip if unit does not exist or null disk - if (pUnit == NULL || pUnit->IsNULL()) { - continue; - } - - // Output the header - if (!find) { - FPRT(fp, "\n"); - FPRT(fp, "+----+----+------+-------------------------------------\n"); - FPRT(fp, "| ID | UN | TYPE | DEVICE STATUS\n"); - FPRT(fp, "+----+----+------+-------------------------------------\n"); - find = TRUE; - } - - // ID,UNIT,Type,Device Status - type[0] = (char)(pUnit->GetID() >> 24); - type[1] = (char)(pUnit->GetID() >> 16); - type[2] = (char)(pUnit->GetID() >> 8); - type[3] = (char)(pUnit->GetID()); - FPRT(fp, "| %d | %d | %s | ", id, un, type); - - // mount status output - if (pUnit->GetID() == MAKEID('S', 'C', 'B', 'R')) { - FPRT(fp, "%s", "HOST BRIDGE"); - } else { - pUnit->GetPath(filepath); - FPRT(fp, "%s", - (pUnit->IsRemovable() && !pUnit->IsReady()) ? - "NO MEDIA" : filepath.GetPath()); - } - - // Write protection status - if (pUnit->IsRemovable() && pUnit->IsReady() && pUnit->IsWriteP()) { - FPRT(fp, "(WRITEPROTECT)"); - } - - // Goto the next line - FPRT(fp, "\n"); - } - - // If there is no controller, find will be null - if (!find) { - FPRT(fp, "No device is installed.\n"); - return; - } - - FPRT(fp, "+----+----+------+-------------------------------------\n"); -} - -//--------------------------------------------------------------------------- -// -// Controller Mapping -// -//--------------------------------------------------------------------------- -void MapControler(FILE *fp, Disk **map) -{ - int i; - int j; - int unitno; - int sasi_num; - int scsi_num; - - // Replace the changed unit - for (i = 0; i < CtrlMax; i++) { - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - if (disk[unitno] != map[unitno]) { - // Check if the original unit exists - if (disk[unitno]) { - // Disconnect it from the controller - if (ctrl[i]) { - ctrl[i]->SetUnit(j, NULL); - } - - // Free the Unit - delete disk[unitno]; - } - - // Setup a new unit - disk[unitno] = map[unitno]; - } - } - } - - // Reconfigure all of the controllers - for (i = 0; i < CtrlMax; i++) { - // Examine the unit configuration - sasi_num = 0; - scsi_num = 0; - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - // branch by unit type - if (disk[unitno]) { - if (disk[unitno]->IsSASI()) { - // Drive is SASI, so increment SASI count - sasi_num++; - } else { - // Drive is SCSI, so increment SCSI count - scsi_num++; - } - } - - // Remove the unit - if (ctrl[i]) { - ctrl[i]->SetUnit(j, NULL); - } - } - - // If there are no units connected - if (sasi_num == 0 && scsi_num == 0) { - if (ctrl[i]) { - delete ctrl[i]; - ctrl[i] = NULL; - continue; - } - } - - // Mixture of SCSI and SASI - if (sasi_num > 0 && scsi_num > 0) { - FPRT(fp, "Error : SASI and SCSI can't be mixed\n"); - continue; - } - - if (sasi_num > 0) { - // Only SASI Unit(s) - - // Release the controller if it is not SASI - if (ctrl[i] && !ctrl[i]->IsSASI()) { - delete ctrl[i]; - ctrl[i] = NULL; - } - - // Create a new SASI controller - if (!ctrl[i]) { - ctrl[i] = new SASIDEV(); - ctrl[i]->Connect(i, bus); - } - } else { - // Only SCSI Unit(s) - - // Release the controller if it is not SCSI - if (ctrl[i] && !ctrl[i]->IsSCSI()) { - delete ctrl[i]; - ctrl[i] = NULL; - } - - // Create a new SCSI controller - if (!ctrl[i]) { - ctrl[i] = new SCSIDEV(); - ctrl[i]->Connect(i, bus); - } - } - - // connect all units - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - if (disk[unitno]) { - // Add the unit connection - ctrl[i]->SetUnit(j, disk[unitno]); - } - } - } -} - -//--------------------------------------------------------------------------- -// -// Command Processing -// -//--------------------------------------------------------------------------- -BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file) -{ - Disk *map[CtrlMax * UnitNum]; - int len; - char *ext; - Filepath filepath; - Disk *pUnit; - - // Copy the Unit List - memcpy(map, disk, sizeof(disk)); - - // Check the Controller Number - if (id < 0 || id >= CtrlMax) { - FPRT(fp, "Error : Invalid ID\n"); - return FALSE; - } - - // Check the Unit Number - if (un < 0 || un >= UnitNum) { - FPRT(fp, "Error : Invalid unit number\n"); - return FALSE; - } - - // Connect Command - if (cmd == 0) { // ATTACH - // Distinguish between SASI and SCSI - ext = NULL; - pUnit = NULL; - if (type == 0) { - // Passed the check - if (!file) { - return FALSE; - } - - // Check that command is at least 5 characters long - len = strlen(file); - if (len < 5) { - return FALSE; - } - - // Check the extension - if (file[len - 4] != '.') { - return FALSE; - } - - // If the extension is not SASI type, replace with SCSI - ext = &file[len - 3]; - if (xstrcasecmp(ext, "hdf") != 0) { - type = 1; - } - } - - // Create a new drive, based upon type - switch (type) { - case 0: // HDF - pUnit = new SASIHD(); - break; - case 1: // HDS/HDN/HDI/NHD/HDA - if (ext == NULL) { - break; - } - if (xstrcasecmp(ext, "hdn") == 0 || - xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0) { - pUnit = new SCSIHD_NEC(); - } else if (xstrcasecmp(ext, "hda") == 0) { - pUnit = new SCSIHD_APPLE(); - } else { - pUnit = new SCSIHD(); - } - break; - case 2: // MO - pUnit = new SCSIMO(); - break; - case 3: // CD - pUnit = new SCSICD(); - break; - case 4: // BRIDGE - pUnit = new SCSIBR(); - break; - default: - FPRT(fp, "Error : Invalid device type\n"); - return FALSE; - } - - // drive checks files - if (type <= 1 || (type <= 3 && xstrcasecmp(file, "-") != 0)) { - // Set the Path - filepath.SetPath(file); - - // Open the file path - if (!pUnit->Open(filepath)) { - FPRT(fp, "Error : File open error [%s]\n", file); - delete pUnit; - return FALSE; - } - } - - // Set the cache to write-through - pUnit->SetCacheWB(FALSE); - - // Replace with the newly created unit - map[id * UnitNum + un] = pUnit; - - // Re-map the controller - MapControler(fp, map); - return TRUE; - } - - // Is this a valid command? - if (cmd > 4) { - FPRT(fp, "Error : Invalid command\n"); - return FALSE; - } - - // Does the controller exist? - if (ctrl[id] == NULL) { - FPRT(fp, "Error : No such device\n"); - return FALSE; - } - - // Does the unit exist? - pUnit = disk[id * UnitNum + un]; - if (pUnit == NULL) { - FPRT(fp, "Error : No such device\n"); - return FALSE; - } - - // Disconnect Command - if (cmd == 1) { // DETACH - // Free the existing unit - map[id * UnitNum + un] = NULL; - - // Re-map the controller - MapControler(fp, map); - return TRUE; - } - - // Valid only for MO or CD - if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O') && - pUnit->GetID() != MAKEID('S', 'C', 'C', 'D')) { - FPRT(fp, "Error : Operation denied(Deveice isn't removable)\n"); - return FALSE; - } - - switch (cmd) { - case 2: // INSERT - // Set the file path - filepath.SetPath(file); - - // Open the file - if (!pUnit->Open(filepath)) { - FPRT(fp, "Error : File open error [%s]\n", file); - return FALSE; - } - break; - - case 3: // EJECT - pUnit->Eject(TRUE); - break; - - case 4: // PROTECT - if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O')) { - FPRT(fp, "Error : Operation denied(Deveice isn't MO)\n"); - return FALSE; - } - pUnit->WriteP(!pUnit->IsWriteP()); - break; - default: - ASSERT(FALSE); - return FALSE; - } - - return TRUE; -} - -//--------------------------------------------------------------------------- -// -// Argument Parsing -// -//--------------------------------------------------------------------------- -BOOL ParseArgument(int argc, char* argv[]) -{ -#ifdef BAREMETAL - FRESULT fr; - FIL fp; - char line[512]; -#else - int i; -#endif // BAREMETAL - int id; - int un; - int type; - char *argID; - char *argPath; - int len; - char *ext; - -#ifdef BAREMETAL - // Mount the SD card - fr = f_mount(&fatfs, "", 1); - if (fr != FR_OK) { - FPRT(stderr, "Error : SD card mount failed.\n"); - return FALSE; - } - - // If there is no setting file, the processing is interrupted - fr = f_open(&fp, "rascsi.ini", FA_READ); - if (fr != FR_OK) { - return FALSE; - } -#else - // If the ID and path are not specified, the processing is interrupted - if (argc < 3) { - return TRUE; - } - i = 1; - argc--; -#endif // BAREMETAL - - // Start Decoding - - while (TRUE) { -#ifdef BAREMETAL - // Get one Line - memset(line, 0x00, sizeof(line)); - if (f_gets(line, sizeof(line) -1, &fp) == NULL) { - break; - } - - // Delete the CR/LF - len = strlen(line); - while (len > 0) { - if (line[len - 1] != '\r' && line[len - 1] != '\n') { - break; - } - line[len - 1] = '\0'; - len--; - } -#else - if (argc < 2) { - break; - } - - argc -= 2; -#endif // BAREMETAL - - // Get the ID and Path -#ifdef BAREMETAL - argID = &line[0]; - argPath = &line[4]; - line[3] = '\0'; - - // Check if the line is an empty string - if (argID[0] == '\0' || argPath[0] == '\0') { - continue; - } -#else - argID = argv[i++]; - argPath = argv[i++]; - - // Check if the argument is invalid - if (argID[0] != '-') { - FPRT(stderr, - "Error : Invalid argument(-IDn or -HDn) [%s]\n", argID); - goto parse_error; - } - argID++; -#endif // BAREMETAL - - if (strlen(argID) == 3 && xstrncasecmp(argID, "id", 2) == 0) { - // ID or ID Format - - // Check that the ID number is valid (0-7) - if (argID[2] < '0' || argID[2] > '7') { - FPRT(stderr, - "Error : Invalid argument(IDn n=0-7) [%c]\n", argID[2]); - goto parse_error; - } - - // The ID unit is good - id = argID[2] - '0'; - un = 0; - } else if (xstrncasecmp(argID, "hd", 2) == 0) { - // HD or HD format - - if (strlen(argID) == 3) { - // Check that the HD number is valid (0-9) - if (argID[2] < '0' || argID[2] > '9') { - FPRT(stderr, - "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); - goto parse_error; - } - - // ID was confirmed - id = (argID[2] - '0') / UnitNum; - un = (argID[2] - '0') % UnitNum; - } else if (strlen(argID) == 4) { - // Check that the HD number is valid (10-15) - if (argID[2] != '1' || argID[3] < '0' || argID[3] > '5') { - FPRT(stderr, - "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); - goto parse_error; - } - - // The ID unit is good - create the id and unit number - id = ((argID[3] - '0') + 10) / UnitNum; - un = ((argID[3] - '0') + 10) % UnitNum; -#ifdef BAREMETAL - argPath++; -#endif // BAREMETAL - } else { - FPRT(stderr, - "Error : Invalid argument(IDn or HDn) [%s]\n", argID); - goto parse_error; - } - } else { - FPRT(stderr, - "Error : Invalid argument(IDn or HDn) [%s]\n", argID); - goto parse_error; - } - - // Skip if there is already an active device - if (disk[id * UnitNum + un] && - !disk[id * UnitNum + un]->IsNULL()) { - continue; - } - - // Initialize device type - type = -1; - - // Check ethernet and host bridge - if (xstrcasecmp(argPath, "bridge") == 0) { - type = 4; - } else { - // Check the path length - len = strlen(argPath); - if (len < 5) { - FPRT(stderr, - "Error : Invalid argument(File path is short) [%s]\n", - argPath); - goto parse_error; - } - - // Does the file have an extension? - if (argPath[len - 4] != '.') { - FPRT(stderr, - "Error : Invalid argument(No extension) [%s]\n", argPath); - goto parse_error; - } - - // Figure out what the type is - ext = &argPath[len - 3]; - if (xstrcasecmp(ext, "hdf") == 0 || - xstrcasecmp(ext, "hds") == 0 || - xstrcasecmp(ext, "hdn") == 0 || - xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 || - xstrcasecmp(ext, "hda") == 0) { - // HD(SASI/SCSI) - type = 0; - } else if (strcasecmp(ext, "mos") == 0) { - // MO - type = 2; - } else if (strcasecmp(ext, "iso") == 0) { - // CD - type = 3; - } else { - // Cannot determine the file type - FPRT(stderr, - "Error : Invalid argument(file type) [%s]\n", ext); - goto parse_error; - } - } - - // Execute the command - if (!ProcessCmd(stderr, id, un, 0, type, argPath)) { - goto parse_error; - } - } - -#ifdef BAREMETAL - // Close the configuration file - f_close(&fp); -#endif // BAREMETAL - - // Display the device list - ListDevice(stdout); - - return TRUE; - -parse_error: - -#ifdef BAREMETAL - // Close the configuration file - f_close(&fp); -#endif // BAREMETAL - - return FALSE; -} - -#ifndef BAREMETAL //--------------------------------------------------------------------------- // // Pin the thread to a specific CPU @@ -1024,122 +354,6 @@ void FixCpu(int cpu) } } -//--------------------------------------------------------------------------- -// -// Monitor Thread -// -//--------------------------------------------------------------------------- -static void *MonThread(void *param) -{ - struct sched_param schedparam; - struct sockaddr_in client; - socklen_t len; - int fd; - FILE *fp; - char buf[BUFSIZ]; - char *p; - int i; - char *argv[5]; - int id; - int un; - int cmd; - int type; - char *file; - - // Scheduler Settings - schedparam.sched_priority = 0; - sched_setscheduler(0, SCHED_IDLE, &schedparam); - - // Set the affinity to a specific processor core - FixCpu(2); - - // Wait for the execution to start - while (!running) { - usleep(1); - } - - // Setup the monitor socket to receive commands - listen(monsocket, 1); - - while (1) { - // Wait for connection - memset(&client, 0, sizeof(client)); - len = sizeof(client); - fd = accept(monsocket, (struct sockaddr*)&client, &len); - if (fd < 0) { - break; - } - - // Fetch the command - fp = fdopen(fd, "r+"); - p = fgets(buf, BUFSIZ, fp); - - // Failed to get the command - if (!p) { - goto next; - } - - // Remove the newline character - p[strlen(p) - 1] = 0; - - // List all of the devices - if (xstrncasecmp(p, "list", 4) == 0) { - ListDevice(fp); - goto next; - } - - // Parameter separation - argv[0] = p; - for (i = 1; i < 5; i++) { - // Skip parameter values - while (*p && (*p != ' ')) { - p++; - } - - // Replace spaces with null characters - while (*p && (*p == ' ')) { - *p++ = 0; - } - - // The parameters were lost - if (!*p) { - break; - } - - // Recognized as a parameter - argv[i] = p; - } - - // Failed to get all parameters - if (i < 5) { - goto next; - } - - // ID, unit, command, type, file - id = atoi(argv[0]); - un = atoi(argv[1]); - cmd = atoi(argv[2]); - type = atoi(argv[3]); - file = argv[4]; - - // Wait until we becom idle - while (active) { - usleep(500 * 1000); - } - - // Execute the command - ProcessCmd(fp, id, un, cmd, type, file); - -next: - // Release the connection - fclose(fp); - close(fd); - } - - return NULL; -} -#endif // BAREMETAL - static DWORD high_bits = 0x0; static DWORD low_bits = 0xFFFFFFFF; @@ -1163,15 +377,8 @@ int main(int argc, char* argv[]) DWORD prev_low = low_bits; DWORD prev_sample = 0xFFFFFFFF; DWORD this_sample = 0; - //int i; int ret; -// int actid; - //DWORD now; - //BUS::phase_t phase; -// BYTE data; -#ifndef BAREMETAL - struct sched_param schparam; -#endif // BAREMETAL + struct sched_param schparam; spdlog::set_level(spdlog::level::trace); spdlog::trace("Entering the function with {0:x}{1:X} arguments", argc,20); @@ -1189,32 +396,12 @@ int main(int argc, char* argv[]) // Reset Reset(); -#ifdef BAREMETAL - // BUSY assert (to hold the host side) - bus->SetBSY(TRUE); -#endif - - // Argument parsing - if (!ParseArgument(argc, argv)) { - ret = EINVAL; - goto err_exit; - } - -#ifdef BAREMETAL - // Release the busy signal - bus->SetBSY(FALSE); -#endif - -#ifndef BAREMETAL // Set the affinity to a specific processor core FixCpu(3); -#ifdef USE_SEL_EVENT_ENABLE // Scheduling policy setting (highest priority) schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); sched_setscheduler(0, SCHED_FIFO, &schparam); -#endif // USE_SEL_EVENT_ENABLE -#endif // BAREMETAL // Start execution running = TRUE; @@ -1249,226 +436,12 @@ int main(int argc, char* argv[]) prev_sample = this_sample; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - continue; -//////// -//////// // Target sending data -//////// if(!bus->GetIO() && bus->GetREQ() && bus->GetACK()) -//////// { -//////// BYTE data = bus->GetDAT(); -//////// printf("+%02X ",data); -//////// -//////// -//////// -//////// DWORD now = SysTimer::GetTimerLow(); -//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) -//////// { -//////// bus->Aquire(); -//////// if (bus->GetACK() == FALSE) { -//////// break; -//////// } -//////// } -//////// -//////// if(bus->GetACK() != FALSE) -//////// { -//////// spdlog::warn("got an invalid req/ack sequence for target sending data"); -//////// } -//////// } -//////// -//////// -//////// -//////// if(bus->GetIO() && bus->GetREQ() && !bus->GetACK()) -//////// { -//////// BYTE data = bus->GetDAT(); -//////// printf("-%02X ",data); -//////// -//////// -//////// DWORD now = SysTimer::GetTimerLow(); -//////// while ((SysTimer::GetTimerLow() - now) < SECONDS_1/100) -//////// { -//////// bus->Aquire(); -//////// if (bus->GetREQ() == FALSE) { -//////// break; -//////// } -//////// } -//////// -//////// if(bus->GetREQ() != TRUE) -//////// { -//////// spdlog::warn("REQ didn't de-assert when I wanted it to."); -//////// } -//////// -//////// -//////// } -//////// -//////// continue; -//////// -//////// // Wait until BSY is released as there is a possibility for the -//////// // initiator to assert it while setting the ID (for up to 3 seconds) -//////// if (bus->GetSEL() ) { -//////// BYTE data = bus->GetDAT(); -//////// printf("SEL is asserted. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); -//////// now = SysTimer::GetTimerLow(); -//////// while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) { -//////// bus->Aquire(); -//////// if (!bus->GetSEL()) { -//////// printf("SEL is clear. Data: %02X, BSY: %d, SEL %d\n", data, bus->GetBSY(), bus->GetSEL()); -//////// break; -//////// } -//////// } -//////// } -//////// else{ -//////// -//////// continue; -//////// } -////////// spdlog::trace("Busy: {}",bus->GetBSY()); -//////// -//////// -//////// // For monitor mode, we just want to make sure the initiator -//////// // released the BSY signal within 3 seconds. If it hasn't -//////// // the initiator is misbehaving -////////// if (bus->GetBSY()) { -////////// spdlog::warn("The initiator (%d) did not release the BSY signal after 3 seconds", bus->GetDAT()); -////////// continue; -////////// } -//////// -////////////////////// -////////////////////// // Stop because it the bus is busy or another device responded -////////////////////// if (bus->GetBSY() || !bus->GetSEL()) { -////////////////////// continue; -////////////////////// } -// -// // Notify all controllers -// data = bus->GetDAT(); -//// spdlog::trace("Data is {x}",data); -// for (i = 0; i < CtrlMax; i++) { -// if (!ctrl[i] || (data & (1 << i)) == 0) { -// continue; -// } -//// spdlog::trace("Found an active controller! Let's do some selection {}", i); -// // Find the target that has moved to the selection phase -// if (ctrl[i]->Process() == BUS::selection) { -// // Get the target ID -// actid = i; -// -// // Bus Selection phase -// phase = BUS::selection; -// break; -// } -// } -// -// // Return to bus monitoring if the selection phase has not started -// if (phase != BUS::selection) { -// continue; -// } -// -// // Start target device -// active = TRUE; -// spdlog::trace("Found a target device {} ID:{}",actid, ctrl[actid]->GetID()); -// -//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) -// // Scheduling policy setting (highest priority) -// schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); -// sched_setscheduler(0, SCHED_FIFO, &schparam); -//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL -// -// // Loop until the bus is free -// while (running) { -// // Target drive -// phase = ctrl[actid]->Process(); -// -// // End when the bus is free -// if (phase == BUS::busfree) { -// break; -// } -// } -// -//#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL) -// // Set the scheduling priority back to normal -// schparam.sched_priority = 0; -// sched_setscheduler(0, SCHED_OTHER, &schparam); -//#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL -// -// // End the target travel -// active = FALSE; } -err_exit: // Cleanup Cleanup(); init_exit: -#if !defined(BAREMETAL) exit(ret); -#else - return ret; -#endif // BAREMETAL } From 7b10c2299fc82dd987548547d5fdfda18018056c Mon Sep 17 00:00:00 2001 From: akuker Date: Sun, 19 Jul 2020 00:24:07 -0500 Subject: [PATCH 09/12] Updated git ignore for scsishark --- src/raspberrypi/.gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/raspberrypi/.gitignore b/src/raspberrypi/.gitignore index c5fb48a..0067677 100644 --- a/src/raspberrypi/.gitignore +++ b/src/raspberrypi/.gitignore @@ -6,7 +6,9 @@ *.layout *.log rascsi -scsimon +scsishark rasctl sasidump rasdump +log.* + From a033451863738b30acfa617f91c3f3f7354af145 Mon Sep 17 00:00:00 2001 From: akuker Date: Sun, 19 Jul 2020 14:59:40 -0500 Subject: [PATCH 10/12] Un-do extraneous changes before merging back into source branch --- src/raspberrypi/convert_data.py | 65 --------------------------------- src/raspberrypi/disk.cpp | 51 +++++++------------------- src/raspberrypi/gpiobus.h | 41 ++++++++++----------- src/raspberrypi/log.h | 3 ++ src/raspberrypi/rascsi.cpp | 1 - 5 files changed, 36 insertions(+), 125 deletions(-) delete mode 100644 src/raspberrypi/convert_data.py diff --git a/src/raspberrypi/convert_data.py b/src/raspberrypi/convert_data.py deleted file mode 100644 index a57d1a5..0000000 --- a/src/raspberrypi/convert_data.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/python - -import sys - -outfile = open('data.json', 'w') -infile = open('timing_drawer.txt','r') - -print("{signal: [", file=outfile) -firstline = infile.readline() - -num_columns = len(firstline.split(";")) - -# Skip the time field -field_num = 1 - -while (field_num < num_columns): - var = firstline.split(";") - var2 = var[field_num].split("=") - field_name = var2[0] - infile.seek(0) - print(" {name: '" + field_name + "', wave: '", file=outfile, end='') - prev_val = '' - if (field_name == "DATA"): - for line in infile: - value_pair = line.split(";")[field_num] - z = value_pair.split("=")[1].strip().replace(".","") - if(z == prev_val): - out = '.' - prev_val = z - elif (z == '00'): - out = '0' - else: - out = '2' - print(out, file=outfile, end='') - prev_val = z - print("', data: [", file=outfile, end='') - infile.seek(0) - for line in infile: - value_pair = line.split(";")[field_num] - z = value_pair.split("=")[1].strip().replace(".","") - if(z == prev_val): - continue - print("'" + z + "', ", file=outfile, end='') - prev_val = z - print("]},", file=outfile) - else: - for line in infile: - value_pair = line.split(";")[field_num] - z = value_pair.split("=")[1] - if(z == prev_val): - z = '.' - else: - prev_val = z - print(z, file=outfile, end='') - - print("'},", file=outfile) - - field_num = field_num + 1 - -print("]}", file=outfile) - - -outfile.close() - - diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index cda94ef..06ac18b 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -43,14 +43,6 @@ // Disk // //=========================================================================== -#ifndef DISK_LOG -#define DISK_LOG -#endif // DISK_LOG -#ifndef RASCSI -#define RASCSI -#endif // RASCSI - - #ifdef RASCSI #define BENDER_SIGNATURE "RaSCSI" @@ -6447,16 +6439,14 @@ void FASTCALL SASIDEV::Selection() return; } - // Wait for this monitor target to assert the selection - // before moving on to the selection phase. - if(ctrl.bus->GetBSY()) - { - // Phase change - ctrl.phase = BUS::selection; - spdlog::trace( - "[ID %d] Selection Phase (with device)", ctrl.id); - } + spdlog::trace( + "Selection Phase ID=%d (with device)", ctrl.id); + // Phase change + ctrl.phase = BUS::selection; + + // Raise BSY and respond + ctrl.bus->SetBSY(TRUE); return; } @@ -6495,14 +6485,6 @@ void FASTCALL SASIDEV::Command() ctrl.bus->SetCD(TRUE); ctrl.bus->SetIO(FALSE); - // Wait until target sets the following condition: - // MSG = FALSE - // CD = TRUE - // IO = FALSE - if (ctrl.bus->GetMSG() || !ctrl.bus->GetCD() || ctrl.bus->GetIO()) { - return; - } - // Data transfer is 6 bytes x 1 block ctrl.offset = 0; ctrl.length = 6; @@ -8037,7 +8019,6 @@ BUS::phase_t FASTCALL SCSIDEV::Process() return ctrl.phase; } -// spdlog::trace("ID {} in phase {}",ctrl.id,ctrl.phase); // Phase processing switch (ctrl.phase) { // Bus free phase @@ -8162,20 +8143,14 @@ void FASTCALL SCSIDEV::Selection() return; } + spdlog::trace( + "Selection Phase ID={} (with device)", ctrl.id); + + // Phase setting ctrl.phase = BUS::selection; - // Wait for this monitor target to assert the selection - // before moving on to the selection phase. - if(ctrl.bus->GetBSY()) - { - // Phase change - spdlog::trace( - "[ID {} Selection Phase (with device)", ctrl.id); - } - else{ - spdlog::trace("[ID {}] Selection phase", ctrl.id); - } - + // Raise BSY and respond + ctrl.bus->SetBSY(TRUE); return; } diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h index 3e1b844..9d269e1 100644 --- a/src/raspberrypi/gpiobus.h +++ b/src/raspberrypi/gpiobus.h @@ -141,25 +141,6 @@ #define PIN_BSY 26 // BSY #define PIN_SEL 27 // SEL -#define ALL_SCSI_PINS \ - ((1< Date: Sun, 19 Jul 2020 15:05:24 -0500 Subject: [PATCH 11/12] Un-do extraneous changes before merging back into source branch --- src/raspberrypi/disk.cpp | 4 ++-- src/raspberrypi/rascsi.cpp | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index 06ac18b..bc845f9 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -8151,8 +8151,8 @@ void FASTCALL SCSIDEV::Selection() // Raise BSY and respond ctrl.bus->SetBSY(TRUE); - return; - } + return; + } // Selection completed if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index cf2f68f..58324c9 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -15,6 +15,7 @@ #include "fileio.h" #include "disk.h" #include "gpiobus.h" +#include "spdlog/spdlog.h" //--------------------------------------------------------------------------- // @@ -995,6 +996,9 @@ int main(int argc, char* argv[]) struct sched_param schparam; #endif // BAREMETAL + spdlog::set_level(spdlog::level::trace); + spdlog::trace("Entering the function with %d arguments", argc); + // Output the Banner Banner(argc, argv); From 52ba5c2fa75228f7e219b159df2388c0c4e222c4 Mon Sep 17 00:00:00 2001 From: akuker Date: Sun, 19 Jul 2020 15:10:17 -0500 Subject: [PATCH 12/12] Un-do extraneous changes before merging back into source branch --- src/raspberrypi/disk.cpp | 33 ++++++++++++++++----------------- src/raspberrypi/rascsi.cpp | 1 - 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index bc845f9..483487a 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -6439,14 +6439,14 @@ void FASTCALL SASIDEV::Selection() return; } - spdlog::trace( - "Selection Phase ID=%d (with device)", ctrl.id); + spdlog::trace( + "Selection Phase ID=%d (with device)", ctrl.id); - // Phase change - ctrl.phase = BUS::selection; + // Phase change + ctrl.phase = BUS::selection; - // Raise BSY and respond - ctrl.bus->SetBSY(TRUE); + // Raise BSY and respond + ctrl.bus->SetBSY(TRUE); return; } @@ -8133,26 +8133,25 @@ void FASTCALL SCSIDEV::Selection() // invalid if IDs do not match id = 1 << ctrl.id; if ((ctrl.bus->GetDAT() & id) == 0) { - spdlog::trace("[ID {}] ID doesn't match {}",ctrl.id,id); + spdlog::trace("[ID {}] ID doesn't match {}",ctrl.id,id); return; } // End if there is no valid unit if (!HasUnit()) { - spdlog::trace("[ID {}] No unit attached",ctrl.id); + spdlog::trace("[ID {}] No unit attached",ctrl.id); return; } + + spdlog::trace("Selection Phase ID={} (with device)", ctrl.id); - spdlog::trace( - "Selection Phase ID={} (with device)", ctrl.id); + // Phase setting + ctrl.phase = BUS::selection; - // Phase setting - ctrl.phase = BUS::selection; - - // Raise BSY and respond - ctrl.bus->SetBSY(TRUE); - return; - } + // Raise BSY and respond + ctrl.bus->SetBSY(TRUE); + return; + } // Selection completed if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 58324c9..16221d2 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -998,7 +998,6 @@ int main(int argc, char* argv[]) spdlog::set_level(spdlog::level::trace); spdlog::trace("Entering the function with %d arguments", argc); - // Output the Banner Banner(argc, argv);