;*DDK*************************************************************************/
;
; 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.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = EGASTATE.ASM
;*
;* DESCRIPTIVE NAME = Pointer shape support routines
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/06/87
;*
;* DESCRIPTION  SAVE_HW_REGS is called by the pointer shape routine to save
;*              the state of those EGA's registers which must be used to
;*              draw the pointer shape.  RES_HW_REGS is called by the
;*              pointer shape routine to restore the state of those EGA
;*              registers saved by SAVE_HW_REGS, and to prepare for the next
;*              call to SAVE_HW_REGS.  INIT_HW_REGS is called immediately
;*              after the EGA is placed into graphics mode to initialize
;*              locations in EGA memory that are required by, but not
;*              altered by, SAVE_HW_REGS.
;*
;*              Restrictions:
;*
;*              These routines are intended to be executed while protected
;*              with some form of a semephore.  The contents of both the
;*              Graphics Controller Address Register and the Sequencer Address
;*              Register are assumed to belong to these pieces of code while
;*              executing, and assumed not to change unless done so by these
;*              routines.  INIT_HW_REGS must be called before any call to
;*              either SAVE_HW_REGS or RES_HW_REGS.  RES_HW_REGS must be
;*              called prior to the next call to SAVE_HW_REGS or the detection
;*              code will fail.
;*
;* FUNCTIONS    init_hw_regs
;*              set_misc_regs
;*              set_test_locs
;*              DeviceSeamlessInit
;*              far_exclude16
;*              init_hw_regs16
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   06-Jan-1987                  Written by Walt Moore [waltm]
;*   11/26/92                     John Batty. Added DCAF changes.
;*   04/13/93              63750  Fix video corruption problem
;*
;*****************************************************************************/

.386
.MODEL FLAT
ASSUME  SS:FLAT, DS:FLAT, CS:FLAT, ES:FLAT

        .xlist
        include pmgre.inc
        DINCL_BITMAP            equ     1
        DINCL_EGAMEM            equ     1
        DINCL_ENABLE            equ     1
        include driver.inc
        include egafam.inc
        include extern.inc
IFDEF DCAF                                                           ;          
        include protos.inc                                           ;          
ENDIF ;DCAF                                                          ;          
ifdef EGAMEM_IS_STRUCT
        include egamem.inc
endif
ifdef SEAMLESS
        include seamless.inc
        INCLUDE pointer.inc
        include curstrc.inc
endif
if SCAN_CNT EQ 768
IFNDEF DCAF                                                          ;          
        include protos.inc
ENDIF ; DCAF                                                         ;          
        include oem_macs.inc
endif
        .list


set_test_locs PROTO SYSCALL
set_misc_regs PROTO SYSCALL
far_exclude16 PROTO FAR16 SYSCALL
far_unexclude16 PROTO FAR16 SYSCALL
init_hw_regs16 PROTO FAR16 SYSCALL


;/*
;**  Data register I/O addresses must follow the Address register
;**  I/O addresses.
;*/

        .ERRNZ  GRAF_DATA-GRAF_ADDR-1
        .ERRNZ  SEQ_DATA-SEQ_ADDR-1

;/*
;**   Don't want to explicitly define a read mode on every output to
;**   the Graphics Controller's Mode Register.  The default should be
;**   Data Read if not specified.
;*/

        .ERRNZ  M_DATA_READ

;/*
;**   The ordering of the planes and their index values are assumed
;**   to be the following.  It is unlikely that these will ever
;**   change.
;*/

        .ERRNZ  MM_C3-00001000b         ;Map mask values
        .ERRNZ  MM_C2-00000100b
        .ERRNZ  MM_C1-00000010b
        .ERRNZ  MM_C0-00000001b

        .ERRNZ  RM_C0                   ;Read map values (sequential)
        .ERRNZ  RM_C1-RM_C0-1
        .ERRNZ  RM_C2-RM_C1-1
        .ERRNZ  RM_C3-RM_C2-1


;/*
;**  The following locations are used to save and restore
;**  the indicated EGA registers.
;*/


.DATA
        ALIGN   4


                db      GRAF_ENAB_SR    ;Enable Set/Reset register address
saved_enab_sr   db      ?               ;Computed Enable Set/Reset

                db      GRAF_DATA_ROT   ;Data Rotate register address
saved_data_rot  db      ?               ;Computed Data Rotate function

                db      GRAF_READ_MAP   ;Read Map register address
saved_read_map  db      ?               ;Computed Read Map Select

                db      GRAF_BIT_MASK   ;Bit Mask register address
saved_bit_mask  db      ?               ;Computed Bit Mask

saved_map_mask  db      ?               ;Computed Map Mask

;/*
;**   The func_select table is used to translate the results of step
;**   5C into the actual value for the Data Rotate register.  The
;**   algorithm which scans the planes to determine the boolean
;**   operation of the Data Rotate register returns 0 wherever a
;**   changed occured in the table listed for step 5C.
;**
;**   Since C0 is never involved in the result, it is masked off
;**   via a SHR instruction.
;*/



        ALIGN   4
func_select     label   byte
        db      DR_SET                  ;000 - illegal
        db      DR_SET                  ;001 - illegal
        db      DR_XOR                  ;010 - XOR
        db      DR_SET                  ;011 - illegal
        db      DR_SET                  ;100 - SET
        db      DR_AND                  ;101 - AND
        db      DR_OR                   ;110 - OR
        db      DR_SET                  ;111 - illegal


ifdef SEAMLESS


_SEAMLESSDATA SEGMENT 'DATA'

PUBLIC SeamDataStart
SeamDataStart   LABEL DWORD

else ;NOT SEAMLESS

_DATA SEGMENT 'DATA'

PUBLIC DataStart
DataStart   LABEL DWORD
endif  ;SEAMLESS

        ALIGN   4
drqVideo           vvdrq_s <0A0000h,\
                            0ffffffffh,\
                            reserved_latches,\
                            OFFSET fbShadowFlags,\
                            OFFSET fControllerOwned,\
                            OFFSET fControllerNotify,\
                            shadow_size,\
                            OFFSET shadow_data>

;/*
;**   The following shadow data is updated by the Video VDD whenever it
;**   is sharing VRAM with the display driver.  Note that when the VDD
;**   doesn't own the controller, this data simply contains the default
;**   settings required by display driver for normal task-time operation.
;**
;**   In other words, the pointer code always restores unreadable registers
;**   directly from these tables.  It does not care who (PM thread, or
;**   windowed graphics VDM thread) it interrupts.
;*/

        public  shadow_data             ;shadow_data must be the address
        public  shadow_size             ;of the first "shadowed_xxx" entry

        public  shadowed_seq_indx
        public  shadowed_seq_mode
        public  shadowed_graf_indx
        public  shadowed_graf_rot
        public  shadowed_graf_mode
        public  shadowed_graf_misc

        ALIGN   4
        shadow_data label byte
shadowed_seq_indx   vvreg_s     <EGA_BASE+SEQ_ADDR,  -1, SEQ_MAP_MASK>
shadowed_seq_mode   vvreg_s     <EGA_BASE+SEQ_ADDR,  SEQ_MODE,  SM_ODD_PLANE OR SM_EXTENDED>
shadowed_graf_indx  vvreg_s     <EGA_BASE+GRAF_ADDR, -1, GRAF_BIT_MASK>
shadowed_graf_rot   vvreg_s     <EGA_BASE+GRAF_ADDR, GRAF_DATA_ROT, DR_SET>
shadowed_graf_mode  vvreg_s     <EGA_BASE+GRAF_ADDR, GRAF_MODE, M_PROC_WRITE OR M_DATA_READ>
shadowed_graf_misc  vvreg_s     <EGA_BASE+GRAF_ADDR, GRAF_MISC, MS_NON_ALPHA OR MS_A0000_64K>
        shadow_size = ($-shadow_data)/size vvreg_s


;/*
;** The following is data added to support sharing of off-screen memory and
;** the video controller between the PM display driver and the video driver
;** for MVDM.
;**
;** fControllerOwned and fControllerNotify are flags managed jointly by
;** display driver and video driver;  fControllerMine, on the other hand, is
;** set only when fControllerOwned has been set by the display driver.
;**
;** fbOffScreen contains bits describing availability and use of off-screen
;** memory.  If the video driver is loaded, we rely on it for allocation/
;** deallocation of off-screen memory;  otherwise, we are on our own (just
;** like in the good ol' days of 1.1 and 1.2).
;**
;** pOffScreenUsed holds the address of off-screen memory currently in use,
;** and nbOffScreenUsed is the size of that memory (in number of contiguous
;** bytes).  If the display driver ever supports multiple clients of
;** off-screen memory, then it can link blocks of off-screen memory together
;** either with a separate linked list, or by storing links and owner IDs in
;** the blocks themselves.
;**
;** The address kept in pOffScreenUsed is actually an offset from the top of
;** physical VRAM, and must be combined with an appropriate physical VRAM
;** selector/alias before it can be dereferenced.
;**
;** lnbTotalScreenSize is a dword count of the total number of bytes of memory
;** installed on the adapter, divided by the maximum number of planes, to
;** yield the total amount of multi-plane memory available.  For a 256k EGA or
;** VGA, this would be 64k (65536D aka 10000h).
;*/

        public  fVDMControllerMine

        ALIGN   4
fControllerOwned        BYTE    0
fControllerNotify       BYTE    0
fbShadowFlags           BYTE    0
fControllerMine         BYTE    0
fbOffScreen             BYTE    0
fVDMControllerMine      BYTE    0

InnerCheckCursor PROTO SYSCALL

ifdef SEAMLESS
        PUBLIC  SeamlessStack,SeamlessStackEnd
        ALIGN   4
SeamlessStackGuard      db      4   dup('seam')
SeamlessStack           db      250 dup('_SEAMLESS_STACK_')
SeamlessStackEnd        LABEL   DWORD

EXTERNDEF SM_WINDRV:_SM_WINDRV
EXTERNDEF CurData:CURSORSTRUCT

SM_RING2_16BIT_CODE_MAP    EQU  SM_RING2 OR SM_CODE_ADDRESS OR SM_ADDRESS_16BIT OR SM_MAPPING  OR SM_MATCH_LINEAR
SM_RING2_16BIT_DATA_MAP    EQU  SM_RING2 OR SM_DATA_ADDRESS OR SM_ADDRESS_16BIT OR SM_MAPPING  OR SM_MATCH_LINEAR
SM_RING3_16BIT_CODE_MAP    EQU  SM_RING3 OR SM_CODE_ADDRESS OR SM_ADDRESS_16BIT OR SM_MAPPING  OR SM_MATCH_LINEAR
SM_RING2_16BIT_DATA_PASS   EQU  SM_RING2 OR SM_DATA_ADDRESS OR SM_ADDRESS_16BIT OR SM_PASSTHRU OR SM_MATCH_LINEAR

SM_RING2_32BIT_CODE_MAP    EQU  SM_RING2 OR SM_CODE_ADDRESS OR SM_ADDRESS_32BIT OR SM_MAPPING  OR SM_MATCH_LINEAR
SM_RING2_32BIT_DATA_MAP    EQU  SM_RING2 OR SM_DATA_ADDRESS OR SM_ADDRESS_32BIT OR SM_MAPPING  OR SM_MATCH_LINEAR
SM_RING3_32BIT_CODE_MAP    EQU  SM_RING3 OR SM_CODE_ADDRESS OR SM_ADDRESS_32BIT OR SM_MAPPING  OR SM_MATCH_LINEAR
SM_RING2_32BIT_DATA_PASS   EQU  SM_RING2 OR SM_DATA_ADDRESS OR SM_ADDRESS_32BIT OR SM_PASSTHRU OR SM_MATCH_LINEAR


        public          SM_PMDISP_ADDRESSES
        ALIGN   4
SM_PMDISP_ADDRESSES     _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_CODE_MAP,  SEAM_THUNK_SIZE, OFFSET SeamThunkStart>
                        _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_MAP,  SEAM_DATA_SIZE , OFFSET SeamDataStart>
smSem                   _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_MAP,  0fffh          , 0>
smICC                   _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_CODE_MAP,  0fffh          , OFFSET InnerCheckCursor>
smPass                  _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_PASS, 0              , 0>
smVRAM                  _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_MAP,  0fffh          , OFFSET pVRAMInstance>
smVRAMVal               _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_MAP,  0              , 0>
smCurData               _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_MAP,  0fffh          , OFFSET FLAT:CurData>
ifdef DCAF                                                           ;          
smDCAF                  _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_CODE_MAP,  0fffh          , OFFSET SeamlessExcludeCursor> ;          
smSeamlessSCA           _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_DATA_MAP,  0fffh          , OFFSET SeamlessSCA> ;          
endif ;DCAF                                                          ;          
smText                  _SM_PMDISP_ADDRESSES < SM_RING2_32BIT_CODE_MAP,  0ffffh         , OFFSET FLAT:_TEXT>
NUM_SM_ADDRESSES EQU ($-SM_PMDISP_ADDRESSES) / (sizeof _SM_PMDISP_ADDRESSES)

public SM_SETSIZE

ALIGN 4
if SCAN_CNT EQ 480
  SM_SETSIZE      VMSSIZE <, 12h, SCREEN_CX, SCREEN_CY, 1, 1, 28h, 14h, 8>
endif
if SCAN_CNT EQ 600
  SM_SETSIZE      VMSSIZE <, 12h, 800, 600, 1, 1, 28h, 14h, 8>
endif
if SCAN_CNT EQ 768
  SM_SETSIZE      VMSSIZE <, 12h, 1024, 768, 1, 1, 28h, 14h, 8>
endif

endif ;SEAMLESS


ifdef SEAMLESS
SEAM_DATA_SIZE EQU $ - SeamDataStart
_SEAMLESSDATA ENDS

else  ;NOT SEAMLESS
DATA_SIZE EQU $ - DataStart
_DATA ENDS

endif ;SEAMLESS

.CODE

page

;/***************************************************************************
;*
;* FUNCTION NAME = init_hw_regs
;*
;* DESCRIPTION   = This routine is called at display initialization time to
;*                 initialize the state required to save and restore the
;*                 EGA's registers and processor latches.  The default EGA
;*                 state assumed by the rest of the display driver code is
;*                 also initialized.  This code is intended to be called
;*                 immediately after the EGA has been programmed for
;*                 graphics mode and the palette registers set.
;*
;*                 Registers Destroyed:
;*                       AX,CX,DX,FLAGS
;*                 Registers Preserved:
;*                       BX,SI,DI,BP,DS,ES
;*
;* INPUT         = sdScreen.sd_pBits is vga pointer
;*                 Carry   = CLEAR if total reset required, SET if not
;*                           In the SET case, ES need not be set to EGAMem
;* OUTPUT        = SEQ_ADDR        = SEQ_MAP_MASK                  (EGA register)
;*                 SEQ_MAP_MASK    = all planes enabled            (EGA register)
;*                 GRAF_ADDR       = GRAF_BIT_MASK                 (EGA register)
;*                 GRAF_ENAB_SR    = all planes disabled           (EGA register)
;*                 GRAF_DATA_ROT   = DR_SET                        (EGA register)
;*                 GRAF_MODE       = M_DATA_READ+M_PROC_WRITE      (EGA register)
;*                 shadowed_graf_mode  = M_DATA_READ+M_PROC_WRITE  (EGA shadow)
;*                 GRAF_BIT_MASK   = all bits enabled              (EGA register)
;*
;*
;*
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*                   PSEUDO CODE
;*
;* NULL near init_hw_regs()
;* {
;*   SEQ_ADDR            = SEQ_MAP_MASK;             // all code assumes this
;*   set_test_locs;                                  // init ega ram locations
;*   plane_index[C3:C0]  = C3:C0;                    // set read map index
;*   SEQ_MAP_MASK        = MM_ALL;                   // enable all planes
;*   GRAF_ADDR           = GRAF_BIT_MASK;            // --> to BIT MASK
;*   shadowed_graf_mode  = M_READ_MODE+M_PROC_WRITE; // init shadowed mode
;*   return();                                       //   in all planes
;* }
;**************************************************************************/

        ALIGN   4
init_hw_regs PROC SYSCALL USES EDI


        mov     ax,wSVGAtype            ;*   04/13/93             Fix video corruption problem
        mov     CurData.vga_svgatype,ax ;*   04/13/93             Fix video corruption problem

        mov     edi,pVRAMInstance
        mov     dx,EGA_BASE+GRAF_ADDR
        mov     ax,GRAF_ENAB_SR         ;Set all planes disabled
        out     dx,ax

        mov     al,GRAF_DATA_ROT        ;Set to DR_SET
        .ERRNZ  DR_SET
        out     dx,ax
        mov     shadowed_graf_rot.vvr_value,ah

        mov     al,GRAF_MODE            ;Set to M_DATA_READ+M_PROC_WRITE
        .ERRNZ  M_DATA_READ+M_PROC_WRITE
        out     dx,ax
        mov     shadowed_graf_mode.vvr_value,ah

        mov     ax,0FF00h+GRAF_BIT_MASK ;Leave the Graphics Controller
        out     dx,ax                   ;Address register set to the Bit Mas
        mov     shadowed_graf_indx.vvr_value,al

        mov     dl,SEQ_ADDR             ;Set SEQ_ADDR to Map Mask
        mov     al,SEQ_MAP_MASK         ;Only this routine will do this
        out     dx,al                   ; 
        mov     shadowed_seq_indx.vvr_value,al
        inc     dl                      ;advance to SEQ_DATA (in case we jump)
        jc      init_regs_only

        INVOKE  set_test_locs           ;Initialize SAVE_HW_REGS locations

        mov     ax,RM_C3 shl 8 + MM_C3  ;Set Read Map index into each plane.
        .ERRNZ   MM_C3-00001000b         ;Must execute loop four times

init_hw_regs_10:
        out     dx,al                   ;Select plane
        OVAccess        ;access offscreen VRAM
ifdef EGAMEM_IS_STRUCT
        mov     [EDI].EGAMem.plane_index,ah          ;Set plane's index into the plane
else
        mov     [EDI+plane_index],ah          ;Set plane's index into the plane
endif
        OVRestore
        dec     ah                      ;Show next plane
        shr     al,1                    ;Set next Map Enable mask
        jnz     init_hw_regs_10         ;More planes to deal with

init_regs_only:
        mov     al,MM_ALL               ;Set Map Mask to all planes
        out     dx,al

        test    shadowed_seq_mode.vvr_value,SM_ODD_PLANE
        jz      init_hw_setmisc
        mov     al,shadowed_graf_misc.vvr_value
        and     al,MS_NON_ALPHA+MS_ADDR_MASK
        cmp     al,MS_NON_ALPHA+MS_A0000_64K
        je      init_hw_exit

init_hw_setmisc:
        mov     cx,(SM_EXTENDED+SM_ODD_PLANE) + (MS_NON_ALPHA+MS_A0000_64K) shl 8
        INVOKE  set_misc_regs
        mov     shadowed_seq_mode.vvr_value,cl
        mov     shadowed_graf_misc.vvr_value,ch

init_hw_exit:
        ret

init_hw_regs    ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = set_misc_regs
;*
;* DESCRIPTION   = Set miscellaneous registers
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

set_misc_regs PROC SYSCALL

        push    bx                                                ;          
        mov     bx,wSVGAtype            ;insure non-interruption  ;          

        cli                             ;can't use out because of this CLI
        mov     dl,SEQ_ADDR
        mov     ax,0100h                ;clear synchronous reset bit
        out     dx,ax

;/*
;** FIX for timing problem on IBM VGA
;** bypass trashing "mystery reg" 7
;** for these chipsets
;*/

        cmp     bx,VIDEO7_ADAPTER                                 ;          
        je      @F
        cmp     bx,TSENG_ADAPTER                                  ;          
        je      @F

        mov     ax,0007h                ;select "mystery reg" 7 of sequencer
        out     dx,ax                   ;and write a 0 to it
        mov     ax,013Fh                ;select "mystery reg" 3Fh of the CRTC
        mov     dl,CRTC_ADDR            ; 
        out     dx,ax                   ;write a 1 to the color location
        mov     dl,CRTC_ADDR-20h        ; 
        out     dx,ax                   ;and to the mono location as well

;/*
;** END FIX for timing problem on IBM VGA
;*/
@@:
        mov     dl,GRAF_ADDR
        mov     al,GRAF_MISC
        mov     ah,ch
        out     dx,ax                   ;set GRAF_MISC to required configuration
        mov     al,shadowed_graf_indx.vvr_value
        out     dx,al                   ;leave GRAF_ADDR pointing to correct reg

        mov     dl,SEQ_ADDR
        mov     al,SEQ_MODE
        mov     ah,cl
        out     dx,ax                   ;set SEQ_MODE to required configuration

        mov     ax,0300h                ;turn synchronous reset bit back on
        out     dx,ax
        sti                             ;end of uninterruptible section

        mov     al,shadowed_seq_indx.vvr_value
        out     dx,al                   ;leave SEQ_ADDR pointing to correct reg
        pop     bx                                                ;          
        ret

set_misc_regs  ENDP


page
;/***************************************************************************
;*
;* FUNCTION NAME = set_test_locs
;*
;* DESCRIPTION   = This routine is called to initialize those locations of EGA
;*                 memory use by SAVE_HW_REGS to determine the state of the
;*                 EGA registers.
;*
;*                 Registers Destroyed:
;*                       AX,FLAGS
;*                 Registers Preserved:
;*                       BX,DH,SI,DI,BP,DS,ES,FLAGS
;*
;* INPUT         = DS              = PtrData segment selector
;*                 EDI             = EGA memory selector
;*                 DH              = EGA_BASE
;*                 SEQ_ADDR        = SEQ_MAP_MASK               (EGA register)
;*                 GRAF_ENAB_SR    = all planes disabled        (EGA register)
;*                 GRAF_DATA_ROT   = DR_SET                     (EGA register)
;*                 GRAF_MODE       = M_DATA_READ+M_PROC_WRITE   (EGA register)
;*                 GRAF_BIT_MASK   = all bits enabled           (EGA register)
;*
;* OUTPUT        = DL              = SEQ_DATA                   (EGA register)
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;*                  PSEUDO-CODE
;*   NULL near set_test_locs()
;*   {
;*     known_word[C0:C3]  = 0x00FF;
;*     enable_test[C0:C1] = 0x00;
;*     enable_test[C2:C3] = 0xFF;
;*     return();
;*   }
;*
;**************************************************************************/

        ALIGN   4
set_test_locs PROC SYSCALL

        OVAccess        ;access offscreen VRAM
        mov     ax,00FFh                         ;Set 00FF into all planes
ifdef EGAMEM_IS_STRUCT
        mov     [EDI].EGAMem.known_word,ax       ;of a known word
else
        mov     [EDI+known_word],ax              ;of a known word
endif
        mov     dl,SEQ_DATA                      ;Set 00 into C0 and C1
        mov     al,MM_C0+MM_C1
        out     dx,al
ifdef EGAMEM_IS_STRUCT
        mov     [EDI].EGAMem.enable_test,ah
else
        mov     [EDI+enable_test],ah
endif
        mov     al,MM_C2+MM_C3                   ;Set FF into C2 and C3
        out     dx,al
ifdef EGAMEM_IS_STRUCT
        mov     [EDI].EGAMem.enable_test,0FFh
else
        mov     BYTE PTR [EDI+enable_test],0FFh
endif
        OVRestore                                ;Restore VGA to previouse state
        ret
set_test_locs ENDP

ifdef SEAMLESS

EXTERN   DOS32FLATTOSEL:NEAR

;/***************************************************************************
;*
;* FUNCTION NAME = DeviceSeamlessInit
;*
;* DESCRIPTION   = Prepare for seamless operation
;*
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4
DeviceSeamlessInit PROC SYSCALL,
        pAlias:DWORD

        mov     drqVideo.offLatchByte,reserved_latches

        LEA     EAX,fControllerOwned
        MOV     SM_WINDRV.fbControllerOwnedOff,AX
        LEA     EAX,fControllerNotify
        MOV     SM_WINDRV.fbControllerNotifyOff,AX
        LEA     EAX,fbShadowFlags
        MOV     SM_WINDRV.fbShadowFlagsOff,AX
        LEA     EAX,fVDMControllerMine
        MOV     SM_WINDRV.fbControllerMineOff,AX
        LEA     EAX,shadowed_graf_mode
        MOV     SM_WINDRV.fbShadowedGrafModeOff,AX

        LEA     EAX,SeamDataStart
        CALL    DOS32FLATTOSEL
        SHR     EAX,16
        MOV     SM_WINDRV.PtrDataSeg,AX

        LEA     EAX,SM_WINDRV
        CALL    DOS32FLATTOSEL
        MOV     smPass.pStart,EAX

        LEA     EAX,InnerCheckCursor
        MOV     smICC.pStart,EAX

        LEA     EAX,pVRAMInstance
        MOV     smVRAM.pStart,EAX

        MOV     EAX,pVRAMInstance       ;now get value
        MOV     smVRAMVal.pStart,EAX
        MOV     smVRAMVal.ulLength,0ffffh

ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** Give Seamless addressability to the DCAF code and data           ;          
;*/                                                                  ;          
        mov     eax,offset FLAT:SeamlessExcludeCursor                ;          
        mov     smDCAF.pStart,eax                                    ;          
        mov     ebx, offset FLAT:SeamlessCodeEnd                     ;          
        sub     ebx,eax                                              ;          
        mov     smDCAF.ulLength,ebx                                  ;          
                                                                     ;          
        mov     eax,offset FLAT:SeamlessSCA                          ;          
        mov     smSeamlessSCA.pStart,eax                             ;          
        mov     eax,size SCA                                         ;          
        mov     smSeamlessSCA.ulLength,eax                           ;          
endif ;DCAF                                                          ;          
                                                                     ;          

        mov     eax,offset FLAT:CurData
        mov     smCurData.pStart,eax
        mov     smCurData.ulLength,0fffh

        mov     eax,offset FLAT:_TEXT
        mov     smText.pStart,eax
        mov     smText.ulLength,0bfffh

        mov     EDX,pAlias
        mov     [EDX].ALIASPARM.ulLen,SIZEOF ALIASPARM
        LEA     EAX,SeamDataStart
        CALL    DOS32FLATTOSEL
        shr     eax,16
        mov     [EDX].ALIASPARM.dsel,ax
        LEA     EDX,SM_WINDRV
        MOV     AX,SEG _SEAMCODE16
        mov     WORD PTR [EDX+06h],AX
        mov     WORD PTR [EDX+0Ah],AX
        mov     WORD PTR [EDX+0Eh],AX

        mov     ax,offset _SEAMCODE16:far_exclude16
        mov     WORD PTR [EDX+04h],AX
        mov     ax,offset _SEAMCODE16:far_unexclude16
        mov     WORD PTR [EDX+08h],AX
        mov     ax,offset _SEAMCODE16:init_hw_regs16
        mov     WORD PTR [EDX+0Ch],AX

        LEA     EAX,smSem
        mov     edx,NUM_SM_ADDRESSES
        ret
DeviceSeamlessInit ENDP
endif ;SEAMLESS

_SEAMCODE16 SEGMENT     PARA USE16 PUBLIC 'CODE'
PUBLIC SeamThunkStart
SeamThunkStart LABEL DWORD


SEAM_THUNK_SIZE EQU 0fffh


_SEAMCODE16 ENDS

end
