home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progbas / qbnws103.arj / UEVENT.ZIP / EVENTHDW.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-03-06  |  7.4 KB  |  182 lines

  1. ; *********** EVENTHDW.ASM *******************************************
  2.  
  3.         .model medium, basic
  4.         .data
  5.  
  6. IRQLevel        dw      -1      ; the requested IRQ level
  7. OrigMask        db      0       ; how the 8259 IMR was on entry
  8. Chained         db      0       ; did we chain in or take over?
  9.  
  10.         .code
  11.  
  12. PreviousVector  LABEL DWORD     ; placed in the code segment to...
  13. PVOffset        dw      -1      ; ...facilitate chaining if req'd
  14. PVSegment       dw      77      ; a signature to avoid multi-installs
  15.  
  16. EXTRN   SetUEvent:FAR           ; this is in the BC runtime
  17. EXTRN   B_OnExit:FAR            ;          ditto
  18.  
  19. InstallHandler  PROC irqnum, chnd       ; both passed BYVAL
  20.  
  21. ; This takes care of wrapping our metaphorical tentacles around the
  22. ; PC.  We take over the interrupt vector associated with the IRQ level
  23. ; passed, saving the previous contents so that we can put things back
  24. ; the way they were when we exit, and we enable the interrupt level in
  25. ; the PC hardware.
  26.  
  27.         cmp     PVSegment, 77   ; insure this is first time
  28.         jne     iherr
  29.         mov     ax, irqnum      ; test for correct range
  30.         cmp     ax, 2
  31.         jb      iherr           ; vector too low, < 2
  32.         cmp     ax, 7
  33.         ja      iherr           ; vector too high, > 7
  34.         mov     dx, offset RemoveInt
  35.         push    cs              ; push far address of RemoveInt
  36.         push    dx              ; to register the exit routine
  37.         call    B_OnExit        ; so that we don't hang machine
  38.         or      ax, ax          ; registered OK?
  39.         jz      iherr           ; error: too many registered routines
  40.         mov     ax, chnd        ; will we chain or not?
  41.         mov     chained, al     ; keep local copy
  42.         mov     ax, irqnum      ; get this again
  43.         mov     IRQLevel, ax    ; save for removal routine
  44.         mov     cx, ax          ; hold value a moment as shift count
  45.         add     al, 8           ; add 8 to turn low IRQ into INT
  46.         mov     ah, 35H         ; use DOS to get current...
  47.         INT     21H             ; ...holder of the vector
  48.         mov     PVSegment, es   ; save for chaining, removal
  49.         mov     PVOffset, bx
  50.         test    chained, -1     ; who does the 8259?
  51.         jnz     @f              ; ...not me...
  52.  
  53.         mov     ah, 1           ; turn IRQ # into bit mask
  54.         shl     ah, cl
  55.         push    ax              ; preserve mask
  56.         cli                     ; do this with all interrupts off
  57.         in      al, 21H         ; get PC's Interrupt Mask Register
  58.         mov     OrigMask, al    ; save for later removal
  59.         or      al, ah          ; set this IRQ level OFF...
  60.         out     21H, al         ; ...in the IMR
  61.         sti                     ; interrupts back on
  62.         mov     ax, cx          ; get IRQ number again
  63.         add     al, 8           ; turn into INT number
  64. @@:
  65.         mov     ah, 25H         ; tell DOS we're taking this vector
  66.         push    ds              ; hold DS a moment
  67.         mov     bx, cs          ; transfer CS to DS
  68.         mov     ds, bx
  69.         mov     dx, offset IntHandler; get address of our MASM handler
  70.         INT     21H             ; grab the vector, Victor
  71.         pop     ds              ; restore DS
  72.         test    chained, -1     ; who's doing the 8259?
  73.         jnz     @f              ; ..the other guy is
  74.  
  75.         pop     ax              ; get mask back
  76.         not     ax              ; invert mask bits
  77.         cli                     ; all interrupts off
  78.         in      al, 21H         ; get IMR
  79.         and     al, ah          ; set this IRQ level ON
  80.         out     21H, al         ; set IMR
  81.         sti                     ; interrupts back on again
  82. @@:
  83.         xor     ax, ax          ; return zero: all OK
  84. @@:     ret
  85.  
  86. iherr:  mov     ax, -1          ; couldn't install: return TRUE
  87.         jmp     @b
  88.  
  89. InstallHandler  ENDP
  90.  
  91. RemoveInt       PROC
  92.  
  93. ; RemoveInt will undo the InstallHandler by restoring the PC to the
  94. ; state it was in before we came along.  This is vital, because
  95. ; otherwise when the program terminates the interrupt vector will
  96. ; point into volatile space, guaranteeing an eventual machine hang.
  97.  
  98. ; Because we "register" this routine with B_OnExit, restoring the
  99. ; machine state becomes a part of BASIC's normal shutdown process...
  100. ; we don't need to call this routine explicitly.
  101.  
  102.         test    chained, -1     ; who's job is the 8259?
  103.         jnz     @f              ; not ours, skip mask stuff
  104.         mov     cx, IRQLevel    ; level we're using
  105.         mov     ax, 1           ; turn into bit mask
  106.         shl     ax, cl          ; by shifting
  107.         mov     ah, al          ; protect it
  108.         push    ax              ; save AH for later
  109.         cli                     ; do this with interrupts off
  110.         in      al, 21H         ; get IMR
  111.         or      al, ah          ; this IRQ level OFF
  112.         out     21H, al         ; set IMR
  113.         sti                     ; interrupts on again
  114. @@:     mov     ax, IRQLevel    ; IRQ number
  115.         add     al, 8           ; becomes INT number
  116.         mov     ah, 25H         ; SET VECTOR call
  117.         push    ds              ; protect DS
  118.         lds     dx, PreviousVector; get original vector
  119.         INT     21H             ; restore it
  120.         pop     ds              ; so we can read OrigMask
  121.         test    chained, -1     ; who's job is the 8259?
  122.         jnz     @f              ; not ours, skip mask stuff
  123.         pop     ax              ; recover mask in AH
  124.         test    OrigMask, ah    ; the state before we interfered
  125.         jnz     @f              ; originally off, leave off
  126.         not     ah              ; bit clear = ON
  127.         cli                     ; all interrupts off
  128.         in      al, 21H         ; get IMR
  129.         and     al, ah          ; this IRQ level ON
  130.         out     21H, al         ; set IMR
  131.         sti                     ; interrupts back on
  132. @@:     ret
  133.  
  134. RemoveInt       ENDP
  135.  
  136. IntHandler      PROC FAR  ;note that we don't just say "PROC" here
  137.  
  138. ; This routine notifies the BASIC runtime that an event has occurred.
  139. ; You MUST save and restore any registers you use.  In this example
  140. ; we're overly pessimistic, assuming that BC will destroy everything.
  141.  
  142.         assume  cs:@code, ds:nothing, es:nothing, ss:nothing
  143.  
  144.         sti                     ; allow more important interrupts
  145.         push    ax
  146.         push    ds              ; only save the registers you really need to
  147.         push    di
  148.         push    es              ; here, we assume BC can destroy anything
  149.         push    si
  150.         push    dx
  151.         push    cx
  152.         push    bx
  153.         call    SetUEvent       ; notify BC/QB that the event occurred
  154. ;
  155. ;  If there are hardware-specific duties, do them here
  156. ;
  157.         pop     bx
  158.         pop     cx
  159.         pop     dx
  160.         pop     si
  161.         pop     es
  162.         pop     di
  163.         mov     ax, @data
  164.         mov     ds, ax
  165.         assume  ds:@data
  166.         test    chained, -1     ; is someone else doing the 8259?
  167.         pop     ds
  168.         assume  ds:nothing
  169.         jnz     @f              ; yes, skip the following
  170.         mov     al, 20H         ; clear PC's interrupt by
  171.         out     20H, al         ; using a non-specific EOI
  172.         pop     ax
  173.         iret                    ; resume program in progress
  174. @@:
  175.         pop     ax
  176.         jmp     [PreviousVector]
  177.  
  178. IntHandler      ENDP
  179.  
  180.         END
  181.  
  182.