Bläddra i källkod

Merge pull request #251 from ZuluSCSI/dev_cd_tray_inquiry

Improve CD image switching logic
Alex Perez 2 år sedan
förälder
incheckning
76c0d99144
4 ändrade filer med 60 tillägg och 33 borttagningar
  1. 23 18
      src/ZuluSCSI_cdrom.cpp
  2. 5 1
      src/ZuluSCSI_cdrom.h
  3. 21 10
      src/ZuluSCSI_disk.cpp
  4. 11 4
      src/ZuluSCSI_disk.h

+ 23 - 18
src/ZuluSCSI_cdrom.cpp

@@ -1148,6 +1148,20 @@ bool cdromValidateCueSheet(image_config_t &img)
 /* Ejection and image switching logic */
 /**************************************/
 
+// Close CDROM tray and note media change event
+void cdromCloseTray(image_config_t &img)
+{
+    if (img.ejected)
+    {
+        uint8_t target = img.scsiId & 7;
+        dbgmsg("------ CDROM close tray on ID ", (int)target);
+        img.ejected = false;
+        img.cdrom_events = 2; // New media
+    }
+}
+
+// Eject CDROM tray if closed, close if open
+// Switch image on ejection.
 void cdromPerformEject(image_config_t &img)
 {
     uint8_t target = img.scsiId & 7;
@@ -1160,16 +1174,11 @@ void cdromPerformEject(image_config_t &img)
         dbgmsg("------ CDROM open tray on ID ", (int)target);
         img.ejected = true;
         img.cdrom_events = 3; // Media removal
+        cdromSwitchNextImage(img); // Switch media for next time
     }
     else
     {
-        dbgmsg("------ CDROM close tray on ID ", (int)target);
-        if (!cdromSwitchNextImage(img))
-        {
-            // Reinsert the single image
-            img.ejected = false;
-            img.cdrom_events = 2; // New media
-        }
+        cdromCloseTray(img);
     }
 }
 
@@ -1179,17 +1188,16 @@ void cdromReinsertFirstImage(image_config_t &img)
     if (img.image_index > 0)
     {
         // Multiple images for this drive, force restart from first one
-        dbgmsg("---- Restarting from first CD-ROM image");
-        img.image_index = IMAGE_INDEX_MAX;
+        uint8_t target = img.scsiId & 7;
+        dbgmsg("---- Restarting from first CD-ROM image for ID ", (int)target);
+        img.image_index = -1;
         img.current_image[0] = '\0';
         cdromSwitchNextImage(img);
     }
     else if (img.ejected)
     {
         // Reinsert the single image
-        dbgmsg("---- Closing CD-ROM tray");
-        img.ejected = false;
-        img.cdrom_events = 2; // New media
+        cdromCloseTray(img);
     }
 }
 
@@ -1216,8 +1224,6 @@ bool cdromSwitchNextImage(image_config_t &img)
 
         if (status)
         {
-            img.ejected = false;
-            img.cdrom_events = 2; // New media
             return true;
         }
     }
@@ -1255,7 +1261,7 @@ static void doGetEventStatusNotification(bool immed)
         {
             // We are now reporting to host that the drive is open.
             // Simulate a "close" for next time the host polls.
-            cdromSwitchNextImage(img);
+            cdromCloseTray(img);
         }
     }
     else
@@ -1849,12 +1855,11 @@ extern "C" int scsiCDRomCommand()
             int start = scsiDev.cdb[4] & 1;
             if (start)
             {
-                dbgmsg("------ CDROM close tray on ID ", (int)(img.scsiId & 7));
-                img.ejected = false;
-                img.cdrom_events = 2; // New media
+                cdromCloseTray(img);
             }
             else
             {
+                // Eject and switch image
                 cdromPerformEject(img);
             }
         }

+ 5 - 1
src/ZuluSCSI_cdrom.h

@@ -11,7 +11,11 @@
 // Called by scsi.c from SCSI2SD
 extern "C" int scsiCDRomCommand(void);
 
-// Eject the given CD-ROM
+// Close CDROM tray and note media change event
+void cdromCloseTray(image_config_t &img);
+
+// Eject CDROM tray if closed, close if open
+// Switch image on ejection.
 void cdromPerformEject(image_config_t &img);
 
 // Reinsert ejected CD-ROM and restart from first image

+ 21 - 10
src/ZuluSCSI_disk.cpp

@@ -163,7 +163,16 @@ static image_config_t g_DiskImages[S2S_MAX_TARGETS];
 
 void scsiDiskResetImages()
 {
-    memset(g_DiskImages, 0, sizeof(g_DiskImages));
+    for (int i = 0; i < S2S_MAX_TARGETS; i++)
+    {
+        g_DiskImages[i].clear();
+    }
+}
+
+void image_config_t::clear()
+{
+    static const image_config_t empty; // Statically zero-initialized
+    *this = empty;
 }
 
 void scsiDiskCloseSDCardImages()
@@ -502,6 +511,8 @@ static void scsiDiskConfigDefaults(int target_idx)
     img.headsPerCylinder = defaults.headsPerCylinder;
     img.quirks = defaults.quirks;
     img.prefetchbytes = defaults.prefetchBytes;
+    img.reinsert_on_inquiry = true;
+    img.reinsert_after_eject = true;
     memset(img.vendor, 0, sizeof(img.vendor));
     memset(img.prodId, 0, sizeof(img.prodId));
     memset(img.revision, 0, sizeof(img.revision));
@@ -520,8 +531,8 @@ static void scsiDiskLoadConfig(int target_idx, const char *section)
     img.quirks = ini_getl(section, "Quirks", img.quirks, CONFIGFILE);
     img.rightAlignStrings = ini_getbool(section, "RightAlignStrings", 0, CONFIGFILE);
     img.prefetchbytes = ini_getl(section, "PrefetchBytes", img.prefetchbytes, CONFIGFILE);
-    img.reinsert_on_inquiry = ini_getbool(section, "ReinsertCDOnInquiry", 1, CONFIGFILE);
-    img.reinsert_after_eject = ini_getbool(section, "ReinsertAfterEject", 1, CONFIGFILE);
+    img.reinsert_on_inquiry = ini_getbool(section, "ReinsertCDOnInquiry", img.reinsert_on_inquiry, CONFIGFILE);
+    img.reinsert_after_eject = ini_getbool(section, "ReinsertAfterEject", img.reinsert_after_eject, CONFIGFILE);
     img.ejectButton = ini_getl(section, "EjectButton", 0, CONFIGFILE);
 
     char tmp[32];
@@ -678,7 +689,7 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
     else
     {
         img.image_index++;
-        if (img.image_index > IMAGE_INDEX_MAX)
+        if (img.image_index > IMAGE_INDEX_MAX || img.image_index < 0)
         {
             img.image_index = 0;
         }
@@ -695,13 +706,13 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
         {
             // there may be more than one image but we've ran out of new ones
             // wrap back to the first image
-            img.image_index = IMAGE_INDEX_MAX;
+            img.image_index = -1;
             return scsiDiskGetNextImageName(img, buf, buflen);
         }
         else
         {
             // images are not defined in config
-            img.image_index = IMAGE_INDEX_MAX;
+            img.image_index = -1;
             return 0;
         }
     }
@@ -1103,7 +1114,7 @@ static int doTestUnitReady()
         {
             // We are now reporting to host that the drive is open.
             // Simulate a "close" for next time the host polls.
-            cdromSwitchNextImage(img);
+            cdromCloseTray(img);
         }
     }
     else if (unlikely(!(blockDev.state & DISK_PRESENT)))
@@ -1920,13 +1931,13 @@ void scsiDiskPoll()
             checkDiskGeometryDivisible(img);
         }
 
-        // Check for Inquiry command to reinsert CD-ROMs on boot
+        // Check for Inquiry command to close CD-ROM tray on boot
         if (command == 0x12)
         {
             image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
             if (img.deviceType == S2S_CFG_OPTICAL && img.reinsert_on_inquiry)
             {
-                cdromReinsertFirstImage(img);
+                cdromCloseTray(img);
             }
         }
     }
@@ -1948,7 +1959,7 @@ void scsiDiskReset()
     g_scsi_prefetch.sector = 0;
 #endif
 
-    // Reinsert any ejected CD-ROMs
+    // Reinsert any ejected CD-ROMs on BUS RESET and restart from first image
     for (int i = 0; i < S2S_MAX_TARGETS; ++i)
     {
         image_config_t &img = g_DiskImages[i];

+ 11 - 4
src/ZuluSCSI_disk.h

@@ -43,9 +43,7 @@ extern "C" {
 // Extended configuration stored alongside the normal SCSI2SD target information
 struct image_config_t: public S2S_TargetCfg
 {
-    // There should be only one global instance of this struct per device, so disallow copy constructor.
-    image_config_t() = default;
-    image_config_t(const image_config_t&) = delete;
+    image_config_t() {};
 
     ImageBackingStore file;
 
@@ -66,9 +64,11 @@ struct image_config_t: public S2S_TargetCfg
     bool image_directory;
     // the name of the currently mounted image in a dynamic image directory
     char current_image[MAX_FILE_PATH];
+
     // Index of image, for when image on-the-fly switching is used for CD drives
     // This is also used for dynamic directories to track how many images have been seen
-    uint8_t image_index;
+    // Negative value forces restart from first image.
+    int image_index;
 
     // Cue sheet file for CD-ROM images
     FsFile cuesheetfile;
@@ -83,6 +83,13 @@ struct image_config_t: public S2S_TargetCfg
 
     // Warning about geometry settings
     bool geometrywarningprinted;
+
+    // Clear any image state to zeros
+    void clear();
+
+private:
+    // There should be only one global instance of this struct per device, so make copy constructor private.
+    image_config_t(const image_config_t&) = default;
 };
 
 // Should be polled intermittently to update the platform eject buttons.