From 1d4c4d3a5bb167a4df0202a1c1d9e44abd4c156d Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 12 Jun 2009 16:31:14 +0000 Subject: [PATCH] * 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 --- .../kernel/busses/scsi/ahci/ahci_port.cpp | 60 +++++++++++-------- .../kernel/busses/scsi/ahci/ahci_port.h | 1 + .../kernel/busses/scsi/ahci/sata_request.cpp | 14 ++++- .../kernel/busses/scsi/ahci/sata_request.h | 9 +++ 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index 753fcd9d3f..ef468734d6 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -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) { diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h index 90eeb8b324..97814584e7 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -67,6 +67,7 @@ private: uint32 fSectorSize; uint64 fSectorCount; bool fIsATAPI; + bool fTestUnitReadyActive; bool fResetPort; bool fError; diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp index 1a4bbb0e17..39fb6012a7 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp @@ -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 diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h index 71532ab9ad..f1efcf271f 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h @@ -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() {