mirror of
https://git.missingno.dev/kolibrios-nvme-driver/
synced 2024-12-22 22:08:47 +01:00
some refactoring and fixes
This commit is contained in:
parent
b011dae650
commit
d4bb46c00b
@ -450,120 +450,122 @@ proc get_log_page stdcall, pci:dword, dptr:dword, lid:byte
|
|||||||
|
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
proc free_prp_list stdcall, prp_list_ptr:dword, nprps:dword
|
||||||
|
|
||||||
|
push ebx edi
|
||||||
|
mov edi, [prp_list_ptr]
|
||||||
|
xor ebx, ebx
|
||||||
|
|
||||||
|
@@:
|
||||||
|
invoke KernelFree, dword [edi + ebx * 4]
|
||||||
|
inc ebx
|
||||||
|
cmp ebx, [nprps]
|
||||||
|
jb @b
|
||||||
|
pop edi ebx
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
endp
|
||||||
|
|
||||||
proc build_prp_list stdcall, nprps:dword
|
proc build_prp_list stdcall, nprps:dword
|
||||||
|
|
||||||
push ebx edi
|
push ebx edi
|
||||||
mov ebx, [nprps]
|
xor edi, edi
|
||||||
push ebx
|
mov ecx, [nprps]
|
||||||
shl ebx, 2
|
mov ebx, ecx
|
||||||
invoke KernelAlloc, ebx
|
shl ecx, 3
|
||||||
pop ebx
|
invoke KernelAlloc, ecx ; store pointers to the PRP entries here
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err
|
jz .err
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
xor ecx, ecx
|
mov ecx, [nprps]
|
||||||
|
imul ecx, PAGE_SIZE
|
||||||
@@:
|
invoke KernelAlloc, ecx
|
||||||
invoke KernelAlloc, 0x1000
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .cleanup
|
jz .err
|
||||||
mov dword [edi + ecx], eax
|
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
|
inc ecx
|
||||||
cmp ecx, ebx
|
cmp ecx, ebx
|
||||||
jb @b
|
jb @b
|
||||||
mov dword [esi + ecx], edi
|
|
||||||
mov eax, edi
|
|
||||||
pop edi ebx
|
pop edi ebx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.cleanup:
|
.err:
|
||||||
xor ecx, ecx
|
test edi, edi
|
||||||
|
jnz @f
|
||||||
|
invoke KernelFree, edi
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
invoke KernelFree, dword [edi + ecx]
|
|
||||||
inc ecx
|
|
||||||
cmp ecx, edx
|
|
||||||
jb @b
|
|
||||||
|
|
||||||
.err:
|
|
||||||
xor eax, eax
|
|
||||||
pop edi ebx
|
pop edi ebx
|
||||||
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; Returns a PRP/PRP List
|
proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, start_sector:qword, numsectors: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 esi edi
|
||||||
mov esi, [ns]
|
mov esi, [ns]
|
||||||
mov edi, [flags_ptr]
|
mov edi, [prps_ptr]
|
||||||
mov ebx, dword [esi + NSINFO.pg_sectors]
|
mov qword [esi], 0
|
||||||
mov esi, [prps_ptr]
|
invoke KernelAlloc, PAGE_SIZE
|
||||||
mov dword [esi + 4], 0 ; set PRP #2 to reserved by default
|
|
||||||
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 dword [edi], eax
|
||||||
mov dword [esi], eax
|
|
||||||
pop ebx edi esi
|
|
||||||
ret
|
|
||||||
|
|
||||||
.numsectors_over_1pg:
|
; is the number of sectors equal to two memory pages in size?
|
||||||
; check if offset portion of PRP1 is 0
|
mov eax, dword [esi + NSINFO.pg_sectors]
|
||||||
mov eax, dword [esi]
|
|
||||||
and eax, (PAGE_SIZE shl NVM_MPS) - 1
|
|
||||||
test eax, eax
|
|
||||||
jz .check_prp2_cond_bii
|
|
||||||
|
|
||||||
; check PRP2 condition b) i.
|
|
||||||
cmp ebx, [numsectors]
|
|
||||||
jne .check_prp2_cond_cici
|
|
||||||
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_bii:
|
|
||||||
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:
|
|
||||||
; is the command data transfer length greater or equal to two memory pages?
|
|
||||||
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
|
|
||||||
jz .err
|
|
||||||
mov dword [esi + 4], eax
|
|
||||||
jmp .alloc_prp1_entry
|
|
||||||
|
|
||||||
|
; allocate a single PRP entry for PRP2
|
||||||
|
invoke KernelAlloc, PAGE_SIZE
|
||||||
|
test eax, eax
|
||||||
|
jz .err
|
||||||
|
mov dword [edi + 4], eax
|
||||||
|
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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user