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:
parent
e2e1e50490
commit
78af4fb996
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user