Cleanup of hard reset, works on Intel, doesn't work on Jmicron.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22307 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -223,12 +223,7 @@ AHCIController::ResetController()
|
|||||||
#if 1
|
#if 1
|
||||||
fRegs->ghc |= GHC_HR;
|
fRegs->ghc |= GHC_HR;
|
||||||
FlushPostedWrites();
|
FlushPostedWrites();
|
||||||
for (int i = 0; i < 20; i++) {
|
if (wait_until_clear(&fRegs->ghc, GHC_HR, 1000000) < B_OK)
|
||||||
snooze(50000);
|
|
||||||
if ((fRegs->ghc & GHC_HR) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (fRegs->ghc & GHC_HR)
|
|
||||||
return B_TIMED_OUT;
|
return B_TIMED_OUT;
|
||||||
#else
|
#else
|
||||||
fRegs->ghc &= ~GHC_AE;
|
fRegs->ghc &= ~GHC_AE;
|
||||||
|
|||||||
@@ -63,12 +63,14 @@ AHCIPort::Init1()
|
|||||||
fCommandList[0].ctbau = HI32(physAddr);
|
fCommandList[0].ctbau = HI32(physAddr);
|
||||||
// prdt follows after command table
|
// prdt follows after command table
|
||||||
|
|
||||||
|
// disable transitions to partial or slumber state
|
||||||
|
fRegs->sctl |= 0x300;
|
||||||
|
|
||||||
// clear IRQ status bits
|
// clear IRQ status bits
|
||||||
fRegs->is = fRegs->is;
|
fRegs->is = fRegs->is;
|
||||||
|
|
||||||
// clear error bits
|
// clear error bits
|
||||||
// fRegs->serr = fRegs->serr;
|
fRegs->serr = fRegs->serr;
|
||||||
fRegs->serr = 0xffffffff;
|
|
||||||
|
|
||||||
// power up device
|
// power up device
|
||||||
fRegs->cmd |= PORT_CMD_POD;
|
fRegs->cmd |= PORT_CMD_POD;
|
||||||
@@ -102,7 +104,7 @@ AHCIPort::Init2()
|
|||||||
|
|
||||||
FlushPostedWrites();
|
FlushPostedWrites();
|
||||||
|
|
||||||
// if (fRegs->sig == 0xffffffff)
|
if (1 /* fRegs->sig == 0xffffffff */)
|
||||||
ResetDevice();
|
ResetDevice();
|
||||||
|
|
||||||
PostResetDevice();
|
PostResetDevice();
|
||||||
@@ -114,6 +116,7 @@ AHCIPort::Init2()
|
|||||||
TRACE("sctl 0x%08lx\n", fRegs->sctl);
|
TRACE("sctl 0x%08lx\n", fRegs->sctl);
|
||||||
TRACE("serr 0x%08lx\n", fRegs->serr);
|
TRACE("serr 0x%08lx\n", fRegs->serr);
|
||||||
TRACE("sact 0x%08lx\n", fRegs->sact);
|
TRACE("sact 0x%08lx\n", fRegs->sact);
|
||||||
|
TRACE("tfd 0x%08lx\n", fRegs->tfd);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -156,7 +159,6 @@ AHCIPort::Uninit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AHCIPort::ResetDevice()
|
AHCIPort::ResetDevice()
|
||||||
{
|
{
|
||||||
@@ -173,9 +175,8 @@ AHCIPort::ResetDevice()
|
|||||||
// perform a hard reset
|
// perform a hard reset
|
||||||
fRegs->sctl = (fRegs->sctl & ~0xf) | 1;
|
fRegs->sctl = (fRegs->sctl & ~0xf) | 1;
|
||||||
FlushPostedWrites();
|
FlushPostedWrites();
|
||||||
snooze(10000);
|
spin(1100);
|
||||||
fRegs->sctl &= ~0xf;
|
fRegs->sctl &= ~0xf;
|
||||||
fRegs->serr = 0xffffffff;
|
|
||||||
FlushPostedWrites();
|
FlushPostedWrites();
|
||||||
|
|
||||||
if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) {
|
if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) {
|
||||||
@@ -183,8 +184,7 @@ AHCIPort::ResetDevice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clear error bits
|
// clear error bits
|
||||||
// fRegs->serr = fRegs->serr;
|
fRegs->serr = fRegs->serr;
|
||||||
fRegs->serr = 0xffffffff;
|
|
||||||
FlushPostedWrites();
|
FlushPostedWrites();
|
||||||
|
|
||||||
if (fRegs->ssts & 1) {
|
if (fRegs->ssts & 1) {
|
||||||
@@ -194,7 +194,8 @@ AHCIPort::ResetDevice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clear error bits
|
// clear error bits
|
||||||
fRegs->serr = 0xffffffff;
|
fRegs->serr = fRegs->serr;
|
||||||
|
FlushPostedWrites();
|
||||||
|
|
||||||
// start DMA engine
|
// start DMA engine
|
||||||
fRegs->cmd |= PORT_CMD_ST;
|
fRegs->cmd |= PORT_CMD_ST;
|
||||||
@@ -209,25 +210,21 @@ AHCIPort::PostResetDevice()
|
|||||||
{
|
{
|
||||||
TRACE("AHCIPort::PostResetDevice port %d\n", fIndex);
|
TRACE("AHCIPort::PostResetDevice port %d\n", fIndex);
|
||||||
|
|
||||||
TRACE("tfd 1 0x%08lx\n", fRegs->tfd);
|
if ((fRegs->ssts & 0xf) != 0x3 || (fRegs->tfd & 0xff) == 0x7f) {
|
||||||
|
TRACE("AHCIPort::PostResetDevice port %d: no device\n", fIndex);
|
||||||
// wait for DMA idle ?
|
return B_OK;
|
||||||
// if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 1000000) < B_OK) {
|
|
||||||
// TRACE("AHCIPort::PostResetDevice port %d error DMA engine doesn't stop\n", fIndex);
|
|
||||||
// }
|
|
||||||
|
|
||||||
switch (fRegs->tfd & 0xff) {
|
|
||||||
case 0x7f:
|
|
||||||
TRACE("no device present?\n");
|
|
||||||
break;
|
|
||||||
case 0xff:
|
|
||||||
TRACE("invalid task file status 0xff\n");
|
|
||||||
// fall through
|
|
||||||
default:
|
|
||||||
TRACE("waiting...\n");
|
|
||||||
wait_until_clear(&fRegs->tfd, ATA_BSY | ATA_DRQ, 31000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((fRegs->tfd & 0xff) == 0xff)
|
||||||
|
snooze(200000);
|
||||||
|
|
||||||
|
if ((fRegs->tfd & 0xff) == 0xff) {
|
||||||
|
TRACE("AHCIPort::PostResetDevice port %d: invalid task file status 0xff\n", fIndex);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_until_clear(&fRegs->tfd, ATA_BSY, 31000000);
|
||||||
|
|
||||||
if (fRegs->sig == 0xeb140101)
|
if (fRegs->sig == 0xeb140101)
|
||||||
fRegs->cmd |= PORT_CMD_ATAPI;
|
fRegs->cmd |= PORT_CMD_ATAPI;
|
||||||
else
|
else
|
||||||
@@ -237,13 +234,22 @@ AHCIPort::PostResetDevice()
|
|||||||
TRACE("device signature 0x%08lx (%s)\n", fRegs->sig,
|
TRACE("device signature 0x%08lx (%s)\n", fRegs->sig,
|
||||||
(fRegs->sig == 0xeb140101) ? "ATAPI" : (fRegs->sig == 0x00000101) ? "ATA" : "unknown");
|
(fRegs->sig == 0xeb140101) ? "ATAPI" : (fRegs->sig == 0x00000101) ? "ATA" : "unknown");
|
||||||
|
|
||||||
TRACE("tfd 0x%08lx\n", fRegs->tfd);
|
|
||||||
TRACE("device detection: 0x%lx\n", fRegs->ssts & 0xf);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AHCIPort::DumpD2HFis()
|
||||||
|
{
|
||||||
|
TRACE("D2H FIS:\n");
|
||||||
|
TRACE(" DW0 %02x %02x %02x %02x\n", fFIS->rfis[3], fFIS->rfis[2], fFIS->rfis[1], fFIS->rfis[0]);
|
||||||
|
TRACE(" DW1 %02x %02x %02x %02x\n", fFIS->rfis[7], fFIS->rfis[6], fFIS->rfis[5], fFIS->rfis[4]);
|
||||||
|
TRACE(" DW2 %02x %02x %02x %02x\n", fFIS->rfis[11], fFIS->rfis[10], fFIS->rfis[9], fFIS->rfis[8]);
|
||||||
|
TRACE(" DW3 %02x %02x %02x %02x\n", fFIS->rfis[15], fFIS->rfis[14], fFIS->rfis[13], fFIS->rfis[12]);
|
||||||
|
TRACE(" DW4 %02x %02x %02x %02x\n", fFIS->rfis[19], fFIS->rfis[18], fFIS->rfis[17], fFIS->rfis[16]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AHCIPort::Interrupt()
|
AHCIPort::Interrupt()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ private:
|
|||||||
status_t ResetDevice();
|
status_t ResetDevice();
|
||||||
status_t PostResetDevice();
|
status_t PostResetDevice();
|
||||||
void FlushPostedWrites();
|
void FlushPostedWrites();
|
||||||
|
void DumpD2HFis();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fIndex;
|
int fIndex;
|
||||||
|
|||||||
Reference in New Issue
Block a user