diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index abcd415f4..e69d3cc93 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -197,6 +197,7 @@ #define ASC_NONE 0x00 #define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_NOT_READY 0x04 +#define ASC_WRITE_ERROR 0x0c #define ASC_UNRECOVERED_READ_ERROR 0x11 #define ASC_ILLEGAL_OPCODE 0x20 #define ASC_LBA_OUT_OF_RANGE 0x21 diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 792dad31b..10fdf04a6 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -647,6 +647,24 @@ scsi_disk_bus_master_error(scsi_common_t *sc) scsi_disk_cmd_error(dev); } +static void +scsi_disk_write_error(scsi_disk_t *dev) +{ + scsi_disk_sense_key = SENSE_MEDIUM_ERROR; + scsi_disk_asc = ASC_WRITE_ERROR; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); +} + +static void +scsi_disk_read_error(scsi_disk_t *dev) +{ + scsi_disk_sense_key = SENSE_MEDIUM_ERROR; + scsi_disk_asc = ASC_UNRECOVERED_READ_ERROR; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); +} + static void scsi_disk_invalid_lun(scsi_disk_t *dev) { @@ -727,10 +745,17 @@ scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), int ou *len = dev->requested_blocks << 9; for (int i = 0; i < dev->requested_blocks; i++) { - if (out) - hdd_image_write(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)); - else - hdd_image_read(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)); + if (out) { + if (hdd_image_write(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)) < 0) { + scsi_disk_write_error(dev); + return -1; + } + } else { + if (hdd_image_read(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)) < 0) { + scsi_disk_read_error(dev); + return -1; + } + } } scsi_disk_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); @@ -1040,7 +1065,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); if (ret <= 0) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = PHASE_COMPLETE; + dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; dev->callback = 20.0 * SCSI_TIME; scsi_disk_set_callback(dev); scsi_disk_buf_free(dev); @@ -1501,7 +1526,8 @@ scsi_disk_phase_data_out(scsi_common_t *sc) dev->temp_buffer[6] = (s >> 8) & 0xff; dev->temp_buffer[7] = s & 0xff; } - hdd_image_write(dev->id, i, 1, dev->temp_buffer); + if (hdd_image_write(dev->id, i, 1, dev->temp_buffer) < 0) + scsi_disk_write_error(dev); } break; case GPCMD_MODE_SELECT_6: