dev_name DB 'AUX '
Для блочных устройств первый байт поля dev_name содержит количество устройств, обслуживаемых данным драйвером, остальные семь байтов не используются:
dev_name DB 1
DB 7 dup(?)
Таким образом, мы выяснили, что драйвер содержит в самом начале заголовок, и где-то дальше должны располагаться программы стратегии и прерывания. (Не следует путать программу прерывания драйвера с программой обслуживания аппаратных или программных прерываний. Хотя программа прерывания драйвера немного похожа на обработчик программных прерываний, назначение этой программы и механизм ее использования совершенно другой). Что еще может находиться в программе-драйвере? Это могут быть области данных, используемые драйвером, и подпрограммы, вызываемые программами стратегии и прерывания. Иногда стандартные драйверы переназначают на себя некоторые вектора прерываний, и тогда они содержат в себе обработчики этих прерываний. В области памяти, отведенной операционной системой драйверу, может располагаться стек драйвера, если размер системного стека недостаточен. На длину драйвера накладывается такое же ограничение, как и на длину COM- программ - 64 килобайта, то есть один сегмент.
Связь драйвера с операционной системой
Рассмотрим теперь более подробно механизм взаимодействия драйвера и операционной системы. После загрузки драйвер становится как бы частью операционной системы. Все обращения к драйверу 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 байт, и переменной части, размер и формат которой зависит от выполняемой функции. Приведем формат заголовка запроса: |(0)|size |Длина запроса в байтах (длина заголовка запроса плюс длина переменной | |1 | |части запроса) | |(+1|unit |Номер устройства (используется для блочных устройств, указывает, с каким| |) 1| |именно устройством, обслуживаемым драйвером, будет работать операционная| | | |система) | |(+2|cmd |Код команды, которую требуется выполнить (может иметь значение от 0 до | |) 1| |18h) | |(+3|statu|Слово состояния устройства, заполняется драйвером перед возвратом | |) 2|s |управления операционной системе | |(+5|reser|Зарезервировано | |) 8|ved | |
После вызова программы стратегии DOS передает управление программе прерывания (без параметров). Задача программы прерывания - выполнить команду, код которой находится в поле cmd заголовка запроса. Если драйвер блочного устройства обслуживает несколько логических устройств, то в поле unit находится номер устройства, для которого необходимо выполнить команду.
В зависимости от выполняемой команды запрос может содержать другую информацию, необходимую для выполнения команды. Как результаты выполнения команды возвращаются DOS? Данные (или адреса данных), полученные драйвером от физического устройства ввода/вывода, помещаются в область переменной части запроса. Кроме того, драйвер должен установить слово соcтояния устройства status в заголовке запроса в соответствии с результатами выполнения команды. Приведем формат слова состояния устройства: |Би|Назначение | |т | | |0-|Код ошибки устройства (если команда выполнена с ошибкой и драйвер установил | |7 |признак ошибки (бит 15) в единицу, в это поле он должен записать код ошибки). | |8 |Команда выполнена. Этот бит всегда устанавливается драйвером перед тем, как он | | |возвращает управление операционной системе. | |9 |Занято. Этот бит устанавливается обработчиком команды, когда физическое | | |устройство занято выполнением предыдущей операции и поэтому не может выполнить | | |требуемую команду. Этот бит используется также для передачи такой информации, | | |как "буфер клавиатуры не пуст", "среда носителя данных заменяемая" (в команде | | |проверки возможности замены среды носителя данных). | |10|Зарезервировано. | |-1| | |4 | | |15|Признак ошибки. Устанавливается драйвером, когда он не может обработать запрос | | |или произошла физическая либо логическая ошибка при обработке правильного | | |запроса. Биты 0-7 при этом должны содержать код ошибки. |
Приведем таблицу возможных кодов ошибок: |Ко|Описание | |д | | |0 |Нарушение защиты от записи. Была предпринята попытка записи информации на | | |защищенное от записи устройство. | |1 |Неизвестное устройство. | |2 |Устройство не готово. | |3 |Неизвестная команда. Затребованная команда не поддерживается драйвером. | |4 |Ошибка CRC. При выполнении команды обнаружена ошибка циклического кода | | |проверки. | |5 |Неправильная длина запроса. Поле длины в заголовке запроса содержит неверное | | |значение. | |6 |Ошибка при поиске дорожки (дорожка не найдена). | |7 |Неизвестный носитель данных. | |8 |Сектор не найден. | |9 |Нет бумаги в принтере. | |0A|Ошибка записи. | |h | | |0B|Ошибка чтения. | |h | | |0C|Общая ошибка. | |h | | |0D|Зарезервировано. | |h | | |0E|Зарезервировано. | |h | | |0F|Неразрешенная замена диска (только для DOS версии 3.0 и более поздних версий).| |h | |
Общая схема действий программы прерывания драйвера такова:
. получив управление от операционной системы, программа прерывания сохраняет содержимое всех регистров процессора и считывает номер команды из заголовка запроса;
. при необходимости программа считывает дополнительную информацию из области запроса;
. затребованная команда выполняется (если она поддерживается драйвером);
. если драйвер считывает какие-либо данные от обслуживаемого физического устройства для передачи их DOS, то сами данные или их адреса программа прерывания записывает в область запроса;
. программа прерывания устанавливает слово состояния устройства в соответствии с результатами выполнения команды (если драйвер не поддерживает затребованную команду, в слове состояния устройства устанавливаются биты 15 и в биты 0-7 записывается код ошибки 3 - неизвестная команда);
. восстанавливается содержимое регистров процессора, и управление возвращается операционной системе с помощью команды возврата из дальней процедуры.
Инициализация драйвера
Эта функция выполняется только один раз при загрузке драйвера и подключении его к операционной системе. Функция инициализации должна поддерживаться любым драйвером, так как она сообщает операционной системе сведения, необходимые DOS для правильного подключения и использования драйвера. Приведем формат запроса для команды инициализации: |(0)|head|Заголовок запроса. | |13 |er | | |(+1|n_un|Количество устройств, обслуживаемых драйвером. Это поле заполняется | |3) |its |только блочным драйвером. | |1 | | | |(+1|end_|Конечный FAR-адрес резидентной части кода драйвера. В это поле драйвер | |4) |addr|записывает адрес байта памяти, следующего за той частью кода драйвера, | |4 | |которая должна стать резидентной. | |(+1|parm|FAR-адрес строки параметров инициализации драйвера из файла CONFIG.SYS. | |8) | |Эта строка содержит все, что находится в строке файла после команды | |4 | |'DEVICE=', она заканчивается символами перевода строки и возврата | | | |каретки 0Ah, 0Dh. При возврате драйвер блочного устройства должен | | | |записать в это поле адрес массива указателей на блоки параметров | | | |BIOSBIOS (BPB), по одному указателю на каждое устройство, обслуживаемое | | | |драйвером. | |(+2|driv|Номер устройства. Для версии DOS 3.0 и более поздних версий в это поле | |2) |e |при загрузке драйвера операционная система заносит номер, назначенный | |1 | |устройству, обслуживаемому драйвером. Например, для устройства А: это 0,| | | |для B: - 1 и т.д. |
При инициализации драйвер символьного устройства сохраняет в своей внутренней области данных параметры инициализации, используя адрес parm. Если параметры содержат числовые величины, программа инициализации может произвести их перекодировку и сохранить значения в двоичном формате. Затем драйвер может выполнить инициализацию обслуживаемого физического устройства ввода/вывода, инициализацию своих внутренних переменных, вывести на экран какие-либо сообщения либо даже запросить у оператора дополнительные данные - функция инициализации может пользоваться для организации диалога с оператором и других действий функциями прерывания 21h с номерами от 01h до 0Ch, 25h, 30h, 35h и функциями BIOS. Кроме этого, драйвер должен заполнить поле end_addr адресом конца резидентной части драйвера. Так как программа инициализации выполняется только один раз, обычно ее располагают в конце драйвера и для экономии памяти не оставляют резидентной. Драйверы блочных устройств дополнительно должны возвратить DOS количество обслуживаемых устройств (в поле n_units) и указатель на массив указателей на блоки BPB (в поле parm). Количество устройств используется DOS для определения логических имен устройств. Например, если Ваш драйвер обслуживает три логических устройства, и на момент его загрузки в системе имеются устройства A:, B: и C:, то устройства, обслуживаемые Вашим драйвером, получат имена D:, E: и F:. Количество устройств необходимо указывать также и в заголовке драйвера, в первом байте поля имени устройства dev_name. Для каждого логического устройства драйвер должен содержать так называемый блок параметров BIOS (BIOS Parameter Block) BPB. Блок BPB содержится в загрузочном секторе диска и содержит информацию, необходимую BIOS для работы с диском. Приведем формат BPB: |(0) |sect|Количество байтов в одном секторе диска. | |2 |_siz| | |(+2)|clus|Количество секторов в одном кластере. | |1 |tsiz| | |(+3)|res_|Количество зарезервированных секторов. | |2 |sect| | |(+5)|fat_|Количество таблиц FAT. | |1 |cnt | | |(+6)|root|Максимальное количество дескрипторов файлов, | |2 |_siz|содержащихся в корневом каталоге диска. | |(+8)|tot_|Общее количество секторов на носителе данных (в разделе| |2 |sect|DOS). | |(+10|medi|Байт-описатель среды носителя данных. | |) 1 |a | | |(+11|fat_|Количество секторов, занимаемых одной копией FAT. | |) 2 |size| |
Страницы: 1, 2, 3, 4