Merge pull request #72 from TC1995/master

SCSI not ready/unit attention handler also made available when a comm…
This commit is contained in:
OBattler
2017-01-03 20:36:08 +01:00
committed by GitHub
2 changed files with 125 additions and 57 deletions

View File

@@ -1414,69 +1414,75 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer,
uint32_t i;
BuslogicLog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]);
pclog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]);
for (i = 1; i < BuslogicRequests->CmdBlock.common.CdbLength; i++)
BuslogicLog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]);
pclog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]);
BuslogicLog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte);
BuslogicLog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength);
BuslogicLog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode);
if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND))
pclog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte);
pclog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength);
pclog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode);
//This not ready/unit attention stuff below is only for the Buslogic!
//The Adaptec one is in scsi_cdrom.c.
if (scsi_model)
{
if (cdrom->medium_changed())
if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND))
{
BuslogicLog("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))
if (cdrom->medium_changed())
{
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
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);
}
/* Next it's time for NOT READY. */
if ((SCSICommandTable[BuslogicRequests->CmdBlock.common.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;
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);
}
/* 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;
}
}
//First, get the data buffer otherwise putting it after the
@@ -1522,8 +1528,8 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer,
BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK));
}
BuslogicLog("Request complete\n");
BuslogicLog("SCSI Status %02X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq);
pclog("Request complete\n");
pclog("SCSI Status %02X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq);
if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES ||

View File

@@ -642,7 +642,7 @@ int cdrom_read_data(uint8_t *buffer)
void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA)
{
if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA || (SCSISense.SenseKey == SENSE_ILLEGAL_REQUEST && SCSISense.Asc == ASC_INV_FIELD_IN_CMD_PACKET))
if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA)
{
pclog("Sense cleared\n");
ScsiPrev=Command;
@@ -698,6 +698,64 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cmdbuffer, uint8_t *cdb)
msf = cdb[1] & 2;
//The not ready/unit attention stuff below is only for the Adaptec!
//The Buslogic one is located in buslogic.c.
if (!scsi_model)
{
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[cdb[0]] & ALLOW_UA))
{
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSICallback[id]=50*SCSI_TIME;
return;
}
}
else if (SCSISense.UnitAttention == 2)
{
if (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 (cdb[0]!=GPCMD_REQUEST_SENSE)
{
SCSIClearSense(cdb[0], 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;
}
}
prev_status = cd_status;
cd_status = cdrom->status();
if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED)))
@@ -773,7 +831,9 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cmdbuffer, uint8_t *cdb)
}
/* Clear the sense stuff as per the spec. */
SCSIClearSense(cdb[0], 0);
ScsiPrev=cdb[0];
if (cdrom->ready())
SCSISenseCodeOk();
return;
case GPCMD_READ_6:
@@ -1529,6 +1589,8 @@ SCSIOut:
SCSIDMAResetPosition(id);
break;
}
}
void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
@@ -1542,7 +1604,7 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
case GPCMD_READ_12:
case GPCMD_READ_CD_MSF:
case GPCMD_READ_CD:
pclog("Total data length requested: %d\n", datalen);
pclog("Total data length requested: %d\n", datalen);
while (datalen > 0)
{
read_length = cdrom_read_data(data); //Fill the buffer the data it needs