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; 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) read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len)
{ {
uint8_t *bb = rbuf; uint8_t *bb = rbuf;
const int offset = (!!(mode2 & 0x03)) ? 24 : 16; 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 */ /* Sync bytes */
bb[0] = 0; 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); memset(bb, 0, 280);
else if (!mode2) else if (!mode2)
memset(bb, 0, 288); memset(bb, 0, 288);
return ret;
} }
static void static int
read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b) 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); memcpy(b, raw_buffer, 2352);
cdrom_sector_size = 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) 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)) 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 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; 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; cdrom_sector_size += 288;
b += 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) 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)) 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 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; 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; cdrom_sector_size += 2336;
b += 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) 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)) 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 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; 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; cdrom_sector_size += 280;
b += 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) 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)) 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 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; 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; cdrom_sector_size += 2328;
b += 2328; b += 2328;
} }
return ret;
} }
int int
@@ -1763,6 +1779,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
int m; int m;
int s; int s;
int f; int f;
int ret = 0;
if (dev->cd_status == CD_STATUS_EMPTY) if (dev->cd_status == CD_STATUS_EMPTY)
return 0; return 0;
@@ -1827,21 +1844,21 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
return 0; return 0;
} }
read_audio(dev, lba, temp_b); ret = read_audio(dev, lba, temp_b);
} else if (cdrom_sector_type == 2) { } else if (cdrom_sector_type == 2) {
if (audio || mode2) { if (audio || mode2) {
cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id); cdrom_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id);
return 0; 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) { } else if (cdrom_sector_type == 3) {
if (audio || !mode2 || (mode2 & 0x03)) { if (audio || !mode2 || (mode2 & 0x03)) {
cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id); cdrom_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id);
return 0; 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) { } else if (cdrom_sector_type == 4) {
if (audio || !mode2 || ((mode2 & 0x03) != 1)) { 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); 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; 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) { } else if (cdrom_sector_type == 8) {
if (audio) { if (audio) {
cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id); 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)) 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) 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 { else {
cdrom_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id); 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; return 0;
@@ -1873,16 +1890,16 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
} else { } else {
if (mode2) { if (mode2) {
if ((mode2 & 0x03) == 0x01) 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) 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 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 { } else {
if (audio) if (audio)
read_audio(dev, lba, temp_b); ret = read_audio(dev, lba, temp_b);
else 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; *len = cdrom_sector_size;
return 1; return ret;
} }
/* Peform a master init on the entire module. */ /* 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) { if (fseeko64(tf->fp, seek, SEEK_SET) == -1) {
cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); cdrom_image_backend_log("CDROM: binary_read failed during seek!\n");
return 0; return -1;
} }
if (fread(buffer, count, 1, tf->fp) != 1) { if (fread(buffer, count, 1, tf->fp) != 1) {
cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); cdrom_image_backend_log("CDROM: binary_read failed during read!\n");
return 0; return -1;
} }
if (UNLIKELY(tf->motorola)) { 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) { if (raw && !track_is_raw) {
memset(buffer, 0x00, 2448); memset(buffer, 0x00, 2448);
const int ret = trk->file->read(trk->file, buffer + offset, seek, length); const int ret = trk->file->read(trk->file, buffer + offset, seek, length);
if (!ret) if (ret <= 0)
return 0; return ret;
/* Construct the rest of the raw sector. */ /* Construct the rest of the raw sector. */
memset(buffer + 1, 0xff, 10); memset(buffer + 1, 0xff, 10);
buffer += 12; 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++) { for (uint32_t i = 0; i < num; i++) {
success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i);
if (!success) if (success <= 0)
break; break;
/* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an /* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an
audio track. */ audio track. */

View File

@@ -716,8 +716,11 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
} }
/* Read data. */ /* Read data. */
if (entry->file && (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) != -1)) if (!entry->file || (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) == -1))
return -1;
read = fread(buffer, 1, sector_remain, entry->file); read = fread(buffer, 1, sector_remain, entry->file);
if (sector_remain && !read)
return -1;
} }
/* Fill remainder with 00 bytes if needed. */ /* 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); cdrom_stop(&cdrom);
ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0); ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
if (!ret) if (ret <= 0)
return 0; return 0;
if (dev->mode & 0x40) { if (dev->mode & 0x40) {
dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff); dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff);

View File

@@ -189,6 +189,7 @@
/* SCSI Sense Keys */ /* SCSI Sense Keys */
#define SENSE_NONE 0 #define SENSE_NONE 0
#define SENSE_NOT_READY 2 #define SENSE_NOT_READY 2
#define SENSE_MEDIUM_ERROR 3
#define SENSE_ILLEGAL_REQUEST 5 #define SENSE_ILLEGAL_REQUEST 5
#define SENSE_UNIT_ATTENTION 6 #define SENSE_UNIT_ATTENTION 6
@@ -196,6 +197,7 @@
#define ASC_NONE 0x00 #define ASC_NONE 0x00
#define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_AUDIO_PLAY_OPERATION 0x00
#define ASC_NOT_READY 0x04 #define ASC_NOT_READY 0x04
#define ASC_UNRECOVERED_READ_ERROR 0x11
#define ASC_ILLEGAL_OPCODE 0x20 #define ASC_ILLEGAL_OPCODE 0x20
#define ASC_LBA_OUT_OF_RANGE 0x21 #define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24
@@ -212,6 +214,7 @@
#define ASCQ_NONE 0x00 #define ASCQ_NONE 0x00
#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 #define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01
#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 #define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define ASCQ_CIRC_UNRECOVERED_ERROR 0x06
#define ASCQ_CAPACITY_DATA_CHANGED 0x09 #define ASCQ_CAPACITY_DATA_CHANGED 0x09
#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 #define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11
#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 #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(); plat_cdrom_close();
dummy_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size); dummy_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size);
return 0; return -1;
} }
void void

View File

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

View File

@@ -1244,6 +1244,15 @@ scsi_cdrom_not_ready(scsi_cdrom_t *dev)
scsi_cdrom_cmd_error(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 static void
scsi_cdrom_invalid_lun(scsi_cdrom_t *dev) 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) { if (!ret) {
scsi_cdrom_illegal_mode(dev); scsi_cdrom_illegal_mode(dev);
return 0; return 0;
} else if (ret < 0) {
pclog("we have a circ\n");
scsi_cdrom_circ_error(dev);
return -1;
} }
} }