From 7e71c33f3f19e945a38ab5bcdbfe3531febfc84e Mon Sep 17 00:00:00 2001 From: Abdur-Rahman Mansoor Date: Sun, 21 Jul 2024 14:14:04 -0400 Subject: [PATCH] fix: nvme_readwrite and build_prp_list This fixes the number of PRPs calculation before build_prp_list is invoked. It also accounts for the fact that the NLB field in the NVMe I/O read and write commands is a 0-based value, unlike numsectors. start_sector is also converted into the appropriate LBA number as it should be before sending the I/O command. --- drivers/nvme/nvme.asm | 56 ++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/nvme/nvme.asm b/drivers/nvme/nvme.asm index e7547a9..bc16673 100644 --- a/drivers/nvme/nvme.asm +++ b/drivers/nvme/nvme.asm @@ -621,18 +621,17 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword, prp_list_pt mov ecx, dword [esi + NSINFO.pg_sectors] xor edx, edx div ecx - test edx, edx - jz @f - inc eax + ;test edx, edx + ;jz @f + ;inc eax @@: - mov eax, [buf] - and eax, not (PAGE_SIZE - 1) - add eax, PAGE_SIZE - stdcall build_prp_list, edx, eax, [prp_list_ptr] + mov edx, [buf] + and edx, not (PAGE_SIZE - 1) + add edx, PAGE_SIZE + stdcall build_prp_list, eax, edx, [prp_list_ptr] test eax, eax jz .err - DEBUGF DBG_INFO, "Successfully allocated PRP list at: %x\n", eax mov dword [edi + 4], eax jmp .success @@ -669,16 +668,8 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors ; [esp + 16] - virtual pointer to PRP2 PRP list (if allocated, 0 if not) mov ebx, esp - ; its important to do a memset here as otherwise a PRP offset error will - ; probably occur. - mov eax, [numsectors_ptr] - mov eax, dword [eax] mov esi, [ns] mov edi, [buf] - mov ecx, dword [esi + NSINFO.lbads] - imul ecx, eax - shr ecx, 2 - stdcall memsetdz, edi, ecx mov eax, [numsectors_ptr] mov eax, dword [eax] @@ -697,14 +688,28 @@ proc nvme_readwrite stdcall, ns:dword, buf:dword, start_sector:qword, numsectors jz .dptr_fail DEBUGF DBG_INFO, "PRP1: %x, PRP2: %x\n", [ebx], [ebx + 4] + + mov eax, dword [start_sector] + mov ecx, dword [esi + NSINFO.lbads] + xor edx, edx + div ecx + DEBUGF DBG_INFO, "sector start: %u\n", eax + + ; According to the NVMe specification, the NLB field in the I/O read and write + ; commands is a 0-based value (i.e., 0 is equivalant to 1, 1 is equivalant to 2, ...) + ; As far as I know, KolibriOS doesn't follow this mechanism so let's just decrement the + ; value and it should have the same effect. + mov ecx, dword [ebx + 12] + dec ecx + stdcall nvme_io_rw, [esi + NSINFO.pci], \ 1, \ [esi + NSINFO.nsid], \ dword [ebx], \ dword [ebx + 4], \ - dword [start_sector], \ + eax, \ dword [start_sector + 4], \ - dword [ebx + 12], \ + ecx, \ dword [ebx + 8] ; assume command completes successfully for now @@ -1114,23 +1119,20 @@ proc nvme_init stdcall, pci:dword div ecx mov dword [ebx + NSINFO.pg_sectors], eax invoke KernelFree, edi - if 0 + if 1 invoke KernelAlloc, 0x4000 test eax, eax jz .exit_fail mov edi, eax - stdcall memsetdz, edi, 0x4000 / 4 invoke KernelAlloc, 0x8 test eax, eax jz .exit_fail mov edx, NVM_CMD_READ - mov dword [eax], 17 - ;add edi, 4094 - stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0, 0, eax - test eax, eax - jz .exit_fail - add edi, PAGE_SIZE + mov dword [eax], 23 + stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0x1000, 0, eax DEBUGF DBG_INFO, "STRING: %s\n", edi + add edi, 0x1fe0 + DEBUGF DBG_INFO, "STRING: %s\n", edi end if DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num] xor eax, eax @@ -1477,7 +1479,7 @@ align 4 dd 0 ; no close function dd 0 ; no closemedia function dd nvme_query_media - dd nvme_read + dd 0 dd 0 ; no write function (for now) dd 0 ; no flush function dd 0 ; use default cache size