* Call PostReset() at the end of ResetPort() as it's always used in that way.
* Reset the port directly after executing a command failed instead of letting the next call do the reset first. This is arbitrary but looks cleaner to me. * Provide a way to check if a given sata_request is a SCSI_OP_TEST_UNIT_READY over ATAPI and use this info to calm down all error output. This avoids spamming the syslog with error output on each media status poll when no disk is present in a ATAPI device. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31014 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
46d4d11ff6
commit
1d4c4d3a5b
|
@ -43,6 +43,7 @@ AHCIPort::AHCIPort(AHCIController *controller, int index)
|
|||
fSectorSize(0),
|
||||
fSectorCount(0),
|
||||
fIsATAPI(false),
|
||||
fTestUnitReadyActive(false),
|
||||
fResetPort(false),
|
||||
fError(false)
|
||||
{
|
||||
|
@ -140,7 +141,6 @@ AHCIPort::Init2()
|
|||
FlushPostedWrites();
|
||||
|
||||
ResetPort(true);
|
||||
PostReset();
|
||||
|
||||
TRACE("ie 0x%08lx\n", fRegs->ie);
|
||||
TRACE("is 0x%08lx\n", fRegs->is);
|
||||
|
@ -233,7 +233,8 @@ AHCIPort::ResetDevice()
|
|||
status_t
|
||||
AHCIPort::ResetPort(bool forceDeviceReset)
|
||||
{
|
||||
TRACE("AHCIPort::ResetPort port %d\n", fIndex);
|
||||
if (!fTestUnitReadyActive)
|
||||
TRACE("AHCIPort::ResetPort port %d\n", fIndex);
|
||||
|
||||
// stop DMA engine
|
||||
fRegs->cmd &= ~PORT_CMD_ST;
|
||||
|
@ -246,8 +247,10 @@ AHCIPort::ResetPort(bool forceDeviceReset)
|
|||
|
||||
bool deviceBusy = fRegs->tfd & (ATA_BSY | ATA_DRQ);
|
||||
|
||||
TRACE("AHCIPort::ResetPort port %d, deviceBusy %d, forceDeviceReset %d\n",
|
||||
fIndex, deviceBusy, forceDeviceReset);
|
||||
if (!fTestUnitReadyActive) {
|
||||
TRACE("AHCIPort::ResetPort port %d, deviceBusy %d, "
|
||||
"forceDeviceReset %d\n", fIndex, deviceBusy, forceDeviceReset);
|
||||
}
|
||||
|
||||
if (deviceBusy || forceDeviceReset)
|
||||
ResetDevice();
|
||||
|
@ -256,14 +259,15 @@ AHCIPort::ResetPort(bool forceDeviceReset)
|
|||
fRegs->cmd |= PORT_CMD_ST;
|
||||
FlushPostedWrites();
|
||||
|
||||
return B_OK;
|
||||
return PostReset();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AHCIPort::PostReset()
|
||||
{
|
||||
TRACE("AHCIPort::PostReset port %d\n", fIndex);
|
||||
if (!fTestUnitReadyActive)
|
||||
TRACE("AHCIPort::PostReset port %d\n", fIndex);
|
||||
|
||||
if ((fRegs->ssts & 0xf) != 0x3 || (fRegs->tfd & 0xff) == 0x7f) {
|
||||
TRACE("AHCIPort::PostReset port %d: no device\n", fIndex);
|
||||
|
@ -289,9 +293,11 @@ AHCIPort::PostReset()
|
|||
fRegs->cmd &= ~PORT_CMD_ATAPI;
|
||||
FlushPostedWrites();
|
||||
|
||||
TRACE("device signature 0x%08lx (%s)\n", fRegs->sig,
|
||||
(fRegs->sig == 0xeb140101) ? "ATAPI" : (fRegs->sig == 0x00000101) ?
|
||||
"ATA" : "unknown");
|
||||
if (!fTestUnitReadyActive) {
|
||||
TRACE("device signature 0x%08lx (%s)\n", fRegs->sig,
|
||||
(fRegs->sig == 0xeb140101) ? "ATAPI" : (fRegs->sig == 0x00000101) ?
|
||||
"ATA" : "unknown");
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -345,20 +351,25 @@ AHCIPort::InterruptErrorHandler(uint32 is)
|
|||
{
|
||||
uint32 ci = fRegs->ci;
|
||||
|
||||
TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08lx, "
|
||||
"is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci);
|
||||
if (!fTestUnitReadyActive) {
|
||||
TRACE("AHCIPort::InterruptErrorHandler port %d, "
|
||||
"fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex,
|
||||
fCommandsActive, is, ci);
|
||||
|
||||
TRACE("ssts 0x%08lx\n", fRegs->ssts);
|
||||
TRACE("sctl 0x%08lx\n", fRegs->sctl);
|
||||
TRACE("serr 0x%08lx\n", fRegs->serr);
|
||||
TRACE("sact 0x%08lx\n", fRegs->sact);
|
||||
TRACE("ssts 0x%08lx\n", fRegs->ssts);
|
||||
TRACE("sctl 0x%08lx\n", fRegs->sctl);
|
||||
TRACE("serr 0x%08lx\n", fRegs->serr);
|
||||
TRACE("sact 0x%08lx\n", fRegs->sact);
|
||||
}
|
||||
|
||||
// read and clear SError
|
||||
uint32 serr = fRegs->serr;
|
||||
fRegs->serr = serr;
|
||||
|
||||
if (is & PORT_INT_TFE) {
|
||||
TRACE("Task File Error\n");
|
||||
if (!fTestUnitReadyActive)
|
||||
TRACE("Task File Error\n");
|
||||
|
||||
fResetPort = true;
|
||||
fError = true;
|
||||
}
|
||||
|
@ -740,6 +751,7 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
|||
fCommandList->cfl = 5; // 20 bytes, length in DWORDS
|
||||
memcpy((char *)fCommandTable->cfis, request->fis(), 20);
|
||||
|
||||
fTestUnitReadyActive = request->is_test_unit_ready();
|
||||
if (request->is_atapi()) {
|
||||
// ATAPI PACKET is a 12 or 16 byte SCSI command
|
||||
memset((char *)fCommandTable->acmd, 0, 32);
|
||||
|
@ -755,7 +767,7 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
|||
|
||||
if (wait_until_clear(&fRegs->tfd, ATA_BSY | ATA_DRQ, 1000000) < B_OK) {
|
||||
TRACE("ExecuteAtaRequest port %d: device is busy\n", fIndex);
|
||||
fResetPort = true;
|
||||
ResetPort();
|
||||
FinishTransfer();
|
||||
request->abort();
|
||||
return;
|
||||
|
@ -763,9 +775,9 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
|||
|
||||
cpu_status cpu = disable_interrupts();
|
||||
acquire_spinlock(&fSpinlock);
|
||||
fCommandsActive |= 1;
|
||||
fRegs->ci = 1;
|
||||
FlushPostedWrites();
|
||||
fCommandsActive |= 1;
|
||||
release_spinlock(&fSpinlock);
|
||||
restore_interrupts(cpu);
|
||||
|
||||
|
@ -790,13 +802,17 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
|||
TRACE("tfd 0x%08lx\n", fRegs->tfd);
|
||||
*/
|
||||
|
||||
if (fResetPort || status == B_TIMED_OUT) {
|
||||
fResetPort = false;
|
||||
ResetPort();
|
||||
}
|
||||
|
||||
size_t bytesTransfered = fCommandList->prdbc;
|
||||
|
||||
FinishTransfer();
|
||||
|
||||
if (status == B_TIMED_OUT) {
|
||||
TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex);
|
||||
fResetPort = true;
|
||||
request->abort();
|
||||
} else {
|
||||
request->finish(tfd, bytesTransfered);
|
||||
|
@ -807,12 +823,6 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
|||
void
|
||||
AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
|
||||
{
|
||||
if (fResetPort) {
|
||||
fResetPort = false;
|
||||
ResetPort();
|
||||
PostReset();
|
||||
}
|
||||
|
||||
// TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
|
||||
|
||||
if (fIsATAPI && request->cdb[0] != SCSI_OP_INQUIRY) {
|
||||
|
|
|
@ -67,6 +67,7 @@ private:
|
|||
uint32 fSectorSize;
|
||||
uint64 fSectorCount;
|
||||
bool fIsATAPI;
|
||||
bool fTestUnitReadyActive;
|
||||
bool fResetPort;
|
||||
bool fError;
|
||||
|
||||
|
|
|
@ -105,8 +105,13 @@ sata_request::finish(int tfd, size_t bytesTransfered)
|
|||
if (tfd & (ATA_ERR | ATA_DF)) {
|
||||
uint8 status = tfd & 0xff;
|
||||
uint8 error = (tfd >> 8) & 0xff;
|
||||
dprintf("ahci: sata_request::finish ATA command 0x%02x failed\n", fFis[2]);
|
||||
dprintf("ahci: sata_request::finish status 0x%02x, error 0x%02x\n", status, error);
|
||||
|
||||
if (!is_test_unit_ready()) {
|
||||
dprintf("ahci: sata_request::finish ATA command 0x%02x failed\n",
|
||||
fFis[2]);
|
||||
dprintf("ahci: sata_request::finish status 0x%02x, error 0x%02x\n",
|
||||
status, error);
|
||||
}
|
||||
}
|
||||
|
||||
if (fCcb) {
|
||||
|
@ -116,13 +121,16 @@ sata_request::finish(int tfd, size_t bytesTransfered)
|
|||
if (tfd & (ATA_ERR | ATA_DF)) {
|
||||
fCcb->subsys_status = SCSI_REQ_CMP_ERR;
|
||||
if (fIsATAPI) {
|
||||
dprintf("ahci: sata_request::finish ATAPI packet %02x %02x %02x %02x "
|
||||
if (!is_test_unit_ready()) {
|
||||
dprintf("ahci: sata_request::finish ATAPI packet %02x %02x %02x %02x "
|
||||
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x (len %d)\n",
|
||||
fCcb->cdb[0], fCcb->cdb[1], fCcb->cdb[2], fCcb->cdb[3],
|
||||
fCcb->cdb[4], fCcb->cdb[5], fCcb->cdb[6], fCcb->cdb[7],
|
||||
fCcb->cdb[8], fCcb->cdb[9], fCcb->cdb[10], fCcb->cdb[11],
|
||||
fCcb->cdb[12], fCcb->cdb[13], fCcb->cdb[14], fCcb->cdb[15],
|
||||
fCcb->cdb_length);
|
||||
}
|
||||
|
||||
fCcb->device_status = SCSI_STATUS_CHECK_CONDITION;
|
||||
} else {
|
||||
// TODO ATA error handling goes here
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define _SATA_REQUEST_H
|
||||
|
||||
#include "ahci_defs.h"
|
||||
#include "scsi_cmds.h"
|
||||
|
||||
class sata_request
|
||||
{
|
||||
|
@ -22,6 +23,7 @@ public:
|
|||
|
||||
void set_atapi_cmd(size_t transferLength);
|
||||
bool is_atapi();
|
||||
bool is_test_unit_ready();
|
||||
|
||||
scsi_ccb * ccb();
|
||||
const void * fis();
|
||||
|
@ -65,6 +67,13 @@ sata_request::is_atapi()
|
|||
}
|
||||
|
||||
|
||||
inline bool
|
||||
sata_request::is_test_unit_ready()
|
||||
{
|
||||
return fIsATAPI && fCcb != NULL && fCcb->cdb[0] == SCSI_OP_TEST_UNIT_READY;
|
||||
}
|
||||
|
||||
|
||||
inline void *
|
||||
sata_request::data()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue