DEVICE_OPEN PROC NEAR ; D - открыть устройство xor ax,ax ret
DEVICE_OPEN ENDP
;
DEVICE_CLOSE PROC NEAR ; E - закрыть устройство xor ax,ax ret
DEVICE_CLOSE ENDP
REMOVABLE PROC NEAR ; F - носитель сменный ? mov ax,ST_BUSY ; нет ! ret
REMOVABLE ENDP
GENERIC_IOCTL PROC NEAR ; 13 - групповой IOCTL запрос xor ax,ax ret
GENERIC_IOCTL ENDP
GET_LOGICAL PROC NEAR ; 17 - получить имя логического xor ax,ax ; диска ret
GET_LOGICAL ENDP
SET_LOGICAL PROC NEAR ; 18 - установить имя логического xor ax,ax ; диска ret
SET_LOGICAL ENDP
PAGE
; ------------ Подпрограммы обработки запросов -----------------------
; Эти подпрограммы вызываются для обработки параметров любого запроса
; на ввод/вывод.
; На входе :
; ES:DI - содержит адрес блока запроса
; Действия :
; Проверка параметра "номер сектора" на допустимость.
; Преобразование этого параметра в "сегмент:смещение".
; Выровнять счетчик для предотвращения "перекрытия".
; На выходе :
; DS:SI - содержит адрес "сектора" в RAM-диске
; 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
; ************ КОД И ДАННЫЕ ДЛЯ ОТЛАДКИ *************
; Отладочные сообщения
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,'$'
; ===== ТАБЛИЦА АДРЕСОВ ОТЛАДОЧНЫХ СООБЩЕНИЙ =====
; 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 - установить имя диска
; 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
; ;** ВНУТРЕННИЙ СТЕК И КОНЕЦ ОПЕРАЦИОННОЙ ЧАСТИ ДРАЙВЕРА **
; 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)
RDISK LABEL BYTE ; начало RAM-диска
RPARA EQU ($-ORIGIN)/16 ; размер кода в параграфах
; ------------ Блок параметров BIOS ----------------------------------
; jmp short boot ; короткий JMP (2 байта) nop ; требуется для boot_record db 'IBM 3.1' ; 8 байт имя и версия
; bpb bpbstrc 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
Список используемой литературы
Страницы: 1, 2