Драйверы устройств в системе Windows

Библиотека DLL для драйвера


     При написании приложений в  системе Windows обычно в  программном модуле  имеют  дело  только  с  двумя  типами  сегментов: перемещаемым (moveable)  и  выгружаемым  (discardable).  Сегменты  данных программы являются  перемещаемыми,  т.е.  их  линейные  адреса  в  памяти  могут изменяться,  когда  программе   управления  памятью  системы   Windows требуется  организовать  память.   Селектор  (selector)  и   смещение, используемые  для  доступа  к  определенной  ячейке  памяти,  остаются фиксированными,  но  под  схемой  селектор-смещение  система   Windows может перемещать фактические данные в линейной памяти.

     Сегменты   программ-кодов    также   перемещаемые,    но    имеют дополнительный  атрибут  -  выгружаемые.  Их  содержимое  может   быть выгружено полностью, а  при необходимости загружено  с диска, так  как нельзя   писать   и   (или)   модифицировать   информацию  в  сегменте программы-кода. Если  при обращении  к сегменту  из программы Windows, он оказался выгруженным, программа управления памятью системы  Windows автоматически обратится к диску и прочитает ранее выгруженный сегмент.

     Итак,  каким  образом  это  обстоятельство  влияет  на  код   для программы ISR?  Так как  прерывание может  произойти в  любое время, а код ISR может оказаться  выгруженным, то возникнет проблема  загрузить код  в  память,  если  фиксируется  прерывание.  Вместо  этого,  можно описать  сегмент  как  FIXED   (фиксированный),  а  не  как   MOVEABLE (перемещаемый)  или  DISCARDABLE  (выгружаемый).  Сегмент  с атрибутом FIXED  будет  оставаться  в  единственном  месте  линейной памяти и не будет выгружаться,  даже если  он содержит  код. В  этом случае,  если произойдет  прерывание,  код  будет  доступен  и  готов  к выполнению. Однако следует отметить один  малоизвестный факт, а именно:  в системе Windows  только  те  сегменты  будут  считаться  FIXED,  которые  были описаны в библиотеке DLL.  Сегмент FIXED в обычном  программном модуле будет рассматриваться  как MOVEABLE.  Таким образом  в системе Windows нельзя будет  поместить программу  ISR в  обычный программный  модуль.


Вместо этого ее необходимо поместить в библиотеку DLL.

     Листинг 2 представляет исходный код bogusa.asm на ассемблере  для библиотеки DLL, который содержит  программу ISR и может  выполняться в окружении Windows. Программа IntSvcRtn очень похожа на свой  дубликат, работающий  в  системе  MS-DOS.  Однако  кроме  увеличения переменной-счетчика данная  программа ISR  также записывает  в очередь  сообщение Windows.  Чтобы  избежать   переполнения  очереди,  запись   сообщения производится  только   в  случае,   когда  переменная-счетчик   wCount изменяет значение от  0 к 1.  Функция обнуления счетчика  wCount после того,  как  закончена  обработка  сообщения,  передана высокоуровневой программе системы Windows.

     С первого  взгляда все  эти рассуждения  кажутся простыми, однако обработка прерываний  в системе  Windows совсем  не так  проста, как в системе MS-DOS.

page ,132

; masm tisr ; >err

    .286p

.xlist

include bogus.inc



include pic.h

.list

WM_COMMAND=0111h

EXTRN POSTMESSAGE:FAR

Words struc

LoWord dw ?

HiWord dw ?

Words ends

;

; Установить переменные для нашего номера прерывания

;

ife (FAKE_IRQ GE 8)

INT_DEV equ (INT_MASTER_0+(FAKE_IRQ AND 7))

PIC00 equ INTA00

PIC01 equ INTA01

else

INT_DEV equ (INT_SLAVE_0+(FAKE_IRQ AND 7))

INT_MASK equ 1 SHL (FAKE_IRQ AND 7))

PIC00 equ INTB00

PIC01 equ INTB01

endif

FIXED_DATA SEGMENT DWORD PUBLIC 'DATA'

PUBLIC _hWndEvent,_wParamEvent,_wCount

_hWndEvent label word

hWndEvent  dw   0      ; Окно для постирования событий

_wParamEvent label word

wParamEvent  dw  0     ; Значение wParam для постирования

_wCount label word

wCount dw   0          ; Счетчик необработанных прерываний

FIXED_DATA ENDS

; IP IntSvcRtn - программа обслуживания прерываний

;

; WARNINGS (Предупреждения)

;

; NOTES (Примечания)

; Данная  программа ISR  увеличивает   счетчик  прерываний  и  заново

; маскирует устройство.

; Если предыдущее  значение  счетчика  было  равно 0, то записывается



; сообщение

; Если установлен флаг "fStopping", устройство не маскируется заново.

;

FIXED_TEXT SEGMENT PARA PUBLIC 'CODE'

selData1    dw   FIXED_DATA

     assume  CS:FIXED_TEXT,DS:NOTHING

PUBLIC _IntSvcRtn

_IntSvcRtn label far

IntSvcRtn proc far

    push     ax

    push     dx

    push     ds

    mov ds,selDatal

    assume  ds:FIXED_DATA

    inc wCount

    mov al,NOT FAKE_CTL_EOI

    mov dx,FAKE_PORT

    out dx,al          ; посылаем устройству EOI

    mov al,EOI

    out PIC00,al       ; посылаем EOI контроллеру PIC

ife (PIC00 EQ INTA00)

    out INTA00,al      ; посылаем EOI также главному контроллеру PIC

endif

    cmp hWndEvent,0    ; завершать?

    jz  isr9           ; если да, то не делаем перезапуска и

                       ; постирования

    cmp wCount,1       ; требуется постирование?

    jne isr8           ; пропускаем, если нет

    push   bx          ; сохраняем оставшиеся регистры

    push   cx

    push   es

    push   hWndEvent

    push   WM_COMMAND

    push   wParamEvent

    push   0   ; lParam равно 0

    push   0

    call   POSTMESSAGE    ; регистрируем

событие

    pop es

    pop cx

    pop bx

isr8:

    mov al,NOT FAKE_CTL_START

    mov dx,FAKE_PORT

    out dx,al          ; возобновляем ввод-вывод

isr9:

    pop ds

    assume  ds:NOTHING

    pop dx

    pop ax

    iret

IntSvcRtn endp

; требуется программе AllocIntReflector

PUBLIC _BogusCallback

_BogusCallback label far

BogusCallback proc far

    pushf

    call     IntSvcRtn

    ret

BogusCallback endp

FIXED_TEXT ENDS

    end

; конец файла

_____________________________________________________________________

     Листинг 2. Программа bogusa.asm


Содержание раздела