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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user