浏览代码

Merge pull request #286 from jjakob/xebec_s1410

New Xebec S1410 vendor command and various work
Alex Perez 2 年之前
父节点
当前提交
39d95667f2

+ 1 - 11
lib/SCSI2SD/src/firmware/diagnostic.c

@@ -196,7 +196,7 @@ void scsiReadBuffer()
 }
 
 // Callback after the DATA OUT phase is complete.
-static void doWriteBuffer(void)
+void doWriteBuffer(void)
 {
 	if (scsiDev.status == GOOD) // skip if we've already encountered an error
 	{
@@ -234,14 +234,4 @@ void scsiWriteBuffer()
 	}
 }
 
-// XEBEC specific command. See
-// http://www.bitsavers.org/pdf/westernDigital/WD100x/79-000004_WD1002-SHD_OEM_Manual_Aug1984.pdf
-// Section 4.3.14
-void scsiWriteSectorBuffer()
-{
-	scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;
-	scsiDev.phase = DATA_OUT;
-	scsiDev.postDataOutHook = doWriteBuffer;
-}
-
 

+ 1 - 1
lib/SCSI2SD/src/firmware/diagnostic.h

@@ -19,8 +19,8 @@
 
 void scsiSendDiagnostic(void);
 void scsiReceiveDiagnostic(void);
+void doWriteBuffer(void);
 void scsiWriteBuffer(void);
-void scsiWriteSectorBuffer(void);
 void scsiReadBuffer(void);
 
 #endif

+ 51 - 13
lib/SCSI2SD/src/firmware/scsi.c

@@ -382,14 +382,57 @@ static void process_Command()
 		{
 			// Completely non-standard
 			allocLength = 4;
-			if (scsiDev.target->sense.code == NO_SENSE)
-				scsiDev.data[0] = 0;
-			else if (scsiDev.target->sense.code == ILLEGAL_REQUEST)
-				scsiDev.data[0] = 0x20; // Illegal command
-			else if (scsiDev.target->sense.code == NOT_READY)
-				scsiDev.data[0] = 0x04; // Drive not ready
-			else
-				scsiDev.data[0] = 0x11;  // Uncorrectable data error
+
+			switch (scsiDev.target->sense.code)
+			{
+				case NO_SENSE:
+					scsiDev.data[0] = 0;
+					break;
+				case MEDIUM_ERROR:
+					switch (scsiDev.target->sense.asc)
+					{
+						case NO_SEEK_COMPLETE:
+							scsiDev.data[0] = 0x15; // Seek Error
+							break;
+						case WRITE_ERROR_AUTO_REALLOCATION_FAILED:
+							scsiDev.data[0] = 0x03; // Write fault
+							break;
+						default:
+						case UNRECOVERED_READ_ERROR:
+							scsiDev.data[0] = 0x11; // Uncorrectable read error
+							break;
+					}
+					break;
+				case ILLEGAL_REQUEST:
+					switch (scsiDev.target->sense.asc)
+					{
+						case LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE:
+							scsiDev.data[0] = 0x14; // Target sector not found
+							break;
+						case WRITE_PROTECTED:
+							scsiDev.data[0] = 0x03; // Write fault
+							break;
+						default:
+							scsiDev.data[0] = 0x20; // Invalid command
+							break;
+					}
+					break;
+				case NOT_READY:
+					switch (scsiDev.target->sense.asc)
+					{
+						default:
+						case MEDIUM_NOT_PRESENT:
+							scsiDev.data[0] = 0x04; // Drive not ready
+							break;
+						case LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED:
+							scsiDev.data[0] = 0x1A; // Format Error
+							break;
+					}
+					break;
+				default:
+					scsiDev.data[0] = 0x11;  // Uncorrectable data error
+					break;
+			}
 
 			scsiDev.data[1] = (scsiDev.cdb[1] & 0x20) | ((transfer.lba >> 16) & 0x1F);
 			scsiDev.data[2] = transfer.lba >> 8;
@@ -540,11 +583,6 @@ static void process_Command()
 	{
 		scsiWriteBuffer();
 	}
-	else if (command == 0x0f &&
-		scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
-	{
-		scsiWriteSectorBuffer();
-	}
 	else if (command == 0x3C)
 	{
 		scsiReadBuffer();

+ 34 - 2
lib/SCSI2SD/src/firmware/vendor.c

@@ -17,12 +17,27 @@
 
 #include "scsi.h"
 #include "vendor.h"
-
+#include "diagnostic.h"
 
 // Callback after the DATA OUT phase is complete.
 static void doAssignDiskParameters(void)
 {
-	scsiDev.phase = STATUS;
+	if (scsiDev.status == GOOD)
+	{
+		scsiDev.phase = STATUS;
+	}
+}
+
+// XEBEC specific commands
+// http://www.bitsavers.org/pdf/xebec/104524C_S1410Man_Aug83.pdf
+// WD100x seems to be identical to the Xebec but calls this command "Set Parameters"
+// http://www.bitsavers.org/pdf/westernDigital/WD100x/79-000004_WD1002-SHD_OEM_Manual_Aug1984.pdf
+static void doXebecInitializeDriveCharacteristics()
+{
+	if (scsiDev.status == GOOD)
+	{
+		scsiDev.phase = STATUS;
+	}
 }
 
 int scsiVendorCommand()
@@ -48,6 +63,23 @@ int scsiVendorCommand()
 		scsiDev.phase = DATA_OUT;
 		scsiDev.postDataOutHook = doAssignDiskParameters;
 	}
+	else if (command == 0x0C &&
+		scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
+	{
+		// XEBEC S1410: "Initialize Drive Characteristics"
+		// WD100x: "Set Parameters"
+		scsiDev.dataLen = 8;
+		scsiDev.phase = DATA_OUT;
+		scsiDev.postDataOutHook = doXebecInitializeDriveCharacteristics;
+	}
+	else if (command == 0x0F &&
+		scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
+	{
+		// XEBEC S1410, WD100x: "Write Sector Buffer"
+		scsiDev.dataLen = scsiDev.target->liveCfg.bytesPerSector;
+		scsiDev.phase = DATA_OUT;
+		scsiDev.postDataOutHook = doWriteBuffer;
+	}
 	else
 	{
 		commandHandled = 0;

+ 2 - 1
src/ZuluSCSI_log_trace.cpp

@@ -49,7 +49,8 @@ static const char *getCommandName(uint8_t cmd)
         case 0x08: return "Read6";
         case 0x0A: return "Write6";
         case 0x0B: return "Seek6";
-        case 0x0F: return "WriteSectorBuffer";
+        case 0x0C: return "Xebec InitializeDriveCharacteristics";
+        case 0x0F: return "Xebec WriteSectorBuffer";
         case 0x10: return "WriteFilemarks";
         case 0x11: return "Space";
         case 0x12: return "Inquiry";