diff --git a/software/SCSI2SD/SCSI2SD.cydsn/disk.c b/software/SCSI2SD/SCSI2SD.cydsn/disk.c index 20de53b..c94aaa8 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/disk.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/disk.c @@ -118,6 +118,10 @@ static void doWrite(uint32 lba, uint32 blocks) scsiDev.phase = DATA_OUT; scsiDev.dataLen = SCSI_BLOCK_SIZE; scsiDev.dataPtr = SCSI_BLOCK_SIZE; // TODO FIX scsiDiskPoll() + + // No need for single-block reads atm. Overhead of the + // multi-block read is minimal. + transfer.multiBlock = 1; sdPrepareWrite(); } } @@ -140,7 +144,20 @@ static void doRead(uint32 lba, uint32 blocks) transfer.currentBlock = 0; scsiDev.phase = DATA_IN; scsiDev.dataLen = 0; // No data yet - sdPrepareRead(); + + if ((blocks == 1) || + (((uint64) lba) + blocks == blockDev.capacity) + ) + { + // We get errors on reading the last sector using a multi-sector + // read :-( + transfer.multiBlock = 0; + } + else + { + transfer.multiBlock = 1; + sdPrepareRead(); + } } } @@ -352,7 +369,14 @@ void scsiDiskPoll() { if (scsiDev.dataLen == 0) { - sdReadSector(); + if (transfer.multiBlock) + { + sdReadSectorMulti(); + } + else + { + sdReadSectorSingle(); + } } else if (scsiDev.dataPtr == scsiDev.dataLen) { @@ -361,9 +385,13 @@ void scsiDiskPoll() transfer.currentBlock++; if (transfer.currentBlock >= transfer.blocks) { + int needComplete = transfer.multiBlock; scsiDev.phase = STATUS; scsiDiskReset(); - sdCompleteRead(); + if (needComplete) + { + sdCompleteRead(); + } } } } @@ -378,6 +406,7 @@ void scsiDiskPoll() scsiDev.dataLen = 0; scsiDev.dataPtr = 0; scsiDev.phase = STATUS; + scsiDiskReset(); if (writeOk) @@ -397,6 +426,7 @@ void scsiDiskReset() transfer.lba = 0; transfer.blocks = 0; transfer.currentBlock = 0; + transfer.multiBlock = 0; } void scsiDiskInit() diff --git a/software/SCSI2SD/SCSI2SD.cydsn/disk.h b/software/SCSI2SD/SCSI2SD.cydsn/disk.h index 2133279..a58425f 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/disk.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/disk.h @@ -42,6 +42,7 @@ typedef struct typedef struct { int dir; + int multiBlock; // True if we're using a multi-block SPI transfer. uint32 lba; uint32 blocks; diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.c b/software/SCSI2SD/SCSI2SD.cydsn/sd.c index a35ea6e..bf2d12c 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.c @@ -147,7 +147,7 @@ void sdPrepareRead() } } -void sdReadSector() +static void doReadSector() { int prep, i, guard; @@ -163,7 +163,10 @@ void sdReadSector() } if (token != 0xFE) { - sdCompleteRead(); + if (transfer.multiBlock) + { + sdCompleteRead(); + } if (scsiDev.status != CHECK_CONDITION) { scsiDev.status = CHECK_CONDITION; @@ -235,6 +238,39 @@ void sdReadSector() scsiDev.dataPtr = SCSI_BLOCK_SIZE; } +void sdReadSectorSingle() +{ + uint8 v; + uint32 len = (transfer.lba + transfer.currentBlock); + if (!sdDev.ccs) + { + len = len * SCSI_BLOCK_SIZE; + } + v = sdCommandAndResponse(SD_READ_SINGLE_BLOCK, len); + if (v) + { + scsiDiskReset(); + sdClearStatus(); + + scsiDev.status = CHECK_CONDITION; + scsiDev.sense.code = HARDWARE_ERROR; + scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE; + scsiDev.phase = STATUS; + } + else + { + doReadSector(); + } +} + +void sdReadSectorMulti() +{ + // Pre: sdPrepareRead called. + + doReadSector(); +} + + void sdCompleteRead() { // We cannot send even a single "padding" byte, as we normally would when @@ -294,8 +330,6 @@ int sdWriteSector() scsiEnterPhase(DATA_OUT); } - // Wait for a previously-written sector to complete. - sdWaitWriteBusy(); sdSpiByte(0xFC); // MULTIPLE byte start token prep = 0; @@ -382,8 +416,7 @@ int sdWriteSector() } else { - // The card is probably in the busy state. - // Don't wait, as we could read the SCSI interface instead. + sdWaitWriteBusy(); result = 1; } @@ -394,9 +427,6 @@ void sdCompleteWrite() { uint8 r1, r2; - // Wait for a previously-written sector to complete. - sdWaitWriteBusy(); - sdSpiByte(0xFD); // STOP TOKEN // Wait for the card to come out of busy. sdWaitWriteBusy(); diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.h b/software/SCSI2SD/SCSI2SD.cydsn/sd.h index 7cdca9a..7eb8fcf 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.h +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.h @@ -26,6 +26,7 @@ typedef enum SD_STOP_TRANSMISSION = 12, SD_SEND_STATUS = 13, SD_SET_BLOCKLEN = 16, + SD_READ_SINGLE_BLOCK = 17, SD_READ_MULTIPLE_BLOCK = 18, SD_APP_SET_WR_BLK_ERASE_COUNT = 23, SD_APP_SEND_OP_COND = 41, @@ -60,7 +61,8 @@ int sdWriteSector(void); void sdCompleteWrite(void); void sdPrepareRead(void); -void sdReadSector(void); +void sdReadSectorMulti(void); +void sdReadSectorSingle(void); void sdCompleteRead(void); #endif