Use implemented ports mask to check if maximum port count needs to be extended.

* This should fix #8953
 * Also fix some harmless off-by-one errors
This commit is contained in:
Marcus Overhagen
2012-09-10 22:32:20 +02:00
parent 1946d374f2
commit 8040911a25
3 changed files with 28 additions and 3 deletions
@@ -131,12 +131,21 @@ AHCIController::Init()
fPortCountMax = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK); fPortCountMax = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
fPortImplementedMask = fRegs->pi; fPortImplementedMask = fRegs->pi;
// reported mask of implemented ports is sometimes empty
if (fPortImplementedMask == 0) { if (fPortImplementedMask == 0) {
fPortImplementedMask = 0xffffffff >> (32 - fPortCountMax); fPortImplementedMask = 0xffffffff >> (32 - fPortCountMax);
TRACE("ports-implemented mask is zero, using 0x%" B_PRIx32 " instead.\n", TRACE("ports-implemented mask is zero, using 0x%" B_PRIx32 " instead.\n",
fPortImplementedMask); fPortImplementedMask);
} }
// reported number of ports is sometimes too small
int maxPortIndex;
maxPortIndex = fls(fPortImplementedMask);
if (fPortCountMax < maxPortIndex) {
TRACE("reported number of ports is wrong, using %d instead.\n", maxPortIndex);
fPortCountMax = maxPortIndex;
}
fPortCountAvail = count_bits_set(fPortImplementedMask); fPortCountAvail = count_bits_set(fPortImplementedMask);
TRACE("cap: Interface Speed Support: generation %" B_PRIu32 "\n", (fRegs->cap >> CAP_ISS_SHIFT) & CAP_ISS_MASK); TRACE("cap: Interface Speed Support: generation %" B_PRIu32 "\n", (fRegs->cap >> CAP_ISS_SHIFT) & CAP_ISS_MASK);
@@ -169,7 +178,7 @@ AHCIController::Init()
goto err; goto err;
} }
for (int i = 0; i <= fPortCountMax; i++) { for (int i = 0; i < fPortCountMax; i++) {
if (fPortImplementedMask & (1 << i)) { if (fPortImplementedMask & (1 << i)) {
fPort[i] = new (std::nothrow)AHCIPort(this, i); fPort[i] = new (std::nothrow)AHCIPort(this, i);
if (!fPort[i]) { if (!fPort[i]) {
@@ -189,7 +198,7 @@ AHCIController::Init()
fRegs->ghc |= GHC_IE; fRegs->ghc |= GHC_IE;
FlushPostedWrites(); FlushPostedWrites();
for (int i = 0; i <= fPortCountMax; i++) { for (int i = 0; i < fPortCountMax; i++) {
if (fPort[i]) { if (fPort[i]) {
status_t status = fPort[i]->Init2(); status_t status = fPort[i]->Init2();
if (status < B_OK) { if (status < B_OK) {
@@ -215,7 +224,7 @@ AHCIController::Uninit()
{ {
TRACE("AHCIController::Uninit\n"); TRACE("AHCIController::Uninit\n");
for (int i = 0; i <= fPortCountMax; i++) { for (int i = 0; i < fPortCountMax; i++) {
if (fPort[i]) { if (fPort[i]) {
fPort[i]->Uninit(); fPort[i]->Uninit();
delete fPort[i]; delete fPort[i];
@@ -121,3 +121,17 @@ swap_words(void *data, size_t size)
word++; word++;
} }
} }
int
fls(unsigned mask)
{
if (mask == 0)
return 0;
int pos = 1;
while (mask != 1) {
mask >>= 1;
pos++;
}
return pos;
}
@@ -20,6 +20,8 @@ status_t sg_memcpy(const physical_entry *sgTable, int sgCount, const void *data,
void swap_words(void *data, size_t size); void swap_words(void *data, size_t size);
int fls(unsigned mask);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif