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

Adding Ensoniq ASR-10 support and improved FORMAT UNIT command.

- Read the data-phase bytes during a FORMAT UNIT command
- Return the exact number of bytes requested for the REQUEST SENSE command
Michael McMaster 11 жил өмнө
parent
commit
92b2e58d27

+ 2 - 0
lib/SCSI2SD/CHANGELOG

@@ -1,5 +1,7 @@
 201404??		3.4
 201404??		3.4
 	- Fix to ensure SCSI phase bits are set atomically.
 	- Fix to ensure SCSI phase bits are set atomically.
+	- Always return the requested number of bytes for a REQUEST SENSE command
+		This is required to support the Ensoniq ASR-10.
 	- Decreased (unused) heap and stack sizes to prepare for a memory
 	- Decreased (unused) heap and stack sizes to prepare for a memory
 	write cache
 	write cache
 
 

+ 1 - 1
lib/SCSI2SD/readme.txt

@@ -66,5 +66,5 @@ Users have reported success on these systems:
     Roland JS-30 Sampler
     Roland JS-30 Sampler
     Akai S1000, S3200, S3000XL, MPC 2000XL, DPS 12
     Akai S1000, S3200, S3000XL, MPC 2000XL, DPS 12
     EMU Emulator E4X with EOS 3.00b and E6400 (classic) with Eos 4.01
     EMU Emulator E4X with EOS 3.00b and E6400 (classic) with Eos 4.01
-    Ensoniq ASR-X
+    Ensoniq ASR-X, ASR-10 (from v3.4, 2GB size limit)
     HP 16601A logic analyzer
     HP 16601A logic analyzer

+ 78 - 4
lib/SCSI2SD/software/SCSI2SD/src/disk.c

@@ -18,6 +18,7 @@
 
 
 #include "device.h"
 #include "device.h"
 #include "scsi.h"
 #include "scsi.h"
+#include "scsiPhy.h"
 #include "config.h"
 #include "config.h"
 #include "disk.h"
 #include "disk.h"
 #include "sd.h"
 #include "sd.h"
@@ -38,11 +39,69 @@ static int doSdInit()
 	return result;
 	return result;
 }
 }
 
 
+// Callback once all data has been read in the data out phase.
+static void doFormatUnitComplete(void)
+{
+	// TODO start writing the initialisation pattern to the SD
+	// card
+	scsiDev.phase = STATUS;
+}
+
+static void doFormatUnitSkipData(int bytes)
+{
+	// We may not have enough memory to store the initialisation pattern and
+	// defect list data.  Since we're not making use of it yet anyway, just
+	// discard the bytes.
+	scsiEnterPhase(DATA_OUT);
+	int i;
+	for (i = 0; i < bytes; ++i)
+	{
+		scsiReadByte();	
+	}
+}
 
 
-static void doFormatUnit()
+// Callback from the data out phase.
+static void doFormatUnitPatternHeader(void)
 {
 {
-	// Low-level formatting is not required.
-	// Nothing left to do.
+	int defectLength =
+		((((uint16_t)scsiDev.data[2])) << 8) +
+			scsiDev.data[3];
+			
+	int patternLength =
+		((((uint16_t)scsiDev.data[4 + 2])) << 8) +
+		scsiDev.data[4 + 3];
+
+		doFormatUnitSkipData(defectLength + patternLength);
+		doFormatUnitComplete();
+}
+
+// Callback from the data out phase.
+static void doFormatUnitHeader(void)
+{
+	int IP = (scsiDev.data[1] & 0x08) ? 1 : 0;
+	int DSP = (scsiDev.data[1] & 0x04) ? 1 : 0;
+	
+	if (! DSP) // disable save parameters
+	{
+		configSave(); // Save the "MODE SELECT savable parameters"
+	}
+	
+	if (IP)
+	{
+		// We need to read the initialisation pattern header first.
+		scsiDev.dataLen += 4;
+		scsiDev.phase = DATA_OUT;
+		scsiDev.postDataOutHook = doFormatUnitPatternHeader;
+	}
+	else
+	{
+		// Read the defect list data
+		int defectLength =
+			((((uint16_t)scsiDev.data[2])) << 8) +
+			scsiDev.data[3];
+		doFormatUnitSkipData(defectLength);
+		doFormatUnitComplete();
+	}
 }
 }
 
 
 static void doReadCapacity()
 static void doReadCapacity()
@@ -240,7 +299,22 @@ int scsiDiskCommand()
 	else if (command == 0x04)
 	else if (command == 0x04)
 	{
 	{
 		// FORMAT UNIT
 		// FORMAT UNIT
-		doFormatUnit();
+		// We don't really do any formatting, but we need to read the correct
+		// number of bytes in the DATA_OUT phase to make the SCSI host happy.
+		
+		int fmtData = (scsiDev.cdb[1] & 0x10) ? 1 : 0;
+		if (fmtData)
+		{
+			// We need to read the parameter list, but we don't know how
+			// big it is yet. Start with the header.
+			scsiDev.dataLen = 4;
+			scsiDev.phase = DATA_OUT;
+			scsiDev.postDataOutHook = doFormatUnitHeader;
+		}
+		else
+		{
+			// No data to read, we're already finished!
+		}
 	}
 	}
 	else if (command == 0x08)
 	else if (command == 0x08)
 	{
 	{

+ 10 - 17
lib/SCSI2SD/software/SCSI2SD/src/scsi.c

@@ -281,8 +281,12 @@ static void process_Command()
 	{
 	{
 		// REQUEST SENSE
 		// REQUEST SENSE
 		uint32 allocLength = scsiDev.cdb[4];
 		uint32 allocLength = scsiDev.cdb[4];
-		if (allocLength == 0) allocLength = 256;
-		memset(scsiDev.data, 0, 18);
+
+		// As specified by the SASI and SCSI1 standard.
+		// Newer initiators won't be specifying 0 anyway.
+		if (allocLength == 0) allocLength = 4;
+
+		memset(scsiDev.data, 0, 256); // Max possible alloc length
 		scsiDev.data[0] = 0xF0;
 		scsiDev.data[0] = 0xF0;
 		scsiDev.data[2] = scsiDev.sense.code & 0x0F;
 		scsiDev.data[2] = scsiDev.sense.code & 0x0F;
 
 
@@ -292,23 +296,12 @@ static void process_Command()
 		scsiDev.data[6] = transfer.lba;
 		scsiDev.data[6] = transfer.lba;
 
 
 		// Additional bytes if there are errors to report
 		// Additional bytes if there are errors to report
-		int responseLength;
-		if (scsiDev.sense.code == NO_SENSE)
-		{
-			responseLength = 8;
-		}
-		else
-		{
-			responseLength = 18;
-			scsiDev.data[7] = 10; // additional length
-			scsiDev.data[12] = scsiDev.sense.asc >> 8;
-			scsiDev.data[13] = scsiDev.sense.asc;
-		}
+		scsiDev.data[7] = 10; // additional length
+		scsiDev.data[12] = scsiDev.sense.asc >> 8;
+		scsiDev.data[13] = scsiDev.sense.asc;
 
 
 		// Silently truncate results. SCSI-2 spec 8.2.14.
 		// Silently truncate results. SCSI-2 spec 8.2.14.
-		enter_DataIn(
-			(allocLength < responseLength) ? allocLength : responseLength
-			);
+		enter_DataIn(allocLength);
 
 
 		// This is a good time to clear out old sense information.
 		// This is a good time to clear out old sense information.
 		scsiDev.sense.code = NO_SENSE;
 		scsiDev.sense.code = NO_SENSE;