Browse Source

Merge branch 'eric/relPrep'

Eric Helgeson 1 năm trước cách đây
mục cha
commit
19633f4fc9

+ 1 - 0
lib/BlueSCSI_platform_RP2040/BlueSCSI_platform.h

@@ -15,6 +15,7 @@ extern "C" {
 extern const char *g_platform_name;
 #define PLATFORM_NAME "BlueSCSI"
 #define PLATFORM_REVISION "2.0"
+#define PLATFORM_TOOLBOX_API 0
 #define PLATFORM_INQUIRY PLATFORM_NAME " v" BLUESCSI_FW_VERSION
 #define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_10
 #define PLATFORM_OPTIMAL_MIN_SD_WRITE_SIZE 32768

+ 1 - 2
lib/SCSI2SD/src/firmware/geometry.h

@@ -18,8 +18,7 @@
 #define GEOMETRY_H
 
 #include "config.h"
-// TODO #include "sd.h"
-#define SD_SECTOR_SIZE 512
+#include "sd.h"
 
 typedef enum
 {

+ 22 - 2
lib/SCSI2SD/src/firmware/inquiry.c

@@ -80,6 +80,16 @@ static const uint8_t AscImpOperatingDefinition[] =
 'S','C','S','I','-','2'
 };
 
+static const uint8_t IOMegaVendorInquiry[] =
+{
+'0', '8', '/', '2', '0', '/', '9', '6', 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+'(', 'c', ')', ' ', 'C', 'o', 'p', 'y', 'r', 'i', 'g', 'h', 't', ' ', 'I', 'O',
+'M', 'E', 'G', 'A', ' ', '1', '9', '9', '5', ' '
+};
+
 void s2s_scsiInquiry()
 {
 	uint8_t evpd = scsiDev.cdb[1] & 1; // enable vital product data.
@@ -200,6 +210,7 @@ void s2s_scsiInquiry()
 
 		case S2S_CFG_FLOPPY_14MB:
 		case S2S_CFG_REMOVEABLE:
+		case S2S_CFG_ZIP100:
 			scsiDev.data[1] |= 0x80; // Removable bit.
 			break;
 
@@ -248,10 +259,19 @@ uint32_t s2s_getStandardInquiry(
 		sizeof(cfg->prodId) +
 		sizeof(cfg->revision);
 
+    if(cfg->deviceType == S2S_CFG_ZIP100) {
+        memcpy(&out[size], IOMegaVendorInquiry, sizeof(IOMegaVendorInquiry));
+        size += sizeof(IOMegaVendorInquiry);
+        out[7] = 0x00; // Disable sync and linked commands
+        out[4] = 0x75; // 117 length
+    }
 	// Mac Daynaport Driver does not like this added.
-	if(cfg->deviceType != S2S_CFG_NETWORK) {
-		memcpy(&out[36], PLATFORM_INQUIRY, sizeof(PLATFORM_INQUIRY));
+    // IOMega already has a vendor inquiry
+	if(cfg->deviceType != S2S_CFG_NETWORK && cfg->deviceType != S2S_CFG_ZIP100) {
+		memcpy(&out[size], PLATFORM_INQUIRY, sizeof(PLATFORM_INQUIRY));
 		size += sizeof(PLATFORM_INQUIRY);
+		out[size] = PLATFORM_TOOLBOX_API;
+		size += 1;
 	}
 	return size;
 }

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

@@ -28,11 +28,11 @@
 #include "cdrom.h"
 // #include "debug.h"
 // #include "log.h"
+#include "bluescsi_toolbox.h"
+#include "mo.h"
 #include "network.h"
 #include "tape.h"
-#include "mo.h"
 #include "vendor.h"
-#include "bluescsi_toolbox.h"
 
 #include <string.h>
 
@@ -546,7 +546,7 @@ static void process_Command()
 			// Newer initiators won't be specifying 0 anyway.
 			if (allocLength == 0) allocLength = 4;
 
-			// If we receve a stand alone REQUEST SENSE to a bad LUN we still need to respond
+			// If we receive a stand-alone REQUEST SENSE to a bad LUN we still need to respond
 			// with LUN not supported. SCSI-2 Spec 7.5.3.
 			if (scsiDev.lun && scsiDev.lastStatus != CHECK_CONDITION)
 			{
@@ -604,7 +604,7 @@ static void process_Command()
 
 		enter_Status(CHECK_CONDITION);
 	}
-	else if (scsiDev.lun)
+	else if (scsiDev.lun && (command < 0xD0))
 	{
 		scsiDev.target->sense.code = ILLEGAL_REQUEST;
 		scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;

+ 2 - 2
platformio.ini

@@ -49,8 +49,8 @@ build_flags =
     ; -DSCSI2SD_BUFFER_SIZE=57344
 
 ; Experimental Audio build
-; Rquires seperate hardware and overclock. 
-; For expermeination only, do not use.
+; Requires separate hardware and overclock.
+; For experimentation only, do not use.
 [env:BlueSCSI_Pico_Audio]
 extends = env:BlueSCSI_Pico
 build_flags =

+ 2 - 0
src/BlueSCSI.cpp

@@ -193,6 +193,8 @@ const char * typeToChar(int deviceType)
     return "Tape";
   case S2S_CFG_REMOVEABLE:
     return "Removable";
+  case S2S_CFG_ZIP100:
+    return "ZIP100";
   default:
     return "Unknown";
   }

+ 25 - 11
src/BlueSCSI_Toolbox.cpp

@@ -66,13 +66,20 @@ static void doCountFiles(const char * dir_name)
             file.close();
             break;
         }
-        file.getName(name, MAX_FILE_PATH);
+        bool isDir = file.isDirectory();
+        size_t len = file.getName(name, MAX_FILE_PATH);
         file.close();
+        if (isDir)
+            continue;
+        // truncate filename the same way listing does, before validating name
+        if (len > MAX_MAC_PATH)
+            name[MAX_MAC_PATH] = 0x0;
+        debuglog("TOOLBOX COUNT FILES: truncated filename is '", name, "'");
         // only count valid files.
         if(toolboxFilenameValid(name))
         {
             file_count = file_count + 1;
-            if(file_count > 100) {
+            if(file_count > MAX_FILE_LISTING_FILES) {
                 scsiDev.status = CHECK_CONDITION;
                 scsiDev.target->sense.code = ILLEGAL_REQUEST;
                 scsiDev.target->sense.asc = OPEN_RETRO_SCSI_TOO_MANY_FILES;
@@ -91,15 +98,17 @@ void onListFiles(const char * dir_name) {
     FsFile dir;
     FsFile file;
 
-    memset(scsiDev.data, 0, 4096);
-    int ENTRY_SIZE = 40;
+    memset(scsiDev.data, 0, ENTRY_SIZE * (MAX_FILE_LISTING_FILES + 1));
     char name[MAX_FILE_PATH] = {0};
+    uint8_t index = 0;
+    byte file_entry[ENTRY_SIZE] = {0};
+
     dir.open(dir_name);
     dir.rewindDirectory();
-    uint8_t index = 0;
-    byte file_entry[40] = {0};
     while (file.openNext(&dir, O_RDONLY))
     {
+        memset(name, 0, MAX_FILE_PATH);
+        memset(file_entry, 0, ENTRY_SIZE);
         uint8_t isDir = file.isDirectory() ? 0x00 : 0x01;
         int len = file.getName(name, MAX_FILE_PATH);
         if (len > MAX_MAC_PATH)
@@ -122,10 +131,11 @@ void onListFiles(const char * dir_name) {
         file_entry[39] = (size) & 0xff;
         memcpy(&(scsiDev.data[ENTRY_SIZE * index]), file_entry, ENTRY_SIZE);
         index = index + 1;
+        if (index >= MAX_FILE_LISTING_FILES) break;
     }
     dir.close();
 
-    scsiDev.dataLen = 4096;
+    scsiDev.dataLen = ENTRY_SIZE * index;
     scsiDev.phase = DATA_IN;
 }
 
@@ -145,8 +155,11 @@ FsFile get_file_from_index(uint8_t index, const char * dir_name)
       file_test.close();
       break;
     }
-    file_test.getName(name, MAX_FILE_PATH);
 
+    // truncate filename the same way listing does, before validating name
+    size_t len = file_test.getName(name, MAX_FILE_PATH);
+    if (len > MAX_MAC_PATH)
+        name[MAX_MAC_PATH] = 0x0;
     if(!toolboxFilenameValid(name))
     {
         file_test.close();
@@ -184,6 +197,7 @@ void onListDevices()
     }
   }
   scsiDev.dataLen = NUM_SCSIID;
+  scsiDev.phase = DATA_IN;
 }
 
 void onSetNextCD(const char * img_dir)
@@ -197,10 +211,10 @@ void onSetNextCD(const char * img_dir)
     next_cd.getName(name, sizeof(name));
     next_cd.close();
     snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", img_dir, name);
-    cdromSwitch(img, full_path);
+    switchNextImage(img, full_path);
 }
 
-FsFile gFile; // global so we can keep it open while transfering.
+FsFile gFile; // global so we can keep it open while transferring.
 void onGetFile10(char * dir_name) {
     uint8_t index = scsiDev.cdb[1];
 
@@ -232,7 +246,7 @@ void onGetFile10(char * dir_name) {
 }
 
 /*
-  Prepares a file for receving. The file name is null terminated in the scsi data.
+  Prepares a file for receiving. The file name is null terminated in the scsi data.
 */
 void onSendFilePrep(char * dir_name)
 {

+ 3 - 0
src/BlueSCSI_Toolbox.h

@@ -20,6 +20,9 @@
 #pragma once
 
 #define MAX_MAC_PATH 32
+#define ENTRY_SIZE 40
+#define MAX_FILE_LISTING_FILES 100
+
 #define CD_IMG_DIR "CD%d"
 
 #define BLUESCSI_TOOLBOX_COUNT_FILES    0xD2

+ 2 - 65
src/BlueSCSI_cdrom.cpp

@@ -1181,7 +1181,7 @@ void cdromPerformEject(image_config_t &img)
         debuglog("------ CDROM open tray on ID ", (int)target);
         img.ejected = true;
         img.cdrom_events = 3; // Media removal
-        cdromSwitchNextImage(img); // Switch media for next time
+        switchNextImage(img); // Switch media for next time
     }
     else
     {
@@ -1199,7 +1199,7 @@ void cdromReinsertFirstImage(image_config_t &img)
         debuglog("---- Restarting from first CD-ROM image for ID ", (int)target);
         img.image_index = -1;
         img.current_image[0] = '\0';
-        cdromSwitchNextImage(img);
+        switchNextImage(img);
     }
     else if (img.ejected)
     {
@@ -1208,69 +1208,6 @@ void cdromReinsertFirstImage(image_config_t &img)
     }
 }
 
-// Check if we have multiple CD-ROM images to cycle when drive is ejected.
-bool cdromSwitchNextImage(image_config_t &img)
-{
-    // Check if we have a next image to load, so that drive is closed next time the host asks.
-    char filename[MAX_FILE_PATH];
-    int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
-    scsiDiskGetNextImageName(img, filename, sizeof(filename));
-
-    if (filename[0] != '\0')
-    {
-#ifdef ENABLE_AUDIO_OUTPUT
-    // if in progress for this device, terminate audio playback immediately (Annex C)
-    audio_stop(target_idx);
-    // Reset position tracking for the new image
-    audio_get_status_code(target_idx); // trash audio status code
-#endif
-        log("Switching to next CD-ROM image for ", target_idx, ": ", filename);
-        img.file.close();
-        bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0,
-                                           getBlockSize(filename, target_idx, 2048));
-
-        if (status)
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-// Check if we have multiple CD-ROM images to cycle when drive is ejected.
-bool cdromSwitch(image_config_t &img, const char* filename)
-{
-    // Check if we have a next image to load, so that drive is closed next time the host asks.
-    int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
-
-    if (filename[0] != '\0')
-    {
-#ifdef ENABLE_AUDIO_OUTPUT
-        // if in progress for this device, terminate audio playback immediately (Annex C)
-        audio_stop(target_idx);
-        // Reset position tracking for the new image
-        audio_get_status_code(target_idx); // trash audio status code
-#endif
-        log("Switching to next CD-ROM image for ", target_idx, ": ", filename);
-        img.file.close();
-        bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048);
-
-        if (status)
-        {
-            img.ejected = false;
-            img.cdrom_events = 2; // New media
-            return true;
-        }
-    }
-    else
-    {
-        log("Could not switch to CD-ROM image as provide filename was empty.");
-    }
-
-    return false;
-}
-
 static void doGetEventStatusNotification(bool immed)
 {
     image_config_t &img = *(image_config_t*)scsiDev.target->cfg;

+ 0 - 6
src/BlueSCSI_cdrom.h

@@ -21,9 +21,6 @@ void cdromPerformEject(image_config_t &img);
 // Reinsert ejected CD-ROM and restart from first image
 void cdromReinsertFirstImage(image_config_t &img);
 
-// Switch to next CD-ROM image if multiple have been configured
-bool cdromSwitchNextImage(image_config_t &img);
-
 // Check if the currently loaded cue sheet for the image can be parsed
 // and print warnings about unsupported track types
 bool cdromValidateCueSheet(image_config_t &img);
@@ -32,6 +29,3 @@ bool cdromValidateCueSheet(image_config_t &img);
 // boolean flag is true if just basic mechanism status (playback true/false)
 // is desired, or false if historical audio status codes should be returned
 void cdromGetAudioPlaybackStatus(uint8_t *status, uint32_t *current_lba, bool current_only);
-
-// switch to a given filename for the cd.
-bool cdromSwitch(image_config_t &img, const char* filename);

+ 4 - 4
src/BlueSCSI_config.h

@@ -6,8 +6,8 @@
 #include <BlueSCSI_platform.h>
 
 // Use variables for version number
-#define FW_VER_NUM      "2024.04.03"
-#define FW_VER_SUFFIX   "dev"
+#define FW_VER_NUM      "2024.05.22"
+#define FW_VER_SUFFIX   "dev" // 3 char only - 'dev' or 'rel'
 #define BLUESCSI_FW_VERSION FW_VER_NUM "-" FW_VER_SUFFIX
 
 // Configuration and log file paths
@@ -68,7 +68,7 @@
 #define APPLE_DRIVEINFO_TAPE      {"BlueSCSI", "APPLE_TAPE",      "",     ""}
 
 // Default Iomega ZIP drive information
-#define IOMEGA_DRIVEINFO_ZIP100     {"IOMEGA", "ZIP 100", "E.08", ""}
+#define IOMEGA_DRIVEINFO_ZIP100     {"IOMEGA", "ZIP 100", "D.13", ""}
 #define IOMEGA_DRIVEINFO_ZIP250     {"IOMEGA", "ZIP 250", "42.S", ""}
 #define IOMEGA_DRIVEINFO_JAZ        {"iomega", "jaz", "", ""}
 
@@ -93,4 +93,4 @@ int getImgDir(int scsiId, char* dirname);
 
 int getImg(int scsiId, int img_index, char* filename);
 
-int getToolBoxSharedDir(char * dir_name);
+int getToolBoxSharedDir(char * dir_name);

+ 64 - 14
src/BlueSCSI_disk.cpp

@@ -289,6 +289,7 @@ static void setDefaultDriveInfo(int target_idx)
             case S2S_CFG_MO:            driveinfo = apl_driveinfo_magopt; break;
             case S2S_CFG_NETWORK:       driveinfo = apl_driveinfo_network; break;
             case S2S_CFG_SEQUENTIAL:    driveinfo = apl_driveinfo_tape; break;
+            case S2S_CFG_ZIP100:        driveinfo = iomega_driveinfo_removeable; break;
             default:                    driveinfo = apl_driveinfo_fixed; break;
         }
     }
@@ -659,6 +660,14 @@ static void scsiDiskLoadConfig(int target_idx, const char *section)
                 img.deviceType = S2S_CFG_FLOPPY_14MB;
                 img.image_directory = true;
             }
+            strcpy(tmp, "ZPX");
+            tmp[2] = '0' + target_idx;
+            if(SD.exists(tmp))
+            {
+                log("-- SCSI ID: ", target_idx, " using Zip 100 image directory \'", tmp, "'");
+                img.deviceType = S2S_CFG_ZIP100;
+                img.image_directory = true;
+            }
         }
     }
 }
@@ -753,9 +762,11 @@ int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
         int dirlen = getImgDir(target_idx, dirname);
         if (!dirlen)
         {
-            // If image_directory set but ImgDir is not look for an well known ImgDir
+            // 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
                 strcpy(dirname, "HDX");
             dirname[2] = '0' + target_idx;
@@ -839,11 +850,54 @@ void scsiDiskLoadConfig(int target_idx)
     if (scsiDiskGetNextImageName(img, filename, sizeof(filename)))
     {
         int blocksize = getBlockSize(filename, target_idx, (img.deviceType == S2S_CFG_OPTICAL) ? 2048 : 512);
-        log("-- Opening '", filename, "' for ID:", target_idx);
+        log("-- Opening '", filename, "' for ID: ", target_idx);
         scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, blocksize);
     }
 }
 
+// Check if we have multiple drive images to cycle when drive is ejected.
+bool switchNextImage(image_config_t &img, const char* next_filename)
+{
+    // Check if we have a next image to load, so that drive is closed next time the host asks.
+    char filename[MAX_FILE_PATH];
+    int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+    if (next_filename == nullptr)
+    {
+        scsiDiskGetNextImageName(img, filename, sizeof(filename));
+    }
+    else
+    {
+        strncpy(filename, next_filename, MAX_FILE_PATH);
+    }
+
+    if (filename[0] != '\0')
+    {
+        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);
+
+        if (status)
+        {
+            if (next_filename != nullptr && img.deviceType == S2S_CFG_OPTICAL)
+            {
+                // present the drive as ejected until the host queries it again,
+                // to make sure host properly detects the media change
+                img.ejected = true;
+                img.reinsert_after_eject = true;
+                img.cdrom_events = 2; // New Media
+            }
+            return true;
+        }
+    }
+    else
+    {
+        log("Could not switch to image as provide filename was empty.");
+    }
+
+    return false;
+}
+
 bool scsiDiskCheckAnyImagesConfigured()
 {
     for (int i = 0; i < S2S_MAX_TARGETS; i++)
@@ -1029,6 +1083,11 @@ void s2s_configInit(S2S_BoardCfg* config)
     if (ini_getbool("SCSI", "Debug", 0, CONFIGFILE))
     {
         log("-- Debug is enabled");
+        g_scsi_log_mask = ini_getl("SCSI", "DebugLogMask", 0xFF, CONFIGFILE) & 0b11111111;
+        if(g_scsi_log_mask != 0xFF)
+        {
+            log("--- DebugLogMask set to ", g_scsi_log_mask, " only SCSI IDs matching this mask will be logged.");
+        }
     }
 
     if (ini_getbool("SCSI", "EnableParity", defaults.enableParity, CONFIGFILE))
@@ -1879,22 +1938,13 @@ int scsiDiskCommand()
         //int immed = scsiDev.cdb[1] & 1;
         int start = scsiDev.cdb[4] & 1;
 
-        if (scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100)
+        if (start)
         {
-            // If it's a ZIP drive, it likes to eject all the time so this
-            // little dance helps keep a disc loaded
-            if (start)
-            {
-                scsiDev.target->started = 1;
-            }
-            else
-            {
-                scsiDev.target->started = 0;
-            }
+            scsiDev.target->started = 1;
         }
         else
         {
-            scsiDev.target->started = 1;
+            scsiDev.target->started = 0;
         }
     }
     else if (unlikely(command == 0x00))

+ 3 - 0
src/BlueSCSI_disk.h

@@ -143,3 +143,6 @@ void scsiDiskStartWrite(uint32_t lba, uint32_t blocks);
 
 // Returns true if there is at least one network device active
 bool scsiDiskCheckAnyNetworkDevicesConfigured();
+
+// Switch to next Drive image if multiple have been configured
+bool switchNextImage(image_config_t &img, const char* next_filename = nullptr);

+ 1 - 0
src/BlueSCSI_log.cpp

@@ -7,6 +7,7 @@
 
 const char *g_log_firmwareversion = BLUESCSI_FW_VERSION " " __DATE__ " " __TIME__;
 bool g_log_debug = false;
+uint8_t g_scsi_log_mask = 0;
 bool g_test_mode = false;
 
 // This memory buffer can be read by debugger and is also saved to log.txt

+ 8 - 1
src/BlueSCSI_log.h

@@ -4,8 +4,9 @@
 
 #pragma once
 
-#include <stdint.h>
+#include "scsiPhy.h"
 #include <stddef.h>
+#include <stdint.h>
 
 // Get total number of bytes that have been written to log
 uint32_t log_get_buffer_len();
@@ -17,6 +18,7 @@ const char *log_get_buffer(uint32_t *startpos, uint32_t *available = nullptr);
 
 // Whether to enable debug messages
 extern "C" bool g_log_debug;
+extern "C" uint8_t g_scsi_log_mask;
 
 // Enables output test mode
 extern bool g_test_mode;
@@ -97,6 +99,11 @@ inline void debuglog(Params... params)
 {
     if (g_log_debug)
     {
+        uint8_t log_for_id = (0x01 << (*SCSI_STS_SELECTED & 7)) & g_scsi_log_mask;
+        if(log_for_id == 0)
+        {
+            return;
+        }
         log_raw("[", (int)millis(), "ms] DBG ");
         log_raw(params...);
         log_raw("\n");