CD-ROM: Report image backend I/O errors as media CRC errors to the drive

This commit is contained in:
RichardG867
2024-10-27 13:17:55 -03:00
parent 31beadd103
commit aeaaa09b16
8 changed files with 75 additions and 39 deletions

View File

@@ -1520,13 +1520,13 @@ track_type_is_valid(UNUSED(uint8_t id), int type, int flags, int audio, int mode
return 1;
}
static void
static int
read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len)
{
uint8_t *bb = rbuf;
const int offset = (!!(mode2 & 0x03)) ? 24 : 16;
dev->ops->read_sector(dev, CD_READ_DATA, rbuf + offset, lba);
int ret = dev->ops->read_sector(dev, CD_READ_DATA, rbuf + offset, lba);
/* Sync bytes */
bb[0] = 0;
@@ -1546,25 +1546,30 @@ read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, i
memset(bb, 0, 280);
else if (!mode2)
memset(bb, 0, 288);
return ret;
}
static void
static int
read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b)
{
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
int ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
memcpy(b, raw_buffer, 2352);
cdrom_sector_size = 2352;
return ret;
}
static void
static int
read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
{
int ret;
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048))
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048);
ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048);
else
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
cdrom_sector_size = 0;
@@ -1610,15 +1615,18 @@ read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int
cdrom_sector_size += 288;
b += 288;
}
return ret;
}
static void
static int
read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
{
int ret;
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2336))
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336);
ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336);
else
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
cdrom_sector_size = 0;
@@ -1654,15 +1662,18 @@ read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t m
cdrom_sector_size += 2336;
b += 2336;
}
return ret;
}
static void
static int
read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
{
int ret;
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2048))
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048);
ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048);
else
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
cdrom_sector_size = 0;
@@ -1705,15 +1716,18 @@ read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t
cdrom_sector_size += 280;
b += 280;
}
return ret;
}
static void
static int
read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b)
{
int ret;
if ((dev->cd_status == CD_STATUS_DATA_ONLY) || (dev->ops->sector_size(dev, lba) == 2324))
read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324);
ret = read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324);
else
dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
ret = dev->ops->read_sector(dev, CD_READ_RAW, raw_buffer, lba);
cdrom_sector_size = 0;
@@ -1748,6 +1762,8 @@ read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t
cdrom_sector_size += 2328;
b += 2328;
}
return ret;
}
int
@@ -1763,6 +1779,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
int m;
int s;
int f;
int ret = 0;
if (dev->cd_status == CD_STATUS_EMPTY)
return 0;
@@ -1827,21 +1844,21 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
return 0;
}
read_audio(dev, lba, temp_b);
ret = read_audio(dev, lba, temp_b);
} else if (cdrom_sector_type == 2) {
if (audio || mode2) {
cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id);
return 0;
}
read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
} else if (cdrom_sector_type == 3) {
if (audio || !mode2 || (mode2 & 0x03)) {
cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id);
return 0;
}
read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
} else if (cdrom_sector_type == 4) {
if (audio || !mode2 || ((mode2 & 0x03) != 1)) {
cdrom_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id);
@@ -1855,7 +1872,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
return 0;
}
read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
} else if (cdrom_sector_type == 8) {
if (audio) {
cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id);
@@ -1863,9 +1880,9 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
}
if (mode2 && ((mode2 & 0x03) == 1))
read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
else if (!mode2)
read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
else {
cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id);
return 0;
@@ -1873,16 +1890,16 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
} else {
if (mode2) {
if ((mode2 & 0x03) == 0x01)
read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
else if ((mode2 & 0x03) == 0x02)
read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
else
read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
} else {
if (audio)
read_audio(dev, lba, temp_b);
ret = read_audio(dev, lba, temp_b);
else
read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
ret = read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b);
}
}
@@ -1914,7 +1931,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
*len = cdrom_sector_size;
return 1;
return ret;
}
/* Peform a master init on the entire module. */

View File

@@ -181,13 +181,13 @@ bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
if (fseeko64(tf->fp, seek, SEEK_SET) == -1) {
cdrom_image_backend_log("CDROM: binary_read failed during seek!\n");
return 0;
return -1;
}
if (fread(buffer, count, 1, tf->fp) != 1) {
cdrom_image_backend_log("CDROM: binary_read failed during read!\n");
return 0;
return -1;
}
if (UNLIKELY(tf->motorola)) {
@@ -502,8 +502,8 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
if (raw && !track_is_raw) {
memset(buffer, 0x00, 2448);
const int ret = trk->file->read(trk->file, buffer + offset, seek, length);
if (!ret)
return 0;
if (ret <= 0)
return ret;
/* Construct the rest of the raw sector. */
memset(buffer + 1, 0xff, 10);
buffer += 12;
@@ -534,7 +534,7 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3
for (uint32_t i = 0; i < num; i++) {
success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i);
if (!success)
if (success <= 0)
break;
/* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an
audio track. */

View File

@@ -716,8 +716,11 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
}
/* Read data. */
if (entry->file && (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) != -1))
read = fread(buffer, 1, sector_remain, entry->file);
if (!entry->file || (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) == -1))
return -1;
read = fread(buffer, 1, sector_remain, entry->file);
if (sector_remain && !read)
return -1;
}
/* Fill remainder with 00 bytes if needed. */

View File

@@ -197,7 +197,7 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first)
}
cdrom_stop(&cdrom);
ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
if (!ret)
if (ret <= 0)
return 0;
if (dev->mode & 0x40) {
dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff);

View File

@@ -189,6 +189,7 @@
/* SCSI Sense Keys */
#define SENSE_NONE 0
#define SENSE_NOT_READY 2
#define SENSE_MEDIUM_ERROR 3
#define SENSE_ILLEGAL_REQUEST 5
#define SENSE_UNIT_ATTENTION 6
@@ -196,6 +197,7 @@
#define ASC_NONE 0x00
#define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_NOT_READY 0x04
#define ASC_UNRECOVERED_READ_ERROR 0x11
#define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
@@ -212,6 +214,7 @@
#define ASCQ_NONE 0x00
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define ASCQ_CIRC_UNRECOVERED_ERROR 0x06
#define ASCQ_CAPACITY_DATA_CHANGED 0x09
#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11
#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12

View File

@@ -207,7 +207,7 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector)
plat_cdrom_close();
dummy_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size);
return 0;
return -1;
}
void

View File

@@ -342,7 +342,7 @@ plat_cdrom_get_sector_size(UNUSED(uint32_t sector))
int
plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector)
{
BOOL status;
int status;
long size = 0;
int buflen = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
@@ -370,7 +370,7 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector)
plat_cdrom_close();
win_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size);
return (size == buflen) && (status > 0);
return (status > 0) ? (size == buflen) : -1;
}
void

View File

@@ -1244,6 +1244,15 @@ scsi_cdrom_not_ready(scsi_cdrom_t *dev)
scsi_cdrom_cmd_error(dev);
}
static void
scsi_cdrom_circ_error(scsi_cdrom_t *dev)
{
scsi_cdrom_sense_key = SENSE_MEDIUM_ERROR;
scsi_cdrom_asc = ASC_UNRECOVERED_READ_ERROR;
scsi_cdrom_ascq = ASCQ_CIRC_UNRECOVERED_ERROR;
scsi_cdrom_cmd_error(dev);
}
static void
scsi_cdrom_invalid_lun(scsi_cdrom_t *dev)
{
@@ -1367,6 +1376,10 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *l
if (!ret) {
scsi_cdrom_illegal_mode(dev);
return 0;
} else if (ret < 0) {
pclog("we have a circ\n");
scsi_cdrom_circ_error(dev);
return -1;
}
}