diff --git a/drivers/nvme/nvme.asm b/drivers/nvme/nvme.asm index 648c444..aa5305d 100644 --- a/drivers/nvme/nvme.asm +++ b/drivers/nvme/nvme.asm @@ -540,21 +540,31 @@ proc nvme_init stdcall, pci:dword test eax, eax jz .exit_fail mov dword [esi + pcidev.sq_ptr], eax - DEBUGF DBG_INFO, "(NVMe) ASQ: Virtual Address: 0x%x\n", eax invoke GetPhysAddr - DEBUGF DBG_INFO, "(NVMe) ASQ: Physical Address: 0x%x\n", eax mov dword [edi + NVME_MMIO.ASQ], eax and dword [edi + NVME_MMIO.ASQ + 4], 0 invoke KernelAlloc, 0x1000 test eax, eax jz .exit_fail mov dword [esi + pcidev.cq_ptr], eax - DEBUGF DBG_INFO, "(NVMe) ACQ: Virtual Address: 0x%x\n", eax invoke GetPhysAddr - DEBUGF DBG_INFO, "(NVMe) ACQ: Physical Address: 0x%x\n", eax mov dword [edi + NVME_MMIO.ACQ], eax and dword [edi + NVME_MMIO.ACQ + 4], 0 + stdcall memset, dword [esi + pcidev.sq_ptr], 0, sizeof.SQ_ENTRY * NVM_ASQS + stdcall memset, dword [esi + pcidev.cq_ptr], 0, sizeof.CQ_ENTRY * NVM_ACQS + + ; Allocate list of queues + invoke KernelAlloc, sizeof.NVM_QUEUE * NVM_ASQS + test eax, eax + jz .exit_fail + mov dword [esi + pcidev.queue_ptr], eax + stdcall memset, eax, 0, sizeof.NVM_QUEUE * NVM_ASQS + + ; we want to disable all interrupts for now, since the controller randomly + ; generates interrupts while starting up + mov dword [edi + NVME_MMIO.INTMS], 0xffffffff + ; Attach interrupt handler movzx eax, byte [esi + pcidev.iline] DEBUGF DBG_INFO, "(NVMe) Attaching interrupt handler to IRQ %u\n", eax @@ -565,6 +575,7 @@ proc nvme_init stdcall, pci:dword ; Restart the controller stdcall nvme_controller_start, edi + mov dword [edi + NVME_MMIO.INTMC], 0xffffffff ; re-enable interrupts invoke KernelAlloc, 0x1000 test eax, eax @@ -631,7 +642,7 @@ proc nvme_wait stdcall, mmio:dword mov esi, dword [esi + NVME_MMIO.CAP] and esi, CAP_TO shr esi, 24 - imul esi, 50 + imul esi, 100 ; TODO: bad time delay, set to appropriate value later invoke Sleep pop esi ret @@ -656,7 +667,6 @@ proc sqytdbl_write stdcall, pci:dword, y:byte, sqt:word DEBUGF DBG_INFO, "(NVMe) Writing to submission queue 0x%x doorbell register\n", ebx mov esi, [esi + pcidev.io_addr] - DEBUGF DBG_INFO, "(NVMe) MMIO: %x\n", esi mov ax, [sqt] mov word [esi + ebx], ax ; Write to register pop esi ebx @@ -665,23 +675,24 @@ 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 +proc cqyhdbl_write stdcall, pci:dword, y:byte - push esi + push esi edi mov esi, [pci] ; 1000h + ((2y + 1) * (4 << CAP.DSTRD)) - xor eax, eax - mov cl, [y] - shl eax, cl - inc eax - mov edx, 4 + movzx eax, [y] + shl al, 1 + inc al + mov dx, 4 mov cl, byte [esi + pcidev.dstrd] - shl edx, cl - imul edx, eax - add edx, 0x1000 + shl dx, cl + imul dx, ax + add dx, 0x1000 - movzx eax, [cqh] + movzx ecx, [y] + mov edi, dword [esi + pcidev.queue_ptr] + mov ax, word [edi + ecx * sizeof.NVM_QUEUE + NVM_QUEUE.head] ; get head for completion queue Y cmp ax, NVM_ACQS jl @f xor ax, ax @@ -689,9 +700,10 @@ proc cqyhdbl_write stdcall, pci:dword, y:byte, cqh:word @@: inc ax mov esi, dword [esi + pcidev.io_addr] - ;DEBUGF DBG_INFO, "(NVMe) Writing to CQ%uHDBL\n", edx + DEBUGF DBG_INFO, "(NVMe) Writing to completion queue doorbell register 0x%x: %u\n", dx, ax mov word [esi + edx], ax ; Write to CQyHDBL - pop esi + mov word [edi + ecx * sizeof.NVM_QUEUE + NVM_QUEUE.head], ax + pop edi esi ret endp @@ -700,16 +712,18 @@ proc write_admin_cmd stdcall, pci:dword push esi mov esi, [pci] - mov ax, word [esi + pcidev.sq_adm_tail] + mov esi, dword [esi + pcidev.queue_ptr] + mov ax, word [esi + NVM_QUEUE.tail] cmp ax, NVM_ASQS jl @f xor ax, ax @@: - mov word [esi + pcidev.sq_adm_tail], ax + mov esi, [pci] mov esi, dword [esi + pcidev.io_addr] inc ax mov word [esi + 0x1000], ax + mov word [esi + NVM_QUEUE.tail], ax pop esi ret @@ -758,8 +772,8 @@ proc irq_handler jmp .exit @@: - stdcall cqyhdbl_write, [p_nvme_devices], 0, 0x0 mov dword [esi + NVME_MMIO.INTMC], 0x1 + stdcall cqyhdbl_write, [p_nvme_devices], 0 .exit: ; Interrupt handled by driver, return 1