diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-21 12:54:45 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-21 12:54:45 -0400 |
commit | 04378cf03492449de6301c72c9f86fb7d3b68c2f (patch) | |
tree | c09bb318fad0a7156bc2463b31f90b6fc9dd48d7 /src/sys/io/ic | |
parent | 5e60c3277f04275bd5c6c68d42f390b82f0725bb (diff) |
kern: ahci: Ensure HBA is in AHCI-mode after reset
The global host control register (described by section 3.1.2 in the AHCI
spec) has an HBA reset bit which resets *everything* to a known state.
This means that after the reset, we'll have to indicate to the HBA that
we want to speak to it over the AHCI interface. We do it once before the
reset if needed, then we do it again after.
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/io/ic')
-rw-r--r-- | src/sys/io/ic/ahci.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/sys/io/ic/ahci.c b/src/sys/io/ic/ahci.c index 3d0e890..4bec02d 100644 --- a/src/sys/io/ic/ahci.c +++ b/src/sys/io/ic/ahci.c @@ -109,8 +109,17 @@ ahci_hba_reset(struct ahci_hba *hba) uint32_t ghc; int error; - /* Begin the reset */ + /* + * The HBA must be in an AHCI aware state before + * we can follow through with a reset + */ ghc = mmio_read32(&io->ghc); + if (!ISSET(ghc, AHCI_GHC_AE)) { + ghc |= AHCI_GHC_AE; + mmio_write32(&io->ghc, ghc); + } + + /* Now perform the actual reset */ ghc |= AHCI_GHC_HR; mmio_write32(&io->ghc, ghc); @@ -135,11 +144,6 @@ ahci_hba_init(struct ahci_hba *hba) uint32_t ghc; int error; - /* Ensure the host controller is AHCI aware */ - ghc = mmio_read32(&io->ghc); - ghc |= AHCI_GHC_AE; - mmio_write32(&io->ghc, ghc); - /* * We cannot be so certain what state the BIOS or whatever * firmware left the host controller in, therefore the HBA @@ -148,6 +152,17 @@ ahci_hba_init(struct ahci_hba *hba) if ((error = ahci_hba_reset(hba)) < 0) { return error; } + + /* + * Make the HBA AHCI aware, we do this after the reset + * as the reset logic ensures of this before continuing. + * + * We simply do it twice as the reset value is zero and we + * want to ensure it is still AHCI aware after this. + */ + ghc = mmio_read32(&io->ghc); + ghc |= AHCI_GHC_AE; + mmio_write32(&io->ghc, ghc); return 0; } |