Программирование и кодирование
ret
_boisprt ENDP
;
- 6-57 -
IFNDEF DEBUG ; если не включено как часть
_TEXT ENDS ; DEBUG, то потребуются наши
ENDIF ; собственные ENDS
;
; ************ КОНЕЦ ФАЙЛА BIOSIO.ASM ********************************
; END ; При использовании в библиотеке, удалите ";"
----------------------------------------------------------------------
Листинг 6-10. Исходный текст драйвера RAM-диска
----------------------------------------------------------------------
PAGE 60,132
; ************ RDISK.ASM : MS-DOS ДРАЙВЕР RAM-ДИСКА ******************
;
; Этот файл содержит исходный текст простого MS-DOS драйвера RAM-диска
; эмулирующего 360K флоппи-диск.
;
; В этом примере демонстрируются основные принципы построения драйвера
; устройств, включая один из методов, который можно использовать для
; отладки драйверов. Для установки этого драйвера включите в файл
; CONFIG.SYS строку "DEVICE=RDISK.SYS"
;
; ============ ВСПОМОГАТЕЛЬНЫЕ ФАЙЛЫ ДЛЯ ДРАЙВЕРА ====================
;
INCLUDE driver.inc ; Константы для MS-DOS драйвера
IFDEF DEBUG
INCLUDE biosio.inc ; Определения для отладки
ENDIF
;
; ============ КОНСТАНТЫ =============================================
;
; Ограничения,накладываемые версией MS-DOS на максимальный код команды
;
CMD_PRE_30 EQU 00Ch ; до MS-DOS версии 3.00
CMD_PRE_32 EQU 00Fh ; до MS-DOS версии 3.20
CMD_32 EQU 018h ; начиная с версии 3.20
;
IFDEF DEBUG
CR EQU 0Ah ; используются в отладочных
LF EQU 0Dh ; сообщениях
ENDIF
;
PAGE
;
; ============ ШАБЛОНЫ СТРУКТУР ======================================
;
request EQU es:[di.rv] ; указатель на блок запроса
; request EQU es:[di[rv]
; Структура заголовка запроса
;
reqhdr STRUC
rlength db ? ; размер блока запроса
unit db ? ; номер устройства
command db ? ; код команды
status dw ? ; возвращаемый статус
db 8 DUP (?) ; зарезервировано
reghdr ENDS
- 6-58 -
;
; Структура блока запроса для команды INIT
;
inithdr STRUC
db (type reqhdr) DUP (?)
units db ? ; количество устройств
endadro dw ? ; смещение и сегмент
endadrs dw ? ; адреса завершения
bpbtabo dw ? ; смещение и сегмент
bpbtabs dw ? ; таблицы BPB
devnum db ? ; номер устройства
inithdr ENDS
;
; Структура блока запроса для команды MEDIA CHECK
;
mchkhdr STRUC
db (type reqhdr) DUP (?)
mbd db ? ; описатель носителя
chande dw ? ; статус замены
volume dd ? ; указатель на имя тома
mchkhdr ENDS
;
; Структура блока запроса для команды BUILD BPB
;
bpbhdr STRUC
db (type reqhdr) DUP (?)
db ? ; описатель носителя
dd ? ; указатель на FAT
bpbptro dw ? ; смещение BPB
bpbptrs dw ? ; сегмент BPB
bpbhdr ENDS
;
; Структура блока запроса для команд чтения/записи
;
iohdr STRUC
db (type reqhdr) DUP(?)
db ? ; описатель носителя
bufprt dd ? ; адрес буфера
count dw ? ; кол-во байт/секторов
start dw ? ; # начального сектора
nuvol dd ? ; адрес нов. имени тома
iohdr ENDS
;
; Структура блока параметров BIOS (BPB)
;
bpbstrc STRUC
bps dw ? ; количество байтов в секторе
spau db ? ; кол-во секторов в кластере
nrs dw ? ; кол-во зарезервир. секторов
nft db ? ; количество копий FAT
nde dw ? ; кол-во элементов директория
nls dw ? ; кол-во логических секторов
md db ? ; байт описателя носителя
nfs dw ? ; размер FAT в секторах
bpbstrc ENDS
;
- 6-59 -
PAGE
;
; ============= НАЧАЛО КОДА ДРАЙВЕРА =================================
;
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:_TEXT, DS:_TEXT, ES:NOTHING
ORG 0
ORIGIN EQU $
;
; ============= ЗАГОЛОВОК ДРАЙВЕРА ===================================
;
dw -1,-1 ; указатель на след. драйвер
dw AT_IOCTL OR AT_OCRM OR AT_NET
dw offset STRATEGY ; смещение СТРАТЕГИЙ
dw offset INTERRUPT ; смещение ПРЕРЫВАНИЙ
db 1,'CDEVICE.. ; кол-во устройств/имя
;
; ============= ТАБЛИЦА АДРЕСОВ ОБРАБОТЧИКОВ КОМАНД ==================
;
JUMPTAB LABEL WORD
dw offset INIT ; 0 - инициализация
dw offset MEDIA_CHECK ; 1 - проверка носителя
dw offset BUILD_BPB ; 2 - построить BPB
dw offset IOCTL_INPUT ; 3 - IOCTL ввод
dw offset READ ; 4 - ввод из устр-ва
dw offset READ_NOWAIT ; 5 - неразруш. ввод
dw offset INPUT_STATUS ; 6 - ввод статуса
dw offset INPUT_FLUSH ; 7 - сбросить ввод
dw offset WRITE ; 8 - вывод на устр-во
dw offset WRITE_VERIFY ; 9 - вывод с проверкой
dw offset OUTPUT_STATUS ; A - вывод статуса
dw offset OUTPUT_FLUSH ; B - сбросить вывод
dw offset IOCTL_OUTPUT ; C - вывод IOCTL
dw offset DEVICE_OPEN ; D - открыть устр-во
dw offset DEVICE_CLOSE ; E - закрыть устр-во
dw offset REMOVABLE ; F - носитель сменный?
dw offset NO_COMMAND ; 10
dw offset NO_COMMAND ; 11
dw offset NO_COMMAND ; 12
dw offset GENERIC_IOCTL ; 13 - Generic IOCTL
dw offset NO_COMMAND ; 14
dw offset NO_COMMAND ; 15
dw offset NO_COMMAND ; 16
dw offset GET_LOGICAL ; 17 - получить/устано-
dw offset SET_LOGICAL ; 18 - вить лог.устр-во
;
; ============ ОБЛАСТЬ ДАННЫХ ДРАЙВЕРА ===============================
;
reg_ptr dd ? ; адрес блока запроса
max_cmd db CMD_PRE_30 ; максимально допустимый код
; ; команды
save_ss dw ? ; значение SS на входе
save_sp dw ? ; значение SP на входе
;
- 6-60 -
PAGE
;
; ============ ПРОГРАММА СТРАТЕГИЙ ====================================
;
STRATEGY PROC FAR
mov cs:word ptr [reg_ptr],bx
mov cs:word ptr [reg_ptr+2],es
ret
strategy ENDP
;
; ============ ПРОГРАММА ПРЕРЫВАНИЙ ===================================
;
INTERRUPT PROC FAR
push ax ; сохранить все рабочие
push cx ; регистры
push dx
push bx
push bp
push si
push di
push ds
push es
;
push cs ; определим локальный сегмент
pop ds ; данных
;
mov word ptr save_ss,ss ; сохраним входное
mov word ptr save_sp,sp ; значение SS и SP
;
mov bx,cs ; установим локальный
mov ax,offset local_stack - 2 ; стек
mov ss,bx
mov sp,ax
;
les di,[req_ptr] ; получить адрес блока
mov bl,request.command ; запроса и команду
;
; установим заранее код ошибки на случай если команда неверная
;
mov ax,(ST_ERROR OR UNKNOWN_COMMAND)
cmp bl,[max_cmd] ; команда поддерживается ?
ja exit ; нет - отвергаем ее
;
; Выдаем указанную команду на выполнение соответствующему обработчику.
; Каждый обработчик получает управление с CS и DS установленными на
; сегмент драйвера и ES:DI указывающем на блок запроса. Свой статус
; обработчики возвращают в регистре AX.
;
xor bh,bh ; BX - индекс в таблице
shl bx,1 ; команд
IFDEF DEBUG
call print_command ; выдаем имя обрабатываемой
ENDIF ; команды
call word ptr jumptab[bx] ; вызываем обработчик
;
; Перешлем статус из регистра AX в слово состояния блока запроса
;
exit: push cs ; установка локального
- 6-61 -
pop ds ; сегмента данных
;
les di,[req_ptr] ; получим адрес блока запроса
or ax,ST_DONE ; установим бит DONE
mov request.status,ax ; сохраним статус
;
mov ss,word ptr save_ss ; восстановим значение
mov sp,word ptr save_sp ; регистров SS:SP
;
pop es ; восстановим содержимое
pop ds ; регистров
pop di
pop si