home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / video / 12 / 12_3.asm < prev    next >
Encoding:
Assembly Source File  |  1988-08-11  |  8.7 KB  |  248 lines

  1.                 TITLE   'Listing 12-3'
  2.                 NAME    VRMCGA
  3.                 PAGE    55,132
  4.  
  5. ;
  6. ; Name:         VRMCGA
  7. ;
  8. ; Function:     Vertical Interrupt Service routine for MCGA
  9. ;
  10. ; Caller:       Microsoft C:
  11. ;
  12. ;                       int EnableISR0A();      /* returns 0 if installed ok */
  13. ;
  14. ;                       void DisableISR0A();
  15. ;
  16.  
  17. ADDR_6845       EQU     63h
  18.  
  19. DGROUP          GROUP   _DATA
  20.  
  21. _TEXT           SEGMENT byte public 'CODE'
  22.                 ASSUME  cs:_TEXT,ds:DGROUP
  23.  
  24. ISR0A           PROC    far             ; Interrupt handler for INT 0Ah
  25.  
  26.                 push    ax              ; preserve registers
  27.                 push    dx
  28.                 push    ds
  29.  
  30.                 mov     ax,seg DGROUP
  31.                 mov     ds,ax           ; DS -> DGROUP
  32.  
  33.                 mov     dx,Port3x4      ; DX := CRTC Address reg number
  34.                 in      al,dx
  35.                 push    ax              ; preserve CRTC Address reg value
  36.  
  37. ; determine whether a vertical interrupt has occurred
  38.  
  39.                 mov     al,IContReg     ; AL := register number
  40.                 out     dx,al
  41.                 jmp     $+2             ; wait for MCGA to respond
  42.                 inc     dx              ; DX := 3D5H
  43.                 in      al,dx           ; AL := current Interrupt Control
  44.                                         ;  register value
  45.                 dec     dx
  46.                 test    al,40h          ; test bit 6
  47.                 jnz     L10             ; jump if vertical interrupt
  48.  
  49. ; not a vertical interrupt so chain to previous interrupt handler
  50.  
  51.                 pushf                   ; simulate an INT to the
  52.                 call    ds:PrevISR0A    ;  previous INT 0Ah handler
  53.                 jmp     short Lexit
  54.  
  55. ; handle a vertical interrupt
  56.  
  57. L10:            mov     ax,DefaultICont ; AH := default value for
  58.                                         ;  Interrupt Control register
  59.                                         ; AL := 11h (register number)
  60.                 and     ah,11101111b    ; AH bit 4 := 0 (clear interrupt latch)
  61.                 out     dx,ax           ; update Interrupt Control reg
  62.                 jmp     $+2             ; wait for MCGA to respond
  63.  
  64. ; send End of Interrupt to Programmable Interrupt Controller
  65. ;  to allow subsequent IRQ2 interrupts to occur
  66.  
  67.                 mov     al,20h          ; PIC I/O port
  68.                 out     20h,al          ; send nonspecific EOI to PIC
  69.                 jmp     $+2             ; wait for PIC to respond
  70.                 sti                     ; enable interrupts
  71.  
  72. ; do something useful ...
  73.  
  74.                 inc     word ptr _VRcount       ; increment a counter
  75.  
  76. ; enable CRTC to generate another interrupt
  77.  
  78.                 cli                     ; disable interrupts
  79.                 mov     ax,DefaultICont ; AH := default value for
  80.                                         ;  Interrupt Control register
  81.                                         ; AL := 11h (register number)
  82.                 and     ah,11011111b    ; AH bit 5 := 0 (enable vert int)
  83.                 or      ah,00010000b    ; AH bit 4 := 1 (enable int latch)
  84.                 out     dx,ax
  85.                 jmp     $+2
  86.  
  87. Lexit:          pop     ax
  88.                 out     dx,al           ; restore previous 3D4H value
  89.  
  90.                 pop     ds              ; restore registers and exit
  91.                 pop     dx
  92.                 pop     ax
  93.                 iret
  94.  
  95. ISR0A           ENDP
  96.  
  97. ;
  98. ; EnableISR0A -- enable Vertical Interrupt Handler
  99. ;
  100.                 PUBLIC  _EnableISR0A
  101. _EnableISR0A    PROC    near
  102.  
  103.                 push    bp              ; preserve caller registers
  104.                 mov     bp,sp
  105.                 push    si
  106.                 push    di
  107.  
  108.                 mov     ax,40h
  109.                 mov     es,ax           ; ES -> video BIOS data area
  110.  
  111. ; save default CRTC register values
  112.  
  113.                 mov     dx,es:[ADDR_6845]  ; DX := CRTC Address port
  114.                 mov     Port3x4,dx      ; save port address
  115.  
  116.                 mov     ax,1A00h        ; AH := 1AH (INT 10H function number)
  117.                                         ; AL := 0 (read Display Combination)
  118.                 int     10h             ; AL := 1AH if function 1AH supported
  119.                                         ; BL := active video subsystem
  120.                 cmp     al,1Ah
  121.                 jne     L20             ; jump if not an MCGA
  122.  
  123.                 cmp     bl,0Bh
  124.                 je      L21             ; jump if MCGA
  125.  
  126.                 cmp     bl,0Ch
  127.                 je      L21             ; jump if MCGA
  128.  
  129. L20:            mov     ax,0FFFFh       ; return 0FFFFh if not an MCGA
  130.                 jmp     short L23
  131.  
  132. ; get default value for MCGA Interrupt Control register
  133.  
  134. L21:            mov     al,IContReg     ; AL := Interrupt Control reg number
  135.                 cli
  136.                 out     dx,al
  137.                 jmp     $+2
  138.                 inc     dx              ; DX := 3D5H
  139.                 in      al,dx           ; AL := current value for register
  140.                 sti
  141.  
  142.                 mov     IContValue,al   ; save this value
  143.  
  144. ; save old interrupt 0Ah vector
  145.  
  146.                 mov     ax,350Ah        ; AH := 35H (INT 21h function number)
  147.                                         ; AL := 0AH (interrupt number)
  148.                 int     21h             ; ES:BX := previous INT 0AH vector
  149.  
  150.                 mov     word ptr PrevISR0A,bx
  151.                 mov     word ptr PrevISR0A+2,es ; save previous vector
  152.  
  153. ; update interrupt 0AH vector with address of this handler
  154.  
  155.                 push    ds              ; preserve DS
  156.                 mov     dx,offset ISR0A
  157.                 push    cs
  158.                 pop     ds              ; DS:DX -> ISR0A
  159.                 mov     ax,250Ah        ; AH := 25H (INT 21H function number)
  160.                                         ; AL := 0AH (interrupt number)
  161.                 int     21h             ; update INT 0AH vector
  162.                 pop     ds              ; restore DS
  163.  
  164. ; enable IRQ2 by zeroing bit 2 of the PIC's mask register
  165.  
  166.                 cli                     ; clear interrupts
  167.                 mov     dx,21h          ; DX := PIC mask register
  168.                 in      al,dx           ; AL := mask register value
  169.                 and     al,11111011b    ; reset bit 2
  170.                 out     dx,al
  171.  
  172. ; enable vertical interrupts
  173.  
  174.                 mov     dx,Port3x4      ; DX := CRTC Address port
  175.                 mov     ax,DefaultICont
  176.  
  177.                 and     ah,11001111b
  178.                 out     dx,ax           ; clear bits 4 and 5 of Int Control reg
  179.                 jmp     $+2             ; wait for MCGA to respond
  180.                 or      ah,00010000b
  181.                 out     dx,ax           ; set bit 4
  182.                 jmp     $+2
  183.                 sti                     ; enable interrupts
  184.  
  185.                 xor     ax,ax           ; AX := 0 (return value)
  186.  
  187. L23:            pop     di              ; restore registers and exit
  188.                 pop     si
  189.                 mov     sp,bp
  190.                 pop     bp
  191.                 ret
  192.  
  193. _EnableISR0A    ENDP
  194.  
  195. ;
  196. ; DisableISR0A -- disable Vertical Interrupt Handler
  197. ;
  198.                 PUBLIC  _DisableISR0A
  199. _DisableISR0A   PROC    near
  200.  
  201.                 push    bp
  202.                 mov     bp,sp
  203.                 push    si
  204.                 push    di
  205.                 push    ds
  206.  
  207. ; disable vertical interrupts
  208.  
  209.                 cli                     ; disable interrupts
  210.                 mov     dx,Port3x4
  211.                 mov     ax,DefaultICont
  212.                 out     dx,ax           ; restore Interrupt Control register
  213.                 jmp     $+2
  214.                 sti                     ; enable interrupts
  215.  
  216. ; restore previous interrupt 0Ah handler
  217.  
  218.                 lds     dx,PrevISR0A    ; DS:DX := previous INT 0AH vector
  219.                 mov     ax,250Ah        ; AH := 25H (INT 21H function number)
  220.                                         ; AL := 0AH (interrupt number)
  221.                 int     21h
  222.  
  223.                 pop     ds              ; restore registers and exit
  224.                 pop     di
  225.                 pop     si
  226.                 mov     sp,bp
  227.                 pop     bp
  228.                 ret
  229.  
  230. _DisableISR0A   ENDP
  231.  
  232. _TEXT           ENDS
  233.  
  234. _DATA           SEGMENT word public 'DATA'
  235.  
  236.                 EXTRN   _VRcount:word   ; declared in C caller
  237.  
  238. PrevISR0A       DD      ?               ; save area for old int 0Ah vector
  239. Port3x4         DW      ?               ; 3B4h or 3D4h
  240.  
  241. DefaultICont    LABEL   word
  242. IContReg        DB      11h             ; Interrupt Control register number
  243. IContValue      DB      ?               ; default value for Int Control reg
  244.  
  245. _DATA           ENDS
  246.  
  247.                 END
  248.