Операционная система MS-DOS© Александр Фролов, Григорий ФроловТом 1, книги 1-2, М.: Диалог-МИФИ, 1991. 6.4. Связь драйвера с операционной системойРассмотрим теперь более подробно механизм взаимодействия драйвера и операционной системы. После загрузки драйвер становится как бы частью операционной системы. Все обращения к драйверу DOS выполняет с использованием заголовка драйвера. Для примера приведем вид заголовка символьного драйвера, выполняющего только простейшие функции: next DD 0FFFFFFFFh attrib DW 8000h strateg DW strateg_proc interrupt DW interrupt_proc dev_name DB 'TESTDRV ' Это символьный драйвер (старший бит поля attrib равен 1), исходный текст содержит только один драйвер (поле next содержит значение 0FFFFFFFFh), имя устройства, которое нужно будет использовать при обращении к драйверу - TESTDRV. Имя устройства не должно совпадать с именем файла, содержащего символьный драйвер, иначе Вы не сможете обратиться к файлу, например, для его переименования - DOS будет работать не с файлом, а с устройством. Как уже было сказано, перед обращением к драйверу 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. Запрос операционной системы к драйверу соcтоит из заголовка, имеющего фиксированный формат и длину 13 байт, и переменной части, размер и формат которой зависит от выполняемой функции. Приведем формат заголовка запроса:
После вызова программы стратегии DOS передает управление программе прерывания (без параметров). Задача программы прерывания - выполнить команду, код которой находится в поле cmd заголовка запроса. Если драйвер блочного устройства обслуживает несколько логических устройств, то в поле unit находится номер устройства, для которого необходимо выполнить команду. В зависимости от выполняемой команды запрос может содержать другую информацию, необходимую для выполнения команды. Как результаты выполнения команды возвращаются DOS? Данные (или адреса данных), полученные драйвером от физического устройства ввода/вывода, помещаются в область переменной части запроса. Кроме того, драйвер должен установить слово соcтояния устройства 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 ;обнуляем 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 В следующем разделе мы подробно рассмотрим все команды, коды которых могут передаваться драйверу через заголовок запроса. Для каждой команды будет приведен формат области запроса. |