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_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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user