|
@@ -37,6 +37,9 @@ struct image_config_t: public S2S_TargetCfg
|
|
|
bool ejected;
|
|
bool ejected;
|
|
|
uint8_t cdrom_events;
|
|
uint8_t cdrom_events;
|
|
|
|
|
|
|
|
|
|
+ // Index of image, for when image on-the-fly switching is used for CD drives
|
|
|
|
|
+ int image_index;
|
|
|
|
|
+
|
|
|
// Right-align vendor / product type strings (for Apple)
|
|
// Right-align vendor / product type strings (for Apple)
|
|
|
// Standard SCSI uses left alignment
|
|
// Standard SCSI uses left alignment
|
|
|
// This field uses -1 for default when field is not set in .ini
|
|
// This field uses -1 for default when field is not set in .ini
|
|
@@ -275,6 +278,21 @@ static void scsiDiskLoadConfig(int target_idx, const char *section)
|
|
|
if (tmp[0]) memcpy(img.serial, tmp, sizeof(img.serial));
|
|
if (tmp[0]) memcpy(img.serial, tmp, sizeof(img.serial));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// Check if image file name is overridden in config
|
|
|
|
|
+static bool get_image_name(int target_idx, char *buf, size_t buflen)
|
|
|
|
|
+{
|
|
|
|
|
+ image_config_t &img = g_DiskImages[target_idx];
|
|
|
|
|
+
|
|
|
|
|
+ char section[6] = "SCSI0";
|
|
|
|
|
+ section[4] = '0' + target_idx;
|
|
|
|
|
+
|
|
|
|
|
+ char key[5] = "IMG0";
|
|
|
|
|
+ key[3] = '0' + img.image_index;
|
|
|
|
|
+
|
|
|
|
|
+ ini_gets(section, key, "", buf, buflen, CONFIGFILE);
|
|
|
|
|
+ return buf[0] != '\0';
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void scsiDiskLoadConfig(int target_idx)
|
|
void scsiDiskLoadConfig(int target_idx)
|
|
|
{
|
|
{
|
|
|
char section[6] = "SCSI0";
|
|
char section[6] = "SCSI0";
|
|
@@ -288,6 +306,16 @@ void scsiDiskLoadConfig(int target_idx)
|
|
|
|
|
|
|
|
// Then settings specific to target ID
|
|
// Then settings specific to target ID
|
|
|
scsiDiskLoadConfig(target_idx, section);
|
|
scsiDiskLoadConfig(target_idx, section);
|
|
|
|
|
+
|
|
|
|
|
+ // Check if we have image specified by name
|
|
|
|
|
+ char filename[MAX_FILE_PATH];
|
|
|
|
|
+ if (get_image_name(target_idx, filename, sizeof(filename)))
|
|
|
|
|
+ {
|
|
|
|
|
+ image_config_t &img = g_DiskImages[target_idx];
|
|
|
|
|
+ int blocksize = (img.deviceType == S2S_CFG_OPTICAL) ? 2048 : 512;
|
|
|
|
|
+ azlog("-- Opening ", filename, " for id:", target_idx, ", specified in " CONFIGFILE);
|
|
|
|
|
+ scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, blocksize, false);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*******************************/
|
|
/*******************************/
|
|
@@ -513,6 +541,38 @@ static void doReadCapacity()
|
|
|
/* TestUnitReady command */
|
|
/* TestUnitReady command */
|
|
|
/*************************/
|
|
/*************************/
|
|
|
|
|
|
|
|
|
|
+// Check if we have multiple CD-ROM images to cycle when drive is ejected.
|
|
|
|
|
+static bool checkNextCDImage()
|
|
|
|
|
+{
|
|
|
|
|
+ // Check if we have a next image to load, so that drive is closed next time the host asks.
|
|
|
|
|
+ image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
|
|
|
|
|
+ img.image_index++;
|
|
|
|
|
+ char filename[MAX_FILE_PATH];
|
|
|
|
|
+ int target_idx = img.scsiId & 7;
|
|
|
|
|
+ if (!get_image_name(target_idx, filename, sizeof(filename)))
|
|
|
|
|
+ {
|
|
|
|
|
+ img.image_index = 0;
|
|
|
|
|
+ get_image_name(target_idx, filename, sizeof(filename));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (filename[0] != '\0')
|
|
|
|
|
+ {
|
|
|
|
|
+ azlog("Switching to next CD-ROM image for ", target_idx, ": ", filename);
|
|
|
|
|
+ image_config_t &img = g_DiskImages[target_idx];
|
|
|
|
|
+ img.file.close();
|
|
|
|
|
+ bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048, false);
|
|
|
|
|
+
|
|
|
|
|
+ if (status)
|
|
|
|
|
+ {
|
|
|
|
|
+ img.ejected = false;
|
|
|
|
|
+ img.cdrom_events = 2; // New media
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static int doTestUnitReady()
|
|
static int doTestUnitReady()
|
|
|
{
|
|
{
|
|
|
int ready = 1;
|
|
int ready = 1;
|
|
@@ -532,6 +592,10 @@ static int doTestUnitReady()
|
|
|
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;
|
|
|
scsiDev.phase = STATUS;
|
|
scsiDev.phase = STATUS;
|
|
|
|
|
+
|
|
|
|
|
+ // We are now reporting to host that the drive is open.
|
|
|
|
|
+ // Simulate a "close" for next time the host polls.
|
|
|
|
|
+ checkNextCDImage();
|
|
|
}
|
|
}
|
|
|
else if (unlikely(!(blockDev.state & DISK_PRESENT)))
|
|
else if (unlikely(!(blockDev.state & DISK_PRESENT)))
|
|
|
{
|
|
{
|
|
@@ -577,6 +641,13 @@ static void doGetEventStatusNotification(bool immed)
|
|
|
scsiDev.dataLen = 8;
|
|
scsiDev.dataLen = 8;
|
|
|
scsiDev.phase = DATA_IN;
|
|
scsiDev.phase = DATA_IN;
|
|
|
img.cdrom_events = 0;
|
|
img.cdrom_events = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (img.ejected)
|
|
|
|
|
+ {
|
|
|
|
|
+ // We are now reporting to host that the drive is open.
|
|
|
|
|
+ // Simulate a "close" for next time the host polls.
|
|
|
|
|
+ checkNextCDImage();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|