diff --git a/CHANGELOG b/CHANGELOG index 896e65c..7c694e0 100644 --- a/CHANGELOG +++ b/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 diff --git a/readme.txt b/readme.txt index f6de680..daaea7c 100644 --- a/readme.txt +++ b/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 diff --git a/software/SCSI2SD/src/disk.c b/software/SCSI2SD/src/disk.c index fb76ff2..d9961d3 100755 --- a/software/SCSI2SD/src/disk.c +++ b/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; } - -static void doFormatUnit() +// Callback once all data has been read in the data out phase. +static void doFormatUnitComplete(void) { - // Low-level formatting is not required. - // Nothing left to do. + // 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(); + } +} + +// Callback from the data out phase. +static void doFormatUnitPatternHeader(void) +{ + 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) { diff --git a/software/SCSI2SD/src/scsi.c b/software/SCSI2SD/src/scsi.c index 3d64116..a687cef 100755 --- a/software/SCSI2SD/src/scsi.c +++ b/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;