Есть два дополнения.
Это не обязательно, но желательно иметь функцию для получения версии API драйвера. Для этого зарезервирован ioctl.io_code=0
вот пример из недоделанного драйвера uart.
Code:
SRV_GETVERSION equ 0
; retval
; ebx= service version
; eax= error code
; 0= no error
; -1= common error
align 4
init_uart:
mov eax, 68
mov ebx, 16
mov ecx, szUart
int 0x40
mov [Uart], eax
test eax, eax
jz .fail
push 0 ;storage for version
mov eax, esp ;eax= pointer to output buffer
xor ebx, ebx
push 4 ;.out_size
push eax ;.output
push ebx ;.inp_size
push ebx ;.input
push SRV_GETVERSION ;.code
push [Uart] ;.handle
mov eax, 68
mov ebx, 17
mov ecx, esp ;address of IOCTL in app stack
int 0x40
add esp, 24 ;sizeof IOCTL
pop ebx ;load version
ret
.fail:
or eax, -1
ret
68.16 получает логический номер драйвера и сохраняет его в переменной Uart. После чего в стеке формируется стрктура IOCTL. Чтобы избежать проблем в будущем рекомендую заполнять все поля структуры. В данном примере это происходит в обратном порядке. Последним в стек помещается логический номер драйвера после чего esp становится указателем на структуру IOCTL. После вызова стек восстанавливается командой add esp,24 а pop ebx загружает возвращённый драйвером номер версии.
Второе замечание по кодам ошибок.
Вызовы 68.17 возвращают в eax коды ошибок. Это 0 в случае успеха и ненулевое значение в случае неудачи, обычно -1 как признак общей ошибки, другие коды неопределены. Поэтому драйвер не должен использовать регистр eax для
возврата значений приложению. Все данные от драйвера должны возвращаться в буфере IOCTL.output
Кстати, есть смысл определить стандартные коды ошибок при вызовах 68.17 Например от -1 коды ошибок ядра: драйвер не установлен, неправильный логический номер драйвера и т.д. от +1 коды внутренних ошибок драйвера