|  | @@ -5,6 +5,7 @@
 | 
											
												
													
														|  |  //    Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
 |  |  //    Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
 | 
											
												
													
														|  |  //    Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com>
 |  |  //    Copyright (C) 2014 Doug Brown <doug@downtowndougbrown.com>
 | 
											
												
													
														|  |  //    Copyright (C) 2022 Rabbit Hole Computing
 |  |  //    Copyright (C) 2022 Rabbit Hole Computing
 | 
											
												
													
														|  | 
 |  | +//    Copyright (C) 2024 Eric Helgeson <erichelgeson@gmail.com>
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #include "BlueSCSI_disk.h"
 |  |  #include "BlueSCSI_disk.h"
 | 
											
												
													
														|  |  #include "BlueSCSI_log.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;
 |  |      int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      // sanity check: is provided buffer is long enough to store a filename?
 |  |      // 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)
 |  |      if (img.image_directory)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          // image directory was found during startup
 |  |          // image directory was found during startup
 | 
											
												
													
														|  |          char dirname[MAX_FILE_PATH];
 |  |          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 image_directory set but ImgDir is not look for a well known ImgDir
 | 
											
												
													
														|  |              if(img.deviceType == S2S_CFG_OPTICAL)
 |  |              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;
 |  |              dirname[2] = '0' + target_idx;
 | 
											
												
													
														|  |              if(!SD.exists(dirname))
 |  |              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;
 |  |                  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);
 |  |              log("Image directory was empty for ID", target_idx);
 | 
											
												
													
														|  |              return 0;
 |  |              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");
 |  |              log("Directory '", dirname, "' and file '", nextname, "' exceed allowed length");
 | 
											
												
													
														|  |              return 0;
 |  |              return 0;
 | 
											
										
											
												
													
														|  | @@ -829,10 +830,10 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
 | 
											
												
													
														|  |          else
 |  |          else
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              // construct a return value
 |  |              // construct a return value
 | 
											
												
													
														|  | -            strncpy(buf, dirname, buflen);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            strncpy(buf, dirname, buf_len);
 | 
											
												
													
														|  |              if (buf[strlen(buf) - 1] != '/') strcat(buf, "/");
 |  |              if (buf[strlen(buf) - 1] != '/') strcat(buf, "/");
 | 
											
												
													
														|  |              strcat(buf, nextname);
 |  |              strcat(buf, nextname);
 | 
											
												
													
														|  | -            return dirlen + nextlen;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            return dir_len + nextlen;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      else
 |  |      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
 |  |              // there may be more than one image but we've ran out of new ones
 | 
											
												
													
														|  |              // wrap back to the first image
 |  |              // wrap back to the first image
 | 
											
												
													
														|  |              img.image_index = -1;
 |  |              img.image_index = -1;
 | 
											
												
													
														|  | -            return scsiDiskGetNextImageName(img, buf, buflen);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            return scsiDiskGetNextImageName(img, buf, buf_len);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          else
 |  |          else
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
										
											
												
													
														|  | @@ -1365,9 +1366,9 @@ static void doReadCapacity()
 | 
											
												
													
														|  |  /* TestUnitReady command */
 |  |  /* TestUnitReady command */
 | 
											
												
													
														|  |  /*************************/
 |  |  /*************************/
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -static int doTestUnitReady()
 |  | 
 | 
											
												
													
														|  | 
 |  | +static bool doTestUnitReady()
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  | -    int ready = 1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +    bool ready = true;
 | 
											
												
													
														|  |      image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
 |  |      image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
 | 
											
												
													
														|  |      if (unlikely(!scsiDev.target->started || !img.file.isOpen()))
 |  |      if (unlikely(!scsiDev.target->started || !img.file.isOpen()))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
										
											
												
													
														|  | @@ -1379,7 +1380,7 @@ static int doTestUnitReady()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      else if (img.ejected)
 |  |      else if (img.ejected)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        ready = 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        ready = false;
 | 
											
												
													
														|  |          scsiDev.status = CHECK_CONDITION;
 |  |          scsiDev.status = CHECK_CONDITION;
 | 
											
												
													
														|  |          scsiDev.target->sense.code = NOT_READY;
 |  |          scsiDev.target->sense.code = NOT_READY;
 | 
											
												
													
														|  |          scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
 |  |          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.
 |  |              // We are now reporting to host that the drive is open.
 | 
											
												
													
														|  |              // Simulate a "close" for next time the host polls.
 |  |              // 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)))
 |  |      else if (unlikely(!(blockDev.state & DISK_PRESENT)))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        ready = 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        ready = false;
 | 
											
												
													
														|  |          scsiDev.status = CHECK_CONDITION;
 |  |          scsiDev.status = CHECK_CONDITION;
 | 
											
												
													
														|  |          scsiDev.target->sense.code = NOT_READY;
 |  |          scsiDev.target->sense.code = NOT_READY;
 | 
											
												
													
														|  |          scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
 |  |          scsiDev.target->sense.asc = MEDIUM_NOT_PRESENT;
 | 
											
										
											
												
													
														|  | @@ -1402,7 +1406,7 @@ static int doTestUnitReady()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
 |  |      else if (unlikely(!(blockDev.state & DISK_INITIALISED)))
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        ready = 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +        ready = false;
 | 
											
												
													
														|  |          scsiDev.status = CHECK_CONDITION;
 |  |          scsiDev.status = CHECK_CONDITION;
 | 
											
												
													
														|  |          scsiDev.target->sense.code = NOT_READY;
 |  |          scsiDev.target->sense.code = NOT_READY;
 | 
											
												
													
														|  |          scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE;
 |  |          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 */
 |  |  /* Command dispatch */
 | 
											
										
											
												
													
														|  | @@ -1978,11 +2007,17 @@ int scsiDiskCommand()
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          if (start)
 |  |          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))
 |  |      else if (unlikely(command == 0x00))
 |