Skip to content

Commit

Permalink
Enhancements to DMA transfer debug
Browse files Browse the repository at this point in the history
Some minor enhancements to the debug output around the DMA transfer.
The debug now reports how many bytes were received before DMA transfer
failure.  The DMA read and write routines have also been changed
slightly to increase execution speed.
  • Loading branch information
Simon Inns committed Jan 22, 2017
1 parent 56b7d2c commit 98bb544
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 28 deletions.
36 changes: 18 additions & 18 deletions BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.c
Expand Up @@ -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
Expand Down Expand Up @@ -251,16 +253,17 @@ 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;

// 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)
Expand All @@ -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;
Expand All @@ -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 ------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions BeebSCSI_AVR/BeebSCSI_AVR/hostadapter.h
Expand Up @@ -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);

Expand Down
25 changes: 17 additions & 8 deletions BeebSCSI_AVR/BeebSCSI_AVR/scsi.c
Expand Up @@ -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"));
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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"));
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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"));
Expand Down Expand Up @@ -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;
}

Expand All @@ -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"));
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 98bb544

Please sign in to comment.