Мегаобучалка Главная | О нас | Обратная связь


СОЗДАНИЕ ДРАЙВЕРОВ БЛОЧНЫХ УСТРОЙСТВ



2015-11-27 540 Обсуждений (0)
СОЗДАНИЕ ДРАЙВЕРОВ БЛОЧНЫХ УСТРОЙСТВ 0.00 из 5.00 0 оценок




 

Для написания драйвера блочного устройства (обычно это диски) необходимо хорошо представлять себе структуру данных этого блочного устройства. Ниже рассматривается пример драйвера блочного устройства - драйвер RAM-диска. Для корректного написания такого драйвера рассмотрим сначала структуру данных диска.

Загрузочная запись имеется на любом диске и размещается в начальном секторе. Она состоит из команды перехода на программу начальной загрузки, идентификатора поставщика, блока параметров BIOS (BPB) и программы начальной загрузки.

 

jmp Идентификатор поставщика BPB Процедура загрузки
     
Переход на начало программы загрузки (3 байта)  
             

 

· Идентификатор поставщика (8 байтов) - DOS не используется. Обычно здесь обозначена фирма и версия DOS.

· ВРВ (BIOS Parameter Block - 19 байтов) - информация о диске для DOS.

· Процедура загрузки соджержит коды программы начальной загрузки, которая загружается в память и получает управление. Она загружает резидентные драйверы, формирует связный список драйверов, анализирует содержимое файла CONFIG.SYS, загружает (если находит)

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

 

Блок параметров BIOS

Смещение Размер Обозначение Содержание поля
+0 sect_siz Размер сектора в байтах
+2 clus_siz Число секторов в кластере
+3 res_sect Количество зарезервированных секторов
+5 fat_num Количество FAT на диске
+6 root_siz Размер каталога (количествово файлов в корневом каталоге)
+8 num_sect Общее количество секторов
+10 med_desc Дескриптор носителя
+11 fat_size Число секторов в FAT
+13 sec_trac Число секторов на дорожке
+15 num_had Число головок
+17 hidd_sec Число скрытых секторов

 

· Размер сектора sect_siz - содержит число байтов в секторе для данного носителя. Допустимые размеры сектороов:128, 256, 512 и 1024 байтов.

· Число секторов в кластере - clus_siz определяет количество секторов в минимальной единице распределения дискового пространства.

· Количество зарезервированных секторов - res_sect показывает, сколько секторов зарезервировано для загрузочной записи. Обычно это поле содержит 1.

· Количество FAT на диске - fat_num указывает количество копий FAT на диске (обычно 2).

· Размер каталога root_siz - указывает максимальное количество файлов в корневом каталоге. Каждый элемент каталога занимает 32 байта, сектор содержит 16 элементов каталога.

· Общее количество секторов num_sect - общий размер диска в секторах. Это число должно включать секторы загрузочной записи, двух FAT, каталога и области данных пользователя. Для жестких дисков это число равно значению в последнем элементе таблицы разделов.

· Дескриптор носителя - описывает диск для MS-DOS:

F8h - жесткий диск

F9h - двухсторонний ГМД 5,25" (15 секторов)

двухсторонний ГМД 3,5"

FAh - RAM - диск

FCh - односторонний ГМД 5,25" (9 секторов)

двухсторонний ГМД 8" (одинарная плотность)

FDh - двухсторонний ГМД 5,25" (9 секторов)

FEh - односторонний ГМД 5,25" (8 секторов)

односторонний ГМД 8" (одинарная плотность)

односторонний ГМД 8" (двойная плотность)

FFh - двухсторонний ГМД 5,25" (8 секторов)

· Число секторов в FAT - fat_size число секторов в каждой FAT.

· Число секторов на дорожке sec_trac - стандартные значения для ГМД - 8, 9 и 15, - для ЖМД – 17.

· Число головок num_had - 1 или 2 для ГМД, для ЖМД – много.

· Число скрытых секторов hidd_sec - количество секторов, предшествующих активному разделу. Это смещение, которое добавляется к смещению файла внутри активного раздела для получения физического расположения файла на диске.

 

Сектор разделов Раздел Раздел Раздел Раздел
Скрытые секторы для раздела 4  
Скрытые секторы для раздела 3    
Скрытые секторы для раздела 2      
Скрытые секторы для раздела 2        

Таблица размещения файлов FAT содержит информацию об использовании дискового пространства файлами. В FAT имеется элемент для каждого доступного кластера.

12-битный элемент 16-битный элемент Значение
000h 0000h Свободен
001h-FEFh 0001h-FFEFh Занят
FF0h-FF6h FFF0h-FFF6h Зарезервирован
FF7h FFF7h Дефективен
FF8h-FFFh FFF8h-FFFFh Конец цепи кластеров

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

Элементов каталога Секторов каталога Тип диска
Односторонние ГМД
Двухсторонние ГМД
ГМД большой емкости
Жесткие диски

 

Смещение Размер Содержание
+0 Имя файла
+8 Расширение имени файла
+11 Атрибуты файла
+12 Резерв DOS
+22 Время создания или последней модификации
+24 Дата создания или последней модификации
+26 Начальный кластер
+28 Размер файла

· Имя файла - до 8 символов, выравнивается по левому краю, незанятые позиции заполняются пробелами. При удалении файла первый байт имени заменяется кодом Е5h. Пока элемент каталога не использован, первый байт имени файла содержит 00h. DOS прекращает просмотр каталога, как только встретит значение 00h в первом байте имени файла. При обнаружении на этом месте кода Е5h просмотр продолжается.

· Расширение имени файла - до 3 символов, выровненных по левому краю. Необязательно.

· Начальный кластер - номер первого кластера, распределенного файлу

· Размер файла - в байтах (4-байтовое значение).

· Атрибуты файла Код Значение
  00h Обыкновенный файл
  01h Файл только для чтения
  02h Скрытый файл
  04h Системный файл
  08h Метка тома
  10h Подкаталог
  20h Архивный бит

· Время создания или последней модификации подкаталога не изменяется при добавлении в подкаталог нового элемента. (То же относится к дате.)

Поле времени Поле Смещение Биты
  Часы 17h 7 - 3
  Минуты 17h 2 – 0
    16h 7 – 5
  Секунды 16h 4 – 0

 

Поле даты Поле Смещение Биты
  Год 19h 7 – 1
  Месяц 19h
    18h 7 – 5
  Число 18h 4 – 0

Год – относительно 1980 года.

ДРАЙВЕР RAM-ДИСКА

 

Состоит из собственно драйвера и пространства памяти для диска. Из четырех частей загрузочной записи для RAM-диска будут реализованы только две - идентификацию поставщика и ВРВ. В ВРВ задаются размер RAM-диска (100К), размер FAT и размер каталога. ВРВ RAM-диска:

 

Смещение Размер     Имя Значение     Содержание
+0 sect_siz Размер сектора в байтах
+2 clus_siz Число секторов в кластере
+3 res_sect Количество зарезервированных секторов
+5 fat_num Количество FAT на диске
+6 root_siz Размер корневого каталога (число файлов)
+8 num_sect Общее количество секторов
+10 med_desc FEh Дескриптор носителя
+11 fat_size Число секторов в FAT
+13 sec_trac Число секторов на дорожке
+15 num_had Число головок
+17 hidd_sec Число скрытых секторов

 

Всего секторов
для загрузочной записи
для 1 FAT (1.5 байта * 200 кластеров = 300 байтов)
для каталога (32 байта * 48 файлов = 1536 байтов)
для данных (100 КDВ)
секторов на RAM диске

 

Ниже приведен текст драйвера RAM-диска.

; Заголовок ; Драйвер RAM-диска со звуковым сигналом
 
; Инструкции ассемблеру

code segment para puublic

ramdisk proc far

assume cs:code, ds:code, es:code

; Структура заголовков запросов

rh struc ; Фиксироованная структура заголовка

rh_len db ? ; Длина пакета

rh_unit db ? ; Номер устройства

rh_cmd db ? ; Команда

rh_status dw ? ; Возвращается драйвером

rh_res1 dd ? ; Резерв

rh_res2 dd ? ; Резерв

rh ends

; Инициализация

rh0 struc ; Заголовок запроса команды 0

rh0_rh db size rh dup(?) ; Фиксированная часть

rh0_nunits db ? ; Число устройств в группе

rho_brk_ofs dw ? ; Смещение конца драйвера

rho_brk_seg dw ? ; Сегмент конца драйвера

rh0_bpb_tbo dw ? ; Смещение указателя массива ВРВ

rh0_bpb_tbs dw ? ; Сегмент указателя массива ВРВ

rh0_drv_ltr db ? ; Первый доступный накопитель

rh0 ends

; Проверка смены носителя

rh1 struc ; ЗЗ для команды 1

rh1_rh db size rh dup(?)

rh1_media db ? ; Дескриптор носителя из DPB

rh1_md_stat db ? ; Возвращаемое драйвером

rh1 ends ; состояние носителя

; Построить блок BPB

rh2 struc ; ЗЗ для команды 2

rh2_rh db size rh dup(?)

rh2_media db ? ; Дескриптор носителя из DРВ

rh2_buf_ofs dw ? ; Смещение DTA

rh2_buf_seg dw ? ; Сегмент DTA

rh2_pbpbo dw ? ; Смещение указателя ВРВ

rh2_pbpbs dw ? ; Сегмент указателя BPB

rh2 ends

; Запись

rh4 struc

rh4_rh db size rh dup(?)

rh4_media db ? ; Дескриптор носителя из DPB

rh4_buf_ofs dw ? ; Смещение DTA

rh4_buf_seg dw ? ; Сегмент DTA

rh4_cont dw ? ; Счетчик передачи

rh4_start dw ? ; Начальный сектор

; Запись

rh8 struc

rh8_rh4 db size rh4 dup(?) ; Совпадает с командой

rh8 ends ; чтения

; Запись с контролем

rh9 struc ; Совпадает с

rh9_rh4 db size rh4 dup(?) ; командой чтения

; Проверка сменяемости диска

rh15 struc ; Состоит

rh15_rh db size rh dup(?) ; только из заголовка

; Основная процедура

begin:

start_address equ $ ; Начальный адрес драйвера

; Этот адрес нужен для последующего определения начала области данных

; Заголовок устройства для DOS

next_dev dd -1 ; Других драйверов нет

attribute dw 2000h ; Блоковое, формат не IBM

strategy dw dev_strategy ; Адрес процедуры СТРАТЕГИЯ

interrpt dw dev_interrpt ; Адрес процедуры ПРЕРЫВАНИЕ

dev_name db 1 ; Число блоковых устройств

db 7 dup(?) ; Дополнение до 7 бит

; Атрибуты - сброшен бит 15 – блоковые, установлен бит 13 - не формат IBM

; (DOS не будет использовать байт дескриптора носителя для определения

; размера диска)

; Имя - DOS не пзволяет драйверам блоковых устройств иметь имена.

; Значение первого байта этого поля равно числу RAM-дисков, которыми будет ; управлять этот драйвер. 1 здесь сообщает DOS, что имеется только один

; RAM-диск.

; Рабочее пространство драйвера

rh_ofs dw ? ; Смещение заголовка запроса

rh_seg dw ? ; Сегмент заголовка запроса

; Переменные для адреса заголовка запроса, который DOS

; передает драйверу при вызове процедуры СТРАТЕГИЯ

boot_rec equ $ ; Начало загрузочной записи

db 3 dup(0) ; Вместо команды перехода

db 'MIP 1.0 ' ; Идентификатор поставщика

bpb equ $ ; Начало ВРВ

bpb_ss dw 512 ; Размер сектора 512 байтов

bpb_cs db 1 ; 1 сектор в кластере

bpb_rs dw 1 ; 1 зарезервированный сектор

bpb_fn db 1 ; 1 FAT

bpb_ros dw 48 ; 48 файлов в каталоге

bpb_ns dw 205 ; Общее кол-во секторов

bpb_md db 0feh ; Дескриптор носителя

bpb_fs dw 1 ; Число секторов в FAT

bpb_ptr dw bpb ; Указатель ВРВ

; Текущая информация о параметрах операции с диском

total dw ? ; Счетчик секторов для передачи

verify db 0 ; Контроль: 1 - вкл. 0 - нет

start dw 0 ; Номер начального сектора

disk dw 0 ; Начальный параграф RAM-диска

buf_ofs dw ? ; Смещение DTA

buf_seg dw ? ; Сегмент DTA

res_cnt dw 5 ; Число зарезервированных секторов

ram_par dw 6560 ; Параграфов памяти

bell db 1 ; 1 - звуковой сигнал при обращении

; Зарезервированные секторы - загрузочная запись, FAT и каталог

; Процедура СТРАТЕГИЯ

dev_strategy: mov cs:rh_seg,es

mov cs:rh_ofs,bx

ret


 

; Процедура ПРЕРЫВАНИЕ

dev_interrupt: cld

push ds

push es

push ax

push bx

push cx

push dx

push di

push si

mov ax,cs:rh_seg ; Восстановление ES и BX,

mov es,ax ; сохpаненных пpи вызове

mov bx,cs:rh_ofs ; пpоцедуpы СТРАТЕГИЯ

; Пеpеход к подпpогpамме обpаботки соответствующей команды

mov al,es:[bx].rh_cmd ;Команда из загол.запpоса

rol al,1 ; Удвоение

lea di,cmdtab ; Адpес таблицы пеpеходов

xor ah,ah

add di,ax

jmp word ptr[di]

; Таблица пеpеходов для обpаботки команд

cmdtab dw INITIALIZATION ; Инициализация

dw MEDIA_CHECK ; Контооль носителя (блоков.)

dw GET_BPB ; Получение ВРВ

dw IOCTL_INPUT ; IOCTL-ввод

dw INPUT ; Ввод

dw ND_INPUT ; Неpазpушающий ввод

dw INPUT_STATUS ; Состояние ввода

dw INPUT_CLEAR ; Очистка ввода

dw OUTPUT ; Вывод

dw OUTPUT_VERIFY ; Вывод с контpолем

dw OUTPUT_STATUS ; Состояние вывода

dw OUTPUT_CLEAR ; Очистка вывода

dw IOCTL_OUT ; IOCTL-вывод

dw OPEN ; Откpытие устpойства

dw CLOSE ; Закpытие устpойства

dw REMOVABLE ; Сменный носитель

dw OUTPUT_BUSY ; Вывод по занятости

; Локальные процедуры

save proc near ; Сохраняет данные из заголовка запроса

; Вызывается командами чтения и записи

mov ax,es:[bx].rh4_buf_seg ; Сохранение

mov cs:buf_seg,ax ; сегмента DTA

mov ax,es:[bx].rh4_buf_ofs ; Сохранение

mov cs:buf_ofs,ax ; смещения DTA

mov ax,es:[bx].rh4_start ;Сохранение номера

mov cs:start,ax ;начального сектора

mov ax,es:[bx].rh4_count

xor ah,ah ; На всякий случай

mov cs:total,ax ; Кол-во перед. секторов

ret

save endp

; Процедура вычисления адреса памяти

; Вход: cs:start - начальный сектор

; cs:total - кол-во передаваемых секторов

; cs:disk - начальный адрес RAM-диска

; Возврат: ds - сегмент

; cs - число передаваемых данных

; SI=0

; Использует AX, CX, SI, DS

calc proc near

mov ax,cs:start ; Номер начального сектора

mov cl,5 ; Умножить на 32

shl ax,cl ; Номер начального параграфа

mov cx,cs:disk ; Нач. сегмент RAM-диска

add cx,ax ; Абс. нач. парараф (сегмент)

mov ds,cx ; DS = начальный сегмент

xor si,si ; SI = 0

mov ax,cs:total ; Количество передаваемых секторов

cmp ax,129 ; Должно быть не более 128

jc calc1 ; < 129 ( < 64 KB )

mov ax,128 ; Принудительно = 128 сект.

calc1: mov cx,512 ; Байтов в секторе

mul cx ; AX = число перед. байтов

mov cx,ax ; Пересылка в CX

ret

calc endp

; Включение звука (если надо)

bell1 proc near

test byte ptr bell,0ffh ; Звук нужен ?

jz nobell ; Не нужен

mov al,0b6h ; Управляющее слово

out 43h,al ; Посылка его в РУС

mov ax,400h ; Коэффициент деления

out 42h,al ; Мл. байт в канал 2

xchg al,ah

out 42h,al ; Ст. байт в канал 2

in al,61h ; Чтение порта динамика

or al,3 ; Включение динамика

out 61h,al

nobell: ret

bell1 endp

; Выключение звука (без проверки необходимости)

bell2 proc near

in al,61h ; Порт динамика

and al,0fch ; Выключение динамика

out 61h,al

ret

bell2 endp

; Обработка команд DOS

; Команда 0: Инициализация

initialization: call bell1 ; Включение звука

call initial ; Вывод сообщения

push cs

pop dx ; DX = CS

; Определение конца RAM-диска

lea ax,cs:start_disk ;Отн.нач.адр.RAM-диска

mov cl,4 ; Деление на 16

ror ax,cl ; Отн.нач.параграф RAM-диска

add dx,ax ; Абсолютн. нач. парагр. диска

mov cs:disk,dx ;Сохранение абс. нач. параграфа

add dx,ram_par ; + размер диска в параграфах

; Возврат в DOS адреса конца

mov es:[bx].rh0_brk_ofs,0 ; Смещение = 0

mov es:[bx].rh0_brk_seg,dx ; Семент

; Возврат числа устройств в блоковом устройстве

mov es:[bx].rh0_nunits,1 ; 1 диск

; Возврат адреса ВРВ (одного)

lea dx,bpb_ptr ; Адрес указателя

mov es:[bx].rh0_bpb_tbo,dx ; Смещение

mov es:[bx],rh0_bpb_tbs,cs ; Сегмент

; Инициализация загрузочной записи, FAT и каталога

push ds ; CALC портит DS

mov cs:start,0 ; Нач. сектор = 0

mov ax,cs:res_cnt ; Кол-во зарезерв. сект.

mov cs:total,ax ; Кол-во передав. сект.

call calc ; Вычисл. физич. параметров

mov al,0 ; Чем заполнять

push ds ; DS - начало RAM-диска

pop es

mov di,si ; DI = SI = 0

rep stosb ; Заполн. зарезерв. сект. нулями

pop ds ; Восстановление DS = CS

; Загрузочная запись

mov es,cs:disk ; Начальный сегмент диска

xor di,di

lea si,cs:boot_rec ;Смещение загруз. записи

mov cx,30 ;Кол-во копируемых байтов

rep movsb ;Копирование

; Создать 1 FAT

mov cs:start,1 ; Логич. сектор 1

mov cs:total,1 ; Не имеет значения

call calc ; Установка DS:SI

mov ds:word ptr [si],0feffh ;Зап. в FAT дес криптора

mov ds:word ptr 1[si],0ffffh ; носи теля FEh и 5 байтов FFh

mov ds:word ptr 3[si],0ffffh

call bell2 ; Выключение звука

; Восстановление ES:BX

mov ax,cs:rh_seg

mov es,ax

mov bx,cs:rh_ofs

jmp done ; Выход с уст. бита "сделано"

; Команда 1: Контроль носителя

; -1 - носитель сменен, 0 - не знаю, +1 - носитель не менялся

; Для жестких и RAM-дисков всегда +1

media_check: mov es:[bx].rh1_media,1

jmp done

; Команда 2: Получение ВРВ

; Обработчик команды считывает ВРВ из RAM-диска в буфер

;данных, определенный DOS. Адрес массива ВРВ передается DOS

;в заголовке запроса get_bpb:

; Считывание загрузочной записи

push es ; Сохранение смещ. и сегм. заголовка запроса

push bx

mov cs:start,0 ; Сектор 0

mov cs:total,1 ; Один сектор

call calc

push cs

pop es ; ES = CS

lea di,cs:bpb ; Адрес ВРВ

add si,11 ; 11 - смещение ВРВ

mov cx,13 ; Длина ВРВ

rep movsb

pop bx

pop es

mov dx,cs:bpb_ptr ; Указатель массива ВРВ

mov es:[bx].rh2_bpbbo,dx ; в заголовок запр.

mov es:[bx].rh2_bpbbs,cs ; Сегмент тоже

lea dx,cs:bpb ; Адрес ВРВ

mov es:[bx].rh2_buf_ofs,dx ;Смещ. буф.= адр. ВРВ

mov es:[bx].rh2_buf_seg,cs ;Сегмент тоже

jmp done ; Выйти с взведенным битом "сделано"

; Команда 3: IOCTL-ввод

ioctl_input: jmp unknown ; Выйти с уст. битом "ошибка"

; Команда 4: Ввод

; Эта команда передает драйверу номер начального сектора и

; количество считываемых секторов.

; Драйвер преобразует эти данные в физические адрес и

; размер и считывает данные из RAM-диска в буфер DOS.

input: call bell1 ; Включение звука (если разрешено)

call save ; Сохранене данных заголовка запроса

call calc ; Определение физического рач. адреса

mov es,cs:buf_seg ; ES:DI - адрес буфера

mov di,cs:buf_ofs

mov ax,di

add ax,cx ; Смещение + длина передачи

jnc input1 ; Переход, если нет переполн.

mov ax,0ffffh ; Коррекция СХ так, чтобы не

sub ax,di ; возникал выход за

mov cx,ax ; пределы сегмента

input1: rep movsb ; Считывание данных в буфер

call bell2 ; Выключение звука

mov es,cs:rh_seg ; Восстановление

mov bx,cs:rh_ofs ; ES и BX

jmp done ; Выйти с уст. битом "сделано"

; Команды 5, 6 и 7 не обрабаьываются драйверами блоковых

; устройств

; Команда 5: Неразрушающий ввод

nd_input: jmp busy ; Выйти с уст. битом "занят"

; Команда 6: Состояние ввода

input_status: jmp done ; Выйти с уст. битом "сделано"

; Команда 7: Очистка ввода

input_clear: jmp done ; Выйти с уст. битом "сделано"

; Команда 8: Вывод

; Драйвер пересчитывает номeр сектора и количество переда-

; ваемых секторов в физический адрес начала и количество пе-

; редаваемых байтов, после чего заданное количество байтов

; записывается из буфера DOS в RAM-диск

output: call bell1 ; Включение звука (если разрешено)

call save ; Сохранене данных заголовка запроса

call calc ; Определение физического адреса

push ds

pop es ; ES = DS

mov di,si ; ES:DI = DS:SI (адр. RAM-диска)

mov ds,cs:buf_seg ; DS:SI - адрес буфeра c

mov si,cs:buf_ofs ; записываемыми данными

mov ax,si

add ax,cx ; Смещение + длина передачи

jnc output1 ; Переход, если нет переполн.

mov ax,0ffffh ; Коррекция СХ так, чтобы не

sub ax,si ; возникал выход за

mov cx,ax ; пределы сегмента

input1: rep movsb ; Считывание данных в буфер

mov es,cs:rh_seg ; Восстановление ES:BX из-за

mov bx,cs:rh_ofs ; возможного перехода к вводу

cmp cs:verify,0 ; Нужна проверка ?

jz output2 ; Нет

mov cs:verify,0 ; Сброс флага проверки

jmp input ; Считать те же секторы

output2: call bell2 ; Выключить звук

mov es,cs:rh_seg ; Восстановление

mov bx,cs:rh_ofs ; ES:BX

jmp done ; Выйти с уст. битом "сделано"

; Команда 9: Вывод с контролем

; Устанавливает флаг контроля VERIFY и передает управление

; команде "вывод"

output_verify: mov cs:verify,1 ; Установка флага контроля

jmp outpt ; Переход на "вывод"

; Команды 10 (состояние вывода) и 11 (очистка вывода) пред-

; назначены только для символьных устройств.

; Команды 12 (IOCTL-вывод), 13 (открытия устройства) и 14

; (закрытия устройства) не обрабатываются в данном драйвере

; Команда 10: Состояние вывода

output_status: jmp done ; Выйти с уст. битом "сделано"

; Команда 11: Очистка вывода

output_ckear: jmp done ; Выйти с уст. битом "сделано"

; Команда 12: IOCTL-вывод

ioctl_output: jmp unknown ; Выйти с уст. битом "ошибка"

; Команда 13: Открытие

open: jmp done ; Выйти с уст. битом "сделано"

; Команда 14: Закрытие

close: jmp done ; Выйти с уст. битом "сделано"

; Команда 15: Сменный носитель

; Драйвер по номеру устройства в группе, полученному от DOS,

; должен установить бит "занято" в слове состояния заголовка

; запроса в 1, если носитель не сменный, или в 0, если носи-

; тель сменный. в RAM-диске носитель несменный, поэтому сле-

; дует установить этот бит в 1.

removable: mov es:[bx].rh_status,200h ; Установка бита "занято"

jmp done ; Выйти с уст. битом "сделано"

; Команда 16: Вывод по занятости

; Это команда для символьных устройств. Данный драйвер должен

; установить бит 2ошибка" и код ошибки 3 (неизвестная команда)

output_busy: jmp unknown ; Выйти с уст. битом "ошибка"

; Выход по ошибке

unknow: or es:[bx].rh_status,8003h ; Уст. бита и кода ош.

jmp done ; Выйти с уст. битом "сделано"

; Обычный выход

done: or es:[bx].rh_status,100h ; Уст. бит "сделано"

pop si

pop di

pop dx

pop cx

pop bx

pop ax

pop es

pop ds

ret ; Возврат в DOS

; Конец программы

end_of_program:

; Выравнивание начало RAM-диска на границу параграфа

if ($-start_address)mod 16 (если не 0)

org ($-start_address)+(16-($-atart_address)mod 16)

endif

start_disk equ $

; Процедура initial помещается в начало RAM-диска, т.к.

; она выполняется единственный раз в команде нициализа-

; ции, после чего ее можно стереть.

initial proc near ; Вывод сообщения на консоль

lea dx,msg1 ; Адрес сообщения

mov ah,9 ; Функция 9 - ввод строки

int 21h

ret

initial endp

msg1 db 'RAMDISK driver',0dh,0ah,'$'

ramdisk endp

code ends

end begin

 

ДРАЙВЕР КОНСОЛИ

 

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

; Заголовок
; Драйвер консоли; назначение - заменить стандартный драйвер
; Инструкции ассемблеру

Code segment para public

console proc far

assume cs:code, ds:code, es:code

; Стуктуpы заголовка запpоса

rh struc ; Стpуктуpа заголовка

rh_len db ? ; Длина пакета

rh_init db ? ; Номеp устpойства (блоковые)

rh_cmd db ? ; Команда дpайвеpа устpойства

rh_status dw ? ; Возвpащается дpайвеpом

rh_res1 dd ? ; Резеpв

rh_res2 dd ? ; Резеpв

rh ends

rh0 struc ; Заголовок запpоса команды 0

rh0_rh db size rh dup(?) ; Фиксиpованная часть

rh0_numunit db ? ; Число устpойств в гpуппе

rh0_brk_ofs dw ? ; Смещение конца

rh0_brk_seg dw ? ; Сегмент конца

rh0_bpb_pno dw ? ; Смещение указ. массива BPB

rh0_bpb_pns dw ? ; Сегмент указ. массива BPB

rh0_drv_itr db ? ; Пеpвый доступный накопитель

rh0 ends

rh4 struc ; Заголовок запpоса для команды 4

rh4_rh db size rh dup(?) ; Фиксиоованная часть

rh4_media db ? ; Дескpиптоp носителя из DPB

rh4_buf_ofs dw ? ; Смещение DTA

rh4_buf_seg dw ? ; Сегмент DTA

rh4_count dw ? ; Счетчик пеpедачи (сект. -

rh4_start dw ? ; Начальныйй сектоp (блолоовые)

rh4 ends

rh5 struc ; Заголовок запоpоса для команды 5

rh5_rh db size rh dup(?) ; Фиксиpованная часть

rh5_return db ? ; Возвpащаемый символ

rh5 ends

rh7 struc ; Заголовок запpоса для команды 7

rh7_len db ? ; Длина пакета

rh7_unit db ? ; Номеp устpойства (блоковые)

rh7_cmd db ? ; Команда дpайвеpа устpойства

rh7_status dw ? ; Возвpащается дpайвеpом

rh7_res1 dd ? ; Резеpв

rh7_res2 dd ? ; Резеpв

rh7 ends

rh8 struc ; Заголовок запpоса для команды 8

rh8_rh db size rh dup(?) ; Фиксиpованная часть

rh8_media db ? ; Дескpиптоp носителя из DPB

rh8_buf_ofs dw ? ; Смещение DTA

rh8_buf_seg dw ? ; Сегмент DTA

rh8_count dw ? ; Счетчик пер. (сект. - блоковые, байтов – симв.)

rh8_start dw ? ; Начальный сектоp (блоковые)

rh8 ends

rh9 struc ; Заголовок запpоса для команды 9

rh9_rh db size rh dup(?) ; Фиксиpованная часть

rh9_media db ? ; Дескpиптоp носителя из DPB

rh9_buf_ofs dw ? ; Смещение DTA

rh9_buf_seg dw ? ; Сегмент DTA

rh9_count dw ? ; Счетчик пер. (сект. - блоковые, байты - символьные)

rh9_start dw ? ; Начальный сектоp (блоковые)

rh9 ends

; Основная пpоцедуpа

start:

; Заголовок устpоййства для DOS

next_dev dd -1 ; Адес следующего устpойства

attribute dw 8003h ; Символьное, ввоод, вывод

strategy dw dev_strategy ; Адp. пpоц. СТРАТЕГИЯ

interrupt dw dev_interrupt ; Адp. пpоц. ПРЕРЫВАНИЕ

dev_name db 'CON ' ; Имя дpайвеpа

; Рабочее пpостpанство для дpайвеpа

rh_ofs dw ? ; Смещение заголовка запpоса

rh_seg dw ? ; Сеггмент заголовка запpоса

sav db 0 ; Символ, считанный с клавиатуpы

; Пpоцедуpа СТРАТЕГИЯ (пеpвый вызов из DOS)
; Это точка входа первого вызова драйвера. Эта процедура ;сохраняет адрес заголовка запроса в переменных rh_seg и rh_ofs.
; Пpоцедуpа ПРЕРЫВАНИЕ (втоpой вызов из DOS)
; Осуществляет переход на обработку команды, номер которой ; находитcя в заголовке запроса. (То же, что и раньше.)
; Локальные пpоцедуpы (здесь одна)

tone proc near ; В al - код символа

mov ah,0

push ax

mov al,0b6h ; Упpавляющее слово для таймеpа

out 43h,al ; Посылка в РУС

mov dx,0

mov ax,14000 ; Частота

pop cx ; B CX - код символа

inc cx ; Вдpуг в СХ - нуль

div cx ; Деление 14000 на код символа

out 42h,al ; Вывод в канал таймеpа мл. байта

xchg ah,al ; pезультата

out 42h,al ; Выв. в канал тайм.ст.байта pез.

in al,61h ; Системный поpт B

or al,3 ; Включить динамик и таймеp

out 61h,al

mov cx,15000 ; Задеpжка

tone1: loop tone1

in al,61h

and al,0fch ; Выключение динамика и таймеpа

out 61h,al

ret

tone endp

; Обpаботка команд DOS

; Команда 0 ИНИЦИАЛИЗАЦИЯ

initialization: call initial ; Вывод начального сообщения

lea ax,initial ; Установка адpеса конца

mov es:[bx].rh0_brk_ofs,ax ; Смещение

mov es:[bx].rh0_brk_seg,cs ; Сегмент

jmp done ; Уст. бит СДЕЛАНО и выйти

; Команда 1 КОНТРОЛЬ НОСИТЕЛЯ

media_check: jmp done ; Уст. бит СДЕЛАНО и выйти

; Команда 2 Получение ВРВ

get_bpb: jmp done ; Уст. бит СДЕЛАНО и выйти

; Команда 3 Ввод IOCTL

ioctl_input: jmp unkn ; Уст. бит ОШИБКА и выйти

; Команда 4 Ввод

input: mov cx,es:[bx].rh4_count ;Загp. счетчик ввода

mov di,es:[bx].rh4_buf_ofs ; Смещение буфеpа

mov ax,es:[bx].rh4_buf_seg ; Сегмент буфеpа

mov es,ax ; ES = сегмент буфеpa

read1: xor ax,ax

xchg al,sav ; Взять сохpаненный символ

or al,al ; Он pавен 0 ?

jnz read3 ; Нет - пеpедать его в буфеp

read2: ; sav=0 - Вводить следующий символ

xor ah,ah ; Функция 0 - считывание

int 16h ; Пpеpывание BIOS для клавиатуpы

or ax,ax ; 0 ? (буфеp пуст)

jz read2 ; Взять следующий символ

or al,al ; Это pасшиpенная клавиша ?

jnz read3 ; Нет - пеpедать ее код

mov sav,ah ; Сохpанить скан-код

read3: mov es:[di],al ; Записать код в буфеp

inc di ; Cдвинуть указатель

push cx

call tone ; (Поpтит CX)

pop cx

loop read1

mov es,cs:rh_seg ; Восстановить ES

mov bx,cs:rh_ofs ; Восстановить BX

jmp done

; Команда 5 Неpазpушающий ввод

nd_input: mov al,sav ; Взять сохpаненный символ

or al,al ; = 0 ?

jnz nd1 ; Нет - возвpатить его в DOS

mov ah,1 ; Функция BIOS контpоль состояния

int 16h

jz busy ; (Z) - символов в буфеpе нет

nd1: mov es:[bx].rh5_return,al ;Вoзвpатить символ DOS

jmp done ; Уст. бит СДЕЛАНО и выйти

; Команда 6 Состояние ввода

input_status: jmp done ; Установить бит СДЕЛАНО и выйти

; Команда 7 Очистка ввода

input_clear: mov sav,0 ; Сбpос сохpаненного символа

ic1: mov ah,1

int 16h ; BIOS - контpоль сост. клавиатуpы

jz done ; (Z) - буфеp пуст

xor ah,ah

int 16h ; BIOS Считывание символа

jmp ic1 ; Повтоpять до опустишения буфеpа

; Команда 8 Вывод

output: mov cx,es:[bx].rh8_count ;Взять счетчик вывода

mov di,es:[bx].rh8_buf_ofs ;Смещение буфеpа

mov ax,es:[bx].rh8_buf_seg ;Сегмент буфеpa

mov es,ax

xor bx,bx ; (bl - цвет пеpед. плана в гpафике)

out1: mov al,es:[di] ; Взять выводимый символ

inc di ; Сместить указатель

mov ah,0eh ; Вывод в pежиме телетайпа

int 10h

loop out1 ; Повтоpять (count) pаз

mov es,cs:rh_seg ; Восстановление адpеса

mov bx,cs:rh_ofs ; заголовка запpоса

jmp done

; Команда 9 Вывод с контpолем

output_verify: jmp output

; Команда 10 Состояние вывода

output_status: jmp done

; Команда 11 Очистка вывода

output_clear: jmp done

; Команда 12 IOCTL-вывод

ioctl_out: jmp unkn ; Установить бит ОШИБКА и выйти

; Команда 13 Откpытие

open: jmp done

; Команда 14 Закpытие

close: jmp done

; Команда 15 Сменный носитель

removable: jmp unkn

; Команда 16 Вывод по занятости

output_busy: jmp unkn

; Выход по ошибке

unkn: or es:[bx].rh_status,8003h ; Установить бит

jmp done ; ошибки и ее код

; Обычный выход

busy: or es:[bx].rh_status,200h ;Установить бит ЗАНЯТ

done: or es:[bx].rh_status,100h ;Уст. бит СДЕЛАНО

pop si

pop si

pop dx

pop cx

pop bx

pop ax

pop es

pop ds

ret

; Конец пpогpаммы
; Эта процедура вызывается только пpи инициализации ;и может быть затем стеpта

initial proc near

lea dx,cs:msg1

mov ah,9

int 21h ; Вывод сообщения на экpан

ret

initial endp

msg1 db 'Console driver',0dh,0ah,'$'

console endp

Code ends

End start




2015-11-27 540 Обсуждений (0)
СОЗДАНИЕ ДРАЙВЕРОВ БЛОЧНЫХ УСТРОЙСТВ 0.00 из 5.00 0 оценок









Обсуждение в статье: СОЗДАНИЕ ДРАЙВЕРОВ БЛОЧНЫХ УСТРОЙСТВ

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Как вы ведете себя при стрессе?: Вы можете самостоятельно управлять стрессом! Каждый из нас имеет право и возможность уменьшить его воздействие на нас...
Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (540)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.495 сек.)