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:
parent
d4bb46c00b
commit
b6e6a69de7
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user