2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-01-08 22:16:13 +01:00

implement allocating and freeing PRP lists

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-05 14:05:36 -04:00
parent d4bb46c00b
commit b6e6a69de7

View File

@ -450,27 +450,38 @@ proc get_log_page stdcall, pci:dword, dptr:dword, lid:byte
endp endp
proc free_prp_list stdcall, prp_list_ptr:dword, nprps:dword proc free_prp_list stdcall, prp_list_ptr:dword, nprps:dword, recursive:byte
push ebx edi push edi
mov edi, [prp_list_ptr] mov edi, [prp_list_ptr]
xor ebx, ebx mov ecx, [nprps]
cmp ecx, PAGE_SIZE / 8 - 1
jbe @f
mov eax, dword [edi + PAGE_SIZE - 8]
sub ecx, PAGE_SIZE / 8 - 1
stdcall free_prp_list, eax, ecx, TRUE
@@: @@:
invoke KernelFree, dword [edi + ebx * 4] cmp [recursive], 0
inc ebx jz @f
cmp ebx, [nprps] invoke FreePage, edi
jb @b jmp .exit
pop edi ebx
@@:
invoke KernelFree, edi
.exit:
xor eax, eax xor eax, eax
pop edi
ret ret
endp endp
proc build_prp_list stdcall, nprps:dword proc build_prp_list stdcall, nprps:dword
push ebx edi push esi ebx edi
xor edi, edi xor edi, edi
xor esi, esi
mov ecx, [nprps] mov ecx, [nprps]
mov ebx, ecx mov ebx, ecx
shl ecx, 3 shl ecx, 3
@ -478,34 +489,61 @@ proc build_prp_list stdcall, nprps:dword
test eax, eax test eax, eax
jz .err jz .err
mov edi, eax mov edi, eax
mov ecx, [nprps] mov ecx, ebx
imul ecx, PAGE_SIZE imul ecx, PAGE_SIZE
invoke KernelAlloc, ecx invoke KernelAlloc, ecx
test eax, eax test eax, eax
jz .err jz .err
mov edx, eax mov esi, eax
xor ecx, ecx xor ecx, ecx
push esi
@@: .loop:
push edx ecx ; check if we need to build another PRP list
invoke GetPhysAddr, edx mov eax, ebx
pop ecx edx sub eax, PAGE_SIZE
; is this the last entry in the list? If so, build yet another PRP list here
cmp ecx, PAGE_SIZE / 8 - 1
jne @f
push ecx
stdcall build_prp_list, eax
pop ecx
test eax, eax
jz .cleanup_prp_list
invoke GetPhysAddr
mov dword [edi + ecx * 4], eax mov dword [edi + ecx * 4], eax
mov dword [edi + ecx * 4 + 4], 0 mov dword [edi + ecx * 4 + 4], 0
add edx, PAGE_SIZE jmp .success
@@:
mov eax, esi
push ecx
invoke GetPhysAddr
pop ecx
mov dword [edi + ecx * 4], eax
mov dword [edi + ecx * 4 + 4], 0
add esi, PAGE_SIZE
inc ecx inc ecx
cmp ecx, ebx cmp ecx, ebx
jb @b jb .loop
pop edi ebx
.success:
mov eax, edi
pop esi
pop edi ebx esi
ret ret
.cleanup_prp_list:
pop esi
invoke KernelFree, esi
.err: .err:
test edi, edi test edi, edi
jnz @f jz @f
invoke KernelFree, edi invoke KernelFree, edi
@@: @@:
pop edi ebx pop edi ebx esi
xor eax, eax xor eax, eax
ret ret
@ -549,7 +587,7 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsector
jmp .success jmp .success
.free_prp_list: .free_prp_list:
invoke KernelFree, eax stdcall free_prp_list, edi, eax
.err: .err:
mov eax, dword [edi] mov eax, dword [edi]
@ -574,7 +612,7 @@ proc nvme_read ns:dword, dst:dword, start_sector:qword, numsectors_ptr:dword
push ebx esi edi push ebx esi edi
sub esp, 8 sub esp, 8
stdcall alloc_dptr, [ns], dword [esp], dword [esp + 4], [start_sector], [numsectors_ptr] stdcall alloc_dptr, [ns], esp, [start_sector], [numsectors_ptr]
test eax, eax test eax, eax
jz .end jz .end
mov edi, eax mov edi, eax
@ -618,7 +656,7 @@ proc nvme_read ns:dword, dst:dword, start_sector:qword, numsectors_ptr:dword
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, prp1:dword, prp2:dword, slba_lo:dword, slba_hi:dword, nlb:word, opcode:dword proc nvme_io_rw stdcall, pci:dword, qid:word, nsid:dword, prps:qword, slba_lo:dword, slba_hi:dword, 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
@ -629,9 +667,9 @@ proc nvme_io_rw stdcall, pci:dword, qid:word, nsid:dword, prp1:dword, prp2:dword
movzx ecx, [qid] movzx ecx, [qid]
stdcall set_cdw0, [pci], ecx, [opcode] stdcall set_cdw0, [pci], ecx, [opcode]
mov dword [esp + SQ_ENTRY.cdw0], eax ; CDW0 mov dword [esp + SQ_ENTRY.cdw0], eax ; CDW0
mov eax, [prp1] mov eax, dword [prps]
mov dword [esp + SQ_ENTRY.dptr], eax mov dword [esp + SQ_ENTRY.dptr], eax
mov eax, [prp2] mov eax, dword [prps + 4]
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