Эх сурвалжийг харах

Merge pull request #199 from BlueSCSI/eric/NeXT

NeXT improvements
Eric Helgeson 1 жил өмнө
parent
commit
c45bfd21a6

+ 2 - 2
lib/BlueSCSI_platform_RP2040/BlueSCSI_platform_config_hook.cpp

@@ -73,7 +73,7 @@ static bool isValidMacintoshImage(image_config_t *img)
     return result;
 }
 
-// Called from BlueSCSI_disk after image is initalized.
+// Called from BlueSCSI_disk after image is initialized.
 void platformConfigHook(image_config_t *img)
 {
     if(ini_getbool("SCSI", "DisableConfigHook", false, CONFIGFILE))
@@ -94,7 +94,7 @@ void platformConfigHook(image_config_t *img)
                 debuglog("---- Valid Macintosh Device Image detected.");
             }
         }
-        // Macintosh hosts reserve ID 7, so warn the user this configuration wont work
+        // Macintosh hosts reserve ID 7, so warn the user this configuration won't work
         if((img->scsiId & S2S_CFG_TARGET_ID_BITS) == 7)
         {
           log("---- WARNING: Quirks set to Apple so can not use SCSI ID 7!");

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

@@ -175,7 +175,7 @@ void s2s_scsiInquiry()
 			allocationLength = 254;
 		}
 
-		// "real" hard drives send back exactly allocationLenth bytes, padded
+		// "real" hard drives send back exactly allocationLength bytes, padded
 		// with zeroes. This only seems to happen for Inquiry responses, and not
 		// other commands that also supply an allocation length such as Mode Sense or
 		// Request Sense.

+ 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.cpp

@@ -391,7 +391,7 @@ bool findHDDImages()
         {
           log("== Opening ", fullname, " for ID: ", id, " LUN: ", lun);
 
-          imageReady = scsiDiskOpenHDDImage(id, fullname, id, lun, blk, type);
+          imageReady = scsiDiskOpenHDDImage(fullname, id, lun, blk, type);
           if(imageReady)
           {
             foundImage = true;
@@ -430,7 +430,7 @@ bool findHDDImages()
 
       if (cfg->deviceType == S2S_CFG_NETWORK)
       {
-        log("* ID: ", (int)(cfg->scsiId & 7),
+        log("* ID: ", (int)(cfg->scsiId & S2S_CFG_TARGET_ID_BITS),
               ", Type: ", typeToChar((int)cfg->deviceType),
               ", Quirks: ", quirksToChar((int)cfg->quirks));
       }
@@ -536,7 +536,7 @@ static void reinitSCSI()
   {
 #if RAW_FALLBACK_ENABLE
     log("No images found, enabling RAW fallback partition");
-    scsiDiskOpenHDDImage(RAW_FALLBACK_SCSI_ID, "RAW:0:0xFFFFFFFF", RAW_FALLBACK_SCSI_ID, 0,
+    scsiDiskOpenHDDImage("RAW:0:0xFFFFFFFF", RAW_FALLBACK_SCSI_ID, 0,
                          RAW_FALLBACK_BLOCKSIZE);
 #else
     log("No valid image files found!");

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

+ 1 - 0
src/BlueSCSI_config.h

@@ -12,6 +12,7 @@
 
 // Configuration and log file paths
 #define CONFIGFILE  "bluescsi.ini"
+#define CONFIGFILE_BAD  "bluescsi.ini.txt"
 #define LOGFILE     "log.txt"
 #define CRASHFILE   "err.txt"
 

+ 100 - 33
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"
@@ -129,7 +130,7 @@ bool scsiDiskActivateRomDrive()
     }
 
     log("---- Activating ROM drive, SCSI id ", (int)hdr.scsi_id, " size ", (int)(hdr.imagesize / 1024), " kB");
-    bool status = scsiDiskOpenHDDImage(hdr.scsi_id, "ROM:", hdr.scsi_id, 0, hdr.blocksize, hdr.drivetype);
+    bool status = scsiDiskOpenHDDImage("ROM:", hdr.scsi_id, 0, hdr.blocksize, hdr.drivetype);
 
     if (!status)
     {
@@ -367,16 +368,16 @@ static void setDefaultDriveInfo(int target_idx)
     formatDriveInfoField(img.serial, sizeof(img.serial), true);
 }
 
-bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int scsi_lun, int blocksize, S2S_CFG_TYPE type)
+bool scsiDiskOpenHDDImage(const char *filename, int scsi_id, int scsi_lun, int block_size, S2S_CFG_TYPE type)
 {
-    image_config_t &img = g_DiskImages[target_idx];
+    image_config_t &img = g_DiskImages[scsi_id];
     img.cuesheetfile.close();
-    img.file = ImageBackingStore(filename, blocksize);
+    img.file = ImageBackingStore(filename, block_size);
 
     if (img.file.isOpen())
     {
-        img.bytesPerSector = blocksize;
-        img.scsiSectors = img.file.size() / blocksize;
+        img.bytesPerSector = block_size;
+        img.scsiSectors = img.file.size() / block_size;
         img.scsiId = scsi_id | S2S_CFG_TARGET_ENABLED;
         img.sdSectorStart = 0;
 
@@ -467,7 +468,7 @@ bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int
             log("Vendor / product id set from image file name");
         }
 
-        setDefaultDriveInfo(target_idx);
+        setDefaultDriveInfo(scsi_id);
 
 #ifdef PLATFORM_CONFIG_HOOK
         PLATFORM_CONFIG_HOOK(&img);
@@ -590,7 +591,7 @@ static void scsiDiskConfigDefaults(int target_idx)
 }
 
 // Load values for target configuration from given section if they exist.
-// Otherwise keep current settings.
+// Otherwise, keep current settings.
 static void scsiDiskLoadConfig(int target_idx, const char *section)
 {
     image_config_t &img = g_DiskImages[target_idx];
@@ -671,6 +672,30 @@ static void scsiDiskLoadConfig(int target_idx, const char *section)
                 img.deviceType = S2S_CFG_ZIP100;
                 img.image_directory = true;
             }
+            strcpy(tmp, "MOX");
+            tmp[2] = '0' + target_idx;
+            if(SD.exists(tmp))
+            {
+              log("-- SCSI ID: ", target_idx, " using Magneto-optical image directory \'", tmp, "'");
+              img.deviceType = S2S_CFG_MO;
+              img.image_directory = true;
+            }
+            strcpy(tmp, "REX");
+            tmp[2] = '0' + target_idx;
+            if(SD.exists(tmp))
+            {
+              log("-- SCSI ID: ", target_idx, " using Removable image directory \'", tmp, "'");
+              img.deviceType = S2S_CFG_REMOVEABLE;
+              img.image_directory = true;
+            }
+            strcpy(tmp, "TPX");
+            tmp[2] = '0' + target_idx;
+            if(SD.exists(tmp))
+            {
+              log("-- SCSI ID: ", target_idx, " using Tape image directory \'", tmp, "'");
+              img.deviceType = S2S_CFG_SEQUENTIAL;
+              img.image_directory = true;
+            }
         }
     }
 }
@@ -751,31 +776,39 @@ 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)
                 strcpy(dirname, "CDX");
             else if(img.deviceType == S2S_CFG_ZIP100)
                 strcpy(dirname, "ZPX");
+            else if(img.deviceType == S2S_CFG_FLOPPY_14MB)
+                strcpy(dirname, "FDX");
+            else if(img.deviceType == S2S_CFG_MO)
+                strcpy(dirname, "MOX");
+            else if(img.deviceType == S2S_CFG_REMOVEABLE)
+                strcpy(dirname, "REX");
+            else if(img.deviceType == S2S_CFG_SEQUENTIAL)
+                strcpy(dirname, "TPX");
             else
                 strcpy(dirname, "HDX");
             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;
             }
         }
@@ -789,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;
@@ -797,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
@@ -821,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
         {
@@ -854,7 +887,7 @@ void scsiDiskLoadConfig(int target_idx)
     {
         int blocksize = getBlockSize(filename, target_idx, (img.deviceType == S2S_CFG_OPTICAL) ? 2048 : 512);
         log("-- Opening '", filename, "' for ID: ", target_idx);
-        scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, blocksize);
+        scsiDiskOpenHDDImage(filename, target_idx, 0, blocksize);
     }
 }
 
@@ -878,7 +911,7 @@ bool switchNextImage(image_config_t &img, const char* next_filename)
         log("Switching to next image for ID: ", target_idx, ": ", filename);
         img.file.close();
         int block_size = getBlockSize(filename, target_idx, (img.deviceType == S2S_CFG_OPTICAL) ? 2048 : 512);
-        bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, block_size);
+        bool status = scsiDiskOpenHDDImage(filename, target_idx, 0, block_size);
 
         if (status)
         {
@@ -998,12 +1031,12 @@ void s2s_configInit(S2S_BoardCfg* config)
 {
     char tmp[64];
 
-    if (SD.exists(CONFIGFILE))
-    {
+    if (SD.exists(CONFIGFILE)) {
         log("Reading configuration from " CONFIGFILE);
-    }
-    else
-    {
+    } else {
+        if (SD.exists(CONFIGFILE_BAD)) {
+          log("ERROR: Please remove the .txt file extension from the config file: ", CONFIGFILE_BAD);
+        }
         log("Config file " CONFIGFILE " not found, using defaults");
     }
 
@@ -1333,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()))
     {
@@ -1347,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;
@@ -1357,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;
@@ -1370,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;
@@ -1924,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 */
@@ -1946,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))

+ 10 - 3
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.
  * 
@@ -106,7 +107,7 @@ void scsiDiskResetImages();
 // Close any files opened from SD card (prepare for remounting SD)
 void scsiDiskCloseSDCardImages();
 
-bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int scsi_lun, int blocksize, S2S_CFG_TYPE type = S2S_CFG_FIXED);
+bool scsiDiskOpenHDDImage(const char *filename, int scsi_id, int scsi_lun, int block_size, S2S_CFG_TYPE type = S2S_CFG_FIXED);
 void scsiDiskLoadConfig(int target_idx);
 
 // Checks if a filename extension is appropriate for further processing as a disk image.
@@ -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);

+ 20 - 4
src/BlueSCSI_presets.cpp

@@ -1,7 +1,7 @@
 #include "BlueSCSI_presets.h"
+#include "BlueSCSI_config.h"
 #include "BlueSCSI_disk.h"
 #include "BlueSCSI_log.h"
-#include "BlueSCSI_config.h"
 #include <strings.h>
 
 // Helper function for case-insensitive string compare
@@ -54,14 +54,30 @@ preset_config_t getSystemPreset(const char *presetName)
         cfg.mapLunsToIDs = true;
         cfg.enableParity = false;
     }
-    else if (strequals(presetName, "X68000"))
+    else if (strequals(presetName, "X68000") || strequals(presetName, "X68000-SCSI"))
     {
-        cfg.presetName = "X68000";
+        cfg.presetName = "X68000-SCSI";
         cfg.selectionDelay = 0;
         cfg.quirks = S2S_CFG_QUIRKS_X68000;
-        cfg.enableSCSI2 = 0;
+        cfg.enableSCSI2 = false;
         cfg.maxSyncSpeed = 5;
     }
+    else if (strequals(presetName, "X68000-SASI"))
+    {
+        cfg.presetName = "X68000-SASI";
+        cfg.selectionDelay = 0;
+        cfg.quirks = S2S_CFG_QUIRKS_X68000;
+        cfg.enableSCSI2 = false;
+        cfg.enableParity = false;
+        cfg.maxSyncSpeed = 5;
+    }
+    else if (strequals(presetName, "NeXT"))
+    {
+        cfg.presetName = "NeXT";
+        cfg.quirks = S2S_CFG_QUIRKS_NONE;
+        cfg.sectorsPerTrack = 139;
+        cfg.headsPerCylinder = 4;
+    }
     else
     {
         log("Unknown preset name ", presetName, ", using default settings");