From: Michael McMaster Date: Mon, 20 Apr 2015 06:09:51 +0000 (+1000) Subject: Small compatibility improvements, and added scsi2sd-monitor test program X-Git-Tag: v4.02.02^0 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=9ad7cc15d0af9c62e642fc7431ab15b3ac66113d;p=SCSI2SD-V6.git Small compatibility improvements, and added scsi2sd-monitor test program --- diff --git a/CHANGELOG b/CHANGELOG index cf022b57..423d64ea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,7 @@ -201501?? 4.1.1 +20150420 4.2.2 + - Improved compatibility with older SCSI1 hosts. + +20150123 4.1.1 - Fix MODE SENSE bug when the allocation length is less than the page size. - Add WRITE BUFFER and WRITE AND VERIFY support. diff --git a/readme.txt b/readme.txt index 1c22fde7..11c43482 100644 --- a/readme.txt +++ b/readme.txt @@ -13,7 +13,6 @@ computer and a modern PC (who still has access to a working floppy drive ?) Features In-built active terminator. - Can optional supply terminator power back to the SCSI bus Emulates up to 4 SCSI devices Supports sector sizes from 64 bytes to 8192 bytes Firmware updatable over USB @@ -95,6 +94,8 @@ Samplers SCSI cable reversed on S3200 There are compatibility problems with the Akai MPC3000. It works (slowly) with the alternate Vailixi OS with multi-sector transfers disabled. EMU Emulator E4X with EOS 3.00b and E6400 (classic) with Eos 4.01 + EMU E6400 w/ EOS2.80f + EMU Emax2 Ensoniq ASR-X, ASR-10 (from v3.4, 2GB size limit) ASR-20 Requires TERMPWR jumper. ASR-X resets when writing to devices > 2Gb. @@ -113,3 +114,5 @@ Other Reftek RT-72A Seismic datalogger. http://www.iris.iris.edu/passcal/Reftek/72A-R-005-00.1.pdf http://www.iris.iris.edu/passcal/Manual/rtfm.s3a.13.html + Konami Simpson's Bowling arcade machine + http://forums.arcade-museum.com/showthread.php?p=3027446 diff --git a/software/SCSI2SD/src/config.c b/software/SCSI2SD/src/config.c index 6178b9fb..732d4c47 100755 --- a/software/SCSI2SD/src/config.c +++ b/software/SCSI2SD/src/config.c @@ -32,7 +32,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0411; +static const uint16_t FIRMWARE_VERSION = 0x0422; enum USB_ENDPOINTS { @@ -53,8 +53,30 @@ static int usbInEpState; static int usbDebugEpState; static int usbReady; +uint8_t DEFAULT_CONFIG[256] + __attribute__ ((section(".DEFAULT_CONFIG"))) = +{ + CONFIG_TARGET_ENABLED, + CONFIG_FIXED, + 0, + 0, + 0, 0, 0, 0, + 0xff, 0xff, 0x3f, 0x00, // 4194303, 2GB - 1 sector + 0x00, 0x02, //512 + 63, 0, + 255, 0, + ' ', 'c', 'o', 'd', 'e', 's', 'r', 'c', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'S', 'C', 'S', 'I', '2', 'S', 'D', + ' ', '4', '.', '2', + '1','2','3','4','5','6','7','8','1','2','3','4','5','6','7','8' +}; +// otherwise linker removes unused section. +volatile uint8_t trickLinker; + void configInit() { + trickLinker = DEFAULT_CONFIG[0]; + // The USB block will be powered by an internal 3.3V regulator. // The PSoC must be operating between 4.6V and 5V for the regulator // to work. @@ -132,6 +154,20 @@ sdInfoCommand() hidPacket_send(response, sizeof(response)); } + + +static void +scsiTestCommand() +{ + int resultCode = scsiSelfTest(); + uint8_t response[] = + { + resultCode == 0 ? CONFIG_STATUS_GOOD : CONFIG_STATUS_ERR, + resultCode + }; + hidPacket_send(response, sizeof(response)); +} + static void processCommand(const uint8_t* cmd, size_t cmdSize) { @@ -157,6 +193,10 @@ processCommand(const uint8_t* cmd, size_t cmdSize) sdInfoCommand(); break; + case CONFIG_SCSITEST: + scsiTestCommand(); + break; + case CONFIG_NONE: // invalid default: break; diff --git a/software/SCSI2SD/src/disk.c b/software/SCSI2SD/src/disk.c index af1c50a9..5b6a70d0 100755 --- a/software/SCSI2SD/src/disk.c +++ b/software/SCSI2SD/src/disk.c @@ -728,7 +728,7 @@ void scsiDiskPoll() { if (scsiDev.parityError && (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) && - !scsiDev.compatMode) + (scsiDev.compatMode >= COMPAT_SCSI2)) { scsiDev.target->sense.code = ABORTED_COMMAND; scsiDev.target->sense.asc = SCSI_PARITY_ERROR; diff --git a/software/SCSI2SD/src/mode.c b/software/SCSI2SD/src/mode.c index c66608ac..4ed790f4 100755 --- a/software/SCSI2SD/src/mode.c +++ b/software/SCSI2SD/src/mode.c @@ -145,231 +145,224 @@ static void pageIn(int pc, int dataIdx, const uint8* pageData, int pageLen) static void doModeSense( int sixByteCmd, int dbd, int pc, int pageCode, int allocLength) { - if (pc == 0x03) // Saved Values not supported. + ////////////// Mode Parameter Header + //////////////////////////////////// + + // Skip the Mode Data Length, we set that last. + int idx = 1; + if (!sixByteCmd) ++idx; + + uint8_t mediumType = 0; + uint8_t deviceSpecificParam = 0; + uint8_t density = 0; + switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL) { - scsiDev.status = CHECK_CONDITION; - scsiDev.target->sense.code = ILLEGAL_REQUEST; - scsiDev.target->sense.asc = SAVING_PARAMETERS_NOT_SUPPORTED; - scsiDev.phase = STATUS; + case CONFIG_FIXED: + case CONFIG_REMOVEABLE: + mediumType = 0; // We should support various floppy types here! + // Contains cache bits (0) and a Write-Protect bit. + deviceSpecificParam = + (blockDev.state & DISK_WP) ? 0x80 : 0; + density = 0; // reserved for direct access + break; + + case CONFIG_FLOPPY_14MB: + mediumType = 0x1E; // 90mm/3.5" + deviceSpecificParam = + (blockDev.state & DISK_WP) ? 0x80 : 0; + density = 0; // reserved for direct access + break; + + case CONFIG_OPTICAL: + mediumType = 0x02; // 120mm CDROM, data only. + deviceSpecificParam = 0; + density = 0x01; // User data only, 2048bytes per sector. + break; + + }; + + scsiDev.data[idx++] = mediumType; + scsiDev.data[idx++] = deviceSpecificParam; + + if (sixByteCmd) + { + if (dbd) + { + scsiDev.data[idx++] = 0; // No block descriptor + } + else + { + // One block descriptor of length 8 bytes. + scsiDev.data[idx++] = 8; + } } else { - ////////////// Mode Parameter Header - //////////////////////////////////// - - // Skip the Mode Data Length, we set that last. - int idx = 1; - if (!sixByteCmd) ++idx; - - uint8_t mediumType = 0; - uint8_t deviceSpecificParam = 0; - uint8_t density = 0; - switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL) - { - case CONFIG_FIXED: - case CONFIG_REMOVEABLE: - mediumType = 0; // We should support various floppy types here! - // Contains cache bits (0) and a Write-Protect bit. - deviceSpecificParam = - (blockDev.state & DISK_WP) ? 0x80 : 0; - density = 0; // reserved for direct access - break; - - case CONFIG_FLOPPY_14MB: - mediumType = 0x1E; // 90mm/3.5" - deviceSpecificParam = - (blockDev.state & DISK_WP) ? 0x80 : 0; - density = 0; // reserved for direct access - break; - - case CONFIG_OPTICAL: - mediumType = 0x02; // 120mm CDROM, data only. - deviceSpecificParam = 0; - density = 0x01; // User data only, 2048bytes per sector. - break; - - }; - - scsiDev.data[idx++] = mediumType; - scsiDev.data[idx++] = deviceSpecificParam; - - if (sixByteCmd) + scsiDev.data[idx++] = 0; // Reserved + scsiDev.data[idx++] = 0; // Reserved + if (dbd) { - if (dbd) - { - scsiDev.data[idx++] = 0; // No block descriptor - } - else - { - // One block descriptor of length 8 bytes. - scsiDev.data[idx++] = 8; - } + scsiDev.data[idx++] = 0; // No block descriptor + scsiDev.data[idx++] = 0; // No block descriptor } else { - scsiDev.data[idx++] = 0; // Reserved - scsiDev.data[idx++] = 0; // Reserved - if (dbd) - { - scsiDev.data[idx++] = 0; // No block descriptor - scsiDev.data[idx++] = 0; // No block descriptor - } - else - { - // One block descriptor of length 8 bytes. - scsiDev.data[idx++] = 0; - scsiDev.data[idx++] = 8; - } + // One block descriptor of length 8 bytes. + scsiDev.data[idx++] = 0; + scsiDev.data[idx++] = 8; } + } - ////////////// Block Descriptor - //////////////////////////////////// - if (!dbd) - { - scsiDev.data[idx++] = density; - // Number of blocks - // Zero == all remaining blocks shall have the medium - // characteristics specified. - scsiDev.data[idx++] = 0; - scsiDev.data[idx++] = 0; - scsiDev.data[idx++] = 0; + ////////////// Block Descriptor + //////////////////////////////////// + if (!dbd) + { + scsiDev.data[idx++] = density; + // Number of blocks + // Zero == all remaining blocks shall have the medium + // characteristics specified. + scsiDev.data[idx++] = 0; + scsiDev.data[idx++] = 0; + scsiDev.data[idx++] = 0; + + scsiDev.data[idx++] = 0; // reserved + + // Block length + uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; + scsiDev.data[idx++] = bytesPerSector >> 16; + scsiDev.data[idx++] = bytesPerSector >> 8; + scsiDev.data[idx++] = bytesPerSector & 0xFF; + } - scsiDev.data[idx++] = 0; // reserved + int pageFound = 0; - // Block length - uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; - scsiDev.data[idx++] = bytesPerSector >> 16; - scsiDev.data[idx++] = bytesPerSector >> 8; - scsiDev.data[idx++] = bytesPerSector & 0xFF; - } + if (pageCode == 0x01 || pageCode == 0x3F) + { + pageFound = 1; + pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage)); + idx += sizeof(ReadWriteErrorRecoveryPage); + } - int pageFound = 0; + if (pageCode == 0x02 || pageCode == 0x3F) + { + pageFound = 1; + pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage)); + idx += sizeof(DisconnectReconnectPage); + } - if (pageCode == 0x01 || pageCode == 0x3F) + if (pageCode == 0x03 || pageCode == 0x3F) + { + pageFound = 1; + pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage)); + if (pc != 0x01) { - pageFound = 1; - pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage)); - idx += sizeof(ReadWriteErrorRecoveryPage); + // Fill out the configured bytes-per-sector + uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; + scsiDev.data[idx+12] = bytesPerSector >> 8; + scsiDev.data[idx+13] = bytesPerSector & 0xFF; } - - if (pageCode == 0x02 || pageCode == 0x3F) + else { - pageFound = 1; - pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage)); - idx += sizeof(DisconnectReconnectPage); + // Set a mask for the changeable values. + scsiDev.data[idx+12] = 0xFF; + scsiDev.data[idx+13] = 0xFF; } - if (pageCode == 0x03 || pageCode == 0x3F) - { - pageFound = 1; - pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage)); - if (pc != 0x01) - { - // Fill out the configured bytes-per-sector - uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; - scsiDev.data[idx+12] = bytesPerSector >> 8; - scsiDev.data[idx+13] = bytesPerSector & 0xFF; - } - else - { - // Set a mask for the changeable values. - scsiDev.data[idx+12] = 0xFF; - scsiDev.data[idx+13] = 0xFF; - } + idx += sizeof(FormatDevicePage); + } - idx += sizeof(FormatDevicePage); - } + if (pageCode == 0x04 || pageCode == 0x3F) + { + pageFound = 1; + pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry)); - if (pageCode == 0x04 || pageCode == 0x3F) + if (pc != 0x01) { - pageFound = 1; - pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry)); - - if (pc != 0x01) - { - // Need to fill out the number of cylinders. - uint32 cyl; - uint8 head; - uint32 sector; - LBA2CHS( - getScsiCapacity( - scsiDev.target->cfg->sdSectorStart, - scsiDev.target->liveCfg.bytesPerSector, - scsiDev.target->cfg->scsiSectors), - &cyl, - &head, - §or); - - scsiDev.data[idx+2] = cyl >> 16; - scsiDev.data[idx+3] = cyl >> 8; - scsiDev.data[idx+4] = cyl; - - memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3); - memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3); - } - - idx += sizeof(RigidDiskDriveGeometry); + // Need to fill out the number of cylinders. + uint32 cyl; + uint8 head; + uint32 sector; + LBA2CHS( + getScsiCapacity( + scsiDev.target->cfg->sdSectorStart, + scsiDev.target->liveCfg.bytesPerSector, + scsiDev.target->cfg->scsiSectors), + &cyl, + &head, + §or); + + scsiDev.data[idx+2] = cyl >> 16; + scsiDev.data[idx+3] = cyl >> 8; + scsiDev.data[idx+4] = cyl; + + memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3); + memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3); } - // DON'T output the following pages for SCSI1 hosts. They get upset when - // we have more data to send than the allocation length provided. - // (ie. Try not to output any more pages below this comment) + idx += sizeof(RigidDiskDriveGeometry); + } + // DON'T output the following pages for SCSI1 hosts. They get upset when + // we have more data to send than the allocation length provided. + // (ie. Try not to output any more pages below this comment) - if (!scsiDev.compatMode && (pageCode == 0x08 || pageCode == 0x3F)) - { - pageFound = 1; - pageIn(pc, idx, CachingPage, sizeof(CachingPage)); - idx += sizeof(CachingPage); - } - if (!scsiDev.compatMode && (pageCode == 0x0A || pageCode == 0x3F)) - { - pageFound = 1; - pageIn(pc, idx, ControlModePage, sizeof(ControlModePage)); - idx += sizeof(ControlModePage); - } + if ((scsiDev.compatMode >= COMPAT_SCSI2) && + (pageCode == 0x08 || pageCode == 0x3F)) + { + pageFound = 1; + pageIn(pc, idx, CachingPage, sizeof(CachingPage)); + idx += sizeof(CachingPage); + } - if (( - (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) || - (idx + sizeof(AppleVendorPage) <= allocLength) - ) && - (pageCode == 0x30 || pageCode == 0x3F)) - { - pageFound = 1; - pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage)); - idx += sizeof(AppleVendorPage); - } + if ((scsiDev.compatMode >= COMPAT_SCSI2) + && (pageCode == 0x0A || pageCode == 0x3F)) + { + pageFound = 1; + pageIn(pc, idx, ControlModePage, sizeof(ControlModePage)); + idx += sizeof(ControlModePage); + } + + if (( + (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) || + (idx + sizeof(AppleVendorPage) <= allocLength) + ) && + (pageCode == 0x30 || pageCode == 0x3F)) + { + pageFound = 1; + pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage)); + idx += sizeof(AppleVendorPage); + } - if (!pageFound) + if (!pageFound) + { + // Unknown Page Code + pageFound = 0; + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB; + scsiDev.phase = STATUS; + } + else + { + // Go back and fill out the mode data length + if (sixByteCmd) { - // Unknown Page Code - pageFound = 0; - scsiDev.status = CHECK_CONDITION; - scsiDev.target->sense.code = ILLEGAL_REQUEST; - scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB; - scsiDev.phase = STATUS; + // Cannot currently exceed limits. yay + scsiDev.data[0] = idx - 1; } else { - // Go back and fill out the mode data length - if (sixByteCmd) - { - // Cannot currently exceed limits. yay - scsiDev.data[0] = idx - 1; - } - else - { - scsiDev.data[0] = ((idx - 2) >> 8); - scsiDev.data[1] = (idx - 2); - } - - scsiDev.dataLen = idx > allocLength ? allocLength : idx; - scsiDev.phase = DATA_IN; + scsiDev.data[0] = ((idx - 2) >> 8); + scsiDev.data[1] = (idx - 2); } + + scsiDev.dataLen = idx > allocLength ? allocLength : idx; + scsiDev.phase = DATA_IN; } } + // Callback after the DATA OUT phase is complete. static void doModeSelect(void) { diff --git a/software/SCSI2SD/src/scsi.c b/software/SCSI2SD/src/scsi.c index 15622d59..0e5a78d9 100755 --- a/software/SCSI2SD/src/scsi.c +++ b/software/SCSI2SD/src/scsi.c @@ -53,7 +53,7 @@ static void enter_BusFree() { // This delay probably isn't needed for most SCSI hosts, but it won't // hurt either. It's possible some of the samplers needed this delay. - if (scsiDev.compatMode) + if (scsiDev.compatMode < COMPAT_SCSI2) { CyDelayUs(2); } @@ -214,7 +214,7 @@ static void process_DataOut() if (scsiDev.parityError && (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) && - !scsiDev.compatMode) + (scsiDev.compatMode >= COMPAT_SCSI2)) { scsiDev.target->sense.code = ABORTED_COMMAND; scsiDev.target->sense.asc = SCSI_PARITY_ERROR; @@ -274,7 +274,7 @@ static void process_Command() } else if (scsiDev.parityError && (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) && - !scsiDev.compatMode) + (scsiDev.compatMode >= COMPAT_SCSI2)) { scsiDev.target->sense.code = ABORTED_COMMAND; scsiDev.target->sense.asc = SCSI_PARITY_ERROR; @@ -459,6 +459,7 @@ static void scsiReset() scsiDev.atnFlag = 0; scsiDev.resetFlag = 0; scsiDev.lun = -1; + scsiDev.compatMode = COMPAT_UNKNOWN; if (scsiDev.target) { @@ -500,7 +501,6 @@ static void enter_SelectionPhase() scsiDev.phase = SELECTION; scsiDev.lun = -1; scsiDev.discPriv = 0; - scsiDev.compatMode = 0; scsiDev.initiatorId = -1; scsiDev.target = NULL; @@ -513,6 +513,12 @@ static void enter_SelectionPhase() static void process_SelectionPhase() { + if (scsiDev.compatMode < COMPAT_SCSI2) + { + // Required for some older SCSI1 devices using a 5380 chip. + CyDelayUs(100); + } + int sel = SCSI_ReadFilt(SCSI_Filt_SEL); int bsy = SCSI_ReadFilt(SCSI_Filt_BSY); @@ -552,7 +558,11 @@ static void process_SelectionPhase() if (!scsiDev.atnFlag) { target->unitAttention = 0; - scsiDev.compatMode = 1; + scsiDev.compatMode = COMPAT_SCSI1; + } + else if (scsiDev.compatMode == COMPAT_UNKNOWN) + { + scsiDev.compatMode = COMPAT_SCSI2; } // We've been selected! @@ -611,7 +621,7 @@ static void process_MessageOut() if (scsiDev.parityError && (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) && - !scsiDev.compatMode) + (scsiDev.compatMode >= COMPAT_SCSI2)) { // Skip the remaining message bytes, and then start the MESSAGE_OUT // phase again from the start. The initiator will re-send the @@ -872,6 +882,7 @@ void scsiInit() scsiDev.resetFlag = 1; scsiDev.phase = BUS_FREE; scsiDev.target = NULL; + scsiDev.compatMode = COMPAT_UNKNOWN; int i; for (i = 0; i < MAX_SCSI_TARGETS; ++i) diff --git a/software/SCSI2SD/src/scsi.h b/software/SCSI2SD/src/scsi.h index 2a48af38..adb61c80 100755 --- a/software/SCSI2SD/src/scsi.h +++ b/software/SCSI2SD/src/scsi.h @@ -57,6 +57,13 @@ typedef enum MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG = 0x0B } SCSI_MESSAGE; +typedef enum +{ + COMPAT_UNKNOWN, + COMPAT_SCSI1, + COMPAT_SCSI2 +} SCSI_COMPAT_MODE; + // Maximum value for bytes-per-sector. #define MAX_SECTOR_SIZE 8192 #define MIN_SECTOR_SIZE 64 @@ -112,7 +119,7 @@ typedef struct uint8 cdbLen; // 6, 10, or 12 byte message. int8 lun; // Target lun, set by IDENTIFY message. uint8 discPriv; // Disconnect priviledge. - uint8_t compatMode; // true for SCSI1 and SASI hosts. + uint8_t compatMode; // SCSI_COMPAT_MODE // Only let the reserved initiator talk to us. // A 3rd party may be sending the RESERVE/RELEASE commands diff --git a/software/SCSI2SD/src/scsiPhy.c b/software/SCSI2SD/src/scsiPhy.c index 5952b855..900192ba 100755 --- a/software/SCSI2SD/src/scsiPhy.c +++ b/software/SCSI2SD/src/scsiPhy.c @@ -447,4 +447,87 @@ void scsiPhyInit() SCSI_RST_ISR_StartEx(scsiResetISR); } + +// 1 = DBx error +// 2 = Parity error +// 4 = MSG error +// 8 = CD error +// 16 = IO error +// 32 = other error +int scsiSelfTest() +{ + int result = 0; + + // TEST DBx and DBp + int i; + SCSI_Out_Ctl_Write(1); // Write bits manually. + SCSI_CTL_PHASE_Write(__scsiphase_io); // Needed for parity generation + for (i = 0; i < 256; ++i) + { + SCSI_Out_Bits_Write(i); + scsiDeskewDelay(); + if (scsiReadDBxPins() != (i & 0xff)) + { + result |= 1; + } + if (Lookup_OddParity[i & 0xff] != SCSI_ReadPin(SCSI_In_DBP)) + { + result |= 2; + } + } + SCSI_Out_Ctl_Write(0); // Write bits normally. + + // TEST MSG, CD, IO + for (i = 0; i < 8; ++i) + { + SCSI_CTL_PHASE_Write(i); + scsiDeskewDelay(); + + if (SCSI_ReadPin(SCSI_In_MSG) != !!(i & __scsiphase_msg)) + { + result |= 4; + } + if (SCSI_ReadPin(SCSI_In_CD) != !!(i & __scsiphase_cd)) + { + result |= 8; + } + if (SCSI_ReadPin(SCSI_In_IO) != !!(i & __scsiphase_io)) + { + result |= 16; + } + } + SCSI_CTL_PHASE_Write(0); + + uint32_t signalsOut[] = { SCSI_Out_ATN, SCSI_Out_BSY, SCSI_Out_RST, SCSI_Out_SEL }; + uint32_t signalsIn[] = { SCSI_Filt_ATN, SCSI_Filt_BSY, SCSI_Filt_RST, SCSI_Filt_SEL }; + + for (i = 0; i < 4; ++i) + { + SCSI_SetPin(signalsOut[i]); + scsiDeskewDelay(); + + int j; + for (j = 0; j < 4; ++j) + { + if (i == j) + { + if (! SCSI_ReadFilt(signalsIn[j])) + { + result |= 32; + } + } + else + { + if (SCSI_ReadFilt(signalsIn[j])) + { + result |= 32; + } + } + } + SCSI_ClearPin(signalsOut[i]); + } + return result; +} + + #pragma GCC pop_options diff --git a/software/SCSI2SD/src/scsiPhy.h b/software/SCSI2SD/src/scsiPhy.h index b4c0f79f..006107be 100755 --- a/software/SCSI2SD/src/scsiPhy.h +++ b/software/SCSI2SD/src/scsiPhy.h @@ -88,4 +88,6 @@ uint8_t scsiReadDBxPins(void); void scsiEnterPhase(int phase); +int scsiSelfTest(void); + #endif diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h index 0db6988e..6df123ee 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h @@ -103,7 +103,7 @@ #define USBFS_arb_int__INTC_CLR_PD_REG CYREG_NVIC_CLRPEND0 #define USBFS_arb_int__INTC_MASK 0x400000u #define USBFS_arb_int__INTC_NUMBER 22u -#define USBFS_arb_int__INTC_PRIOR_NUM 7u +#define USBFS_arb_int__INTC_PRIOR_NUM 6u #define USBFS_arb_int__INTC_PRIOR_REG CYREG_NVIC_PRI_22 #define USBFS_arb_int__INTC_SET_EN_REG CYREG_NVIC_SETENA0 #define USBFS_arb_int__INTC_SET_PD_REG CYREG_NVIC_SETPEND0 diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc index 6c74b5f1..a7a64017 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc @@ -103,7 +103,7 @@ .set USBFS_arb_int__INTC_CLR_PD_REG, CYREG_NVIC_CLRPEND0 .set USBFS_arb_int__INTC_MASK, 0x400000 .set USBFS_arb_int__INTC_NUMBER, 22 -.set USBFS_arb_int__INTC_PRIOR_NUM, 7 +.set USBFS_arb_int__INTC_PRIOR_NUM, 6 .set USBFS_arb_int__INTC_PRIOR_REG, CYREG_NVIC_PRI_22 .set USBFS_arb_int__INTC_SET_EN_REG, CYREG_NVIC_SETENA0 .set USBFS_arb_int__INTC_SET_PD_REG, CYREG_NVIC_SETPEND0 diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc index ec345816..dc757612 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc @@ -103,7 +103,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0 USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0 USBFS_arb_int__INTC_MASK EQU 0x400000 USBFS_arb_int__INTC_NUMBER EQU 22 -USBFS_arb_int__INTC_PRIOR_NUM EQU 7 +USBFS_arb_int__INTC_PRIOR_NUM EQU 6 USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22 USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0 USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0 diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc index be5a1f54..aba1877f 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc @@ -103,7 +103,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0 USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0 USBFS_arb_int__INTC_MASK EQU 0x400000 USBFS_arb_int__INTC_NUMBER EQU 22 -USBFS_arb_int__INTC_PRIOR_NUM EQU 7 +USBFS_arb_int__INTC_PRIOR_NUM EQU 6 USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22 USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0 USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0 diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c index c07d0218..efccf012 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c @@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used)) const uint8 cy_meta_loadable[] = { 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x20u, 0x04u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x22u, 0x04u, 0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit index afd79826..bcf9ae3a 100644 Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit differ diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyprj b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyprj index 2f7d4692..e30584eb 100755 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyprj +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyprj @@ -3357,7 +3357,7 @@ - + diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch b/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch index e5f05a0a..285360e4 100755 Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h index ae0e2a06..159ba3d1 100644 --- a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h +++ b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h @@ -104,7 +104,7 @@ #define USBFS_arb_int__INTC_CLR_PD_REG CYREG_NVIC_CLRPEND0 #define USBFS_arb_int__INTC_MASK 0x400000u #define USBFS_arb_int__INTC_NUMBER 22u -#define USBFS_arb_int__INTC_PRIOR_NUM 7u +#define USBFS_arb_int__INTC_PRIOR_NUM 6u #define USBFS_arb_int__INTC_PRIOR_REG CYREG_NVIC_PRI_22 #define USBFS_arb_int__INTC_SET_EN_REG CYREG_NVIC_SETENA0 #define USBFS_arb_int__INTC_SET_PD_REG CYREG_NVIC_SETPEND0 @@ -2322,7 +2322,7 @@ #define SD_RX_DMA__DRQ_CTL CYREG_IDMUX_DRQ_CTL0 #define SD_RX_DMA__DRQ_NUMBER 2u #define SD_RX_DMA__NUMBEROF_TDS 0u -#define SD_RX_DMA__PRIORITY 2u +#define SD_RX_DMA__PRIORITY 0u #define SD_RX_DMA__TERMIN_EN 0u #define SD_RX_DMA__TERMIN_SEL 0u #define SD_RX_DMA__TERMOUT0_EN 1u @@ -2344,7 +2344,7 @@ #define SD_TX_DMA__DRQ_CTL CYREG_IDMUX_DRQ_CTL0 #define SD_TX_DMA__DRQ_NUMBER 3u #define SD_TX_DMA__NUMBEROF_TDS 0u -#define SD_TX_DMA__PRIORITY 2u +#define SD_TX_DMA__PRIORITY 1u #define SD_TX_DMA__TERMIN_EN 0u #define SD_TX_DMA__TERMIN_SEL 0u #define SD_TX_DMA__TERMOUT0_EN 1u diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc index be56b151..0b4af89b 100644 --- a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc +++ b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc @@ -104,7 +104,7 @@ .set USBFS_arb_int__INTC_CLR_PD_REG, CYREG_NVIC_CLRPEND0 .set USBFS_arb_int__INTC_MASK, 0x400000 .set USBFS_arb_int__INTC_NUMBER, 22 -.set USBFS_arb_int__INTC_PRIOR_NUM, 7 +.set USBFS_arb_int__INTC_PRIOR_NUM, 6 .set USBFS_arb_int__INTC_PRIOR_REG, CYREG_NVIC_PRI_22 .set USBFS_arb_int__INTC_SET_EN_REG, CYREG_NVIC_SETENA0 .set USBFS_arb_int__INTC_SET_PD_REG, CYREG_NVIC_SETPEND0 @@ -2322,7 +2322,7 @@ .set SD_RX_DMA__DRQ_CTL, CYREG_IDMUX_DRQ_CTL0 .set SD_RX_DMA__DRQ_NUMBER, 2 .set SD_RX_DMA__NUMBEROF_TDS, 0 -.set SD_RX_DMA__PRIORITY, 2 +.set SD_RX_DMA__PRIORITY, 0 .set SD_RX_DMA__TERMIN_EN, 0 .set SD_RX_DMA__TERMIN_SEL, 0 .set SD_RX_DMA__TERMOUT0_EN, 1 @@ -2344,7 +2344,7 @@ .set SD_TX_DMA__DRQ_CTL, CYREG_IDMUX_DRQ_CTL0 .set SD_TX_DMA__DRQ_NUMBER, 3 .set SD_TX_DMA__NUMBEROF_TDS, 0 -.set SD_TX_DMA__PRIORITY, 2 +.set SD_TX_DMA__PRIORITY, 1 .set SD_TX_DMA__TERMIN_EN, 0 .set SD_TX_DMA__TERMIN_SEL, 0 .set SD_TX_DMA__TERMOUT0_EN, 1 diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc index a59ad0e6..b6c06fb4 100644 --- a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc +++ b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc @@ -104,7 +104,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0 USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0 USBFS_arb_int__INTC_MASK EQU 0x400000 USBFS_arb_int__INTC_NUMBER EQU 22 -USBFS_arb_int__INTC_PRIOR_NUM EQU 7 +USBFS_arb_int__INTC_PRIOR_NUM EQU 6 USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22 USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0 USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0 @@ -2322,7 +2322,7 @@ SCSI_Out_DBx__DB7__SLW EQU CYREG_PRT2_SLW SD_RX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0 SD_RX_DMA__DRQ_NUMBER EQU 2 SD_RX_DMA__NUMBEROF_TDS EQU 0 -SD_RX_DMA__PRIORITY EQU 2 +SD_RX_DMA__PRIORITY EQU 0 SD_RX_DMA__TERMIN_EN EQU 0 SD_RX_DMA__TERMIN_SEL EQU 0 SD_RX_DMA__TERMOUT0_EN EQU 1 @@ -2344,7 +2344,7 @@ SD_RX_DMA_COMPLETE__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0 SD_TX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0 SD_TX_DMA__DRQ_NUMBER EQU 3 SD_TX_DMA__NUMBEROF_TDS EQU 0 -SD_TX_DMA__PRIORITY EQU 2 +SD_TX_DMA__PRIORITY EQU 1 SD_TX_DMA__TERMIN_EN EQU 0 SD_TX_DMA__TERMIN_SEL EQU 0 SD_TX_DMA__TERMOUT0_EN EQU 1 diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc index f2b9e4cc..4cc15c6e 100644 --- a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc +++ b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc @@ -104,7 +104,7 @@ USBFS_arb_int__INTC_CLR_EN_REG EQU CYREG_NVIC_CLRENA0 USBFS_arb_int__INTC_CLR_PD_REG EQU CYREG_NVIC_CLRPEND0 USBFS_arb_int__INTC_MASK EQU 0x400000 USBFS_arb_int__INTC_NUMBER EQU 22 -USBFS_arb_int__INTC_PRIOR_NUM EQU 7 +USBFS_arb_int__INTC_PRIOR_NUM EQU 6 USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22 USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0 USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0 @@ -2322,7 +2322,7 @@ SCSI_Out_DBx__DB7__SLW EQU CYREG_PRT2_SLW SD_RX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0 SD_RX_DMA__DRQ_NUMBER EQU 2 SD_RX_DMA__NUMBEROF_TDS EQU 0 -SD_RX_DMA__PRIORITY EQU 2 +SD_RX_DMA__PRIORITY EQU 0 SD_RX_DMA__TERMIN_EN EQU 0 SD_RX_DMA__TERMIN_SEL EQU 0 SD_RX_DMA__TERMOUT0_EN EQU 1 @@ -2344,7 +2344,7 @@ SD_RX_DMA_COMPLETE__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0 SD_TX_DMA__DRQ_CTL EQU CYREG_IDMUX_DRQ_CTL0 SD_TX_DMA__DRQ_NUMBER EQU 3 SD_TX_DMA__NUMBEROF_TDS EQU 0 -SD_TX_DMA__PRIORITY EQU 2 +SD_TX_DMA__PRIORITY EQU 1 SD_TX_DMA__TERMIN_EN EQU 0 SD_TX_DMA__TERMIN_SEL EQU 0 SD_TX_DMA__TERMOUT0_EN EQU 1 diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c index dfaca9db..ee269a7a 100644 --- a/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c +++ b/software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c @@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used)) const uint8 cy_meta_loadable[] = { 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x10u, 0x04u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x22u, 0x04u, 0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit index 7cb75d6f..239ad50c 100644 Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit differ diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyprj b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyprj index 0f6ea558..465dedeb 100755 --- a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyprj +++ b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyprj @@ -2499,7 +2499,7 @@ - + diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch b/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch index 99cb7695..71ca8219 100755 Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ diff --git a/software/include/scsi2sd.h b/software/include/scsi2sd.h index cec7485c..3e8cf47f 100755 --- a/software/include/scsi2sd.h +++ b/software/include/scsi2sd.h @@ -181,7 +181,14 @@ typedef enum // Response: // uint8_t[16] CSD // uint8_t[16] CID - CONFIG_SDINFO + CONFIG_SDINFO, + + // Command content: + // uint8_t CONFIG_SCSITEST + // Response: + // CONFIG_STATUS + // uint8_t result code (0 = passed) + CONFIG_SCSITEST } CONFIG_COMMAND; typedef enum diff --git a/software/scsi2sd-util/ConfigUtil.cc b/software/scsi2sd-util/ConfigUtil.cc index e717cf8d..446a91b7 100644 --- a/software/scsi2sd-util/ConfigUtil.cc +++ b/software/scsi2sd-util/ConfigUtil.cc @@ -24,7 +24,6 @@ using namespace SCSI2SD; -ADD QUIRKS MODES namespace { // Endian conversion routines. @@ -105,7 +104,7 @@ ConfigUtil::Default(size_t targetIdx) config.headsPerCylinder = 255; memcpy(config.vendor, " codesrc", 8); memcpy(config.prodId, " SCSI2SD", 16); - memcpy(config.revision, " 4.0", 4); + memcpy(config.revision, " 4.2", 4); memcpy(config.serial, "1234567812345678", 16); // Reserved fields, already set to 0 @@ -146,6 +145,7 @@ ConfigUtil::toBytes(const TargetConfig& _config) return std::vector(begin, begin + sizeof(config)); } +/* wxXmlNode* ConfigUtil::toXML(const TargetConfig& config) { @@ -203,3 +203,4 @@ ConfigUtil::deserialise(const std::string& in) { } +*/ diff --git a/software/scsi2sd-util/Makefile b/software/scsi2sd-util/Makefile index d1ae7453..22794df0 100755 --- a/software/scsi2sd-util/Makefile +++ b/software/scsi2sd-util/Makefile @@ -51,7 +51,7 @@ endif export CC CXX -all: $(BUILD)/scsi2sd-util$(EXE) +all: $(BUILD)/scsi2sd-util$(EXE) $(BUILD)/scsi2sd-monitor$(EXE) CYAPI = \ $(BUILD)/cybtldr_api2.o \ @@ -66,7 +66,6 @@ HIDAPI = \ OBJ = \ $(CYAPI) $(HIDAPI) \ - $(BUILD)/scsi2sd-util.o \ $(BUILD)/ConfigUtil.o \ $(BUILD)/Firmware.o \ $(BUILD)/TargetPanel.o \ @@ -74,8 +73,14 @@ OBJ = \ $(BUILD)/SCSI2SD_HID.o \ $(BUILD)/hidpacket.o \ +EXEOBJ = \ + $(BUILD)/scsi2sd-util.o \ + $(BUILD)/scsi2sd-monitor.o \ + + $(OBJ): $(BUILD)/zlib/buildstamp +$(EXEOBJ): $(BUILD)/zlib/buildstamp $(BUILD)/zlib/buildstamp: mkdir -p $(dir $@) ( \ @@ -87,6 +92,7 @@ $(BUILD)/zlib/buildstamp: touch $@ $(OBJ): $(BUILD)/wx.buildstamp +$(EXEOBJ): $(BUILD)/wx.buildstamp $(BUILD)/wx.buildstamp: $(BUILD)/zlib/buildstamp mkdir -p $(dir $@) ( \ @@ -97,6 +103,7 @@ $(BUILD)/wx.buildstamp: $(BUILD)/zlib/buildstamp touch $@ $(OBJ): $(BUILD)/libzipper/buildstamp +$(EXEOBJ): $(BUILD)/libzipper/buildstamp $(BUILD)/libzipper/buildstamp: $(BUILD)/zlib/buildstamp mkdir -p $(dir $@) ( \ @@ -114,7 +121,11 @@ $(BUILD)/%.o: %.cc mkdir -p $(dir $@) $(CXX) $(CPPFLAGS) $(CXXFLAGS) `$(BUILD)/wx-config --cxxflags` $< -c -o $@ -$(BUILD)/scsi2sd-util$(EXE): $(OBJ) +$(BUILD)/scsi2sd-util$(EXE): $(OBJ) $(BUILD)/scsi2sd-util.o + mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) `$(BUILD)/wx-config --libs` -o $@ + +$(BUILD)/scsi2sd-monitor$(EXE): $(OBJ) $(BUILD)/scsi2sd-monitor.o mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) `$(BUILD)/wx-config --libs` -o $@ diff --git a/software/scsi2sd-util/SCSI2SD_HID.cc b/software/scsi2sd-util/SCSI2SD_HID.cc index b2aa4d0c..df83b67a 100644 --- a/software/scsi2sd-util/SCSI2SD_HID.cc +++ b/software/scsi2sd-util/SCSI2SD_HID.cc @@ -338,7 +338,7 @@ HID::getSD_CSD() std::vector out; try { - sendHIDPacket(cmd, out, 1); + sendHIDPacket(cmd, out, 16); } catch (std::runtime_error& e) { @@ -356,7 +356,7 @@ HID::getSD_CID() std::vector out; try { - sendHIDPacket(cmd, out, 1); + sendHIDPacket(cmd, out, 16); } catch (std::runtime_error& e) { @@ -368,6 +368,23 @@ HID::getSD_CID() return result; } +bool +HID::scsiSelfTest() +{ + std::vector cmd { CONFIG_SCSITEST }; + std::vector out; + try + { + sendHIDPacket(cmd, out, 2); + } + catch (std::runtime_error& e) + { + return false; + } + return (out.size() >= 1) && (out[0] == CONFIG_STATUS_GOOD); +} + + void HID::sendHIDPacket( const std::vector& cmd, diff --git a/software/scsi2sd-util/SCSI2SD_HID.hh b/software/scsi2sd-util/SCSI2SD_HID.hh index 443b3df7..2cf17471 100644 --- a/software/scsi2sd-util/SCSI2SD_HID.hh +++ b/software/scsi2sd-util/SCSI2SD_HID.hh @@ -58,6 +58,8 @@ public: std::vector getSD_CSD(); std::vector getSD_CID(); + bool scsiSelfTest(); + void enterBootloader(); void readFlashRow(int array, int row, std::vector& out); diff --git a/software/scsi2sd-util/scsi2sd-monitor.cc b/software/scsi2sd-util/scsi2sd-monitor.cc new file mode 100644 index 00000000..872001ac --- /dev/null +++ b/software/scsi2sd-util/scsi2sd-monitor.cc @@ -0,0 +1,288 @@ +// Copyright (C) 2015 Michael McMaster +// +// This file is part of SCSI2SD. +// +// SCSI2SD is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// SCSI2SD is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SCSI2SD. If not, see . + + +// For compilers that support precompilation, includes "wx/wx.h". +#include +#ifndef WX_PRECOMP +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ConfigUtil.hh" +#include "TargetPanel.hh" +#include "SCSI2SD_Bootloader.hh" +#include "SCSI2SD_HID.hh" +#include "Firmware.hh" + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +#include +#include +using std::shared_ptr; +#else +#include +#include +using std::tr1::shared_ptr; +#endif + +#define MIN_FIRMWARE_VERSION 0x0400 + +using namespace SCSI2SD; + +namespace +{ + +static uint8_t sdCrc7(uint8_t* chr, uint8_t cnt, uint8_t crc) +{ + uint8_t a; + for(a = 0; a < cnt; a++) + { + uint8_t data = chr[a]; + uint8_t i; + for(i = 0; i < 8; i++) + { + crc <<= 1; + if ((data & 0x80) ^ (crc & 0x80)) + { + crc ^= 0x09; + } + data <<= 1; + } + } + return crc & 0x7F; +} + +class TimerLock +{ +public: + TimerLock(wxTimer* timer) : + myTimer(timer), + myInterval(myTimer->GetInterval()) + { + myTimer->Stop(); + }; + + virtual ~TimerLock() + { + if (myTimer && myInterval > 0) + { + myTimer->Start(myInterval); + } + } +private: + wxTimer* myTimer; + int myInterval; +}; + +class AppFrame : public wxFrame +{ +public: + AppFrame() : + wxFrame(NULL, wxID_ANY, "scsi2sd-monitor", wxPoint(50, 50), wxSize(250, 150)) + { + wxFlexGridSizer *fgs = new wxFlexGridSizer(3, 2, 9, 25); + + fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SCSI2SD Device:"))); + myBoardText = new wxStaticText(this, wxID_ANY, wxT("")); + fgs->Add(myBoardText); + fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SD Test:"))); + mySDText = new wxStaticText(this, wxID_ANY, wxT("")); + fgs->Add(mySDText); + fgs->Add(new wxStaticText(this, wxID_ANY, wxT("SCSI Test:"))); + mySCSIText = new wxStaticText(this, wxID_ANY, wxT("")); + fgs->Add(mySCSIText); + + wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL); + hbox->Add(fgs, 1, wxALL | wxEXPAND, 15); + this->SetSizer(hbox); + Centre(); + + //Fit(); // Needed to reduce window size on Windows + //FitInside(); // Needed on Linux to prevent status bar overlap + + myTimer = new wxTimer(this, ID_Timer); + myTimer->Start(1000); + } + +private: + wxTimer* myTimer; + shared_ptr myHID; + shared_ptr myBootloader; + + wxStaticText* myBoardText; + wxStaticText* mySDText; + wxStaticText* mySCSIText; + + enum + { + ID_ConfigDefaults = wxID_HIGHEST + 1, + ID_Timer + }; + + void evaluate() + { + if (myHID) + { + std::stringstream msg; + msg << "Ready, " << + myHID->getFirmwareVersionStr(); + myBoardText->SetLabelText(msg.str()); + + + std::vector csd(myHID->getSD_CSD()); + std::vector cid(myHID->getSD_CID()); + + bool sdGood = false; + for (size_t i = 0; i < 16; ++i) + { + if (csd[i] != 0) + { + sdGood = true; + //break; + } + } + + sdGood = sdGood && + (sdCrc7(&csd[0], 15, 0) == (csd[15] >> 1)) && + (sdCrc7(&cid[0], 15, 0) == (cid[15] >> 1)); + + if (sdGood) + { + mySDText->SetLabelText("OK"); + } + else + { + mySDText->SetLabelText("FAIL"); + } + + if (myHID->scsiSelfTest()) + { + mySCSIText->SetLabelText("OK"); + } + else + { + mySCSIText->SetLabelText("FAIL"); + } + } + else + { + if (myBootloader) + { + myBoardText->SetLabelText("Bootloader"); + } + else + { + myBoardText->SetLabelText("Missing"); + } + mySDText->SetLabelText("-"); + mySCSIText->SetLabelText("-"); + } + } + + void OnID_Timer(wxTimerEvent& event) + { + // Check if we are connected to the HID device. + // AND/or bootloader device. + try + { + if (myBootloader) + { + // Verify the USB HID connection is valid + if (!myBootloader->ping()) + { + myBootloader.reset(); + } + } + + if (!myBootloader) + { + myBootloader.reset(Bootloader::Open()); + } + + if (myHID && !myHID->ping()) + { + // Verify the USB HID connection is valid +std::cerr << "RESET!" << std::endl; + myHID.reset(); + } + + if (!myHID) + { + myHID.reset(HID::Open()); + + } + } + catch (std::runtime_error& e) + { + std::cerr << e.what() << std::endl; + } + + evaluate(); + } + + // Note: Don't confuse this with the wxApp::OnExit virtual method + void OnExitEvt(wxCommandEvent& event) + { + Close(true); + } + + wxDECLARE_EVENT_TABLE(); +}; + +wxBEGIN_EVENT_TABLE(AppFrame, wxFrame) + EVT_MENU(wxID_EXIT, AppFrame::OnExitEvt) + + EVT_TIMER(AppFrame::ID_Timer, AppFrame::OnID_Timer) + +wxEND_EVENT_TABLE() + + + +class App : public wxApp +{ +public: + virtual bool OnInit() + { + AppFrame* frame = new AppFrame(); + frame->Show(true); + SetTopWindow(frame); + return true; + } +}; +} // namespace + +// Main Method +wxIMPLEMENT_APP(App); + + diff --git a/software/scsi2sd-util/scsi2sd-util.cc b/software/scsi2sd-util/scsi2sd-util.cc index cc26e8ba..6e3e782a 100644 --- a/software/scsi2sd-util/scsi2sd-util.cc +++ b/software/scsi2sd-util/scsi2sd-util.cc @@ -108,6 +108,26 @@ void ProgressUpdate(unsigned char arrayId, unsigned short rowNum) namespace { +static uint8_t sdCrc7(uint8_t* chr, uint8_t cnt, uint8_t crc) +{ + uint8_t a; + for(a = 0; a < cnt; a++) + { + uint8_t data = chr[a]; + uint8_t i; + for(i = 0; i < 8; i++) + { + crc <<= 1; + if ((data & 0x80) ^ (crc & 0x80)) + { + crc ^= 0x09; + } + data <<= 1; + } + } + return crc & 0x7F; +} + class TimerLock { public: @@ -163,6 +183,11 @@ public: "Log SCSI data", "Log SCSI commands"); + mySelfTestChk = menuDebug->AppendCheckItem( + ID_SelfTest, + "SCSI Standalone Self-Test", + "SCSI Standalone Self-Test"); + wxMenu *menuHelp = new wxMenu(); menuHelp->Append(wxID_ABOUT); @@ -229,6 +254,7 @@ private: wxButton* myLoadButton; wxButton* mySaveButton; wxMenuItem* mySCSILogChk; + wxMenuItem* mySelfTestChk; wxTimer* myTimer; shared_ptr myHID; shared_ptr myBootloader; @@ -329,7 +355,8 @@ private: ID_BtnLoad, ID_BtnSave, ID_LogWindow, - ID_SCSILog + ID_SCSILog, + ID_SelfTest }; void OnID_ConfigDefaults(wxCommandEvent& event) @@ -629,6 +656,10 @@ private: myHID->getSDCapacity() << std::endl; sdinfo << "SD CSD Register: "; + if (sdCrc7(&csd[0], 15, 0) != (csd[15] >> 1)) + { + sdinfo << "BADCRC "; + } for (size_t i = 0; i < csd.size(); ++i) { sdinfo << @@ -637,6 +668,10 @@ private: } sdinfo << std::endl; sdinfo << "SD CID Register: "; + if (sdCrc7(&cid[0], 15, 0) != (cid[15] >> 1)) + { + sdinfo << "BADCRC "; + } for (size_t i = 0; i < cid.size(); ++i) { sdinfo << @@ -646,6 +681,14 @@ private: wxLogMessage(this, "%s", sdinfo.str()); + if (mySelfTestChk->IsChecked()) + { + std::stringstream scsiInfo; + scsiInfo << "SCSI Self-Test: " << + (myHID->scsiSelfTest() ? "Passed" : "FAIL"); + wxLogMessage(this, "%s", scsiInfo.str()); + } + if (!myInitialConfig) { wxCommandEvent loadEvent(wxEVT_NULL, ID_BtnLoad);