Jelajahi Sumber

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 tahun lalu
induk
melakukan
92b2e58d27

+ 2 - 0
lib/SCSI2SD/CHANGELOG

@@ -1,5 +1,7 @@
 201404??		3.4
 	- 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
 	write cache
 

+ 1 - 1
lib/SCSI2SD/readme.txt

@@ -66,5 +66,5 @@ Users have reported success on these systems:
     Roland JS-30 Sampler
     Akai S1000, S3200, S3000XL, MPC 2000XL, DPS 12
     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

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

@@ -18,6 +18,7 @@
 
 #include "device.h"
 #include "scsi.h"
+#include "scsiPhy.h"
 #include "config.h"
 #include "disk.h"
 #include "sd.h"
@@ -38,11 +39,69 @@ static int doSdInit()
 	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()
@@ -240,7 +299,22 @@ int scsiDiskCommand()
 	else if (command == 0x04)
 	{
 		// 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)
 	{

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

@@ -281,8 +281,12 @@ static void process_Command()
 	{
 		// REQUEST SENSE
 		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[2] = scsiDev.sense.code & 0x0F;
 
@@ -292,23 +296,12 @@ static void process_Command()
 		scsiDev.data[6] = transfer.lba;
 
 		// 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.
-		enter_DataIn(
-			(allocLength < responseLength) ? allocLength : responseLength
-			);
+		enter_DataIn(allocLength);
 
 		// This is a good time to clear out old sense information.
 		scsiDev.sense.code = NO_SENSE;