;*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 = INIT.ASM
;*
;* DESCRIPTIVE NAME = Driver Initialization routines
;*
;*
;* VERSION      V2.0
;*
;* DATE         09/01/90
;*
;* DESCRIPTION  This file contains all the functions which are performed only at
;*              boot time.  This includes those initialization functions which are
;*              performed the very first time that the Enable function is called.
;*
;*              Load procedure called once when module is loaded.
;*
;*              At 16bit driver level, register contents were:
;*
;*                    AX = module handle of loading "application"
;*                    SI = HEAPSIZE parameter
;*                    DI = module handle of .DLL
;*                    DS = DGROUP for module if there is one, otherwise appl's DS
;*
;*              Following comments extracted from \dos\task\tklibi.c which seems to
;*              be relevant documentation for this:
;*
;*               If dispatching to a 32-bit DLL init the user stack on entry to the
;*               init routine looks as follows:
;*                      (ESP+0) return address to the ring 3 dispatcher
;*                      (ESP+4) module handle of this library
;*                      (ESP+8) PDLL group handle, 0 if none
;*
;* FUNCTIONS    DllLoadProc
;*              one_time_init
;*              get_rip_flag
;*              ring3_VioGetConfig
;*              GetVRAMPointer
;*              GetVRAMR0Pointer
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   09/01/90                     Rewrite for 32 bit OS/2 - ScottL @ Micrografx
;*   07/06/92              41616  DAK  model/submodel for nectarine and cursor type
;*   12/06/92             SM12669 DAK  separate fonts into different HMODULE
;*   11/02/92              56549  Changes needed to work with 256-color SVGA
;*   01/12/93              59460  Model/submodel for nectarine prime and cursor type
;*   01/18/93                     Dynamic loading of DCAF function addresses
;*   11/04/93  @NI2      PJ11007  Modified to load FM at the per-proc init time.
;*****************************************************************************/

        .386

        OPTION  OLDSTRUCTS

        .MODEL FLAT,SYSCALL

        ASSUME  SS:FLAT, DS:FLAT, CS:FLAT, ES:FLAT

        .xlist

ifdef DCAF                                                           ;          
INCL_GRE_SCREEN         equ     1                                    ;          
endif ;DCAF                                                          ;          
INCL_GRE_FONTS          equ     1
INCL_DOSRESOURCES       equ     1
INCL_DOSNLS             equ     1
INCL_FONTFILEFORMAT     equ     1
INCL_GRE_FONTS          equ     1
INCL_DEV                equ     1
INCL_VIO                equ     1
INCL_DOSFILEMGR         equ     1
INCL_DOSPROCESS         equ     1
INCL_DOSMVDM            equ     1
INCL_DOSDEVICES         equ     1
INCL_DOSMODULEMGR       equ     1
INCL_AVIOP              equ     1
INCL_WINSHELLDATA       equ     1

        include pmgre.inc

DINCL_VIO       equ     1
DINCL_ERROR     equ     1
DINCL_ENABLE    equ     1
DINCL_BITMAP    equ     1

        include driver.inc
        include protos.inc
        include extern.inc
        include fontseg.inc
        include svgadd.inc

ifdef SEAMLESS

        include seamless.inc

endif

        .list

EXTERN   DOS32SELTOFLAT:NEAR

        .DATA
OemHelp BYTE      "OEMHLP$",0

ifdef DCAF                                                           ;          
pfnGetScreenBits          DWORD 0                                    ;          
pfnSetScreenBits          DWORD 0                                    ;          
pfnUnPackBuffer           DWORD 0                                    ;          
fDCAFEnabled              DWORD 0                                    ;          
PUBLIC pfnGetScreenBits                                              ;          
PUBLIC pfnSetScreenBits                                              ;          
PUBLIC pfnUnPackBuffer                                               ;          
PUBLIC fDCAFEnabled                                                  ;          
endif ;DCAF                                                          ;          

ifdef SEAMLESS

_SEAMDATA2      SEGMENT 'DATA'

ALIGN 4

wHeartbeat      WORD    0       ;VDM Heartbeat

PUBLIC SM_WINDRV

ALIGN 4

SM_WINDRV       _SM_WINDRV <>

ALIGN 4

semDriver       FSRSEM  <,,0,0,0,0,-1,0>

_SEAMDATA2 ENDS

EXTERNDEF SM_PMDISP_ADDRESSES:_SM_PMDISP_ADDRESSES

EXTERNDEF SM_SETSIZE:VMSSIZE

ALIGN 4

NUM_SM_ADDRESSES DWORD   0

fSeamless       BYTE    0       ;Set to true if initialization of seamles windows
                                ;  was successful.
ALIGN 4

hWinVDD         DWORD   0       ;Handle to VWIN.SYS

szWinVDD        BYTE    'VWIN',0

else    ;not seamless

ALIGN 4

semDriver       FSRSEM  <,,0,0,0,0,-1,0>

ENDIF   ;SEAMLESS


DESPERATION_CP  equ     437             ; Used when we can't get the code page

ALIGN 4

_VIOCONFIGINFO          STRUCT 2t
cb                      WORD            ?
adapter                 WORD            ?
display                 WORD            ?
cbMemory                DWORD           ?
Configuration           WORD            ?
VDHVersion              WORD            ?
Flags                   WORD            ?
HWBufferSize            DWORD           ?
FullSaveSize            DWORD           ?
PartSaveSize            DWORD           ?
EMAdaptersOFF           WORD            ?
EMDisplaysOFF           WORD            ?
_VIOCONFIGINFO          ENDS

TVIOCONFIGINFO          TYPEDEF         _VIOCONFIGINFO

PVIOCONFIGINFO          TYPEDEF         PTR TVIOCONFIGINFO

                                        ; defined by DosGetCtryInfo.

_INSTANCEDATA   SEGMENT PARA PUBLIC USE32 'INSTDATA'    ;@NI2
PUBLIC  _hModuleFM                                      ;@NI2
_hModuleFM      DD      0                               ;@NI2
_INSTANCEDATA   ENDS                                    ;@NI2

;/*
;** Global Data
;*/

PUBLIC MoveCursorDescription

ALIGN 4

MoveCursorDescription   MCDESCRIPTION <>
EXTERNDEF               MCDevice:MCDESCRIPTION

abSvgaFlags        BYTE    "SVGAFLAGS="

ALIGN 4

default_vio_cpid   DWORD   0                 ; The meaning of code page zero...
szSVGA             BYTE    "SVGA",0          ; svga kernal device driver name
szSQ               BYTE    "\DEV\SINGLEQ$",0    ;This is PMDD.SYS
szVideoVDD         BYTE    "VVIDEO1$",0

ALIGN 4

flFirstTime        DWORD   1
flInitInProgress   DWORD   1
szResourceFileName BYTE    "DSPRES",0
szDeviceDllName    BYTE    "IBMDEV32",0

szAppName          BYTE    "PM_IBMVGA",0
szCursorKey        BYTE    "CURSOR_SIZE",0

ALIGN 4
flVRAMFirst        DWORD   1

;/*
;** The address of the exit list routine which will be invoked when a
;** process terminates.  This will be passed to DosExitList whenever
;** fill_log_dev_blk is called.  It is defined in this manner instead
;** of synthesizing it on the fly so that the linker will determine
;** the correct segment for it.
;*/

ALIGN 4

pfnExit            DWORD exit_list_proc


ALIGN 4

vioin   TVIOCONFIGINFO <>

ifdef IBMJ                                                              ;IBMJ
szVarHWBitBlt   db      'HARDWAREBITBLT',0
szVarSeamless   db      'SEAMLESSENABLE',0
szVarSprite     db      'SPRITEENABLE',0               ; pochi h/w cursor
szVarFontWidth  db      'MAXVIOFONTWIDTH',0
szOn            db      'ON',0
szOff           db      'OFF',0
endif;IBMJ                                                              ;IBMJ

;/*
;** Local Functions
;*/

get_rip_flag            PROTO SYSCALL

GetVRAMPointer          PROTO SYSCALL


.CODE

;/***************************************************************************
;*
;* FUNCTION NAME = DllLoadProc
;*
;* DESCRIPTION   = Save local heap size to be initialized later, and the module
;*                 handle. This routine is called once, when the module is loaded.
;*                 NOTE - This procedure gets called from and runs at ring 3
;*
;* INPUT         = (ESP+0) return address to the ring 3 dispatcher
;*                 (ESP+4) module handle of this library
;*                 (ESP+8) PDLL group handle, 0 if none
;*                 NOTE That pushing EBP for the stack frame adds 4 to all of these
;*                 values
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 1
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4

DllLoadProc     PROC SYSCALL USES EBX ESI EDI,
                        hMod    :DWORD,         ;module handle of this library
                        ulFlag  :DWORD          ;Flag=0:Init, 1:Terminate

;/*
;**
;** Insure only one thread at a time enters
;** during FIRST TIME EVER initialization
;**
;** DosEnterCritSec applies only to threads in the same
;** process, this must apply to ALL threads so we can't use it.
;**
;*/

        cmp     ulFlag,1
        jne     @F

        DebugMsg2 <IBMVGA32 Process Exiting.>

        INVOKE   exit_list_proc,0

        jmp     load_done

ALIGN 4

@@:

        mov     ecx,0

WaitForIt:

MutexStart:

        xchg    ecx,flInitInProgress    ;=1 means not in progress
        jecxz   WaitForIt               ;=0 means in progress,
                                        ;   so we must wait...
;/*
;** Start critical section
;*/

        mov     ecx,0
        xchg    ecx,flFirstTime         ;First Time EVER?
        or      ecx,ecx
        jz      PerProcInit             ;NO - We will end critsec immediately
                                        ;YES- Proceed into FIRST TIME EVER
                                        ;     critsec code
ifdef FIREWALLS

        Debug32Output PROTO SYSCALL, pszMsg:DWORD

        INVOKE  Debug32Output,ADDR vga32date

endif


;/*
;** copy the dll group handle to the module handle used
;** when getting resources
;*/

        INVOKE  DosLoadModule,
                0,
                0,
                ADDR szResourceFileName,
                ADDR _hModuleFnt

        or      eax,eax
        jz      @F
ifdef FIREWALLS
        DebugMsg2 <DSPRES.DLL Can not be found!! Install it and REBOOT!!! >
        INT 3
endif
        jmp     critsec_error_relay
ALIGN 4

@@:
        INVOKE  DosLoadModule,
                0,
                0,
                ADDR szDeviceDllName,
                ADDR _hModuleDev

        or      eax,eax
        jz      @F
ifdef FIREWALLS
        DebugMsg2 <IBMDEV32.DLL Can not be found!! Install it and REBOOT!!! >
        INT 3
endif
        jmp     critsec_error_relay

ALIGN 4
@@:

        LEA     ESI,MCDevice

        LEA     EDI,MoveCursorDescription
        MOV     ECX,SIZEOF MoveCursorDescription/4
        REP     MOVSD

;/*
;** Create Semaphores here
;*/

;/*
;** set module handle into font loading info table
;*/

        mov     ecx,cResource           ; get number of fonts
        mov     ebx,OFFSET defFontChar

ld_fnt_init:
        mov     eax,_hModuleFnt
        cmp     (FONT_RES PTR [ebx]).fr_usType,RT_OUR_FONT ; is it font or marker?
        je      @F
        mov     eax,_hModuleDev                     ; only fonts come from hModuleFnt
@@:
        mov     (FONT_RES PTR [ebx]).fr_hModule,eax ; save handle in table entry
        add     ebx,SIZEOF FONT_RES                 ; move to next entry
        loopd   ld_fnt_init

        INVOKE  device_specific_init

        or      ecx,ecx
        jnz     @F

ifdef FIREWALLS

        DebugMsg2 <device_specific_init FAILED! >

        INT 3

endif

        jmp     critsec_error_relay

ALIGN 4

@@:

;/*
;** End critical section
;*/

        mov     flInitInProgress,1
        jmp     SemOpened

ALIGN 4

critsec_error_relay:

        mov     flInitInProgress,1
        jmp     per_proc_init_error

ALIGN 4

PerProcInit:

        mov     flInitInProgress,1

;/*
;** PER PROCESS INITIALIZATION!!!
;**
;*/


        INVOKE  DosLoadModule,          ;Must be loaded for each process
                0,
                0,
                ADDR szResourceFileName,
                ADDR _hModuleFnt

        or      eax,eax

        jz      @F
ifdef FIREWALLS
        DebugMsg2 <DSPRES.DLL Can not be found!! Install it and REBOOT !!@ >
        INT 3
endif
        jmp     per_proc_init_error
ALIGN 4
@@:
        INVOKE  DosLoadModule,          ;Must be loaded for each process
                0,
                0,
                ADDR szDeviceDllName,
                ADDR _hModuleDev

        or      eax,eax

        jz      @F
ifdef FIREWALLS
        DebugMsg2 <IBMDEV32.DLL Can not be found!! Install it and REBOOT !!@ >
        INT 3
endif
        jmp     per_proc_init_error
ALIGN 4
@@:
        mov     eax,cs                                                  ;@NI2
        and     eax,1           ;at R3?                                 ;@NI2
        jnz     Case_R3         ;Yes                                    ;@NI2
                                                                        ;@NI2
; Load DBCS font manager (from Ring 2).                                 ;@NI2
                                                                        ;@NI2
ring3_DosLoadModule     PROTO SYSCALL   ; DBCSFONT.ASM                  ;@NI2
EXTERNDEF       szPMNLSFM:BYTE          ; DBCSFONT.ASM                  ;@NI2
                                                                        ;@NI2
        LEA     EDX,szPMNLSFM           ; EDX -> "PMNLSFM"              ;@NI2
        INVOKE  Vga32CallBack,OFFSET ring3_DosLoadModule                ;@NI2
        mov     _hModuleFM,edx          ; Save it into our instance.    ;@NI2
        or      eax,eax                 ; Any error ?                   ;@NI2
        jz      @f                      ; No..                          ;@NI2
        jmp     load_fm_error                                           ;@NI2
                                                                        ;@NI2
Case_R3:                                                                ;@NI2
        LEA     EDX,szPMNLSFM                                           ;@NI2
        INVOKE  ring3_DosLoadModule                                     ;@NI2
        mov     _hModuleFM,edx          ; Into our instance data..      ;@NI2
        or      eax,eax                 ; Error ?                       ;@NI2
        jz      @f                      ; No..                          ;@NI2
load_fm_error:                                                          ;@NI2
ifdef FIREWALLS                                                         ;@NI2
        DebugMsg2 <PMNLSFM.DLL Can not be found!! Install it and REBOOT !!@ >;@NI2
        INT 3                                                           ;@NI2
endif;FIREWALLS                                                         ;@NI2
        jmp     per_proc_init_error                                     ;@NI2
ALIGN 4                                                                 ;@NI2
@@:                                                                     ;@NI2

SemOpened:

;/*
;** The Rest Gets Executed by EVERY PROCESS!!!
;*/

        INVOKE  GetVRAMPointer
        or      eax,eax
        jnz      @F

ifdef FIREWALLS

        DebugMsg2 <GetVRAMPointer FAILED! >

        INT 3

endif

        jmp     per_proc_init_error

ALIGN 4

@@:

        mov     pVRAMInstance,eax
        mov     selDeathToUse,eax

        jmp     load_done

ALIGN 4

per_proc_init_error:

        mov     ebx,eax                 ;Save DOS error code in BX
        mov     eax,PMERR_BASE_ERROR

        save_error_code

        DebugMsg2 <Fatal Error Initializing Display.dll>

        rip     text,<Fatal Error Initializing Display.dll>

        errn$  load_done

load_done:
                mov     eax,1
                ret

DllLoadProc     ENDP

page

;/***************************************************************************
;*
;* FUNCTION NAME = one_time_init
;*
;* DESCRIPTION   = This gets called ONE TIME ONLY!! on the first call to
;*                 fill_log_dev_blk (not once per process)
;*
;*                 All initialization code which cannot be performed at load time
;*                 (which is almost all of it thanks to there being no guarantee
;*                 of load ordering) is performed by this routine.  This routine
;*                 will be called by the Enable function when the first
;*                 FillLogDevBlock call is received.
;*
;*                 one_time_init does:
;*                   1. Get screen pointer into selDeathToUse, and selScreenPtr
;*                   2. Gets the codepage
;*                   ;REMOVED! 3. Inits the heap
;*                   4. Sets up padBitmapFormats, and adDevCapsData
;*                   5. COMMENTED OUT !!! Gets a CS Alias for bitblt to use.
;*                   6. Loads the font resources (sets ddc_ca.ca_fs, and each fr_pp)
;*                   7. Sets up the default pick window.
;*                   8. Tries to setup drqVideo with the VDD (sets fbOffScreen)
;*
;*                   Registers Destroyed:
;*                         AX,BX,CX,DX,ES,DS,FLAGS
;*                   Registers Preserved:
;*                         SI,DI,BP
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL = AX = 0
;* RETURN-ERROR  = AX <> 0
;*                 error has not been logged
;**************************************************************************/

ALIGN 4

one_time_init   PROC SYSCALL USES esi edi ebx

        .errnz  COUNTRYCODE.ctryc_country  - COUNTRYINFO.ctryc_country
        .errnz  COUNTRYCODE.ctryc_codepage - COUNTRYINFO.ctryc_codepage

        LOCAL   hSQ:DWORD
        LOCAL   c_returned:DWORD
        LOCAL   ctrycode:COUNTRYCODE
        LOCAL   ctryinfo:COUNTRYINFO
        LOCAL   aliasdata:ALIASPARM
        LOCAL   alias16:ALIAS16
        LOCAL   ulAction:DWORD
        LOCAL   ulAction1:DWORD
        LOCAL   selTemp:WORD
        LOCAL   SVGAdata:SVGAstruct
        LOCAL   OemHndl:DWORD
ifdef IBMJ                                                              ;IBMJ
        LOCAL   pszResult:DWORD
endif;IBMJ                                                              ;IBMJ

;/*
;** ctryinfo is supposed to be the leading portion of a COUNTRYINFO
;** structure.  We assume that prefix matches the COUNTRYCODE structure.
;** These structures are defined in bsedos.inc
;*/

        mov     ctrycode.ctryc_country,0
        mov     ctrycode.ctryc_codepage,0

        INVOKE  DosQueryCtryInfo,
                        SIZEOF COUNTRYCODE,
                        ADDR ctrycode,
                        ADDR ctryinfo,
                        ADDR c_returned

        mov     eax,ctryinfo.ctryi_codepage
        mov     default_vio_cpid,eax

IFDEF DBCS  ; DBCS codepage / DBCS device font support                  ;IBMJ

; We will initialize display driver for DBCS environment, if all of
; DBCS support modules are available.

        mov     eax,ctryinfo.ctryi_codepage
        mov     edx,ctryinfo.ctryi_country
        INVOKE  DbcsGetRuntimeOptions   ; construct runtime option flags

ENDIF;DBCS                                                              ;IBMJ

ifdef IBMJ                                                              ;IBMJ

ifdef JTUNE                                                             ;IBMJ
        or      swFlags,SW_CT_DISABLE
endif;JTUNE                                                             ;IBMJ
        or      swFlags,SW_SEAMLESS

;/*
;** This is hidden environment value handling ... like
;**       SET SPRITEENABLE=ON                       pochi h/w cursor
;**       SET SEAMLESSENABLE=OFF
;** You can remove this if you do not need this.
;*/
        INVOKE  DosScanEnv, ADDR szVarSeamless, ADDR pszResult
        or      eax,eax
        jnz     @F
        mov     esi,pszResult
        lea     edi,szOff
        mov     ecx,3
        call    szcomp
        jne     @F
        and     swFlags,not SW_SEAMLESS
@@:
        INVOKE  DosScanEnv, ADDR szVarSprite, ADDR pszResult      ; pochi
        or      eax,eax                                           ; 
        jnz     @F                                                ; 
        mov     esi,pszResult                                     ; 
        lea     edi,szOn                                          ;  h/w
        mov     ecx,2                                             ;  cursor
        call    szcomp                                            ; 
        jne     @F                                                ; 
        or      swFlags,SW_SPRITE                                 ; 
@@:                                                               ; 
        mov     ax,DEVCAPS_COLORS
        cmp     ax,256
        jne     @F
        test    adDevCapsData[SIZE_DWORD*CAPS_ADDITIONAL_GRAPHICS],CAPS_PALETTE_MANAGER
        jnz     @F
        and     swFlags,not SW_SEAMLESS
@@:
endif;IBMJ                                                              ;IBMJ

        INVOKE  get_rip_flag

cp_map_available:

        jmp     @F

ALIGN 4

oti_resource_load_error:

        rip     text,<DosGetResource2 returned an error>

        xchg    eax,ebx                 ; error in BX
        mov     eax,PMERR_BASE_ERROR

        jmp     oti_exit

ALIGN 4

@@:

;/*
;** Loop through all the font resources which need to be loaded and
;** load them.
;*/

        cld
        lea     esi,cResource

        lodsd                           ;Get count of resources to load
        xchg    eax,ecx
        or      ecx,ecx
        jz      resources_loaded

        ASSUME  esi:PFONT_RES

resource_load_loop:

;/*
;** DosGetResource loads the resource and returns a pointer
;** to it in fr_pp
;** The fonts are in a struct FOCAFONT
;*/

        INVOKE  DosGetResource2,
                [esi].fr_hModule,
                [esi].fr_usType,
                [esi].fr_usId,
                [esi].fr_pp

        or      eax,eax           ; Error if eax != 0
        jnz     oti_resource_load_error
        add     esi,sizeof FONT_RES
        loopd   resource_load_loop

IFNDEF DBCS                                                            ;IBMJ
        ASSUME  ESI:NOTHING

        lea     esi,cResource

        add     esi,sizeof DWORD
        mov     ebx,[esi].FONT_RES.fr_pp
        mov     edx,ebx                 ;edx is now a FOCAFONT

ELSE; DBCS  ; DBCS device font support                                  ;IBMJ

;/*
;** This is hidden environment value handling ... like
;**       SET MAXVIOFONTWIDTH=10
;** You can remove this if you do not need this.
;*/

        mov     ax,DEVCAPS_COLORS
        cmp     ax,16                           ; not 256 colored SVGA ?
        je      not_consider_user_modify

get_vio_font_width:
        INVOKE  DosScanEnv, ADDR szVarFontWidth, ADDR pszResult
        or      eax,eax
        jnz     not_consider_user_modify
        mov     esi,pszResult
        lodsb
        cmp     al,'9'
        ja      not_consider_user_modify
        sub     al,'0'
        jc      not_consider_user_modify
        mov     ah,al
        lodsb
        or      al,al
        jz      @F
        cmp     al,'9'
        ja      not_consider_user_modify
        sub     al,'0'
        jc      not_consider_user_modify
        xchg    al,ah
        shl     al,1
        add     ah,al
        shl     al,2
        add     ah,al
        lodsb
        or      al,al
        jnz     not_consider_user_modify
@@:
        cmp     ah,6
        jb      not_consider_user_modify
        cmp     ah,13
        ja      not_consider_user_modify
        movzx   eax,ah
        mov     DeviceFontWidth,eax
not_consider_user_modify:

; Replace SBCS device fonts by DBCS device fonts, if our environment is
; enough to display DBCS characters.

        INVOKE  DbcsModifySystemFonts   ; EDX --> default fontseg address
ENDIF;DBCS                                                              ;IBMJ
        lea     ebx,ddcInit             ; This is pddcInit


;/*
;** Now reach into the font and pull out lots of good information so we
;** can set a bunch of different CA_ flags.
;*/

        mov     eax,0

        .IF([edx].FOCAFONT.ff_fmMetrics.foca_fsTypeFlags & FM_TYPE_64K)

        jmp     oti_resource_load_error

ALIGN 4

        .ENDIF

        mov     ecx,CA_VECTOR

;/*
;** test for raster instead of vector
;*/

        .IF(!([edx].FOCAFONT.ff_fmMetrics.foca_fsDefn & FM_DEFN_OUTLINE))

        and     ecx,not CA_VECTOR       ;It is raster

        .ENDIF

        .IF([edx].FOCAFONT.ff_fdDefinitions.fdh_xCellWidth == 8)

        or      ecx,CA_WIDTH_IS_8

        .ENDIF

        .IF([edx].FOCAFONT.ff_fmMetrics.foca_fsTypeFlags & FM_FIXED_PITCH)

        or      ecx,CA_FIXED_PITCH

        .ENDIF

        .IF([edx].FOCAFONT.ff_fdDefinitions.fdh_fsChardef == FONTDEFCHAR3)

        or      ecx,CA_ABC_SPACE

        .ENDIF

;/*
;** compute_pick
;*/

        mov     (DDC PTR [ebx]).ddc_ca.ca_fs,ecx        ; save flags

;/*
;** Set up the default pick window.
;** cW = ((cH * HorzRes) + VertRes/2) / VertRes
;*/

        mov     eax,DEVCAPS_HORIZONTAL_RESOLUTION
        mov     edx,adDevCapsData[CAPS_GRAPHICS_CHAR_HEIGHT*SIZE_DWORD]

        mul     edx

;/*
;** result in edx:eax
;*/

        mov     ecx,DEVCAPS_VERTICAL_RESOLUTION
        shr     ecx,1
        add     eax,ecx
        adc     edx,0
        mov     ecx,DEVCAPS_VERTICAL_RESOLUTION
        div     ecx

;/*
;** Q eax,R edx = edx:eax / ecx
;*/

        shr     eax,1                   ; width /2
        mov     ebx,OFFSET rddcInit

        ASSUME  ebx:PRDDC

        mov     [ebx].rddc_rclPick.rcl_xRight,eax
        neg     eax
        mov     [ebx].rddc_rclPick.rcl_xLeft,eax

        mov     eax,adDevCapsData[CAPS_GRAPHICS_CHAR_HEIGHT*SIZE_DWORD]

        shr     eax,1                   ; width /2
        mov     [ebx].rddc_rclPick.rcl_yTop,eax
        neg     eax
        mov     [ebx].rddc_rclPick.rcl_yBottom,eax

        lea     esi,ddcInit             ; This is pddcInit

        INVOKE  alloc_brush
        mov     [esi].DDC.ddc_pa.pa_abColor,eax

resources_loaded:

        ASSUME  ebx:NOTHING
        ASSUME  esi:NOTHING


        INVOKE  Vga32CallBack,
                OFFSET ring3_VioGetConfig


        mov     wAdapter,bx
        mov     wDisplay,cx
        mov     lnbTotalScreenSize,eax

;/*
;** find out machine model and sub-model types.
;*/

        INVOKE  DosDevConfig,
                ADDR bModel,
                DEVINFO_MODEL

        INVOKE  DosDevConfig,
                ADDR bSubModel,
                DEVINFO_SUBMODEL

;/*
;** Find out if this flat-panel (plasma/lcd) display is color?
;*/

        mov     ah,bModel                ; get machine model/submodel
        mov     al,bSubModel             ; into AX
        cmp     ax,MACHINE_NECTARINE     ; Is it Nectarine
        je      @F                       ;          
        cmp     ax,MACHINE_NECTARINEPR   ;           is it Nectarine Prime
        jne     got_display              ;          

@@:                                      ;          
                                         ; It is a nectarine. But is it color?
        mov     al,080h                  ; index for chip ID
        mov     dx,0D00h                 ; write it to index register
        out     dx,al
        mov     dx,0D01h                 ; read from data register
        in      al,dx
        cmp     al,02h                   ; 02 indicates Airway, which is
                                         ; the chip/display used by Nectarine-color
        jne     got_display
        mov     wDisplay,DISPLAY_COLOR_LCD
got_display:

;/*
;** load cursor info from OS2.INI
;*/

        INVOKE  PrfQueryProfileInt,
                HINI_PROFILE,
                ADDR szAppName,
                ADDR szCursorKey,
                0
        mov     lCursorSize,eax         ; 


        INVOKE  DosOpen,
                ADDR OemHelp,      ;lpDevice -> device name string
                ADDR OemHndl,      ;pass -> handle return value
                ADDR ulAction1,     ;dAction return value
                0,                 ;filesize (zero)
                0,                 ;file attribute (zero)
                1,                 ;open flag (open existing file)
                0000000011000010b, ;open mode
                0                  ;reserved

        INVOKE  DosDevIOCtl,
                OemHndl,
                80h,
                08h,
                0,
                0,
                0,
                ADDR SVGAdata,
                SIZEOF SVGAdata,
                0
        mov     ax,SVGAdata.SVGAadaptertype
        mov     wSVGAtype,ax

        INVOKE  DosClose,
                OemHndl

ifdef  JTUNE                                                            ;IBMJ
        mov     ax,DEVCAPS_COLORS
        cmp     ax,16                   ; VGA mode ?
        je      @F
        cmp     wSVGAtype,5             ; ATI ?
        jne     @F
        or      swFlags,SW_HAVE_ACCEL   ; force h/w BitBlt on
@@:

;/*
;** This is hidden environment value handling ... like
;**       SET HARDWAREBITBLT=ON
;** You can remove this if you do not need this.
;*/
        INVOKE  DosScanEnv, ADDR szVarHWBitBlt, ADDR pszResult
        or      eax,eax
        jnz     HWBitBltNotFound
        mov     esi,pszResult
        lea     edi,szOn
        mov     ecx,2
        call    szcomp
        jne     @F
        or      swFlags,SW_HAVE_ACCEL
@@:
        mov     esi,pszResult
        lea     edi,szOff
        mov     ecx,3
        call    szcomp
        jne     @F
        and     swFlags,not SW_HAVE_ACCEL
@@:
HWBitBltNotFound:
endif ;JTUNE                                                            ;IBMJ

        mov     ax,DEVCAPS_COLORS       ;           If we are not 16 color
        cmp     ax,16                   ;           don't register with
        ja      skip_vvideo             ;           Virtual Video
not_skip_vvideo:                                                        ;IBMJ

        INVOKE  DosOpenVDD,
                ADDR szVideoVDD,
                ADDR hVideoVDD

        or      eax,eax  ; if(Video VDD is loaded)
        jnz     no_vdd   ; No
                         ; Yes

skip_vvideo:                            ;          

        INVOKE  DosOpen,
                ADDR szSQ,         ;lpDevice -> device name string
                ADDR hSQ,          ;pass -> handle return value
                ADDR ulAction,     ;dAction return value
                0,                 ;filesize (zero)
                0,                 ;file attribute (zero)
                1,                 ;open flag (open existing file)
                0000000011000000b, ;open mode
                0                  ;reserved

;/*
;** if error on DosOpen, can't use VDD
;*/

        or      eax,eax
        jnz     no_vdd  ;error

IOCTL_SCR_AND_PTRDRAW   EQU             000000003h
SCR_DEALLOCLDT          EQU             000000071h

ifdef   SEAMLESS

        INVOKE  DeviceSeamlessInit,
                ADDR aliasdata

;/*
;** returns pointer to share record for semDriver
;*/

        MOV     [EAX]._SM_PMDISP_ADDRESSES.pStart,OFFSET semDriver

;/*
;** and NUM_SM_ADDRESSES in EDX
;*/

        mov     NUM_SM_ADDRESSES,EDX



        mov     alias16.ap_len,sizeof ALIAS16
        mov     ax,aliasdata.dsel
        mov     alias16.ap_ds,ax

        INVOKE  DosDevIOCtl,
                hSQ,
                03h,
                71h,
                ADDR alias16,
                SIZEOF ALIAS16,
                0,
                ADDR alias16,
                SIZEOF ALIAS16,
                0

        or      eax,eax
        jnz     alias_error             ;if error on DosDevIOCTL, can't use VDD

        DebugMsg2       <drqVideo Ring0 alias OK. >

        mov     ax,alias16.ap_ds       ;get ring 0 alias

;/*
;** Move ax into the selector portion of the dword 16:16 pointers
;*/

        mov     WORD PTR drqVideo.pfbShadowFlags[2],ax
        mov     WORD PTR drqVideo.pfControllerOwned[2],ax
        mov     WORD PTR drqVideo.pfControllerNotify[2],ax
        mov     WORD PTR drqVideo.pShadowData[2],ax
        mov     ax,DEVCAPS_COLORS       ;           If we are not 16 color
        cmp     ax,16                   ;           don't register with
        ja      @f                      ;           Virtual Video
vdd_for_atlas:                                                          ;IBMJ
        or      fbOffScreen,OFFSCR_VDD  ;we can use the VDD now


        jmp     @f

ALIGN 4

alias_error:

        DebugMsg2       <drqVideo Ring0 alias Failed! >

        jmp     no_vdd_close

ALIGN 4

@@:

        LEA     EAX,semDriver
        MOV     SM_WINDRV.hwsemOff,AX
        LEA     EAX,wHeartbeat
        MOV     SM_WINDRV.wHeartbeatOff,AX

        INVOKE  DosOpenVDD,
                ADDR szWinVDD,
                ADDR hWinVDD

        or      eax,eax                   ;was Win VDD loaded?
        jz      sm_found_vwin           ;yes

        IFDEF   FIREWALLS

        DebugMsg2 <PMVGA: Could not open VWIN.>

        ENDIF   ;FIREWALLS

        jmp     seamless_exit           ;Can't find VWIN

ALIGN 4

sm_found_vwin:

IFDEF   FIREWALLS

        DebugMsg2 <PMVGA: Opened VWIN successfully.>

ENDIF   ;FIREWALLS

        INVOKE  DosRequestVDD,
                hWinVDD,                        ;hvdd
                0,
                VWIN_INIT,
                NUM_SM_ADDRESSES,               ;cbInput
                ADDR SM_PMDISP_ADDRESSES,       ;pInput
                0,                              ;cbOutput
                0                               ;pOutput

        or      eax,eax                         ;was call to Win VDD successfull?
        jz      seamless_ok                     ;yes

seamless_error:

IFDEF   FIREWALLS

        DebugMsg2 <PMVGA: Send address to VWIN failed.>

ENDIF   ;FIREWALLS

        INVOKE  DosCloseVDD,
                ADDR hWinVDD

        jmp     seamless_exit

ALIGN 4

seamless_ok:
ifdef  IBMJ                                                             ;IBMJ
        test    swFlags,SW_SEAMLESS
        jnz     do_not_cut_seamless
        mov     ax,DEVCAPS_COLORS
        cmp     ax,16                           ;color > 16 (net VGA mode) ?
        ja      seamless_exit                   ;This patch only for RIKER-I

do_not_cut_seamless:
endif ;IBMJ                                                             ;IBMJ

        INVOKE  DosRequestVDD,
                hWinVDD,                        ;hvdd
                0,
                VWIN_SETSIZE,
                sizeof VMSSIZE,                 ;cbInput
                ADDR SM_SETSIZE,                ;pInput
                0,                              ;cbOutput
                0                               ;pOutput

        or      eax,eax                 ;was call to Win VDD successfull?
        jnz     seamless_error          ;no

        or      fSeamless,SEAMLESS_ACTIVE       ;Make seamless active
        mov     semDriver.fsrs_Timeout,DWORD PTR SEAMLESS_TIMEOUT

IFDEF   FIREWALLS

        DebugMsg2 <PMVGA: Sent address to VWIN successfully.>

ENDIF   ;FIREWALLS

seamless_exit:

ENDIF   ;SEAMLESS

no_vdd_close:

        INVOKE  DosClose, hSQ

no_vdd:

ifdef  JTUNE                                                            ;IBMJ
        public  identify_cpu
identify_cpu::

        or      swFlags,SW_CPU_386      ; default CPU
        mov     ax,cs
        test    ax,1
        jnz     @F                      ; quit if ring 3

        cli
        pushfd                          ; save current flags
        mov     ebx,esp                 ; save current stack pointer
        and     esp,0fffffffch          ; adjust stack pointer to dword boundly

        pushfd
        pop     eax                     ; eax <- flags
        or      eax,40000h              ; bit18 = 1 (alignment check on)
        push    eax
        popfd                           ; eax -> flags
        pushfd
        pop     eax                     ; eax <- flags

        mov     esp,ebx                 ; restore stack pointer
        popfd
        sti

        test    eax,40000h              ; bit18 works ?
        jz      @F                      ; no, it's 386
        mov     eax,04030201h
        .486
        bswap   eax
        .386
        cmp     eax,01020304h
        jne     @F

        and     swFlags,not SW_CPU_386  ; it's not 386 (486 or higher)
@@:
endif ;JTUNE                                                            ;IBMJ

        INVOKE  device_specific_post_init

ifdef DCAF                                                           ;          
;/*                                                                  ;          
;** Try to find the exported DCAF functions in the IBMDEV32 module.  ;          
;**                                                                  ;          
;** If any of these calls fail then DCAF will not be supported.      ;          
;*/                                                                  ;          
                                                                     ;          
;/*                                                                  ;          
;** Save the current return value                                    ;          
;*/                                                                  ;          
        push    eax                                                  ;          
                                                                     ;          
;/*                                                                  ;          
;** Look for GetScreenBits.                                          ;          
;*/                                                                  ;          
        INVOKE  DosQueryProcAddr,                                    ;          
                _hModuleDev,                                         ;          
                ORD_GETSCREENBITS,                                   ;          
                0,                                                   ;          
                ADDR pfnGetScreenBits                                ;          
                                                                     ;          
        cmp     pfnGetScreenBits, 0                                  ;          
        je      dcaf_not_supported                                   ;          
                                                                     ;          
;/*                                                                  ;          
;** Look for SetScreenBits.                                          ;          
;*/                                                                  ;          
        INVOKE  DosQueryProcAddr,                                    ;          
                _hModuleDev,                                         ;          
                ORD_SETSCREENBITS,                                   ;          
                0,                                                   ;          
                ADDR pfnSetScreenBits                                ;          
                                                                     ;          
        cmp     pfnSetScreenBits, 0                                  ;          
        je      dcaf_not_supported                                   ;          
                                                                     ;          
;/*                                                                  ;          
;** Look for UnPackBuffer.                                           ;          
;*/                                                                  ;          
        INVOKE  DosQueryProcAddr,                                    ;          
                _hModuleDev,                                         ;          
                ORD_UNPACKBUFFER,                                    ;          
                0,                                                   ;          
                ADDR pfnUnPackBuffer                                 ;          
                                                                     ;          
        cmp     pfnUnPackBuffer, 0                                   ;          
        je      dcaf_not_supported                                   ;          
                                                                     ;          
;/*                                                                  ;          
;** We have successfully loaded all of the DCAF entry points.        ;          
;** Set the flag to indicate that DCAF is enabled.                   ;          
;*/                                                                  ;          
        mov     fDCAFEnabled, TRUE                                   ;          
                                                                     ;          
dcaf_not_supported:                                                  ;          
;/*                                                                  ;          
;** Restore the return value                                         ;          
;*/                                                                  ;          
        pop     eax                                                  ;          
                                                                     ;          
endif ;DCAF                                                          ;          

oti_exit:
                ret

one_time_init   ENDP

page
;/***************************************************************************
;*
;* FUNCTION NAME = get_rip_flag
;*
;* DESCRIPTION   = The environment is searched for a SVGAFLAGS entry.  If it is
;*                 set to "R", then the rip flag will be passed to WinSetErrorInfo.
;*                 This feature will be in both the FIREWALLed and non FIREWALLed
;*                 version of the driver.
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
get_rip_flag    PROC SYSCALL USES EDI ESI EBX
        LOCAL   myppib            :DWORD,
                myptib            :DWORD

        INVOKE  DosGetInfoBlocks,
                ADDR myptib,
                ADDR myppib

        or      eax,eax
        jnz     have_rip_flag           ;Probably no environment present yet

        mov     ebx, myppib
        mov     edi,[ebx].pib_s.pib_pchenv   ;DI -->environemnt
        cld

match_next_string:

        mov     esi,OFFSET abSvgaFlags
        mov     ecx,SIZEOF abSvgaFlags
        repe    cmps byte ptr [esi],byte ptr [edi]
                                        ; zero flag set if match
        jne     goto_next_string        ; zf not set if no match

;/*
;** We want to make the test of the flags are a word test to make sure that
;** we match only on the flag value, not a somehting like "RI".
;*/

        cmp     [edi],SVGAFLAGS_RIP
        je      set_rip_flag
        cmp     [edi],SVGAFLAGS_RIP_LC
        jne     have_rip_flag

set_rip_flag:

        mov     fbRip,DDF_RIP_ERROR     ;Non-zero to show rip
        jmp     have_rip_flag

ALIGN 4

goto_next_string:

        cmp     byte ptr [edi-1],0      ;Have we found a null char?
        jz      done_this_string        ;  Yes
        mov     ecx,0FFFFh
        repne   scasb                   ;Find first null

done_this_string:

        cmp     byte ptr [edi],0        ;End of environment strings?
        jne     match_next_string       ;  No, search next

have_rip_flag:

        ret

get_rip_flag ENDP

ALIGN 4

;/***************************************************************************
;*
;* FUNCTION NAME = ring3_VioGetConfig
;*
;* DESCRIPTION   = Calls Vio32GetConfig at ring 3.
;*
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ring3_VioGetConfig    PROC SYSCALL

        mov     vioin.cb,sizeof TVIOCONFIGINFO

        INVOKE  Vio32GetConfig,
                0,
                ADDR vioin,
                0

        mov     bx,vioin.adapter
        mov     cx,vioin.display
        mov     eax,vioin.cbMemory
        ret

ring3_VioGetConfig ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = GetVRAMPointer
;*
;* DESCRIPTION   = Uses an Ioctl to get a pointer to VRAM.
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/
ALIGN 4

GetVRAMPointer PROC SYSCALL USES EDI
        LOCAL   hSVGA:DWORD
        LOCAL   ulAction:DWORD
        LOCAL   scrnTx:SCRNTX
        LOCAL   scrnRx:SCRNRX
        LOCAL   fAttach:BYTE

        INVOKE  DosOpen,
                ADDR szSQ,         ;lpDevice -> device name string
                ADDR hSVGA,        ;pass -> handle return value
                ADDR ulAction,     ;dAction return value
                0,                 ;filesize (zero)
                0,                 ;file attribute (zero)
                1,                 ;open flag (open existing file)
                0000000011000000b, ;open mode
                0                  ;reserved
        or      eax,eax
        jnz     getvram_error

        mov     eax,gsspScreen.pPhysMem
        mov     scrnTx.stx_Address,eax
        mov     eax,gsspScreen.cb

        mov     scrnTx.stx_Size,eax
        mov     scrnTx.stx_flFlag,0

        mov     ecx,0
        mov     fAttach,0
        xchg    ecx,flVRAMFirst
        mov     ebx,07eh        ;assume first time: allocate
        or      ecx,ecx
        jnz     gvp_allocate    ;first time so allocate
        mov     ebx,07fh        ;Not first time so attach
        mov     eax,pVRAMInstance
        mov     scrnTx.stx_Address,eax
        mov     fAttach,1

gvp_allocate:

        INVOKE  DosDevIOCtl,
                hSVGA,                  ;hDevice
                03h,                    ; ulCat
                ebx,                    ; ulFunction
                ADDR scrnTx,            ; pParmList
                SIZEOF scrnTx,          ; cbParmList
                0,                      ; plReserved
                ADDR scrnRx,            ; pData
                SIZEOF scrnRx,          ; cbData
                0                       ; plReserved

        mov     ebx,eax ;save return code
        INVOKE  DosClose, hSVGA

        mov     eax,scrnRx.srx_ScrnPtr
        cmp     fAttach,1
        jne     @F
        mov     eax,pVRAMInstance

@@:

;/*
;** check return from dosdevioctl call
;*/

        or      ebx,ebx
        jz      getvram_exit

getvram_error:

        mov     eax,0   ;error return

getvram_exit:

        ret

GetVRAMPointer ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = GetVRAMR0Pointer
;*
;* DESCRIPTION   = Uses an Ioctl to get a pointer to VRAM.
;*
;* INPUT         =
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/
ALIGN 4

GetVRAMR0Pointer PROC SYSCALL USES EDI
        LOCAL   hSVGA:DWORD
        LOCAL   ulAction:DWORD
        LOCAL   scrnTx:SCRNTX
        LOCAL   scrnRx:SCRNRX
        LOCAL   fAttach:BYTE

        INVOKE  DosOpen,
                ADDR szSQ,       ;lpDevice -> device name string
                ADDR hSVGA,        ;pass -> handle return value
                ADDR ulAction,     ;dAction return value
                0,                 ;filesize (zero)
                0,                 ;file attribute (zero)
                1,                 ;open flag (open existing file)
                0000000011000000b, ;open mode
                0                  ;reserved
        or      eax,eax
        jnz     getvram_error

        mov     eax,gsspScreen.pPhysMem
        mov     scrnTx.stx_Address,eax
        mov     eax,gsspScreen.cb

        mov     scrnTx.stx_Size,eax
        mov     scrnTx.stx_flFlag,1

        INVOKE  DosDevIOCtl,
                hSVGA,                  ;hDevice
                03h,                    ; ulCat
                7eh,                    ; ulFunction
                ADDR scrnTx,            ; pParmList
                SIZEOF scrnTx,          ; cbParmList
                0,                      ; plReserved
                ADDR scrnRx,            ; pData
                SIZEOF scrnRx,          ; cbData
                0                       ; plReserved

        mov     ebx,eax ;save return code

        INVOKE  DosClose, hSVGA

        mov     eax,scrnRx.srx_ScrnPtr

@@:

;/*
;** check return from dosdevioctl call
;*/

        or      ebx,ebx
        jz      getvram_exit

getvram_error:

        mov     eax,0   ;error return

getvram_exit:

        ret

GetVRAMR0Pointer ENDP

        END     DllLoadProc
