Small compatibility improvements, and added scsi2sd-monitor test program v4.02.02
authorMichael McMaster <michael@codesrc.com>
Mon, 20 Apr 2015 06:09:51 +0000 (16:09 +1000)
committerMichael McMaster <michael@codesrc.com>
Mon, 20 Apr 2015 06:09:51 +0000 (16:09 +1000)
32 files changed:
CHANGELOG
readme.txt
software/SCSI2SD/src/config.c
software/SCSI2SD/src/disk.c
software/SCSI2SD/src/mode.c
software/SCSI2SD/src/scsi.c
software/SCSI2SD/src/scsi.h
software/SCSI2SD/src/scsiPhy.c
software/SCSI2SD/src/scsiPhy.h
software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h
software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc
software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc
software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc
software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c
software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit
software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyprj
software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch
software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h
software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc
software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitteriar.inc
software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc
software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c
software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit
software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyprj
software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch
software/include/scsi2sd.h
software/scsi2sd-util/ConfigUtil.cc
software/scsi2sd-util/Makefile
software/scsi2sd-util/SCSI2SD_HID.cc
software/scsi2sd-util/SCSI2SD_HID.hh
software/scsi2sd-util/scsi2sd-monitor.cc [new file with mode: 0644]
software/scsi2sd-util/scsi2sd-util.cc

index cf022b5..423d64e 100644 (file)
--- 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.
index 1c22fde..11c4348 100644 (file)
@@ -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
index 6178b9f..732d4c4 100755 (executable)
@@ -32,7 +32,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x0411;\r
+static const uint16_t FIRMWARE_VERSION = 0x0422;\r
 \r
 enum USB_ENDPOINTS\r
 {\r
@@ -53,8 +53,30 @@ static int usbInEpState;
 static int usbDebugEpState;\r
 static int usbReady;\r
 \r
+uint8_t DEFAULT_CONFIG[256]\r
+       __attribute__ ((section(".DEFAULT_CONFIG"))) =\r
+{\r
+       CONFIG_TARGET_ENABLED,\r
+       CONFIG_FIXED,\r
+       0,\r
+       0,\r
+       0, 0, 0, 0,\r
+       0xff, 0xff, 0x3f, 0x00, // 4194303, 2GB - 1 sector\r
+       0x00, 0x02, //512\r
+       63, 0,\r
+       255, 0,\r
+       ' ', 'c', 'o', 'd', 'e', 's', 'r', 'c',\r
+       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'S', 'C', 'S', 'I', '2', 'S', 'D',\r
+       ' ', '4', '.', '2',\r
+       '1','2','3','4','5','6','7','8','1','2','3','4','5','6','7','8'\r
+};\r
+// otherwise linker removes unused section.\r
+volatile uint8_t trickLinker;\r
+\r
 void configInit()\r
 {\r
+       trickLinker = DEFAULT_CONFIG[0];\r
+\r
        // The USB block will be powered by an internal 3.3V regulator.\r
        // The PSoC must be operating between 4.6V and 5V for the regulator\r
        // to work.\r
@@ -132,6 +154,20 @@ sdInfoCommand()
 \r
        hidPacket_send(response, sizeof(response));\r
 }\r
+\r
+\r
+static void\r
+scsiTestCommand()\r
+{\r
+       int resultCode = scsiSelfTest();\r
+       uint8_t response[] =\r
+       {\r
+               resultCode == 0 ? CONFIG_STATUS_GOOD : CONFIG_STATUS_ERR,\r
+               resultCode\r
+       };\r
+       hidPacket_send(response, sizeof(response));\r
+}\r
+\r
 static void\r
 processCommand(const uint8_t* cmd, size_t cmdSize)\r
 {\r
@@ -157,6 +193,10 @@ processCommand(const uint8_t* cmd, size_t cmdSize)
                sdInfoCommand();\r
                break;\r
 \r
+       case CONFIG_SCSITEST:\r
+               scsiTestCommand();\r
+               break;\r
+\r
        case CONFIG_NONE: // invalid\r
        default:\r
                break;\r
index af1c50a..5b6a70d 100755 (executable)
@@ -728,7 +728,7 @@ void scsiDiskPoll()
                {\r
                        if (scsiDev.parityError &&\r
                                (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-                               !scsiDev.compatMode)\r
+                               (scsiDev.compatMode >= COMPAT_SCSI2))\r
                        {\r
                                scsiDev.target->sense.code = ABORTED_COMMAND;\r
                                scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
index c66608a..4ed790f 100755 (executable)
@@ -145,231 +145,224 @@ static void pageIn(int pc, int dataIdx, const uint8* pageData, int pageLen)
 static void doModeSense(\r
        int sixByteCmd, int dbd, int pc, int pageCode, int allocLength)\r
 {\r
-       if (pc == 0x03) // Saved Values not supported.\r
+       ////////////// Mode Parameter Header\r
+       ////////////////////////////////////\r
+\r
+       // Skip the Mode Data Length, we set that last.\r
+       int idx = 1;\r
+       if (!sixByteCmd) ++idx;\r
+\r
+       uint8_t mediumType = 0;\r
+       uint8_t deviceSpecificParam = 0;\r
+       uint8_t density = 0;\r
+       switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)\r
        {\r
-               scsiDev.status = CHECK_CONDITION;\r
-               scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
-               scsiDev.target->sense.asc = SAVING_PARAMETERS_NOT_SUPPORTED;\r
-               scsiDev.phase = STATUS;\r
+       case CONFIG_FIXED:\r
+       case CONFIG_REMOVEABLE:\r
+               mediumType = 0; // We should support various floppy types here!\r
+               // Contains cache bits (0) and a Write-Protect bit.\r
+               deviceSpecificParam =\r
+                       (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+               density = 0; // reserved for direct access\r
+               break;\r
+\r
+       case CONFIG_FLOPPY_14MB:\r
+               mediumType = 0x1E; // 90mm/3.5"\r
+               deviceSpecificParam =\r
+                       (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+               density = 0; // reserved for direct access\r
+               break;\r
+\r
+       case CONFIG_OPTICAL:\r
+               mediumType = 0x02; // 120mm CDROM, data only.\r
+               deviceSpecificParam = 0;\r
+               density = 0x01; // User data only, 2048bytes per sector.\r
+               break;\r
+\r
+       };\r
+\r
+       scsiDev.data[idx++] = mediumType;\r
+       scsiDev.data[idx++] = deviceSpecificParam;\r
+\r
+       if (sixByteCmd)\r
+       {\r
+               if (dbd)\r
+               {\r
+                       scsiDev.data[idx++] = 0; // No block descriptor\r
+               }\r
+               else\r
+               {\r
+                       // One block descriptor of length 8 bytes.\r
+                       scsiDev.data[idx++] = 8;\r
+               }\r
        }\r
        else\r
        {\r
-               ////////////// Mode Parameter Header\r
-               ////////////////////////////////////\r
-\r
-               // Skip the Mode Data Length, we set that last.\r
-               int idx = 1;\r
-               if (!sixByteCmd) ++idx;\r
-\r
-               uint8_t mediumType = 0;\r
-               uint8_t deviceSpecificParam = 0;\r
-               uint8_t density = 0;\r
-               switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)\r
-               {\r
-               case CONFIG_FIXED:\r
-               case CONFIG_REMOVEABLE:\r
-                       mediumType = 0; // We should support various floppy types here!\r
-                       // Contains cache bits (0) and a Write-Protect bit.\r
-                       deviceSpecificParam =\r
-                               (blockDev.state & DISK_WP) ? 0x80 : 0;\r
-                       density = 0; // reserved for direct access\r
-                       break;\r
-\r
-               case CONFIG_FLOPPY_14MB:\r
-                       mediumType = 0x1E; // 90mm/3.5"\r
-                       deviceSpecificParam =\r
-                               (blockDev.state & DISK_WP) ? 0x80 : 0;\r
-                       density = 0; // reserved for direct access\r
-                       break;\r
-\r
-               case CONFIG_OPTICAL:\r
-                       mediumType = 0x02; // 120mm CDROM, data only.\r
-                       deviceSpecificParam = 0;\r
-                       density = 0x01; // User data only, 2048bytes per sector.\r
-                       break;\r
-\r
-               };\r
-\r
-               scsiDev.data[idx++] = mediumType;\r
-               scsiDev.data[idx++] = deviceSpecificParam;\r
-\r
-               if (sixByteCmd)\r
+               scsiDev.data[idx++] = 0; // Reserved\r
+               scsiDev.data[idx++] = 0; // Reserved\r
+               if (dbd)\r
                {\r
-                       if (dbd)\r
-                       {\r
-                               scsiDev.data[idx++] = 0; // No block descriptor\r
-                       }\r
-                       else\r
-                       {\r
-                               // One block descriptor of length 8 bytes.\r
-                               scsiDev.data[idx++] = 8;\r
-                       }\r
+                       scsiDev.data[idx++] = 0; // No block descriptor\r
+                       scsiDev.data[idx++] = 0; // No block descriptor\r
                }\r
                else\r
                {\r
-                       scsiDev.data[idx++] = 0; // Reserved\r
-                       scsiDev.data[idx++] = 0; // Reserved\r
-                       if (dbd)\r
-                       {\r
-                               scsiDev.data[idx++] = 0; // No block descriptor\r
-                               scsiDev.data[idx++] = 0; // No block descriptor\r
-                       }\r
-                       else\r
-                       {\r
-                               // One block descriptor of length 8 bytes.\r
-                               scsiDev.data[idx++] = 0;\r
-                               scsiDev.data[idx++] = 8;\r
-                       }\r
+                       // One block descriptor of length 8 bytes.\r
+                       scsiDev.data[idx++] = 0;\r
+                       scsiDev.data[idx++] = 8;\r
                }\r
+       }\r
 \r
-               ////////////// Block Descriptor\r
-               ////////////////////////////////////\r
-               if (!dbd)\r
-               {\r
-                       scsiDev.data[idx++] = density;\r
-                       // Number of blocks\r
-                       // Zero == all remaining blocks shall have the medium\r
-                       // characteristics specified.\r
-                       scsiDev.data[idx++] = 0;\r
-                       scsiDev.data[idx++] = 0;\r
-                       scsiDev.data[idx++] = 0;\r
+       ////////////// Block Descriptor\r
+       ////////////////////////////////////\r
+       if (!dbd)\r
+       {\r
+               scsiDev.data[idx++] = density;\r
+               // Number of blocks\r
+               // Zero == all remaining blocks shall have the medium\r
+               // characteristics specified.\r
+               scsiDev.data[idx++] = 0;\r
+               scsiDev.data[idx++] = 0;\r
+               scsiDev.data[idx++] = 0;\r
+\r
+               scsiDev.data[idx++] = 0; // reserved\r
+\r
+               // Block length\r
+               uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+               scsiDev.data[idx++] = bytesPerSector >> 16;\r
+               scsiDev.data[idx++] = bytesPerSector >> 8;\r
+               scsiDev.data[idx++] = bytesPerSector & 0xFF;\r
+       }\r
 \r
-                       scsiDev.data[idx++] = 0; // reserved\r
+       int pageFound = 0;\r
 \r
-                       // Block length\r
-                       uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
-                       scsiDev.data[idx++] = bytesPerSector >> 16;\r
-                       scsiDev.data[idx++] = bytesPerSector >> 8;\r
-                       scsiDev.data[idx++] = bytesPerSector & 0xFF;\r
-               }\r
+       if (pageCode == 0x01 || pageCode == 0x3F)\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage));\r
+               idx += sizeof(ReadWriteErrorRecoveryPage);\r
+       }\r
 \r
-               int pageFound = 0;\r
+       if (pageCode == 0x02 || pageCode == 0x3F)\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage));\r
+               idx += sizeof(DisconnectReconnectPage);\r
+       }\r
 \r
-               if (pageCode == 0x01 || pageCode == 0x3F)\r
+       if (pageCode == 0x03 || pageCode == 0x3F)\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage));\r
+               if (pc != 0x01)\r
                {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage));\r
-                       idx += sizeof(ReadWriteErrorRecoveryPage);\r
+                       // Fill out the configured bytes-per-sector\r
+                       uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
+                       scsiDev.data[idx+12] = bytesPerSector >> 8;\r
+                       scsiDev.data[idx+13] = bytesPerSector & 0xFF;\r
                }\r
-\r
-               if (pageCode == 0x02 || pageCode == 0x3F)\r
+               else\r
                {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage));\r
-                       idx += sizeof(DisconnectReconnectPage);\r
+                       // Set a mask for the changeable values.\r
+                       scsiDev.data[idx+12] = 0xFF;\r
+                       scsiDev.data[idx+13] = 0xFF;\r
                }\r
 \r
-               if (pageCode == 0x03 || pageCode == 0x3F)\r
-               {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage));\r
-                       if (pc != 0x01)\r
-                       {\r
-                               // Fill out the configured bytes-per-sector\r
-                               uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
-                               scsiDev.data[idx+12] = bytesPerSector >> 8;\r
-                               scsiDev.data[idx+13] = bytesPerSector & 0xFF;\r
-                       }\r
-                       else\r
-                       {\r
-                               // Set a mask for the changeable values.\r
-                               scsiDev.data[idx+12] = 0xFF;\r
-                               scsiDev.data[idx+13] = 0xFF;\r
-                       }\r
+               idx += sizeof(FormatDevicePage);\r
+       }\r
 \r
-                       idx += sizeof(FormatDevicePage);\r
-               }\r
+       if (pageCode == 0x04 || pageCode == 0x3F)\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry));\r
 \r
-               if (pageCode == 0x04 || pageCode == 0x3F)\r
+               if (pc != 0x01)\r
                {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry));\r
-\r
-                       if (pc != 0x01)\r
-                       {\r
-                               // Need to fill out the number of cylinders.\r
-                               uint32 cyl;\r
-                               uint8 head;\r
-                               uint32 sector;\r
-                               LBA2CHS(\r
-                                       getScsiCapacity(\r
-                                               scsiDev.target->cfg->sdSectorStart,\r
-                                               scsiDev.target->liveCfg.bytesPerSector,\r
-                                               scsiDev.target->cfg->scsiSectors),\r
-                                       &cyl,\r
-                                       &head,\r
-                                       &sector);\r
-\r
-                               scsiDev.data[idx+2] = cyl >> 16;\r
-                               scsiDev.data[idx+3] = cyl >> 8;\r
-                               scsiDev.data[idx+4] = cyl;\r
-\r
-                               memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3);\r
-                               memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3);\r
-                       }\r
-\r
-                       idx += sizeof(RigidDiskDriveGeometry);\r
+                       // Need to fill out the number of cylinders.\r
+                       uint32 cyl;\r
+                       uint8 head;\r
+                       uint32 sector;\r
+                       LBA2CHS(\r
+                               getScsiCapacity(\r
+                                       scsiDev.target->cfg->sdSectorStart,\r
+                                       scsiDev.target->liveCfg.bytesPerSector,\r
+                                       scsiDev.target->cfg->scsiSectors),\r
+                               &cyl,\r
+                               &head,\r
+                               &sector);\r
+\r
+                       scsiDev.data[idx+2] = cyl >> 16;\r
+                       scsiDev.data[idx+3] = cyl >> 8;\r
+                       scsiDev.data[idx+4] = cyl;\r
+\r
+                       memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3);\r
+                       memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3);\r
                }\r
 \r
-               // DON'T output the following pages for SCSI1 hosts. They get upset when\r
-               // we have more data to send than the allocation length provided.\r
-               // (ie. Try not to output any more pages below this comment)\r
+               idx += sizeof(RigidDiskDriveGeometry);\r
+       }\r
 \r
+       // DON'T output the following pages for SCSI1 hosts. They get upset when\r
+       // we have more data to send than the allocation length provided.\r
+       // (ie. Try not to output any more pages below this comment)\r
 \r
-               if (!scsiDev.compatMode && (pageCode == 0x08 || pageCode == 0x3F))\r
-               {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, CachingPage, sizeof(CachingPage));\r
-                       idx += sizeof(CachingPage);\r
-               }\r
 \r
-               if (!scsiDev.compatMode && (pageCode == 0x0A || pageCode == 0x3F))\r
-               {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, ControlModePage, sizeof(ControlModePage));\r
-                       idx += sizeof(ControlModePage);\r
-               }\r
+       if ((scsiDev.compatMode >= COMPAT_SCSI2) &&\r
+               (pageCode == 0x08 || pageCode == 0x3F))\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, CachingPage, sizeof(CachingPage));\r
+               idx += sizeof(CachingPage);\r
+       }\r
 \r
-               if ((\r
-                               (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||\r
-                               (idx + sizeof(AppleVendorPage) <= allocLength)\r
-                       ) &&\r
-                       (pageCode == 0x30 || pageCode == 0x3F))\r
-               {\r
-                       pageFound = 1;\r
-                       pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage));\r
-                       idx += sizeof(AppleVendorPage);\r
-               }\r
+       if ((scsiDev.compatMode >= COMPAT_SCSI2)\r
+               && (pageCode == 0x0A || pageCode == 0x3F))\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, ControlModePage, sizeof(ControlModePage));\r
+               idx += sizeof(ControlModePage);\r
+       }\r
+\r
+       if ((\r
+                       (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||\r
+                       (idx + sizeof(AppleVendorPage) <= allocLength)\r
+               ) &&\r
+               (pageCode == 0x30 || pageCode == 0x3F))\r
+       {\r
+               pageFound = 1;\r
+               pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage));\r
+               idx += sizeof(AppleVendorPage);\r
+       }\r
 \r
-               if (!pageFound)\r
+       if (!pageFound)\r
+       {\r
+               // Unknown Page Code\r
+               pageFound = 0;\r
+               scsiDev.status = CHECK_CONDITION;\r
+               scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
+               scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
+               scsiDev.phase = STATUS;\r
+       }\r
+       else\r
+       {\r
+               // Go back and fill out the mode data length\r
+               if (sixByteCmd)\r
                {\r
-                       // Unknown Page Code\r
-                       pageFound = 0;\r
-                       scsiDev.status = CHECK_CONDITION;\r
-                       scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
-                       scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;\r
-                       scsiDev.phase = STATUS;\r
+                       // Cannot currently exceed limits. yay\r
+                       scsiDev.data[0] = idx - 1;\r
                }\r
                else\r
                {\r
-                       // Go back and fill out the mode data length\r
-                       if (sixByteCmd)\r
-                       {\r
-                               // Cannot currently exceed limits. yay\r
-                               scsiDev.data[0] = idx - 1;\r
-                       }\r
-                       else\r
-                       {\r
-                               scsiDev.data[0] = ((idx - 2) >> 8);\r
-                               scsiDev.data[1] = (idx - 2);\r
-                       }\r
-\r
-                       scsiDev.dataLen = idx > allocLength ? allocLength : idx;\r
-                       scsiDev.phase = DATA_IN;\r
+                       scsiDev.data[0] = ((idx - 2) >> 8);\r
+                       scsiDev.data[1] = (idx - 2);\r
                }\r
+\r
+               scsiDev.dataLen = idx > allocLength ? allocLength : idx;\r
+               scsiDev.phase = DATA_IN;\r
        }\r
 }\r
 \r
+\r
 // Callback after the DATA OUT phase is complete.\r
 static void doModeSelect(void)\r
 {\r
index 15622d5..0e5a78d 100755 (executable)
@@ -53,7 +53,7 @@ static void enter_BusFree()
 {\r
        // This delay probably isn't needed for most SCSI hosts, but it won't\r
        // hurt either. It's possible some of the samplers needed this delay.\r
-       if (scsiDev.compatMode)\r
+       if (scsiDev.compatMode < COMPAT_SCSI2)\r
        {\r
                CyDelayUs(2);\r
        }\r
@@ -214,7 +214,7 @@ static void process_DataOut()
 \r
                if (scsiDev.parityError &&\r
                        (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-                       !scsiDev.compatMode)\r
+                       (scsiDev.compatMode >= COMPAT_SCSI2))\r
                {\r
                        scsiDev.target->sense.code = ABORTED_COMMAND;\r
                        scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
@@ -274,7 +274,7 @@ static void process_Command()
        }\r
        else if (scsiDev.parityError &&\r
                (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-               !scsiDev.compatMode)\r
+               (scsiDev.compatMode >= COMPAT_SCSI2))\r
        {\r
                scsiDev.target->sense.code = ABORTED_COMMAND;\r
                scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
@@ -459,6 +459,7 @@ static void scsiReset()
        scsiDev.atnFlag = 0;\r
        scsiDev.resetFlag = 0;\r
        scsiDev.lun = -1;\r
+       scsiDev.compatMode = COMPAT_UNKNOWN;\r
 \r
        if (scsiDev.target)\r
        {\r
@@ -500,7 +501,6 @@ static void enter_SelectionPhase()
        scsiDev.phase = SELECTION;\r
        scsiDev.lun = -1;\r
        scsiDev.discPriv = 0;\r
-       scsiDev.compatMode = 0;\r
 \r
        scsiDev.initiatorId = -1;\r
        scsiDev.target = NULL;\r
@@ -513,6 +513,12 @@ static void enter_SelectionPhase()
 \r
 static void process_SelectionPhase()\r
 {\r
+       if (scsiDev.compatMode < COMPAT_SCSI2)\r
+       {\r
+               // Required for some older SCSI1 devices using a 5380 chip.\r
+               CyDelayUs(100);\r
+       }\r
+\r
        int sel = SCSI_ReadFilt(SCSI_Filt_SEL);\r
        int bsy = SCSI_ReadFilt(SCSI_Filt_BSY);\r
 \r
@@ -552,7 +558,11 @@ static void process_SelectionPhase()
                if (!scsiDev.atnFlag)\r
                {\r
                        target->unitAttention = 0;\r
-                       scsiDev.compatMode = 1;\r
+                       scsiDev.compatMode = COMPAT_SCSI1;\r
+               }\r
+               else if (scsiDev.compatMode == COMPAT_UNKNOWN)\r
+               {\r
+                       scsiDev.compatMode = COMPAT_SCSI2;\r
                }\r
 \r
                // We've been selected!\r
@@ -611,7 +621,7 @@ static void process_MessageOut()
 \r
        if (scsiDev.parityError &&\r
                (scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&\r
-               !scsiDev.compatMode)\r
+               (scsiDev.compatMode >= COMPAT_SCSI2))\r
        {\r
                // Skip the remaining message bytes, and then start the MESSAGE_OUT\r
                // phase again from the start. The initiator will re-send the\r
@@ -872,6 +882,7 @@ void scsiInit()
        scsiDev.resetFlag = 1;\r
        scsiDev.phase = BUS_FREE;\r
        scsiDev.target = NULL;\r
+       scsiDev.compatMode = COMPAT_UNKNOWN;\r
 \r
        int i;\r
        for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
index 2a48af3..adb61c8 100755 (executable)
@@ -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
index 5952b85..900192b 100755 (executable)
@@ -447,4 +447,87 @@ void scsiPhyInit()
 \r
        SCSI_RST_ISR_StartEx(scsiResetISR);\r
 }\r
+\r
+// 1 = DBx error\r
+// 2 = Parity error\r
+// 4 = MSG error\r
+// 8 = CD error\r
+// 16 = IO error\r
+// 32 = other error\r
+int scsiSelfTest()\r
+{\r
+       int result = 0;\r
+\r
+       // TEST DBx and DBp\r
+       int i;\r
+       SCSI_Out_Ctl_Write(1); // Write bits manually.\r
+       SCSI_CTL_PHASE_Write(__scsiphase_io); // Needed for parity generation\r
+       for (i = 0; i < 256; ++i)\r
+       {\r
+               SCSI_Out_Bits_Write(i);\r
+               scsiDeskewDelay();\r
+               if (scsiReadDBxPins() != (i & 0xff))\r
+               {\r
+                       result |= 1;\r
+               }\r
+               if (Lookup_OddParity[i & 0xff] != SCSI_ReadPin(SCSI_In_DBP))\r
+               {\r
+                       result |= 2;\r
+               }\r
+       }\r
+       SCSI_Out_Ctl_Write(0); // Write bits normally.\r
+\r
+       // TEST MSG, CD, IO\r
+       for (i = 0; i < 8; ++i)\r
+       {\r
+               SCSI_CTL_PHASE_Write(i);\r
+               scsiDeskewDelay();\r
+\r
+               if (SCSI_ReadPin(SCSI_In_MSG) != !!(i & __scsiphase_msg))\r
+               {\r
+                       result |= 4;\r
+               }\r
+               if (SCSI_ReadPin(SCSI_In_CD) != !!(i & __scsiphase_cd))\r
+               {\r
+                       result |= 8;\r
+               }\r
+               if (SCSI_ReadPin(SCSI_In_IO) != !!(i & __scsiphase_io))\r
+               {\r
+                       result |= 16;\r
+               }\r
+       }\r
+       SCSI_CTL_PHASE_Write(0);\r
+\r
+       uint32_t signalsOut[] = { SCSI_Out_ATN, SCSI_Out_BSY, SCSI_Out_RST, SCSI_Out_SEL };\r
+       uint32_t signalsIn[] = { SCSI_Filt_ATN, SCSI_Filt_BSY, SCSI_Filt_RST, SCSI_Filt_SEL };\r
+\r
+       for (i = 0; i < 4; ++i)\r
+       {\r
+               SCSI_SetPin(signalsOut[i]);\r
+               scsiDeskewDelay();\r
+\r
+               int j;\r
+               for (j = 0; j < 4; ++j)\r
+               {\r
+                       if (i == j)\r
+                       {\r
+                               if (! SCSI_ReadFilt(signalsIn[j]))\r
+                               {\r
+                                       result |= 32;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if (SCSI_ReadFilt(signalsIn[j]))\r
+                               {\r
+                                       result |= 32;\r
+                               }\r
+                       }\r
+               }\r
+               SCSI_ClearPin(signalsOut[i]);\r
+       }\r
+       return result;\r
+}\r
+\r
+\r
 #pragma GCC pop_options\r
index b4c0f79..006107b 100755 (executable)
@@ -88,4 +88,6 @@ uint8_t scsiReadDBxPins(void);
 
 void scsiEnterPhase(int phase);
 
+int scsiSelfTest(void);
+
 #endif
index 0db6988..6df123e 100644 (file)
 #define USBFS_arb_int__INTC_CLR_PD_REG CYREG_NVIC_CLRPEND0\r
 #define USBFS_arb_int__INTC_MASK 0x400000u\r
 #define USBFS_arb_int__INTC_NUMBER 22u\r
-#define USBFS_arb_int__INTC_PRIOR_NUM 7u\r
+#define USBFS_arb_int__INTC_PRIOR_NUM 6u\r
 #define USBFS_arb_int__INTC_PRIOR_REG CYREG_NVIC_PRI_22\r
 #define USBFS_arb_int__INTC_SET_EN_REG CYREG_NVIC_SETENA0\r
 #define USBFS_arb_int__INTC_SET_PD_REG CYREG_NVIC_SETPEND0\r
index 6c74b5f..a7a6401 100644 (file)
 .set USBFS_arb_int__INTC_CLR_PD_REG, CYREG_NVIC_CLRPEND0\r
 .set USBFS_arb_int__INTC_MASK, 0x400000\r
 .set USBFS_arb_int__INTC_NUMBER, 22\r
-.set USBFS_arb_int__INTC_PRIOR_NUM, 7\r
+.set USBFS_arb_int__INTC_PRIOR_NUM, 6\r
 .set USBFS_arb_int__INTC_PRIOR_REG, CYREG_NVIC_PRI_22\r
 .set USBFS_arb_int__INTC_SET_EN_REG, CYREG_NVIC_SETENA0\r
 .set USBFS_arb_int__INTC_SET_PD_REG, CYREG_NVIC_SETPEND0\r
index ec34581..dc75761 100644 (file)
@@ -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\r
 USBFS_arb_int__INTC_MASK EQU 0x400000\r
 USBFS_arb_int__INTC_NUMBER EQU 22\r
-USBFS_arb_int__INTC_PRIOR_NUM EQU 7\r
+USBFS_arb_int__INTC_PRIOR_NUM EQU 6\r
 USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22\r
 USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0\r
 USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0\r
index be5a1f5..aba1877 100644 (file)
@@ -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\r
 USBFS_arb_int__INTC_MASK EQU 0x400000\r
 USBFS_arb_int__INTC_NUMBER EQU 22\r
-USBFS_arb_int__INTC_PRIOR_NUM EQU 7\r
+USBFS_arb_int__INTC_PRIOR_NUM EQU 6\r
 USBFS_arb_int__INTC_PRIOR_REG EQU CYREG_NVIC_PRI_22\r
 USBFS_arb_int__INTC_SET_EN_REG EQU CYREG_NVIC_SETENA0\r
 USBFS_arb_int__INTC_SET_PD_REG EQU CYREG_NVIC_SETPEND0\r
index c07d021..efccf01 100644 (file)
@@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used))
 const uint8 cy_meta_loadable[] = {\r
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,\r
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,\r
-    0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x20u, 0x04u,\r
+    0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x22u, 0x04u,\r
     0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,\r
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,\r
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,\r
index afd7982..bcf9ae3 100644 (file)
Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit differ
index 2f7d469..e30584e 100755 (executable)
 <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@General@Enable printf Float" v="True" />\r
 <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Optimization Level" v="Size" />\r
 <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Remove Unused Functions" v="True" />\r
-<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="" />\r
+<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="-Wl,--section-start=.DEFAULT_CONFIG=0x0001BC00" />\r
 </name>\r
 </platform>\r
 <platform>\r
index e5f05a0..285360e 100755 (executable)
Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ
index ae0e2a0..159ba3d 100644 (file)
 #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
 #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
 #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
index be56b15..0b4af89 100644 (file)
 .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
 .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
 .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
index a59ad0e..b6c06fb 100644 (file)
@@ -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
index f2b9e4c..4cc15c6 100644 (file)
@@ -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
index dfaca9d..ee269a7 100644 (file)
@@ -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,
index 7cb75d6..239ad50 100644 (file)
Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit differ
index 0f6ea55..465dede 100755 (executable)
 <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@General@Enable printf Float" v="True" />
 <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Optimization Level" v="Size" />
 <name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Optimization@Remove Unused Functions" v="True" />
-<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="" />
+<name_val_pair name="c9323d49-d323-40b8-9b59-cc008d68a989@Release@CortexM3@Linker@Command Line@Command Line" v="-Wl,--section-start=.DEFAULT_CONFIG=0x0001BC00" />
 </name>
 </platform>
 <platform>
index 99cb769..71ca821 100755 (executable)
Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ
index cec7485..3e8cf47 100755 (executable)
@@ -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
index e717cf8..446a91b 100644 (file)
@@ -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<uint8_t>(begin, begin + sizeof(config));
 }
 
+/*
 wxXmlNode*
 ConfigUtil::toXML(const TargetConfig& config)
 {
@@ -203,3 +203,4 @@ ConfigUtil::deserialise(const std::string& in)
 {
 
 }
+*/
index d1ae745..22794df 100755 (executable)
@@ -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 $@
 
index b2aa4d0..df83b67 100644 (file)
@@ -338,7 +338,7 @@ HID::getSD_CSD()
        std::vector<uint8_t> out;
        try
        {
-               sendHIDPacket(cmd, out, 1);
+               sendHIDPacket(cmd, out, 16);
        }
        catch (std::runtime_error& e)
        {
@@ -356,7 +356,7 @@ HID::getSD_CID()
        std::vector<uint8_t> 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<uint8_t> cmd { CONFIG_SCSITEST };
+       std::vector<uint8_t> 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<uint8_t>& cmd,
index 443b3df..2cf1747 100644 (file)
@@ -58,6 +58,8 @@ public:
        std::vector<uint8_t> getSD_CSD();
        std::vector<uint8_t> getSD_CID();
 
+       bool scsiSelfTest();
+
        void enterBootloader();
 
        void readFlashRow(int array, int row, std::vector<uint8_t>& out);
diff --git a/software/scsi2sd-util/scsi2sd-monitor.cc b/software/scsi2sd-util/scsi2sd-monitor.cc
new file mode 100644 (file)
index 0000000..872001a
--- /dev/null
@@ -0,0 +1,288 @@
+//     Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
+//
+//     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 <http://www.gnu.org/licenses/>.
+
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include <wx/wxprec.h>
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/filedlg.h>
+#include <wx/filefn.h>
+#include <wx/filename.h>
+#include <wx/log.h>
+#include <wx/notebook.h>
+#include <wx/progdlg.h>
+#include <wx/utils.h>
+#include <wx/windowptr.h>
+#include <wx/thread.h>
+
+#include <zipper.hh>
+
+#include "ConfigUtil.hh"
+#include "TargetPanel.hh"
+#include "SCSI2SD_Bootloader.hh"
+#include "SCSI2SD_HID.hh"
+#include "Firmware.hh"
+
+#include <algorithm>
+#include <iomanip>
+#include <vector>
+#include <set>
+#include <sstream>
+
+#if __cplusplus >= 201103L
+#include <cstdint>
+#include <memory>
+using std::shared_ptr;
+#else
+#include <stdint.h>
+#include <tr1/memory>
+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<HID> myHID;
+       shared_ptr<Bootloader> 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<uint8_t> csd(myHID->getSD_CSD());
+                       std::vector<uint8_t> 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);
+
+
index cc26e8b..6e3e782 100644 (file)
@@ -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<HID> myHID;
        shared_ptr<Bootloader> 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);