2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-01-21 20:58:13 +01:00

bug fixes

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-30 14:38:53 -04:00
parent dd4db45869
commit c3901b163e
3 changed files with 50 additions and 32 deletions

View File

@ -27,9 +27,4 @@ macro PDEBUGF _level*, _fmt*, _bus*, _devfn*, [_args] {
end if
}
macro LOCK_SPINLOCK {
common
mov dword [spinlock], 1
}
; vim: syntax=fasm

View File

@ -50,10 +50,10 @@ proc START c, reason:dword
jz .err
xor ebx, ebx
mov esi, dword [p_nvme_devices]
DEBUGF DBG_INFO, "p_nvme_devices: 0x%x\n", [p_nvme_devices]
sub esi, sizeof.pcidev
.loop:
lea esi, [esi + ebx * 4]
add esi, sizeof.pcidev
push esi ebx
stdcall device_is_compat, esi
test eax, eax
@ -176,7 +176,9 @@ endp
; See pages 161-205 of the NVMe 1.4 specification for reference
proc nvme_identify stdcall, pci:dword, nsid:dword, prp1:dword, cns:byte
LOCK_SPINLOCK
push esi
mov esi, [pci]
mov dword [esi + pcidev.spinlock], 1
sub esp, sizeof.SQ_ENTRY
stdcall memsetdz, esp, sizeof.SQ_ENTRY / 4
@ -184,14 +186,15 @@ proc nvme_identify stdcall, pci:dword, nsid:dword, prp1:dword, cns:byte
mov dword [esp + SQ_ENTRY.nsid], eax
mov eax, [prp1]
mov dword [esp + SQ_ENTRY.prp1], eax
stdcall set_cdw0, [pci], ADMIN_QUEUE, ADM_CMD_IDENTIFY
stdcall set_cdw0, esi, ADMIN_QUEUE, ADM_CMD_IDENTIFY
mov dword [esp + SQ_ENTRY.cdw0], eax
mov al, [cns]
mov byte [esp + SQ_ENTRY.cdw10], al
stdcall sqytdbl_write, [pci], ADMIN_QUEUE, esp
stdcall sqytdbl_write, esi, ADMIN_QUEUE, esp
add esp, sizeof.SQ_ENTRY
call nvme_poll
stdcall nvme_poll, esi
pop esi
ret
endp
@ -294,10 +297,12 @@ endp
; See page 101 of the NVMe 1.4 specification for reference
proc create_io_completion_queue stdcall, pci:dword, prp1:dword, qid:dword, ien:byte
LOCK_SPINLOCK
push esi
mov esi, [pci]
mov dword [esi + pcidev.spinlock], 1
sub esp, sizeof.SQ_ENTRY
stdcall memsetdz, esp, sizeof.SQ_ENTRY / 4
stdcall set_cdw0, [pci], ADMIN_QUEUE, ADM_CMD_CRE_IO_COMPLETION_QUEUE
stdcall set_cdw0, esi, ADMIN_QUEUE, ADM_CMD_CRE_IO_COMPLETION_QUEUE
mov dword [esp + SQ_ENTRY.cdw0], eax
mov eax, [prp1]
mov dword [esp + SQ_ENTRY.prp1], eax
@ -308,9 +313,10 @@ proc create_io_completion_queue stdcall, pci:dword, prp1:dword, qid:dword, ien:b
or eax, 0x1 ; CDW11.PC
; Don't set CDW11.IV since we're not using MSI-X or MSI vector
mov dword [esp + SQ_ENTRY.cdw11], eax
stdcall sqytdbl_write, [pci], ADMIN_QUEUE, esp
stdcall sqytdbl_write, esi, ADMIN_QUEUE, esp
add esp, sizeof.SQ_ENTRY
call nvme_poll
stdcall nvme_poll, esi
pop esi
ret
endp
@ -318,7 +324,9 @@ endp
; See page 103-104 of the NVMe 1.4 specification for reference
proc create_io_submission_queue stdcall, pci:dword, prp1:dword, qid:dword, cqid:word
LOCK_SPINLOCK
push esi
mov esi, [pci]
mov dword [esi + pcidev.spinlock], 1
sub esp, sizeof.SQ_ENTRY
stdcall memsetdz, esp, sizeof.SQ_ENTRY / 4
stdcall set_cdw0, [pci], ADMIN_QUEUE, ADM_CMD_CRE_IO_SUBMISSION_QUEUE
@ -333,9 +341,10 @@ proc create_io_submission_queue stdcall, pci:dword, prp1:dword, qid:dword, cqid:
or eax, 0x1 ; CDW11.PC (always set this to 1 as some devices may not support non-contiguous pages)
; TODO: Set CDW10.QPRIO
mov dword [esp + SQ_ENTRY.cdw11], eax
stdcall sqytdbl_write, [pci], ADMIN_QUEUE, esp
stdcall sqytdbl_write, esi, ADMIN_QUEUE, esp
add esp, sizeof.SQ_ENTRY
call nvme_poll
stdcall nvme_poll, esi
pop esi
ret
endp
@ -343,6 +352,9 @@ endp
; See page 95-96 of the NVMe 1.4 specification for reference
proc abort stdcall, pci:dword, cid:word, sqid:word
push esi
mov esi, [pci]
mov dword [esi + pcidev.spinlock], 1
sub esp, sizeof.SQ_ENTRY
stdcall memsetdz, esp, sizeof.SQ_ENTRY / 4
stdcall set_cdw0, [pci], ADMIN_QUEUE, ADM_CMD_ABORT
@ -353,6 +365,8 @@ proc abort stdcall, pci:dword, cid:word, sqid:word
mov dword [esp + SQ_ENTRY.cdw10], eax
stdcall sqytdbl_write, [pci], ADMIN_QUEUE, esp
add esp, sizeof.SQ_ENTRY
stdcall nvme_poll, esi
pop esi
ret
endp
@ -646,7 +660,10 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors
dec ecx
; TODO: add non-blocking mechanisms later on
LOCK_SPINLOCK
push eax
mov eax, dword [esi + NSINFO.pci]
mov dword [eax + pcidev.spinlock], 1
pop eax
stdcall nvme_io_rw, [esi + NSINFO.pci], \
1, \
[esi + NSINFO.nsid], \
@ -664,7 +681,7 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors
invoke KernelFree, edx
@@:
call nvme_poll
stdcall nvme_poll, [esi + NSINFO.pci]
test eax, eax
jz .fail
xor eax, eax
@ -751,7 +768,9 @@ proc detect_nvme
mov ecx, dword [pcidevs_len]
dec ecx
mov edi, dword [p_nvme_devices]
lea edi, [edi + ecx * 4]
mov edx, ecx
imul edx, sizeof.pcidev
lea edi, [edi + edx]
movzx eax, byte [esi + PCIDEV.bus]
mov byte [edi + pcidev.bus], al
@ -1039,12 +1058,12 @@ proc nvme_init stdcall, pci:dword
invoke KernelFree, edi
mov eax, 1 or (1 shl 16) ; CDW11 (set the number of queues we want)
LOCK_SPINLOCK
mov esi, [pci]
mov dword [esi + pcidev.spinlock], 1
stdcall set_features, [pci], NULLPTR, FID_NUMBER_OF_QUEUES, eax
call nvme_poll
stdcall nvme_poll, esi
test eax, eax
jz .exit_fail
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]
@ -1130,9 +1149,9 @@ proc nvme_init stdcall, pci:dword
mov edx, NVM_CMD_READ
mov dword [eax], 25
add edi, 0x5
LOCK_SPINLOCK
mov dword [esi + pcidev.spinlock], 1
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0x1000, 0, eax
call nvme_poll
stdcall nvme_poll, esi
test eax, eax
jz .exit_fail
DEBUGF DBG_INFO, "STRING: %s\n", edi
@ -1212,8 +1231,10 @@ proc nvme_controller_start stdcall, pci:dword
endp
proc nvme_poll
proc nvme_poll stdcall, pci:dword
push esi
mov esi, [pci]
xor ecx, ecx
@@:
@ -1222,17 +1243,19 @@ proc nvme_poll
je @f
xor eax, eax
inc eax
xchg eax, dword [spinlock]
xchg eax, dword [esi + pcidev.spinlock]
test eax, eax
jnz @b
; lock was released, return 1
pop esi
xor eax, eax
inc eax
ret
@@:
; timeout: lock wasn't released, return 0
pop esi
xor eax, eax
ret
@ -1414,7 +1437,7 @@ proc irq_handler
mov edi, dword [esi + pcidev.io_addr]
mov dword [edi + NVME_MMIO.INTMS], 0x3
mov eax, dword [spinlock]
mov eax, dword [esi + pcidev.spinlock]
test eax, eax
jz @f ; not locked, so it must be an I/O command
stdcall consume_cq_entries, esi, 0
@ -1424,9 +1447,9 @@ proc irq_handler
; Interrupt handled by driver, return 1
mov dword [edi + NVME_MMIO.INTMC], 0x3
pop edi esi ebx
xor eax, eax
xchg eax, dword [spinlock] ; unlock spinlock
xchg eax, dword [esi + pcidev.spinlock] ; unlock spinlock
pop edi esi ebx
mov eax, 1
ret
@ -1463,7 +1486,6 @@ endp
align 4
p_nvme_devices dd 0
pcidevs_len dd 0
spinlock dd 0
my_service db "NVMe",0 ;max 16 chars include zero
disk_functions:
dd disk_functions.end - disk_functions

View File

@ -332,6 +332,7 @@ struct pcidev
queue_entries dd ?
version dd ?
nsid dd ?
spinlock dd ?
nsinfo dd ?
nn dd ?
dstrd db ?