From 8fcc49cd315afe94e79708bbcd77373995c6ceed Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Jan 2017 04:38:53 +0100 Subject: [PATCH] Modified ATAPI and SCSI disc change handling. --- src/buslogic.c | 82 ++++++++++++++++++++++++++++----------------- src/cdrom-ioctl.c | 9 ++++- src/ide.c | 26 +++++++++------ src/scsi_cdrom.c | 84 +++++------------------------------------------ 4 files changed, 85 insertions(+), 116 deletions(-) diff --git a/src/buslogic.c b/src/buslogic.c index ab7267247..6b1bdd670 100644 --- a/src/buslogic.c +++ b/src/buslogic.c @@ -1373,43 +1373,65 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, BuslogicSenseBufferAllocate(BuslogicRequests); BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit); + + uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength); - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (!(SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention) + if ((CmdBlock.common.ControlByte != 0x03) && (CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND)) { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[Id]=50*SCSI_TIME; - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - clear the UNIT ATTENTION condition if it's set. */ - if (BuslogicRequests->CmdBlock.common.Cdb[0]!=GPCMD_REQUEST_SENSE) - { - if (SCSISense.UnitAttention) + if (cdrom->medium_changed()) { + pclog("Media changed\n"); + SCSICDROM_Insert(); + } + + if (!cdrom->ready() && SCSISense.UnitAttention) + { + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ SCSISense.UnitAttention = 0; + } + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (SCSISense.UnitAttention == 1) + { + SCSISense.UnitAttention = 2; + if (!(SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & ALLOW_UA)) + { + SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); + SCSIStatus = SCSI_STATUS_CHECK_CONDITION; + SCSICallback[Id]=50*SCSI_TIME; + BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); + return; + } + } + else if (SCSISense.UnitAttention == 2) + { + if (BuslogicRequests->CmdBlock.common.Cdb[0]!=GPCMD_REQUEST_SENSE) + { + SCSISense.UnitAttention = 0; + } + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + clear the UNIT ATTENTION condition if it's set. */ + if (BuslogicRequests->CmdBlock.common.Cdb[0]!=GPCMD_REQUEST_SENSE) + { SCSIClearSense(BuslogicRequests->CmdBlock.common.Cdb[0], 0); - SCSIStatus = SCSI_STATUS_OK; - BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, - MBI_SUCCESS); + } + + /* Next it's time for NOT READY. */ + if ((SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & CHECK_READY) && !cdrom->ready()) + { + BuslogicLog("Not ready\n"); + SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); + SCSIStatus = SCSI_STATUS_CHECK_CONDITION; + SCSICallback[Id]=50*SCSI_TIME; + BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); + return; } } - - /* Next it's time for NOT READY. */ - if ((SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & CHECK_READY) && !cdrom->ready()) - { - BuslogicLog("Not ready\n"); - SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[Id]=50*SCSI_TIME; - BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, - MBI_ERROR); - return; - } - - uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength); uint32_t i; diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 2b33f73d7..51f95e799 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -303,7 +303,14 @@ static int ioctl_medium_changed(void) if (cdrom_drive != old_cdrom_drive) old_cdrom_drive = cdrom_drive; cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); - return 1; + if (cdrom_drive == old_cdrom_drive) + { + return 1; + } + else + { + return 0; + } } else { diff --git a/src/ide.c b/src/ide.c index 48f1edc5c..c9c30fbe7 100644 --- a/src/ide.c +++ b/src/ide.c @@ -1771,7 +1771,7 @@ static void atapi_invalid_field(IDE *ide) static void atapi_illegal_mode(IDE *ide) { SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; + SCSISense.Asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; SCSISense.Ascq = 0; atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_MODE_FOR_THIS_TRACK, 0); } @@ -1779,7 +1779,7 @@ static void atapi_illegal_mode(IDE *ide) static void atapi_incompatible_format(IDE *ide) { SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; + SCSISense.Asc = ASC_INCOMPATIBLE_FORMAT; SCSISense.Ascq = 0; atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_INCOMPATIBLE_FORMAT, 0); } @@ -1787,7 +1787,7 @@ static void atapi_incompatible_format(IDE *ide) static void atapi_data_phase_error(IDE *ide) { SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; + SCSISense.Asc = ASC_DATA_PHASE_ERROR; SCSISense.Ascq = 0; atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0); } @@ -1848,16 +1848,22 @@ static void atapicommand(int ide_board) /* If the UNIT ATTENTION condition is set and the command does not allow execution under it, error out and report the condition. */ - if (!(SCSICommandTable[idebufferb[0]] & ALLOW_UA) && SCSISense.UnitAttention) + if (SCSISense.UnitAttention == 1) { - // pclog("UNIT ATTENTION: Command not allowed to pass through\n"); - atapi_cmd_error(ide, SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - return; + SCSISense.UnitAttention = 2; + if (!(SCSICommandTable[idebufferb[0]] & ALLOW_UA)) + { + // pclog("UNIT ATTENTION: Command not allowed to pass through\n"); + atapi_cmd_error(ide, SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); + return; + } } - - if (idebufferb[0] == GPCMD_READ_TOC_PMA_ATIP) + else if (SCSISense.UnitAttention == 2) { - SCSISense.UnitAttention = 0; + if (idebufferb[0]!=GPCMD_REQUEST_SENSE) + { + SCSISense.UnitAttention = 0; + } } /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* diff --git a/src/scsi_cdrom.c b/src/scsi_cdrom.c index 4c1ea766f..d08f440e0 100644 --- a/src/scsi_cdrom.c +++ b/src/scsi_cdrom.c @@ -34,11 +34,11 @@ uint8_t SCSICommandTable[0x100] = [GPCMD_READ_10] = CHECK_READY, [GPCMD_SEEK_10] = CHECK_READY | NONDATA, [GPCMD_READ_SUBCHANNEL] = CHECK_READY, - [GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY | ALLOW_UA, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS + [GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. */ [GPCMD_READ_HEADER] = CHECK_READY, [GPCMD_PLAY_AUDIO_10] = CHECK_READY, [GPCMD_GET_CONFIGURATION] = ALLOW_UA, @@ -754,48 +754,6 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) int ret = 0; msf = cdb[1] & 2; - - if (cdrom->medium_changed()) - { - pclog("Media changed\n"); - SCSICDROM_Insert(); - } - - if (!cdrom->ready() && SCSISense.UnitAttention) - { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - SCSISense.UnitAttention = 0; - } - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ -#if 0 - if (!(SCSICommandTable[cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention) - { - pclog("UNIT ATTENTION\n"); - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[id]=50*SCSI_TIME; - return; - } -#endif - - if (cdb[0] == GPCMD_READ_TOC_PMA_ATIP) - SCSISense.UnitAttention = 0; - -#if 0 - /* Next it's time for NOT READY. */ - if ((SCSICommandTable[cdb[0]] & CHECK_READY) && !cdrom->ready()) - { - pclog("Not ready\n"); - SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[id]=50*SCSI_TIME; - return; - } -#endif prev_status = cd_status; cd_status = cdrom->status(); @@ -845,7 +803,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) { pclog("Trying to read beyond the end of disc\n"); SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0); SCSICallback[id]=50*SCSI_TIME; break; } @@ -1047,7 +1005,7 @@ SCSIOut: if (cdb[4]!=2 && cdb[4]!=3 && cdb[4]) { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); SCSICallback[id]=50*SCSI_TIME; break; } @@ -1095,7 +1053,7 @@ SCSIOut: if (cdb[3] != 1) { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); SCSICallback[id]=50*SCSI_TIME; break; } @@ -1141,10 +1099,6 @@ SCSIOut: default: SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - if (SCSISense.UnitAttention) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - } SCSICallback[id]=50*SCSI_TIME; return; } @@ -1395,10 +1349,6 @@ SCSIOut: { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - if (SCSISense.UnitAttention) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - } SCSICallback[id]=50*SCSI_TIME; return; } @@ -1414,10 +1364,6 @@ SCSIOut: { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - if (SCSISense.UnitAttention) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - } SCSICallback[id]=50*SCSI_TIME; return; } @@ -1469,10 +1415,6 @@ SCSIOut: { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - if (SCSISense.UnitAttention) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - } SCSICallback[id]=50*SCSI_TIME; return; } @@ -1515,10 +1457,6 @@ SCSIOut: default: SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - if (SCSISense.UnitAttention) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - } SCSICallback[id]=50*SCSI_TIME; return; } @@ -1548,11 +1486,7 @@ SCSIOut: { //pclog("Trying to read beyond the end of disc\n"); SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); - if (SCSISense.UnitAttention) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - } + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0); SCSICallback[id]=50*SCSI_TIME; break; } @@ -1612,7 +1546,7 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen, ui if (!read_length) { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); SCSICallback[id]=50*SCSI_TIME; break; }