mirror of
https://git.missingno.dev/kolibrios-nvme-driver/
synced 2024-12-22 22:08:47 +01:00
fix lots of nasty bugs!
This commit is contained in:
parent
e2e1e50490
commit
78af4fb996
@ -42,13 +42,13 @@ proc START c, reason:dword
|
||||
test eax, eax
|
||||
jz .err
|
||||
xor ecx, ecx
|
||||
mov ebx, eax
|
||||
|
||||
.loop:
|
||||
stdcall device_is_compat, dword [ebx + ecx * sizeof.pcidev]
|
||||
mov ebx, dword [p_nvme_devices]
|
||||
stdcall device_is_compat, ebx
|
||||
test eax, eax
|
||||
jz @f
|
||||
stdcall nvme_init, dword [ebx + ecx * sizeof.pcidev]
|
||||
stdcall nvme_init, ebx
|
||||
|
||||
@@:
|
||||
inc ecx
|
||||
@ -157,20 +157,23 @@ proc detect_nvme
|
||||
mov ebx, dword [p_nvme_devices]
|
||||
test ebx, ebx
|
||||
jnz @f
|
||||
invoke KernelAlloc, TOTAL_PCIDEVS_MALLOC_SZ
|
||||
invoke KernelAlloc, sizeof.pcidev
|
||||
test eax, eax
|
||||
jz .err_no_mem
|
||||
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]
|
||||
dec ecx
|
||||
pop eax
|
||||
mov ebx, dword [p_nvme_devices]
|
||||
|
||||
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]
|
||||
mov byte [ebx + ecx * sizeof.pcidev + pcidev.devfn], dl
|
||||
mov byte [ebx + pcidev.devfn], dl
|
||||
|
||||
pop edx
|
||||
jmp .next_dev
|
||||
|
||||
@ -188,44 +191,30 @@ endp
|
||||
|
||||
proc device_is_compat stdcall, pci:dword
|
||||
|
||||
push ebx
|
||||
invoke PciRead32, dword [pci + pcidev.bus], dword [pci + pcidev.devfn], PCI_header00.base_addr_0
|
||||
push ebx
|
||||
mov ebx, [pci]
|
||||
invoke PciRead32, dword [ebx + pcidev.bus], dword [ebx + pcidev.devfn], PCI_header00.base_addr_0
|
||||
and eax, 0xfffffff0
|
||||
test eax, eax
|
||||
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
|
||||
jz .failure
|
||||
mov dword [pci + pcidev.mmio_ptr], eax
|
||||
mov ebx, dword [eax + NVME_REG_MAP.VS]
|
||||
|
||||
if __DEBUG__
|
||||
push ecx
|
||||
mov ecx, 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
|
||||
|
||||
DEBUGF DBG_INFO, "(NVMe) MMIO allocated at: 0x%x\n", eax
|
||||
mov ebx, [pci]
|
||||
mov dword [ebx + pcidev.mmio_ptr], eax
|
||||
mov eax, dword [eax + NVME_MMIO.VS]
|
||||
DEBUGF DBG_INFO, "(NVMe) controller version: 0x%x\n", eax
|
||||
pop ebx
|
||||
xor eax, eax
|
||||
inc eax
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
.unsupported:
|
||||
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): unsupported controller version\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
|
||||
|
||||
.failure:
|
||||
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): something went wrong checking NVMe device compatibility\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
|
||||
xor eax, eax
|
||||
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): something went wrong checking NVMe device compatibility\n", byte [ebx + pcidev.bus], byte [ebx + pcidev.devfn]
|
||||
pop ebx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
endp
|
||||
@ -233,81 +222,69 @@ endp
|
||||
; nvme_init: Initializes the NVMe controller
|
||||
proc nvme_init stdcall, pci:dword
|
||||
|
||||
push ebx ecx
|
||||
mov eax, dword [pci + pcidev.mmio_ptr]
|
||||
mov bx, word [eax + NVME_REG_MAP.CAP]
|
||||
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe maximum queue entries supported: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], bx
|
||||
push ebx
|
||||
mov eax, dword [pci]
|
||||
mov eax, dword [eax + pcidev.mmio_ptr]
|
||||
mov ebx, dword [eax + NVME_MMIO.CAP]
|
||||
test ebx, CAP_CQR
|
||||
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:
|
||||
; 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.
|
||||
mov ebx, dword [eax + NVME_REG_MAP.CAP + 4]
|
||||
mov ebx, dword [eax + NVME_MMIO.CAP + 4]
|
||||
test ebx, CAP_CSS_NVM_CMDSET
|
||||
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
|
||||
mov ebx, dword [eax + NVME_REG_MAP.CC]
|
||||
stdcall nvme_controller_reset, [pci]
|
||||
stdcall nvme_controller_reset, [pci]
|
||||
|
||||
xor eax, eax
|
||||
inc eax
|
||||
pop ecx ebx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
.exit_fail:
|
||||
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): failed to initialize NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
|
||||
xor eax, eax
|
||||
pop ecx ebx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
proc nvme_controller_reset stdcall, pci:dword
|
||||
|
||||
DEBUGF DBG_INFO, "(NVMe) Resetting Controller...\n"
|
||||
push ebx
|
||||
PDEBUGF DBG_INFO, "PCI(%u.%u.%u): Resetting NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn]
|
||||
mov eax, dword [pci + pcidev.mmio_ptr]
|
||||
mov ebx, dword [eax + NVME_REG_MAP.CSTS]
|
||||
mov ebx, dword [pci]
|
||||
mov ebx, dword [ebx + pcidev.mmio_ptr]
|
||||
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:
|
||||
test ebx, CSTS_RDY
|
||||
mov eax, dword [ebx + NVME_MMIO.CSTS]
|
||||
test eax, CSTS_RDY
|
||||
jnz .wait
|
||||
mov ebx, dword [eax + NVME_REG_MAP.CC]
|
||||
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]
|
||||
DEBUGF DBG_INFO, "(NVMe) Successfully reset controller...\n"
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Should be called only after the value of CC.EN has changed
|
||||
proc nvme_wait stdcall, pci:dword
|
||||
|
||||
push esi
|
||||
mov eax, dword [pci + pcidev.mmio_ptr]
|
||||
mov eax, dword [eax + NVME_REG_MAP.CAP]
|
||||
mov eax, [pci]
|
||||
mov eax, [eax + pcidev.mmio_ptr]
|
||||
mov eax, dword [eax + NVME_MMIO.CAP]
|
||||
and eax, CAP_TO
|
||||
shr eax, 24
|
||||
DEBUGF DBG_INFO, "CSTS.TO = %u\n", eax
|
||||
mov esi, eax
|
||||
;imul esi, 500
|
||||
;invoke Sleep
|
||||
pop esi
|
||||
imul esi, 50
|
||||
invoke Sleep
|
||||
ret
|
||||
|
||||
endp
|
||||
@ -316,17 +293,17 @@ proc nvme_cleanup
|
||||
|
||||
DEBUGF DBG_INFO, "(NVMe): Cleaning up...\n"
|
||||
push ecx
|
||||
xor ecx, ecx
|
||||
mov eax, dword [p_nvme_devices]
|
||||
mov ecx, eax
|
||||
test eax, eax
|
||||
jnz .loop
|
||||
ret
|
||||
|
||||
.loop:
|
||||
;invoke KernelFree, dword [p_nvme_devices + ecx * sizeof.pcidev + pcidev.ident_ptr]
|
||||
inc ecx
|
||||
cmp ecx, dword [pcidevs_len]
|
||||
jne .loop
|
||||
dec ecx
|
||||
test ecx, ecx
|
||||
jnz .loop
|
||||
invoke KernelFree, dword [p_nvme_devices]
|
||||
pop ecx
|
||||
ret
|
||||
|
@ -163,41 +163,41 @@ CSTS_SHST = (1 shl 2) or (1 shl 3)
|
||||
CSTS_NSSRO = 1 shl 4
|
||||
CSTS_PP = 1 shl 5
|
||||
|
||||
struct NVME_REG_MAP
|
||||
CAP rq 1 ; Controller Capabilities
|
||||
VS rd 1 ; Version
|
||||
INTMS rd 1 ; Interrupt Mask Set
|
||||
INTMC rd 1 ; Interrupt Mask Clear
|
||||
CC rd 1 ; Controller Configuration
|
||||
rd 1 ; Reserved
|
||||
CSTS rd 1 ; Controller Status
|
||||
NSSR rd 1 ; NVM Subsystem Reset
|
||||
AQA rd 1 ; Admin Queue Attributes
|
||||
ASQ rq 1 ; Admin Submission Queue Base Address
|
||||
ACQ rq 1 ; Admin Completion Queue Base Address
|
||||
CMBLOC rd 1 ; Controller Memory Buffer Location
|
||||
struct NVME_MMIO
|
||||
CAP dq ? ; Controller Capabilities
|
||||
VS dd ? ; Version
|
||||
INTMS dd ? ; Interrupt Mask Set
|
||||
INTMC dd ? ; Interrupt Mask Clear
|
||||
CC dd ? ; Controller Configuration
|
||||
dd ? ; Reserved
|
||||
CSTS dd ? ; Controller Status
|
||||
NSSR dd ? ; NVM Subsystem Reset
|
||||
AQA dd ? ; Admin Queue Attributes
|
||||
ASQ dq ? ; Admin Submission Queue Base Address
|
||||
ACQ dq ? ; Admin Completion Queue Base Address
|
||||
CMBLOC dd ? ; Controller Memory Buffer Location
|
||||
ends
|
||||
|
||||
; Submission Queue Entry (64 bytes)
|
||||
struct SQ_ENTRY
|
||||
cdw0 rd 1
|
||||
nsid rd 1
|
||||
cdw2 rd 1
|
||||
cdw3 rd 1
|
||||
mptr rq 1
|
||||
dptr rq 1
|
||||
cdw10 rd 1
|
||||
cdw11 rd 1
|
||||
cdw12 rd 1
|
||||
cdw13 rd 1
|
||||
cdw14 rd 1
|
||||
cdw15 rd 1
|
||||
cdw0 dd ?
|
||||
nsid dd ?
|
||||
cdw2 dd ?
|
||||
cdw3 dd ?
|
||||
mptr dq ?
|
||||
dptr dq ?
|
||||
cdw10 dd ?
|
||||
cdw11 dd ?
|
||||
cdw12 dd ?
|
||||
cdw13 dd ?
|
||||
cdw14 dd ?
|
||||
cdw15 dd ?
|
||||
ends
|
||||
|
||||
; Completion Queue Entry (16 bytes)
|
||||
struct CQ_ENTRY
|
||||
cdw0 dd ?
|
||||
dd ? ; reserved
|
||||
rd 1 ; reserved
|
||||
sqhd dw ?
|
||||
sqid dw ?
|
||||
cid dw ?
|
||||
@ -207,7 +207,7 @@ ends
|
||||
struct pcidev
|
||||
bus db ?
|
||||
devfn db ?
|
||||
dw ?
|
||||
rw 1
|
||||
mmio_ptr dd ?
|
||||
ends
|
||||
TOTAL_PCIDEVS = 4
|
||||
|
Loading…
Reference in New Issue
Block a user