diff --git a/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.c b/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.c index b05f762..55a9c2f 100644 --- a/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.c +++ b/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.c @@ -39,6 +39,8 @@ // Timeout counter (used when interrupts are not available to ensure // DMA read and writes do not hang the AVR waiting for host response +// Note: This is an unsigned 32 bit integer and should therefore be +// smaller than 4,294,967,295 #define TOC_MAX 100000 // Globals for the interrupt service routines @@ -251,7 +253,8 @@ inline void hostadapterWriteByte(uint8_t databusValue) // Host DMA transfer functions ---------------------------------------------------------- // Host reads data from SCSI device using DMA transfer (reads a 256 byte block) -void hostadapterPerformReadDMA(uint8_t *dataBuffer) +// Returns number of bytes transferred (for debug in case of DMA failure) +uint16_t hostadapterPerformReadDMA(uint8_t *dataBuffer) { uint16_t currentByte = 0; uint32_t timeoutCounter = 0; @@ -259,8 +262,8 @@ void hostadapterPerformReadDMA(uint8_t *dataBuffer) // Loop to write bytes (unless a reset condition is detected) while(currentByte < 256 && timeoutCounter != TOC_MAX) { - // Write the current byte to the databus - PORTA = ~dataBuffer[currentByte]; + // Write the current byte to the databus and point to the next byte + PORTA = ~dataBuffer[currentByte++]; // Set the REQuest signal STATUS_NREQ_PORT &= ~STATUS_NREQ; // REQ = 0 (active) @@ -270,25 +273,24 @@ void hostadapterPerformReadDMA(uint8_t *dataBuffer) while((NACK_PIN & NACK) != 0) { - timeoutCounter++; - if (timeoutCounter == TOC_MAX) + if (++timeoutCounter == TOC_MAX) { // Set the host reset flag and quit nrstFlag = true; - return; + return currentByte - 1; } } // Clear the REQuest signal STATUS_NREQ_PORT |= STATUS_NREQ; // REQ = 1 (inactive) - - // Point to the next byte - currentByte++; } + + return currentByte - 1; } // Host writes data to SCSI device using DMA transfer (writes a 256 byte block) -void hostadapterPerformWriteDMA(uint8_t *dataBuffer) +// Returns number of bytes transferred (for debug in case of DMA failure) +uint16_t hostadapterPerformWriteDMA(uint8_t *dataBuffer) { uint16_t currentByte = 0; uint32_t timeoutCounter = 0; @@ -304,24 +306,22 @@ void hostadapterPerformWriteDMA(uint8_t *dataBuffer) while((NACK_PIN & NACK) != 0) { - timeoutCounter++; - if (timeoutCounter == TOC_MAX) + if (++timeoutCounter == TOC_MAX) { // Set the host reset flag and quit nrstFlag = true; - return; + return currentByte; } } - // Read the current byte from the databus - dataBuffer[currentByte] = ~PINA; + // Read the current byte from the databus and point to the next byte + dataBuffer[currentByte++] = ~PINA; // Clear the REQuest signal STATUS_NREQ_PORT |= STATUS_NREQ; // REQ = 1 (inactive) - - // Point to the next byte - currentByte++; } + + return currentByte - 1; } // Host adapter signal control and detection functions ------------------------------------ diff --git a/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.h b/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.h index 78e51b1..1436390 100644 --- a/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.h +++ b/BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.h @@ -113,8 +113,8 @@ void hostadapterDatabusOutput(void); uint8_t hostadapterReadByte(void); void hostadapterWriteByte(uint8_t databusValue); -void hostadapterPerformReadDMA(uint8_t *dataBuffer); -void hostadapterPerformWriteDMA(uint8_t *dataBuffer); +uint16_t hostadapterPerformReadDMA(uint8_t *dataBuffer); +uint16_t hostadapterPerformWriteDMA(uint8_t *dataBuffer); bool hostadapterConnectedToExternalBus(void); diff --git a/BeebSCSI_AVR/BeebSCSI_AVR/scsi.c b/BeebSCSI_AVR/BeebSCSI_AVR/scsi.c index e5fa2cf..56b083c 100644 --- a/BeebSCSI_AVR/BeebSCSI_AVR/scsi.c +++ b/BeebSCSI_AVR/BeebSCSI_AVR/scsi.c @@ -844,6 +844,8 @@ uint8_t scsiCommandRead6(void) uint32_t numberOfBlocks = 0; uint32_t currentBlock = 0; + uint16_t bytesTransferred = 0; + if (debugFlag_scsiCommands) { debugString_P(PSTR("SCSI Commands: READ command (0x08) received\r\n")); @@ -935,14 +937,14 @@ uint8_t scsiCommandRead6(void) // Send the data to the host cli(); - hostadapterPerformReadDMA(scsiSectorBuffer); + bytesTransferred = hostadapterPerformReadDMA(scsiSectorBuffer); sei(); // Check for a host reset condition if (hostadapterReadResetFlag()) { sei(); - if (debugFlag_scsiCommands) debugString_P(PSTR("SCSI Commands: ReadDMA interrupted by host reset\r\n")); + if (debugFlag_scsiCommands) debugStringInt16_P(PSTR("SCSI Commands: Read DMA interrupted by host reset at byte #"), bytesTransferred, true); // Close the currently open LUN image filesystemCloseLunForRead(); @@ -999,6 +1001,8 @@ uint8_t scsiCommandWrite6(void) uint32_t numberOfBlocks = 0; uint32_t currentBlock = 0; + uint16_t bytesTransferred = 0; + if (debugFlag_scsiCommands) { debugString_P(PSTR("SCSI Commands: WRITE command (0x0A) received\r\n")); @@ -1070,13 +1074,13 @@ uint8_t scsiCommandWrite6(void) { // Get the data from the host cli(); - hostadapterPerformWriteDMA(scsiSectorBuffer); + bytesTransferred = hostadapterPerformWriteDMA(scsiSectorBuffer); sei(); // Check for a host reset condition if (hostadapterReadResetFlag()) { - if (debugFlag_scsiCommands) debugString_P(PSTR("SCSI Commands: ReadDMA interrupted by host reset\r\n")); + if (debugFlag_scsiCommands) debugStringInt16_P(PSTR("SCSI Commands: Write DMA interrupted by host reset at byte #"), bytesTransferred, true); // Close the currently open LUN image filesystemCloseLunForWrite(); @@ -1687,6 +1691,8 @@ uint8_t scsiCommandVerify(void) // of the block. uint8_t scsiWriteFCode(void) { + uint16_t bytesTransferred = 0; + if (debugFlag_scsiCommands) { debugString_P(PSTR("SCSI Commands: WRITE F-Code command (G6 0x0A) received\r\n")); @@ -1718,12 +1724,12 @@ uint8_t scsiWriteFCode(void) // Note: Since VFS is slower than ADFS we do not disable interrupts here as // disabling interrupts can cause incoming serial bytes to be lost if (debugFlag_scsiCommands) debugString_P(PSTR("SCSI Commands: Transferring F-Code buffer from the host...\r\n")); - hostadapterPerformWriteDMA(scsiFcodeBuffer); + bytesTransferred = hostadapterPerformWriteDMA(scsiFcodeBuffer); // Check for a host reset condition if (hostadapterReadResetFlag()) { - if (debugFlag_scsiCommands) debugString_P(PSTR("SCSI Commands: ReadDMA interrupted by host reset\r\n")); + if (debugFlag_scsiCommands) debugStringInt16_P(PSTR("SCSI Commands: Write DMA interrupted by host reset at byte #"), bytesTransferred, true); return SCSI_BUSFREE; } @@ -1750,6 +1756,8 @@ uint8_t scsiWriteFCode(void) // phase is necessary. uint8_t scsiReadFCode(void) { + uint16_t bytesTransferred = 0; + if (debugFlag_scsiCommands) { debugString_P(PSTR("SCSI Commands: READ F-Code command (G6 0x08) received\r\n")); @@ -1784,13 +1792,14 @@ uint8_t scsiReadFCode(void) // Note: Since VFS is slower than ADFS we do not disable interrupts here as // disabling interrupts can cause incoming serial bytes to be lost if (debugFlag_scsiCommands) debugString_P(PSTR("SCSI Commands: Transferring F-Code buffer to the host...\r\n")); - hostadapterPerformReadDMA(scsiFcodeBuffer); + bytesTransferred = hostadapterPerformReadDMA(scsiFcodeBuffer); // Check for a host reset condition if (hostadapterReadResetFlag()) { sei(); - if (debugFlag_scsiCommands) debugString_P(PSTR("SCSI Commands: ReadDMA interrupted by host reset\r\n")); + if (debugFlag_scsiCommands) debugStringInt16_P(PSTR("SCSI Commands: Read DMA interrupted by host reset at byte #"), bytesTransferred, true); + return SCSI_BUSFREE; }