;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        PAGE    60,132
        TITLE   VDHRTRC.ASM -- CGA Retrace Routines
;/*****************************************************************************
;*
;* SOURCE FILE NAME = VDHRTRC.ASM
;*
;* DESCRIPTIVE NAME = CGA Retrace Routines 
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* DESCRIPTION  Video Device Handler Retrace Routines   
;*
;* FUNCTIONS    CGA_REP_MOVSB_INCDI_LOOP   
;*              CGA_REP_MOVSB_INCSI_LOOP                           
;*              CGA_REP_MOVSW_ADDSI2_LOOP                          
;*              CGA_REP_LODSB_STOSW_LOOP                           
;*              CGA_REP_MOVSW_STOSW_LOOP                           
;*              CGA_REP_MOVSW  
;*              CGA_REP_STOSB_INCDI_LOOP                           
;*              CGA_REP_INCDI_STOSB_LOOP                           
;*              CGA_REP_STOSW  
;*                                                                         
;* NOTES        NONE
;*             
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES   
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;*   03/25/89  @P1        D132    TPL, DCR 132 changes
;*   06/25/89  @T37       B703759 TPL, DCR 132 fix, 
;*   01/29/91  MS00               TPL, Convert IFDEF to IF
;*   01/29/91  MS01               TPL, Rollover MS's runtime
;*                                check for CGA speedup
;*   01/29/91  MS27               TPL, add OEM detection logic
;*****************************************************************************/

        .286c                           ; 286 protect mode instructions

        .xlist
        INCLUDE struc.inc               ; Structure macro
        INCLUDE error2.inc              ; Subsystem error equates
        INCLUDE vdhstruc.inc            ; Buffer update data structures
        INCLUDE vdhctl.inc              ; Conditional assembly control  ;MS00
        INCLUDE vdhequ.inc              ; Buffer update equates
        .list

;/*
;** If CGA video memory accesses may need to wait for retrace,        ;MS00
;** these routines are necessary.  (See MAKEFILE)                     ;MS00
;*/

IFE CGA_ALWAYS_FAST     ; IF NOT CGA_ALWAYS_FAST                      ;MS00

extrn   _OEMFlags:word                  ; OEM specific features       ;MS27

HORZWAIT MACRO                          ; Wait for horizontal retrace only
        .repeat                         ; 
            in      al, dx              ; 
            test    al, 1               ; 
        .until  <z>                     ; Wait until retrace appears
        cli                             ; Disable interrupts
        .repeat                         ; 
            in      al, dx              ; 
            test    al, 1               ; 
        .until  <nz>                    ; Wait until retrace disappears
         ENDM                           ; 


ALLWAIT  MACRO                          ; Wait for all retraces
        .repeat                         ; 
            in      al, dx              ; 
            test    al, 9               ; 
        .until  <z>                     ; Wait until no retrace of any kind
        cli                             ; Disable interrupts
        .repeat                         ; 
            in      al, dx              ; 
            test    al, 1               ; 
        .until  <nz>                    ; Wait for start of horizontal retrace
         ENDM                           ; 


R2SEG   SEGMENT WORD    PUBLIC 'CODE'
        ASSUME  CS:R2SEG,DS:NOTHING,ES:NOTHING

        PUBLIC  CGA_REP_MOVSB_INCDI_LOOP                                ;@P1
CGA_REP_MOVSB_INCDI_LOOP    PROC    FAR                                 ;@P1

;/*
;** If CGA adapter was identified as FAST during BVH initialization,    ;MS01
;** don't need retrace logic -- use direct data move.                   ;MS01
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                movsb                                                   ;MS01
                inc     di                                              ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**   CGA is slow -- need retrace logic:     
;*/

        push    ax                      ;                               ;@T37
        push    dx                      ; 
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port
        test    cl, 1                   ; 
        .if     <nz>                    ; Odd byte?
            HORZWAIT                    ; Wait for horizontal retrace
            movsb                       ; Transfer 1 byte to PVB
            sti                         ; Enable interrupt as soon as possible
            inc     di                  ; Skip pass attribute byte
        .endif                          ; 
        shr     cx, 1                   ; Setup to move 2 bytes
        .if     <ncxz>                  ; Anything to move?
            .repeat                     ; 
                HORZWAIT                ; Wait for horizontal retrace
                movsb                   ; Transfer to bytes to PVB
                inc     di              ; Skip pass attribute byte
                movsb                   ; 
                sti                     ; Enable interrupt as soon as possible
                inc     di              ; 
            .loop                       ; 
        .endif                          ; 
        pop     dx                      ; 
        pop     ax                      ;                               ;@T37
        ret

CGA_REP_MOVSB_INCDI_LOOP    ENDP                                        ;@P1

        PUBLIC  CGA_REP_MOVSB_INCSI_LOOP                                ;@P1
CGA_REP_MOVSB_INCSI_LOOP   PROC    FAR                                  ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,   
;**  don't need retrace logic -- use direct data move.                  
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                movsb                                                   ;MS01
                inc     si                                              ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**   CGA is slow -- need retrace logic:    
;*/

        push    dx                      ; 
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port
        test    cl, 1                   ; 
        .if     <nz>                    ; Odd byte?
            HORZWAIT                    ; Wait for horizontal retrace
            movsb                       ; Transfer 1 byte from PVB
            sti                         ; Enable interrupt as soon as possible
            inc     si                  ; Skip pass attribute byte
        .endif                          ; 
        shr     cx, 1                   ; Setup to move 2 bytes
        .if     <ncxz>                  ; Anything to move?
            .repeat                     ; 
                HORZWAIT                ; Wait for horizontal retrace
                movsb                   ; Transfer two bytes from PVB
                inc     si              ; Skip pass attribute byte
                movsb                   ; 
                sti                     ; Enable interrupt as soon as possible
                inc     si              ; 
            .loop                       ; 
        .endif                          ; 
        pop     dx                      ; 
        ret                             ; 

CGA_REP_MOVSB_INCSI_LOOP    ENDP                                        ;@P1

        PUBLIC  CGA_REP_MOVSW_ADDSI2_LOOP                               ;@P1
CGA_REP_MOVSW_ADDSI2_LOOP   PROC    FAR                                 ;@P1

;/*
;** If CGA adapter was identified as FAST during BVH initialization, 
;** don't need retrace logic -- use direct data move.
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                movsw                                                   ;MS01
                add     si,2                                            ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**   CGA is slow -- need retrace logic:                         
;*/

        push    dx                      ;                               ;@P1
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port ;@P1
        test    cl, 1                   ;                               ;@P1
        .if     <nz>                    ; Odd byte?                     ;@P1
            HORZWAIT                    ; Wait for horizontal retrace   ;@P1
            movsw                       ; Transfer 1 byte from PVB      ;@P1
            sti                         ; Enable interrupt as soon as possible
            add     si,2                ; Skip pass attribute byte      ;@P1
        .endif                          ;                               ;@P1
        shr     cx, 1                   ; Setup to move 2 bytes         ;@P1
        .if     <ncxz>                  ; Anything to move?             ;@P1
            .repeat                     ;                               ;@P1
                HORZWAIT                ; Wait for horizontal retrace   ;@P1
                movsw                   ; Transfer two bytes from PVB   ;@P1
                add     si,2            ; Skip pass attribute byte      ;@P1
                movsw                   ;                               ;@P1
                sti                     ; Enable interrupt as soon as possible
                add     si,2            ;                               ;@P1
            .loop                       ;                               ;@P1
        .endif                          ;                               ;@P1
        pop     dx                      ;                               ;@P1
        ret                             ;                               ;@P1

CGA_REP_MOVSW_ADDSI2_LOOP   ENDP                                        ;@P1

        PUBLIC  CGA_REP_LODSB_STOSW_LOOP                                ;@P1
CGA_REP_LODSB_STOSW_LOOP    PROC    FAR                                 ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,   
;**  don't need retrace logic -- use direct data move.                  
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                lodsb                                                   ;MS01
                stosw                                                   ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**  CGA is slow -- need retrace logic:                  
;*/

        push    bx                      ;                               ;@P1
        push    dx                      ;                               ;@P1
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port ;@P1
        test    cl, 1                   ;                               ;@P1
        .if     <nz>                    ; Odd byte?                     ;@P1
            HORZWAIT                    ; Wait for horizontal retrace   ;@P1
            lodsb                       ; Get character from DS:SI      ;@P1
            stosw                       ; Transfer the attribute        ;@P1
            sti                         ; Enable interrupts             ;@P1
        .endif                          ;                               ;@P1
        shr     cx, 1                   ; Setup to move 2 bytes         ;@P1
        .if     <ncxz>                  ;                               ;@P1
            mov     bx, ax              ; BH = Attribute                ;@P1
            .repeat                     ;                               ;@P1
                HORZWAIT                ; Wait for horizontal retrace   ;@P1
                mov     ax, bx          ; AH = Attribute byte           ;@P1
                lodsb                   ; Get 1st character from DS:SI  ;@P1
                stosw                   ; Transfer the 1st cell         ;@P1
                lodsb                   ; Get 2nd character from DS:SI  ;@P1
                stosw                   ; Transfer the 2nd cell         ;@P1
                sti                     ; Enable interrupts             ;@P1
            .loop                       ;                               ;@P1
        .endif                          ;                               ;@P1
        pop     dx                      ;                           @T37,@P1
        pop     bx                      ;                           @T37,@P1
        ret                             ;                               ;@P1

CGA_REP_LODSB_STOSW_LOOP    ENDP                                        ;@P1

        PUBLIC  CGA_REP_MOVSW_STOSW_LOOP                                ;@P1
CGA_REP_MOVSW_STOSW_LOOP    PROC    FAR                                 ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,
;**  don't need retrace logic -- use direct data move.
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                movsw                                                   ;MS01
                stosw                                                   ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**  CGA is slow -- need retrace logic:                             
;*/

        push    bx                      ;                               ;@P1
        push    dx                      ;                               ;@P1
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port ;@P1
        test    cl, 1                   ;                               ;@P1
        mov     bx, ax                  ; BH = Final word of cell       ;@P1
        .if     <nz>                    ; Odd byte?                     ;@P1
            HORZWAIT                    ; Wait for horizontal retrace   ;@P1
            movsw                       ; Get character from DS:SI      ;@P1
            stosw                       ; Transfer the attribute        ;@P1
            sti                         ; Enable interrupts             ;@P1
        .endif                          ;                               ;@P1
        shr     cx, 1                   ; Setup to move 2 bytes         ;@P1
        .if     <ncxz>                  ;                               ;@P1
            .repeat                     ;                               ;@P1
                HORZWAIT                ; Wait for horizontal retrace   ;@P1
                mov     ax, bx          ; AH = Attribute byte           ;@P1
                movsw                   ; Get 1st character from DS:SI  ;@P1
                stosw                   ; Transfer the 1st cell         ;@P1
                movsw                   ; Get 2nd character from DS:SI  ;@P1
                stosw                   ; Transfer the 2nd cell         ;@P1
                sti                     ; Enable interrupts             ;@P1
            .loop                       ;                               ;@P1
        .endif                          ;                               ;@P1
        pop     dx                      ;                           @T37,@P1
        pop     bx                      ;                           @T37,@P1
        ret                             ;                               ;@P1

CGA_REP_MOVSW_STOSW_LOOP    ENDP                                        ;@P1

        PUBLIC  CGA_REP_MOVSW                                           ;@P1
CGA_REP_MOVSW   PROC    FAR                                             ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,
;**  don't need retrace logic -- use direct data move.
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            rep     movsw                                               ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**  CGA is slow -- need retrace logic:                            
;*/

        push    ax                      ; 
        push    dx                      ; 
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port
        .repeat                         ; 
            ALLWAIT                     ; Wait for horizontal retrace
            movsw                       ; Transfer 1 word
            dec     cx                  ; Adjust transfer count
            .repeat                     ; 
                in      al, dx          ; 
                test    al, 1           ; 
            .leave  <z>                 ; Retraces have passed?
                test    al, 8           ; 
                .if     <nz>            ; Vertical retrace has begun?
                    mov     ax, 312     ; 
                    .if     <ax a cx>   ; 
                        mov     ax, cx  ; 
                    .endif              ; 
                    sub     cx, ax      ; 
                    push    cx          ; 
                    mov     cx, ax      ; 
                    rep     movsw       ; 
                    pop     cx          ; 
            .leave                      ; 
                .endif                  ; 
            .until                      ; 
            sti                         ; Enable interrupts
            or      cx, cx              ; 
        .until  <z>                     ; 
        pop    dx                       ; 
        pop    ax                       ; 
        ret                             ; 

CGA_REP_MOVSW   ENDP                                                    ;@P1

        PUBLIC  CGA_REP_STOSB_INCDI_LOOP                                ;@P1
CGA_REP_STOSB_INCDI_LOOP    PROC    FAR                                 ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,
;**  don't need retrace logic -- use direct data move.
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                stosb                                                   ;MS01
                inc     di                                              ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**  CGA is slow -- need retrace logic:                                    ;MS01
;*/

        push    ax                      ; 
        push    dx                      ; 
        push    si                      ; 
        mov     si, ax                  ; SI = character or attribute
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port
        test    cl, 1                   ; 
        .if     <nz>                    ; Odd byte?
            HORZWAIT                    ; Wait for horizontal retrace
            mov     ax, si              ; 
            stosb                       ; Transfer 1 byte
            sti                         ; Enable interrupts
            inc     di                  ; 
        .endif                          ; 
        shr     cx, 1                   ; Setup to move 2 bytes
        .if     <ncxz>                  ; More to transfer?
            .repeat                     ; 
                HORZWAIT                ; Wait for horizontal retrace
                mov     ax, si          ; Restore attribute byte
                stosb                   ; 
                inc     di              ; 
                stosb                   ; 
                sti                     ; Enable interrupts
                inc     di              ; 
            .loop                       ; 
        .endif                          ; 
        pop     si                      ; 
        pop     dx                      ; 
        pop     ax                      ; 
        ret                             ; 

CGA_REP_STOSB_INCDI_LOOP    ENDP                                        ;@P1

        PUBLIC  CGA_REP_INCDI_STOSB_LOOP                                ;@P1
CGA_REP_INCDI_STOSB_LOOP    PROC    FAR                                 ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,
;**  don't need retrace logic -- use direct data move.
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            .repeat                                                     ;MS01
                inc     di                                              ;MS01
                stosb                                                   ;MS01
            .loop                                                       ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**  CGA is slow -- need retrace logic:                                
;*/

        push    ax                      ;                               ;@P1
        push    dx                      ;                               ;@P1
        push    si                      ;                               ;@P1
        mov     si, ax                  ; SI = character or attribute   ;@P1
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port ;@P1
        test    cl, 1                   ;                               ;@P1
        .if     <nz>                    ; Odd byte?                     ;@P1
            inc     di                  ;                               ;@P1
            HORZWAIT                    ; Wait for horizontal retrace   ;@P1
            mov     ax, si              ;                               ;@P1
            stosb                       ; Transfer 1 byte               ;@P1
            sti                         ; Enable interrupts             ;@P1
        .endif                          ;                               ;@P1
        shr     cx, 1                   ; Setup to move 2 bytes         ;@P1
        .if     <ncxz>                  ; More to transfer?             ;@P1
            .repeat                     ;                               ;@P1
                inc     di              ;                               ;@P1
                HORZWAIT                ; Wait for horizontal retrace   ;@P1
                mov     ax, si          ; Restore attribute byte        ;@P1
                stosb                   ;                               ;@P1
                inc     di              ;                               ;@P1
                stosb                   ;                               ;@P1
                sti                     ; Enable interrupts             ;@P1
            .loop                       ;                               ;@P1
        .endif                          ;                               ;@P1
        pop     si                      ;                               ;@P1
        pop     dx                      ;                               ;@P1
        pop     ax                      ;                               ;@P1
        ret                             ;                               ;@P1

CGA_REP_INCDI_STOSB_LOOP    ENDP                                        ;@P1

        PUBLIC  CGA_REP_STOSW                                           ;@P1
CGA_REP_STOSW   PROC    FAR                                             ;@P1

;/*
;**  If CGA adapter was identified as FAST during BVH initialization,
;**  don't need retrace logic -- use direct data move.
;*/

        push    ds                                                      ;MS01
        push    ax                                                      ;MS01
        mov     ax,seg _OEMFlags                                        ;MS01
        mov     ds,ax                                                   ;MS01
        test    ds:word ptr[_OEMFlags],FAST_CGA                         ;MS01
        pop     ax                                                      ;MS01
        pop     ds                                                      ;MS01
        .if     <nz>                                                    ;MS01
            rep     stosw                                               ;MS01
            ret                                                         ;MS01
        .endif                                                          ;MS01

;/*
;**  CGA is slow -- need retrace logic:
;*/

        push    ax                      ; 
        push    bx                      ; 
        push    dx                      ; 
        push    si                      ; 
        mov     si, ax                  ; SI = char/attr pair
        mov     dx, STATUS_PORT         ; Setup CGA retrace status port
        test    cl, 1                   ; 
        .if     <nz>                    ; Odd byte?
            HORZWAIT                    ; Wait for horizontal retrace
            mov     ax, si              ; Get char/attr pair
            stosw                       ; 
            sti                         ; Enable interrupts
            dec     cx                  ; 
        .endif                          ; 
        .if     <ncxz>                  ; More to transfer?
            .repeat                     ; 
                ALLWAIT                 ; 
                mov     ax, si          ; Restore Cell
                stosw                   ; 
                stosw                   ; 
                dec     cx              ; 
                dec     cx              ; 
                .repeat                 ; 
                    in      al, dx      ; 
                    test    al, 1       ; 
                .leave  <z>             ; Retraces have passed
                    test    al, 8       ; 
                    .if     <nz>        ; Vertical retrace has begun
                        mov     bx, 624 ; 
                        .if     <bx a cx>
                            mov     bx, cx
                        .endif          ; 
                        sub     cx, bx  ; 
                        push    cx      ; 
                        mov     cx, bx  ; 
                        mov     ax, si  ; 
                        rep     stosw   ; 
                        pop     cx      ; 
                .leave                  ; 
                    .endif              ; 
                .until                  ; 
                sti                     ; Enable interrupts
                or      cx, cx          ; 
            .until  <z>                 ; 
        .endif                          ; 
        pop     si                      ; 
        pop     dx                      ; 
        pop     bx                      ; 
        pop     ax                      ; 
        ret                             ; 

CGA_REP_STOSW   ENDP                                                    ;@P1

R2SEG   ENDS

ENDIF   ;NOT CGA_ALWAYS_FAST                                            ;MS00
        END

