Драйверная модель пока не устоялась, так что вся информация предварительная. С терминологией тоже может быть путаница.
intel.obj это типичный драйвер. Он ищет поддерживаемое устройство через вызовы PCI, настраивает, устанавливает обработчик IRQ, и обрабатывает аппаратные прерывания от контроллера. Intel.asm и Sis.asm можно использовать как общие шаблоны для подобных драйверов устройств. Infinity.obj программный драйвер. Он отвечает за создание буферов, ресемплирование и микширование звука. В исходниках встречается термин service обычно так называют драйвер, выполняющийся как отдельная задача. Таких в ОС пока нет.
Система может загружать 32 драйвера. Каждый драйвер должен иметь своё уникальное имя. Максимальная длина имени 16 байт включая завершающий ноль. Драйвер регестрирует себя в системе вызывая функцию ядра
reg_service stdcall, sz_name:dword, handler:dword
sz_name имя драйвера, по этому имени будет происходить поиск драйвера при вызовах
get_service. Проверок на совпадение имен не проводится.
handler содержит адрес главной функции-обработчика драйвера.
Взаимодействие с драйвером происходит через вызовы
srv_handler, ioctl:dword если вызов из ядра, или
srv_handlerEx stdcall, ioctl:dword если вызов из приложения.
ioctl - адрес структуры IOCTL
Code:
struc IOCTL
{ .handler dd ? логический номер сервиса
.io_code dd ? код команды
.input dd ? указатель на входной буфер
.inp_size dd ? размер буфера
.output dd ? указатель на выходной буфер
.out_size dd ? размер буфера
}
Вот пример вызова функции
Code:
align 4
proc SetMasterVol stdcall,hSrv:dword,vol:dword
;устанавливает значение регистра MASTER_VOLUME
;AC97 кодека
;макросы proc stdcall locals помогают
;передавать параметры через стек,
;создавать стековые переменные, избавлют от
;ненужных push и pop и позволяют не забивать голову
;вычислениями [esp+...]
;функцию можно вызывать как из ассемблерных программ
; так и из С программ объявив
; extern int stdcall SetMasterVol(DWORD hSrv, int vol);
;для этого в asm файле функция должна быть указана как public
locals
handle dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
endl
mov eax, [hSrv] ;логический номер драйвера "SOUND"
lea ecx, [vol] ;указатель на значение громкости
xor ebx, ebx
mov [handle], eax
mov [io_code], DEV_SET_MASTERVOL ж команда драйверу
mov [input], ecx
mov [inp_size], 4
mov [output], ebx
mov [out_size], 0
lea eax, [handle]
stdcall CallServiceEx, eax
;можно вызвать напрямую
; mov eax, 68
; mov ebx, 17
; lea ecx, [handle]
; int 0x40
;
ret
endp
align 4
proc CallServiceEx stdcall, ioctl:dword
mov eax, 68
mov ebx, 17
mov ecx, [ioctl]
int 0x40
ret
endp
;другие примеры в исходниках ac97wav.c и k_lib.asm
загрузка драйверов происходит через вызов
get_service stdcall, sz_name:dword эта функция ищет драйвер среди загруженных и если не находит, то загружает с диска. После чего управление передаётся точке входа драйвера "START" чтобы он выполнил настройку и зарегестрировал себя в системе. Функция возвращает логический номер драйвера (точнее это адрес структуры SRV в памяти ядра).
Соответствие между именами драйверов(сервисов) и именами файлов пока жёстко задаются в ядре
Code:
drv_sound db 'INTEL OBJ', 0 ;имена файлов
drv_infinity db 'INFINITYOBJ', 0
szSound db 'SOUND',0 ;регестрируемые имена
szInfinity db 'INFINITY',0
szSTART db 'START',0 ;имя точки входа драйвера
szEXPORTS db 'EXPORTS',0 ;не используется (для DLL)
szIMPORTS db 'IMPORTS',0 ;таблица импорта
align 16
services: ;таблица соответствия имя/файл
dd szSound, drv_sound
dd szInfinity, drv_infinity
dd 0 ;последний элемент
В будущем эту таблицу должен заменить текстовый файл.
(например dev SOUND = /rd/intel.obj)
Драйвер должен быть скомпилирован в формате MS СOFF и состоять из одной секции. Обязательно должны быть объявлены метки public START и public IMPORTS чтобы загрузчик мог найти их в таблице символов COFF файла.
Динамическое связывание.
Загрузчик просматривает таблицу IMPORTS и заменяет адреса строк sz... адресами функций ядра. Для этого строки с именами функций в драйвере и в ядре (exports.asm] должны совпадать. Порядок функций и строк не важен.
Code:
align 16
IMPORTS:
AttachIntHandler dd szAttachIntHandler
SysMsgBoardStr dd szSysMsgBoardStr
PciApi dd szPciApi
PciRead32 dd szPciRead32
PciRead8 dd szPciRead8
AllocKernelSpace dd szAllocKernelSpace
MapPage dd szMapPage
KernelAlloc dd szKernelAlloc
KernelFree dd szKernelFree
GetPgAddr dd szGetPgAddr
RegService dd szRegService
GetCurrentTask dd szGetCurrentTask
GetService dd szGetService
ServiceHandler dd szServiceHandler
FpuSave dd szFpuSave
FpuRestore dd szFpuRestore
dd 0 ;завершающий элемент
szAttachIntHandler db 'AttachIntHandler',0
szSysMsgBoardStr db 'SysMsgBoardStr', 0
szPciApi db 'PciApi', 0
szPciRead32 db 'PciRead32', 0
szPciRead8 db 'PciRead8', 0
szAllocKernelSpace db 'AllocKernelSpace',0
szMapPage db 'MapPage',0
szRegService db 'RegService',0
szKernelAlloc db 'KernelAlloc',0
szGetPgAddr db 'GetPgAddr',0
szGetCurrentTask db 'GetCurrentTask ',0
szGetService db 'GetService',0
szServiceHandler db 'ServiceHandler',0
szKernelFree db 'KernelFree',0
szFpuSave db 'FpuSave',0
szFpuRestore db 'FpuRestore',0
;exports.asm
align 16
kernel_export:
dd szAttachIntHandler, attach_int_handler
dd szSysMsgBoardStr , sys_msg_board_str
dd szPciApi , pci_api
dd szPciRead32 , pci_read32
dd szPciRead8 , pci_read8
dd szPciWrite8 , pci_write8
dd szAllocKernelSpace, alloc_kernel_space
dd szMapPage , map_page
dd szRegService , reg_service
dd szKernelAlloc , kernel_alloc
dd szKernelFree , kernel_free
dd szGetPgAddr , get_pg_addr
dd szGetCurrentTask , get_curr_task
dd szGetService , get_service
dd szServiceHandler , srv_handler
dd szFpuSave , fpu_save
dd szFpuRestore , fpu_restore
dd 0
szAttachIntHandler db 'AttachIntHandler',0
szSysMsgBoardStr db 'SysMsgBoardStr', 0
szPciApi db 'PciApi', 0
szPciRead32 db 'PciRead32', 0
szPciRead8 db 'PciRead8', 0
szPciWrite8 db 'PciWrite8',0
szAllocKernelSpace db 'AllocKernelSpace',0
szMapPage db 'MapPage',0
szRegService db 'RegService',0
szKernelAlloc db 'KernelAlloc',0
szKernelFree db 'KernelFree',0
szGetPgAddr db 'GetPgAddr',0
szGetCurrentTask db 'GetCurrentTask ',0
szGetService db 'GetService',0
szServiceHandler db 'ServiceHandler',0
szFpuSave db 'FpuSave',0
szFpuRestore db 'FpuRestore',0
После связывания функцию можно вызывать косвенно
stdcall [KernelAlloc], 16*512 ; из infinity.asm
Способ передачи параметров может быть любым.
Code:
if DEBUG ;из infinity.asm
mov esi, msgFail
call [SysMsgBoardStr]
end if
msgFail db 'Sound service not found',13,10,0