PAGE    ,132
TITLE   VDMMA - VDM Manager Assembly Interfaces
NAME    VDMMA
SCCSID  equ     "@(#)vdmma.asm  6.29 92/03/13"
;***    VDMMA.ASM
;
;       IBM Confidential
;
;       Copyright (c) IBM Corporation 1987, 1989, 1992
;
;       All Rights Reserved
;
;       Version 1.18.2.6, for src/dos/mvdm/vdmma.asm, vdmm, mer.krnl, currbld
;
;       Title:
;
;       VDM manager assembly interfaces
;
;       Description:
;
;       Contains the assembly routines and interfaces for VDM
;       manager.
;
;       Created     Sudeep Bharati
;
;       Public routines:
;
;       MVDMINIT
;       vdmmEnterCreateVDM
;       vdmmExitCreateVDM
;       vdmmStart
;       vdmmInitGDT_PTDA
;
;       Revisions:
;
;   - 001   2/22/91     Mark Rogalski,   IBM
;     CP20 DCR 1329  Add DOS=UMB support
;
;   - 002   5/06/91     Mark Rogalski,   IBM
;     CP20 DCR 1360  Add DOS=HIGH support
;
;***********************************************************************;BN011;
; 19Jun91 - G.L.Fulk                                                    ;BN011;
; Add support for a DOS ONLY "FILES=" statement in CONFIG.SYS.          ;BN011;
;***********************************************************************;BN011;
; 6.11  08/17/91  Jeff Muir  CP20 B725703   Added PIC mask original value
;       01/09/92  MarkF                     Added Seamless Windows support
;       01/30/92  Frank Schroeder CP20 AZ09655 Added extended error support
;       07/27/92  Frank Schroeder            Added VDHFSCtl support
; 1.2   10/30/92  Family 1 POS support
;       10/20/93  ChangeTeam      73541     Added em86Is32Sel
;       12/15/93  RAC 76699 Make Perfview Optional with flag PERFVIEW
; WIN32 06/16/94  Liren Ji defect 86296     Add VDHInstallFaultHandler
;       06/24/94  r207 86481   TPL          Added VDHWaitRamSem for VWIN
; WIN32 06/27/94  Joe Luu  defect 87734     Add VDHViewHandle
;
;     12 AUG 1994 ChangeTeam      93273     Added VDDGenEntryTbl VDHGetFlags
;       09/19/94  bjn       Changed segment names for page tuning.
;       11/21/94  ChangeTeam  defect 104925  rolled defects 73080 in r207
;                       defect 73080 Added VDHVMDETACH
;       03/01/96  GCM                       Removed Unloading of VDD for
;       04/11/96  @V3.2SEN00     151783     Added int10 support.
;                                           debugger traces.
;       07/19/96  Gil Pratte - defect 141181
;                 Added the new table entries for the new VDH services
;                 needed to run WIN32S 1.25a applications
;--------------------------------------------------------------------------

INCL_NONE       equ     1                       ; don't include everything
INCL_TYPES      equ     1                       ; include basic types
INCL_DEF        equ     1                       ; include typedef macros
INCL_VDHALL     equ     1                       ; include VDH services

.xlist
        include dosseg.inc
        include fnomvdm.inc
        include osmaca.inc
        include osconst.inc
        include error.inc
        include mi.inc
        include protmode.inc
        include vmowner.inc
        include dossymc.inc
        include sigdef.inc
        include except.inc
        include seldesc.inc
        include pgexport.inc
        include vmexport.inc
        include selxport.inc
        include infoseg.inc
        include tkexport.inc
        include dirent.inc
        include curdir.inc
        include find.inc
        include screen.inc
        include sft.inc
        include sem.inc
        include tkptda.inc
        include kmode.inc
        include sysentry.inc
        include ordmvdm.inc
        include sicg.inc
        include inicfg.inc
        include mvdm.inc
        include semxport.inc
        include propp.inc
        include sas.inc
        include config.inc
        include dosseg.inc                                               ;BN001;
        include basemaca.inc                                             ;BN001;
        include fnoinit.inc                                              ;BN001;
        include struc.inc                                                ;BN001;
        include fisam.inc                                                ;BN001;
        include ldrvars.inc                                              ;BN001;
        include demsvc.inc                                               ;@xxxx
        include mvdmexp.inc                                              ;@xxxx
        include virtsym.inc                                              ;@xxxx
.list

        ModName  , FNO_VDMMA_ASM
        CpuMode 386

        ReferGlobal     NumIO,BYTE      ; Number of physical drives
        ReferGlobal     NumIORipl,BYTE  ; # of reserved drives for RIPL
        ReferGlobal     SISData,BYTE            ;@PAA04757A - for SIS_BootDrv
        ReferGlobal     uchLastDrive,BYTE
        ReferGlobal     _ulPICMask,DWORD      ; 6.11 Pic Mask at boot time
        ReferFlat       _ulPICMaskState,DWORD ; 6.11 PIC Mask used for sysvalue
        ReferGlobal     ABIOS_present,BYTE
        ReferInitGlobal ABIOSSelTable,WORD
        ReferInitGlobal ABIOSSelTableEnd,BYTE

        ReferGDT        GDT_PTDA,WORD
        EXTRN16         SuBuff
        EXTRN16         SemRequest
        EXTRN16         SemClear
        EXTRN16         SemSet
        EXTRN16         SemWait
        EXTRN16         SemRequest
        EXTRN16         FindChar
        EXTRN16         FindPathEnd
        EXTRN16         SegAlloc2                               ;@xxxx
        EXTRN16         VirtToPhys                              ;@xxxx
IFDEF   PMDEBUG
        EXTRN16         DebugRemoveSymMTE:NEAR
ENDIF


;        EXTRN32         _SCHSetState
        EXTRN32         _TKUpdateState
        EXTRN32         _SCHSetPriority
        EXTRNF32        SELSegFree                                       ;@xxxx
        ReferFlat       _lidtV86IDT,FWORD

if RAS
        ReferFlat       _RASselSTDA,WORD
endif ;RAS

DefCode IMPORT, SWAP
DefFn   demMapVirt
EndCode


DefCode IMPORT, GLOBAL, PASCAL
DefFn   VDMMInit
DefFn   vdmmCreateVDM
DefFn   VDHAssertVDMTaskOnly
DefFn   vdmmUpperCase
EndCode

DefCode IMPORT, GLOBAL, C
DefFn   VMAllocKHB
DefFn   SELVirtToLin
DefFn   TKDieSoonPTDA
EndCode

DefCode EXPORT, GLOBAL, PASCAL
DefFn   vdmmEnterCreateVDM
DefFn   vdmmExitCreateVDM
DefFn   vdmmEnterTerminateVDM
DefFn   vdmmExitTerminateVDM
DefFn   vdmmInitGDT_PTDA
DefFn   vdmmRemoveSymMTE
DefFn   vdmmSem
DefFn   vdmmSetState
DefFn   vdmmAdjustError
DefFn   vdmmGetFileFromPath
DefFn   vdmmGetMachineInfo
DefFn   vdmmGetPlanarPOS
DefFn   vdmmGetVideoPOS                      ; 6.8
DefFn   vdmmGetSlotPOS
DefFn   vdmmGetPort90
DefFn   vdmmGetPort92
EndCode

DefCode EXPORT, GLOBAL, C
DefFn   vdmmStart
DefFn   vdmmInt13SVCCode                     ;@xxxx
EndCode

DefData IMPORT, GLOBAL, C
ULONG   cbKrnlInstance
ULONG   pPTDACur
PVOID   pTCBCur
PVOID   vdmid_mphvdmptcb
EndData


DATA segment

        public          mutexCreateVDM, eventCreateVDM
mutexCreateVDM          dd      0       ; sem to allow only one VDM creation
eventCreateVDM          dd      0       ; VDM creation is done event semaphore
retCreateVDM            dd      0       ; return code from VDM creation

DATA ends

INITBSS segment
        public          pszzBaseVDDs
ALIGN 4
PSZZ    pszzBaseVDDs,0
INITBSS ends

DefData PRIVATE, GLOBAL
ALIGN 4
VDMCONFIG vdmconfigGlobal
ALIGN 4
VDMINITCONFIG vdminitconfigGlobal
ALIGN 4
PSZZ      pszzOtherVDDs,0
EndData

DefData EXPORT, GLOBAL, C
SEL     selGDT_PTDA
EndData

ThunkFar32 VDMMINITTIMER,,CINIT_TEXT
ThunkFar32 VDMMGETPOSREGS,,CINIT_TEXT

        FARCODE HIGH32
DefCode PRIVATE, INIT, PASCAL

;***    MVDMINIT - initialize mvdm
;
;       ENTRY   (DS:SI) = pointer to struc sicg_pktA (see sicg.inc)
;
;       EXIT    (EAX) = 0, 3xBox started successfully
;               (EAX) = !0, couldn't start 3xBox
;                      (EAX) = error code
;
;       USES    EAX, EBX, ECX, EDX, EDI, ESI, DS, ES, FS, GS, Flags
;
;       NOTE    Only DOS DD strings are being converted to upper case
;               because of DOS compatibility reason.
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure MVDMINIT,far32
        movzx   ebx,si
        mov     eax,ds
        mov     fs,eax                  ; (FS:EBX) = sicg_pktA pointer
        FlatContext <ds,es>,ax
        mov     ax,fs:[ebx].siA_rmsize
        mov     [vdmconfigGlobal].usRMSIZE,ax
        mov     ax,fs:[ebx].siA_fcbcnt
        mov     [vdmconfigGlobal].nFCBs,ax
        mov     ax,fs:[ebx].siA_fcbkeep
        mov     [vdmconfigGlobal].nFCBsNoClose,ax
        mov     ax,fs:[ebx].siA_filescount                              ;BN011;
        mov     [vdmconfigGlobal].nFILES,ax                             ;BN011;
        movzx   ax,fs:[ebx].siA_break
        mov     [vdmconfigGlobal].iBREAK,ax
        movzx   ax,fs:[ebx].siA_Dos_Flags                          ;BN002
        mov     [vdmconfigGlobal].Dos_Flags,ax                     ;BN002
        mov     [vdmconfigGlobal].pszSHELL,0
        mov     [vdmconfigGlobal].pszzDOSDDs,0

;       Store Away the LastDrive parameter after all checks.
;       Remember config.sys value is passed 0 based that is A=0;B=1...

; These drives are not necessarily consecutive.
;@PAA04757A Begins
        cmp     [NumIORipl], 0
        je      mvi_as_before

        mov     ax, [SISData].SIS_BootDrv ; If Ripl, this is our boot drive
        mov     ah, [NumIO]               ; al:RiplBootDrv, ah:NumIO

        cmp     ah, al
        jg      mvi_as_before            ; This means the boot drive is in
                                         ; amidst the real, local hard drives

                                         ; Else, add up the number of total
                                         ; Ripl drives.  The sum is the lastdrv.

        add       al, [NumIORipl]        ; Add number of Ripl drives
        dec       al                     ; Gives the last Ripl drive number
        jmp short mvi_Ripl

mvi_as_before:


        mov     al,[NumIO]              ; al = # of logical drives in system
        add     al,[NumIORipl]          ; al = total needed drives

mvi_Ripl:
;@PAA04757A Ends
        dec     al                      ; al = 0 based total drives
        cmp     al,fs:[ebx].siA_lastdrive
        jg      short mvi5              ; jmp if config.sys value is low
        mov     al,fs:[ebx].siA_lastdrive
mvi5:
        mov     [uchLastDrive],al       ; store LastDrive value

;       copy the mask to local sysvalue area
;
        mov     eax,[_ulPICMask]                     ; 6.11  Copy from 16:16
        mov     [_ulPICMaskState],eax                ; 6.11  to 0:32 area


;       Now copy the communication-information structure

        mov     eax,fs:[ebx].siA_cb
        mov     [vdminitconfigGlobal].ulcbFailureBuf,eax

        mov     eax,fs:[ebx].siA_pbuf
        mov     [vdminitconfigGlobal].pFailureBuf,eax

        mov     eax,fs:[ebx].siA_pusEC
        mov     [vdminitconfigGlobal].pusErrorCode,eax

        mov     eax,fs:[ebx].siA_hsemMBE
        mov     [vdminitconfigGlobal].hsemBufEmpty,eax

        mov     eax,fs:[ebx].siA_hsemEHB
        mov     [vdminitconfigGlobal].hsemErrHBusy,eax

        cmp     fs:[ebx].siA_Shell.Offst,0
        je      short mvi10
        lgs     si,fs:[ebx].siA_Shell
        mov     edi,offset FLAT:vdmconfigGlobal.pszSHELL
        call    vdmmBuildPSZZ

mvi10:  cmp     fs:[ebx].siA_RMDevice.Offst,0
        je      short mvi20
        lgs     si,fs:[ebx].siA_RMDevice
        mov     edi,offset FLAT:vdmconfigGlobal.pszzDOSDDs
        call    vdmmBuildPSZZ
        mov     edi,[vdmconfigGlobal].pszzDOSDDs
        PCall   vdmmUpperCase <edi>     ; Convert to upper case PTR B785758

mvi20:  cmp     fs:[ebx].siA_VDDDevice.Offst,0
        je      short mvi30
        lgs     si,fs:[ebx].siA_VDDDevice
        mov     edi,offset FLAT:pszzOtherVDDs
        call    vdmmBuildPSZZ

mvi30:  DosInitContext gs
        movzx   eax,[pszzBaseVDDs].Offst
        movzx   ebx,[pszzBaseVDDs].Segmt
        CCALL32 SELVirtToLin, <eax, ebx>
        mov     pszzBaseVDDs,eax            ;save 0:32 address
        PCall   VDMMInit, <[pszzBaseVDDs], [pszzOtherVDDs],\
                           (offset FLAT:vdmconfigGlobal),\
                           (offset FLAT:vdminitconfigGlobal)>
mvix:   ret
mviie:  Panic   <"MVDMINIT: VMAllocKHB">
EndProc   MVDMINIT

;***LP  vdmmBuildPSZZ - build pszz string from sysinit cfg chain
;
;       ENTRY   (GS:SI) = pointer to 16 bit device chain head
;               (EDI) = flat pointer to put address of PSZZ block
;
;       EXIT    NONE
;
;       USES    EAX, ECX, EDX, ESI, EDI, Flags
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmBuildPSZZ,near,local
        xor     edx,edx                 ; (EDX) = starting length (0)
        movzx   esi,si
        push    esi
        push    edi

;determine length of all strings and allocate space for large string

bpz10:  .if     <<gs:[esi].CFG_Size> ne -1> ;if this is a high driver    BN001
          add   edx,16                      ;add space for size value    BN001
        .endif                              ;                            BN001
        movzx   edi,gs:[esi].CFG_FileSpec
        call    vdmmStrLen              ; (ECX) = file name length
        add     edx,ecx                 ; (EDX) = current length
        movzx   edi,gs:[esi].CFG_Parameters
        or      edi,edi                 ; are there parameters?
        jz      short bpz20             ;  no, don't get the length
        call    vdmmStrLen              ; (ECX) = parameters length
        add     edx,ecx                 ; BN001
;BD001  or      ecx,ecx
;BD001  jnz     short bpz20
;BD001  mov     gs:[esi].CFG_Parameters,0
;BD001  dec     edx                     ; cancel out one for space
;BD001  bpz20:  add     edx,ecx                 ; (EDX) = total length of name/parms
bpz20:  inc     edx                     ; one for space
        inc     edx                     ; one for null
        movzx   esi,gs:[esi].CFG_Next
        or      esi,esi                 ; end of chain?
        jnz     short bpz10             ;  yes, exit loop

        pop     edi                     ; (EDI) = pointer to put PSZZ address
        pop     esi                     ; (ESI) = pointer to chain head
        inc     edx                     ; one more for last double null
        CCALL32 VMAllocKHB <VM_HKH_PUB_RESRW, edx, VDDCFGSTROWNER, NA, edi>
        or      eax,eax
        jnz     short mviie
        mov     edi,[edi]               ; (EDI) = PSZZ address
        push    ebx

;copy small strings to large one in ASCIIZZ format

bpz30:  .if     <<gs:[esi].CFG_Size> ne -1> ;if this is a high driver   ;BN001
          mov     eax,'EZIS'                ;copy size string over      ;BN001
          mov     es:[edi],eax                                          ;BN001
          add     edi,4                                                 ;BN001
          mov     al,'='                                                ;BN001
          stosb                                                         ;BN001
          mov     eax,gs:[esi].CFG_Size     ;setup integer parm         ;BN001
          call    Int2Ascii                 ;convert integer to ascii   ;BN001
          mov     ax,'  '                                               ;BN001
          stosw                             ;add space after size       ;BN001
        .endif                                                          ;BN001
        movzx   ebx,gs:[esi].CFG_FileSpec
        call    vdmmStrCpy
        movzx   ebx,gs:[esi].CFG_Parameters
        or      ebx,ebx                 ; are there parameters?
        jz      short bpz40             ;  no, don't copy parameter string
        mov     al,' '                  ; separate name and arg with a space
        stosb
        call    vdmmStrCpy
bpz40:  xor     al,al                   ; null terminate
        stosb
        movzx   esi,gs:[esi].CFG_Next
        or      esi,esi                 ; end of chain?
        jnz     short bpz30             ;  yes, exit loop

        pop     ebx
        xor     al,al
        stosb
        ret
EndProc   vdmmBuildPSZZ

;***LP  vdmmStrCpy - copy string
;
;       ENTRY   (GS:EBX) = pointer to 16 bit string address
;               (EDI) = flat pointer to destination
;
;       EXIT    (EDI) = updated flat pointer to destination
;
;       USES    EAX, ECX, EDI, Flags
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmStrCpy,near,local
        push    esi
        push    edi
        mov     edi,ebx
        call    vdmmStrLen              ; (ECX) = string length
        mov     esi,edi                 ; (GS:ESI) = source pointer
        pop     edi
        rep movs byte ptr es:[edi],byte ptr gs:[esi]
        pop     esi
        ret
EndProc   vdmmStrCpy

;***LP  vdmmStrLen - compute length of string
;
;       ENTRY   (GS:EDI) = string address
;
;       EXIT    (GS:EDI) = start of string after leading tabs and spaces
;               (ECX) = size of string EXCLUDING leading tabs, spaces
;               and the terminating NULL.
;
;       USES    EAX, ECX, EDI, Flags
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmStrLen,near,local
        mov     eax,gs
        mov     es,eax
        mov     ecx,-1
        mov     al,' '                  ; skip leading spaces
        repe scasb
        dec     edi
        mov     al,c_HT                 ; skip leading tabs
        repe scasb
        dec     edi
        push    edi
        xor     al,al
        mov     ecx,-1
        repne scasb
        not     ecx
        dec     ecx
        pop     edi
        FlatContext <es>,eax
        ret
EndProc   vdmmStrLen

;***LP  vdmmGetMachineInfo - Get Machine Model and Sub-Model Byte
;
;       ENTRY   (GS:EBX) = pointer to 16 bit string address
;               (EDI) = flat pointer to destination
;
;       EXIT    AH = Model byte, AL = Model type
;
;       USES    EAX, EBX, ES
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmGetMachineInfo,near,local

        SaveReg <es, ebx>               ;
        xor     eax,eax                 ;  zero out EAX
        mov     ax,SAS_selector         ;  AX = SAS selector = DevConfigTbl Sel
        mov     es,ax                   ;  ES = DevConfigTbl selector
        mov     bx,es:[SAS_config_data] ;  BX = address of DevConfigTbl off.
        mov     bx,es:[bx]              ;  BX = DevConfigTbl off.
        mov     ah,es:[bx].Config_model ;  AH = Model byte
        mov     al,es:[bx].Config_type  ;  AL = Type byte (sub-model)
        RestoreReg  <ebx, es>           ;
        ret                             ;

EndProc   vdmmGetMachineInfo


;***EP  vdmmSem - generic interface between VDMM and Sem{Set,Clear,Wait}
;
;       ENTRY   hsem    -- the semaphore
;               ulCmd   -- what to do.  0 = Set, 1 = Clear, 2 = Wait
;
;       EXIT    NONE
;
        ASSUME DS:NOTHING

Procedure vdmmSem,near

ArgVar  sem_hsem,DWORD
ArgVar  sem_ulCmd,DWORD

        EnterProc
        SaveReg <ebx, esi, edi, ds, es>
        mov     ax,[sem_hsem.Segmt]             ; (AX:BX) = semaphore handle
        mov     bx,[sem_hsem.Offst]             ; (AX:BX) = semaphore handle
        mov     ecx,[sem_ulCmd]                 ; why were we called?
        loop    vsm10
        CALL16  SemClear
        jmp     short vsm30

vsm10:  loop    vsm20
        mov     cx,-1
        mov     di,cx
        CALL16  SemWait
        jmp     short vsm30

vsm20:  CALL16  SemSet
vsm30:  RestoreReg <es, ds, edi, esi, ebx>
        ExitProc
EndProc   vdmmSem


;***EP  vdmmRemoveSymMTE - Remove symbols linkage for VDD
;
;       ENTRY   handle to MTE
;
;       EXIT    Symbol linkage removed
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmRemoveSymMTE,near
ArgVar  phobmte,DWORD

        EnterProc
        SaveReg <ebx, esi, edi, ds, es>

IFDEF   PMDEBUG
        mov     esi,[phobmte]
        mov     si,word ptr [esi]
        CALL16  DebugRemoveSymMTE       ; unlink VDD's MTE info, keep symbols
ENDIF

        RestoreReg <es, ds, edi, esi, ebx>
        ExitProc

        ret
EndProc   vdmmRemoveSymMTE

;***LP  Clear96 - clear out the adapter select port
;
;       This function makes sure that we don't have an adapter
;       selected in setup mode
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    EAX
;
;       CONTEXT SYSInit time
;
;       PSEUDO-CODE
;         place a zero value into port 96h (adapter select)
;
Procedure Clear96,near,local
        push    eax                     ; save registers
        xor     al,al                   ; zero out al
        out     POS_ADP_SETUP_REG,al    ; write port
        pop     eax                     ; restore registers
        ret
EndProc Clear96

;***LP  POSRead - read a POS port and return the value
;
;       This function reads a POS port value and places the value
;       in EAX.
;
;       ENTRY   (EAX) = POS Port address
;       EXIT    (EAX) = POS Port value
;       USES    EAX,EDX
;
;       CONTEXT SysInit Time
;
;       PSEUDO-CODE
;         read pos port value into EAX
;
Procedure POSRead,near,local
        push    edx                     ;save registers
        mov     edx,eax                 ;transfer port address into EDX
;       out     4fh,al                  ; delay for IBM 486 systems
        jmp     $+2                     ; delay for IBM 386 systems
        jmp     $+2                     ; delay for IBM 386 systems
        in      al,dx                   ;read from the POS port
        xor     ah,ah                   ;place the value into EAX
        movzx   eax,ax
        pop     edx                     ;restore registers
        ret
EndProc POSRead

;***LP  vdmmGetSlotPOS - read all POS registers for a specified slot
;
;       This function reads all POS register values into a structure
;       for a specified slot.
;
;       ENTRY   Slot    = Slot in computer to read POS ports (0-based)
;               SlotPOS = pointer to structure of POS register values
;
;       EXIT    SlotPOS values modified
;
;       USES    EAX,EBX,EDX,EDI
;
;       CONTEXT SYSInit time
;
;       PSEUDO-CODE
;
;           unselect all adapters (just for safety)
;           select adapter based on Slot
;
;       WARNINGS  This code should not be executed while multithreading
;                 is operational.  Placing the planar into setup mode
;                 could cause some strange bugs to occur while other
;                 programs are running.
;
;
Procedure vdmmGetSlotPOS,near

ArgVar  Slot,ULONG
ArgVar  SlotPOSData,PVOID

        EnterProc
        SaveReg <eax,ebx,ecx,edx,edi>   ; save registers

        pushfd                          ; save flags
        cli                             ; turn off interrupts

        mov     eax,Slot                ; get slot number
        or      al,08h                  ; put slot into setup mode
        out     POS_ADP_SETUP_REG,al    ; to read pos ports

        mov     edi,SlotPOSData         ; get address of structure
        mov     ebx,POS_BASE_REG        ; load the base POS address
        mov     ecx,8                   ; loop for 8 times (8 bytes)
        cld                             ; direction up

LoopPOSRead:
        mov     eax,ebx                 ; get POS port to read
        call    POSRead                 ; do the read
        stosb                           ; store value in POS data structure
        inc     ebx                     ; move to next POS port
        loop    LoopPOSRead             ; repeat until transfer done

        call    Clear96                 ; deselect option

        popfd                           ; restore flags

        RestoreReg <edi,edx,ecx,ebx,eax>   ; restore registers
        ExitProc

EndProc vdmmGetSlotPOS

;***LP  vdmmGetPlanarPOS - read all POS registers for the planar
;
;       This function reads all POS register values into a structure
;       for the system slot.
;
;       ENTRY
;               pPlanarPOS = pointer to structure of POS register values
;
;       EXIT    PlanarPOS values modified
;
;       USES    EAX,EBX,ECX,EDX,EDI
;
;       CONTEXT SysInit time
;
;       PSEUDO-CODE
;
;           unselect all adapters (just for safety)
;           setup for 8 byte transfer from planar to structure
;           do {
;             save flags
;             disable interrupts
;             place planar into setup
;             read Planar POS value
;             store away planar POS value
;             move to next Planar pos address
;             restore flags
;             }
;             until transfer done
;
;       EFFECTS   Places planar into setup mode to get information and
;                 restores state when done.
;
;       WARNINGS  This code should not be executed while multithreading
;                 is operational.  Placing the planar into setup mode
;                 could cause some strange bugs to occur while other
;                 programs are running.
;
Procedure vdmmGetPlanarPOS,near

ArgVar  pPlanarPOS,PVOID

        EnterProc
        SaveReg <eax,ebx,ecx,edx,edi>

        call    Clear96                 ; deselect all adapters for setup
        mov     edi,pPlanarPOS          ; get address of Planar port struct

        mov     ebx,POS_BASE_REG        ; start at base of POS regs (100h)
        mov     ecx,8                   ; for a length of 8 bytes
        cld                             ; clear the direction bit
        pushfd                          ; save flags
        cli                             ; disable interrupts
        mov     al,07fh                 ; enable setup of planar
        out     POS_SYS_SETUP_REG,al    ; at port 094h
        mov     edx,ebx                 ;
        mov     al,0ffh                 ; 20Mhz Model 80 needs this
        out     dx,al                   ; output to Port 100 with FF
        jmp     short LoopPlanarRead    ;
LoopPlanarRead:
        mov     eax,ebx                 ; put the POS port address into EAX
        call    POSRead                 ; read the POS port value
        stosb                           ; store POS value into the structure
        inc     ebx                     ; move to the next port
        loop    LoopPlanarRead          ; loop back until all 8 bytes read
        mov     al,0ffh                 ; turn setup of planar off
        out     POS_SYS_SETUP_REG,al    ; again
        popfd                           ; restore flags

        RestoreReg<edi,edx,ecx,ebx,eax>
        ExitProc
EndProc vdmmGetPlanarPOS

;***LP  vdmmGetVideoPOS - read all POS registers for VIDEO    added 6.8
;
;       This function reads all POS register values into a structure
;       for the VIDEO slot.
;
;       ENTRY
;               pVideoPOS = pointer to structure of POS register values
;
;       EXIT    VideoPOS values modified
;
;       USES    EAX,EBX,ECX,EDX,EDI
;
;       CONTEXT SysInit time
;
;       PSEUDO-CODE
;
;           unselect all adapters (just for safety)
;           setup for 8 byte transfer from video to structure
;           do {
;             save flags
;             disable interrupts
;             place planar into setup
;             read Video POS value
;             store away video POS value
;             move to next Planar pos address
;             restore flags
;             }
;             until transfer done
;
;       EFFECTS   Places planar into video setup mode to get information and
;                 restores state when done.
;
;       WARNINGS  This code should not be executed while multithreading
;                 is operational.  Placing the planar into setup mode
;                 could cause some strange bugs to occur while other
;                 programs are running.
;
Procedure vdmmGetVideoPOS,near

ArgVar  pVideoPOS,PVOID

        EnterProc
        SaveReg <eax,ebx,ecx,edx,edi>

        call    Clear96                 ; deselect all adapters for setup
        mov     edi,pVideoPOS          ; get address of Planar port struct

        mov     ebx,POS_BASE_REG        ; start at base of POS regs (100h)
        mov     ecx,8                   ; for a length of 8 bytes
        cld                             ; clear the direction bit
LoopVideoRead:
        pushfd                          ; save flags
        cli                             ; disable interrupts
        mov     al,0dfh                 ; enable setup of video
        out     POS_SYS_SETUP_REG,al    ; at port 094h
        mov     eax,ebx                 ; put the POS port address into EAX
        call    POSRead                 ; read the POS port value
        stosb                           ; store POS value into the structure
        inc     ebx                     ; move to the next port
        mov     al,0ffh                 ; turn setup of planar off
        out     POS_SYS_SETUP_REG,al    ; again
        popfd                           ; restore flags
        loop    LoopVideoRead           ; loop back until all 8 bytes read

        RestoreReg<edi,edx,ecx,ebx,eax>
        ExitProc
EndProc vdmmGetVideoPOS

;***LP  vdmmGetPort90 - get current value of Port 90
;
;       This function reads port 90 and returns the value in AL.
;
;       ENTRY   NONE
;       EXIT    (AL) = Port 90 contents
;       USES    AL
;
;       CONTEXT SYSINIT time
;
;       PSEUDO-CODE
;         read from PORT 90
;
Procedure  vdmmGetPort90,near

        in      al,POS_CEN_ARB_REG
        ret
EndProc    vdmmGetPort90

;***LP  vdmmGetPort92 - get current value of Port 92
;
;       This function reads port 92 and returns the value in AL.
;
;       ENTRY   NONE
;       EXIT    (AL) = Port 92 contents
;       USES    AL
;
;       CONTEXT SYSINIT time
;
;       PSEUDO-CODE
;         read from PORT 92
;
Procedure  vdmmGetPort92,near

        in      al,POS_SYS_CTRLA_REG
        ret
EndProc    vdmmGetPort92


EndCode

DefCode PRIVATE, SWAP, PASCAL

;***LP  vdmmGetFileFromPath - get base name of the program from the full
;       path taking care of DBCS.
;
;       ENTRY - pszPath     - Path String
;               cbPath      - Length of string including null
;
;       EXIT  - return base name pointer
;               if cbPath == 0 return null
;
;       PCODE
;           search for '\' backward
;               if found return rest of the string as base name.
;           else search for ':'
;               if found return rest of the string
;           else return pszPath
;

Procedure vdmmGetFileFromPath,NEAR

ArgVar  pszPath,DWORD
ArgVar  cbPath,DWORD

        EnterProc
        mov     eax,[cbPath]            ; Length should be > 1
        cmp     eax,1
        jg      short vgg5
        xor     eax,eax                 ; If not return NULL
        jmp     short vgg30
vgg5:
        SaveReg <EBX,ECX,EDI,ESI,ES>
        cld
        mov     eax,[pszPath]           ; (EAX) = linear address
        mov     ecx,[cbPath]            ; (ECX) = transfer size
        xor     edx,edx                 ; (EDX) = selector index
        call    demMapVirt              ; (AX) = selector

        mov     es,ax
        xor     edi,edi
        CALL16  FindPathEnd             ; Find last '\'
        jnc     short vgg20             ; If NC means got it

        mov     al,':'                  ; Else search for ':'
        xor     edi,edi
        CALL16  FindChar                ; If ZR means edi points to ':'
        jz      short vgg10

        mov     eax,[pszPath]           ; else path is file name
        jmp     short vgg20

vgg10:  inc     edi
vgg20:  mov     eax,[pszPath]
        add     eax,edi
        RestoreReg <ES,ESI,EDI,ECX,EBX>
vgg30:
        ExitProc
EndProc vdmmGetFileFromPath

SWAP32_23 segment
;***EP  vdmmEnterCreateVDM - entry setup for VDMMApiCreateVDM
;
;       This function is an assembly stub for VDMMApiCreateVDM that
;       requests the create VDM mutex semaphore and initializes the
;       wait for VDM creation to be done.
;
;       ENTRY   NONE
;
;       EXIT    SUCCESS, returns 0
;               FAILURE,  returns !0
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmEnterCreateVDM,near
        SaveReg <ebx, esi, edi>
        DosContext ,ax
        mov     bx,offset DOSGROUP:mutexCreateVDM
        mov     cx,-1
        mov     di,cx                   ; no time out
        CALL16  SemRequest
        movzx   eax,ax
        jc      short encx              ; jump to exit if error interrupted

        DosContext ,ax
        mov     bx,offset DOSGROUP:eventCreateVDM
        CALL16  SemSet                  ; set VDM creation is done semaphore
        jc      short encie
        xor     eax,eax
        .errnz  NO_ERROR

encx:   FlatContext <ds,es>,ebx
        RestoreReg <edi, esi, ebx>
        ret
encie:  Panic   <"vdmmEnterCreateVDM: SemSet">
EndProc   vdmmEnterCreateVDM
SWAP32_23 ends

SWAP32_23 segment
;***EP  vdmmExitCreateVDM - exit code for VDMMApiCreateVDM
;
;       This function is the assembly language stub code for VDM
;       creation exit.  It waits until the "in context" VDM creation
;       to finish, retrieves the return code from the child VDM and
;       puts the return codes into the buffer passed to the API.
;
;       ENTRY   ret          - return code so far
;               presultcodes - pointer to put return codes
;               resultcodes  - return codes
;
;       EXIT    SUCCESS, returns 0
;               FAILURE,  returns !0
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmExitCreateVDM,near

ArgVar  dcv_ret,DWORD
ArgVar  dcv_presultcodes,DWORD          ; 16 bit sel:off from shell
ArgVar  dcv_resultcodes,DWORD

        EnterProc
        SaveReg <ebx, esi, edi>
        cmp     [dcv_ret],NO_ERROR      ; already an error?
        jne     short exc20             ;  yes, just clear mutex semaphore

        DosContext ,ax
        mov     bx,offset DOSGROUP:eventCreateVDM
        mov     cx,-1
        mov     di,cx                   ; no time out
        CALL16  SemWait                 ; wait until VDM creation is finished
        jc      short exc10             ; jump to exit if error interrupted

        FlatContext <ds>,eax
        mov     eax,[retCreateVDM]      ; (EAX) = return code from vdmmStart
        mov     [dcv_ret],eax           ; set return code

        push    ss
        pop     ds
        lea     si,[dcv_resultcodes]    ; (DS:SI) = source
        mov     bx,[dcv_presultcodes.Segmt] ; (BX:DI) = destination address
        mov     di,[dcv_presultcodes.Offst]
        mov     cx,4                    ; (CX) = count
        CALL16  SuBuff                  ; set result codes, ignore errors
        jnc     short exc20

exc10:  movzx   eax,ax                  ; (EAX) = error code
        mov     [dcv_ret],eax

exc20:  DosContext ,ax
        mov     bx,offset DOSGROUP:mutexCreateVDM
        CALL16  SemClear
        jc      short excie

excx:   FlatContext <ds,es>,ebx
        mov     eax,[dcv_ret]           ; (EAX) = error code
        RestoreReg <edi, esi, ebx>
        ExitProc
excie:  Panic   <"vdmmExitCreateVDM: SemClear">
EndProc   vdmmExitCreateVDM
SWAP32_23 ends

SWAP32_27 segment
;***EP  vdmmEnterTerminateVDM - entry setup for vdmmExpungeVDM
;
;       This function is an assembly stub for vdmmExpungeVDM that
;       requests the create VDM mutex semaphore.
;
;       ENTRY   NONE
;
;       EXIT    SUCCESS, returns 0
;               FAILURE,  returns !0
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmEnterTerminateVDM,near
        SaveReg <ebx, esi, edi>
        DosContext ,ax
        mov     bx,offset DOSGROUP:mutexCreateVDM
        mov     cx,-1
        mov     di,cx                   ; no time out
        CALL16  SemRequest
        movzx   eax,ax
        jc      short entx              ; jump to exit if error interrupted
        xor     eax,eax
entx:   FlatContext <ds,es>,ebx
        RestoreReg <edi, esi, ebx>
        ret
EndProc   vdmmEnterTerminateVDM
SWAP32_27 ends

SWAP32_27 segment
;***EP  vdmmExitTerminateVDM - exit code for vdmmExpungeVDM
;
;       This function is the assembly language stub code for VDM
;       termination exit.
;
;       ENTRY   NONE
;
;       EXIT    SUCCESS, returns 0
;               FAILURE,  returns !0
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmExitTerminateVDM,near
        SaveReg <ebx, esi, edi>
        DosContext ,ax
        mov     bx,offset DOSGROUP:mutexCreateVDM
        CALL16  SemClear
        jc      short extie
        xor     eax,eax
        FlatContext <ds,es>,ebx
        RestoreReg <edi, esi, ebx>
        ret
extie:  Panic   <"vdmmExitTerminateVDM: SemClear">
EndProc   vdmmExitTerminateVDM
SWAP32_27 ends
EndCode

        FARCODE HIGH32
DefCode PRIVATE, SWAP, C
SWAP32_23 segment
;***LP  vdmmStart - start routine of a newly created VDM
;
;       ENTRY   ((SS:ESP)) = dummy return address
;               ((SS:ESP)+4) = VSF stack frame
;
;       EXIT    To V86 code
;
;       USES    ALL
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmStart,near
        pop     eax                     ; toss the dummy return address
        FlatContext <ds,es>,eax
        PCall   vdmmCreateVDM
        mov     [retCreateVDM],eax      ; return errors during VDM creation
        or      eax,eax                 ; check if VDM creation failed
        je      short vds10             ; go ahead if success
        CCALL32 TKDieSoonPTDA, <pPTDACur, eax, TC_HARDERR, 0>
                                        ; force the VDM to die.
vds10:  DosContext ,ax
        mov     bx,offset DOSGROUP:eventCreateVDM
        CALL16  SemClear                ; signal that VDM creation is finished
        jc      TUNE ;  excie

;       Since we obviously cannot create the VDM process frozen (else this
;       start routine would not run), we freeze ourselves after waking
;       the caller.

        FlatContext <ds,es>,eax
        cmp     [retCreateVDM],NO_ERROR ; did the vdm creation fail?
        jne     short vdsx              ;  yes, skip the SetState
        sidt    [_lidtV86IDT]           ; save V86 mode IDT
        PCall   vdmmSetState, <vdmid_mphvdmptcb,FALSE>

;       When the NPX processor doesn't exist, VDMs must have the EM bit
;       and the TS bit clear.  VDM process creation starts with the EM
;       and TS bits clear, but a newly created VDM process (before ProcType
;       is set to PT_REALMODE) may task switch which sets the TS bit for
;       OS/2 processes.  We clear it here in case it was set during
;       VDM creation.

        mov     eax,cr0
        test    eax,CR0_MP              ; if NPX is not present
        jnz     short vdsx
        and     eax,not CR0_TS          ; clear TS bit
        mov     cr0,eax
vdsx:
;-----------------------;
public  VDMM_IRETD      ;
VDMM_IRETD:             ;
;-----------------------;
        KMExitKmodeVDM v86              ; exit kernel and return to V86 code
TUNE:   jmp  excie
EndProc   vdmmStart
SWAP32_23 ends
EndCode

        FARCODE HIGH32                                                   ;@xxxx
DefCode PRIVATE, GLOBAL, C                                               ;@xxxx
                                                                         ;@xxxx
Procedure _vdmmEnterV86Mode, near                                        ;@xxxx
        FlatContext <ds,es>,eax                                          ;@xxxx
        mov     eax,cr0                                                  ;@xxxx
        test    eax,CR0_MP              ; if NPX is not present          ;@xxxx
        jnz     short vdsx1                                              ;@xxxx
        and     eax,not CR0_TS          ; clear TS bit                   ;@xxxx
        mov     cr0,eax                                                  ;@xxxx
vdsx1:  add     esp, 0Ch                ; Adjust stack                   ;@xxxx
        KMExitKmodeVDM v86              ; exit kernel/return to V86 code ;@xxxx
                                                                         ;@xxxx
EndProc _vdmmEnterV86Mode                                                ;@xxxx
                                                                         ;@xxxx
                                                                         ;@xxxx
Procedure _vdmmInt13SVCCode                                              ;@xxxx
                                                                         ;@xxxx
visc1:    svc   SVC_DEMVDMINT13REQUEST                                   ;@xxxx
          jmp   visc1                                                    ;@xxxx

          org   _vdmmInt13SVCCode+16
visc2:    svc   SVC_DEMVDMINT13REQUEST                                   ;@xxxx
          jmp   visc2                                                    ;@xxxx
                                                                         ;@xxxx
EndProc   _vdmmInt13SVCCode                                              ;@xxxx
                                                                         ;@xxxx

;@V3.2SEN00 adding int10 support

Procedure _vdmmInt10SVCCode                                       ;@V3.2SEN00
                                                                  ;@V3.2SEN00
ivisc1:    svc   SVC_DEMVDMINT10REQUEST                           ;@V3.2SEN00
          jmp   ivisc1                                            ;@V3.2SEN00

          org   _vdmmInt10SVCCode+16
ivisc2:    svc   SVC_DEMVDMINT10REQUEST                           ;@V3.2SEN00
          jmp   ivisc2                                            ;@V3.2SEN00
                                                                  ;@V3.2SEN00
EndProc   _vdmmInt10SVCCode                                       ;@V3.2SEN00

Procedure _vdmmInt13BufferAlloc                                          ;@xxxx

        ArgVar pSel,PUSHORT                                              ;@xxxx
        ArgVar BufLen,ULONG                                              ;@xxxx

        EnterProc                                                        ;@xxxx
        SaveReg <ebx,ecx,esi,edi>                                        ;@xxxx
        DosContext <ds>
        mov     ax,word ptr BufLen[2]   ;                                ;@xxxx
        mov     bx,word ptr BufLen[0]   ;                                ;@xxxx
        mov     si,HF_LOWMEM            ; memory from below 1Meg         ;@xxxx
        mov     di,INITOWNER            ; owner                          ;@xxxx
        mov     ch,D_DATA0              ; data segment ring 0            ;@xxxx
        mov     cl,SA_GDT               ; segment gdt entry              ;@xxxx
        CALL16  SegAlloc2                                                ;@xxxx
        jc      viba10                                                   ;@xxxx
        FlatContext <ds>
        mov     esi, [pSel]                                              ;@xxxx
        mov     word ptr [esi],bx                                        ;@xxxx
        DosContext <ds>
        mov     ds,bx                   ; address                        ;@xxxx
        xor     si,si                                                    ;@xxxx
        CALL16  VirtToPhys                                               ;@xxxx
        movzx   ecx,ax                                                   ;@xxxx
        shl     ecx,16                                                   ;@xxxx
        mov     cx,bx                                                    ;@xxxx
        mov     eax,ecx                                                  ;@xxxx
        jmp     viba20                                                   ;@xxxx
                                                                         ;@xxxx
viba10: xor     eax,eax                                                  ;@xxxx
viba20:                                                                  ;@xxxx
        FlatContext <ds>
        RestoreReg <edi,esi,ecx,ebx>                                     ;@xxxx
        ExitProc
                                                                         ;@xxxx
EndProc   _vdmmInt13BufferAlloc                                          ;@xxxx

Procedure _vdmmInt13BufferFree                                           ;@xxxx
                                                                         ;@xxxx
        SaveReg         <si, di, ds, es>                                 ;@xxxx
                                                                         ;@xxxx
        xor             cx, cx                                           ;@xxxx
        FlatContext     <ds, es>, bx                                     ;@xxxx
        CALLF32         SELSegFree                                       ;@xxxx
                                                                         ;@xxxx
        RestoreReg      <es, ds, di, si>                                 ;@xxxx
        ExitProc                                                         ;@xxxx
                                                                         ;@xxxx
EndProc   _vdmmInt13BufferFree                                           ;@xxxx

SelTblEntry     struc
SelTblSel       dw      0       ; Selector
SelTblSeg       dw      0       ; Segment
SelTblLimit     dw      0       ; Limit
SelTblAccess    dd      0       ; Access Rights
SelTblEntry     ends

ABTblEntry      struc
ABTblSel        dd      0       ; Selector
ABTblSeg        dd      0       ; Segment
ABTblLimit      dd      0       ; Limit
ABTblAccess     dd      0       ; Access Rights
ABTblEntry      ends

Procedure _vdmmReadABIOSSelTbl                                           ;@xxxx

        ArgVar TblIndex,ULONG
        ArgVar pTblContents,PUSHORT

        EnterProc

        SaveReg <es, ds>

        FlatContext     <ds>
        DosContext      <es>

        .if <es:ABIOS_present ne 0>

          DosInitContext  <es>
          mov    edx, [pTblContents]

          mov    eax, [TblIndex]
          imul   eax, size SelTblEntry

          .if <ax b <offset DOSINITDATA:ABIOSSelTableEnd>>

            mov    ecx, es:ABIOSSelTable[eax].SelTblAccess
            mov    [edx].ABTblAccess, ecx
            movzx  ecx, es:ABIOSSelTable[eax].SelTblLimit
            mov    [edx].ABTblLimit, ecx
            movzx  ecx, es:ABIOSSelTable[eax].SelTblSeg
            mov    [edx].ABTblSeg, ecx
            movzx  ecx, es:ABIOSSelTable[eax].SelTblSel
            mov    [edx].ABTblSel, ecx
            mov    eax, ecx

          .else

            xor    eax, eax

          .endif

        .else

          xor    eax, eax
          mov    [edx].SelTblSel,   ax
          mov    [edx].SelTblSeg,   ax
          mov    [edx].SelTblLimit, ax

        .endif

        RestoreReg <ds, es>
        ExitProc

EndProc   _vdmmReadABIOSSelTbl

EndCode                                                                  ;@xxxx

        FARCODE HIGH32
DefCode PRIVATE, SWAP, PASCAL

;***EP  vdmmInitGDT_PTDA - initialize GDT_PTDA for C code
;
;       ENTRY   NONE
;
;       EXIT    NONE
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmInitGDT_PTDA,near
        mov     ax,GSEL GDT_PTDA
        mov     selGDT_PTDA,ax
        ret
EndProc   vdmmInitGDT_PTDA

SWAP32_18 segment
;***LP  vdmmSetState - Set the state of a VDM (ie, frozen or ready)
;
;       This is an assembly interface between VDMM and SetState.
;
;       ENTRY   ptcb (pointer to VDM TCB)
;               fReady (TRUE to make "ready", FALSE to make "frozen")
;
;       EXIT    None
;
;       CONTEXT Task
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmSetState,NEAR

ArgVar  ptcb,PVOID
ArgVar  fReady,BOOL

        EnterProc
        mov     edx,[ptcb]
        cmp     [fReady],FALSE          ;freeze?
        jne     short vss10             ;no

        or      [edx].TCBForce_Flg,TK_FF_ICE
        jmp     short vss30             ;yes, set force-flag and get out

vss10:  and     [edx].TCBForce_Flg,not TK_FF_ICE
        cmp     [edx].TCBState,STATE_FROZEN
        jne     short vss30             ;not frozen, so don't thaw

;        CCALL32 _SCHSetState,<edx, STATE_READY>
        mov     [edx].TCBState,STATE_READY
        CCALL32 _TKUpdateState,<edx>
vss30:  ExitProc
EndProc vdmmSetState
SWAP32_18 ends

;***LP  vdmmAdjustError - Adjust kernel return code to extended error code.
;
;       The kernel returns a limited set of return codes but stores an
;       extended error code in the current TCB.  If an extended error code
;       exists, vdmmAdjustError maps the kernel error code to the appropriate
;       extended error code otherwise it returns the kernel return code
;       (in that case, the kernel return code = the extended error code).
;
;       ENTRY   AX = kernel return code
;               CY = set
;               [TCBFailErr] = extended error code or zero
;
;       EXIT    AX = true error code
;
;       CONTEXT Task
;
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure vdmmAdjustError,NEAR

        push    esi                             ; save register
        mov     esi,[pTCBCur]                   ; (ESI) = TCB pointer
        cmp     [esi].TCBFailErr,0              ; was there a low level failure?
        jz      short adjusterr1                ; no, exit
        xor     eax,eax                         ; clear eax
        mov     ax,[esi].TCBFailErr             ; retrieve true extended error
adjusterr1:
        pop     esi
        ret
EndProc vdmmAdjustError

EndCode

        FARCODE HIGH32
DefCode PRIVATE, GLOBAL, PASCAL
;
; SUBROUTINE NAME:  Int2Ascii
;
; DESCRIPTIVE NAME:  Integer to Ascii
;
; FUNCTION:      To convert an unsigned 32 bit integer to an
;                ASCII string
;
; NOTES:         Int2Ascii operates recursively to produce
;                an ASCII string.  Note that no trailing 0 is
;                generated (the string is not ASCIIZ)
;
; ENTRY POINT:   Int2Ascii
;    LINKAGE:    call near
;
; INPUT:
;
;                EAX        = unsigned integer to be converted
;                ES:DI     -> location to put string
;
; EXIT-NORMAL:
;
;                ES:DI     -> position immediately following
;                          the produced string
;                EAX       destroyed
;
; EXIT-ERROR:    none
;
; EFFECTS:       none
;
; INTERNAL REFERENCES:
;    ROUTINES:   none
;
; EXTERNAL REFERENCES:
;    ROUTINES:   none
;
; PTR B783548
;     This routine was modified to use 32 bit registers
;
;Save remainder
;Divide EAX by 10
;IF EAX is not 0
;        Call Int2Ascii recursively
;ENDIF
;Convert remainder to ASCII
;Store the character
;Restore remainder
Procedure       Int2Ascii,NEAR,LOCAL
                push    edx
                xor     edx,edx
                push    ecx
                mov     ecx,10
                div     ecx                    ;Divide 0:EAX by 10
                pop     ecx
                .if     <nonzero eax>          ;If the quotient is > 0
                  call    Int2Ascii            ;Recurse
                .endif
                add     dl,'0'                  ;Convert digit to ascii
                mov     al,dl                   ;Store the digit
                stosb
                pop     edx
                ret
EndProc         Int2Ascii


;***    VDH services MTE entry table
;
;       This table generates an MTE entry table slot for each
;       VDH service exported to VDDs.
;

VDDGenEntryTbl VDHSETDOSDEVICE,         ORD_VDHSetDosDevice
VDDGenEntryTbl _TKSSBase,               ORD__TKSSBase
VDDGenEntryTbl VDHINSTALLUSERHOOK,      ORD_VDHInstallUserHook
VDDGenEntryTbl VDHPOPUP,                ORD_VDHPopup
VDDGenEntryTbl VDHKILLVDM,              ORD_VDHKillVDM
VDDGenEntryTbl VDHSETPRIORITY,          ORD_VDHSetPriority
VDDGenEntryTbl VDHFREEZEVDM,            ORD_VDHFreezeVDM
VDDGenEntryTbl VDHTHAWVDM,              ORD_VDHThawVDM
VDDGenEntryTbl VDHISVDMFROZEN,          ORD_VDHIsVDMFrozen
VDDGenEntryTbl VDHENUMERATEVDMS,        ORD_VDHEnumerateVDMs
VDDGenEntryTbl VDHHANDLEFROMSGID,       ORD_VDHHandleFromSGID
VDDGenEntryTbl VDHHANDLEFROMPID,        ORD_VDHHandleFromPID
VDDGenEntryTbl VDHINSTALLIOHOOK,        ORD_VDHInstallIOHook
VDDGenEntryTbl VDHREMOVEIOHOOK,         ORD_VDHRemoveIOHook
VDDGenEntryTbl VDHSETIOHOOKSTATE,       ORD_VDHSetIOHookState
VDDGenEntryTbl VDHINSTALLINTHOOK,       ORD_VDHInstallIntHook
VDDGenEntryTbl VDHARMBPHOOK,            ORD_VDHArmBPHook
VDDGenEntryTbl VDHARMSTIHOOK,           ORD_VDHArmSTIHook
VDDGenEntryTbl VDHARMRETURNHOOK,        ORD_VDHArmReturnHook
VDDGenEntryTbl VDHINSTALLFAULTHOOK,     ORD_VDHInstallFaultHook         ; WIN32
VDDGenEntryTbl VDHREMOVEFAULTHOOK,      ORD_VDHRemoveFaultHook
VDDGenEntryTbl VDHOPENPDD,              ORD_VDHOpenPDD
VDDGenEntryTbl VDHREGISTERVDD,          ORD_VDHRegisterVDD
VDDGenEntryTbl VDHOPENVDD,              ORD_VDHOpenVDD
VDDGenEntryTbl VDHREQUESTVDD,           ORD_VDHRequestVDD
VDDGenEntryTbl VDHALLOCMEM,             ORD_VDHAllocMem
VDDGenEntryTbl VDHFREEMEM,              ORD_VDHFreeMem
VDDGenEntryTbl VDHALLOCDOSMEM,          ORD_VDHAllocDosMem
VDDGenEntryTbl VDHCREATEBLOCKPOOL,      ORD_VDHCreateBlockPool
VDDGenEntryTbl VDHALLOCBLOCK,           ORD_VDHAllocBlock
VDDGenEntryTbl VDHFREEBLOCK,            ORD_VDHFreeBlock
VDDGenEntryTbl VDHDESTROYBLOCKPOOL,     ORD_VDHDestroyBlockPool
VDDGenEntryTbl VDHCOPYMEM,              ORD_VDHCopyMem
VDDGenEntryTbl VDHEXCHANGEMEM,          ORD_VDHExchangeMem
VDDGenEntryTbl VDHLOCKMEM,              ORD_VDHLockMem
VDDGenEntryTbl VDHUNLOCKMEM,            ORD_VDHUnLockMem
VDDGenEntryTbl VDHQUERYSEL,             ORD_VDHQuerySel
VDDGenEntryTbl VDHCREATESEL,            ORD_VDHCreateSel
VDDGenEntryTbl VDHDESTROYSEL,           ORD_VDHDestroySel
VDDGenEntryTbl VDHALLOCPAGES,           ORD_VDHAllocPages
VDDGenEntryTbl VDHREALLOCPAGES,         ORD_VDHReallocPages
VDDGenEntryTbl VDHFREEPAGES,            ORD_VDHFreePages
VDDGenEntryTbl VDHFINDFREEPAGES,        ORD_VDHFindFreePages
VDDGenEntryTbl VDHGETDIRTYPAGEINFO,     ORD_VDHGetDirtyPageInfo
VDDGenEntryTbl VDHQUERYFREEPAGES,       ORD_VDHQueryFreePages
VDDGenEntryTbl VDHRESERVEPAGES,         ORD_VDHReservePages
VDDGenEntryTbl VDHMAPPAGES,             ORD_VDHMapPages
VDDGenEntryTbl VDHARMTIMERHOOK,         ORD_VDHArmTimerHook
VDDGenEntryTbl VDHDISARMTIMERHOOK,      ORD_VDHDisarmTimerHook
VDDGenEntryTbl VDHPUSHINT,              ORD_VDHPushInt
VDDGenEntryTbl VDHPOPINT,               ORD_VDHPopInt
VDDGenEntryTbl VDHINSTALLFAULTHANDLER,  ORD_VDHInstallFaultHandler      ; WIN32
VDDGenEntryTbl VDHPUSHREGS,             ORD_VDHPushRegs
VDDGenEntryTbl VDHPOPREGS,              ORD_VDHPopRegs
VDDGenEntryTbl VDHVIEWHANDLE,           ORD_VDHViewHandle               ; WIN32
VDDGenEntryTbl VDHPUSHFARCALL,          ORD_VDHPushFarCall
VDDGenEntryTbl VDHGETERROR,             ORD_VDHGetError
VDDGenEntryTbl VDHSETERROR,             ORD_VDHSetError
VDDGenEntryTbl VDHQUERYSYSVALUE,        ORD_VDHQuerySysValue
VDDGenEntryTbl VDHPUTSYSVALUE,          ORD_VDHPutSysValue
VDDGenEntryTbl VDHOPEN,                 ORD_VDHOpen
VDDGenEntryTbl VDHCLOSE,                ORD_VDHClose
VDDGenEntryTbl VDHREAD,                 ORD_VDHRead
VDDGenEntryTbl VDHWRITE,                ORD_VDHWrite
VDDGenEntryTbl VDHSEEK,                 ORD_VDHSeek
VDDGenEntryTbl VDHDEVIOCTL,             ORD_VDHDevIOCtl
VDDGenEntryTbl VDHPHYSICALDISK          ORD_VDHPhysicalDisk
VDDGenEntryTbl VDHYIELD,                ORD_VDHYield
VDDGenEntryTbl VDHARMCONTEXTHOOK,       ORD_VDHArmContextHook
VDDGenEntryTbl VDHHALTSYSTEM,           ORD_VDHHaltSystem
VDDGenEntryTbl VDHGETCODEPAGEFONT,      ORD_VDHGetCodePageFont
VDDGenEntryTbl VDHRELEASECODEPAGEFONT,  ORD_VDHReleaseCodePageFont
VDDGenEntryTbl __panicfmt,              ORD__VDHPanic
ifdef PMDEBUG
VDDGenEntryTbl _printf,                 ORD__printf
else
VDDGenEntryTbl _nulroutine,             ORD__printf
endif
VDDGenEntryTbl VDHSETTIMER0,            ORD_VDHSetTimer0
VDDGenEntryTbl VDHDEVBEEP,              ORD_VDHDevBeep
VDDGenEntryTbl VDHSETFLAGS,             ORD_VDHSetFlags
                                               ;149007
VDDGenEntryTbl VDHASSERTTASK,           ORD_VDHAssertTask
VDDGenEntryTbl VDHASSERTVDMTASK,        ORD_VDHAssertVDMTask
VDDGenEntryTbl VDHASSERTTASKONLY,       ORD_VDHAssertTaskOnly
VDDGenEntryTbl VDHASSERTVDMTASKONLY,    ORD_VDHAssertVDMTaskOnly
VDDGenEntryTbl VDHASSERTINITONLY,       ORD_VDHAssertInitOnly
VDDGenEntryTbl VDHCHECKHVDM,            ORD_VDHCheckHVDM
VDDGenEntryTbl VDHALLOCHOOK,            ORD_VDHAllocHook
VDDGenEntryTbl VDHQUERYHOOKDATA,        ORD_VDHQueryHookData
VDDGenEntryTbl VDHFREEHOOK,             ORD_VDHFreeHook
VDDGenEntryTbl VDHReleaseNPX,           ORD_VDHReleaseNPX
VDDGenEntryTbl VDHNPXReset,             ORD_VDHNPXReset
VDDGenEntryTbl VDHNPXClearBusy,         ORD_VDHNPXClearBusy
VDDGenEntryTbl VDHNPXRegisterVDD,       ORD_VDHNPXRegisterVDD
VDDGenEntryTbl VDHUNRESERVEPAGES,       ORD_VDHUnreservePages
VDDGenEntryTbl VDHQUERYLIN,             ORD_VDHQueryLin
VDDGenEntryTbl VDHCREATESEM             ORD_VDHCreateSem
VDDGenEntryTbl VDHDESTROYSEM            ORD_VDHDestroySem
VDDGenEntryTbl VDHQUERYSEM              ORD_VDHQuerySem
VDDGenEntryTbl VDHRESETEVENTSEM         ORD_VDHResetEventSem
VDDGenEntryTbl VDHPOSTEVENTSEM          ORD_VDHPostEventSem
VDDGenEntryTbl VDHWAITEVENTSEM          ORD_VDHWaitEventSem
VDDGenEntryTbl VDHREQUESTMUTEXSEM       ORD_VDHRequestMutexSem
VDDGenEntryTbl VDHRELEASEMUTEXSEM       ORD_VDHReleaseMutexSem
VDDGenEntryTbl VDHPUSHSTACK,            ORD_VDHPushStack
VDDGenEntryTbl VDHPOPSTACK,             ORD_VDHPopStack
VDDGenEntryTbl VDHREGISTERPROPERTY,     ORD_VDHRegisterProperty
VDDGenEntryTbl VDHQUERYPROPERTY,        ORD_VDHQueryProperty
ifdef PERFVIEW
VDDGenEntryTbl VDHREGISTERPERFCTRS,     ORD_VDHRegisterPerfCtrs
else
VDDGenEntryTbl _nulroutine,             ORD_VDHRegisterPerfCtrs
endif
VDDGenEntryTbl VDHALLOCDMABUFFER,       ORD_VDHAllocDMABuffer
VDDGenEntryTbl VDHFREEDMABUFFER,        ORD_VDHFreeDMABuffer
VDDGenEntryTbl INTSetVDMIRQ,            ORD_INTSetVDMIRQ
VDDGenEntryTbl INTUnsetVDMIRQ,          ORD_INTUnsetVDMIRQ
VDDGenEntryTbl INTEOIVDMIRQ,            ORD_INTEOIVDMIRQ
VDDGenEntryTbl VDHSWITCHTOV86,          ORD_VDHSwitchToV86
VDDGenEntryTbl VDHSWITCHTOVPM,          ORD_VDHSwitchToVPM
VDDGenEntryTbl VDHCHECKVPMINTVECTOR,    ORD_VDHCheckVPMIntVector
VDDGenEntryTbl VDHGETVPMINTVECTOR,      ORD_VDHGetVPMIntVector
VDDGenEntryTbl VDHSETVPMINTVECTOR,      ORD_VDHSetVPMIntVector
VDDGenEntryTbl VDHARMVPMBPHOOK,         ORD_VDHArmVPMBPHook
VDDGenEntryTbl VDHENDUSEVPMSTACK,       ORD_VDHEndUseVPMStack
VDDGenEntryTbl VDHBEGINUSEVPMSTACK,     ORD_VDHBeginUseVPMStack
VDDGenEntryTbl _flVdmStatus,            ORD__flVdmStatus
VDDGenEntryTbl VDHCLOSEVDD,             ORD_VDHCloseVDD
VDDGenEntryTbl VDHDECODEPROPERTY,       ORD_VDHDecodeProperty
VDDGenEntryTbl _pdhdHostData,           ORD__pdhdHostData
VDDGenEntryTbl VDHREGISTERDPMI,         ORD_VDHRegisterDPMI
VDDGenEntryTbl _flVpmIRQHooks,          ORD__flVpmIRQHooks
VDDGenEntryTbl VDHCHANGEVPMIF,          ORD_VDHChangeVPMIF
VDDGenEntryTbl VDHGETSELBASE,           ORD_VDHGetSelBase
VDDGenEntryTbl VDHREADUBUF,             ORD_VDHReadUBuf
VDDGenEntryTbl VDHWRITEUBUF,            ORD_VDHWriteUBuf
VDDGenEntryTbl VDHCHECKPAGEPERM,        ORD_VDHCheckPagePerm
VDDGenEntryTbl VDHRAISEEXCEPTION,       ORD_VDHRaiseException
VDDGenEntryTbl VDHSTARTHWINT,           ORD_VDHStartHWInt
VDDGenEntryTbl VDHGETVPMEXCEPT,         ORD_VDHGetVPMExcept
VDDGenEntryTbl VDHSETVPMEXCEPT,         ORD_VDHSetVPMExcept
VDDGenEntryTbl VDHPROBEUBUF,            ORD_VDHProbeUBuf
VDDGenEntryTbl VDHPREPVPMIRET,          ORD_VDHPrepVPMIret
VDDGenEntryTbl VDHPOPVPMFARRET,         ORD_VDHPopVPMFarRet
VDDGenEntryTbl VDHSETBOOST,             ORD_VDHSetBoost
VDDGenEntryTbl VDHWAKERAMSEM,           ORD_VDHWakeRamSem
VDDGenEntryTbl VDHREQUESTRAMSEM,        ORD_VDHRequestRamSem
VDDGenEntryTbl VDHPROCESSTOGLOBAL,      ORD_VDHProcessToGlobal
VDDGenEntryTbl VDHVALIDATEPID,          ORD_VDHValidatePID
VDDGenEntryTbl VDHMAPMEMBLOCK,          ORD_VDHMapMemBlock
VDDGenEntryTbl DevWOHandle,             ORD_DevWOHandle
VDDGenEntryTbl VDHVMGETHANDLE,          ORD_VDHVMGetHandle
VDDGenEntryTbl VDHVMATTACH,             ORD_VDHVMAttach
VDDGenEntryTbl VDHCREATETHREAD,         ORD_VDHCreateThread
VDDGenEntryTbl VDHEXITTHREAD,           ORD_VDHExitThread
VDDGenEntryTbl VDHFSCTL,                ORD_VDHFSCtl
VDDGenEntryTbl VDHREGISTERAPI,          ORD_VDHRegisterAPI
VDDGenEntryTbl VDHCHECKVPMEXCEPT,       ORD_VDHCheckVPMExcept
VDDGenEntryTbl _em86Is32Sel,            ORD__em86Is32Sel
VDDGenEntryTbl _nulroutine,             ORD__em86Is32Sel+1     ;reserved 86481
VDDGenEntryTbl VDHWAITRAMSEM,           ORD_VDHWaitRamSem               ;86481
VDDGenEntryTbl _nulroutine,             ORD_VDHWaitRamSem+1    ;reserved 86481
VDDGenEntryTbl VDHGetFlags,             ORD_VDHGetFlags                 ;93273
VDDGenEntryTbl VDHVMDETACH,             ORD_VDHVMDetach                 ;73080
VDDGenEntryTbl VDHALLOCSHAREDMEM,       ORD_VDHAllocSharedMem
VDDGenEntryTbl VDHFREESHAREDMEM,        ORD_VDHFreeSharedMem
VDDGenEntryTbl VDHALLOCUSERMEM,         ORD_VDHAllocUserMem       ;141181
VDDGenEntryTbl VDHFREEUSERMEM,          ORD_VDHFreeUserMem        ;141181
VDDGenEntryTbl VDHSETUSERMEM,           ORD_VDHSetUserMem         ;141181
VDDGenEntryTbl VDHQUERYUSERMEM,         ORD_VDHQueryUserMem       ;141181
VDDGenEntryTbl VDHQUERYARENA,           ORD_VDHQueryArena         ;141181
VDDGenEntryTbl VDHSETMAXFILEHANDLES     ORD_VDHSetMaxFileHandles  ;141181


Procedure       _nulroutine,near,local
        ret
EndProc         _nulroutine

EndCode

        END
