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

fix: nvme_readwrite and build_prp_list

This fixes the number of PRPs calculation before build_prp_list is
invoked. It also accounts for the fact that the NLB field in the NVMe
I/O read and write commands is a 0-based value, unlike numsectors.
start_sector is also converted into the appropriate LBA number as it
should be before sending the I/O command.
This commit is contained in:
Abdur-Rahman Mansoor 2024-07-21 14:14:04 -04:00
parent bb952838ca
commit 7e71c33f3f

View File

@ -621,18 +621,17 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword, prp_list_pt
mov ecx, dword [esi + NSINFO.pg_sectors]
xor edx, edx
div ecx
test edx, edx
jz @f
inc eax
;test edx, edx
;jz @f
;inc eax
@@:
mov eax, [buf]
and eax, not (PAGE_SIZE - 1)
add eax, PAGE_SIZE
stdcall build_prp_list, edx, eax, [prp_list_ptr]
mov edx, [buf]
and edx, not (PAGE_SIZE - 1)
add edx, PAGE_SIZE
stdcall build_prp_list, eax, edx, [prp_list_ptr]
test eax, eax
jz .err
DEBUGF DBG_INFO, "Successfully allocated PRP list at: %x\n", eax
mov dword [edi + 4], eax
jmp .success
@ -669,16 +668,8 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors
; [esp + 16] - virtual pointer to PRP2 PRP list (if allocated, 0 if not)
mov ebx, esp
; its important to do a memset here as otherwise a PRP offset error will
; probably occur.
mov eax, [numsectors_ptr]
mov eax, dword [eax]
mov esi, [ns]
mov edi, [buf]
mov ecx, dword [esi + NSINFO.lbads]
imul ecx, eax
shr ecx, 2
stdcall memsetdz, edi, ecx
mov eax, [numsectors_ptr]
mov eax, dword [eax]
@ -697,14 +688,28 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors
jz .dptr_fail
DEBUGF DBG_INFO, "PRP1: %x, PRP2: %x\n", [ebx], [ebx + 4]
mov eax, dword [start_sector]
mov ecx, dword [esi + NSINFO.lbads]
xor edx, edx
div ecx
DEBUGF DBG_INFO, "sector start: %u\n", eax
; According to the NVMe specification, the NLB field in the I/O read and write
; commands is a 0-based value (i.e., 0 is equivalant to 1, 1 is equivalant to 2, ...)
; As far as I know, KolibriOS doesn't follow this mechanism so let's just decrement the
; value and it should have the same effect.
mov ecx, dword [ebx + 12]
dec ecx
stdcall nvme_io_rw, [esi + NSINFO.pci], \
1, \
[esi + NSINFO.nsid], \
dword [ebx], \
dword [ebx + 4], \
dword [start_sector], \
eax, \
dword [start_sector + 4], \
dword [ebx + 12], \
ecx, \
dword [ebx + 8]
; assume command completes successfully for now
@ -1114,23 +1119,20 @@ proc nvme_init stdcall, pci:dword
div ecx
mov dword [ebx + NSINFO.pg_sectors], eax
invoke KernelFree, edi
if 0
if 1
invoke KernelAlloc, 0x4000
test eax, eax
jz .exit_fail
mov edi, eax
stdcall memsetdz, edi, 0x4000 / 4
invoke KernelAlloc, 0x8
test eax, eax
jz .exit_fail
mov edx, NVM_CMD_READ
mov dword [eax], 17
;add edi, 4094
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0, 0, eax
test eax, eax
jz .exit_fail
add edi, PAGE_SIZE
mov dword [eax], 23
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0x1000, 0, eax
DEBUGF DBG_INFO, "STRING: %s\n", edi
add edi, 0x1fe0
DEBUGF DBG_INFO, "STRING: %s\n", edi
end if
DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num]
xor eax, eax
@ -1477,7 +1479,7 @@ align 4
dd 0 ; no close function
dd 0 ; no closemedia function
dd nvme_query_media
dd nvme_read
dd 0
dd 0 ; no write function (for now)
dd 0 ; no flush function
dd 0 ; use default cache size