2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-01-03 11:25:55 +01:00

feat: add read functionality (to be tested)

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-05 16:02:11 -04:00
parent b6e6a69de7
commit f689eb5b2c

View File

@ -18,6 +18,8 @@ __DEBUG_LEVEL__ = 1
DRIVER_VERSION = 1 DRIVER_VERSION = 1
DBG_INFO = 1 DBG_INFO = 1
NULLPTR = 0 NULLPTR = 0
FALSE = 0
TRUE = 1
; flags for alloc_dptr ; flags for alloc_dptr
PRP1_ENTRY_ALLOCATED = 1 PRP1_ENTRY_ALLOCATED = 1
@ -506,7 +508,7 @@ proc build_prp_list stdcall, nprps:dword
cmp ecx, PAGE_SIZE / 8 - 1 cmp ecx, PAGE_SIZE / 8 - 1
jne @f jne @f
push ecx push ecx
stdcall build_prp_list, eax stdcall build_prp_list, eax, TRUE
pop ecx pop ecx
test eax, eax test eax, eax
jz .cleanup_prp_list jz .cleanup_prp_list
@ -554,7 +556,8 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsector
push esi edi push esi edi
mov esi, [ns] mov esi, [ns]
mov edi, [prps_ptr] mov edi, [prps_ptr]
mov qword [esi], 0 mov dword [esi], 0
mov dword [esi + 4], 0
invoke KernelAlloc, PAGE_SIZE invoke KernelAlloc, PAGE_SIZE
test eax, eax test eax, eax
jz .err jz .err
@ -587,7 +590,7 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsector
jmp .success jmp .success
.free_prp_list: .free_prp_list:
stdcall free_prp_list, edi, eax stdcall free_prp_list, edi, eax, FALSE
.err: .err:
mov eax, dword [edi] mov eax, dword [edi]
@ -608,49 +611,113 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsector
endp endp
proc nvme_read ns:dword, dst:dword, start_sector:qword, numsectors_ptr:dword ; note that prp_list is required to be a physical address
proc write_prp_list_buf stdcall, prp_list:dword, dst:dword, nprps:dword
push ebx esi edi push esi edi
sub esp, 8 mov esi, [prp_list]
stdcall alloc_dptr, [ns], esp, [start_sector], [numsectors_ptr] invoke KernelAlloc, 0x1000
test eax, eax test eax, eax
jz .end jz .err
mov edi, eax mov edi, eax
invoke GetPhysAddr push edi
mov esi, [ns] invoke MapPage, edi, esi, PG_SW+PG_NOCACHE
mov esi, edi
mov edi, [dst]
mov ecx, [nprps]
cmp ecx, PAGE_SIZE
jae @f
shl ecx, 12 + NVM_MPS
rep stosd
pop edi
invoke KernelFree, edi
pop edi esi
xor eax, eax
inc eax
ret
; more than or equal to 4096 PRP entries
@@:
mov ecx, PAGE_SIZE * PAGE_SIZE - 12
rep stosd
sub ecx, PAGE_SIZE
stdcall write_prp_list_buf, [prp_list], edi, ecx
mov esi, eax
pop edi
invoke KernelFree, edi
mov eax, esi
.err:
pop edi esi
ret
endp
nvme_read:
mov edx, NVM_CMD_READ
jmp nvme_readwrite
nvme_write:
mov edx, NVM_CMD_WRITE
proc nvme_readwrite stdcall, ns:dword, dst:dword, start_sector:qword, numsectors_ptr:dword
push ebx esi edi
sub esp, 12
mov ebx, [numsectors_ptr] mov ebx, [numsectors_ptr]
mov ebx, [ebx] mov ebx, [ebx]
stdcall nvme_io_rw, [esi + NSINFO.pci], \ ; PCI device mov dword [esp + 8], edx
1, \ ; QID (1 for now) ; Note that [esp] will contain the value of PRP1 and [esp + 4] will
[esi + NSINFO.nsid], \ ; NSID ; contain the value of PRP2 (after this call, if it completes successfully)
eax, \ ; DPTR stdcall alloc_dptr, [ns], esp, dword [start_sector], dword [start_sector + 4], ebx
dword [start_sector], \ ; SLBA_LO test eax, eax
dword [start_sector + 4], \ ; SLBA_HI jz .end
ebx, \ ; NLB invoke GetPhysAddr
NVM_CMD_READ ; Command opcode mov esi, [ns]
stdcall nvme_io_rw, [esi + NSINFO.pci], \
1, \
[esi + NSINFO.nsid], \
dword [esp], \
dword [esp + 4], \
dword [start_sector], \
dword [start_sector + 4], \
ebx, \
dword [esp + 8]
; assume command completes successfully for now ; assume command completes successfully for now
mov ecx, dword [esi + NSINFO.pg_sectors]
cmp ebx, ecx
ja .is_prp_list
; only 1-2 pages are used, which makes our life easier ; only 1-2 pages are used, which makes our life easier
mov ecx, dword [esi + NSINFO.lbads] mov ecx, dword [esi + NSINFO.lbads]
imul ecx, ebx imul ecx, ebx
mov esi, edi
mov edi, [dst] mov edi, [dst]
mov esi, dword [esp]
rep movsd rep movsd
add esp, 8 invoke KernelFree, dword [esp]
pop edi esi ebx mov esi, dword [esp + 4]
xor eax, eax ; TODO: add proper return value later mov ecx, dword [esi + NSINFO.pg_sectors]
ret cmp ebx, ecx
ja .is_prp_list
xor eax, eax
test esi, esi
jz .end
rep movsd
invoke KernelFree, dword [esp + 4]
xor eax, eax
jmp .end
.is_prp_list: .is_prp_list:
xor edx, edx
mov eax, ebx
mov ecx, dword [esi + NSINFO.lbads]
div ecx
mov ebx, eax
stdcall write_prp_list_buf, dword [esp + 4], [dst], ebx
test eax, eax
stdcall free_prp_list, dword [esp + 4], ebx, FALSE
.end: .end:
add esp, 8 add esp, 12
pop edi esi ebx pop edi esi ebx
xor eax, eax
ret ret
endp endp
@ -661,7 +728,7 @@ proc nvme_io_rw stdcall, pci:dword, qid:word, nsid:dword, prps:qword, slba_lo:dw
; 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
; ;
; Read AWUN/NAWUN ; TODO: Read AWUN/NAWUN
sub esp, sizeof.SQ_ENTRY sub esp, sizeof.SQ_ENTRY
stdcall memset, esp, 0, sizeof.SQ_ENTRY stdcall memset, esp, 0, sizeof.SQ_ENTRY
movzx ecx, [qid] movzx ecx, [qid]