| 25 | } |
| 26 | |
| 27 | int Init(){ |
| 28 | if(!PCI::FindGenericDevice(ahciClassCode, ahciSubclass)){ |
| 29 | Log::Warning("[AHCI] No controller found."); |
| 30 | return 1; |
| 31 | } |
| 32 | |
| 33 | controllerPCIDevice = &PCI::GetGenericPCIDevice(ahciClassCode, ahciSubclass); |
| 34 | assert(controllerPCIDevice->vendorID != 0xFFFF); |
| 35 | |
| 36 | Log::Info("Initializing AHCI Controller..."); |
| 37 | |
| 38 | controllerPCIDevice->EnableBusMastering(); |
| 39 | controllerPCIDevice->EnableInterrupts(); |
| 40 | controllerPCIDevice->EnableMemorySpace(); |
| 41 | |
| 42 | ahciBaseAddress = controllerPCIDevice->GetBaseAddressRegister(5); // BAR 5 is the AHCI Base Address |
| 43 | ahciVirtualAddress = Memory::GetIOMapping(ahciBaseAddress); |
| 44 | |
| 45 | ahciHBA = (hba_mem_t*)ahciVirtualAddress; |
| 46 | |
| 47 | uint8_t irq = controllerPCIDevice->AllocateVector(PCIVectors::PCIVectorAny); |
| 48 | if(irq == 0xFF){ |
| 49 | Log::Warning("[AHCI] Failed to allocate vector!"); |
| 50 | } |
| 51 | |
| 52 | uint32_t pi = ahciHBA->pi; |
| 53 | |
| 54 | while(!(ahciHBA->ghc & AHCI_GHC_ENABLE)){ |
| 55 | ahciHBA->ghc |= AHCI_GHC_ENABLE; |
| 56 | Timer::Wait(1); |
| 57 | } |
| 58 | ahciHBA->ghc |= AHCI_GHC_IE; |
| 59 | |
| 60 | if(debugLevelAHCI >= DebugLevelNormal){ |
| 61 | Log::Info("[AHCI] Interrupt Vector: %x, Base Address: %x, Virtual Base Address: %x", irq, ahciBaseAddress, ahciVirtualAddress); |
| 62 | Log::Info("[AHCI] (Cap: %x, Cap2: %x) Enabled? %Y, BOHC? %Y, 64-bit addressing? %Y, Staggered Spin-up? %Y, Slumber State Capable? %Y, Partial State Capable? %Y, FIS-based switching? %Y", ahciHBA->cap, ahciHBA->cap2, ahciHBA->ghc & AHCI_GHC_ENABLE, ahciHBA->cap2 & AHCI_CAP2_BOHC, ahciHBA->cap & AHCI_CAP_S64A, ahciHBA->cap & AHCI_CAP_SSS, ahciHBA->cap & AHCI_CAP_SSC, ahciHBA->cap & AHCI_CAP_PSC, ahciHBA->cap & AHCI_CAP_FBSS); |
| 63 | } |
| 64 | |
| 65 | IDT::RegisterInterruptHandler(irq, InterruptHandler); |
| 66 | ahciHBA->is = 0xffffffff; |
| 67 | |
| 68 | for(int i = 0; i < 32; i++){ |
| 69 | if((pi >> i) & 1){ |
| 70 | if(((ahciHBA->ports[i].ssts >> 8) & 0x0F) != HBA_PORT_IPM_ACTIVE || (ahciHBA->ports[i].ssts & HBA_PxSSTS_DET) != HBA_PxSSTS_DET_PRESENT) continue; |
| 71 | |
| 72 | if(ahciHBA->ports[i].sig == SATA_SIG_ATAPI) ; |
| 73 | else if(ahciHBA->ports[i].sig == SATA_SIG_PM) ; |
| 74 | else if(ahciHBA->ports[i].sig == SATA_SIG_SEMB) ; |
| 75 | else { |
| 76 | if(debugLevelAHCI >= DebugLevelVerbose){ |
| 77 | Log::Info("Found SATA Drive - Port: %d", i); |
| 78 | } |
| 79 | |
| 80 | ports[i] = new Port(i, &ahciHBA->ports[i], ahciHBA); |
| 81 | |
| 82 | if(ports[i]->status == AHCIStatus::Active) |
| 83 | DeviceManager::RegisterDevice(*(ports[i])); |
| 84 | else { |
nothing calls this directly
no test coverage detected