diff --git a/drivers/nvme/nvme.asm b/drivers/nvme/nvme.asm index c3a9aac..2605365 100644 --- a/drivers/nvme/nvme.asm +++ b/drivers/nvme/nvme.asm @@ -891,7 +891,7 @@ proc nvme_init stdcall, pci:dword invoke PciRead8, dword [esi + pcidev.bus], dword [esi + pcidev.devfn], PCI_header00.cap_ptr and eax, 0xfc ; bottom two bits are reserved, so mask them before we access the configuration space mov edi, eax - DEBUGF DBG_INFO, "nvme%u: Checking capabilities: %x\n", [esi + pcidev.num], edi + DEBUGF DBG_INFO, "nvme%u: Checking capabilities...\n", [esi + pcidev.num] ; We need to check if there are any MSI/MSI-X capabilities, and if so, make sure they're disabled since ; we're using old fashioned pin-based interrupts (for now) @@ -905,6 +905,7 @@ proc nvme_init stdcall, pci:dword movzx edi, ah test edi, edi jnz .read_cap + DEBUGF DBG_INFO, "nvme%u: MSI/MSI-X capability not found\n", [esi + pcidev.num] jmp .end_cap_parse .got_msi_cap: @@ -943,12 +944,14 @@ proc nvme_init stdcall, pci:dword mov eax, dword [edi + NVME_MMIO.CAP + 4] test eax, CAP_CSS_NVM_CMDSET jz .exit_fail + DEBUGF DBG_INFO, "nvme%u: OK... NVM command set supported\n", [esi + pcidev.num] ; Reset controller before we configure it + test dword [edi + NVME_MMIO.CC], CC_EN + jz @f stdcall nvme_controller_reset, esi - if __DEBUG__ - ;stdcall nvme_wait, edi - end if + +@@: mov eax, dword [edi + NVME_MMIO.CAP + 4] and eax, CAP_MPSMIN shr eax, 16 @@ -959,6 +962,7 @@ proc nvme_init stdcall, pci:dword shr eax, 20 cmp eax, NVM_MPS jb .exit_fail + DEBUGF DBG_INFO, "nvme%u: OK... memory page size supported\n", [esi + pcidev.num] ; Configure IOSQES, IOCQES, AMS, MPS, CSS and dword [edi + NVME_MMIO.CC], not (CC_AMS or CC_MPS or CC_CSS or CC_IOSQES or CC_IOCQES) @@ -976,6 +980,7 @@ proc nvme_init stdcall, pci:dword and eax, not (AQA_ASQS or AQA_ACQS) or eax, NVM_ASQS or (NVM_ACQS shl 16) mov dword [edi + NVME_MMIO.AQA], eax + DEBUGF DBG_INFO, "nvme%u: Admin queue attributes: 0x%x\n", [esi + pcidev.num], eax ; Allocate list of queues invoke KernelAlloc, sizeof.NVM_QUEUE_ENTRY * (LAST_QUEUE_ID + 1) @@ -1014,22 +1019,30 @@ proc nvme_init stdcall, pci:dword mov esi, dword [esi + pcidev.io_addr] mov eax, dword [edi + NVM_QUEUE_ENTRY.sq_ptr] invoke GetPhysAddr + push esi + mov esi, [pci] + DEBUGF DBG_INFO, "nvme%u: Admin submission queue base address: 0x%x\n", [esi + pcidev.num], eax + pop esi mov dword [esi + NVME_MMIO.ASQ], eax mov dword [esi + NVME_MMIO.ASQ + 4], 0 mov eax, dword [edi + NVM_QUEUE_ENTRY.cq_ptr] invoke GetPhysAddr + push esi + mov esi, [pci] + DEBUGF DBG_INFO, "nvme%u: Admin completion queue base address: 0x%x\n", [esi + pcidev.num], eax + pop esi mov dword [esi + NVME_MMIO.ACQ], eax mov dword [esi + NVME_MMIO.ACQ + 4], 0 ; Attach interrupt handler mov esi, [pci] movzx eax, byte [esi + pcidev.iline] - ;DEBUGF DBG_INFO, "nvme%u: Attaching interrupt handler to IRQ %u\n", [esi + pcidev.num], eax + DEBUGF DBG_INFO, "nvme%u: Attaching interrupt handler to IRQ %u\n", [esi + pcidev.num], eax invoke AttachIntHandler, eax, irq_handler, 0 test eax, eax jz .exit_fail - ;DEBUGF DBG_INFO, "nvme%u: Successfully attached interrupt handler\n", [esi + pcidev.num] + DEBUGF DBG_INFO, "nvme%u: Successfully attached interrupt handler\n", [esi + pcidev.num] ; Restart the controller stdcall nvme_controller_start, esi @@ -1068,10 +1081,12 @@ proc nvme_init stdcall, pci:dword ; TODO: check IDENTC.AVSCC mov al, byte [edi + IDENTC.sqes] and al, 11110000b + DEBUGF DBG_INFO, "nvme%u: IDENTC.SQES = %u\n", [esi + pcidev.num], al cmp al, 0x60 ; maximum submission queue size should at least be 64 bytes jb .exit_fail mov al, byte [edi + IDENTC.cqes] and al, 11110000b + DEBUGF DBG_INFO, "nvme%u: IDENTC.CQES = %u\n", [esi + pcidev.num], al and al, 0x40 ; maximum completion queue entry size should at least be 16 bytes jb .exit_fail invoke KernelFree, edi @@ -1086,9 +1101,7 @@ proc nvme_init stdcall, pci:dword mov esi, dword [esi + pcidev.queue_entries] mov esi, dword [esi + NVM_QUEUE_ENTRY.cq_ptr] mov eax, dword [esi + sizeof.CQ_ENTRY + CQ_ENTRY.cdw0] - if __DEBUG__ ;DEBUGF DBG_INFO, "nvme%u: Set Features CDW0: 0x%x\n", [esi + pcidev.num], eax - end if test ax, ax ; Number of I/O Submission Queues allocated jz .exit_fail shl eax, 16 @@ -1186,10 +1199,15 @@ proc nvme_init stdcall, pci:dword ret .exit_fail: - if __DEBUG__ mov esi, [pci] - DEBUGF DBG_INFO, "nvme%u: failed to initialize controller\n", [esi + pcidev.num] - end if + DEBUGF DBG_INFO, "nvme%u: Failed to initialize controller\n", [esi + pcidev.num] + mov edi, dword [esi + pcidev.io_addr] + mov eax, dword [edi + NVME_MMIO.CSTS] + test eax, CSTS_CFS + jz @f + DEBUGF DBG_INFO, "nvme%u: A fatal controller error has occurred\n", [esi + pcidev.num] + +@@: xor eax, eax pop edi esi ebx ret @@ -1211,6 +1229,7 @@ endp proc nvme_controller_reset stdcall, pci:dword + ; TODO: Add timeout of CAP.TO seconds push esi edi mov esi, [pci] DEBUGF DBG_INFO, "nvme%u: Resetting Controller...\n", [esi + pcidev.num] @@ -1229,6 +1248,7 @@ endp proc nvme_controller_start stdcall, pci:dword + ; TODO: Add timeout of CAP.TO seconds push esi edi mov esi, [pci] DEBUGF DBG_INFO, "nvme%u: Starting Controller...\n", [esi + pcidev.num] @@ -1245,21 +1265,6 @@ proc nvme_controller_start stdcall, pci:dword endp -; Should be called only after the value of CC.EN has changed -proc nvme_wait stdcall, mmio:dword - - push esi - mov esi, [mmio] - mov esi, dword [esi + NVME_MMIO.CAP] - and esi, CAP_TO - shr esi, 24 - imul esi, 150 ; TODO: bad time delay, set to appropriate value later - invoke Sleep - pop esi - ret - -endp - proc nvme_poll xor ecx, ecx @@ -1353,6 +1358,7 @@ proc sqytdbl_write stdcall, pci:dword, y:word, cmd:dword shl edx, cl imul edx, ebx add edx, 0x1000 + ;DEBUGF DBG_INFO, "nvme%u: Writing to submission queue tail doorbell 0x%x: %u\n", [esi + pcidev.num], edx, ax mov esi, dword [esi + pcidev.io_addr] mov word [esi + edx], ax movzx ecx, [y]