Преглед изворни кода

Implement Iomega ZIP100 support

jokker пре 1 година
родитељ
комит
4c8b6a96e8

+ 1 - 0
lib/SCSI2SD/include/scsi2sd.h

@@ -75,6 +75,7 @@ typedef enum
 	S2S_CFG_MO,
 	S2S_CFG_SEQUENTIAL,
 	S2S_CFG_NETWORK,
+	S2S_CFG_ZIP100,
 } S2S_CFG_TYPE;
 
 typedef enum

+ 22 - 0
lib/SCSI2SD/src/firmware/mode.c

@@ -254,6 +254,20 @@ static const uint8_t BlueSCSIVendorPage[] =
 'S','T','O','L','E','N',' ','F','R','O','M',' ','B','L','U','E','S','C','S','I',0x00
 };
 
+static const uint8_t IomegaZip100VendorPage[] =
+{
+0x2f, // Page Code
+4, // Page Length
+0x5c, 0xf, 0xff, 0xf
+};
+
+static const uint8_t IomegaZip250VendorPage[] =
+{
+0x2f, // Page Code
+4, // Page Length
+0x5c, 0xf, 0x3c, 0xf
+};
+
 static void pageIn(int pc, int dataIdx, const uint8_t* pageData, int pageLen)
 {
 	memcpy(&scsiDev.data[dataIdx], pageData, pageLen);
@@ -510,6 +524,14 @@ static void doModeSense(
 	idx += modeSenseCDDevicePage(pc, idx, pageCode, &pageFound);
 	idx += modeSenseCDAudioControlPage(pc, idx, pageCode, &pageFound);
 
+	if ((scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100) &&
+		(pageCode == 0x2f || pageCode == 0x3f))
+	{
+		pageFound = 1;
+		pageIn(pc, idx, IomegaZip100VendorPage, sizeof(IomegaZip100VendorPage));
+		idx += sizeof(IomegaZip100VendorPage);
+	}
+	
 	if ((scsiDev.target->cfg->deviceType == S2S_CFG_SEQUENTIAL) &&
 		(pageCode == 0x10 || pageCode == 0x3F))
 	{

+ 1 - 0
lib/SCSI2SD/src/firmware/scsi.h

@@ -19,6 +19,7 @@
 
 #include "geometry.h"
 #include "sense.h"
+#include "vendor.h"
 
 #include <stdint.h>
 

+ 78 - 1
lib/SCSI2SD/src/firmware/vendor.c

@@ -19,6 +19,8 @@
 #include "vendor.h"
 #include "diagnostic.h"
 
+#include <string.h>
+
 // Callback after the DATA OUT phase is complete.
 static void doAssignDiskParameters(void)
 {
@@ -45,8 +47,83 @@ int scsiVendorCommand()
 	int commandHandled = 1;
 
 	uint8_t command = scsiDev.cdb[0];
+	uint8_t alloc_length = scsiDev.cdb[4];
+
+	// iomega sense command
+	if (command == 0x06 && scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100)
+	{
+		int subcommand = scsiDev.cdb[2];
+		scsiDev.phase = DATA_IN;
+	
+		// byte 0 is the page
+		scsiDev.data[0] = subcommand;
+
+		if (subcommand == 0x1)
+		{
+			// page is 86 bytes in length
+			scsiDev.dataLen = alloc_length < 0x58 ? alloc_length : 0x58;
+			memset(&scsiDev.data[1], 0xff, scsiDev.dataLen);
+			// byte 1 is the page length minus pagecode and length
+			scsiDev.data[1] = scsiDev.dataLen - 2;
+			
+			scsiDev.data[2] = 1;
+			scsiDev.data[3] = 0;
+			scsiDev.data[4] = 0;
+			scsiDev.data[5] = 0;
+			scsiDev.data[6] = 0x5;
+			scsiDev.data[7] = 0xdc;
+			scsiDev.data[8] = 0x6;
+			scsiDev.data[9] = 0xc;
+			scsiDev.data[10] = 0x5;
+			scsiDev.data[11] = 0xdc;
+			scsiDev.data[12] = 0x6;
+			scsiDev.data[13] = 0xc;
+			scsiDev.data[14] = 0;
+		}
+		else if (subcommand == 0x2) {
+			// page is 61 bytes in length
+			scsiDev.dataLen = alloc_length < 0x3f ? alloc_length : 0x3f;
+			memset(&scsiDev.data[1], 0, scsiDev.dataLen);
+			// byte 1 is the page length minus pagecode and length
+			scsiDev.data[1] = scsiDev.dataLen - 2;
+
+			scsiDev.data[3] = 2;
+			scsiDev.data[6] = 0x2;
+			scsiDev.data[7] = 0xff;
+			scsiDev.data[8] = 0xff;
+			scsiDev.data[11] = 0x2;
 
-	if (command == 0xC0)
+			// this has something to do with the format/disk life
+			// currently this makes it 100%
+			scsiDev.data[14] = 0x7e;
+			scsiDev.data[18] = 0x7e;
+
+			// byte 21 is the read/write/password settings
+			// 5 = password for R/W
+			// 3 = password for W
+			// 2 = RO
+			// 0 = RW
+			scsiDev.data[20] = 0;
+
+			// set a serial number ABCDEFGHIJKLMNO
+			// starts at byte 25 and is 15 bytes long
+			for(int i = 0; i < 20; i++) {
+				scsiDev.data[25 + i] = i + 0x41;
+			}
+
+			scsiDev.data[0x3e] = 1;
+		}
+		else
+		{
+			// anything else is an illegal command
+			scsiDev.status = CHECK_CONDITION;
+			scsiDev.target->sense.code = ILLEGAL_REQUEST;
+			scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;
+			scsiDev.phase = STATUS;
+		}
+
+	}
+	else if (command == 0xC0)
 	{
 		// Define flexible disk format
 		// OMTI-5204 controller

+ 3 - 0
lib/SCSI2SD/src/firmware/vendor.h

@@ -17,6 +17,9 @@
 #ifndef S2S_VENDOR_H
 #define S2S_VENDOR_H
 
+#define ZIP100_DISC_SIZE    100663296 // bytes
+#define ZIP250_DISC_SIZE    250640384 // bytes
+
 int scsiVendorCommand(void);
 
 #endif

+ 3 - 1
src/BlueSCSI.cpp

@@ -284,6 +284,7 @@ bool findHDDImages()
       bool is_ne = (tolower(name[0]) == 'n' && tolower(name[1]) == 'e');
       bool is_re = (tolower(name[0]) == 'r' && tolower(name[1]) == 'e');
       bool is_tp = (tolower(name[0]) == 't' && tolower(name[1]) == 'p');
+      bool is_zp = (tolower(name[0]) == 'z' && tolower(name[1]) == 'p');
 
       if(strcasecmp(name, "CLEAR_ROM") == 0)
       {
@@ -291,7 +292,7 @@ bool findHDDImages()
         continue;
       }
 
-      if (is_hd || is_cd || is_fd || is_mo || is_ne || is_re || is_tp)
+      if (is_hd || is_cd || is_fd || is_mo || is_ne || is_re || is_tp || is_zp)
       {
         // Check if the image should be loaded to microcontroller flash ROM drive
         bool is_romdrive = false;
@@ -371,6 +372,7 @@ bool findHDDImages()
         if (is_ne) type = S2S_CFG_NETWORK;
         if (is_re) type = S2S_CFG_REMOVEABLE;
         if (is_tp) type = S2S_CFG_SEQUENTIAL;
+        if (is_zp) type = S2S_CFG_ZIP100;
 
         // Open the image file
         if (id < NUM_SCSIID && is_romdrive)

+ 5 - 0
src/BlueSCSI_config.h

@@ -67,6 +67,11 @@
 #define APPLE_DRIVEINFO_NETWORK   {"Dayna",    "SCSI/Link",       "2.0f", ""}
 #define APPLE_DRIVEINFO_TAPE      {"BlueSCSI", "APPLE_TAPE",      "",     ""}
 
+// Default Iomega ZIP drive information
+#define IOMEGA_DRIVEINFO_ZIP100     {"IOMEGA", "ZIP 100", "E.08", ""}
+#define IOMEGA_DRIVEINFO_ZIP250     {"IOMEGA", "ZIP 250", "42.S", ""}
+#define IOMEGA_DRIVEINFO_JAZ        {"iomega", "jaz", "", ""}
+
 // Default delay for SCSI phases.
 // Can be adjusted in ini file
 #define DEFAULT_SCSI_DELAY_US 10

+ 27 - 6
src/BlueSCSI_disk.cpp

@@ -273,6 +273,8 @@ static void setDefaultDriveInfo(int target_idx)
     static const char *apl_driveinfo_network[4]   = APPLE_DRIVEINFO_NETWORK;
     static const char *apl_driveinfo_tape[4]      = APPLE_DRIVEINFO_TAPE;
 
+    static const char *iomega_driveinfo_removeable[4] = IOMEGA_DRIVEINFO_ZIP100;
+
     const char **driveinfo = NULL;
 
     if (img.quirks == S2S_CFG_QUIRKS_APPLE)
@@ -302,6 +304,7 @@ static void setDefaultDriveInfo(int target_idx)
             case S2S_CFG_MO:            driveinfo = driveinfo_magopt; break;
             case S2S_CFG_NETWORK:       driveinfo = driveinfo_network; break;
             case S2S_CFG_SEQUENTIAL:    driveinfo = driveinfo_tape; break;
+            case S2S_CFG_ZIP100:        driveinfo = iomega_driveinfo_removeable; break;
             default:                    driveinfo = driveinfo_fixed; break;
         }
     }
@@ -429,6 +432,18 @@ bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int
             log("---- Configuring as tape drive based on image name");
             img.deviceType = S2S_CFG_SEQUENTIAL;
         }
+        else if (type == S2S_CFG_ZIP100)
+        {
+            log("---- Configuration as Iomega ZIP100 drive based on image name");
+            img.deviceType = S2S_CFG_ZIP100;
+            if(img.file.size() != ZIP100_DISC_SIZE)
+            {
+                log("---- ZIP100 disc (", (int)img.file.size(), " bytes) is not exactly ", ZIP100_DISC_SIZE, " bytes, drive is ignored");
+                img.file.close();
+                img.clear();
+                return false;
+            }
+        }
 
         if (img.prefetchbytes != PREFETCH_BUFFER_SIZE)
         {
@@ -1863,14 +1878,20 @@ int scsiDiskCommand()
         // Enable or disable media access operations.
         //int immed = scsiDev.cdb[1] & 1;
         int start = scsiDev.cdb[4] & 1;
-
-        if (start)
+        
+        if (scsiDev.target->cfg->deviceType == S2S_CFG_ZIP100)
         {
-            scsiDev.target->started = 1;
+            if (start)
+            {
+                scsiDev.target->started = 1;
+            }
+            else
+            {
+                scsiDev.target->started = 0;
+            }
         }
-        else
-        {
-            scsiDev.target->started = 0;
+        else {
+            scsiDev.target->started = 1;
         }
     }
     else if (unlikely(command == 0x00))

+ 1 - 0
src/BlueSCSI_log_trace.cpp

@@ -28,6 +28,7 @@ static const char *getCommandName(uint8_t cmd)
         case 0x03: return "RequestSense";
         case 0x04: return "FormatUnit";
         case 0x05: return "ReadBlockLimits";
+        case 0x06: return "IomegaVendorCommand";
         case 0x08: return "Read6";
         case 0x0A: return "Write6";
         case 0x0B: return "Seek6";