Merge branch 'master' of ssh://webhost.codesrc.com/home/michael/projects/SCSI2SD
[SCSI2SD.git] / software / SCSI2SD / src / mode.c
index b234549..b7bd9c0 100755 (executable)
@@ -97,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
@@ -111,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
@@ -128,7 +128,7 @@ static const uint8 RigidDiskDriveGeometry_SCSI1[] =
 0x04, // Page code\r
 0x12, // 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
@@ -161,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
@@ -218,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
@@ -311,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
@@ -351,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
@@ -359,6 +392,8 @@ 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
                if ((scsiDev.compatMode >= COMPAT_SCSI2))\r
@@ -392,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
@@ -543,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