Fix for VMS 5.5-2 for incorrect Inquiry command allocation lengths
[SCSI2SD.git] / software / SCSI2SD / src / inquiry.c
index 9e7c706..3b84c52 100755 (executable)
@@ -1,4 +1,5 @@
 //     Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
+//     Copyright (C) 2019 Landon Rodgers  <g.landon.rodgers@gmail.com>
 //
 //     This file is part of SCSI2SD.
 //
@@ -14,9 +15,6 @@
 //
 //     You should have received a copy of the GNU General Public License
 //     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
-#pragma GCC push_options
-#pragma GCC optimize("-flto")
-
 #include "device.h"
 #include "scsi.h"
 #include "config.h"
@@ -160,6 +158,7 @@ void scsiInquiry()
                        memcpy(&scsiDev.data[8], config->vendor, sizeof(config->vendor));
                        memcpy(&scsiDev.data[16], config->prodId, sizeof(config->prodId));
                        memcpy(&scsiDev.data[32], config->revision, sizeof(config->revision));
+
                        scsiDev.dataLen = sizeof(StandardResponse) +
                                sizeof(config->vendor) +
                                sizeof(config->prodId) +
@@ -181,6 +180,7 @@ void scsiInquiry()
        {
                memcpy(scsiDev.data, UnitSerialNumber, sizeof(UnitSerialNumber));
                scsiDev.dataLen = sizeof(UnitSerialNumber);
+               const TargetConfig* config = scsiDev.target->cfg;
                memcpy(&scsiDev.data[4], config->serial, sizeof(config->serial));
                scsiDev.phase = DATA_IN;
        }
@@ -214,6 +214,13 @@ void scsiInquiry()
 
        if (scsiDev.phase == DATA_IN)
        {
+               // VAX workaround
+               if (allocationLength == 255 &&
+                       (scsiDev.target->cfg->quirks & CONFIG_QUIRKS_VMS))
+               {
+                       allocationLength = 254;
+               }
+
                // "real" hard drives send back exactly allocationLenth bytes, padded
                // with zeroes. This only seems to happen for Inquiry responses, and not
                // other commands that also supply an allocation length such as Mode Sense or
@@ -231,20 +238,19 @@ void scsiInquiry()
                scsiDev.dataLen = allocationLength;
 
                // Set the device type as needed.
+               scsiDev.data[0] = getDeviceTypeQualifier();
+
                switch (scsiDev.target->cfg->deviceType)
                {
                case CONFIG_OPTICAL:
-                       scsiDev.data[0] = 0x05; // device type
                        scsiDev.data[1] |= 0x80; // Removable bit.
                        break;
 
                case CONFIG_SEQUENTIAL:
-                       scsiDev.data[0] = 0x01; // device type
                        scsiDev.data[1] |= 0x80; // Removable bit.
                        break;
                        
                case CONFIG_MO:
-                       scsiDev.data[0] = 0x07; // device type
                        scsiDev.data[1] |= 0x80; // Removable bit.
                        break;
 
@@ -256,6 +262,7 @@ void scsiInquiry()
                        // Accept defaults for a fixed disk.
                        break;
                }
+
        }
 
        // Set the first byte to indicate LUN presence.
@@ -265,4 +272,31 @@ void scsiInquiry()
        }
 }
 
-#pragma GCC pop_options
+uint8_t getDeviceTypeQualifier()
+{
+       // Set the device type as needed.
+       switch (scsiDev.target->cfg->deviceType)
+       {
+       case CONFIG_OPTICAL:
+               return 0x05;
+               break;
+
+       case CONFIG_SEQUENTIAL:
+               return 0x01;
+               break;
+
+       case CONFIG_MO:
+               return 0x07;
+               break;
+
+       case CONFIG_FLOPPY_14MB:
+       case CONFIG_REMOVEABLE:
+               return 0;
+               break;
+
+       default:
+               // Accept defaults for a fixed disk.
+               return 0;
+       }
+}
+