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

refactor: tweak some things

First of all, the driver will now abort initialization if it encounters
the first found namespace LBADS is not 512, since KolibriOS doesn't
support a LBADS greater than 512 as of now.

This commit also removes verbose debug logs and adds appropriate error
codes to nvme_readwrite
This commit is contained in:
Abdur-Rahman Mansoor 2024-07-20 16:38:12 -04:00
parent c21376dde4
commit 0eea7a6130
2 changed files with 35 additions and 27 deletions

View File

@ -11,8 +11,8 @@
format PE DLL native format PE DLL native
entry START entry START
API_VERSION equ 0 ;debug API_VERSION = 0 ;debug
SRV_GETVERSION equ 0 SRV_GETVERSION = 0
__DEBUG__ = 1 __DEBUG__ = 1
__DEBUG_LEVEL__ = 1 __DEBUG_LEVEL__ = 1
DRIVER_VERSION = 1 DRIVER_VERSION = 1
@ -58,7 +58,7 @@ proc START c, reason:dword
jne .err jne .err
.entry: .entry:
DEBUGF DBG_INFO, "Detecting NVMe hardware...\n" DEBUGF DBG_INFO, "Detecting NVMe device...\n"
call detect_nvme call detect_nvme
test eax, eax test eax, eax
jz .err jz .err
@ -123,8 +123,7 @@ proc add_nvme_disk stdcall, pci:dword
push "n" push "n"
push dword [esi + pcidev.num] push dword [esi + pcidev.num]
push "nvme" push "nvme"
mov eax, esp invoke DiskAdd, disk_functions, esp, [esi + pcidev.nsinfo], 0
invoke DiskAdd, disk_functions, eax, [esi + pcidev.nsinfo], 0
add esp, 20 add esp, 20
test eax, eax test eax, eax
jz @f jz @f
@ -145,18 +144,21 @@ endp
proc nvme_query_media stdcall, userdata:dword, info:dword proc nvme_query_media stdcall, userdata:dword, info:dword
push esi edi push ebx esi edi
mov esi, [userdata] mov esi, [userdata]
mov ebx, dword [esi + NSINFO.pci]
mov edi, [info] mov edi, [info]
mov dword [edi + DISKMEDIAINFO.flags], 0 mov dword [edi + DISKMEDIAINFO.flags], 0
mov eax, dword [esi + NSINFO.lbads] mov eax, dword [esi + NSINFO.lbads]
DEBUGF DBG_INFO, "nvme%un%u (Query Media): Sector size = %u\n", [ebx + pcidev.num], [esi + NSINFO.nsid], eax
mov dword [edi + DISKMEDIAINFO.sectorsize], eax mov dword [edi + DISKMEDIAINFO.sectorsize], eax
mov eax, dword [esi + NSINFO.capacity] mov eax, dword [esi + NSINFO.capacity]
mov dword [edi + DISKMEDIAINFO.capacity], eax mov dword [edi + DISKMEDIAINFO.capacity], eax
mov eax, dword [esi + NSINFO.capacity + 4] mov eax, dword [esi + NSINFO.capacity + 4]
mov dword [edi + DISKMEDIAINFO.capacity + 4], eax mov dword [edi + DISKMEDIAINFO.capacity + 4], eax
DEBUGF DBG_INFO, "nvme%un%u (Query Media): Capacity = %u + %u sectors\n", [ebx + pcidev.num], [esi + NSINFO.nsid], [esi + NSINFO.capacity], [esi + NSINFO.capacity + 4]
xor eax, eax xor eax, eax
pop edi esi pop edi esi ebx
ret ret
endp endp
@ -692,14 +694,13 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors
dword [ebx + 8] dword [ebx + 8]
; assume command completes successfully for now ; assume command completes successfully for now
mov ecx, dword [ebx + 12] xor eax, eax
mov eax, [numsectors_ptr]
mov dword [eax], ecx
jmp .end jmp .end
.dptr_fail: .dptr_fail:
mov ebx, [numsectors_ptr] mov ebx, [numsectors_ptr]
mov dword [ebx], 0 mov dword [ebx], 0
or eax, -1 ; generic disk error
.end: .end:
add esp, 20 add esp, 20
@ -758,7 +759,7 @@ proc detect_nvme
.found_dev: .found_dev:
push edx eax push edx eax
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): Detected NVMe device...\n", byte [eax + PCIDEV.bus], byte [eax + PCIDEV.devfn] ;PDEBUGF DBG_INFO, "PCI(%u.%u.%u): Detected NVMe device...\n", byte [eax + PCIDEV.bus], byte [eax + PCIDEV.devfn]
cmp dword [pcidevs_len], TOTAL_PCIDEVS cmp dword [pcidevs_len], TOTAL_PCIDEVS
jne @f jne @f
pop eax edx pop eax edx
@ -773,7 +774,7 @@ proc detect_nvme
test eax, eax test eax, eax
jz .err_no_mem jz .err_no_mem
mov dword [p_nvme_devices], eax mov dword [p_nvme_devices], eax
DEBUGF DBG_INFO, "(NVMe) Allocated pcidev struct at 0x%x\n", [p_nvme_devices] ;DEBUGF DBG_INFO, "(NVMe) Allocated pcidev struct at 0x%x\n", [p_nvme_devices]
@@: @@:
mov ecx, dword [pcidevs_len] mov ecx, dword [pcidevs_len]
@ -837,7 +838,7 @@ proc device_is_compat stdcall, pci:dword
invoke MapIoMem, edx, ecx, PG_SW+PG_NOCACHE invoke MapIoMem, edx, ecx, PG_SW+PG_NOCACHE
mov dword [esi + pcidev.io_addr], eax mov dword [esi + pcidev.io_addr], eax
mov eax, dword [eax + NVME_MMIO.VS] mov eax, dword [eax + NVME_MMIO.VS]
DEBUGF DBG_INFO, "nvme%u: Controller version: 0x%x\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Controller version: 0x%x\n", [esi + pcidev.num], eax
mov dword [esi + pcidev.version], eax mov dword [esi + pcidev.version], eax
pop ecx edx esi pop ecx edx esi
xor eax, eax xor eax, eax
@ -963,11 +964,11 @@ proc nvme_init stdcall, pci:dword
; Attach interrupt handler ; Attach interrupt handler
mov esi, [pci] mov esi, [pci]
movzx eax, byte [esi + pcidev.iline] movzx eax, byte [esi + pcidev.iline]
DEBUGF DBG_INFO, "nvme%u: Attaching interrupt handler to IRQ %u\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Attaching interrupt handler to IRQ %u\n", [esi + pcidev.num], eax
invoke AttachIntHandler, eax, irq_handler, 0 invoke AttachIntHandler, eax, irq_handler, 0
test eax, eax test eax, eax
jz .exit_fail jz .exit_fail
DEBUGF DBG_INFO, "nvme%u: Successfully attached interrupt handler\n", [esi + pcidev.num] ;DEBUGF DBG_INFO, "nvme%u: Successfully attached interrupt handler\n", [esi + pcidev.num]
; Restart the controller ; Restart the controller
stdcall nvme_controller_start, esi stdcall nvme_controller_start, esi
@ -981,15 +982,15 @@ proc nvme_init stdcall, pci:dword
stdcall nvme_identify, [pci], 0, eax, CNS_IDCS stdcall nvme_identify, [pci], 0, eax, CNS_IDCS
mov eax, dword [edi + IDENTC.nn] mov eax, dword [edi + IDENTC.nn]
mov dword [esi + pcidev.nn], eax mov dword [esi + pcidev.nn], eax
DEBUGF DBG_INFO, "nvme%u: Namespace Count: %u\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Namespace Count: %u\n", [esi + pcidev.num], eax
lea ebx, byte [edi + IDENTC.sn] lea ebx, byte [edi + IDENTC.sn]
lea eax, byte [esi + pcidev.serial] lea eax, byte [esi + pcidev.serial]
stdcall memcpy, eax, ebx, 20 stdcall memcpy, eax, ebx, 20
DEBUGF DBG_INFO, "nvme%u: Serial Number: %s\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Serial Number: %s\n", [esi + pcidev.num], eax
add ebx, 20 add ebx, 20
lea eax, byte [esi + pcidev.model] lea eax, byte [esi + pcidev.model]
stdcall memcpy, eax, ebx, 40 stdcall memcpy, eax, ebx, 40
DEBUGF DBG_INFO, "nvme%u: Model: %s\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Model: %s\n", [esi + pcidev.num], eax
mov edx, dword [esi + pcidev.version] mov edx, dword [esi + pcidev.version]
cmp edx, VS140 cmp edx, VS140
@ -998,7 +999,7 @@ proc nvme_init stdcall, pci:dword
mov al, byte [edi + IDENTC.cntrltype] mov al, byte [edi + IDENTC.cntrltype]
cmp al, CNTRLTYPE_IO_CONTROLLER cmp al, CNTRLTYPE_IO_CONTROLLER
jne .exit_fail jne .exit_fail
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 ; TODO: check IDENTC.AVSCC
@ -1019,7 +1020,7 @@ proc nvme_init stdcall, pci:dword
mov esi, dword [esi + NVM_QUEUE_ENTRY.cq_ptr] mov esi, dword [esi + NVM_QUEUE_ENTRY.cq_ptr]
mov eax, dword [esi + sizeof.CQ_ENTRY + CQ_ENTRY.cdw0] mov eax, dword [esi + sizeof.CQ_ENTRY + CQ_ENTRY.cdw0]
if __DEBUG__ if __DEBUG__
DEBUGF DBG_INFO, "nvme%u: Set Features CDW0: 0x%x\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Set Features CDW0: 0x%x\n", [esi + pcidev.num], eax
end if end if
test ax, ax ; Number of I/O Submission Queues allocated test ax, ax ; Number of I/O Submission Queues allocated
jz .exit_fail jz .exit_fail
@ -1036,11 +1037,11 @@ proc nvme_init stdcall, pci:dword
mov eax, dword [esi + NVM_QUEUE_ENTRY.cq_ptr] mov eax, dword [esi + NVM_QUEUE_ENTRY.cq_ptr]
invoke GetPhysAddr invoke GetPhysAddr
stdcall create_io_completion_queue, [pci], eax, 1, IEN_ON stdcall create_io_completion_queue, [pci], eax, 1, IEN_ON
DEBUGF DBG_INFO, "nvme%u: Successfully created I/O completion queue 1\n", [edi + pcidev.num] ;DEBUGF DBG_INFO, "nvme%u: Successfully created I/O completion queue 1\n", [edi + pcidev.num]
mov eax, dword [esi + NVM_QUEUE_ENTRY.sq_ptr] mov eax, dword [esi + NVM_QUEUE_ENTRY.sq_ptr]
invoke GetPhysAddr invoke GetPhysAddr
stdcall create_io_submission_queue, [pci], eax, 1, 1 stdcall create_io_submission_queue, [pci], eax, 1, 1
DEBUGF DBG_INFO, "nvme%u: Successfully created I/O submission queue 1\n", [edi + pcidev.num] ;DEBUGF DBG_INFO, "nvme%u: Successfully created I/O submission queue 1\n", [edi + pcidev.num]
if 1 if 1
stdcall determine_active_nsids, [pci] stdcall determine_active_nsids, [pci]
@ -1048,7 +1049,7 @@ proc nvme_init stdcall, pci:dword
jz .exit_fail ; No active NSIDS jz .exit_fail ; No active NSIDS
mov esi, [pci] mov esi, [pci]
mov dword [esi + pcidev.nsid], eax mov dword [esi + pcidev.nsid], eax
DEBUGF DBG_INFO, "nvme%u: Found active NSID: %u\n", [esi + pcidev.num], eax ;DEBUGF DBG_INFO, "nvme%u: Found active NSID: %u\n", [esi + pcidev.num], eax
else else
mov esi, [pci] mov esi, [pci]
xor eax, eax xor eax, eax
@ -1069,7 +1070,7 @@ proc nvme_init stdcall, pci:dword
mov dword [esi + pcidev.nsinfo], eax mov dword [esi + pcidev.nsinfo], eax
mov al, byte [edi + IDENTN.nsfeat] mov al, byte [edi + IDENTN.nsfeat]
mov byte [ebx + NSINFO.features], al mov byte [ebx + NSINFO.features], al
DEBUGF DBG_INFO, "nvme%un%u: Namespace Features: 0x%x\n", [esi + pcidev.num], [esi + pcidev.nsid], al ;DEBUGF DBG_INFO, "nvme%un%u: Namespace Features: 0x%x\n", [esi + pcidev.num], [esi + pcidev.nsid], al
mov dword [ebx + NSINFO.pci], esi mov dword [ebx + NSINFO.pci], esi
mov eax, dword [edi + IDENTN.nsze] mov eax, dword [edi + IDENTN.nsze]
mov dword [ebx + NSINFO.size], eax mov dword [ebx + NSINFO.size], eax
@ -1079,13 +1080,19 @@ proc nvme_init stdcall, pci:dword
mov dword [ebx + NSINFO.capacity], eax mov dword [ebx + NSINFO.capacity], eax
mov eax, dword [edi + IDENTN.ncap + 4] mov eax, dword [edi + IDENTN.ncap + 4]
mov dword [ebx + NSINFO.capacity + 4], eax mov dword [ebx + NSINFO.capacity + 4], eax
DEBUGF DBG_INFO, "nvme%un%u: Namespace Size: %u + %u logical blocks\n", [esi + pcidev.num], [esi + pcidev.nsid], [edi + IDENTN.nsze], [edi + IDENTN.nsze + 4] ;DEBUGF DBG_INFO, "nvme%un%u: Namespace Size: %u + %u logical blocks\n", [esi + pcidev.num], [esi + pcidev.nsid], [edi + IDENTN.nsze], [edi + IDENTN.nsze + 4]
DEBUGF DBG_INFO, "nvme%un%u: Namespace Capacity: %u + %u logical blocks\n", [esi + pcidev.num], [esi + pcidev.nsid], [edi + IDENTN.ncap], [edi + IDENTN.ncap + 4] ;DEBUGF DBG_INFO, "nvme%un%u: Namespace Capacity: %u + %u logical blocks\n", [esi + pcidev.num], [esi + pcidev.nsid], [edi + IDENTN.ncap], [edi + IDENTN.ncap + 4]
mov eax, dword [edi + IDENTN.lbaf0] mov eax, dword [edi + IDENTN.lbaf0]
shr eax, 16 ; Get LBADS shr eax, 16 ; Get LBADS
and eax, 0xff and eax, 0xff
stdcall pow2, eax stdcall pow2, eax
DEBUGF DBG_INFO, "nvme%un%u: Namespace LBA Data Size: %u\n", [esi + pcidev.num], [esi + pcidev.nsid], eax ;DEBUGF DBG_INFO, "nvme%un%u: Namespace LBA Data Size: %u\n", [esi + pcidev.num], [esi + pcidev.nsid], eax
; KolibriOS only supports a LBADS of 512, so if it's a higher value then we
; have to ignore this namespace
cmp eax, SUPPORTED_LBADS
jne .exit_fail
mov dword [ebx + NSINFO.lbads], eax mov dword [ebx + NSINFO.lbads], eax
mov ecx, PAGE_SIZE mov ecx, PAGE_SIZE
xchg eax, ecx xchg eax, ecx

View File

@ -24,6 +24,7 @@ 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 PAGE_SIZE = 4096 shl NVM_MPS
SUPPORTED_LBADS = 512 ; KolibriOS only supports LBADS of 512, later on we may remove this restriction
ADMIN_QUEUE = 0 ; Admin Queue ID ADMIN_QUEUE = 0 ; Admin Queue ID