Merge branch 'master' of ssh://webhost.codesrc.com/home/michael/projects/SCSI2SD
[SCSI2SD.git] / software / SCSI2SD / src / mode.c
index 4ed790f..b7bd9c0 100755 (executable)
@@ -51,6 +51,18 @@ static const uint8 ReadWriteErrorRecoveryPage[] =
 0x00, 0x00 // Recovery time limit 0 (use default)*/\r
 };\r
 \r
+static const uint8 ReadWriteErrorRecoveryPage_SCSI1[] =\r
+{\r
+0x01, // Page code\r
+0x06, // Page length\r
+0x26,\r
+0x00, // Don't try recovery algorithm during reads\r
+0x00, // Correction span 0\r
+0x00, // Head offset count 0,\r
+0x00, // Data strobe offset count 0,\r
+0xFF // Reserved\r
+};\r
+\r
 static const uint8 DisconnectReconnectPage[] =\r
 {\r
 0x02, // Page code\r
@@ -65,6 +77,18 @@ static const uint8 DisconnectReconnectPage[] =
 0x00, 0x00, 0x00 // Reserved\r
 };\r
 \r
+static const uint8 DisconnectReconnectPage_SCSI1[] =\r
+{\r
+0x02, // Page code\r
+0x0A, // Page length\r
+0, // Buffer full ratio\r
+0, // Buffer empty ratio\r
+0x00, 10, // Bus inactivity limit, 100us increments. Allow 1ms.\r
+0x00, 0x00, // Disconnect time limit\r
+0x00, 0x00, // Connect time limit\r
+0x00, 0x00 // Maximum burst size\r
+};\r
+\r
 static const uint8 FormatDevicePage[] =\r
 {\r
 0x03 | 0x80, // Page code | PS (persist) bit.\r
@@ -73,7 +97,7 @@ static const uint8 FormatDevicePage[] =
 0x00, 0x00, // No alternate sectors\r
 0x00, 0x00, // No alternate tracks\r
 0x00, 0x00, // No alternate tracks per lun\r
-0x00, SCSI_SECTORS_PER_TRACK, // Sectors per track\r
+0x00, 0x00, // Sectors per track, configurable\r
 0xFF, 0xFF, // Data bytes per physical sector. Configurable.\r
 0x00, 0x01, // Interleave\r
 0x00, 0x00, // Track skew factor\r
@@ -87,7 +111,7 @@ static const uint8 RigidDiskDriveGeometry[] =
 0x04, // Page code\r
 0x16, // Page length\r
 0xFF, 0xFF, 0xFF, // Number of cylinders\r
-SCSI_HEADS_PER_CYLINDER, // Number of heads\r
+0x00, // Number of heads (replaced by configured value)\r
 0xFF, 0xFF, 0xFF, // Starting cylinder-write precompensation\r
 0xFF, 0xFF, 0xFF, // Starting cylinder-reduced write current\r
 0x00, 0x1, // Drive step rate (units of 100ns)\r
@@ -99,6 +123,21 @@ SCSI_HEADS_PER_CYLINDER, // Number of heads
 0x00, 0x00 // Reserved\r
 };\r
 \r
+static const uint8 RigidDiskDriveGeometry_SCSI1[] =\r
+{\r
+0x04, // Page code\r
+0x12, // Page length\r
+0xFF, 0xFF, 0xFF, // Number of cylinders\r
+0x00, // Number of heads (replaced by configured value)\r
+0xFF, 0xFF, 0xFF, // Starting cylinder-write precompensation\r
+0xFF, 0xFF, 0xFF, // Starting cylinder-reduced write current\r
+0x00, 0x1, // Drive step rate (units of 100ns)\r
+0x00, 0x00, 0x00, // Landing zone cylinder\r
+0x00, // RPL\r
+0x00, // Rotational offset\r
+0x00 // Reserved\r
+};\r
+\r
 static const uint8 CachingPage[] =\r
 {\r
 0x08, // Page Code\r
@@ -122,6 +161,22 @@ static const uint8 ControlModePage[] =
 0x00, 0x00 // AEN holdoff period.\r
 };\r
 \r
+static const uint8_t SequentialDeviceConfigPage[] =\r
+{\r
+0x10, // page code\r
+0x0E, // Page length\r
+0x00, // CAP, CAF, Active Format\r
+0x00, // Active partition\r
+0x00, // Write buffer full ratio\r
+0x00, // Read buffer empty ratio\r
+0x00,0x01, // Write delay time, in 100ms units\r
+0x00, // Default gap size\r
+0x10, // auto-generation of default eod (end of data)\r
+0x00,0x00,0x00 // buffer-size at early warning\r
+0x00, // No data compression\r
+0x00 // reserved\r
+};\r
+\r
 // Allow Apple 68k Drive Setup to format this drive.\r
 // Code\r
 static const uint8 AppleVendorPage[] =\r
@@ -179,6 +234,17 @@ static void doModeSense(
                density = 0x01; // User data only, 2048bytes per sector.\r
                break;\r
 \r
+       case CONFIG_SEQUENTIAL:\r
+               mediumType = 0; // reserved\r
+               deviceSpecificParam =\r
+                       (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+               density = 0x13; // DAT Data Storage, X3B5/88-185A \r
+               break;\r
+\r
+       case CONFIG_MO:\r
+               TODO\r
+               break;\r
+\r
        };\r
 \r
        scsiDev.data[idx++] = mediumType;\r
@@ -239,15 +305,31 @@ static void doModeSense(
        if (pageCode == 0x01 || pageCode == 0x3F)\r
        {\r
                pageFound = 1;\r
-               pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage));\r
-               idx += sizeof(ReadWriteErrorRecoveryPage);\r
+               if ((scsiDev.compatMode >= COMPAT_SCSI2))\r
+               {\r
+                       pageIn(pc, idx, ReadWriteErrorRecoveryPage, sizeof(ReadWriteErrorRecoveryPage));\r
+                       idx += sizeof(ReadWriteErrorRecoveryPage);\r
+               }\r
+               else\r
+               {\r
+                       pageIn(pc, idx, ReadWriteErrorRecoveryPage_SCSI1, sizeof(ReadWriteErrorRecoveryPage_SCSI1));\r
+                       idx += sizeof(ReadWriteErrorRecoveryPage_SCSI1);\r
+               }\r
        }\r
 \r
        if (pageCode == 0x02 || pageCode == 0x3F)\r
        {\r
                pageFound = 1;\r
-               pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage));\r
-               idx += sizeof(DisconnectReconnectPage);\r
+               if ((scsiDev.compatMode >= COMPAT_SCSI2))\r
+               {\r
+                       pageIn(pc, idx, DisconnectReconnectPage, sizeof(DisconnectReconnectPage));\r
+                       idx += sizeof(DisconnectReconnectPage);\r
+               }\r
+               else\r
+               {\r
+                       pageIn(pc, idx, DisconnectReconnectPage_SCSI1, sizeof(DisconnectReconnectPage_SCSI1));\r
+                       idx += sizeof(DisconnectReconnectPage_SCSI1);\r
+               }\r
        }\r
 \r
        if (pageCode == 0x03 || pageCode == 0x3F)\r
@@ -256,6 +338,10 @@ static void doModeSense(
                pageIn(pc, idx, FormatDevicePage, sizeof(FormatDevicePage));\r
                if (pc != 0x01)\r
                {\r
+                       uint16_t sectorsPerTrack = scsiDev.target->cfg->sectorsPerTrack;\r
+                       scsiDev.data[idx+10] = sectorsPerTrack >> 8;\r
+                       scsiDev.data[idx+11] = sectorsPerTrack & 0xFF;\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
@@ -274,7 +360,14 @@ static void doModeSense(
        if (pageCode == 0x04 || pageCode == 0x3F)\r
        {\r
                pageFound = 1;\r
-               pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry));\r
+               if ((scsiDev.compatMode >= COMPAT_SCSI2))\r
+               {\r
+                       pageIn(pc, idx, RigidDiskDriveGeometry, sizeof(RigidDiskDriveGeometry));\r
+               }\r
+               else\r
+               {\r
+                       pageIn(pc, idx, RigidDiskDriveGeometry_SCSI1, sizeof(RigidDiskDriveGeometry_SCSI1));\r
+               }\r
 \r
                if (pc != 0x01)\r
                {\r
@@ -289,7 +382,9 @@ static void doModeSense(
                                        scsiDev.target->cfg->scsiSectors),\r
                                &cyl,\r
                                &head,\r
-                               &sector);\r
+                               &sector,\r
+                               scsiDev.target->cfg->headsPerCylinder,\r
+                               scsiDev.target->cfg->sectorsPerTrack);\r
 \r
                        scsiDev.data[idx+2] = cyl >> 16;\r
                        scsiDev.data[idx+3] = cyl >> 8;\r
@@ -297,9 +392,18 @@ static void doModeSense(
 \r
                        memcpy(&scsiDev.data[idx+6], &scsiDev.data[idx+2], 3);\r
                        memcpy(&scsiDev.data[idx+9], &scsiDev.data[idx+2], 3);\r
+\r
+                       scsiDev.data[idx+5] = scsiDev.target->cfg->headsPerCylinder;\r
                }\r
 \r
-               idx += sizeof(RigidDiskDriveGeometry);\r
+               if ((scsiDev.compatMode >= COMPAT_SCSI2))\r
+               {\r
+                       idx += sizeof(RigidDiskDriveGeometry);\r
+               }\r
+               else\r
+               {\r
+                       idx += sizeof(RigidDiskDriveGeometry_SCSI1);\r
+               }\r
        }\r
 \r
        // DON'T output the following pages for SCSI1 hosts. They get upset when\r
@@ -323,6 +427,18 @@ static void doModeSense(
                idx += sizeof(ControlModePage);\r
        }\r
 \r
+       if ((scsiDev.target->cfg->deviceType == CONFIG_SEQUENTIAL) &&\r
+               (pageCode == 0x10 || pageCode == 0x3F))\r
+       {\r
+               pageFound = 1;\r
+               pageIn(\r
+                       pc,\r
+                       idx,\r
+                       SequentialDeviceConfigPage,\r
+                       sizeof(SequentialDeviceConfigPage));\r
+               idx += sizeof(SequentialDeviceConfigPage);\r
+       }\r
+\r
        if ((\r
                        (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||\r
                        (idx + sizeof(AppleVendorPage) <= allocLength)\r
@@ -474,7 +590,10 @@ int scsiModeCommand()
                int pc = scsiDev.cdb[2] >> 6; // Page Control\r
                int pageCode = scsiDev.cdb[2] & 0x3F;\r
                int allocLength = scsiDev.cdb[4];\r
-               if (allocLength == 0) allocLength = 256;\r
+\r
+               // SCSI1 standard: (CCS X3T9.2/86-52)\r
+               // "An Allocation Length of zero indicates that no MODE SENSE data shall\r
+               // be transferred. This condition shall not be considered as an error."\r
                doModeSense(1, dbd, pc, pageCode, allocLength);\r
        }\r
        else if (command == 0x5A)\r