Jelajahi Sumber

scsi: allow for switching of any removable media

Eric Helgeson 1 tahun lalu
induk
melakukan
e5d63c9e0d

+ 1 - 1
lib/SCSI2SD/src/firmware/scsi.c

@@ -1340,7 +1340,7 @@ void scsiInit()
 		// won't respond properly to
 		// LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense
 		// code
-		scsiDev.targets[i].started = 1;
+		scsiDev.targets[i].started = true;
 	}
 	firstInit = 0;
 }

+ 1 - 1
lib/SCSI2SD/src/firmware/scsi.h

@@ -112,7 +112,7 @@ typedef struct
 	uint8_t syncOffset;
 	uint8_t syncPeriod;
 
-	uint8_t started; // Controlled by START STOP UNIT
+	bool started; // Controlled by START STOP UNIT
 } TargetState;
 
 typedef struct

+ 3 - 3
src/BlueSCSI_cdrom.cpp

@@ -1149,7 +1149,7 @@ bool cdromValidateCueSheet(image_config_t &img)
 /* Ejection and image switching logic */
 /**************************************/
 
-// Close CDROM tray and note media change event
+// Close CD-ROM tray and note media change event
 void cdromCloseTray(image_config_t &img)
 {
     if (img.ejected)
@@ -1167,7 +1167,7 @@ void cdromCloseTray(image_config_t &img)
     }
 }
 
-// Eject CDROM tray if closed, close if open
+// Eject CD-ROM tray if closed, close if open
 // Switch image on ejection.
 void cdromPerformEject(image_config_t &img)
 {
@@ -1189,7 +1189,7 @@ void cdromPerformEject(image_config_t &img)
     }
 }
 
-// Reinsert any ejected CDROMs on reboot
+// Reinsert any ejected CD-ROMs on reboot
 void cdromReinsertFirstImage(image_config_t &img)
 {
     if (img.image_index > 0)

+ 53 - 18
src/BlueSCSI_disk.cpp

@@ -5,6 +5,7 @@
 //    Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
 //    Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com>
 //    Copyright (C) 2022 Rabbit Hole Computing
+//    Copyright (C) 2024 Eric Helgeson <erichelgeson@gmail.com>
 
 #include "BlueSCSI_disk.h"
 #include "BlueSCSI_log.h"
@@ -775,19 +776,19 @@ static int findNextImageAfter(image_config_t &img,
     }
 }
 
-int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
+int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buf_len)
 {
     int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
 
     // sanity check: is provided buffer is long enough to store a filename?
-    assert(buflen >= MAX_FILE_PATH);
+    assert(buf_len >= MAX_FILE_PATH);
 
     if (img.image_directory)
     {
         // image directory was found during startup
         char dirname[MAX_FILE_PATH];
-        int dirlen = getImgDir(target_idx, dirname);
-        if (!dirlen)
+        int dir_len = getImgDir(target_idx, dirname);
+        if (!dir_len)
         {
             // If image_directory set but ImgDir is not look for a well known ImgDir
             if(img.deviceType == S2S_CFG_OPTICAL)
@@ -807,7 +808,7 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
             dirname[2] = '0' + target_idx;
             if(!SD.exists(dirname))
             {
-                debuglog("ERROR: Looking for ", dirname, " to load images, but was not found.");
+                log("ERROR: Looking for ", dirname, " to load images, but was not found.");
                 return 0;
             }
         }
@@ -821,7 +822,7 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
             log("Image directory was empty for ID", target_idx);
             return 0;
         }
-        else if (buflen < nextlen + dirlen + 2)
+        else if (buf_len < nextlen + dir_len + 2)
         {
             log("Directory '", dirname, "' and file '", nextname, "' exceed allowed length");
             return 0;
@@ -829,10 +830,10 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
         else
         {
             // construct a return value
-            strncpy(buf, dirname, buflen);
+            strncpy(buf, dirname, buf_len);
             if (buf[strlen(buf) - 1] != '/') strcat(buf, "/");
             strcat(buf, nextname);
-            return dirlen + nextlen;
+            return dir_len + nextlen;
         }
     }
     else
@@ -853,7 +854,7 @@ 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 = -1;
-            return scsiDiskGetNextImageName(img, buf, buflen);
+            return scsiDiskGetNextImageName(img, buf, buf_len);
         }
         else
         {
@@ -1365,9 +1366,9 @@ static void doReadCapacity()
 /* TestUnitReady command */
 /*************************/
 
-static int doTestUnitReady()
+static bool doTestUnitReady()
 {
-    int ready = 1;
+    bool ready = true;
     image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
     if (unlikely(!scsiDev.target->started || !img.file.isOpen()))
     {
@@ -1379,7 +1380,7 @@ static int doTestUnitReady()
     }
     else if (img.ejected)
     {
-        ready = 0;
+        ready = false;
         scsiDev.status = CHECK_CONDITION;
         scsiDev.target->sense.code = NOT_READY;
         scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
@@ -1389,12 +1390,15 @@ static int doTestUnitReady()
         {
             // We are now reporting to host that the drive is open.
             // Simulate a "close" for next time the host polls.
-            cdromCloseTray(img);
+            if(img.deviceType == S2S_CFG_OPTICAL)
+                cdromCloseTray(img);
+            else if(img.deviceType != S2S_CFG_FIXED)
+                removableInsert(img);
         }
     }
     else if (unlikely(!(blockDev.state & DISK_PRESENT)))
     {
-        ready = 0;
+        ready = false;
         scsiDev.status = CHECK_CONDITION;
         scsiDev.target->sense.code = NOT_READY;
         scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
@@ -1402,7 +1406,7 @@ static int doTestUnitReady()
     }
     else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
     {
-        ready = 0;
+        ready = false;
         scsiDev.status = CHECK_CONDITION;
         scsiDev.target->sense.code = NOT_READY;
         scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
@@ -1956,6 +1960,31 @@ static void diskDataIn()
     }
 }
 
+void removableInsert(image_config_t &img) {
+    if(img.ejected) {
+      uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+      debuglog("------ Removable inserted on ID ", (int)target);
+      img.ejected = false;
+
+      if (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_UNIT_ATTENTION)
+      {
+        debuglog("------ Posting UNIT ATTENTION after medium change");
+        scsiDev.targets[target].unitAttention = NOT_READY_TO_READY_TRANSITION_MEDIUM_MAY_HAVE_CHANGED;
+      }
+    }
+}
+
+void removableEject(image_config_t &img)
+{
+    uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+    if(!img.ejected) {
+        debuglog(" ----- Ejecting target ID ", (int)target);
+        img.ejected = true;
+        switchNextImage(img);
+    } else {
+        removableInsert(img);
+    }
+}
 
 /********************/
 /* Command dispatch */
@@ -1978,11 +2007,17 @@ int scsiDiskCommand()
 
         if (start)
         {
-            scsiDev.target->started = 1;
+            if(img.deviceType == S2S_CFG_FIXED)
+                scsiDev.target->started = true;
+            else
+                removableInsert(img);
         }
-        else
+        else // Stop
         {
-            scsiDev.target->started = 0;
+            if(img.deviceType == S2S_CFG_FIXED)
+                scsiDev.target->started = false;
+            else
+                removableEject(img);
         }
     }
     else if (unlikely(command == 0x00))

+ 9 - 2
src/BlueSCSI_disk.h

@@ -2,6 +2,7 @@
  * SCSI2SD V6 - Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
  * Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com
  * ZuluSCSI™ - Copyright (c) 2022 Rabbit Hole Computing™
+ * Copyright (C) 2024 Eric Helgeson <erichelgeson@gmail.com>
  * 
  * It is derived from disk.h in SCSI2SD V6.
  * 
@@ -129,7 +130,7 @@ bool scsiDiskCheckAnyImagesConfigured();
 // images. As a side effect this advances image tracking to the next image.
 // Returns the length of the new image filename, or 0 if the target is not
 // configured for multiple images.
-int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen);
+int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buf_len);
 
 // Get pointer to extended image configuration based on target idx
 image_config_t &scsiDiskGetImageConfig(int target_idx);
@@ -145,4 +146,10 @@ void scsiDiskStartWrite(uint32_t lba, uint32_t blocks);
 bool scsiDiskCheckAnyNetworkDevicesConfigured();
 
 // Switch to next Drive image if multiple have been configured
-bool switchNextImage(image_config_t &img, const char* next_filename = nullptr);
+bool switchNextImage(image_config_t &img, const char* next_filename = nullptr);
+
+// For removable, non-CD based images
+void removableInsert(image_config_t &img);
+
+// For removable, non-CD based images
+void removableEject(image_config_t &img);