;*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    58,132
        TITLE   WDHMODE.Asm -- Windowable Device Handler Mode Routines

;/*****************************************************************************
;*
;* SOURCE FILE NAME = WDHMODE.Asm
;*
;* DESCRIPTIVE NAME = Windowable Device Handler Mode Routines
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION  BVS Device Handler for Windowable Sessions
;*              This module contains the equivalent of the OS/2 1.1
;*              hooks for Windowable and Advanced VIO.
;*
;* FUNCTIONS    GetMode, SetMode, ClearLVB
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES  NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;*   12/02/88  @T1        P2944   TPL, Grow LVB as neccessary,
;*   02/16/89  @T16       HZ00014 TPL, Disallowed Get/Set mode in AVIO session,
;*   03/06/89  @@S1       B700065 STJ, Refresh the cursor after SetMode,
;*   03/06/89  @@S2       B700413 STJ, Disallow Color Burst with Mono Modes,
;*   03/15/89  @C11       B700599 CJJ, Allow size of 4 and 5 for SetMode,
;*   03/25/89  @P1        D132    TPL, DCR 132 changes
;*   04/04/89  @C14       B700906 CJJ, Zero out AX after being used as temp
;*                                storage
;*   05/18/89  @C22       HZ00183 CJJ, Update scrollable region in UpdateMode,
;*   08/09/89  @B22       B706089 WKB, Check number of rows for validity,
;*   08/18/89  @S25       B706860 STJ, Use 1.0 length as default for GetXXXX
;*                                calls,
;*   11/02/89  @D549      D549    CJJ, Seltable changes due to rangeless
;*                                sessions
;*   01/22/90  @T52       D704    TPL, DCR 704 work
;*   07/06/90  @T71       B714347 TPL, Allow Shell to make AVIO calls, Hursley
;*                                DCR 25177,
;*   04/11/91             D1348   NAKADA, Enable DBCS support in Vio-Window,
;*   02/06/92  @T80               TPL, Don't use the reserved register FS
;*   11/10/93  @JLO1      D75613  Pj10886. Prevent overwrite of dev_name when
;*                                multiple threads write to Getsysmode area
;*   08/10/94  @92702             WKB, Allow modes other than 80 columns
;*   08/26/94  @94870             WKB, Check number of cols for validity
;*   09/14/94  @95837             WKB, pmwinp.inc -> pmwinx.inc
;*****************************************************************************/

        .xlist
        include pmwinx.inc              ;@95837
        include pmaviop.inc
        include wdhequ.inc              ;Windowable Device Handler Equates
        include wdhgdata.inc            ;BVH global data externals      ;@T52
        include bvscb.inc               ;BVS Control Blocks
        include bvsparms.inc            ;BVS Parameter Equates
        include error2.inc              ;OS/2 Subsystem Error Codes
        include infoseg.inc             ;System Information Segments
        include struc.inc               ;Structured Macros
        include error.inc               ;OS/2 Kernel Error Codes
        .list

        .386p                   ;@D549

        extrn   DOSREALLOCSEG:FAR       ;Realloc AVIO LVB               ;@T1
        extrn   DOSREALLOCHUGE:FAR      ;Realloc VIO windowable         ;@T1

        extrn   SecureSema4:NEAR
        extrn   ReleaseSema4:NEAR

        extrn   RegSave:NEAR
        extrn   RegRest:NEAR
        extrn   UpdateMode:NEAR
        extrn   CheckAvio:NEAR          ;@T16

        extrn   bvh_instance:DWORD                                      ;@T52
        extrn   GREENTRY4:FAR                                           ;@T52
        extrn   GREENTRY6:FAR                                           ;@T52
        extrn   WINSYNCWITHPS:FAR                                       ;@T52

WDHGSEG SEGMENT PARA PUBLIC 'DATA' USE16        ;@D549
WDHGSEG ENDS

R2CSEG  SEGMENT BYTE PUBLIC 'CODE' USE16        ;@D549
        ASSUME  CS:R2CSEG

;/****************************************************************************
;*
;*  SUBROUTINE NAME: GetMode
;*
;*  DESCRIPTIVE NAME: Get current video mode setting
;*
;*  FUNCTION: GetMode is called by BVS to get the current mode setting.
;*            If the request specifies hardware and the hardware is
;*            readable, the actual hardware setting will be read and
;*            returned.  Otherwise the returned information will be
;*            taken from the environment buffer, if it has been passed.
;*
;*  ENTRY POINT: GetMode
;*    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 271 )
;*
;*  INPUT: (Passed on stack)
;*             FAR *Environment ( Environment buffer for the session )
;*             FAR *ParmBlock
;*                     USHORT Length = length of this packet
;*                     USHORT Flags  = 0 - Environment buffer only
;*                                     1 - Hardware also
;*                     VIOMODEINFO FAR *ModeDataPTR
;*             ULONG Function ( Call vector table entry = 271 )
;*         (Referenced)
;*             Modes[] (global data - table of supported video modes )
;*
;*  EXIT-NORMAL: AX = 0
;*               Current mode setting is returned
;*
;*  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
;*
;*  EFFECTS: If hardware specified and hardware is readable, the
;*           environment buffer is updated, if passed.
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

GetMode PROC    FAR
        public  GetMode
        Call    RegSave

        mov     ax,ERROR_VIO_INVALID_LENGTH
;@JLO1  .if     <[si].vp_parmlength eq 8> and
        .if     <[si].vp_parmlength eq 8>                               ;@JLO1
        Call    SecureSema4                                             ;@JLO1
        les     di,dword ptr [si].vp_offset ;Get address of mode data
        lds     si,dword ptr [bp].stk_envblock ;Get environment block
        add     si,env_mdlen            ;Get offset of mode data
        mov     cx,es:[di].mode_datalen ;Get length of mode data
        .if     <cx a 1>
;@JLO1      Call    SecureSema4

            mov     ax,cx
            .if     <al a <size modedata>> ;@S25
                mov     al,mode_attrformat ;@S25
            .endif                      ;@S25

            push    di
            sub     al,size mode_datalen
            .if     <ns>
                movsw
            .endif

            sub     al,size mode_type
            .if     <ns>
                movsb
            .endif

            sub     al,size mode_colors
            .if     <ns>
                movsb
            .endif

            sub     al,size mode_cols
            .if     <ns>
                movsw
            .endif

            sub     al,size mode_rows
            .if     <ns>
                movsw
            .endif

            sub     al,size mode_gcols
            .if     <ns>
                movsw
            .endif

            sub     al,size mode_grows
            .if     <ns>
                movsw
            .endif

            sub     al,size mode_attrformat
            .if     <ns>
                movsb
            .endif

            sub     al,size mode_attrbytes
            .if     <ns>
                movsb
            .endif

            sub     al,size mode_bufaddr
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size mode_bufsize
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size mode_fullbufsz
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size mode_partbufsz
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            sub     al,size mode_extdata
            .if     <ns>
                movsd                                                   ;@T71
            .endif

            mov     ax,di
            pop     di
            sub     ax,di
            .if     <al a 2>            ;More than just a length request
                stosw                   ;Update length in Mode data
            .endif

;@JLO       Call    ReleaseSema4
            sub     ax,ax               ;Set good return code
        .endif

        Call    ReleaseSema4                                            ;@JLO
        .endif                                                          ;@JLO
        Call    RegRest
        ret     12
GetMode ENDP

;/****************************************************************************
;*
;*  SUBROUTINE NAME: SetMode
;*
;*  DESCRIPTIVE NAME: Set video mode
;*
;*  FUNCTION: SetMode is called by BVS to set the video mode.
;*            If the request specifies hardware, the hardware and the
;*            environment buffer, if passed, will be updated.
;*            Otherwise just the environment buffer, if passed, will
;*            be updated.
;*
;*  ENTRY POINT: SetMode
;*    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 272 )
;*
;*  INPUT: (Passed on stack)
;*             FAR *Environment ( Environment buffer for the session )
;*             FAR *ParmBlock
;*                     USHORT Length = length of this packet
;*                     USHORT Flags  = 0 - Environment buffer only
;*                                     1 - Hardware also
;*                     VIOMODEINFO FAR *ModeDataPTR
;*             ULONG Function ( Call vector table entry = 272 )
;*         (Referenced)
;*             Modes[] (global data - table of supported video modes )
;*
;*  EXIT-NORMAL: AX = 0
;*               Video mode is set
;*
;*  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS
;*
;*  INTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;*  EXTERNAL REFERENCES:
;*    ROUTINES: NONE
;*
;****************************************************************************/

SetMode PROC    FAR
        public  SetMode
        Call    RegSave

        mov     ax,ERROR_VIO_EXTENDED_SG ;@T16
        call    CheckAvio               ;@T16
        .if     <z> near                ; Vio windowable session?       ;@T16
            mov     ax,ERROR_VIO_INVALID_LENGTH
;@JLO1      .if     <[si].vp_parmlength eq 8> and near
            .if     <[si].vp_parmlength eq 8> near                      ;@JLO1
            Call    SecureSema4                                         ;@JLO1
            lds     si,dword ptr [si].vp_offset ;Get address of mode data
            mov     cx,[si].mode_datalen ;Get length of mode data
            .if     <cl ae 3> and near
            mov     ax,ERROR_VIO_MODE   ;Preset mode error
            mov     dl,[si].mode_type
            test    dl,NOT (mode_f_color + mode_f_uncolor)
            .if     <z> and near        ;Mono/Color Text only (Type = 0/1)
            mov     dh,dl               ;@@S2
            and     dh,mode_f_color + mode_f_uncolor ;@@S2
            .if     <dh ne mode_f_uncolor> and near ;No Color Burst w/Mono ;@@S2
            .if     <cl eq 3> or        ;Only Type specified
            and     dl,mode_f_color
            shl     dl,2
            .if     <dl eq [si].mode_colors> near ;Type/Colors = 1/4 or 0/0 ;@T1

IFDEF D1348
                .if     <cl ae <mode_attrformat+size mode_attrformat>>
                    mov     al,[si].mode_attrformat
                    .if     <cl ae <mode_attrbytes+size mode_attrbytes>> and
                    mov     ah,[si].mode_attrbytes
                    .if     <ax eq WorldFMTATTR>    and
                    .if     <<[si].mode_cols> eq 0>
                        mov     [si].mode_cols,80   ;set the default value
                    .endif
                    .if     <ax eq WorldFMTATTR>    and
                    .if     <<[si].mode_rows> eq 0>
                        mov     [si].mode_rows,25   ;set the default value
                    .endif
                .endif
ENDIF ;D1348
                mov     dx,25           ;Preset 25 rows
                .if     <cl b <mode_cols+size mode_cols>> or             ;@C11
                .if     <[si].mode_cols le 255> ;@92702
;@92702         .if     <[si].mode_cols eq 80> ;80-column modes only
                    sub     ax,ax
                    .if     <cl ae <mode_rows+size mode_rows>>
                        mov     ax,[si].mode_rows
;@94870                 .if     <ax be 0>       ;Check rows<=0          ;@B22
                        .if     <ax be 0> or    ;Check rows<=0          ;@94870
                        .if     <[si].mode_cols le 0>                   ;@94870
                            mov     ax,ERROR_VIO_MODE                   ;@B22
                        .else
                            mul     [si].mode_cols
                            .if     <ax a 2000h> or
                            .if     <nonzero dx>    ;Buffer too large
                                mov     ax,ERROR_VIO_MODE
                            .else
                                sub     ax,ax
                                mov     dx,[si].mode_cols               ;@92702
                                mov     es:[viops_BufferColumnCount],dx ;@92702
                                mov     dx,[si].mode_rows
                            .endif
                        .endif                                          ;@B22
                    .endif
                .endif

IFDEF D1348 ;set the format ID and attribute count
                .if     <zero ax> and
                mov     es:[viops_FormatID],DefaultFormat    ; initialize
                mov     es:[env_attrbytes],DefaultAttrCount  ; initialize
                .if     <cl ae <mode_attrformat+size mode_attrformat>>
                                        ; check format ID and attribute count
                    mov     ax,word ptr es:[env_attrformat]
                    mov     al,[si].mode_attrformat
                    .if     <cl ae <mode_attrbytes+size mode_attrbytes>>
                        mov     ah,[si].mode_attrbytes
                    .endif
                    .if     <ax eq DefaultFMTATTR> or
                    .if     <ax eq WorldFMTATTR>
                        mov     es:[env_attrbytes],ah        ; update
                        sub     ah,ah
                        mov     es:[viops_FormatID],ax       ; update
                        sub     ax,ax
                    .else
                        mov     ax,ERROR_VIO_MODE
                    .endif
                .endif
ENDIF ;D1348

                .if     <zero ax>   near                                ;@T1
;@JLO1              Call    SecureSema4

                    push    dx          ;Save requested rows
                    push    es          ;Save PS selector

IFDEF D1348 ;prepare the 2nd LVB for DBCS flag
                    mov     ax,es:[viops_FormatID]
                    .if     <al ne es:[env_attrformat]> ; change format ID
                        .if     <al eq DefaultFormat>
                            mov     es:[env_funcindx],DefaultFmtIndx

                            mov     es:[viops_CellByteSize],DefaultCellSize
                        .else                           ; WorldFMTATTR
                            mov     es:[env_funcindx],WorldFmtIndx

                            mov     es:[viops_CellByteSize],WorldCellSize
                        .endif
                        mov     es:[env_attrformat],al  ; update
                        call    ClearLVB                ; clear current LVB
                    .endif
ENDIF ;D1348

                    mov     ax,es:[viops_BufferColumnCount]         ;@T1;@T52
                    mul     dx          ;LVB size = row * col * cellsize;@T1
                    mul     es:[viops_CellByteSize]                 ;@T1;@T52
IFDEF D1348 ;save LVB size
                    push    ax
                    sub     ax,dx                       ; if 64KB, set 0FFFFh
                    mov     es:[env_lvbsize],ax
                    pop     ax
ENDIF ;D1348
                    cmp     dx,word ptr es:[bx].env_bufsize+2           ;@T1
                    .if     < a >   or                                  ;@T1
                    .if     < e > near  and                             ;@T1
                    .if     <ax a <word ptr es:[env_bufsize]>> near ;@T1;@T52
                        mov     di,WDHGSEG                              ;@T1
                        mov     ds,di   ;Global data segment            ;@T1
                        mov     cx,ax   ;Save size(low)                 ;@T1

                        push    dx                                      ;@T1
                        push    ax                                      ;@T1
                        push    es:[viops_Sel_LogicalVideoBuffer]   ;@T1;@T52
                        call    DOSREALLOCHUGE                          ;@T1
                        .if     <zero ax>   or                          ;@T1
                        .if     <ax e ERROR_ACCESS_DENIED>              ;@T1
                            mov     di,word ptr es:[env_bufsize]    ;@T1;@T52
                            sub     cx,di                               ;@T1
IFDEF D1348 ;update LVB clear to corresponding format ID
                            .if     <es:[viops_CellByteSize] eq DefaultCellSize>
ENDIF ;D1348
                                shr     cx,1                                ;@T1
                                mov     ax,0720H                            ;@T1
                                push    es                                  ;@T1
                                mov     es,es:[viops_Sel_LogicalVideoBuffer];@T1;@T52
                                cld                                         ;@T1
                                rep     stosw                               ;@T1
                                pop     es                                  ;@T1
IFDEF D1348 ;update LVB clear to corresponding format ID
                            .else                       ; WorldCellSize
                                shr     cx,2
                                mov     ax,0720h
                                mov     dx,0000h
                                push    es
                                mov     es,es:[viops_Sel_LogicalVideoBuffer]
                                cld
                                .repeat
                                    stosw
                                    mov     es:[di],dx
                                    inc     di
                                    inc     di
                                .loop
                                pop     es
                            .endif
ENDIF ;D1348
                            sub     ax,ax                               ;@T1
                        .endif                                          ;@T1
                    .else                                               ;@T1
                        sub     ax,ax                                   ;@T1
                    .endif                                              ;@T1

                    .if     <zero ax> near                          ;@T1;@T52

                        push    WDHGSEG                                 ;@T52
                        pop     ds                                      ;@T52
                        lgs     si,ds:bvh_instance                      ;@T80

                        push    dword ptr es:[viops_hConsoleDisplayContext] ;@@E,@T71
                        push    dword ptr 5     ;32-bit Index           ;@T71
                        push    gs                                      ;@T80
                        lea     ax,gs:[si].wdhi_Scratch                 ;@T80
                        push    ax              ;32-bit Return Value    ;@T52
                        push    dword ptr 1     ;32-bit number of items ;@T71
                        push    dword ptr 0     ;32-bit "cookie" parm ;@T52,@T71
                        push    dword ptr GreQueryDevCapsLo             ;@T71

                        call    GREENTRY6                               ;@T52

                        pop     es              ;Restore PS selector
                        pop     dx              ;Restore requested number of rows
                        sub     bx,bx
                        .if     <ax ne 1>
                            mov     ax,ERROR_VIO_MODE
                        .else
                            mov     es:[bx].viops_BufferRowCount,dx ;Update #rows
                            Call    UpdateMode

                            push    es
                            push    es:[bx].env_conhandle
                            call    WINSYNCWITHPS                       ;@T52
                            pop     es

                            sub     bx,bx ;@@S1
                            mov     ax,es:[bx].viops_BufferRowCount ;Get # of rows ;@@S1
                            dec     ax  ;Normalize to 0 base ;@@S1
                            mov     es:[bx].viops_TextCursorRow,ax ;@@S1
                            mov     es:[bx].viops_TextCursorColumn,bx ;@@S1

                            mov     ax,es:[bx].viops_CellImageHeight ;@@S1
                            dec     ax  ;@@S1
                            mov     es:[bx].viops_TextCursorEndLine,ax ;@@S1
                            dec     ax  ;@@S1
                            mov     es:[bx].viops_TextCursorStartLine,ax ;@@S1

                            push    es                                  ;@P1
                            push    dword ptr es:[bx].viops_hConsoleDisplayContext ;DC handle ;@@S1,@T71
                            push    es  ;@@S1
                            push    bx  ;Ptr to VioPS ;@@S1
                            push    dword ptr 0  ;"cookie" parm pt. 2 ;@@S1,@T71
                            push    dword ptr GreUpdateCursorLo ;Engine function pt. 2 ;@@S1,@T71
                            call    GREENTRY4 ;Refresh the cursor  ;@@S1;@T52
                            pop     es                                  ;@P1

                            sub     ax,ax
                        .endif
                    .else                                               ;@T1
                        pop     es                                      ;@T1
                        pop     dx                                      ;@T1
                    .endif                                              ;@T1
;@JLO1              Call    ReleaseSema4
                .endif
            .endif                      ;@T16
        .endif

        Call    ReleaseSema4                                            ;@JLO1
        .endif                                                          ;@JLO1

        Call    RegRest
        ret     12
SetMode ENDP

IFDEF D1348

;/****************************************************************************
;*
;* FUNCTION NAME = ClearLVB
;*
;* DESCRIPTION   =
;*
;* INPUT         =
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;****************************************************************************/

ClearLVB proc   near
         public ClearLVB

        push    ds
        push    es
        push    di
        push    cx
        push    dx

        mov     cx,word ptr es:[env_lvbsize]
        mov     dl,es:[env_attrformat]
        push    es
        pop     ds
        mov     es,es:[viops_Sel_LogicalVideoBuffer]    ; LVB selector
        sub     di,di

        .if     <dl eq DefaultFormat>
            shr     cx,1                                ; cell size
            mov     ax,0720h                            ; attr and char
            rep     stosw
                                                        ; prepare the 2nd LVB
                                                        ; for DBCS flag
        .else                                           ; WorldFormat
            shr     cx,2                                ; cell size
            mov     ax,0720h                            ; attr1 and char
            mov     dx,0000h                            ; attr3 and attr2
            .repeat
                stosw
                mov     es:[di],dx
                inc     di
                inc     di
            .loop
        .endif

        pop     dx
        pop     cx
        pop     di
        pop     es
        pop     ds

        ret
ClearLVB endp
ENDIF ;D1348

R2CSEG  ENDS
        END

