2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-02-07 12:46:51 +01:00

more fixes to nvme_io_rw and alloc_dptr

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-09 13:38:55 -04:00
parent 66d24f8e49
commit c9143ca99d

View File

@ -551,26 +551,32 @@ proc build_prp_list stdcall, nprps:dword
endp endp
proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsectors:dword proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword
push esi edi push esi edi
mov esi, [ns]
mov edi, [prps_ptr] mov edi, [prps_ptr]
mov dword [esi], 0 mov dword [edi], 0
mov dword [esi + 4], 0 mov dword [edi + 4], 0
invoke KernelAlloc, PAGE_SIZE invoke AllocPage
test eax, eax test eax, eax
jz .err jz .err
mov dword [edi], eax mov dword [edi], eax
; is the number of sectors equal to two memory pages in size? mov esi, [ns]
mov edx, [numsectors]
mov eax, dword [esi + NSINFO.pg_sectors] mov eax, dword [esi + NSINFO.pg_sectors]
; is the number of sectors less than or equal to one memory page?
cmp eax, edx
jbe .success
; is the number of sectors equal to two memory pages in size? (todo: fix???)
shl eax, 1 shl eax, 1
cmp eax, [numsectors] cmp eax, edx
jne @f jne @f
; allocate a single PRP entry for PRP2 ; allocate a single PRP entry for PRP2
invoke KernelAlloc, PAGE_SIZE invoke AllocPage
test eax, eax test eax, eax
jz .err jz .err
mov dword [edi + 4], eax mov dword [edi + 4], eax
@ -596,7 +602,7 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsector
mov eax, dword [edi] mov eax, dword [edi]
test eax, eax test eax, eax
jz @f jz @f
invoke KernelFree, eax invoke FreePage, eax
@@: @@:
xor eax, eax xor eax, eax
@ -720,65 +726,67 @@ proc nvme_readwrite stdcall, ns:dword, dst:dword, start_sector:qword, numsectors
push ebx esi edi push ebx esi edi
sub esp, 16 sub esp, 16
mov ebx, [numsectors_ptr] mov ebx, esp
mov ebx, [ebx] mov eax, [numsectors_ptr]
mov eax, dword [eax]
mov dword [esp + 8], edx ; command type (read or write) mov dword [esp + 8], edx ; command type (read or write)
mov dword [esp + 12], ebx ; save original numsectors value mov dword [esp + 12], eax ; save original numsectors value
mov esi, [ns]
mov edi, [dst]
mov edx, [numsectors_ptr]
mov edx, [edx]
; Note that [esp] will contain the value of PRP1 and [esp + 4] will ; Note that [esp] will contain the value of PRP1 and [esp + 4] will
; contain the value of PRP2 (after this call, if it completes successfully) ; contain the value of PRP2 (after this call, if it completes successfully)
stdcall alloc_dptr, [ns], esp, dword [start_sector], dword [start_sector + 4], ebx stdcall alloc_dptr, esi, ebx, edx
test eax, eax test eax, eax
jz .end jz .end
invoke GetPhysAddr
mov esi, [ns]
stdcall nvme_io_rw, [esi + NSINFO.pci], \ stdcall nvme_io_rw, [esi + NSINFO.pci], \
1, \ 1, \
[esi + NSINFO.nsid], \ [esi + NSINFO.nsid], \
dword [esp], \ dword [ebx], \
dword [esp + 4], \ dword [ebx + 4], \
dword [start_sector], \ dword [start_sector], \
dword [start_sector + 4], \ dword [start_sector + 4], \
ebx, \ dword [ebx + 12], \
dword [esp + 8] dword [ebx + 8]
; assume command completes successfully for now ; assume command completes successfully for now
; Write PRP1 ; Write PRP1
stdcall write_prp_buf, [ns], dword [esp], [dst], [numsectors_ptr] stdcall write_prp_buf, esi, dword [ebx], edi, [numsectors_ptr]
test eax, eax test eax, eax
jz .end jz .end
; check if PRP2 is needed at all ; check if PRP2 is needed at all
mov ecx, dword [esi + NSINFO.pg_sectors] mov ecx, dword [esi + NSINFO.pg_sectors]
cmp ecx, ebx mov edx, dword [ebx + 8]
cmp edx, ecx
jbe .end jbe .end
; check if PRP2 should be a PRP list or a regular entry ; check if PRP2 should be a PRP list or a regular entry
shl ecx, 1 shl ecx, 1
cmp ecx, ebx cmp ecx, edx
ja .is_prp_list ja .is_prp_list
; PRP2 is a PRP entry ; PRP2 is a PRP entry
mov edi, [dst] mov eax, dword [ebx + 12]
mov eax, dword [esp + 12] imul eax, dword [esi + NSINFO.lbads]
mov edx, [ns] mov edx, [numsectors_ptr]
imul eax, dword [edx + NSINFO.lbads] sub eax, dword [edx]
mov ebx, [numsectors_ptr]
sub eax, dword [ebx]
add edi, eax add edi, eax
stdcall write_prp_buf, [ns], dword [esp + 4], edi, [numsectors_ptr] stdcall write_prp_buf, esi, dword [ebx + 4], edi, [numsectors_ptr]
jmp .end jmp .end
.is_prp_list: .is_prp_list:
mov esi, [ns] ; TODO: Fix this
mov eax, ebx mov eax, ebx
xor edx, edx xor edx, edx
mov ecx, dword [esi + NSINFO.lbads] mov ecx, dword [esi + NSINFO.lbads]
div ecx div ecx
mov ebx, eax mov ebx, eax
stdcall write_prp_list_buf, dword [esp + 4], [dst], ebx stdcall write_prp_list_buf, dword [ebx + 4], [dst], ebx
stdcall free_prp_list, dword [esp + 4], ebx, FALSE stdcall free_prp_list, dword [ebx + 4], ebx, FALSE
.end: .end:
add esp, 16 add esp, 16
@ -788,7 +796,7 @@ proc nvme_readwrite stdcall, ns:dword, dst:dword, start_sector:qword, numsectors
endp endp
; See page 258-261 (read) and 269-271 (write) of the NVMe 1.4 specification for reference ; See page 258-261 (read) and 269-271 (write) of the NVMe 1.4 specification for reference
proc nvme_io_rw stdcall, pci:dword, qid:word, nsid:dword, prps:qword, slba_lo:dword, slba_hi:dword, nlb:word, opcode:dword proc nvme_io_rw stdcall, pci:dword, qid:word, nsid:dword, prps:qword, slba:qword, nlb:word, opcode:dword
; TODO: Use IDENTC.NOIOB to construct read/write commands that don't ; TODO: Use IDENTC.NOIOB to construct read/write commands that don't
; cross the I/O boundary to achieve optimal performance ; cross the I/O boundary to achieve optimal performance
@ -805,9 +813,9 @@ proc nvme_io_rw stdcall, pci:dword, qid:word, nsid:dword, prps:qword, slba_lo:dw
mov dword [esp + SQ_ENTRY.dptr + 8], eax mov dword [esp + SQ_ENTRY.dptr + 8], eax
mov eax, [nsid] mov eax, [nsid]
mov dword [esp + SQ_ENTRY.nsid], eax mov dword [esp + SQ_ENTRY.nsid], eax
mov eax, [slba_lo] mov eax, dword [slba] ; slba_lo
mov dword [esp + SQ_ENTRY.cdw10], eax mov dword [esp + SQ_ENTRY.cdw10], eax
mov eax, [slba_hi] mov eax, dword [slba + 4] ; slba_hi
mov dword [esp + SQ_ENTRY.cdw11], eax mov dword [esp + SQ_ENTRY.cdw11], eax
movzx eax, [nlb] movzx eax, [nlb]
mov word [esp + SQ_ENTRY.cdw12], ax mov word [esp + SQ_ENTRY.cdw12], ax
@ -1171,12 +1179,12 @@ proc nvme_init stdcall, pci:dword
test eax, eax test eax, eax
jz .exit_fail jz .exit_fail
mov edi, eax mov edi, eax
invoke KernelAlloc, 0x4 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], 0x1 mov dword [eax], 0x1
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 1, eax stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 1, 0, eax
test eax, eax test eax, eax
jz .exit_fail jz .exit_fail
DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num] DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num]