Skip to content

Commit

Permalink
Make aligned reads from the SD card for the D8 cmd
Browse files Browse the repository at this point in the history
The code  now fetches data from the SD card aligned on 512 byte
boundaries. This means prefetching and post-fetching from the SD card
so the unaligned 2352 byte CD sector size can properly fit in the
buffer. To be written over the SCSI bus.

The end case where the last CD sector is read hasn't been addressed yet,
so in theory the buffering code could attempt to read past the end
of the SD card.
  • Loading branch information
morio committed Jan 30, 2024
1 parent de540b8 commit e3e864c
Showing 1 changed file with 74 additions and 5 deletions.
79 changes: 74 additions & 5 deletions src/ZuluSCSI_cdrom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "ZuluSCSI_config.h"
#include <CUEParser.h>
#include <assert.h>
#include <minIni.h>
#ifdef ENABLE_AUDIO_OUTPUT
#include "ZuluSCSI_audio.h"
#endif
Expand Down Expand Up @@ -1838,6 +1839,73 @@ static bool doReadCapacity(uint32_t lba, uint8_t pmi)
return true;
}

static void doReadD8(uint32_t lba, uint32_t length, int sector_length, int read_size)
{
image_config_t &img = *(image_config_t*)scsiDev.target->cfg;
uint8_t *buf0 = scsiDev.data;
uint8_t *buf1;// = scsiDev.data + read_length;
// Adjust for plextor d8 offset
if (lba - 2 < 0)
{
logmsg("Error - lba is negative after plextor d8 2 sector adjustment");
}
lba = lba -2;

uint64_t offset = lba * sector_length;


scsiDev.phase = DATA_IN;
scsiDev.dataLen = 0;
scsiDev.dataPtr = 0;
scsiEnterPhase(DATA_IN);
// Format the sectors for transfer
for (uint32_t idx = 0; idx < length; idx++)
{
platform_poll();
diskEjectButtonUpdate(false);

// Where in bytes the sector starts in the image file
uint64_t sector_start = offset + idx * sector_length;
// Where to start reading the image file in bytes, aligned at or before sector start
uint64_t aligned_start = (sector_start / read_size) * read_size;
// The difference between the sector start and aligned start
uint32_t sector_start_offset = (uint32_t)(sector_start - aligned_start);
// Where the sector on the CD ends in bytes
uint64_t sector_end = sector_start + sector_length - 1;
// The number of aligned blocks on the image file to read rounded up
uint32_t number_of_read_sectors = (sector_end - aligned_start + read_size - 1) / read_size;
// How many bytes to read from the image file
uint32_t aligned_read_length = number_of_read_sectors * read_size;
img.file.seek(aligned_start);

// Verify that previous write using this buffer has finished
uint8_t *buf = ((idx & 1) ? buf1 : buf0);
uint8_t *bufstart = buf + sector_start_offset;
uint32_t start = millis();
while (!scsiIsWriteFinished(bufstart + sector_length - 1) && !scsiDev.resetFlag)
{
if ((uint32_t)(millis() - start) > 5000)
{
logmsg("doReadD8() timeout waiting for previous to finish");
scsiDev.resetFlag = 1;
}
platform_poll();
diskEjectButtonUpdate(false);
}
if (scsiDev.resetFlag) break;

// User data
img.file.read(buf, aligned_read_length);

scsiStartWrite(bufstart, sector_length);
}

scsiFinishWrite();

scsiDev.status = 0;
scsiDev.phase = STATUS;
}

/**************************************/
/* CD-ROM command dispatching */
/**************************************/
Expand Down Expand Up @@ -2146,6 +2214,10 @@ extern "C" int scsiCDRomCommand()
const uint32_t CD_C2_SIZE = 294;
const uint32_t CD_SUBCODE_SIZE = 96;
const uint32_t CD_RAW_DATA_SIZE = CD_DATA_SIZE + CD_C2_SIZE + CD_SUBCODE_SIZE;
uint32_t bytes_per_sector = 0;
bytes_per_sector = ini_getl("SCSI","PlextorBytesPerSector", 0, CONFIGFILE);
uint32_t bytes_per_block = ini_getl("SCSI", "PlextorBytesPerBlock", 512 , CONFIGFILE);
if (bytes_per_sector == 0) bytes_per_sector = CD_DATA_SIZE;
uint8_t lun = scsiDev.cdb[1] & 0x7;
uint8_t subcode = scsiDev.cdb[10];
if (lun != 0)
Expand All @@ -2170,11 +2242,8 @@ extern "C" int scsiCDRomCommand()
(((uint32_t) scsiDev.cdb[7]) << 16) +
(((uint32_t) scsiDev.cdb[8]) << 8) +
scsiDev.cdb[9];
uint32_t original_bytes_per_sector = scsiDev.target->liveCfg.bytesPerSector;
scsiDev.target->liveCfg.bytesPerSector = CD_RAW_DATA_SIZE;
dbgmsg("Doing a Plextor 0xD8 CDDA Read, starting: ", (int)lba, " length: ",(int)blocks, " byte-per-sector:", (int) CD_RAW_DATA_SIZE );
scsiDiskStartRead(lba, blocks);
scsiDev.target->liveCfg.bytesPerSector = original_bytes_per_sector;
dbgmsg("Doing a Plextor 0xD8 CDDA Read, starting: ", (int)lba, " length: ",(int)blocks, " byte-per-sector: ", (int) bytes_per_sector, " byte=per=block: ", (int) bytes_per_block );
doReadD8(lba, blocks, bytes_per_sector, bytes_per_block);
}
}
else if (command == 0x4E)
Expand Down

0 comments on commit e3e864c

Please sign in to comment.