From bc11bcfa37399c176f200d9cfe7d5af833f0e728 Mon Sep 17 00:00:00 2001 From: ramenu Date: Mon, 1 Apr 2024 19:47:14 -0400 Subject: [PATCH] more refactoring --- drivers/nvme/nvme.asm | 55 ++++++++++++++++++++++++++-------- drivers/nvme/nvme.inc | 68 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 97 insertions(+), 26 deletions(-) diff --git a/drivers/nvme/nvme.asm b/drivers/nvme/nvme.asm index f01e28d..84b2150 100644 --- a/drivers/nvme/nvme.asm +++ b/drivers/nvme/nvme.asm @@ -69,16 +69,13 @@ proc memset stdcall, p_data:dword, val:byte, sz:dword @@: mov byte [p_data + eax], bh inc eax - cmp eax, dword [sz] - jne @b + test eax, dword [sz] + jnz @b ret endp ; Submit a Command in the Admin Submission Queue proc submit_asq stdcall, p_sq:dword - mov ebx, dword [bar0] - add ebx, NVME_REG_ASQ - xor eax, eax ret endp @@ -90,8 +87,8 @@ proc nvme_identify stdcall, nsid:dword, dptr:dword, cns:byte mov [esp + SQ_ENTRY.nsid], eax mov eax, dword [dptr] mov dword [esp + SQ_ENTRY.dptr], eax - ; TODO: setting CID to 1 for now but later on keep a list of unique list of identifiers - mov dword [esp + SQ_ENTRY.cdw0], ADM_CMD_IDENTIFY or (1 shl 16) + ; TODO: setting CID to 0 for now but later on keep a list of unique list of identifiers + mov dword [esp + SQ_ENTRY.cdw0], ADM_CMD_IDENTIFY mov ah, byte [cns] mov byte [esp + SQ_ENTRY.cdw10], ah stdcall submit_asq, esp @@ -144,14 +141,44 @@ proc detect ; read BAR0 invoke PciRead32, [pcidev_bus], [pcidev_devfn], PCI_header00.base_addr_0 - mov [bar0], eax + and eax, 0xfffffff0 + test eax, eax + jz .no_mmio + invoke MapIoMem, eax, sizeof.NVME_REG_MAP, PG_SW+PG_NOCACHE + test eax, eax + jz .no_mmio + mov [p_mmap], eax + mov ebx, dword [eax + NVME_REG_MAP.CAP] + DEBUGF DBG_INFO,"(NVMe) Maximum queue entries supported: %u\n", bx + test ebx, CAP_CQR + jz .cqr_not_req + DEBUGF DBG_INFO,"(NVMe) Contiguous queues required\n" +.cqr_not_req: + mov ebx, dword [eax + NVME_REG_MAP.CAP + 4] + mov ecx, ebx + test ebx, CAP_CSS_NVM_CMDSET + jz .exit_fail + and ebx, CAP_MPSMIN + and ecx, CAP_MPSMAX + shr ebx, 16 + shr ecx, 16 + DEBUGF DBG_INFO,"(NVMe) Memory page size minimum: %u\n", ebx + DEBUGF DBG_INFO,"(NVMe) Memory page size maximum: %u\n", ecx - invoke Kmalloc, sizeof.NVME_IDENT_CONTROLLER + mov ebx, dword [eax + NVME_REG_MAP.CC] + mov ecx, ebx + and ebx, CC_IOSQES + and ecx, CC_IOCQES + shl ebx, 16 + shl ecx, 16 + DEBUGF DBG_INFO,"(NVMe) I/O Submission Queue Entry Size: %u\n", ebx + DEBUGF DBG_INFO,"(NVMe) I/O completion queue entry size: %u\n", ecx + ; Initialize the controller + + invoke KernelAlloc, sizeof.NVME_IDENT_CONTROLLER test eax, eax jz .alloc_ident_controller_fail - DEBUGF DBG_INFO,"Successfully allocated %u bytes for 'NVME_IDENT_CONTROLLER'\n",sizeof.NVME_IDENT_CONTROLLER mov [p_ident], eax - stdcall nvme_identify, 0, dword [p_ident], CNS_IDCS mov ecx, dword [p_ident] mov edx, dword [ecx + NVME_IDENT_CONTROLLER.tnvmcap] @@ -167,6 +194,10 @@ proc detect .alloc_ident_controller_fail: DEBUGF DBG_INFO,"ERROR: failed to allocate %u bytes for 'NVME_IDENT_CONTROLLER'\n", sizeof.NVME_IDENT_CONTROLLER + jmp .exit_fail +.no_mmio: + DEBUGF DBG_INFO,"ERROR: NVMe Device has no MMIO\n" +.exit_fail: pop eax pop ebx xor eax, eax @@ -186,7 +217,7 @@ endp align 4 pcidev_bus dd ? pcidev_devfn dd ? -bar0 dd ? +p_mmap dd ? p_ident dd ? ;all initialized data place here diff --git a/drivers/nvme/nvme.inc b/drivers/nvme/nvme.inc index 8cc9e05..1b96096 100644 --- a/drivers/nvme/nvme.inc +++ b/drivers/nvme/nvme.inc @@ -8,20 +8,6 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; NVMe Registers -NVME_REG_CAP = 0x0 ; Controller Capabilities -NVME_REG_VS = 0x8 ; Version -NVME_REG_INTMS = 0xC ; Interrupt Mask Set -NVME_REG_INTMC = 0xF ; Interrupt Mask Clear -NVME_REG_CC = 0x14 ; Controller Configuration -NVME_REG_CSTS = 0x1C ; Controller Status -NVME_REG_NSSR = 0x20 ; NVM Subsystem Reset -NVME_REG_AQA = 0x24 ; Admin Queue Attributes -NVME_REG_ASQ = 0x28 ; Admin Submission Queue Base Address -NVME_REG_ACQ = 0x30 ; Admin Completion Queue Base Address -NVME_REG_CMBLOC = 0x38 ; Controller Memory Buffer Location - - ; Opcodes for NVM commands NVM_CMD_FLUSH = 0x00 NVM_CMD_WRITE = 0x01 @@ -90,6 +76,58 @@ OACS_NSMAN_SUPPORTED = 1 shl 3 ; scope is all attached namespaces or all namespaces in NVM subsystem NSID_BROADCAST = 0xFFFFFFFF +NSSRC_RESET = 0x4E564D65 ; "NVMe" (initiates a NVMe subsystem reset) + +; NVMe Capabilities +CAP_MQES = 0xff +CAP_CQR = 1 shl 16 +CAP_AMS = (1 shl 17) or (1 shl 18) +CAP_TO = 0xff000000 +CAP_DSTRD = 1 or (1 shl 1) or (1 shl 2) or (1 shl 3) +CAP_NSSRS = 1 shl 4 +CAP_CSS_NVM_CMDSET = 1 shl 5 +CAP_CSS_OMCS = 1 shl 11 +CAP_CSS_NOIO = 1 shl 12 +CAP_BPS = 1 shl 14 +CAP_CPS_COSCOP = 1 shl 15 +CAP_CPS_DOSCOP = 1 shl 16 +CAP_CPS_NVMSCOP = CAP_CPS_COSCOP or CAP_CPS_DOSCOP +CAP_MPSMIN = (1 shl 17) or (1 shl 18) or (1 shl 19) or (1 shl 20) +CAP_MPSMAX = (1 shl 21) or (1 shl 22) or (1 shl 23) or (1 shl 24) +CAP_PMRS = 1 shl 25 +CAP_CMBS = 1 shl 26 +CAP_NSSS = 1 shl 27 +CAP_CRMS_CRWMS = 1 shl 28 +CAP_CRMS_CRIMS = 1 shl 29 + +; Controller Configuration Bits +CC_ENABLE = 1 +CC_CSS = (1 shl 4) or (1 shl 5) or (1 shl 6) +CC_MPS = (1 shl 7) or (1 shl 8) or (1 shl 9) or (1 shl 10) +CC_AMS = (1 shl 11) or (1 shl 12) or (1 shl 13) +CC_SHN = (1 shl 14) or (1 shl 15) +CC_IOSQES = (1 shl 16) or (1 shl 17) or (1 shl 18) or (1 shl 19) +CC_IOCQES = (1 shl 20) or (1 shl 21) or (1 shl 22) or (1 shl 23) +CC_CRIME = 1 shl 24 + +CC_DEFAULT_IOSQES = 6 shl 16 +CC_DEFAULT_IOCQES = 4 shl 16 + +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 +ends + ; Submission Queue Entry (64 bytes) struct SQ_ENTRY cdw0 rd 1 @@ -106,6 +144,8 @@ struct SQ_ENTRY cdw15 rd 1 ends +; Completion Queue Entry () + struc nvme_dev { .pci_bus dd ? .pci_devfn dd ?