;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; BSD 3-Clause License ;; ;; ;; ;; Copyright (C) 2022, Michael Frolov aka Doczom ;; ;; All rights reserved. ;; ;; ;; ;; Device subsystem from kernel Kolibri OS. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Подсистема устройств ;; Для нормальной работы приложений в ОС должна быть система ;; работы с оборудованием. Для стандартизации доступа (единого ;; интерфейса взаимодействия) к оборудованию нужен интерфейс ;; позволяющий обращаться к функциям устройства и различать эти ;; устройства между собой. ;; Для чёткой идентефикациии устройств есть 2 поля: ;; * virt_type - Это виртуальный тип устройства, на основе ;; которого можно определить базовые функции ;; устройства. Например последовательный порт, ;; HID устройство или принтеры. ;; Для каждого типа должен существовать набор ;; функций, позволяющий организовать минимальный ;; интерфейс для работы с данным оборудованием. ;; Кроме этого базвого интерфейса, могут быть и ;; дополнительные функции. ;; * real_type - Это реальный идентификатор устройства, через ;; который можно получить информацию о расположении ;; оборудования в компьютере(шина данны, порт, номер ;; шины, device_id, vendor_id, класс устройства и тд). ;; ;; Для ; Память под эту структуру выделяет сам драйвер и освобождает тоже он struct DEVICE next dd 0 prev dd 0 virt_type dd 0 dd 0 real_type dd 0 ; real type devise dd 0 dd 0 dd 0 ; ну чтоб точно хватило места на ВСЁ dd 0 dd 0 dd 0 dd 0 root_device dd 0 ; Главное устройство для этого ; fastcall int func(void data, DEV_IOCTL* ioctl) func dd 0 ; fastcall int func(void data, DEV_IOCTL* ioctl) func_k dd 0 ; fastcall void close(void data, int type_close) close dd 0 ; pointer to function clear and destroy this device data dd 0 ; data for functions for this device ends ; real_type format ; ; offset 0x00 ; 0xYYRRRRXX ; YY - bus protool ; 0 - old dev ; 1 - pci dev ; 2 - acpi dev ; 3 - usb dev ; 4 - virtual dev ; XX - подтип, например для pci тут будет по сути класс, для юсб тоже, для acpi не знаю ; RRRR - остальная часть типа, тут может быть подтип например ; ; offset 0x04 - other data for bus: number port, number bus, and etc. ; dword = 0xPPBBRRRR ; PP - port device ; BB - bus number ; RRRR - other data bus ; ; offset 0x08 ; dword = 0xDDDDVVVV ; DDDD - device id ; VVVV - vendor id ; ; offset 0x0C ; other data ; Type ; dword = 0xTTTTTTNN ; TTTTTT - type device ; 0xFF - unknown device type ; NN - motes for this type ; 0xFF - unknown device ;; ;; Kernel functions ;; ; for user api ecx = ptr to DEVICE edx = IOCTL_DEVICE call_device: cmp dword[ecx + DEVICE.func], 0 jz .err_func mov eax, ecx mov ecx, dword[ecx + DEVICE.data] ; fastcall int iocl_func(void data, IOCTL_DEV* ioctl) call dword[eax + DEVICE.func] ret .err_func: xor eax, eax dec eax ret ; for kernel api ecx = ptr to DEVICE edx = IOCTL_DEVICE call_device_k: cmp dword[ecx + DEVICE.func_k], 0 jz .err_func mov eax, ecx mov ecx, dword[ecx + DEVICE.data] ; fastcall int iocl_func(void data, IOCTL_DEV* ioctl) call dword[eax + DEVICE.func_k] ret .err_func: xor eax, eax dec eax ret ;save pointers devices: .next: dd 0 .prev: dd 0 ; for user and kernel api rcx/ecx = type device find_device: mov eax, [devices.first] test eax, eax jz .not_devices @@: cmp dword[eax + DEVICE.type], ecx jz .found cmp eax, dword[devices.last] mov eax, dword[eax + DEVICE.next] jnz @b xor eax, eax .not_devices: .found: ret ;use for kernel api ;stdcall int AddDevice(DEVICE* dev) AddDevice: push ecx push edx mov eax, sizeof.DEVICE call malloc test eax, eax pop edx pop ecx jz .fail_mem mov edi, eax mov eax, [esp + 4] mov ebx, [devices.last] test ebx, ebx jnz @f mov [devices.first], edi mov [devices.last], edi jmp .set_data @@: mov [ebx + DEVICE.next], edi mov [edi + DEVICE.prev], ebx mov [devices.last], edi ret .fail_mem: or eax, -1 ret ;use for kernel api ;stdcall void DelDevice(void* ptr_struct) DelDevice: mov eax, [esp + 4] mov ecx, [eax + DEVICE.data] call [eax + DEVICE.exit] test eax, eax ; 0 - good -1 - error jz .no_exit ; delete item mov ecx, [eax + DEVICE.next] mov edx, [eax + DEVICE.prev] push ebx mov ebx,[devices.last] cmp ebx,[devices.first] jnz @f xor ebx, ebx mov [devices.first], ebx mov [devices.last], ebx jmp .free_struct @@: cmp eax, [devices.first] jnz @f mov [devices.first], ecx jmp .free_struct @@: cmp eax, [devices.last] jnz @f mov [devices.last], edx jmp .free_struct @@: mov [ecx + DEVICE.prev], edx mov [edx + DEVICE.next], ecx .free_struct: pop ebx call free ; eax = ptr to mem ret .no_exit: mov eax, -1 ret ; find device from type ;eax = 81 ;ebx = 0 ;ecx = type ;out: rax/eax = pointer to device or null ; ;get list devices ;eax = 81 ;ebx = 1 ;out: rax/eax - first item, null for error ; rcx/ecx - last item ; ; get item list devices ;eax = 81 ;ebx = 2 ;rcx/ecx = pointer to device struct ;rdx/edx = pointer to buffer ;out: eax - error code: 0 - good; -1 - item not found -2 - Bad buffer ;buffer: ; .next: dd 0 ; dd 0 ; .prev: dd 0 ; dd 0 ; .type: dd 0 ; dd 0 ; .func: dd 0 ; может быть ноль, если драйвер не экспортирует функции для юзермода ; dd 0 ; .subtype: dd 0 ; dd 0 ; dd 0 ; dd 0 ;endbyff: ; call functiion device ;eax = 81 ;ebx = 3 ;ecx = pointer to device struct ;edx = pointer to IOCTL struct ;out: eax = Error code: 0-good -1-device dot found struct DEV_IOCL function dd 0 ; number subfunction size_input dd 0 size_output dd 0 ptr_input dd 0 ptr_output dd 0 ends ; subfunctions: ; 0-7 - mandatory ; 0 - get count subfunctions ; 1 - ger version device ; 2 - get driver ; 3 - get status device ; 4 - get name device ; 5 - get vendor ; 6 - lock device ;; for kernel and user api ; 7 - unlock device ;; for kernel and user api ;; ;; User API ;; sysfn81: test ebx, ebx jnz @f call find_device mov [esp + 32], eax ret @@: dec ebx ; =1 jnz @f mov eax, [devices.first] mov ecx, [devices.last] mov [esp + 32], eax mov [esp + 28], ebx ret @@: dec ebx ; =2 jnz @f stdcall is_region_userspace, ebx, sizeof.DEVICE jnz .bad_buffer mov esi, ecx mov edi, edx mov ecx, 12 ; 12 dword for buffer rep movsd and dword[esp + 32], 0 ret .bad_buffer: mov dword[esp + 32], -2 ret @@: dec ebx ; =3 jnz @f call call_device mov [esp + 32], eax ret @@: or dword[esp + 32], -1 ret