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 В следующем разделе мы подробно рассмотрим все команды, коды которых могут передаваться драйверу через заголовок запроса. Для каждой команды будет приведен формат области запроса. |