From c3342cf811cdf0d1f51f56acd6d2737a278a6115 Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Sat, 24 May 2008 19:17:17 +0000 Subject: [PATCH] added simple error handling git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25647 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/busses/scsi/ahci/ahci_defs.h | 13 ++- .../kernel/busses/scsi/ahci/ahci_port.cpp | 98 ++++++++++++++++--- .../kernel/busses/scsi/ahci/ahci_port.h | 3 + 3 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index 63cd296384..abc5d5bf5c 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -123,7 +123,7 @@ enum { PORT_INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable PORT_INT_OF = (1 << 24), // Overflow Status/Enable PORT_INT_IPM = (1 << 23), // Incorrect Port Multiplier Status/Enable - PORT_INT_PRCE = (1 << 22), // PhyRdy Change Status/Enable + PORT_INT_PRC = (1 << 22), // PhyRdy Change Status/Enable PORT_INT_DI = (1 << 7), // Device Interlock Status/Enable PORT_INT_PC = (1 << 6), // Port Change Status/Enable PORT_INT_DP = (1 << 5), // Descriptor Processed Interrupt @@ -134,10 +134,13 @@ enum { PORT_INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt }; -#define PORT_INT_FATAL (PORT_INT_HBF | PORT_INT_IF | PORT_INT_IPM | PORT_INT_UF) -#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBD) -#define PORT_INT_MASK (PORT_INT_FATAL | PORT_INT_ERROR | PORT_INT_DP |\ - PORT_INT_SDB | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) +#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \ + | PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \ + | PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \ + | PORT_INT_UF) + +#define PORT_INT_MASK (PORT_INT_ERROR | PORT_INT_DP | PORT_INT_SDB \ + | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) enum { ATA_BSY = 0x80, 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 afbacf1745..bc9f9b7091 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -39,6 +39,8 @@ AHCIPort::AHCIPort(AHCIController *controller, int index) , fSectorSize(0) , fSectorCount(0) , fIsATAPI(false) + , fResetPort(false) + , fError(false) { fRequestSem = create_sem(1, "ahci request"); fResponseSem = create_sem(0, "ahci response"); @@ -281,21 +283,16 @@ void AHCIPort::Interrupt() { uint32 is = fRegs->is; - uint32 ci = fRegs->ci; fRegs->is = is; // clear interrupts - RWTRACE("AHCIPort::Interrupt port %d, fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci); - if (is & PORT_INT_ERROR) { - TRACE("AHCIPort::Interrupt 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); + InterruptErrorHandler(is); + return; } - - if (is & PORT_INT_FATAL) - panic("ahci fatal error, is 0x%08lx", is); + + uint32 ci = fRegs->ci; + + RWTRACE("AHCIPort::Interrupt port %d, fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci); int release = 0; @@ -311,6 +308,71 @@ AHCIPort::Interrupt() } +void +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); + + 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"); + fResetPort = true; + fError = true; + } + if (is & PORT_INT_HBF) { + TRACE("Host Bus Fatal Error\n"); + fResetPort = true; + fError = true; + } + if (is & PORT_INT_HBD) { + TRACE("Host Bus Data Error\n"); + fResetPort = true; + fError = true; + } + if (is & PORT_INT_IF) { + TRACE("Interface Fatal Error\n"); + fResetPort = true; + fError = true; + } + if (is & PORT_INT_INF) { + TRACE("Interface Non Fatal Error\n"); + } + if (is & PORT_INT_OF) { + TRACE("Overflow"); + fResetPort = true; + fError = true; + } + if (is & PORT_INT_IPM) { + TRACE("Incorrect Port Multiplier Status"); + } + if (is & PORT_INT_PRC) { + TRACE("PhyReady Change\n"); +// fResetPort = true; + } + if (is & PORT_INT_PC) { + TRACE("Port Connect Change\n"); +// fResetPort = true; + } + if (is & PORT_INT_UF) { + TRACE("Unknown FIS\n"); + fResetPort = true; + } + + if (fError) + release_sem_etc(fResponseSem, 1, B_RELEASE_IF_WAITING_ONLY | B_DO_NOT_RESCHEDULE); +} + + status_t AHCIPort::FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax, const void *data, size_t dataSize) { @@ -386,6 +448,9 @@ AHCIPort::WaitForTransfer(int *tfd, bigtime_t timeout) if (acquire_sem_etc(fResponseSem, 1, B_RELATIVE_TIMEOUT, timeout) < B_OK) { fCommandsActive &= ~1; result = B_TIMED_OUT; + } else if (fError) { + result = B_ERROR; + fError = false; } else { *tfd = fRegs->tfd; } @@ -666,7 +731,10 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite) FinishTransfer(); if (status < B_OK) { - TRACE("ExecuteAtaRequest port %d: device transfer timeout\n", fIndex); + if (status == B_TIMED_OUT) + TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex); + else + TRACE("ExecuteAtaRequest port %d: device error\n", fIndex); request->abort(); } else request->finish(tfd, bytesTransfered); @@ -677,6 +745,12 @@ void AHCIPort::ScsiExecuteRequest(scsi_ccb *request) { + if (fResetPort) { + fResetPort = false; + ResetDevice(); + PostResetDevice(); + } + // 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 d640b4c933..740555acce 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -20,6 +20,7 @@ public: void Uninit(); void Interrupt(); + void InterruptErrorHandler(uint32 is); void ScsiExecuteRequest(scsi_ccb *request); @@ -65,6 +66,8 @@ private: uint32 fSectorSize; uint64 fSectorCount; bool fIsATAPI; + bool fResetPort; + bool fError; volatile fis * fFIS; volatile command_list_entry * fCommandList;