Функции драйвера.
В DOS 2.0 каждый загружаемый драйвер устройства должен поддерживать 13 функций, пронумерованных от 0 до 12, даже если единственным действием некоторых из них является установка флага DONE в слове состояния. DOS версий 3 и 4 включают четыре дополнительные функции, которые могут поддерживаться, но не требуются категорически. Некоторые из этих функций работают только с одним из двух типов драйверов, а другие - с обоими типами драйверов (например, инициализация). Неиспользуемые функции должны как минимум устанавливать флаг DONE. Рассмотрим различные функции подробнее, следуя по порядку их номеров.
Каждая функция, описанная здесь, получает значения своих аргументов из заголовка запроса (адрес которого DOS передала подпрограмме стратегии) и в нем же сохраняет "результаты". Поэтому смещение аргументов относительно начала заголовка запроса передается заданной функции. Затем значения этих аргументов присваиваются переменным. Помимо этого смещения специальный флаг показывает тип данных передаваемой информации: байт, слово или PTR (указатель). Тип данных PTR представляет собой указатель на буфер и состоит из двух смежных слов. Первое слово задает смещение буфера, а второе - сегментный адрес.
Функция 0: инициализация драйвера. DOS вызывает эту функцию при загрузке для того, чтобы инициализировать драйвер устройства. Эта функция может включать инициализацию аппаратной части, присвоение различным внутренним переменным значений по умолчанию или переназначение прерываний. Поскольку в этот момент сама операционная система инициализирована не полностью, процедура инициализации может вызывать функции DOS только с номерами от 1 до 0Ch и 30h (прерывание 21h). Эти функции могут использоваться для определения номера версии DOS и вывода информационного сообщения о драйвере на экран. Даже если подключаемым драйвером является новый драйвер CON, выводом на дисплей управляет старый драйвер CON, потому что после завершения инициализации новые драйверы еще не подключены.
Инициализация и заголовок запроса.
Процедуре инициализации могут потребоваться две порции информации из заголовка запроса. Первая - это адрес участка памяти, содержащий текст, следующий после знака равенства в строке файла CONFIG.SYS, которая загружает драйвер в систему.
Драйверы блочных устройств в DOS версии 3.0 и выше обладают еще одной возможностью. Речь идет о буквенном обозначении первого логического устройства драйвера. Значение 0 соответствует 'A', 1 - 'B', 2 - 'C' и т.д.
Процедура инициализации должна возвратить вызывающей функции DOS четыре параметра. Первый параметр - это состояние функции, т.е. информация о том, корректно ли выполнилась функция. В случае драйвера блочного устройства должно быть передано также количество поддерживаемых логических устройств. Эта информация могла бы быть взята из заголовка драйвера, но она игнорируется DOS. Следующим параметром, который драйвер должен передать DOS, является самый старший адрес памяти, который драйвер занимает или использует. Это позволяет DOS определить место для установки следующего драйвера.
Функция 1: проверка носителя.
Эта функция существенно используется только в драйверах блочных устройств.
Функция 2: построить блок параметров BIOS (BPB).
Эта функция используется только драйверами блочных устройств. Символьный драйвер должен только установить флаг DONE в слове состояния и завершиться.
Функция 3: чтение через IOCTL.
Эта функция передает прикладной программе управляющую информацию от драйвера символьного или блочного устройства. Она может быть вызвана только через функцию 44h прерывания 21h, если бит IOCTL в слове-атрибуте устройства равен 1. Параметры, передаваемые функции зависят от того, является драйвер символьным или блочным.
Драйверу символьного устройства передается количество пересылаемых символов и адрес буфера для пересылки данных.
Драйверу блочного устройства передается номер устройства, дескриптор носителя, адрес буфера для пересылки данных, указатель на первый сектор для чтения и количество секторов, которые нужно прочитать.
|
Входные параметры функции 3: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств). |
|
2 |
байт |
Номер функции (3). |
|
13 |
байт |
Дескриптор носителя (только для блочных устройств). |
|
14 |
PTR |
Адрес буфера для пересылки данных. |
|
18 |
слово |
Количество секторов для чтения (блочные устройства) или количество символов для чтения (символьные устройства). |
|
20 |
слово |
Первый сектор, который нужно прочитать. |
|
Выходные параметры функции 3: | ||
|
3 |
слово |
Слово состояния. |
|
18 |
слово |
Количество прочитанных секторов (блочные устройства) или количество прочитанных символов (символьные устройства). |
Функция 4: чтение.
Эта функция читает данные с устройства в буфер, задаваемый входным параметром. При ошибке во время чтения данных должно устанавливаться состояние ошибки. Кроме того функция должна сообщать о количестве секторов или байт, прочитанных успешно. Одного только сообщения об ошибке недостаточно.
|
Входные параметры функции 4: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств). |
|
2 |
байт |
Номер функции (4). |
|
13 |
байт |
Дескриптор носителя (только для блочных устройств). |
|
14 |
PTR |
Адрес буфера, в который должны быть считаны данные. |
|
18 |
слово |
Количество секторов для чтения (блочные устройства) или количество символов для чтения (символьные устройства). |
|
20 |
слово |
Первый читаемый сектоp |
|
Выходные параметры функции 4: | ||
|
3 |
слово |
Слово состояния. |
|
18 |
слово |
Количество прочитанных секторов (блочные устройства) или количество прочитанных символов (символьные устройства). |
|
22 |
PTR |
Указатель на идентификатор тома при возврате с ошибкой 0Fh (версия 3.0 и выше). |
Функция 5: неразрушающее чтение.
Эта функция используется драйвером символьного устройства для проверки, есть ли во входном буфере непрочитанные символы. В случае блочного устройства функция устанавливает флаг DONE и завершается.
При помощи этой функции DOS запрашивает дополнительные символы. Если они есть, бит занятости (busy) очищается, т.е. получает значение 0, а следующий символ передается DOS. Передаваемый символ на самом деле остается в буфере, поэтому последующий вызов функции чтения возвратит тот же самый символ. Если символов больше нет, бит занятости получает значение 1.
|
Входные параметры функции 5: | ||
|
2 |
байт |
Номер функции (5). |
|
Выходные параметры функции 5: | ||
|
3 |
слово |
Слово состояния. |
|
13 |
байт |
Прочитанный символ. |
Функция 6: состояние ввода.
Эта функция используется для того, чтобы определить, есть ли в буфере ввода символьного устройства символ, ожидающий чтения. В случае блочного устройства функция устанавливает флаг DONE и завершается.
Если символ ожидает чтения из входного буфера, бит занятости очищается (получает значение 0). Если же символа во входном буфере нет, этот бит получает значение 1.
Когда символ ожидает чтения, функция состояния ввода (06h) сбрасывает значение бита занятости слова состояния в нуль и возвращает символ DOS. Символ не удаляется из буфера и, следовательно, является неразрушающим. Эта функция эквивалентна просмотру на один символ вперед.
|
Входные параметры функции 6: | ||
|
2 |
байт |
Номер функции (6). |
|
Выходные параметры функции 6: | ||
|
3 |
слово |
Слово состояния: символы уже в буфере = 0; Запрос на чтение с физ. устр. = 1 |
Функция 7: очистить буферы ввода.
Эта функция очищает внутренние буферы ввода драйвера символьного устройства. При использовании этой функции прочитанные, но не переданные DOS, символы теряются. Блочное устройство устанавливает флаг DONE и завершает функцию.
|
Входные параметры функции 7: | ||
|
2 |
байт |
Номер функции (7). |
|
Выходные параметры функции 7: | ||
|
3 |
слово |
Слово состояния. |
Функция 8: запись.
Эта функция пересылает символы из буфера на текущее устройство. Если при пересылке возникает ошибка, для ее отражения используется слово состояния. Эту функцию используют как блочные, так и символьные устройства.
Параметры, используемые в этой функции, зависят от того, какое имеется ввиду устройство - символьное или блочное. В обоих случаях передается адрес буфера, из которого необходимо переслать некоторое количество символов. Драйверу символьного устройства, кроме этого, необходимо передать еще и количество пересылаемых символов.
Блочный драйвер получает количество пересылаемых секторов (а не символов), номер устройства, его дескриптор носителя и адрес первого сектора на носителе.
В случае ошибки при записи должно устанавливаться состояние ошибки. Кроме того, функция должна сообщать о количестве секторов (или байт), записанных успешно. Просто сообщать об ошибке недостаточно.
|
Входные параметры функции 8: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств) |
|
2 |
байт |
Номер функции (8). |
|
13 |
байт |
Дескриптор носителя устройства (только для блочных устройств). |
|
14 |
PTR |
Адрес буфера, содержащего данные. |
|
18 |
слово |
Количество секторов, которое должно быть записано (блочные устройства), количество символов, которое должно быть запи- сано (символьные устройства). |
|
20 |
слово |
Первый сектор, который должен быть записан (только для блочных устройств). |
|
Выходные параметры функции 8: | ||
|
3 |
слово |
Слово состояния. |
|
18 |
слово |
Количество записанных секторов (блочные устройства) |
|
22 |
PTR |
Указатель на идентификатор тома при возврате с ошибкой 0Fh (версия 3.0 и выше) |
Функция 9: запись с верификацией.
Эта функция аналогична функции 8 с той разницей, что записанные символы считываются еще раз и проверяются.
Некоторые устройства, особенно символьные, такие как монитор или принтер, не нуждаются в верификации, потому что либо при пересылке не бывает ошибок (монитор), либо верификация невозможна (принтер).
|
Входные параметры функции 9: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств) |
|
2 |
байт |
Номер функции (9). |
|
13 |
байт |
Дескриптор носителя устройства (только для блочных устройств). |
|
14 |
PTR |
Адрес буфера, содержащего данные. |
|
18 |
слово |
Количество секторов, которое должно быть записано (блочные устройства), количество символов, которое должно быть запи- сано (символьные устройства). |
|
20 |
слово |
Первый сектор, который должен быть записан (только для блочных устройств). |
|
Выходные параметры функции 9: | ||
|
3 |
слово |
Слово состояния. |
|
18 |
слово |
Количество записанных секторов (блочные устройства) |
|
22 |
PTR |
Указатель на идентификатор тома при возврате с ошибкой 0Fh (версия 3.0 и выше) |
Функция 10: состояние вывода.
Эта функция показывает, завершилась последняя операция записи на символьное устройство или не завершилось. Блочное устройство должно только установить флаг DONE и завершить функцию.
Если последняя операция записи завершилась, бит занятости в слове состояния очищается, а в противном случае - получает значение 1.
|
Входные параметры функции 10: | ||||
|
2 |
байт |
Номер функции (10). | ||
|
Выходные параметры функции 10: | ||||
|
3 |
слово |
Слово состояния: бит занятости равен 1, если последняя операция символьного вывода не закончилась. | ||
Функция 11: очистить буферы вывода.
Эта функция полностью очищает буфер вывода, даже если он содержит символы, ожидающие вывода. Блочное устройство должно только установить флаг DONE и завершить функцию.
|
Входные параметры функции 11: | ||
|
2 |
байт |
Номер функции (11). |
|
Выходные параметры функции 11: | ||
|
3 |
слово |
Слово состояния. |
Функция 12: запись с контролем ввода/вывода.
Эта функция передает драйверу символьного или блочного устройства управляющую информацию. Она может быть вызвана только через функцию 44h прерывания 21h, которая устанавливает бит IOCTL (контроль ввода/вывода) в слове-атрибуте устройства в заголовке драйвера. В зависимости от того, какой тип драйвера - символьный или блочный, функции передаются различные параметры.
Драйверу символьного устройства передается количество символов, которые нужно записать и адрес буфера, из которого пересылаются эти символы.
Драйверу блочного устройства передается номер устройства (в том случае, если драйвер обслуживает логические устройства), байт дескриптора носителя, адрес буфера, из которого берутся данные для записи, номер первого записываемого сектора и количество таких секторов.
Символьный драйвер возвращает количество записанных байт, а блочный
- количество записанных секторов.
|
Входные параметры функции 12: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств) |
|
2 |
байт |
Номер функции (12). |
|
13 |
байт |
Дескриптор носителя устройства (только для блочных устройств). |
|
14 |
PTR |
Адрес буфера, из которого следует читать данные |
|
18 |
слово |
Количество записанных секторов (блочные устройства), количество записанных символов (символьные устройства). |
|
20 |
слово |
Первый записываемый сектор (только для блочных устройств). |
|
Выходные параметры функции 12: | ||
|
3 |
слово |
Слово состояния. |
|
18 |
слово |
Количество записанных секторов (блочн. устp.) Количество записанных символов (симв. устp.) |
Следующие четыре функции поддерживаются DOS 3.0 и выше.
Функция 13: открыть.
Эту функцию можно использовать только если установлен бит OCR (Open/Close/RM - Открыть/Закрыть/Сменяемый носитель) в слове-атрибуте устройства в заголовке драйвера. Ее действия зависят от того, какой драйвер - символьный или блочный.
В символьном драйвере эта функция перед пересылкой данных может послать на устройство строку инициализации. В случае связи с принтером это дает некоторые преимущества. Строка инициализации не должна быть включена в драйвер, но может быть вызвана, например, при помощи функции IOCTL прерывания 21h, которая вызывает функцию 12 драйвера для того, чтобы переслать ее драйверу из прикладной программы.
Функция имеет и другие полезные свойства, например, она препятствует одновременному доступу к одному и тому же устройству двум различным процессам (в многозадачном режиме или сети).
Для устройств CON, PRN и AUX эта функция не вызывается, поскольку они всегда открыты.
|
Входные параметры функции 13: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств) |
|
2 |
байт |
Номер функции (13) |
|
Выходные параметры функции 13: | ||
|
3 |
слово |
Слово состояния. |
Функция 14: закрыть.
Эта функция противоположна функции 13. Ее можно использовать только если установлен бит OCR в слове-атрибуте устройства в заголовке драйвера. Ее действия также зависят от того, какой драйвер - символьный или блочный. Блочный драйвер вызывает ее после закрытия файла. Это можно использовать для уменьшения счетчика открытых файлов. Как только все файлы на устройстве закрываются, драйвер должен очистить все буферы на устройствах со сменяемыми носителями, т.к. эта ситуация скорее всего означает, что пользователь собирается сменить носитель.
Символьный драйвер может использовать эту функцию для того, чтобы послать некоторую закрывающую управляющую информацию устройству после того, как вывод будет закончен. Для принтера такой информацией может быть протяжка страницы. Так же, как в функции 13, строку можно переслать из прикладной программы при помощи функции IOCTL.
|
Входные параметры функции 14: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств) |
|
2 |
байт |
Номер функции (14) |
|
Выходные параметры функции 14: | ||
|
3 |
слово |
Слово состояния. |
Функция 15: сменяемый носитель.
Эта функция показывает, может ли носитель на блочном устройстве быть заменен или нет. Эта функция используется только если установлен бит OCR в слове-атрибуте устройства в драйвере устройства. Драйвер символьного устройства должен только установить флаг DONE в слове состояния и завершить функцию.
Если носитель может быть заменен, бит занятости сбрасывается (0); в противном случае - устанавливается (1).
|
Входные параметры функции 15: | ||
|
1 |
байт |
Номер устройства (только для блочных устройств) |
|
2 |
байт |
Номер функции (14) |
|
Выходные параметры функции 15: | ||
|
3 |
слово |
Слово состояния: если носитель может быть заменен, бит занятости должен содержать значение 0. |
Функция 16: выводить, пока не занято.
Эта функция пересылает данные из буфера на устройство вывода до тех пор, пока устройство будет занято (т.е. не сможет более принимать символы). Поскольку эта функция поддерживается символьными устройствами, блочное устройство должно только установить (1) флаг DONE в слове состояния и завершить функцию.
Эта функция работает особенно хорошо со спулерами печати, через которые файлы посылаются на принтер в качестве фонового процесса, в то время как основным процессом является выполняемая программа. Может получиться так, что не все символьные предназначенные к пересылке, будут посланы на устройство во время вызова этой функции. Причина этого, как правило, не в ошибке, а в том, что устройство становится занятым. Функции передаются количество пересылаемых символов и адрес буфера. Если во время пересылки устройство сообщает, что оно более не может принимать символы, оно показывает количество успешно пересланных символов и возвращает управление драйверу устройства.
|
Входные параметры функции 16: | ||
|
2 |
байт |
Номер функции (16) |
|
14 |
PTR |
Адрес буфера, из которого нужно считывать данные |
|
18 |
слово |
Количество символов, которые нужно прочитать |
|
Выходные параметры функции 16: | ||
|
3 |
слово |
Слово состояния |
|
18 |
слово |
Количество записанных символов |
Далее рассмотрим действия, выполняющиеся до и после вызова функции драйвера устройства.
Цепь событий начинается, когда через прерывание 21h вызывается функция, управляющая вводом/выводом. Вызов одной из этих функций может, в свою очередь, вызвать ряд других функций и соответствующих операций ввода и вывода.
Открытие. В качестве примера можно взять функцию 3Dh (открыть), которая вызывается для того, чтобы открыть файл в каталоге. Прежде всего, перед тем, как открывать, DOS должна найти файл. Это может потребовать просмотра множества каталогов, вместо простого чтения в таблице FAT. При каждом обращении через прерывание 21h, DOS определяет, какой из доступных драйверов устройств должен быть использован для чтения или записи символов. После этого DOS отводит в памяти область, требующуюся драйверу устройства.
При работе с файлами DOS должна преобразовать количество записей, которое нужно обработать, в номера логических секторов. Затем DOS вызывает подпрограмму стратегии драйвера устройства, который она передает адрес только что созданного блока данных (заголовка запроса). После этого вызывается подпрограмма прерывания драйвера, она сохраняет все регистры. Она также отделяет код функции от блока данных и начинает обрабатывать функцию.
Если драйвер, к которому последовало обращение, является драйвером символьного устройства, то функция должна только послать символы физическому устройству или запросить символы для чтения.
Блочные устройства.
Для блочных устройств (устройств массовой памяти, таких, как гибкий или жесткий диск) номер логического сектора должен быть преобразован в физический адрес перед доступом для чтения или записи. Номер логического сектора разбивается на головку, цилиндр (трек) и физический номер сектора.
По окончании операции чтения или записи функция драйвера должна разместить результирующий код в поле состояния заголовка запроса, который должен быть возвращен вызывающей функции DOS. Затем восстанавливается содержимое всех регистров, а управление возвращается вызывающей функции DOS, которая, в зависимости от результатов работы функции драйвера, устанавливает или сбрасывает флаг переноса и помещает код ошибки в регистр AX. Функция прерывания затем возвращает управление подпрограмме, вызвавшей прерывание 21h.
