2024-03-28 23:43:18 +01:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; ;;
|
2024-03-31 21:43:38 +02:00
|
|
|
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
2024-03-28 23:43:18 +01:00
|
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
|
|
;; ;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
;driver sceletone
|
|
|
|
|
|
|
|
format PE DLL native
|
|
|
|
entry START
|
|
|
|
|
|
|
|
API_VERSION equ 0 ;debug
|
|
|
|
SRV_GETVERSION equ 0
|
2024-03-30 04:42:01 +01:00
|
|
|
__DEBUG__ = 1
|
|
|
|
__DEBUG_LEVEL__ = 1
|
|
|
|
DRIVER_VERSION = 1
|
|
|
|
DBG_INFO = 1
|
|
|
|
|
2024-03-28 23:43:18 +01:00
|
|
|
section ".flat" code readable writable executable
|
|
|
|
include "../proc32.inc"
|
|
|
|
include "../struct.inc"
|
|
|
|
include "../macros.inc"
|
2024-03-30 04:42:01 +01:00
|
|
|
include "../fdo.inc"
|
2024-03-28 23:43:18 +01:00
|
|
|
include "../pci.inc"
|
2024-03-30 04:42:01 +01:00
|
|
|
include "../peimport.inc"
|
2024-03-31 21:43:38 +02:00
|
|
|
include "nvme.inc"
|
2024-03-28 23:43:18 +01:00
|
|
|
|
|
|
|
proc START c, reason:dword
|
|
|
|
cmp [reason], DRV_ENTRY
|
|
|
|
jne .exit
|
|
|
|
.entry:
|
|
|
|
push esi
|
2024-03-30 04:42:01 +01:00
|
|
|
DEBUGF DBG_INFO,"Detecting NVMe hardware...\n"
|
2024-03-28 23:43:18 +01:00
|
|
|
call detect
|
|
|
|
pop esi
|
|
|
|
test eax, eax
|
|
|
|
jz .exit
|
|
|
|
|
|
|
|
invoke RegService, my_service, service_proc
|
|
|
|
ret
|
|
|
|
.exit:
|
|
|
|
xor eax, eax
|
|
|
|
ret
|
|
|
|
endp
|
|
|
|
|
|
|
|
proc service_proc stdcall, ioctl:dword
|
|
|
|
|
|
|
|
mov ebx, [ioctl]
|
|
|
|
mov eax, [ebx+IOCTL.io_code]
|
|
|
|
cmp eax, SRV_GETVERSION
|
|
|
|
jne @F
|
|
|
|
|
|
|
|
mov eax, [ebx+IOCTL.output]
|
|
|
|
cmp [ebx+IOCTL.out_size], 4
|
|
|
|
jne .fail
|
|
|
|
mov dword [eax], API_VERSION
|
|
|
|
xor eax, eax
|
|
|
|
ret
|
|
|
|
@@:
|
|
|
|
.fail:
|
|
|
|
or eax, -1
|
|
|
|
ret
|
|
|
|
endp
|
|
|
|
|
2024-03-31 21:43:38 +02:00
|
|
|
proc memset stdcall, p_data:dword, val:byte, sz:dword
|
2024-03-31 22:13:17 +02:00
|
|
|
mov bh, byte [val]
|
|
|
|
xor eax, eax
|
2024-03-31 21:43:38 +02:00
|
|
|
@@:
|
2024-03-31 22:13:17 +02:00
|
|
|
mov byte [p_data + eax], bh
|
|
|
|
inc eax
|
|
|
|
cmp eax, dword [sz]
|
2024-03-31 21:43:38 +02:00
|
|
|
jne @b
|
|
|
|
ret
|
|
|
|
endp
|
|
|
|
|
|
|
|
; Submit a Command in the Admin Submission Queue
|
|
|
|
proc submit_asq stdcall, p_sq:dword
|
2024-03-31 22:13:17 +02:00
|
|
|
mov ebx, dword [bar0]
|
|
|
|
add ebx, NVME_REG_ASQ
|
2024-03-31 21:43:38 +02:00
|
|
|
|
2024-03-31 22:13:17 +02:00
|
|
|
xor eax, eax
|
|
|
|
ret
|
2024-03-31 21:43:38 +02:00
|
|
|
endp
|
|
|
|
|
|
|
|
proc nvme_identify stdcall, nsid:dword, dptr:dword, cns:byte
|
2024-03-31 22:13:17 +02:00
|
|
|
sub esp, sizeof.SQ_ENTRY
|
|
|
|
stdcall memset, esp, 0, sizeof.SQ_ENTRY
|
2024-03-30 04:42:01 +01:00
|
|
|
mov eax, dword [nsid]
|
2024-03-31 22:13:17 +02:00
|
|
|
mov [esp + SQ_ENTRY.nsid], eax
|
2024-03-31 21:43:38 +02:00
|
|
|
mov eax, dword [dptr]
|
2024-03-31 22:13:17 +02:00
|
|
|
mov dword [esp + SQ_ENTRY.dptr], eax
|
2024-03-30 04:42:01 +01:00
|
|
|
; TODO: setting CID to 1 for now but later on keep a list of unique list of identifiers
|
2024-03-31 22:13:17 +02:00
|
|
|
mov dword [esp + SQ_ENTRY.cdw0], ADM_CMD_IDENTIFY or (1 shl 16)
|
2024-03-31 21:43:38 +02:00
|
|
|
mov ah, byte [cns]
|
2024-03-31 22:13:17 +02:00
|
|
|
mov byte [esp + SQ_ENTRY.cdw10], ah
|
|
|
|
stdcall submit_asq, esp
|
|
|
|
add esp, sizeof.SQ_ENTRY
|
|
|
|
xor eax, eax
|
|
|
|
ret
|
2024-03-30 04:42:01 +01:00
|
|
|
endp
|
|
|
|
|
2024-03-28 23:43:18 +01:00
|
|
|
proc detect
|
|
|
|
push ebx
|
|
|
|
invoke GetPCIList
|
|
|
|
mov edx, eax
|
|
|
|
.check_dev:
|
|
|
|
mov ecx, [eax+PCIDEV.class]
|
|
|
|
and ecx, 0x00ffff00 ; retrieve class/subclass code only
|
|
|
|
cmp ecx, 0x00010800 ; Mass Storage Controller - Non-Volatile Memory Controller
|
2024-03-30 04:42:01 +01:00
|
|
|
je .check_cap
|
2024-03-28 23:43:18 +01:00
|
|
|
.next_dev:
|
|
|
|
mov eax, [eax + PCIDEV.fd]
|
|
|
|
cmp eax, edx
|
|
|
|
jne .check_dev
|
|
|
|
|
|
|
|
; no more PCI devices to enumerate?
|
2024-03-30 04:42:01 +01:00
|
|
|
xor eax, eax
|
|
|
|
pop ebx
|
2024-03-28 23:43:18 +01:00
|
|
|
ret
|
|
|
|
.check_cap:
|
|
|
|
push eax
|
|
|
|
movzx ebx, [eax + PCIDEV.bus]
|
2024-03-30 04:42:01 +01:00
|
|
|
mov [pcidev_bus], ebx
|
2024-03-28 23:43:18 +01:00
|
|
|
movzx ebx, [eax + PCIDEV.devfn]
|
2024-03-30 04:42:01 +01:00
|
|
|
mov [pcidev_devfn], ebx
|
|
|
|
invoke PciRead16, [pcidev_bus], [pcidev_devfn], PCI_header00.status
|
2024-03-28 23:43:18 +01:00
|
|
|
test ax, 0x10 ; check capabilities list bit
|
|
|
|
jnz .got_cap
|
|
|
|
pop eax
|
|
|
|
.got_cap:
|
2024-03-30 04:42:01 +01:00
|
|
|
DEBUGF DBG_INFO,"Found NVMe device with capabilities\n"
|
|
|
|
invoke PciRead8, [pcidev_bus], [pcidev_devfn], PCI_header00.cap_ptr
|
2024-03-28 23:43:18 +01:00
|
|
|
and eax, 11111100b
|
|
|
|
mov edi, eax
|
|
|
|
@@:
|
2024-03-30 04:42:01 +01:00
|
|
|
invoke PciRead32, [pcidev_bus], [pcidev_devfn], edi
|
2024-03-28 23:43:18 +01:00
|
|
|
mov ecx, eax
|
2024-03-30 04:42:01 +01:00
|
|
|
;and ecx, 0xff
|
2024-03-28 23:43:18 +01:00
|
|
|
mov eax, ecx
|
|
|
|
movzx edi, ah
|
|
|
|
test edi, edi
|
|
|
|
jnz @b
|
|
|
|
|
2024-03-30 04:42:01 +01:00
|
|
|
; read BAR0
|
|
|
|
invoke PciRead32, [pcidev_bus], [pcidev_devfn], PCI_header00.base_addr_0
|
|
|
|
mov [bar0], eax
|
|
|
|
|
2024-03-31 22:13:17 +02:00
|
|
|
invoke Kmalloc, sizeof.NVME_IDENT_CONTROLLER
|
2024-03-31 21:43:38 +02:00
|
|
|
test eax, eax
|
2024-03-31 22:13:17 +02:00
|
|
|
jz .alloc_ident_controller_fail
|
|
|
|
DEBUGF DBG_INFO,"Successfully allocated %u bytes for 'NVME_IDENT_CONTROLLER'\n",sizeof.NVME_IDENT_CONTROLLER
|
2024-03-31 21:43:38 +02:00
|
|
|
mov [p_ident], eax
|
|
|
|
|
|
|
|
stdcall nvme_identify, 0, dword [p_ident], CNS_IDCS
|
|
|
|
mov ecx, dword [p_ident]
|
2024-03-31 22:13:17 +02:00
|
|
|
mov edx, dword [ecx + NVME_IDENT_CONTROLLER.tnvmcap]
|
|
|
|
DEBUGF DBG_INFO,"Total NVMe SSD capacity: %ub\n", edx
|
2024-03-30 04:42:01 +01:00
|
|
|
|
2024-03-28 23:43:18 +01:00
|
|
|
; return successfully
|
2024-03-31 21:43:38 +02:00
|
|
|
call nvme_cleanup
|
|
|
|
pop eax
|
|
|
|
pop ebx
|
2024-03-28 23:43:18 +01:00
|
|
|
xor eax, eax
|
|
|
|
inc eax
|
|
|
|
ret
|
2024-03-31 21:43:38 +02:00
|
|
|
|
2024-03-31 22:13:17 +02:00
|
|
|
.alloc_ident_controller_fail:
|
|
|
|
DEBUGF DBG_INFO,"ERROR: failed to allocate %u bytes for 'NVME_IDENT_CONTROLLER'\n", sizeof.NVME_IDENT_CONTROLLER
|
2024-03-31 21:43:38 +02:00
|
|
|
pop eax
|
|
|
|
pop ebx
|
|
|
|
xor eax, eax
|
|
|
|
ret
|
|
|
|
endp
|
|
|
|
|
|
|
|
proc nvme_cleanup
|
|
|
|
mov eax, [p_ident]
|
|
|
|
test eax, eax
|
|
|
|
jz @f
|
|
|
|
invoke Kfree, eax
|
|
|
|
@@:
|
|
|
|
ret
|
2024-03-28 23:43:18 +01:00
|
|
|
endp
|
|
|
|
|
|
|
|
; uninitialized data
|
2024-03-31 21:43:38 +02:00
|
|
|
align 4
|
2024-03-30 04:42:01 +01:00
|
|
|
pcidev_bus dd ?
|
|
|
|
pcidev_devfn dd ?
|
|
|
|
bar0 dd ?
|
2024-03-31 21:43:38 +02:00
|
|
|
p_ident dd ?
|
2024-03-28 23:43:18 +01:00
|
|
|
|
|
|
|
;all initialized data place here
|
|
|
|
align 4
|
2024-03-30 04:42:01 +01:00
|
|
|
my_service db "NVMe Service",0 ;max 16 chars include zero
|
|
|
|
include_debug_strings
|
2024-03-28 23:43:18 +01:00
|
|
|
|
|
|
|
align 4
|
|
|
|
data fixups
|
|
|
|
end data
|