|
|
@@ -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))
|