Смекни!
smekni.com

Драйвер виртуального диска (стр. 2 из 2)

; на ввод/вывод.

; На входе :

; ES:DI - содержит адрес блока запроса

; Действия :

; Проверка параметра "номер сектора" на допустимость.

; Преобразование этого параметра в "сегмент:смещение".

; Выровнять счетчик для предотвращения "перекрытия".

; На выходе :

; DS:SI - содержит адрес "сектора" в RAM-диске

; ES:DI - содержит адрес блока запроса

; CX - содержит количество передаваемых слов.

;

verify PROC NEAR

; проверим что номера начального и конечного секторов лежат в пределах

; от 0 до N.

mov cx,request.start ; сравним номер начального

cmp cx,bpb.nls ; сектора с количеством

jae out_of_range ; логических секторов

add cx,request.count ; найдем номер конечного

dec cx ; сектора и тоже сравним

cmp cx,bpb.nls ; если номера секторов

jb in_range ; нормальные то продолжим

; заданные секторы не содержатся на диске

out_of_range:

mov ax,ST_ERROR OR SECTOR_NOT_FOUND

mov request.count,0 ; ничего не было передано

stc ; возвращаемся с ошибкой

ret

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

in_range:

mov ax,bpb.bps ; количество байт в секторе

mov cl,4 ; разделим на 16 для получения

shr ax,cl ; размера в параграфах

mul request.start ; смещение параграфа относи-

; тельно начала диска

add ax,RPARA ; смещение параграфа относи-

mov dx,cs ; тельно CS

add ax,dx ; абсолютное смещ. параграфа

mov si,ax ; сохраним сегмент в SI

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

mov ax,bpb.bps ; размер сектора в байтах

mul request.count ; счетчик передачи в байтах

cmp dx,0 ; проверим на корректность

jne out_of_range

; выровняем счетчик в AX для предотвращения перекрытия

mov cx,word ptr request.bufptr

cmp ax,0 ; смещение = 0

je set_size

neg cx ; остаток = 64K - смещение

cmp cx,ax ; буфера

jae set_size ; если остаток меньше счетчика,

mov ax,cx ; то передаем только остаток

; установим количество передаваемых секторов и счетчик передачи

set_size:

mov cx,ax ; счетчик передачи в байтах

shr cx,1 ; преобразуем в счетчик слов

div bpb.bps ; (DX был 0) кол-во секторов

mov request.count,ax ; сохраним счетчик передачи

; загрузим в DS:SI адрес блока в памяти

mov ds,si

xor si,si

; установим направление передачи и вернемся без ошибок

cld

clc

ret

verify ENDP

;

IFDEF DEBUG

INCLUDE biosio.asm

PAGE

;

; ************ КОД И ДАННЫЕ ДЛЯ ОТЛАДКИ *************

;

; Отладочные сообщения

;

NO_COMMAND_msg db 'NO COMMAND',CR,LF,'$'

INIT_msg db 'INITialization',CR,LF,'$'

MEDIA_CHECK_msg db 'MEDIA Check',CR,LF,'$'

BUILD_BPB_msg db 'Build BIOS Parameter Block',CR,LF,'$'

IOCTL_INPUT_msg db 'IO Control Input',CR,LF,'$'

READ_msg db 'Input from Device',CR,LF,'$'

READ_NOWAIT_msg db 'Nondestructive Input no-wait',CR,LF,'$'

INPUT_STATUS_msg db 'Input Status',CR,LF,'$'

INPUT_FLUSH_msg db 'Flush Input Queue',CR,LF,'$'

WRITE_msg db 'Output to Device',CR,LF,'$'

WRITE_VERIFY_msg db 'Output with Verify',CR,LF,'$'

OUTPUT_STATUS_msg db 'Output Status',CR,LF,'$'

OUTPUT_FLUSH_msg db 'Flush Output Queue',CR,LF,'$'

IOCTL_OUTPUT_msg db 'IO Control Output',CR,LF,'$'

DEVICE_OPEN_msg db 'Open a Device',CR,LF,'$'

DEVICE_CLOSE_msg db 'Close a Device',CR,LF,'$'

REMOVABLE_msg db 'Is Media Removable',CR,LF,'$'

GENERIC_IOCTL_msg db 'Generic IOCTL Request',CR,LF,'$'

GET_LOGICAL_msg db 'Get Logical Device',CR,LF,'$'

SET_LOGICAL_msg db 'Set Logical Device',CR,LF,'$'

;

PAGE

;

; ===== ТАБЛИЦА АДРЕСОВ ОТЛАДОЧНЫХ СООБЩЕНИЙ =====

;

message_table LABEL WORD

dw offset INIT_msg ; 01 - инициализация

dw offset MEDIA_CHECK_msg ; 02 - проверка носителя

dw offset BUILD_BPB_msg ; 03 - построить BPB

dw offset IOCTL_INPUT_msg ; 04 - ввод IOCTL

dw offset READ_msg ; 05 - ввод из устройства

dw offset READ_NOWAIT_msg ; 06 - неразруш. ввод без ожид.

dw offset INPUT_STATUS_msg ; 07 - ввод статуса

dw offset INPUT_FLUSH_msg ; 08 - сброс входной очереди

dw offset WRITE_msg ; 09 - вывод на устройство

dw offset WRITE_VERIFY_msg ; 10 - вывод с проверкой

dw offset OUTPUT_STATUS_msg ; 11 - вывод статуса

dw offset OUTPUT_FLUSH_msg ; 12 - сброс выходной очереди

dw offset IOCTL_OUTPUT_msg ; 13 - вывод IOCTL

dw offset DEVICE_OPEN_msg ; 14 - открыть устройство

dw offset DEVICE_CLOSE_msg ; 15 - закрыть устройство

dw offset REMOVABLE_msg ; 16 - носитель сменный ?

dw offset NO_COMMAND_msg ; 17 -

dw offset NO_COMMAND_msg ; 18 -

dw offset NO_COMMAND_msg ; 19 -

dw offset GENERIC_IOCTL_msg ; 20 - групповой IOCTL запрос

dw offset NO_COMMAND_msg ; 21 -

dw offset NO_COMMAND_msg ; 22 -

dw offset NO_COMMAND_msg ; 23 -

dw offset GET_LOGICAL_msg ; 24 - получить имя диска

dw offset SET_LOGICAL_msg ; 25 - установить имя диска

;

PAGE

; PRINT_COMMAND

;

; Эта процедура вызывает функцию BIOS для печати (_biosprt), передавая

; ей адрес строки, содержащей имя только что вызванной команды. При

; вызове этой процедуры удвоенный код команды передается в регистре BX.

; Все используемые регистры сохраняются.

;

print_command PROC NEAR

push ax ; сохраним содержимое рег. AX

mov ax, BLUE_F OR BRIGHT OR BLACK_B ; установим цвет

push ax

mov ax,word ptr message_table[bx] ; адрес строки

push ax

call _biosprt ; вызываем процедуру BIOS

add sp,4 ; очищаем стек от параметров

pop ax ; восстанавливаем AX и выходим

ret

print_command ENDP

ENDIF

;

PAGE

;

;** ВНУТРЕННИЙ СТЕК И КОНЕЦ ОПЕРАЦИОННОЙ ЧАСТИ ДРАЙВЕРА **

;

db 32 DUP ('stack ') ; внутренний стек глубиной

local_stack EQU $ ; 256 байт

;

bpb_tab dw offset bpb ; указатель на BPB

;

LAST_USED EQU $ ; адрес завершения

;

;*** ХАРАКТЕРИСТИКИ RAM-ДИСКА, ПРИНИМАЕМЫЕ ПО УМОЛЧАНИЮ ***

;

; Параметры для 5-1/4" двустороннего двойной плотности диска с девятью

; секторами на дорожке.

;

MTYPE EQU 0FDh ; байт описателя носителя

TRACKS EQU 40 ; 40 дорожек

SECTORS EQU 9 ; 9 секторов на дорожке

DSIZE EQU 512 ; 512 байт в секторе

SIDES EQU 2 ; 2 стороны на диске

;

FSECS EQU 2 ; количество секторов в FAT

DIREN EQU 112 ; количество элементов директория

DSECS EQU 7 ; 7 секторов в директории

CLSIZ EQU 2 ; 2 сектора в кластере

;

STOTAL EQU TRACKS*SECTORS*SIDES ; всего секторов

PTOTAL EQU (DSIZE/16)*STOTAL ; всего параграфов

;

; ******** НАЧАЛО ОБЛАСТИ ДАННЫХ RAM-ДИСКА **********

;

; RAM-диск д.б. выровнен на границу параграфа

;

IF ($-ORIGIN) mod 16

ORG ($-ORIGIN) + 16 - (($-ORIGIN) mod 16)

ENDIF

RDISK LABEL BYTE ; начало RAM-диска

RPARA EQU ($-ORIGIN)/16 ; размер кода в параграфах

;

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

;

jmp short boot ; короткий JMP (2 байта)

nop ; требуется для boot_record

db 'IBM 3.1' ; 8 байт имя и версия

;

bpb bpbstrc <DSIZE,CLSIZ,1,2,DIREN,STOTAL,MTYPE,FSECS>

dw SECTORS ; количество секторов на дорожке

dw SIDES ; количество головок чтения/записи

dw 0 ; количество скрытых секторов

boot:

db (DSIZE-30) DUP (?) ; остаток boot_sector

;

; ------------ Таблицы размещения файлов (FAT) -----------------------

; ; первые два элемента FAT

FAT_1 db MTYPE,0FFh,0FFh ; нулевой остаток FAT

db (DSIZE-3) DUP (0)

db ((FSECS-1) * DSIZE) DUP (0)

FAT_2 db MTYPE,0FFh,0FFh ; первые два элемента FAT

db (DSIZE-3) DUP (0) ; нулевой остаток FAT

db ((FSECS-1) * DSIZE) DUP (0)

;

; ------------ Сектора директория ------------------------------------

;

DIREC db 'RAM_DISK ' ; имя тома (11 байт)

db 08h ; VID

db 10 DUP (?) ; зарезервировано

dw 0600h ; время 12:00:00 (полдень)

dw 021h ; дата 1 января 1980 года

dw 0 ; начальный кластер 0

dd 0 ; размер файла 0

db (DSIZE-32) DUP (0) ; нулевой остаток директория

db ((DSECS-1) * DSIZE) DUP (0)

BUFFER LABEL BYTE ; начало области данных

;

; ************ ПРОЦЕДУРА ИНИЦИАЛИЗАЦИИ **************

;

INCLUDE stdmac.inc

;

; ============ Область данных инициализации ===========

;

$signon db 'RAM DISK Driver Version 1.00 Installed: Drive

$desig db 'A'

$crlf db 0Dh,0Ah,'$'

;

; ============ Начало процедуры инициализации ===========

;

INIT PROC NEAR ; 00 - инициализация

;

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

; таблицу BPB

;

mov request.endadro,0 ; адрес конца драйвера

mov request.endadrs,cs

add request.endadrs,(RPARA+PTOTAL) ; последний параграф

mov request.units,1

mov request.bpbtabo,offset bpb_tab

mov request.bpbtabs,cs

mov al,$desig ; скорректируем имя диска

add al,request.devnum

mov $desig,al

;

; вывод на экран идентификационной строки

@DisStr $signon

;

; скорректируем значение "max_cmd" исходя из версии MS-DOS

@GetDOSVersion ; получим номер версии MS-DOS

cmp al,3 ; MS-DOS версии 3.00 и выше ?

jb init_done ; нет - прекращаем инициализацию

mov [max_cmd],CMD_PRE_32 ; команды для MS-DOS 3.00

cmp ah,2 ; MS-DOS версии 3.20 и выше ?

jb init_done ; нет - прекращаем инициализацию

mov [max_cmd],CMD_32 ; команды для MS-DOS 3.20

;

init_done:

xor ax,ax ; нет проблем !

ret

INIT ENDP

;

; ************ КОНЕЦ ДРАЙВЕРА. КОНЕЦ ФАЙЛА ************

;

_TEXT ENDS

END

Список используемой литературы