瀏覽代碼

Add 3 modes image writing in initiator mode

In the zuluscsi.ini file a new option `InitiatorImageHandling`
has been added.
The values are:
 - 0: Stop if image exist, an image file exist don't re-image the drive
 - 1: Create new image, an image file exists re-image to a new file
 - 2: Overwrite image, an image file exists overwrite that file

The default is 0

Also added the option `InitiatorID` to zuluscsi.ini which sets the
initiator SCSI ID. The default setting for the host (initiator)
SCSI ID to 7, when the option is used the host SCSI ID is set to that
number. If the value is out of range, it sets it to 7.
Morio 2 年之前
父節點
當前提交
1aeb33de7a

+ 1 - 1
lib/ZuluSCSI_platform_RP2040/rp2040.ld

@@ -22,7 +22,7 @@
 MEMORY
 {
     FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 352k
-    RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 240k  /* Leave space for pico-debug */
+    RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k  /* Leave space for pico-debug */
     SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
     SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
 }

+ 2 - 5
lib/ZuluSCSI_platform_RP2040/scsiHostPhy.cpp

@@ -62,9 +62,9 @@ void scsiHostPhyReset(void)
     g_scsiHostPhyReset = false;
 }
 
-// Select a device, id 0-7.
+// Select a device and an initiator, ids 0-7.
 // Returns true if the target answers to selection request.
-bool scsiHostPhySelect(int target_id)
+bool scsiHostPhySelect(int target_id, uint8_t initiator_id)
 {
     SCSI_RELEASE_OUTPUTS();
 
@@ -86,9 +86,6 @@ bool scsiHostPhySelect(int target_id)
         }
     }
 
-    // Choose initiator ID different than target ID
-    uint8_t initiator_id = (target_id == 7) ? 0 : 7;
-
     // Selection phase
     scsiLogInitiatorPhaseChange(SELECTION);
     dbgmsg("------ SELECTING ", target_id, " with initiator ID ", (int)initiator_id);

+ 3 - 1
lib/ZuluSCSI_platform_RP2040/scsiHostPhy.h

@@ -34,8 +34,10 @@ extern volatile int g_scsiHostPhyReset;
 void scsiHostPhyReset(void);
 
 // Select a device, id 0-7.
+// target_id - target device id 0-7
+// initiator_id - host device id 0-7
 // Returns true if the target answers to selection request.
-bool scsiHostPhySelect(int target_id);
+bool scsiHostPhySelect(int target_id, uint8_t initiator_id);
 
 // Read the current communication phase as signaled by the target
 // Matches SCSI_PHASE enumeration from scsi.h.

+ 1 - 0
platformio.ini

@@ -98,6 +98,7 @@ lib_deps =
     ZuluSCSI_platform_RP2040
     SCSI2SD
     CUEParser
+debug_build_flags = -O2 -ggdb -g3
 build_flags =
     -O2 -Isrc -ggdb -g3
     -Wall -Wno-sign-compare -Wno-ignored-qualifiers

+ 89 - 7
src/ZuluSCSI_initiator.cpp

@@ -29,6 +29,7 @@
 #include "ZuluSCSI_log_trace.h"
 #include "ZuluSCSI_initiator.h"
 #include <ZuluSCSI_platform.h>
+#include <minIni.h>
 #include "SdFat.h"
 
 #include <scsi2sd.h>
@@ -68,6 +69,8 @@ static struct {
     // Bitmap of all drives that have been imaged
     uint32_t drives_imaged;
 
+    uint8_t initiator_id;
+
     // Is imaging a drive in progress, or are we scanning?
     bool imaging;
 
@@ -94,7 +97,15 @@ void scsiInitiatorInit()
 {
     scsiHostPhyReset();
 
-    g_initiator_state.drives_imaged = 0;
+    g_initiator_state.initiator_id = ini_getl("SCSI", "InitiatorID", 7, CONFIGFILE);
+    if (g_initiator_state.initiator_id > 7)
+    {
+        logmsg("InitiatorID set to illegal value in, ", CONFIGFILE, ", defaulting to 7");
+        g_initiator_state.initiator_id = 7;
+    }
+    // treat initiator id as already imaged drive so it gets skipped
+    g_initiator_state.drives_imaged = 1 << g_initiator_state.initiator_id;
+
     g_initiator_state.imaging = false;
     g_initiator_state.target_id = -1;
     g_initiator_state.sectorsize = 0;
@@ -103,6 +114,8 @@ void scsiInitiatorInit()
     g_initiator_state.retrycount = 0;
     g_initiator_state.failposition = 0;
     g_initiator_state.max_sector_per_transfer = 512;
+
+
 }
 
 // Update progress bar LED during transfers
@@ -209,22 +222,90 @@ void scsiInitiatorMainLoop()
                 g_initiator_state.sectorcount = g_initiator_state.sectorcount_all = 0;
             }
 
-            const char *filename_format = "HD00_imaged.hda";
+            char filename_base[12];
+            strncpy(filename_base, "HD00_imaged", sizeof(filename_base));
+            const char *filename_extention = ".hda";
             if (inquiryok)
             {
                 if ((inquiry_data[0] & 0x1F) == 5)
                 {
-                    filename_format = "CD00_imaged.iso";
+                    strncpy(filename_base, "CD00_imaged", sizeof(filename_base));
+                    filename_extention = ".iso";
                 }
             }
 
             if (g_initiator_state.sectorcount > 0)
             {
                 char filename[32] = {0};
-                strncpy(filename, filename_format, sizeof(filename) - 1);
-                filename[2] += g_initiator_state.target_id;
+                filename_base[2] += g_initiator_state.target_id;
+                strncpy(filename, filename_base, sizeof(filename) - 1);
+                strncat(filename, filename_extention, sizeof(filename) - 1);
+                static int handling = -1;
+                if (handling == -1)
+                {
+                    handling = ini_getl("SCSI", "InitiatorImageHandling", 0, CONFIGFILE);
+                }
+                // Stop if a file already exists
+                if (handling == 0)
+                {
+                    if (SD.exists(filename))
+                    {
+                        logmsg("File, ", filename, ", already exists, InitiatorImageHandling set to stop if file exists.");
+                        g_initiator_state.drives_imaged |= (1 << g_initiator_state.target_id);
+                        return;
+                    }
+                }
+                // Create a new copy to the file 002-999
+                else if (handling == 1)
+                {
+                    for (uint32_t i = 1; i <= 1000; i++)
+                    {
+                        if (i == 1)
+                        {
+                            if (SD.exists(filename))
+                                continue;
+                            break;
+                        }
+                        else if(i >= 1000)
+                        {
+                            logmsg("Max images created from SCSI ID ", g_initiator_state.target_id, ", skipping image creation");
+                            g_initiator_state.drives_imaged |= (1 << g_initiator_state.target_id);
+                            return;
+                        }
+                        char filename_copy[6] = {0};
+                        snprintf(filename_copy, sizeof(filename_copy), "_%03lu", i);
+
+                        strncpy(filename, filename_base, sizeof(filename) - 1);
+                        strncat(filename, filename_copy, sizeof(filename) - 1);
+                        strncat(filename, filename_extention, sizeof(filename) - 1);
+
+                        if (SD.exists(filename))
+                            continue;
+                        break;
+                    }
+
+                }
+                // overwrite file if it exists
+                else if (handling == 2)
+                {
+                    if (SD.exists(filename))
+                    {
+                        logmsg("File, ",filename, " already exists, InitiatorImageHandling set to overwrite file");
+                        SD.remove(filename);
+                    }
+                }
+                // InitiatorImageHandling invalid setting
+                else
+                {
+                    static bool invalid_logged_once = false;
+                    if (!invalid_logged_once)
+                    {
+                        logmsg("InitiatorImageHandling is set to, ", handling, ", which is invalid");
+                        invalid_logged_once = true;
+                    }
+                    return;
+                }
 
-                SD.remove(filename);
                 g_initiator_state.target_file = SD.open(filename, O_RDWR | O_CREAT | O_TRUNC);
                 if (!g_initiator_state.target_file.isOpen())
                 {
@@ -334,7 +415,8 @@ int scsiInitiatorRunCommand(int target_id,
                             const uint8_t *bufOut, size_t bufOutLen,
                             bool returnDataPhase)
 {
-    if (!scsiHostPhySelect(target_id))
+
+    if (!scsiHostPhySelect(target_id, g_initiator_state.initiator_id))
     {
         dbgmsg("------ Target ", target_id, " did not respond");
         scsiHostPhyRelease();

+ 4 - 0
zuluscsi.ini

@@ -31,6 +31,10 @@
 #DisableROMDrive = 1 # Disable the ROM drive if it has been loaded to flash
 #ROMDriveSCSIID = 7 # Override ROM drive's SCSI ID
 
+#Initiaor settings
+#InitiatorID = 7 # SCSI ID, 0-7, when the device is in initiator mode, default is 7
+#InitiatorImageHandling = 0 # 0: skip exisitng images, 1: create new image with incrementing suffix, 2: overwrite exising image
+
 # Settings that can be specified either per-device or for all devices.
 #Vendor = "QUANTUM"
 #Product = "FIREBALL1"