Fix completely broken MODE SELECT.
authorMichael McMaster <michael@codesrc.com>
Wed, 16 Apr 2014 10:43:43 +0000 (20:43 +1000)
committerMichael McMaster <michael@codesrc.com>
Wed, 16 Apr 2014 10:43:43 +0000 (20:43 +1000)
Setting the blocksize via a MODE SELECT works now.

software/SCSI2SD/src/mode.c
software/SCSI2SD/src/scsi.c

index 385fdf8..21ddadd 100755 (executable)
@@ -329,18 +329,39 @@ static void doModeSelect(void)
                // scsiDev.dataLen bytes are in scsiDev.data\r
 \r
                int idx;\r
-               if (scsiDev.cdb[0] == 0x15)\r
+               int blockDescLen;\r
+               if (scsiDev.cdb[0] == 0x55)\r
                {\r
-                       int blockDescLen =\r
+                       blockDescLen =\r
                                (((uint16_t)scsiDev.data[6]) << 8) |scsiDev.data[7];\r
-                       idx = 8 + blockDescLen;\r
+                       idx = 8;\r
                }\r
                else\r
                {\r
-                       int blockDescLen = scsiDev.data[3];\r
-                       idx = 4 + blockDescLen;\r
+                       blockDescLen = scsiDev.data[3];\r
+                       idx = 4;\r
                }\r
-               if (idx > scsiDev.dataLen) goto bad;\r
+               \r
+               // The unwritten rule.  Blocksizes are normally set using the\r
+               // block descriptor value, not by changing page 0x03.\r
+               if (blockDescLen >= 8)\r
+               {\r
+                       uint32_t bytesPerSector =\r
+                               (((uint32_t)scsiDev.data[idx+5]) << 16) |\r
+                               (((uint32_t)scsiDev.data[idx+6]) << 8) |\r
+                               scsiDev.data[idx+7];\r
+                       if ((bytesPerSector < MIN_SECTOR_SIZE) ||\r
+                               (bytesPerSector > MAX_SECTOR_SIZE))\r
+                       {\r
+                               goto bad;\r
+                       }\r
+                       else if (bytesPerSector != config->bytesPerSector)\r
+                       {\r
+                               config->bytesPerSector = bytesPerSector;\r
+                               configSave();\r
+                       }\r
+               }\r
+               idx += blockDescLen;\r
 \r
                while (idx < scsiDev.dataLen)\r
                {\r
@@ -373,9 +394,12 @@ static void doModeSelect(void)
                                }\r
                        }\r
                        break;\r
-                       default:\r
-                               goto bad;\r
+                       //default:\r
+                       \r
+                               // Easiest to just ignore for now. We'll get here when changing\r
+                               // the SCSI block size via the descriptor header.\r
                        }\r
+                       idx += 2 + pageLen;\r
                }\r
        }\r
 \r
index 581c17a..3751833 100755 (executable)
@@ -178,14 +178,7 @@ static void process_DataIn()
        if ((scsiDev.dataPtr >= scsiDev.dataLen) &&\r
                (transfer.currentBlock == transfer.blocks))\r
        {\r
-               if (scsiDev.postDataOutHook != NULL)\r
-               {\r
-                       scsiDev.postDataOutHook();\r
-               }\r
-               else\r
-               {\r
-                       enter_Status(GOOD);\r
-               }\r
+               enter_Status(GOOD);\r
        }\r
 }\r
 \r
@@ -219,7 +212,14 @@ static void process_DataOut()
        if ((scsiDev.dataPtr >= scsiDev.dataLen) &&\r
                (transfer.currentBlock == transfer.blocks))\r
        {\r
-               enter_Status(GOOD);\r
+               if (scsiDev.postDataOutHook != NULL)\r
+               {\r
+                       scsiDev.postDataOutHook();\r
+               }\r
+               else\r
+               {\r
+                       enter_Status(GOOD);\r
+               }\r
        }\r
 }\r
 \r