mirror of
https://github.com/fhgwright/SCSI2SD.git
synced 2025-01-03 12:31:26 +00:00
Fix errors reading the last sector of SD card.
This commit is contained in:
parent
0629f76919
commit
09782fcdc5
@ -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()
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user