Moved some SCSI CD-ROM errors to the command byte/CDB decoder;

SCSI CD-ROM now correctly sets status phase on error;
SCSI CD-ROM now correctly errors on bad command.
This commit is contained in:
OBattler
2016-12-26 03:21:43 +01:00
parent f01c61b813
commit e7934a1229
2 changed files with 45 additions and 40 deletions

View File

@@ -2923,7 +2923,7 @@ atapi_out:
atapi_command_ready(ide_board, len); atapi_command_ready(ide_board, len);
break; break;
case GPCMD_SEND_DVD_STRUCTURE: // case GPCMD_SEND_DVD_STRUCTURE:
default: default:
ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/
ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;

View File

@@ -57,7 +57,7 @@ uint8_t SCSICommandTable[0x100] =
[GPCMD_PLAY_CD] = CHECK_READY, [GPCMD_PLAY_CD] = CHECK_READY,
[GPCMD_MECHANISM_STATUS] = 0, [GPCMD_MECHANISM_STATUS] = 0,
[GPCMD_READ_CD] = CHECK_READY | READDATA, [GPCMD_READ_CD] = CHECK_READY | READDATA,
[GPCMD_SEND_DVD_STRUCTURE] = CHECK_READY [GPCMD_SEND_DVD_STRUCTURE] = CHECK_READY
}; };
uint8_t mode_sense_pages[0x40] = uint8_t mode_sense_pages[0x40] =
@@ -98,6 +98,8 @@ void SCSISenseCodeError(uint8_t SenseKey, uint8_t Asc, uint8_t Ascq)
SCSISense.SenseKey=SenseKey; SCSISense.SenseKey=SenseKey;
SCSISense.Asc=Asc; SCSISense.Asc=Asc;
SCSISense.Ascq=Ascq; SCSISense.Ascq=Ascq;
SCSIPhase = SCSI_PHASE_STATUS; /* This *HAS* to be done, SCSIPhase is the same thing that ATAPI returns in IDE sector count, so after any error,
status phase (3) is correct. */
} }
static void static void
@@ -780,10 +782,6 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
pclog("Trying to read beyond the end of disc\n"); pclog("Trying to read beyond the end of disc\n");
SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
if (SCSISense.UnitAttention)
{
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
}
SCSICallback[id]=50*SCSI_TIME; SCSICallback[id]=50*SCSI_TIME;
break; break;
} }
@@ -808,6 +806,24 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
return; return;
case GPCMD_INQUIRY: case GPCMD_INQUIRY:
if (cdb[2] == 0x83)
{
if (SCSIDevices[id].CmdBufferLength < 28)
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
}
}
if ((cdb[2] != 0x00) && (cdb[2] != 0x83))
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
}
SCSIPhase = SCSI_PHASE_DATAIN; SCSIPhase = SCSI_PHASE_DATAIN;
SCSIStatus = SCSI_STATUS_OK; SCSIStatus = SCSI_STATUS_OK;
SCSICallback[id]=60*SCSI_TIME; SCSICallback[id]=60*SCSI_TIME;
@@ -835,6 +851,14 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10: case GPCMD_MODE_SENSE_10:
if (!(mode_sense_pages[cdb[2] & 0x3f] & IMPLEMENTED))
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
}
SCSIPhase = SCSI_PHASE_DATAIN; SCSIPhase = SCSI_PHASE_DATAIN;
SCSIStatus = SCSI_STATUS_OK; SCSIStatus = SCSI_STATUS_OK;
SCSICallback[id]=60*SCSI_TIME; SCSICallback[id]=60*SCSI_TIME;
@@ -899,6 +923,14 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
break; break;
case GPCMD_READ_SUBCHANNEL: case GPCMD_READ_SUBCHANNEL:
if (cdb[3] != 1)
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
}
SCSIPhase = SCSI_PHASE_DATAIN; SCSIPhase = SCSI_PHASE_DATAIN;
SCSIStatus = SCSI_STATUS_OK; SCSIStatus = SCSI_STATUS_OK;
SCSICallback[id]=1000*SCSI_TIME; SCSICallback[id]=1000*SCSI_TIME;
@@ -1142,6 +1174,13 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
SCSIDMAResetPosition(id); SCSIDMAResetPosition(id);
break; break;
// case GPCMD_SEND_DVD_STRUCTURE:
default:
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
SCSICallback[id]=50*SCSI_TIME;
break;
} }
} }
@@ -1267,13 +1306,6 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
break; break;
case 0x83: case 0x83:
if (Idx + 24 > SCSIDevices[id].CmdBufferLength)
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
}
SCSIDevices[id].CmdBuffer[Idx++] = 0x02; SCSIDevices[id].CmdBuffer[Idx++] = 0x02;
SCSIDevices[id].CmdBuffer[Idx++] = 0x00; SCSIDevices[id].CmdBuffer[Idx++] = 0x00;
SCSIDevices[id].CmdBuffer[Idx++] = 0x00; SCSIDevices[id].CmdBuffer[Idx++] = 0x00;
@@ -1296,12 +1328,6 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
ScsiPadStr8(SCSIDevices[id].CmdBuffer + Idx, 20, "53R141"); /* Product */ ScsiPadStr8(SCSIDevices[id].CmdBuffer + Idx, 20, "53R141"); /* Product */
Idx += 20; Idx += 20;
break; break;
default:
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
} }
} }
else else
@@ -1330,18 +1356,8 @@ SCSIOut:
case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10: case GPCMD_MODE_SENSE_10:
Temp = cdb[2] & 0x3f;
memset(SCSIDevices[id].CmdBuffer, 0, datalen); memset(SCSIDevices[id].CmdBuffer, 0, datalen);
if (!(mode_sense_pages[Temp] & IMPLEMENTED))
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
SCSICallback[id]=50*SCSI_TIME;
return;
}
if (cdb[0] == GPCMD_MODE_SENSE_6) if (cdb[0] == GPCMD_MODE_SENSE_6)
{ {
datalen = SCSICDROMModeSense(SCSIDevices[id].CmdBuffer, 4, Temp); datalen = SCSICDROMModeSense(SCSIDevices[id].CmdBuffer, 4, Temp);
@@ -1376,17 +1392,6 @@ SCSIOut:
break; break;
case GPCMD_READ_SUBCHANNEL: case GPCMD_READ_SUBCHANNEL:
if (cdb[3] != 1)
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00);
if (SCSISense.UnitAttention)
{
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
}
SCSICallback[id]=50*SCSI_TIME;
break;
}
SectorLBA = 0; SectorLBA = 0;
SCSIDevices[id].CmdBuffer[SectorLBA++] = 0; SCSIDevices[id].CmdBuffer[SectorLBA++] = 0;
SCSIDevices[id].CmdBuffer[SectorLBA++] = 0; /*Audio status*/ SCSIDevices[id].CmdBuffer[SectorLBA++] = 0; /*Audio status*/