diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp index fed79e9530..fea24f0720 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp @@ -178,6 +178,9 @@ AHCIController::Init() TRACE("cap: Enclosure Management Supported: %s\n", (fRegs->cap & CAP_EMS) ? "yes" : "no"); + TRACE("cap: FIS-based Switching Control: %s\n", + (fRegs->cap & CAP_FBSS) ? "yes" : "no"); + TRACE("cap: Supports Command List Override: %s\n", (fRegs->cap & CAP_SCLO) ? "yes" : "no"); TRACE("cap: Supports Staggered Spin-up: %s\n", diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index d140a01dd4..8006793c21 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -248,8 +248,6 @@ AHCIPort::SoftReset() // start port Enable(); - // TODO: If FBS Enable, clear PxFBS.EN prior to issuing sw reset - if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST, 1000000) < B_OK) { ERROR("%s: port %d still busy. Moving on to port reset.\n", @@ -259,6 +257,16 @@ AHCIPort::SoftReset() // TODO: Just can't get AHCI software reset issued properly. #if 0 + // Spec v1.2.0, ยง9.3.9 + // If FBS supported + enabled, disable + bool fbsDisabled = false; + if ((fRegs->cap & CAP_FBSS) != 0) { + if ((fRegs->fbs & PORT_FBS_EN) != 0) { + fbsDisabled = true; + fRegs->fbs &= ~PORT_FBS_EN; + } + } + // set command table soft reset bit fCommandTable->cfis[2] |= ATA_DEVICE_CONTROL_SOFT_RESET; @@ -281,11 +289,18 @@ AHCIPort::SoftReset() if (wait_until_clear(&fRegs->ci, 0, 1000000) < B_OK) { TRACE("%s: port %d: device is busy\n", __func__, fIndex); + + // Before we bail-out. Re-enable FBS if we disabled it + if (fbsDisabled) + fRegs->fbs |= PORT_FBS_EN; return PortReset(); } fCommandTable->cfis[2] &= ~ATA_DEVICE_CONTROL_SOFT_RESET; + if (fbsDisabled) + fRegs->fbs |= PORT_FBS_EN; + if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST, 1000000) < B_OK) { ERROR("%s: port %d software reset failed. Doing port reset...\n",