MS-DOS для программиста© Александр Фролов, Григорий ФроловТом 18, М.: Диалог-МИФИ, 1995, 254 стр. 6.3. Связь драйвера с операционной системойРассмотрим теперь более подробно механизм взаимодействия драйвера и операционной системы. После загрузки драйвер становится как бы частью операционной системы. Все обращения к драйверу MS-DOS выполняет с использованием заголовка драйвера. Для примера приведем вид заголовка символьного драйвера, выполняющего только простейшие функции: next DD 0FFFFFFFFh attrib DW 8000h strateg DW strateg_proc interrupt DW interrupt_proc dev_name DB 'TESTDRV ' Это символьный драйвер (старший бит поля attrib равен 1), исходный текст содержит только один драйвер (поле next содержит значение 0FFFFFFFFh). Устройство называется TESTDRV. Это имя нужно будет использовать при обращении к драйверу. Имя устройства не должно совпадать с именем файла, содержащего символьный драйвер, иначе вы не сможете работать с файлом драйвера. Как уже было сказано, перед обращением к драйверу MS-DOS готовит заголовок запроса в своей внутренней области данных и вызывает программу стратегии, извлекая ее смещение из заголовка драйвера. Программа стратегии обычно очень проста, так как все, что она должна сделать, это запомнить адрес заголовка запроса в области памяти драйвера. Область для хранения адреса заголовка запроса может быть определена следующим образом: req_off DW ? req_seg DW ? В этом случае программа стратегии должна записать содержимое регистра ES в поле req_seg, а регистра BX - в поле req_off: strateg_proc: mov cs:req_off,bx mov cs:req_seg,es ret Драйвер состоит только из сегмента кода, поэтому для адресации данных используется сегментный регистр CS. Запрос операционной системы к драйверу содержит заголовок, имеющий фиксированный формат и длину 13 байт, а также структуру переменного размера и формата, которые зависят от выполняемой функции (переменная область запроса). Приведем формат заголовка запроса :
После вызова программы стратегии MS-DOS передает управление программе прерывания (без параметров). Задача программы прерывания - выполнить команду, код которой находится в поле cmd заголовка запроса. Если драйвер блочного устройства обслуживает несколько логических устройств, то в поле unit находится номер устройства, для которого необходимо выполнить команду. В зависимости от выполняемой команды запрос может содержать и другую информацию, необходимую для выполнения команды. Как операционная система может определить результат выполнения команды? Данные (или адреса данных), полученные драйвером от физического периферийного устройства, помещаются в переменную область запроса. Кроме того, драйвер должен установить слово состояния устройства status в заголовке запроса в соответствии с результатами выполнения команды. Приведем формат слова состояния устройства :
Приведем таблицу кодов ошибок:
Общая схема действий программы прерывания драйвера такова:
Приведем фрагмент исходного текста программы прерывания , который выполняет описанные выше действия: interrupt_proc:
;Сохраняем регистры
push es
push ds
push ax
push bx
push cx
push dx
push si
push di
push bp
; Устанавливаем ES:BX на заголовок запроса
mov ax,cs:req_seg
mov es,ax
mov bx,cs:req_off
; Загружаем в регистр AL код команды из заголовка
; запроса и умножаем его на 2 для получения индекса
; в таблице адресов команд
mov al,es:[bx]+2
shl al,1
sub ah,ah ;записываем 0 в AH
lea di,functions ;DI содержит смещение таблицы команд
add di,ax ;добавляем смещение
jmp word ptr [di] ;переходим по адресу,
;взятому из таблицы
functions LABEL WORD ;это таблица функций
dw initialize
dw check_media
dw make_bpb
dw ioctl_in
dw input_data
dw nondestruct_in
dw input_status
dw clear_input
dw output_data
dw output_verify
dw output_status
dw clear_output
dw ioctl_out
dw Device_open
dw Device_close
dw Removable_media
;Выходим из драйвера, если функция не поддерживается
check_media:
make_bpb:
ioctl_in:
nondestruct_in:
input_status:
clear_input:
output_verify:
output_status:
clear_output:
ioctl_out:
Removable_media:
; Если функция не поддерживается драйвером, устанавливаем
; в единицу биты 15 (ошибка), 8 (выполнение команды
; завершено). В биты 0-7 записываем код ошибки 3 -
; неизвестная команда.
or es:word ptr [bx]+3,8103h
jmp quit
;=======================================================
; Это пример обработчика команды:
Device_open:
; . . . . . . . . . .
; Некоторые действия для открытия устройства.
; . . . . . . . . . .
jmp quit
;=======================================================
;Выходим, модифицируя байт состояния status в заголовке
;запроса
quit:
or es:word ptr [bx]+3,100h ;устанавливаем бит 8
;(выполнение команды завершено)
;Восстанавливаем регистры
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
pop ds
pop es
ret
В следующем разделе мы подробно рассмотрим все команды, коды которых могут передаваться драйверу через заголовок запроса. Для каждой команды будет приведен формат области запроса. |

