For packet devices we want to actually return a check condition when the device

indicates an error. Also we then need to pass through the request sense command
to the device. This should fix media status reporting for ATAPI.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30253 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2009-04-18 22:37:04 +00:00
parent 20dbdc7914
commit 6a2bc1027b
3 changed files with 37 additions and 22 deletions

View File

@ -215,7 +215,7 @@ ATAChannel::ExecuteIO(scsi_ccb *ccb)
if (result != B_OK)
return result;
if (ccb->cdb[0] == SCSI_OP_REQUEST_SENSE) {
if (ccb->cdb[0] == SCSI_OP_REQUEST_SENSE && fRequest->HasSense()) {
TRACE("request sense\n");
fRequest->RequestSense();
fRequest->Finish(false);

View File

@ -95,13 +95,8 @@ ATAPIDevice::SendPacket(ATARequest *request)
return B_ERROR;
}
if (!request->HasData()) {
result = fChannel->FinishRequest(request, ATA_WAIT_FINISH
| ATA_CHECK_DEVICE_FAULT, ATA_ERROR_ALL);
if (result != B_OK)
TRACE_ERROR("device indicates error after non-data command\n");
return result;
}
if (!request->HasData())
return _FinishRequest(request, ATA_WAIT_FINISH);
if (request->UseDMA()) {
fChannel->PrepareWaitingForInterrupt();
@ -114,8 +109,7 @@ ATAPIDevice::SendPacket(ATARequest *request)
return B_TIMED_OUT;
}
result = fChannel->FinishRequest(request, ATA_CHECK_DEVICE_FAULT,
ATA_ERROR_ALL);
result = _FinishRequest(request, ATA_WAIT_FINISH);
if (result != B_OK) {
TRACE_ERROR("device indicates transfer error after dma\n");
return result;
@ -148,8 +142,7 @@ ATAPIDevice::SendPacket(ATARequest *request)
request->SetStatus(SCSI_CMD_TIMEOUT);
return B_TIMED_OUT;
} else
return fChannel->FinishRequest(request, ATA_WAIT_FINISH
| ATA_CHECK_DEVICE_FAULT, ATA_ERROR_ALL);
return _FinishRequest(request, 0);
}
// PIO data transfer
@ -170,10 +163,14 @@ ATAPIDevice::SendPacket(ATARequest *request)
request->SetBytesLeft(length);
fChannel->ExecutePIOTransfer(request);
if (fChannel->Wait(0, ATA_STATUS_BUSY, 0, request->Timeout()) != B_OK) {
TRACE_ERROR("timeout waiting for device to finish transfer\n");
request->SetStatus(SCSI_CMD_TIMEOUT);
return B_TIMED_OUT;
result = fChannel->Wait(0, ATA_STATUS_BUSY, 0, request->Timeout());
if (result != B_OK) {
if (result == B_TIMED_OUT) {
TRACE_ERROR("timeout waiting for device to finish transfer\n");
request->SetStatus(SCSI_CMD_TIMEOUT);
return B_TIMED_OUT;
} else
return _FinishRequest(request, 0);
}
if ((fChannel->AltStatus() & ATA_STATUS_DATA_REQUEST) == 0) {
@ -183,12 +180,7 @@ ATAPIDevice::SendPacket(ATARequest *request)
}
}
result = fChannel->FinishRequest(request, ATA_WAIT_FINISH
| ATA_CHECK_DEVICE_FAULT, ATA_ERROR_ALL);
if (result != B_OK)
TRACE_ERROR("device indicates transfer error after pio\n");
return result;
return _FinishRequest(request, ATA_WAIT_FINISH);
}
@ -242,3 +234,23 @@ ATAPIDevice::_FillTaskFilePacket(ATARequest *request)
fTaskFile.packet.command = ATA_COMMAND_PACKET;
return B_OK;
}
status_t
ATAPIDevice::_FinishRequest(ATARequest *request, uint32 flags)
{
if (fChannel->FinishRequest(request, flags
| ATA_CHECK_DEVICE_FAULT, 0) != B_OK) {
// when we get an error from a packet device, we instruct the
// scsi layer to do a request sense. but since we don't want to
// return an emulated sense coming from ata, we clear our sense
// key first so that the next request sense will go to the packet
// device directly (as a packet command).
request->ClearSense();
request->SetStatus(SCSI_REQ_CMP_ERR);
request->CCB()->device_status = SCSI_STATUS_CHECK_CONDITION;
return B_ERROR;
}
return B_OK;
}

View File

@ -235,6 +235,8 @@ virtual status_t Configure();
private:
status_t _FillTaskFilePacket(ATARequest *request);
status_t _FinishRequest(ATARequest *request,
uint32 flags);
uint8 fPacket[12];
};
@ -270,6 +272,7 @@ public:
size_t * BytesLeft() { return &fBytesLeft; };
bool HasData() { return fCCB->data_length > 0; };
bool HasSense() { return fSenseKey != 0; };
status_t Finish(bool resubmit);