Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

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 байт, а также структуру переменного размера и формата, которые зависят от выполняемой функции (переменная область запроса).

Приведем формат заголовка запроса :

Смещение, байт Размер, байт Имя поля Описание
0 1 size Общий размер блока запроса в байтах (длина заголовка запроса плюс длина переменной части запроса)
1 1 unit Номер устройства. Используется для блочных устройств; указывает, с каким именно устройством (из числа обслуживаемых данным драйвером) будет работать операционная система
2 1 cmd Код команды, которую требуется выполнить. Может иметь значение от 00h до 18h
3 2 status Слово состояния устройства. Заполняется драйвером перед возвращением управления операционной системе
5 8 reserved Зарезервировано

После вызова программы стратегии MS-DOS передает управление программе прерывания (без параметров). Задача программы прерывания - выполнить команду, код которой находится в поле cmd заголовка запроса. Если драйвер блочного устройства обслуживает несколько логических устройств, то в поле unit находится номер устройства, для которого необходимо выполнить команду.

В зависимости от выполняемой команды запрос может содержать и другую информацию, необходимую для выполнения команды.

Как операционная система может определить результат выполнения команды?

Данные (или адреса данных), полученные драйвером от физического периферийного устройства, помещаются в переменную область запроса. Кроме того, драйвер должен установить слово состояния устройства status в заголовке запроса в соответствии с результатами выполнения команды.

Приведем формат слова состояния устройства :

Бит Назначение
0-7 Код ошибки устройства. Если команда выполнена с ошибкой и драйвер установил признак ошибки (бит 15) в единицу, он должен записать в это поле код ошибки
8 Команда выполнена. Этот бит всегда устанавливается драйвером перед возвращением управления операционной системе
9 Занято. Этот бит устанавливается обработчиком команды, когда физическое устройство занято выполнением предыдущей операции и поэтому не может выполнить новую команду. Данный бит используется также для передачи информации о том, что буфер клавиатуры содержит данные или о том, что среда носителя данных может быть заменена (в команде проверки возможности замены среды носителя данных)
10-14 Зарезервировано
15 Признак ошибки. Устанавливается драйвером, когда он не может обработать запрос или произошла физическая либо логическая ошибка при обработке правильного запроса. Биты 0-7 при этом должны содержать код ошибки

Приведем таблицу кодов ошибок:

Код Описание
0 Нарушение защиты от записи. Была предпринята попытка записи информации на защищенное от записи устройство
1 Неизвестное устройство
2 Устройство не готово
3 Неизвестная команда. Данная команда не поддерживается драйвером
4 Ошибка CRC. При выполнении команды обнаружена ошибка в контрольной сумме
5 Неправильная длина запроса. Поле длины в заголовке запроса содержит неверное значение
6 Ошибка при поиске дорожки (дорожка не найдена)
7 Неизвестный носитель данных
8 Сектор не найден
9 В принтере нет бумаги
0Ah Ошибка записи
0Bh Ошибка чтения
0Ch Общая ошибка
0Dh Зарезервировано
0Eh Зарезервировано
0Fh Замена диска не разрешается

Общая схема действий программы прерывания драйвера такова:

  • получив управление от операционной системы, программа прерывания сохраняет содержимое всех регистров процессора и считывает номер команды из заголовка запроса;
  • при необходимости программа считывает дополнительную информацию из области запроса;
  • затребованная команда выполняется (если она поддерживается драйвером);
  • если драйвер считывает какие-либо данные от физического устройства для передачи их операционной системе, то программа прерывания записывает эти данные или их адреса в область запроса;
  • программа прерывания устанавливает слово состояния устройства в соответствии с результатами выполнения команды (если драйвер не поддерживает затребованную команду, в слове состояния устройства устанавливаются биты 15 и в биты 0-7 записывается код ошибки 3 - неизвестная команда);
  • программа прерывания восстанавливает содержимое регистров процессора, вслед за чем управление возвращается операционной системе (с помощью команды возврата из дальней процедуры).

Приведем фрагмент исходного текста программы прерывания , который выполняет описанные выше действия:

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

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

[Назад] [Содеожание] [Дальше]