2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2024-12-22 22:08:47 +01:00

wip: add interrupt handling code

This commit is contained in:
Abdur-Rahman Mansoor 2024-06-09 13:07:01 -04:00
parent 482d186c1a
commit dd3ebb1716

View File

@ -110,6 +110,7 @@ proc set_cdw0 stdcall, opcode:byte, cid:word
endp
; See pages 161-205 of the NVMe 1.4 specification for reference
proc nvme_identify stdcall, pci:dword, nsid:dword, dptr:dword, cid:word, cns:byte
push esi
@ -448,10 +449,10 @@ proc device_is_compat stdcall, pci:dword
and eax, CAP_DSTRD
; Stride is (2 ^ (2 + DSTRD)) bytes
add eax, 2
add al, 2
stdcall pow2, eax
mov ecx, eax
mov dword [esi + pcidev.dstrd], eax
mov byte [esi + pcidev.dstrd], al
; 1003h + ((2y + 1) * (4 << CAP.DSTRD))
mov eax, 4
@ -522,14 +523,6 @@ proc nvme_init stdcall, pci:dword
cmp eax, NVM_MPS
jl .exit_fail
; Check Interrupt Mask Set/Clear
if 0
mov eax, dword [edi + NVME_MMIO.INTMS]
DEBUGF DBG_INFO, "(NVMe) INTMS: %x\n", eax
mov eax, dword [edi + NVME_MMIO.INTMC]
DEBUGF DBG_INFO, "(NVMe) INTMC: %x\n", eax
end if
; Configure AMS, MPS, CSS
mov eax, dword [edi + NVME_MMIO.CC]
and eax, not (CC_AMS or CC_MPS or CC_CSS)
@ -573,9 +566,11 @@ proc nvme_init stdcall, pci:dword
; Restart the controller
stdcall nvme_controller_start, edi
invoke AllocPage
invoke KernelAlloc, 0x1000
test eax, eax
jz .exit_fail
mov dword [dptr], eax
invoke GetPhysAddr
; pci:dword, nsid:dword, dptr:dword, cid:word, cns:byte
stdcall nvme_identify, [pci], 0, eax, 0, CNS_IDCS
@ -643,21 +638,6 @@ proc nvme_wait stdcall, mmio:dword
endp
; Writes to completion queue 'y' head doorbell
proc cqyhdbl_write stdcall, mmio:dword, dstrd:byte, y:byte
; 1000h + ((2y + 1) * (4 << CAP.DSTRD))
xor ecx, ecx
shl ecx, [y]
inc ecx
mov eax, 4
shl eax, [dstrd]
imul eax, ecx
add eax, 0x1000
ret
endp
; Writes to submission queue 'y' tail doorbell
proc sqytdbl_write stdcall, pci:dword, y:byte, sqt:word
@ -684,6 +664,38 @@ proc sqytdbl_write stdcall, pci:dword, y:byte, sqt:word
endp
; Writes to completion queue 'y' head doorbell
proc cqyhdbl_write stdcall, pci:dword, y:byte, cqh:word
push esi
mov esi, [pci]
; 1000h + ((2y + 1) * (4 << CAP.DSTRD))
xor eax, eax
mov cl, [y]
shl eax, cl
inc eax
mov edx, 4
mov cl, byte [esi + pcidev.dstrd]
shl edx, cl
imul edx, eax
add edx, 0x1000
movzx eax, [cqh]
cmp ax, NVM_ACQS
jl @f
xor ax, ax
@@:
inc ax
mov esi, dword [esi + pcidev.io_addr]
;DEBUGF DBG_INFO, "(NVMe) Writing to CQ%uHDBL\n", edx
mov word [esi + edx], ax ; Write to CQyHDBL
pop esi
ret
endp
proc write_admin_cmd stdcall, pci:dword
push esi
@ -724,19 +736,37 @@ endp
proc irq_handler
push esi
push esi edi
mov esi, dword [p_nvme_devices]
mov esi, dword [esi + pcidev.cq_ptr]
mov ax, word [esi + CQ_ENTRY.sqid]
DEBUGF DBG_INFO, "SQID: %x\n", ax
mov ax, word [esi + CQ_ENTRY.sqhd]
DEBUGF DBG_INFO, "SQHD: %x\n", ax
mov ax, word [esi + CQ_ENTRY.status]
DEBUGF DBG_INFO, "Status: %x\n", ax
mov edi, esi
mov esi, dword [esi + pcidev.io_addr]
mov edi, dword [edi + pcidev.cq_ptr]
mov dword [esi + NVME_MMIO.INTMS], 0x1
mov eax, dword [edi + CQ_ENTRY.sqid]
DEBUGF DBG_INFO, "(NVMe) SQID: %u\n", eax
mov eax, dword [edi + CQ_ENTRY.status]
DEBUGF DBG_INFO, "(NVMe) Status: %x\n", eax
test al, al
jz @f
; error occurred
; Interrupt not handled by driver, return 0
; we have to initiate a controller reset if a admin command encounters
; a fatal error or if a completion is not received for a deletion
; of a submission or completion queue (section 10.1 - page 400 of NVMe 1.4 spec)
stdcall nvme_controller_reset, esi
stdcall nvme_controller_start, esi
jmp .exit
@@:
stdcall cqyhdbl_write, [p_nvme_devices], 0, 0x0
mov dword [esi + NVME_MMIO.INTMC], 0x1
.exit:
; Interrupt handled by driver, return 1
xor eax, eax
pop esi
inc eax
pop edi esi
ret
endp
@ -766,6 +796,7 @@ endp
align 4
p_nvme_devices dd 0
pcidevs_len dd 0
dptr dd ?
my_service db "NVMe",0 ;max 16 chars include zero
if __DEBUG__
include_debug_strings