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:
parent
5bc4a832f1
commit
34ff6d786e
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user