2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-01-08 22:16:13 +01:00

fix lots of nasty bugs!

This commit is contained in:
Abdur-Rahman Mansoor 2024-05-25 18:56:58 -04:00
parent e2e1e50490
commit 78af4fb996
2 changed files with 77 additions and 100 deletions

View File

@ -42,13 +42,13 @@ proc START c, reason:dword
test eax, eax test eax, eax
jz .err jz .err
xor ecx, ecx xor ecx, ecx
mov ebx, eax
.loop: .loop:
stdcall device_is_compat, dword [ebx + ecx * sizeof.pcidev] mov ebx, dword [p_nvme_devices]
stdcall device_is_compat, ebx
test eax, eax test eax, eax
jz @f jz @f
stdcall nvme_init, dword [ebx + ecx * sizeof.pcidev] stdcall nvme_init, ebx
@@: @@:
inc ecx inc ecx
@ -157,20 +157,23 @@ proc detect_nvme
mov ebx, dword [p_nvme_devices] mov ebx, dword [p_nvme_devices]
test ebx, ebx test ebx, ebx
jnz @f jnz @f
invoke KernelAlloc, TOTAL_PCIDEVS_MALLOC_SZ invoke KernelAlloc, sizeof.pcidev
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]
@@: @@:
mov ebx, dword [p_nvme_devices]
mov ecx, dword [pcidevs_len] mov ecx, dword [pcidevs_len]
dec ecx dec ecx
pop eax pop eax
mov ebx, dword [p_nvme_devices]
movzx edx, byte [eax + PCIDEV.bus] movzx edx, byte [eax + PCIDEV.bus]
mov byte [ebx + ecx * sizeof.pcidev + pcidev.bus], dl mov byte [ebx + pcidev.bus], dl
movzx edx, byte [eax + PCIDEV.devfn] movzx edx, byte [eax + PCIDEV.devfn]
mov byte [ebx + ecx * sizeof.pcidev + pcidev.devfn], dl mov byte [ebx + pcidev.devfn], dl
pop edx pop edx
jmp .next_dev jmp .next_dev
@ -188,44 +191,30 @@ endp
proc device_is_compat stdcall, pci:dword proc device_is_compat stdcall, pci:dword
push ebx push ebx
invoke PciRead32, dword [pci + pcidev.bus], dword [pci + pcidev.devfn], PCI_header00.base_addr_0 mov ebx, [pci]
invoke PciRead32, dword [ebx + pcidev.bus], dword [ebx + pcidev.devfn], PCI_header00.base_addr_0
and eax, 0xfffffff0 and eax, 0xfffffff0
test eax, eax test eax, eax
jz .failure jz .failure
invoke MapIoMem, eax, sizeof.NVME_REG_MAP, PG_SW+PG_NOCACHE invoke MapIoMem, eax, sizeof.NVME_MMIO, PG_SW+PG_NOCACHE
test eax, eax test eax, eax
jz .failure jz .failure
mov dword [pci + pcidev.mmio_ptr], eax DEBUGF DBG_INFO, "(NVMe) MMIO allocated at: 0x%x\n", eax
mov ebx, dword [eax + NVME_REG_MAP.VS] mov ebx, [pci]
mov dword [ebx + pcidev.mmio_ptr], eax
if __DEBUG__ mov eax, dword [eax + NVME_MMIO.VS]
push ecx DEBUGF DBG_INFO, "(NVMe) controller version: 0x%x\n", eax
mov ecx, ebx pop ebx
shr ecx, 16
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe controller version: %u.%u.%u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ecx, bh, bl
pop ecx
end if
if 0
cmp ebx, NVM_SUPPORTED_CONTROLLER_VERSION
jne .unsupported
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe controller version is supported\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
end if
xor eax, eax xor eax, eax
inc eax inc eax
pop ebx
ret ret
.unsupported:
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): unsupported controller version\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
.failure: .failure:
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): something went wrong checking NVMe device compatibility\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] PDEBUGF DBG_INFO, "PCI(%u.%u.%u): something went wrong checking NVMe device compatibility\n", byte [ebx + pcidev.bus], byte [ebx + pcidev.devfn]
xor eax, eax
pop ebx pop ebx
xor eax, eax
ret ret
endp endp
@ -233,81 +222,69 @@ endp
; nvme_init: Initializes the NVMe controller ; nvme_init: Initializes the NVMe controller
proc nvme_init stdcall, pci:dword proc nvme_init stdcall, pci:dword
push ebx ecx push ebx
mov eax, dword [pci + pcidev.mmio_ptr] mov eax, dword [pci]
mov bx, word [eax + NVME_REG_MAP.CAP] mov eax, dword [eax + pcidev.mmio_ptr]
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe maximum queue entries supported: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], bx mov ebx, dword [eax + NVME_MMIO.CAP]
test ebx, CAP_CQR test ebx, CAP_CQR
jz .cqr_not_req jz .cqr_not_req
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe contiguous queues required\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
.cqr_not_req: .cqr_not_req:
; For some reason, bit 7 (No I/O command set supported) is also set to 1 despite bit 0 (NVM command set) ; For some reason, bit 7 (No I/O command set supported) is also set to 1 despite bit 0 (NVM command set)
; being set to 1.. so I am not sure if bit 7 should be checked at all.. investigate later. ; being set to 1.. so I am not sure if bit 7 should be checked at all.. investigate later.
mov ebx, dword [eax + NVME_REG_MAP.CAP + 4] mov ebx, dword [eax + NVME_MMIO.CAP + 4]
test ebx, CAP_CSS_NVM_CMDSET test ebx, CAP_CSS_NVM_CMDSET
jz .exit_fail jz .exit_fail
if __DEBUG__
mov ecx, ebx
and ebx, CAP_MPSMIN
and ecx, CAP_MPSMAX
shr ebx, 16
shr ecx, 16
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe memory page size minimum: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ebx
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe memory page size maximum: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ecx
end if
; Reset controller ; Reset controller
mov ebx, dword [eax + NVME_REG_MAP.CC] stdcall nvme_controller_reset, [pci]
stdcall nvme_controller_reset, [pci]
xor eax, eax xor eax, eax
inc eax inc eax
pop ecx ebx pop ebx
ret ret
.exit_fail: .exit_fail:
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): failed to initialize NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] PDEBUGF DBG_INFO, "PCI(%u.%u.%u): failed to initialize NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
xor eax, eax xor eax, eax
pop ecx ebx pop ebx
ret ret
endp endp
proc nvme_controller_reset stdcall, pci:dword proc nvme_controller_reset stdcall, pci:dword
DEBUGF DBG_INFO, "(NVMe) Resetting Controller...\n"
push ebx push ebx
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): Resetting NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] mov ebx, dword [pci]
mov eax, dword [pci + pcidev.mmio_ptr] mov ebx, dword [ebx + pcidev.mmio_ptr]
mov ebx, dword [eax + NVME_REG_MAP.CSTS] mov eax, dword [ebx + NVME_MMIO.CC]
and eax, 0xfffffffe ; CC.EN = 0
mov dword [ebx + NVME_MMIO.CC], eax
stdcall nvme_wait, [pci]
; Wait for controller to be brought to idle state, CSTS.RDY should be cleared to 0 when this happens ; Wait for controller to be brought to idle state, CSTS.RDY should be cleared to 0 when this happens
.wait: .wait:
test ebx, CSTS_RDY mov eax, dword [ebx + NVME_MMIO.CSTS]
test eax, CSTS_RDY
jnz .wait jnz .wait
mov ebx, dword [eax + NVME_REG_MAP.CC] DEBUGF DBG_INFO, "(NVMe) Successfully reset controller...\n"
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe.CC = 0x%x\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ebx
and ebx, 0xfffffffe
mov dword [eax + NVME_REG_MAP.CC], ebx
stdcall nvme_wait, [pci]
pop ebx pop ebx
ret ret
endp endp
; Should be called only after the value of CC.EN has changed
proc nvme_wait stdcall, pci:dword proc nvme_wait stdcall, pci:dword
push esi mov eax, [pci]
mov eax, dword [pci + pcidev.mmio_ptr] mov eax, [eax + pcidev.mmio_ptr]
mov eax, dword [eax + NVME_REG_MAP.CAP] mov eax, dword [eax + NVME_MMIO.CAP]
and eax, CAP_TO and eax, CAP_TO
shr eax, 24 shr eax, 24
DEBUGF DBG_INFO, "CSTS.TO = %u\n", eax
mov esi, eax mov esi, eax
;imul esi, 500 imul esi, 50
;invoke Sleep invoke Sleep
pop esi
ret ret
endp endp
@ -316,17 +293,17 @@ proc nvme_cleanup
DEBUGF DBG_INFO, "(NVMe): Cleaning up...\n" DEBUGF DBG_INFO, "(NVMe): Cleaning up...\n"
push ecx push ecx
xor ecx, ecx
mov eax, dword [p_nvme_devices] mov eax, dword [p_nvme_devices]
mov ecx, eax
test eax, eax test eax, eax
jnz .loop jnz .loop
ret ret
.loop: .loop:
;invoke KernelFree, dword [p_nvme_devices + ecx * sizeof.pcidev + pcidev.ident_ptr] ;invoke KernelFree, dword [p_nvme_devices + ecx * sizeof.pcidev + pcidev.ident_ptr]
inc ecx dec ecx
cmp ecx, dword [pcidevs_len] test ecx, ecx
jne .loop jnz .loop
invoke KernelFree, dword [p_nvme_devices] invoke KernelFree, dword [p_nvme_devices]
pop ecx pop ecx
ret ret

View File

@ -163,41 +163,41 @@ CSTS_SHST = (1 shl 2) or (1 shl 3)
CSTS_NSSRO = 1 shl 4 CSTS_NSSRO = 1 shl 4
CSTS_PP = 1 shl 5 CSTS_PP = 1 shl 5
struct NVME_REG_MAP struct NVME_MMIO
CAP rq 1 ; Controller Capabilities CAP dq ? ; Controller Capabilities
VS rd 1 ; Version VS dd ? ; Version
INTMS rd 1 ; Interrupt Mask Set INTMS dd ? ; Interrupt Mask Set
INTMC rd 1 ; Interrupt Mask Clear INTMC dd ? ; Interrupt Mask Clear
CC rd 1 ; Controller Configuration CC dd ? ; Controller Configuration
rd 1 ; Reserved dd ? ; Reserved
CSTS rd 1 ; Controller Status CSTS dd ? ; Controller Status
NSSR rd 1 ; NVM Subsystem Reset NSSR dd ? ; NVM Subsystem Reset
AQA rd 1 ; Admin Queue Attributes AQA dd ? ; Admin Queue Attributes
ASQ rq 1 ; Admin Submission Queue Base Address ASQ dq ? ; Admin Submission Queue Base Address
ACQ rq 1 ; Admin Completion Queue Base Address ACQ dq ? ; Admin Completion Queue Base Address
CMBLOC rd 1 ; Controller Memory Buffer Location CMBLOC dd ? ; Controller Memory Buffer Location
ends ends
; Submission Queue Entry (64 bytes) ; Submission Queue Entry (64 bytes)
struct SQ_ENTRY struct SQ_ENTRY
cdw0 rd 1 cdw0 dd ?
nsid rd 1 nsid dd ?
cdw2 rd 1 cdw2 dd ?
cdw3 rd 1 cdw3 dd ?
mptr rq 1 mptr dq ?
dptr rq 1 dptr dq ?
cdw10 rd 1 cdw10 dd ?
cdw11 rd 1 cdw11 dd ?
cdw12 rd 1 cdw12 dd ?
cdw13 rd 1 cdw13 dd ?
cdw14 rd 1 cdw14 dd ?
cdw15 rd 1 cdw15 dd ?
ends ends
; Completion Queue Entry (16 bytes) ; Completion Queue Entry (16 bytes)
struct CQ_ENTRY struct CQ_ENTRY
cdw0 dd ? cdw0 dd ?
dd ? ; reserved rd 1 ; reserved
sqhd dw ? sqhd dw ?
sqid dw ? sqid dw ?
cid dw ? cid dw ?
@ -207,7 +207,7 @@ ends
struct pcidev struct pcidev
bus db ? bus db ?
devfn db ? devfn db ?
dw ? rw 1
mmio_ptr dd ? mmio_ptr dd ?
ends ends
TOTAL_PCIDEVS = 4 TOTAL_PCIDEVS = 4