mirror of
https://git.missingno.dev/kolibrios-nvme-driver/
synced 2025-01-22 05:08:16 +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:
parent
bb952838ca
commit
7e71c33f3f
@ -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]
|
mov ecx, dword [esi + NSINFO.pg_sectors]
|
||||||
xor edx, edx
|
xor edx, edx
|
||||||
div ecx
|
div ecx
|
||||||
test edx, edx
|
;test edx, edx
|
||||||
jz @f
|
;jz @f
|
||||||
inc eax
|
;inc eax
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
mov eax, [buf]
|
mov edx, [buf]
|
||||||
and eax, not (PAGE_SIZE - 1)
|
and edx, not (PAGE_SIZE - 1)
|
||||||
add eax, PAGE_SIZE
|
add edx, PAGE_SIZE
|
||||||
stdcall build_prp_list, edx, eax, [prp_list_ptr]
|
stdcall build_prp_list, eax, edx, [prp_list_ptr]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err
|
jz .err
|
||||||
DEBUGF DBG_INFO, "Successfully allocated PRP list at: %x\n", eax
|
|
||||||
mov dword [edi + 4], eax
|
mov dword [edi + 4], eax
|
||||||
jmp .success
|
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)
|
; [esp + 16] - virtual pointer to PRP2 PRP list (if allocated, 0 if not)
|
||||||
mov ebx, esp
|
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 esi, [ns]
|
||||||
mov edi, [buf]
|
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, [numsectors_ptr]
|
||||||
mov eax, dword [eax]
|
mov eax, dword [eax]
|
||||||
@ -697,14 +688,28 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors
|
|||||||
jz .dptr_fail
|
jz .dptr_fail
|
||||||
|
|
||||||
DEBUGF DBG_INFO, "PRP1: %x, PRP2: %x\n", [ebx], [ebx + 4]
|
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], \
|
stdcall nvme_io_rw, [esi + NSINFO.pci], \
|
||||||
1, \
|
1, \
|
||||||
[esi + NSINFO.nsid], \
|
[esi + NSINFO.nsid], \
|
||||||
dword [ebx], \
|
dword [ebx], \
|
||||||
dword [ebx + 4], \
|
dword [ebx + 4], \
|
||||||
dword [start_sector], \
|
eax, \
|
||||||
dword [start_sector + 4], \
|
dword [start_sector + 4], \
|
||||||
dword [ebx + 12], \
|
ecx, \
|
||||||
dword [ebx + 8]
|
dword [ebx + 8]
|
||||||
|
|
||||||
; assume command completes successfully for now
|
; assume command completes successfully for now
|
||||||
@ -1114,23 +1119,20 @@ proc nvme_init stdcall, pci:dword
|
|||||||
div ecx
|
div ecx
|
||||||
mov dword [ebx + NSINFO.pg_sectors], eax
|
mov dword [ebx + NSINFO.pg_sectors], eax
|
||||||
invoke KernelFree, edi
|
invoke KernelFree, edi
|
||||||
if 0
|
if 1
|
||||||
invoke KernelAlloc, 0x4000
|
invoke KernelAlloc, 0x4000
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .exit_fail
|
jz .exit_fail
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
stdcall memsetdz, edi, 0x4000 / 4
|
|
||||||
invoke KernelAlloc, 0x8
|
invoke KernelAlloc, 0x8
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .exit_fail
|
jz .exit_fail
|
||||||
mov edx, NVM_CMD_READ
|
mov edx, NVM_CMD_READ
|
||||||
mov dword [eax], 17
|
mov dword [eax], 23
|
||||||
;add edi, 4094
|
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0x1000, 0, eax
|
||||||
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0, 0, eax
|
|
||||||
test eax, eax
|
|
||||||
jz .exit_fail
|
|
||||||
add edi, PAGE_SIZE
|
|
||||||
DEBUGF DBG_INFO, "STRING: %s\n", edi
|
DEBUGF DBG_INFO, "STRING: %s\n", edi
|
||||||
|
add edi, 0x1fe0
|
||||||
|
DEBUGF DBG_INFO, "STRING: %s\n", edi
|
||||||
end if
|
end if
|
||||||
DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num]
|
DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num]
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -1477,7 +1479,7 @@ align 4
|
|||||||
dd 0 ; no close function
|
dd 0 ; no close function
|
||||||
dd 0 ; no closemedia function
|
dd 0 ; no closemedia function
|
||||||
dd nvme_query_media
|
dd nvme_query_media
|
||||||
dd nvme_read
|
dd 0
|
||||||
dd 0 ; no write function (for now)
|
dd 0 ; no write function (for now)
|
||||||
dd 0 ; no flush function
|
dd 0 ; no flush function
|
||||||
dd 0 ; use default cache size
|
dd 0 ; use default cache size
|
||||||
|
Loading…
Reference in New Issue
Block a user