2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2024-12-22 22:08:47 +01:00

fix: PRP list allocation

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-18 17:01:26 -04:00
parent b88c5185a7
commit 1e315791fb

View File

@ -454,29 +454,19 @@ proc get_log_page stdcall, pci:dword, prp1:dword, lid:byte
endp endp
proc build_prp_list stdcall, nprps:dword, buf_physical:dword, prp_list_ptr:dword proc build_prp_list stdcall, nprps:dword, buf:dword, prp_list_ptr:dword
push esi ebx edi push esi ebx edi
sub esp, 16 sub esp, 4
; stack:
; [esp]: virtual pointer to first PRP list
; here, we store the pointer to the very first ; here, we store the pointer to the very first
; PRP list so that free_prp_list can free the ; PRP list so that free_prp_list can free the
; entire PRP list if something goes wrong, it ; entire PRP list if something goes wrong, it
; also serves as our return value placeholder ; also serves as our return value placeholder
mov dword [esp], 0 mov dword [esp], 0
; store the number of PRPs here, we need to
; cache the result here since we'll subtract
; nprps regularly. If we don't we will lose
; the value.
mov eax, [nprps]
mov dword [esp + 4], eax
; store consecutive PRP list buffer here, since
; we'll increment the PRP list pointer continuously
; its important to cache the value
mov dword [esp + 12], 0
xor edi, edi xor edi, edi
xor esi, esi xor esi, esi
mov ecx, [nprps] mov ecx, [nprps]
@ -484,16 +474,20 @@ proc build_prp_list stdcall, nprps:dword, buf_physical:dword, prp_list_ptr:dword
; we'll store consecutive PRP list buffers here, for example ; we'll store consecutive PRP list buffers here, for example
; given 2 PRP lists, we allocate 2 continuous pages ; given 2 PRP lists, we allocate 2 continuous pages
push ecx
invoke KernelAlloc, ecx ; store pointers to the PRP entries here invoke KernelAlloc, ecx ; store pointers to the PRP entries here
pop ecx
test eax, eax test eax, eax
jz .err jz .err
mov dword [esp + 12], eax mov dword [esp], eax
mov edi, eax mov edi, eax
mov eax, [prp_list_ptr] mov eax, [prp_list_ptr]
mov dword [eax], edi mov dword [eax], edi
shr ecx, 1
stdcall memsetdz, edi, ecx
; note we assume buf_physical is page-aligned ; note we assume buf is page-aligned
mov esi, [buf_physical] mov esi, [buf]
.build_prp_list: .build_prp_list:
; ensure we don't cross a page boundary ; ensure we don't cross a page boundary
@ -505,40 +499,41 @@ proc build_prp_list stdcall, nprps:dword, buf_physical:dword, prp_list_ptr:dword
@@: @@:
xor ecx, ecx xor ecx, ecx
cmp dword [esp], 0 cmp dword [esp], edi
jz @f je .loop
; we need to store the pointer of the newly allocated ; we need to store the pointer of the next
; PRP list to the previous PRP list last slot ; PRP list to the previous PRP list last entry
mov eax, dword [esp + 8] mov eax, edi
mov dword [eax + PAGE_SIZE - 8], esi invoke GetPhysAddr
mov dword [eax + PAGE_SIZE - 4], 0 mov dword [edi - 8], eax
jmp .loop mov dword [edi - 4], 0
@@:
mov dword [esp], esi
.loop: .loop:
mov dword [edi + ecx * 4], esi mov eax, esi
invoke GetPhysAddr
mov dword [edi + ecx * 4], eax
mov dword [edi + ecx * 4 + 4], 0 mov dword [edi + ecx * 4 + 4], 0
DEBUGF DBG_INFO, "PRP: %x\n", esi DEBUGF DBG_INFO, "PRP: %x\n", eax
add esi, PAGE_SIZE add esi, PAGE_SIZE
inc ecx inc ecx
cmp ecx, ebx cmp ecx, ebx
jne .loop jne .loop
; check if we we need to build another PRP list ; check if we we need to build another PRP list
mov dword [esp + 8], edi
add edi, PAGE_SIZE add edi, PAGE_SIZE
cmp ebx, PAGE_SIZE / 8 cmp ebx, PAGE_SIZE / 8
je .build_prp_list je .build_prp_list
; PRP list successfully created
mov eax, dword [esp] mov eax, dword [esp]
invoke GetPhysAddr invoke GetPhysAddr
add esp, 16 add esp, 4
pop edi ebx esi pop edi ebx esi
ret ret
.err: .err:
add esp, 16 add esp, 4
pop edi ebx esi pop edi ebx esi
xor eax, eax xor eax, eax
ret ret
@ -607,12 +602,9 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword, prp_list_pt
inc eax inc eax
@@: @@:
mov edx, dword [buf] mov eax, [buf]
and edx, not (PAGE_SIZE - 1) and eax, not (PAGE_SIZE - 1)
add edx, PAGE_SIZE add eax, PAGE_SIZE
xchg eax, edx
; push edx?
invoke GetPhysAddr
stdcall build_prp_list, edx, eax, [prp_list_ptr] stdcall build_prp_list, edx, eax, [prp_list_ptr]
test eax, eax test eax, eax
jz .err jz .err
@ -1092,11 +1084,12 @@ proc nvme_init stdcall, pci:dword
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], 1 mov dword [eax], 17
add edi, 4094 ;add edi, 4094
stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0, 0, eax stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0, 0, eax
test eax, eax test eax, eax
jz .exit_fail jz .exit_fail
add edi, PAGE_SIZE
DEBUGF DBG_INFO, "STRING: %s\n", edi 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]