added simple error handling
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25647 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -123,7 +123,7 @@ enum {
|
|||||||
PORT_INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable
|
PORT_INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable
|
||||||
PORT_INT_OF = (1 << 24), // Overflow Status/Enable
|
PORT_INT_OF = (1 << 24), // Overflow Status/Enable
|
||||||
PORT_INT_IPM = (1 << 23), // Incorrect Port Multiplier 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_DI = (1 << 7), // Device Interlock Status/Enable
|
||||||
PORT_INT_PC = (1 << 6), // Port Change Status/Enable
|
PORT_INT_PC = (1 << 6), // Port Change Status/Enable
|
||||||
PORT_INT_DP = (1 << 5), // Descriptor Processed Interrupt
|
PORT_INT_DP = (1 << 5), // Descriptor Processed Interrupt
|
||||||
@@ -134,10 +134,13 @@ enum {
|
|||||||
PORT_INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt
|
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_HBF | PORT_INT_HBD \
|
||||||
#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBD)
|
| PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \
|
||||||
#define PORT_INT_MASK (PORT_INT_FATAL | PORT_INT_ERROR | PORT_INT_DP |\
|
| PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \
|
||||||
PORT_INT_SDB | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR)
|
| 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 {
|
enum {
|
||||||
ATA_BSY = 0x80,
|
ATA_BSY = 0x80,
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ AHCIPort::AHCIPort(AHCIController *controller, int index)
|
|||||||
, fSectorSize(0)
|
, fSectorSize(0)
|
||||||
, fSectorCount(0)
|
, fSectorCount(0)
|
||||||
, fIsATAPI(false)
|
, fIsATAPI(false)
|
||||||
|
, fResetPort(false)
|
||||||
|
, fError(false)
|
||||||
{
|
{
|
||||||
fRequestSem = create_sem(1, "ahci request");
|
fRequestSem = create_sem(1, "ahci request");
|
||||||
fResponseSem = create_sem(0, "ahci response");
|
fResponseSem = create_sem(0, "ahci response");
|
||||||
@@ -281,21 +283,16 @@ void
|
|||||||
AHCIPort::Interrupt()
|
AHCIPort::Interrupt()
|
||||||
{
|
{
|
||||||
uint32 is = fRegs->is;
|
uint32 is = fRegs->is;
|
||||||
uint32 ci = fRegs->ci;
|
|
||||||
fRegs->is = is; // clear interrupts
|
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) {
|
if (is & PORT_INT_ERROR) {
|
||||||
TRACE("AHCIPort::Interrupt port %d, fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci);
|
InterruptErrorHandler(is);
|
||||||
TRACE("ssts 0x%08lx\n", fRegs->ssts);
|
return;
|
||||||
TRACE("sctl 0x%08lx\n", fRegs->sctl);
|
|
||||||
TRACE("serr 0x%08lx\n", fRegs->serr);
|
|
||||||
TRACE("sact 0x%08lx\n", fRegs->sact);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is & PORT_INT_FATAL)
|
uint32 ci = fRegs->ci;
|
||||||
panic("ahci fatal error, is 0x%08lx", is);
|
|
||||||
|
RWTRACE("AHCIPort::Interrupt port %d, fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci);
|
||||||
|
|
||||||
int release = 0;
|
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
|
status_t
|
||||||
AHCIPort::FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax, const void *data, size_t dataSize)
|
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) {
|
if (acquire_sem_etc(fResponseSem, 1, B_RELATIVE_TIMEOUT, timeout) < B_OK) {
|
||||||
fCommandsActive &= ~1;
|
fCommandsActive &= ~1;
|
||||||
result = B_TIMED_OUT;
|
result = B_TIMED_OUT;
|
||||||
|
} else if (fError) {
|
||||||
|
result = B_ERROR;
|
||||||
|
fError = false;
|
||||||
} else {
|
} else {
|
||||||
*tfd = fRegs->tfd;
|
*tfd = fRegs->tfd;
|
||||||
}
|
}
|
||||||
@@ -666,7 +731,10 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
|||||||
FinishTransfer();
|
FinishTransfer();
|
||||||
|
|
||||||
if (status < B_OK) {
|
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();
|
request->abort();
|
||||||
} else
|
} else
|
||||||
request->finish(tfd, bytesTransfered);
|
request->finish(tfd, bytesTransfered);
|
||||||
@@ -677,6 +745,12 @@ void
|
|||||||
AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
|
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);
|
// 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) {
|
if (fIsATAPI && request->cdb[0] != SCSI_OP_INQUIRY) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public:
|
|||||||
void Uninit();
|
void Uninit();
|
||||||
|
|
||||||
void Interrupt();
|
void Interrupt();
|
||||||
|
void InterruptErrorHandler(uint32 is);
|
||||||
|
|
||||||
|
|
||||||
void ScsiExecuteRequest(scsi_ccb *request);
|
void ScsiExecuteRequest(scsi_ccb *request);
|
||||||
@@ -65,6 +66,8 @@ private:
|
|||||||
uint32 fSectorSize;
|
uint32 fSectorSize;
|
||||||
uint64 fSectorCount;
|
uint64 fSectorCount;
|
||||||
bool fIsATAPI;
|
bool fIsATAPI;
|
||||||
|
bool fResetPort;
|
||||||
|
bool fError;
|
||||||
|
|
||||||
volatile fis * fFIS;
|
volatile fis * fFIS;
|
||||||
volatile command_list_entry * fCommandList;
|
volatile command_list_entry * fCommandList;
|
||||||
|
|||||||
Reference in New Issue
Block a user