| 80 | } |
| 81 | |
| 82 | Controller::Controller(PCIDevice* pciDev){ |
| 83 | pciDevice = pciDev; |
| 84 | |
| 85 | cRegs = reinterpret_cast<Registers*>(Memory::KernelAllocate4KPages(4)); |
| 86 | Memory::KernelMapVirtualMemory4K(pciDevice->GetBaseAddressRegister(0), (uintptr_t)cRegs, 4); |
| 87 | |
| 88 | pciDevice->EnableBusMastering(); |
| 89 | pciDevice->EnableMemorySpace(); |
| 90 | pciDevice->EnableInterrupts(); |
| 91 | |
| 92 | Disable(); |
| 93 | |
| 94 | { |
| 95 | unsigned spin = 500; |
| 96 | while(spin-- && (cRegs->status & NVME_CSTS_READY)) Timer::Wait(1); |
| 97 | |
| 98 | if(spin <= 0){ |
| 99 | Log::Warning("[NVMe] Controller not disabled! (NVME_CSTS_READY == 1)"); |
| 100 | dStatus = DriverStatus::ControllerError; |
| 101 | return; |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | cRegs->config = NVME_CFG_DEFAULT_IOCQES | NVME_CFG_DEFAULT_IOSQES; |
| 106 | |
| 107 | if(GetMinMemoryPageSize() > PAGE_SIZE_4K || GetMaxMemoryPageSize() < PAGE_SIZE_4K){ |
| 108 | Log::Error("[NVMe] Error: Controller does not support 4K pages"); |
| 109 | return; |
| 110 | } |
| 111 | |
| 112 | SetMemoryPageSize(PAGE_SIZE_4K); |
| 113 | SetCommandSet(NVMeConfigCmdSetNVM); |
| 114 | |
| 115 | uintptr_t admCQBase = Memory::AllocatePhysicalMemoryBlock(); |
| 116 | uintptr_t admSQBase = Memory::AllocatePhysicalMemoryBlock(); |
| 117 | void* admCQ = Memory::KernelAllocate4KPages(1); |
| 118 | void* admSQ = Memory::KernelAllocate4KPages(1); |
| 119 | |
| 120 | cRegs->adminCompletionQ = admCQBase; |
| 121 | cRegs->adminSubmissionQ = admSQBase; |
| 122 | |
| 123 | Memory::KernelMapVirtualMemory4K(admCQBase, (uintptr_t)admCQ, 1); |
| 124 | Memory::KernelMapVirtualMemory4K(admSQBase, (uintptr_t)admSQ, 1); |
| 125 | |
| 126 | adminQueue = NVMeQueue(0 /* admin queue ID is 0 */, admCQBase, admSQBase, admCQ, admSQ, GetCompletionDoorbell(0), GetSubmissionDoorbell(0), MIN(PAGE_SIZE_4K, GetMaxQueueEntries() * sizeof(NVMeCompletion)), MIN(PAGE_SIZE_4K, GetMaxQueueEntries() * sizeof(NVMeCommand))); |
| 127 | |
| 128 | SetAdminCompletionQueueSize(adminQueue.CQSize()); |
| 129 | SetAdminSubmissionQueueSize(adminQueue.SQSize()); |
| 130 | |
| 131 | Enable(); |
| 132 | |
| 133 | { |
| 134 | unsigned spin = 500; |
| 135 | while(spin-- && !(cRegs->status & NVME_CSTS_READY)) Timer::Wait(1); |
| 136 | |
| 137 | if(spin <= 0){ |
| 138 | Log::Warning("[NVMe] Controller not ready! (NVME_CSTS_READY != 1)"); |
| 139 | dStatus = DriverStatus::ControllerError; |
nothing calls this directly
no test coverage detected