2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-02-07 04:36:50 +01:00

fix: initialize I/O queues correctly

This commit is contained in:
Abdur-Rahman Mansoor 2024-06-27 15:55:29 -04:00
parent 5bc4a832f1
commit 34ff6d786e
2 changed files with 52 additions and 44 deletions

View File

@ -643,45 +643,52 @@ proc nvme_init stdcall, pci:dword
mov dword [edi + NVME_MMIO.AQA], eax
; Allocate list of queues
invoke KernelAlloc, sizeof.NVM_QUEUE_ENTRY * NVM_ASQS
invoke KernelAlloc, sizeof.NVM_QUEUE_ENTRY * (LAST_QUEUE_ID + 1)
test eax, eax
jz .exit_fail
mov dword [esi + pcidev.queue_entries], eax
stdcall memset, eax, 0, sizeof.NVM_QUEUE_ENTRY * NVM_ASQS
mov edi, eax
stdcall memset, eax, 0, sizeof.NVM_QUEUE_ENTRY * (LAST_QUEUE_ID + 1)
; Allocate submission/completion queue pointers
xor ecx, ecx
@@:
push ecx
invoke CreateRingBuffer, 0x1000, PG_SW
pop ecx
test eax, eax
jz .exit_fail
mov dword [edi + ecx + NVM_QUEUE_ENTRY.sq_ptr], eax
push ecx
stdcall memset, eax, 0, sizeof.SQ_ENTRY * SQ_ENTRIES
invoke CreateRingBuffer, 0x1000, PG_SW
pop ecx
test eax, eax
jz .exit_fail
mov dword [edi + ecx + NVM_QUEUE_ENTRY.cq_ptr], eax
push ecx
stdcall memset, eax, 0, sizeof.CQ_ENTRY * CQ_ENTRIES
pop ecx
mov dword [edi + ecx + NVM_QUEUE_ENTRY.phase_tag], CQ_PHASE_TAG
add ecx, sizeof.NVM_QUEUE_ENTRY
cmp ecx, (LAST_QUEUE_ID + 1) * sizeof.NVM_QUEUE_ENTRY
jne @b
; Configure Admin Submission/Completion Queue Base Address
push esi
mov esi, dword [esi + pcidev.queue_entries]
; TODO: Allocate ring buffer? (see page 8 of NVMe 1.4 spec)
invoke CreateRingBuffer, 0x1000, PG_SW
test eax, eax
jz .exit_fail
mov dword [esi + NVM_QUEUE_ENTRY.sq_ptr], eax
mov esi, [pci]
mov esi, dword [esi + pcidev.io_addr]
mov eax, dword [edi + NVM_QUEUE_ENTRY.sq_ptr]
invoke GetPhysAddr
mov dword [edi + NVME_MMIO.ASQ], eax
and dword [edi + NVME_MMIO.ASQ + 4], 0
; TODO: Allocate ring buffer? (see page 8 of NVMe 1.4 spec)
invoke CreateRingBuffer, 0x1000, PG_SW
test eax, eax
jz .exit_fail
mov dword [esi + NVM_QUEUE_ENTRY.cq_ptr], eax
mov dword [esi + NVME_MMIO.ASQ], eax
mov dword [esi + NVME_MMIO.ASQ + 4], 0
mov eax, dword [edi + NVM_QUEUE_ENTRY.cq_ptr]
invoke GetPhysAddr
mov dword [edi + NVME_MMIO.ACQ], eax
and dword [edi + NVME_MMIO.ACQ + 4], 0
stdcall memset, dword [esi + NVM_QUEUE_ENTRY.sq_ptr], 0, sizeof.SQ_ENTRY * NVM_ASQS
stdcall memset, dword [esi + NVM_QUEUE_ENTRY.cq_ptr], 0, sizeof.CQ_ENTRY * NVM_ACQS
mov dword [esi + NVM_QUEUE_ENTRY.phase_tag], CQ_PHASE_TAG
; TODO: memset the I/O queues as well
pop esi
; we want to disable all interrupts for now, since the controller randomly
; generates interrupts while starting up
;mov dword [edi + NVME_MMIO.INTMS], 0xffffffff
mov dword [esi + NVME_MMIO.ACQ], eax
mov dword [esi + NVME_MMIO.ACQ + 4], 0
; Attach interrupt handler
mov esi, [pci]
movzx eax, byte [esi + pcidev.iline]
DEBUGF DBG_INFO, "nvme%u: Attaching interrupt handler to IRQ %u\n", [esi + pcidev.num], eax
invoke AttachIntHandler, eax, irq_handler, 0
@ -691,16 +698,14 @@ proc nvme_init stdcall, pci:dword
; Restart the controller
stdcall nvme_controller_start, esi
;mov dword [edi + NVME_MMIO.INTMC], 0xffffffff ; re-enable interrupts
invoke KernelAlloc, 0x1000
test eax, eax
jz .exit_fail
mov ebx, eax
mov edi, eax
invoke GetPhysAddr
; pci:dword, nsid:dword, dptr:dword, cns:byte
stdcall nvme_identify, [pci], 0, eax, CNS_IDCS
mov edi, ebx
mov eax, dword [edi + IDENTC.nn]
mov dword [esi + pcidev.nn], eax
DEBUGF DBG_INFO, "nvme%u: Namespace Count: %u\n", [esi + pcidev.num], eax
@ -735,7 +740,7 @@ proc nvme_init stdcall, pci:dword
mov eax, 1 or (1 shl 16) ; CDW11 (set the number of queues we want)
stdcall set_features, [pci], NULLPTR, FID_NUMBER_OF_QUEUES, eax
mov esi, dword [p_nvme_devices]
mov esi, [pci]
mov esi, dword [esi + pcidev.queue_entries]
mov esi, dword [esi + NVM_QUEUE_ENTRY.cq_ptr]
mov eax, dword [esi + sizeof.CQ_ENTRY + CQ_ENTRY.cdw0]
@ -768,18 +773,19 @@ proc nvme_init stdcall, pci:dword
stdcall create_io_submission_queue, [pci], eax, 1, 1
if 1
stdcall determine_active_nsids, [pci]
test eax, eax
jz .exit_fail ; No active NSIDS
mov esi, [pci]
mov dword [esi + pcidev.nsid], eax
DEBUGF DBG_INFO, "nvme%u: Found active NSID: %u\n", [esi + pcidev.num], eax
stdcall determine_active_nsids, [pci]
test eax, eax
jz .exit_fail ; No active NSIDS
mov esi, [pci]
mov dword [esi + pcidev.nsid], eax
DEBUGF DBG_INFO, "nvme%u: Found active NSID: %u\n", [esi + pcidev.num], eax
else
mov esi, [pci]
xor eax, eax
inc eax
mov dword [esi + pcidev.nsid], eax
mov esi, [pci]
xor eax, eax
inc eax
mov dword [esi + pcidev.nsid], eax
end if
invoke KernelAlloc, 0x1000
test eax, eax
jz .exit_fail

View File

@ -21,6 +21,8 @@ NVM_MPS = 0 ; Memory Page Size (2 ^ (12 + MPS))
NVM_ASQS = 63 ; Admin Submission Queue Size
NVM_ACQS = NVM_ASQS ; Admin Completion Queue Size
LAST_QUEUE_ID = 1 ; Index of the last queue
SQ_ENTRIES = NVM_ASQS ; I/O and Admin Submission Queue Size
CQ_ENTRIES = NVM_ACQS ; I/O and Admin Completion Queue Size
ADMIN_QUEUE = 0 ; Admin Queue ID