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

some refactoring and fixes

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-04 14:42:06 -04:00
parent b011dae650
commit d4bb46c00b
2 changed files with 90 additions and 86 deletions

View File

@ -450,120 +450,122 @@ proc get_log_page stdcall, pci:dword, dptr:dword, lid:byte
endp endp
proc build_prp_list stdcall, nprps:dword proc free_prp_list stdcall, prp_list_ptr:dword, nprps:dword
push ebx edi push ebx edi
mov ebx, [nprps] mov edi, [prp_list_ptr]
push ebx xor ebx, ebx
shl ebx, 2
invoke KernelAlloc, ebx
pop ebx
test eax, eax
jz .err
mov edi, eax
xor ecx, ecx
@@: @@:
invoke KernelAlloc, 0x1000 invoke KernelFree, dword [edi + ebx * 4]
test eax, eax inc ebx
jz .cleanup cmp ebx, [nprps]
mov dword [edi + ecx], eax
inc ecx
cmp ecx, ebx
jb @b jb @b
mov dword [esi + ecx], edi
mov eax, edi
pop edi ebx pop edi ebx
ret
.cleanup:
xor ecx, ecx
@@:
invoke KernelFree, dword [edi + ecx]
inc ecx
cmp ecx, edx
jb @b
.err:
xor eax, eax xor eax, eax
pop edi ebx
ret ret
endp endp
; Returns a PRP/PRP List proc build_prp_list stdcall, nprps:dword
; ----------------------------------------------------------------------------------------------------
; flags (used for identifying how to free the memory used by the PRPs after the command is completed):
; BIT 1 SET: allocated PRP1 entry
; BIT 2 SET: allocated PRP1 list
; BIT 3 SET: allocated PRP2 entry
; BIT 4 SET: allocated PRP2 list
proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsectors:dword, flags_ptr:dword
push esi edi ebx push ebx edi
mov esi, [ns] xor edi, edi
mov edi, [flags_ptr] mov ecx, [nprps]
mov ebx, dword [esi + NSINFO.pg_sectors] mov ebx, ecx
mov esi, [prps_ptr] shl ecx, 3
mov dword [esi + 4], 0 ; set PRP #2 to reserved by default invoke KernelAlloc, ecx ; store pointers to the PRP entries here
cmp ebx, dword [edi]
ja .numsectors_over_1pg
.alloc_prp1_entry:
invoke KernelAlloc, 0x1000
test eax, eax test eax, eax
jz .err jz .err
or byte [edi], PRP1_ENTRY_ALLOCATED mov edi, eax
mov dword [esi], eax mov ecx, [nprps]
pop ebx edi esi imul ecx, PAGE_SIZE
invoke KernelAlloc, ecx
test eax, eax
jz .err
mov edx, eax
xor ecx, ecx
@@:
push edx ecx
invoke GetPhysAddr, edx
pop ecx edx
mov dword [edi + ecx * 4], eax
mov dword [edi + ecx * 4 + 4], 0
add edx, PAGE_SIZE
inc ecx
cmp ecx, ebx
jb @b
pop edi ebx
ret ret
.numsectors_over_1pg: .err:
; check if offset portion of PRP1 is 0 test edi, edi
mov eax, dword [esi] jnz @f
and eax, (PAGE_SIZE shl NVM_MPS) - 1 invoke KernelFree, edi
test eax, eax
jz .check_prp2_cond_bii
; check PRP2 condition b) i. @@:
cmp ebx, [numsectors] pop edi ebx
jne .check_prp2_cond_cici xor eax, eax
invoke KernelAlloc, 0x1000 ret
endp
proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsectors:dword
push esi edi
mov esi, [ns]
mov edi, [prps_ptr]
mov qword [esi], 0
invoke KernelAlloc, PAGE_SIZE
test eax, eax test eax, eax
jz .err jz .err
mov dword [esi + 4], eax mov dword [edi], eax
or byte [edi], PRP2_ENTRY_ALLOCATED
jmp .alloc_prp1_entry
; is the number of sectors equal to two memory pages in size?
.check_prp2_cond_bii: mov eax, dword [esi + NSINFO.pg_sectors]
mov eax, ebx
shl eax, 1 shl eax, 1
cmp eax, [numsectors] cmp eax, [numsectors]
ja .check_prp2_cond_c jne @f
invoke KernelAlloc, 0x1000
test eax, eax
jz .err
mov dword [esi + 4], eax
or byte [edi], PRP2_ENTRY_ALLOCATED
jmp .alloc_prp1_entry
.check_prp2_cond_c: ; allocate a single PRP entry for PRP2
; is the command data transfer length greater or equal to two memory pages? invoke KernelAlloc, PAGE_SIZE
mov eax, ebx
shl eax, 1
cmp eax, [numsectors_ptr]
jb .alloc_prp1_entry
stdcall build_prp_list, 4 ; TODO: replace 4 with proper number of PRPs later
test eax, eax test eax, eax
jz .err jz .err
mov dword [esi + 4], eax mov dword [edi + 4], eax
jmp .alloc_prp1_entry jmp .success
@@:
; allocate PRP list for PRP2
shr eax, 1
mov ecx, [numsectors]
xchg eax, ecx
xor edx, edx
div ecx
stdcall build_prp_list, eax
test eax, eax
jz .free_prp_list
mov dword [edi + 4], eax
jmp .success
.free_prp_list:
invoke KernelFree, eax
.err: .err:
mov eax, dword [edi]
test eax, eax
jz @f
invoke KernelFree, eax
@@:
xor eax, eax xor eax, eax
pop ebx edi esi pop edi esi
ret
.success:
xor eax, eax
inc eax
pop edi esi
ret ret
endp endp
@ -830,6 +832,7 @@ proc nvme_init stdcall, pci:dword
stdcall memset, eax, 0, sizeof.NVM_QUEUE_ENTRY * (LAST_QUEUE_ID + 1) stdcall memset, eax, 0, sizeof.NVM_QUEUE_ENTRY * (LAST_QUEUE_ID + 1)
; Allocate submission/completion queue pointers ; Allocate submission/completion queue pointers
; TODO: Make these queues physically contiguous
xor ecx, ecx xor ecx, ecx
@@: @@:
push ecx push ecx
@ -907,6 +910,7 @@ proc nvme_init stdcall, pci:dword
DEBUGF DBG_INFO, "nvme%u: I/O controller detected...\n", [esi + pcidev.num] DEBUGF DBG_INFO, "nvme%u: I/O controller detected...\n", [esi + pcidev.num]
@@: @@:
; TODO: check IDENTC.AVSCC
mov al, byte [edi + IDENTC.sqes] mov al, byte [edi + IDENTC.sqes]
and al, 11110000b and al, 11110000b
cmp al, 0x60 ; maximum submission queue size should at least be 64 bytes cmp al, 0x60 ; maximum submission queue size should at least be 64 bytes

View File

@ -16,7 +16,6 @@ VS121 = 0x00010201 ; (v1.2.1)
VS130 = 0x00010300 ; (v1.3.0) VS130 = 0x00010300 ; (v1.3.0)
VS140 = 0x00010400 ; (v1.4.0) VS140 = 0x00010400 ; (v1.4.0)
PAGE_SIZE = 4096
NVM_CMDS = 64 ; Number of Commands NVM_CMDS = 64 ; Number of Commands
NVM_MPS = 0 ; Memory Page Size (2 ^ (12 + MPS)) NVM_MPS = 0 ; Memory Page Size (2 ^ (12 + MPS))
NVM_ASQS = 63 ; Admin Submission Queue Size NVM_ASQS = 63 ; Admin Submission Queue Size
@ -24,6 +23,7 @@ NVM_ACQS = NVM_ASQS ; Admin Completion Queue Size
LAST_QUEUE_ID = 1 ; Index of the last queue LAST_QUEUE_ID = 1 ; Index of the last queue
SQ_ENTRIES = NVM_ASQS ; I/O and Admin Submission Queue Size SQ_ENTRIES = NVM_ASQS ; I/O and Admin Submission Queue Size
CQ_ENTRIES = NVM_ACQS ; I/O and Admin Completion Queue Size CQ_ENTRIES = NVM_ACQS ; I/O and Admin Completion Queue Size
PAGE_SIZE = 4096 shl NVM_MPS
ADMIN_QUEUE = 0 ; Admin Queue ID ADMIN_QUEUE = 0 ; Admin Queue ID