        page    78,132
        title   inidin2, Initialize OS2 - Part 2
SCCSID  equ     "@(#)inidin2.asm        6.19 92/03/18"
;                 IBM Confidential
;
;           Copyright (c) IBM Corporation  1987, 1990
;                     All Rights Reserved
;
;       ENTRY POINTS: syiInitOS2Components
;                     syiInitDataStructures
;                     syiInitProcess
; Revision History:
; ID       Date     Description
; ----     -------- --------------------------------------------------------
; D1357    9/3/91   DCR 1357 Suppress boot messages
; 26214    7/14/92  Feature 26214, INT 10H support for XGA DMQS
; 55717    10/30/92 Family 1 POS support for VBIOS
;          05/13/93 FJS Added 32-bit APM BIOS Support.
; 87349    11/17/94 Added AltF1 loop for fast processors
; 121283   05/17/95 Removed code fix from 87349 due to conflict with Warp upgrades.
; 137768   10/01/95 LRN Added security changes.                          @SEC
; 150691   04/08/96 Changes to AltF1 - addition of snoop overrides       ; 150691
; d151440  04/10/96 FJS Added APM BIOS 1.1 Support.
; 152533   04/23/96 Add support for DOS_MODE= environment variable
; 147968   5/11/96  RJM Change FSD and DD system owners to use HMTEs
; 159047   7/11/96  WG  Accurate CPU Initialization
; 159589   7/14/96  BHM Added IODELAY for fast processor and ALTF1 recovery.
;---------------------------------------------------------------------------

        .sall
        .xlist
        .xcref
        include basemid.inc           ; Message IDs
        include dosseg.inc            ; Kernel segments
        include basemaca.inc          ; Kernel macros
        include fnoinit.inc
        include osmaca.inc            ; Kernel macros
        include mi.inc
        include harderr.inc
        include infoseg.inc
        include dossymc.inc
        include inicfg.inc            ; CONFIG.SYS data structures
        include inisms.inc            ; SysInit Message Segment
        include osconst.inc
        include pgexport.inc
        include protmode.inc          ; Protect mode data structures
        include seldesc.inc           ; descriptor data
        include selxport.inc
        include sas.inc               ; System Anchor Segment
        include sicg.inc              ; SICG packets
        include struc.inc             ; Structured assembler macros
        include virtsym.inc           ; SegAlloc flags
        include vmowner.inc           ; Memory ownership definitions
        include vmexport.inc          ; Defs for SELAllocKHB
        include fsc.inc               ; for FSD loading
        include argframe.inc          ; fsa_args
        include ldrvars.inc           ; ste fields
        include tkexport.inc          ; TCB
        include ldrxport.inc          ; STRUC ldrrei_s
        include tkthread.inc          ; Thread creation structure
        include kmode.inc             ; sef stack frame
        include doshlp.inc            ; DosHlp's info
        include sysinvar.inc          ; Definition of DOSHLP_CODESEL
        include error.inc
        include devclass.inc
        include initmac.inc
        include config.inc            ; DevConfigTbl data structure
        include iodelay.inc
        include inialtf1.inc
        include initoken.inc                                            ;152533
        .cref
        .list

        ModName  , FNO_INIDIN2_ASM
        CpuMode 386                     ; Here goes nothing!

        subttl  Data Structures

;       Referenced fields within the PTDA

        ReferTask       AutoFail,BYTE   ; AutoFail PTDA Variable
        ReferTask       CurrTCB,WORD    ; Offset of current TCB
        ReferTask       CurrTSD,WORD    ; Offset of current TSD
        ReferTask       JFN_Flg_Ptr,DWORD ; pointer to flags for JFN
        ReferTask       JFN_Length,WORD ; Length of file handle table
        ReferTask       JFN_pTable,DWORD; pointer to file handle table
        ReferTask       JFN_Table,BYTE  ; default table of file handles
        ReferTask       JFN_Flags,BYTE  ; default table of file handles flags
        ReferTask       LCurDrv,BYTE
        ReferTask       PCurDrv,BYTE
        ReferTask       ptda_handle,WORD
        ReferTask       ptda_environ,WORD
        ReferTask       ptda_pTCBHole,DWORD
        ReferTask       ptda_pTCBHead,DWORD
        ReferTask       ptda_cTCB,WORD

        extrn           RmSelLstNum:ABS ; Number of selectors in RmSelLst

;       Referenced fields within the Kernel Data Segments

        ReferGlobal     SISData,BYTE            ;@PAA04757A - for SIS_BootDrv
        ReferGlobal     ABIOS_present,BYTE
        ReferGlobal     ArenaInfo,DWORD ; pointer to arena info array
        ReferGlobal     SISData,BYTE            ;system infoseg
        ReferGlobal     DevHlp,DWORD
        ReferGlobal     GlobalAutoFail,BYTE     ; From CONFIG.SYS AUTOFAIL
        ReferGlobal     mFSD_FLAG,BYTE
        ReferGlobal     MFSD_Stage,BYTE
        ReferGlobal     MaxSec,WORD
        ReferGlobal     NumIORipl,BYTE          ; number of RIPL reserved drives
        ReferGlobal     pVPBBuf,DWORD   ; pointer to VPB buffer for I/O
        ReferGlobal     fIBMSystem,WORD   ; pointer to VPB buffer for I/O

if RAS
        ReferGlobal     ras_stda_addr,WORD ; STDA selector
        ReferGlobal     ras_stda_phys,WORD ; STDA segment
endif ;RAS

        ReferGlobal     RmSelLst,WORD   ; List of selectors for real-mode use
        ReferGlobal     SAS_dd_area,BYTE
        ReferGlobal     SAS_file_area,BYTE
        ReferGlobal     SAS_RAS_area,BYTE
        ReferGlobal     _SMswapping,BYTE
        ReferGlobal     TaskData,WORD
        ReferGlobal     LoadDevDrv,BYTE
        ReferGlobal     DHF,DWORD
;147968       ReferGlobal     _LDRFSDOwner,WORD       
        ReferGlobal     DiskDCTable,BYTE
        ReferGlobal     DevConfigTbl
        ReferGlobal     _twodiskboot,WORD
        ReferGlobal     RealInitDS,WORD          ;Feature 74378

        ReferInitGlobal OEM_config,WORD
        ReferInitGlobal CFG_Buffers,WORD
        ReferInitGlobal CFG_DiskCache,DWORD
        ReferInitGlobal CFG_DiskThresh,WORD                              ;@9312
        ReferInitGlobal CFG_LazyWrite,BYTE
        ReferInitGlobal CFG_ProtectOnly,BYTE
        ReferInitGlobal error_messages_displayed,byte

if RAS
        ReferInitGlobal CFG_TraceBits,BYTE
        ReferInitGlobal CFG_TraceBuf,WORD
endif

        ReferInitGlobal Config_Sys_Data,WORD
        ReferInitGlobal _vaArenaInfo,DWORD
        ReferInitGlobal SIFSRoutines,WORD
        ReferInitGlobal syiHighMem,WORD
        ReferInitGlobal syiLowMem,WORD
        ReferInitGlobal syiMessageSelector,WORD
        ReferInitGlobal fscNameList,BYTE
        ReferInitGlobal fscInitTemplate,BYTE
        ReferInitGlobal mfscNameList,BYTE
        ReferInitGlobal mfscInitTemplate,BYTE
        ReferInitGlobal pDosLoadModule,DWORD
        ReferInitGlobal pDosFreeModule,DWORD
        ReferInitGlobal tbl_mFSD_failure,BYTE
        ReferInitGlobal ConfigSysFilename,BYTE   ;Feature 74378

        ReferInitGlobal RMSysCmdLine,BYTE       ; 150691
        ReferInitGlobal YesNoTable,BYTE                                 ;152533

        ReferGDT        GDT,BYTE
        ReferGDT        GDT_DOSSICG,WORD        ; DOSSICG call gate label
        ReferGDT        GDT_GDT,WORD
        ReferGDT        GDT_IDT,WORD
        ReferGDT        GDT_mFSD,WORD           ; SysInit's data descriptor

        ReferFlat       _pPTDACur,DWORD
        ReferFlat       _pTCBCur,DWORD
        ReferFlat       _ptcbtkTSDDaemon,DWORD
        ReferFlat       _pTSDCur,DWORD

ifdef PERFVIEW
        ReferFlat       fbPvwPatch,byte
endif

        ReferFlat       _BasicHWConfig,word      ; pd
        ReferFlat       _fhybernation,DWORD                             ;152533

;       External Routines Called or Referenced

        extrn           GDTAllocN:near
        extrn           InitDeviceMgr:near
        extrn           InitFileSystem:near
        extrn           InitLIDTable:near
        extrn           InitNMI:near
        extrn           InitSem:near
        extrn           InitTempBuffers:near
        extrn           DBCSTableInit:near
        extrn           LDRSetMiniFileIO:near
        extrn           ModeSWInit:near
        extrn           MONINIT:near
        extrn           _PGInit:near
        extrn           _PGSwitchInit:near
        extrn           _PGSwitchContextInit:near
        extrn           PhysToVirtInit:near
        extrn           ProcDataResize:near
        extrn           ProcInit:near
        extrn           Get_Machine_Info:near    ;Defect 89875

if RAS
        extrn           RASSTIP:near
endif ;RAS

        extrn           SYIAbort:near
        extrn           syiConfigParse:near
        extrn           SYISaveMessage:near
        extrn           syiDisplayMessage:near
        extrn           syiPauseOnError:near
        extrn           _VMCreatePseudoHandle:near
        extrn           _VMInit:near
        extrn           _VMInitTask:near
        extrn           _PGAgerInit:near
        extrn           InitFSCTemplate:near
        extrn           _StartINITCODE:near
        extrn           SYISaveMessageID:near
        extrn           ProtModeIC:near            ;##AW
        extrn           RealModeIC:near            ;##AW
        extrn           _SELFreeKHB:near           ;26214
        extrn           _SELAllocKHB:near          ;26214
        extrn           syiSwapDiskette:near
        extrn           SYICloseFile:near          ;LieList
        extrn           SYIOpenFile:near           ;LieList
        extrn           SYIReadFile:near           ;LieList
        extrn           Int2Ascii:near
        extrn           Config_CompareStrings:near                      ;152533

ifdef PMDEBUG
        extrn           DebugMovedGDTIDT:near
        EXTRN32         _tkKDBDaemon
endif

        EXTRN32         _SCHSlotSetPriority
        EXTRN32         _TKCreateThread
        EXTRN32         _tkTSDDaemon
        EXTRN32         _kmCTXHDaemon
        EXTRN32         _LazyWriter
        EXTRN32         _AsyncRead
        EXTRN32         _w_nt_SetExtLIBPATH        ;75220

        EXTRNFAR        syiBMPStandBy            ;D1357
        EXTRNFAR        syiBMPRestoreBIOSData    ;D1357
        EXTRNFAR        syiResetVideoMode        ;D1357

        EXTRNF32        InitNPX
        EXTRNF32        INTInit
;;;     EXTRNF32        LoadInit
        EXTRNF32        LDRUnSetMiniFileIO
        EXTRNF32        _PGInitBuf
        EXTRNF32        _PGInitInfoSegs
        EXTRNF32        PreLoadInit
        EXTRNF32         _SELReinit
        EXTRNF32        _SEMInitShrTbl
        EXTRNF32        _SIGInitContextHook
        EXTRNF32        _TKInit
        EXTRNF32        _TKPreInit
        EXTRNF32        _TKSchedInit
        EXTRNF32        _VMInitProtect
        EXTRNF32        LDRLibPathAlloc
        EXTRNF32        VDMMGETPOSREGS
        EXTRNF32        _TKSetSSBase            ; see initmac.inc
        EXTRNF32        ldrLieListAlloc         ; LieList
        EXTRNF32        _KIEnableInit           ; D159047

        EXTRNFAR        VirtToLin
        EXTRNFAR        w_loadmodule
        EXTRNFAR        w_getprocaddr
        EXTRNFAR        w_SICG
        EXTRNFAR        GetDescInfo
        EXTRNFAR        SegAlloc
        EXTRNFAR        SegFree
        EXTRNFAR        SetDescInfo
        EXTRNFAR        syiABiosInit
        EXTRNFAR        syiInitSIFS
        EXTRNFAR        syiReInitSIFS
        EXTRNFAR        syiTermSIFS
        EXTRNFAR        syiProcess
        EXTRNFAR        w_FSAttach
        EXTRNFAR        ExitCritSecUnHoldSig
        EXTRNFAR        SelToSeg                     ;26214

        page
;Feature 74378 start
PORT_SYSB       EQU     61H     ; system control port B
SYSB_SPKENABLE  EQU     02H     ; speaker data enable (R/W)
SYSB_SPKGATE    EQU     01H     ; speaker timer gate enable (R/W)
;Feature 74378 end

INITDATA segment

;       Default LIBPATH= string

default_libpath      equ $            ; root directory of boot drive
default_drive_letter db  'a'          ; boot drive letter
                     db  ':\',0

w1024   dw           1024             ; constant for conversion from
                                      ;   K to bytes

;       For external libpath
Environ_String_Max      equ 1024
Environ_Buffer          db     Environ_String_Max+1 dup(?)
                                      ; buffer to hold parsed environment string
Environ_Keyword_Length  dw ?          ; the length of the environment variable
Environ_Argument_Length dw ?          ; the length of the entire environment string
BeginLibpath            db     'BEGINLIBPATH',0
EndLibpath              db     'ENDLIBPATH',0
DosMode                 db     'DOS_MODE',0                             ;152533

mfsd_filespec        db 'a:\mini_fsd.fsd',0

;       SICG packet to initialize a bimodal device driver
;
;       NOTE: This packet is used for functions 3, 4, 5, 6 and 8
;
;       For function 8 (complete FSD install.), only sicg_devhndl in
;       sicg_packet_3_d is used.

sicg_packet_3   dw         ?
sicg_packet_3_d sicg_pkt3  <>

;       SICG packet for use with fscCheck and fscAdd (see fsc.asm)

sicg_packet_9   dw         SICGFUN9
sicg_packet_9_d sicg_pkt9  <>

;       SICG packet to set up char table entries for base drivers

sicg_packet_10  dw         SICGFUN10

;       Message table for Kernel messages

        public  tbl_kernel_message
tbl_kernel_message SMT <,0>

;       Message table to Insufficent Storage message

tbl_insufficient_memory SMT <MSG_SYSINIT_MORE_MEM,0>

;       Message table for insufficient storage to start DOS Mode

tbl_dos_mode_too_big    SMT <MSG_SYSINIT_DOS_TOO_BIG,0>

;       Message table for DISKCACHE value too big

tbl_diskcache_too_big   SMT <MSG_SYSINIT_CANT_GET_CACHE,0>

;       Message table for general message that a file cannot be found

tbl_no_altf1_screen     SMT <MSG_SYSINIT_SFILE_NOT_FND,1> ; MSG 1518
                        SMT_Var  <AltF1File>
tbl_no_altf1mid_screen  SMT <MSG_SYSINIT_SFILE_NOT_FND,1> ; MSG 1518
                        SMT_Var  <ALTF1MID_filespec>

;       Size of stack allocated for the System Initialization Process

stack_size      equ     4096

IORB_CONFIGURATION     STRUC
  IORBLength      DW      ?
  UnitHandle      DW      ?
  CommandCode     DW      ?
  CommandModifier DW      ?
  RequestControl  DW      ?
  Status          DW      ?
  ErrorCode       DW      ?
  Timeout         DD      ?
  StatusBlockLen  DW      ?
  pStatusBlock    DW      ?
  Reserved_1      DW      ?
  pNxtIORB        DD      ?
  NotifyAddress   DD      ?
  DMWorkSpace     DB      20 DUP (?)
  ADDWorkSpace    DB      16 DUP (?)
  pDeviceTable    DD      ?
  DeviceTableLen  DW      ?
IORB_CONFIGURATION     ENDS

newIORB IORB_CONFIGURATION <0>

;Feature 74378 start

  public AltFxKeyPressed                         ;Feature 74378
  public AltF1Flags

savAltFxKeyPressed db 0                          ;159589
AltFxKeyPressed  db 0
AltF1Flags       db 0
  public AltF1CmdParms
  public AltF1xCmdParms
  public AltF1SecCmdParms
  public AltF1Parm

AltF1CmdParms          db "/C "
AltF1FileDir           db "\OS2\BOOT\"
AltF1File              db "ALTF1.CMD"
AltF1FileSpace         db " "        ;Must be NULL for syiOpenFile but
                                     ;space for command line.
AltF1Parm              db  ?
                       db  0

AltF1xCmdParms          db "/C "
AltF1xFileDir           db "\OS2\BOOT\"
AltF1xFile              db "ALTF1?.CMD",0

AltF1SecCmdParms        db "/C "                    ; @SEC
AltF1SecFileDir         db "\OS2\BOOT\"             ; @SEC
AltF1SecFile            db "ALTF1SEC.CMD",0         ; @SEC

;AltF1ScrTimerStart     db 0dh,0ah,"* Auto Recovery Set - This screen will stay for "
;AltF1ScrTimerValue     db 4 dup (0)
;AltF1ScrTimerEnd       db "seconds *",0dh,0ah
;L_TimerMsg             equ  $-AltF1ScrTimerStart

OS2VER_filespec       db "OS2VER",0        ;LieList file
ALTF1TOP_filespec     db "ALTF1TOP.SCR",0  ;ALT-F1 screen ;Feature 74378
ALTF1MID_filespec     db "ALTF1MID.SCR",0  ;ALT-F1 screen ;Feature 74378
ALTF1BOT_filespec     db "ALTF1BOT.SCR",0  ;ALT-F1 screen ;Feature 74378
ALTF1ARCH_filespec    db "ARCHBASE.$$$",0  ;ALT-F1 archive file
ALTF1SCREENMAX   EQU  800h         ; Maximum characters read from files
                                   ; to display on screen
ALTF1_MissingFile     db 10 DUP (?)        ;ALT-F1 file missing message

WRTSTRING       DB      20h,07h,20h,07h,20h,07h,20h,07h
                DB      20h,07h,20h,07h,20h,07h,20h,07h,20h,07h
;Feature 74378 end

INITDATA ends


INITBSS segment

mfsd_objbuffer       db 200 dup(?)
        public  mFSD_Handle
mFSD_Handle         dw 0
RiplDeviceName      db 3 dup(?)


; Thread ID retured from _TKCreateThread when we start the aging thread.
; The ager is given sysinit's thread 1 and sysinit takes this thread.

SysInitThreadID       dw 0

;       Selectors used by the System Initialization Process
;       which are freed by SICG

        public  syiCodeSelector
syiCodeSelector  dw ?
        public  syiEnvironSelector
syiEnvironSelector dw ?

INITBSS ends


CONSTANTS segment
        public  sysini_handle
sysini_handle   dw      ?             ; handle for SysInit's PTDA
CONSTANTS ends


DATA segment
        public mifs_ptr
mifs_ptr        dd      0
        public _IsMiniIFS
_IsMiniIFS      db      0
        public pLAZCur
pLAZCur                 dd 0
        public DMQS_Sel              ;feature 26214
DMQS_Sel    DW    ?                  ;feature 26214
        public APM_Length            ;d151440
        public APM_CodeSeg
        public APM_DataSeg
        public APM_Offset
        public APM_Flags
        public APM_Level
        public APM_IdleHookRtn
        public APM_32CodeSeg
        public APM_32Offset

        public APM_CSegLength        ;d151440
        public APM_DSegLength        ;d151440

APM_Length      DW      APM_EndStruc - $ ;length of this info segment ;d151440

APM_CodeSeg     DW      0          ;RM code segment for 16-bit interface
APM_DataSeg     DW      0          ;RM data segment for 16/32-bit interface
APM_Offset      DW      0          ;offset for 16-bit interface
APM_Flags       DW      0          ;See APM specification
APM_Level       DW      0          ;major/minor level
APM_IdleHookRtn DF      0          ;16:32 entrypoint to APM device driver
APM_32CodeSeg   DW      0          ;RM code segment for 32-bit interface
APM_32Offset    DD      0          ;offset for 32-bit interface

APM_CSegLength  DW      0          ;code segment length ;d151440
APM_DSegLength  DW      0          ;data segment length ;d151440
APM_EndStruc    equ     $          ;d151440

        public _DDInitTime
_DDInitTime      db      1


DATA ends

;       Structure of a double word

doubleword struc
lsw        dw   ?                     ; least significant word
msw        dw   ?                     ; most significant word
doubleword ends

;       Equates used to modify the contents of the registers pushed
;       by a PUSHA instruction

restore_ax equ  word ptr [bp+14]
restore_bx equ  word ptr [bp+8]
restore_cx equ  word ptr [bp+12]
restore_di equ  word ptr [bp+0]

        FARCODE INIT
INITCODE segment


;***LP  syiInitDataStructures - initialize data structures
;
;       Initialize the major data structures used by the OS/2 Kernel
;
;       ENTRY   ArenaInfo contains the address of the arena information array
;               (SS)  = paragraph address of BIOS data segment
;               (EAX) = Base address of R0DS and R0CS
;               (EBX) = Offset of AI w.r.t. R0DS and R0CS
;       EXIT    NONE
;       USES    EAX, EBX, ECX, EDX, ESI, EDI, ESP,EBP, DS, ES, FS, GS, SS,Flags
;       EFFECTS The stack is switched to the SysInit process TSD kernel stack
;
;       call _PGInit(arenainfo array, linearbias) to initialize Page Manager
;
;       call syiDosHlpFix32 to convert 16:16 addresses of 32-bit DosHlp
;           functions to 32 linear addresses
;
;       change to the System Initialization Process's Kernel stack
;       put the System Initialization's PTDA into the scheduler tables
;       invalidate the TASKAREA selector
;
;       call _VMInit to initialize the Virtual Memory Manager
;       call _SELReinit
;       call PhysToVirtInit to initialize the PhysToVirt Device Helper
;       call _PGInitBuf
;
;       call syiSegAlloc(SMS size,movable) to allocate the SysInitMessage Seg
;       call syiInitSIFS to initialize the SysInit Mini File System
;       call    syiCheckForAltF1 ;use Alternate CONFIG.SYS?
;       if ABIOS is supported
;         call syiAbiosInit to Initialize the ABIOS
;         if no error,
;            call syiReInitSIFS
;         endif
;       endif
;       call syiOS2VER to read the LieListFile
;       if two diskette boot
;          call syiSwapDiskette to prompt user to Swap diskettes
;       endif
;       call syiConfigParse to read and parse the CONFIG.SYS file
;       call VMInitProtect to free memory if NoProtect specified
;
;       call syiCheckMemorySize to insure enough memory to start the system
;
;       if (ABIOS is present)
;           call syiABiosInit to init ABIOS real and protected mode data
;           call syiReInitSIFS to reinitialize the SysInit Mini File System
;
;       if (LIBPATH= was specified)
;           copy the LIBPATH= string
;       else
;           set the LIBPATH= string to boot drive:\
;       call syiSegAlloc to allocate the libpath segment
;       copy the LIBPATH= string to the libpath segment
;
;       if (this is not a protect mode only system)
;           call GDTAllocN to allocate GDT selectors for SysInit

Procedure syiInitDataStructures
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

;       push parameters for _PGInit.  Call is delayed for a few lines.

        neg     eax                     ; eax = linear bias for _PGInit

        FlatContext <ds,es>,cx          ; set up for C calls

;       Initialize Page Manager: enable paging, initialize data structures

        CCALL32 _PGInit,<ebx,eax>       ; _PGInit(parenainfo, linearbias)

;       Paging is enabled, convert 16-bit addresss in DHF to 32-bit linear
;       address to be used in FLAT: (starting with DosHlpInitInterrupts)

        call    syiDosHlpFix32

;       Initialize _pPTDACur, _pTCBCur, and some ptda fields.
;       Switch to ptda stack (GSEL GDT_PTDA).
;       WARNING:
;           _PGSwitchInit knows that (when entered) the stack looks like:
;               dd      far 16 bit return address (to os2ldr)           (high)
;               dw      near 16 bit return address (to caller of this routine)
;               dd      near 32 bit return address (to this routine's thunk)
;                                                                       (low)

        CCALL32 _PGSwitchInit,,<nocall,noalignesp>  ; _PGSwitchInit()
    assume ss:TASKAREA

;       Running on the ptda stack.  The asterisked values will be replaced
;       with sysinit's stack and entry point prior to executing the RETFD
;       at the end of the caller of this routine.
;           The stack now looks like:
;               dd      *os2ldr's ss                                    (high)
;               dd      *os2ldr's esp
;               dd      *os2ldr's cs (actually it's ss)
;               dd      *os2ldr's eip
;               dw      near 16 bit return address (to caller of this routine)
;                                                                       (low)
;
;       Pop off the return address and enter kernel mode.  This must be
;       done before any page faults are taken.

        pop     ax                      ; the macro doesn't trash AX
        KMEnterKmodeCallGate 0,nosti,PASCAL ; EnterKmode, but don't enable ints
        push    ax                      ; put the return address back on stack

;       Initialize the Virtual Memory Manager
;       VMInit(linear arenainfo array pointer)

        DosInitContext fs
        CCALL32 _VMInit,<fs:[_vaArenaInfo]>
    assume fs:nothing

ifdef PERFVIEW
;       Enable Perfview hook patching now that Virtual Memory Manager is
;       initialized (Perfview patching requires VMMapAlias()).  Note that
;       (DS) = Flat from previous KMEnterKmodeCallGate.

        mov     [fbPvwPatch],FALSE
endif

        CALLF32 _SELReinit              ; _SELReinit(void): Reinitialize GDT
ifdef  PMDEBUG
        call    DebugMovedGDTIDT        ; tell debugger GDT moved
endif

;       Initialize the PhysToVirt data structures

        call    PhysToVirtInit          ; PhysToVirtInit(void)

;       Initialize Page Manager PGAllocBuf buffers

        CALLF32 _PGInitBuf              ; _PGInitBuf(void)

;       Initialize the System Init task's Memory Management data

        sub     sp,4                    ; Make room on stack
        movzx   eax,sp
        SSToDS  eax

;       rc = VMCreatePseudoHandle,(laddr, hobowner, &hob)

        CCALL32 _VMCreatePseudoHandle,<[_pPTDACur], TKPTDAOWNER, eax>
        or      eax,eax                 ; Successful?
        pop     eax                     ; (AX) = handle
        .if nz
            Panic <"InitSysInitProc: VMCreatePseudoHandle">
        .endif
        mov     ss:[ptda_handle],ax     ; Put own PTDA handle in PTDA

        CCALL32 _VMInitTask,<[_pPTDACur], VMAT_PRIV_TILED>

;       Allocate the global and local infosegs

        CALLF32 _PGInitInfoSegs

;       Adjust the TaskGroup segment.

        CALLF32 _TKPreInit

;       Set up PTDA, LDT variables

        CCALL32 _PGSwitchContextInit,<[_pTCBCur]>

;       Put the System Initialization Process into the Scheduler Tables

        CALLF32 _TKSchedInit

;       Allocate the System Initialization Message Segment
;       call SegAlloc(size,GDT selector,ring 3 data,system is owner,flags)
;         (WARNING: AX, BX, CX, DX, SI, DI, DS, and ES are modified)

        xor     eax,eax               ; AX:BX = size of segment
        mov     bx,SMS_default_size
        mov     si,HF_MOVABLE         ; SI = flags (movable)
        mov     ch,D_DATA3            ; CH = access rights (ring 3 data)
        mov     cl,SA_GDT             ; CL = flags (GDT selector)
        mov     di,INITOWNER          ; DI = owner
        CALLFAR SegAlloc
    assume ds:nothing, es:nothing
        .if     c                     ; did the SegAlloc fail?
          Panic <"Inidinit: SMS SegAlloc"> ; yes, halt the system
        .endif
        DosInitContext es
        mov     syiMessageSelector,bx ; Save the selector
        mov     es,bx                 ; initialize the segment
        assume  es:nothing

;       Initialize the header fields in the message segment

        mov     es:[0].SMS_Size,SMS_default_size
        mov     es:[0].SMS_First,0
        mov     es:[0].SMS_Last,0
        mov     es:[0].SMS_Free,size SMS

;       Preinitialize the Loader
        push    ds
        FlatContext <ds,es>,ax          ; set up for C call
        CALLF32 PreLoadInit
    assume es:nothing
        pop     ds
    assume ds:DOSINITDATA

;       Initialize mini-FSD
        call    syiMiniFSD

;       Read and parse the CONFIG.SYS file

        DosContext ds
        CALLFAR syiInitSIFS      ; initialize the sysinit file system

        DosInitContext ds                   ;159589 begin

        push     eax                        ;159589 
        push     ebx                        ;159589 
        push     ecx                        ;159589 
        mov      ax,8                       ;159589 select a threshold 
        .if      <ax le DOSIODELAYCNT>      ;159589 for fast guys only
           xor   ecx,ecx                    ;159589 clear counter
           mov   bx,DOSIODELAYCNT           ;159589 load IO delay
           shl   ebx,7                      ;159589 boost the delay amount
           .repeat                          ;159589 try for 1 sec
               kIODelay                     ;159589 delay 500ns
               call     syiCheckForAltF1    ;159589 get keystroke or archive file
	       .if <savAltFxKeyPressed gt 0>;159589 check for either above
		    mov ecx, ebx            ;159589 if either then quit
	       .endif                       ;159589 end checking
               inc      ecx                 ;159589 update counter
           .until <ecx gt ebx>              ;159589 quit if delayed or key/file
        .endif                              ;159589 end checking
        pop      ecx                        ;159589 
        pop      ebx                        ;159589 
        pop      eax                        ;159589

	.if <savAltFxKeyPressed eq 0>       ;159589

          call    syiCheckForAltF1 ;use Alternate CONFIG.SYS?
	
	.endif

        DosContext ds

;       Initialize the ABIOS real and protect mode data structures

        DosInitContext es
        test    ES:[OEM_config], CFG_ABIOS_SUPPORTED
        .if     <nz>

             CALLFAR syiABiosInit
             .if   <nc>
                mov     ABIOS_present,1 ; ABIOS present
                mov     cx,fIBMSystem   ; IBM/OEM ABIOS indicator       ;D90588
                FlatContext es
                or      es:[_BasicHWConfig],CFG_ABIOS_PRESENT
                or      es:[_BasicHWConfig],cx                          ;D90588

                CALLFAR syiReInitSIFS   ; initialize the sysinit file system

                DosInitContext es
                or      ES:[OEM_config],cx                              ;D90588
                or      ES:[OEM_config],CFG_ABIOS_PRESENT               ;D89875

                ; Get_Machine_Info needs DS=DosInitData and ES=DosGroup ;D89875
                ; They are reversed now, just XCGH                      ;D89875
                mov     ax,ds                                           ;D89875
                mov     bx,es                                           ;D89875
                mov     ds,bx                                           ;D89875
                mov     es,ax                                           ;D89875
                call    Get_Machine_Info  ; touch up Machine info pkt   ;D89875
                mov     ax,es             ; Restore DS                  ;D89875
                mov     ds,ax             ; (Don't care about ES)       ;D89875
             .endif
        .endif
        assume  es:nothing

;       Read OS2VER file    LieList

        call   syiOS2VER

;       Swap diskettes if needed

        mov  cx,_twodiskboot
        .if <nonzero cx>                   ; _twodiskboot?
           call         syiSwapDiskette ; yes, prompt for next diskette
        .endif

        call    syiConfigParse  ; process CONFIG.SYS

        FlatContext <ds,es>,bx

;       Free protected region area if NoProtect Specified

        CALLF32 _VMInitProtect          ; _VMInitProtect(void)

;       Allocate the PTDA and TCB BMP regions.

        FlatContext <ds>,ax
        CALLF32 _TKInit
    assume es:nothing
        DosContext  <ds>,ax

;       Make sure there is enough memory to start the system

        call    syiCheckMemorySize

        ; r205 p055717
        ; The following section is used to decide if POS registers need
        ; to be collected for VBIOS POS emulation.  Originally, we only
        ; worked with machines with ABIOS present.  Now we add the AT-Class
        ; machines with Planar POS. Clone XGA-2 drove this issue.
        ;
        ;   IBM AT-class machines with Planar POS
        ;
        ;   Model SubModel  Name
        ;
        ;   0xF8     0x19   Model 35 or 40
        ;   0xF8     0x23   Model L40SX
        ;   0xF8     0x24   Model 35 or 40
        ;   0xF8     0x30   PS/1 386sx
        ;   0xF8     0x33   Model 30-386sx
        ;   0xF8     0x34   Model 25-386sx
        ;   0xF8     0x49   PS/ValuePoint
        ;   0xF8     0x97   PS/2 laptop
        ;

        cmp     ABIOS_present,1                       ; ABIOS machines
        je      short sids12

        cmp     DevConfigTbl.Config_model,0f8h        ; IBM 386/486 machines
        jne     short sids13

        mov     al,DevConfigTbl.Config_type
        cmp     al,019h                 ; Model 35/40 20Mhz
        je      short sids12
        cmp     al,023h                 ; Model L40sx
        je      short sids12
        cmp     al,024h                 ; Model 35/40 25Mhz
        je      short sids12
        cmp     al,030h                 ; PS/1 386SX
        je      short sids12
        cmp     al,033h                 ; Model 30-386sx
        je      short sids12
        cmp     al,034h                 ; Model 25-386sx
        je      short sids12
        cmp     al,049h                 ; PS/ValueLine
        je      short sids12
        cmp     al,097h                 ; PS/2 Laptop
        je      short sids12
        jmp     short sids13
sids12:
        FlatContext <ds,es>,ax  ; get the POS registers early
        CALLF32 VDMMGETPOSREGS
        DosContext  <ds>,ax
        DosInitContext es
sids13:
        call    syiDMQS                 ;feature 26214

        push    ds
        mov     bx,ss:[CurrTSD]         ; (SS:BX) = current TSD pointer
        mov     ss:[bx].TSDUserSS,ss

        pop     ds
        assume  ds:DOSGROUP

;       Find the length of the LIBPATH= string

        DosInitContext es
        mov     es,Config_Sys_Data    ; point to CONFIG.SYS data segment
        mov     si,es:[0].CFG_LibPath.CFG_Tail ; point to LIBPATH packet
        .if     <zero si>
          DosInitContext es
          mov   ax,[SISData].SIS_BootDrv        ;get the boot drive from
          add   al,'A' - 1                      ;the system infoseg
          mov   [default_drive_letter],al
          lea   di,default_libpath    ; set up default LIBPATH= string
        .else
          mov   di,es:[si].CFG_Path   ; point to LIBPATH= string
        .endif

        SaveReg <es,di>
        xor     ax,ax                 ; calculate length of string
        xor     ecx,ecx
        mov     cx,-1
        cld
        repne   scasb

        not     cx                    ; size in ecx

;       Allocate the libpath segment

        CALLF32 LDRLibPathAlloc

        RestoreReg <si,ds>            ; DS:SI = address of libpath string

        FlatContext     es
        mov     edi,eax               ; ES:EDI = address of _LDRLibPath

        mov     ah,'/'                  ; will save one clock per compare

sids0:  lodsb                           ; fetch a character
        cmp     al,ah                   ; is character / ?
        jne     short sids1             ;  no, skip ahead
        mov     al,'\'                  ; change '/' to '\'
sids1:  B1EMac stos byte ptr es:[edi]   ; copy a character
        or      al,al                   ; done with copy?
        jnz     short sids0             ;  no, loop for more

        assume  es:nothing

;       Allocate GDT selectors
;       call GDTAllocN(number of selectors,selector list)
;         (WARNING: AX, CX, and DI are modified)

        DosContext es
        mov     cx,RmSelLstNum                  ; (cx) = number of selectors
        mov     di,offset DOSGROUP:RmSelLst     ; (es:di) = selector array
        call    GDTAllocN

;       Allocate the Shared Semaphore Table

        FlatContext <ds,es>,ax                  ; set up for C call
        CALLF32 _SEMInitShrTbl                  ; allocate shared sem. table

;       Allocate Context hook for signals

        CALLF32 _SIGInitContextHook
        ret
EndProc syiInitDataStructures


;***LP  syiMiniFSD - Initialize mini File System Driver
;
;       Check if there exists mini-FSD. If there is no mini-FSD, return to
;       caller.  Otherwise, load the mini File System Driver and resolve the
;       exports and the imports relationships between the mini-FSD and OS/2.
;
;       ENTRY   [GDT_mFSD]  = address of mini-FSD
;               [mFSD_FLAG] = 0 for FAT boot system
;                           = boot mode flags for non FAT boot system
;                  bits 7-3 = 0
;                  bit  2   = 1 if mini-FSD is present
;                  bit  1   = 1 if boot volume is not local
;                  bit  0   = 1 if mini-FSD does NOT use mFSH_DOVOLIO function.
;               (DS)        = DosInitData
;       EXIT    NONE
;       USES    Flags

Procedure syiMiniFSD,,local
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        LocalVar segcount,WORD
        EnterProc
        SaveReg <ds,es>
        pusha
        DosContext es
        .if     <es:mFSD_FLAG ne 0> near  ;If Mini_FSD
          mov     bl,3                    ; (BL) = 4 special
          mov     es:[_IsMiniIFS],bl      ; faked kernel mode
          mov     es:LoadDevDrv,bl         ; tell DOSLOADMODULE load type
          mov     word ptr es:[mifs_ptr],0
          mov     word ptr es:[mifs_ptr+2],GSEL GDT_mFSD

          DosInitContext ds
          mov     si,offset mfsd_objbuffer        ; ds:si=address of object name buffer
          mov     ax,200                ; length of object name buffer

          push    ds
          pop     es
          mov     di,offset mfsd_filespec ; address of file specification
          CALLFAR w_loadmodule            ;destroys registers
          .if     c                     ; did the loadmodule fail?
            lea   si,tbl_mFSD_failure     ; Yes, handle the failure
            call  SYIAbort
          .endif

;147968          DosContext    ds,ax
;147968          inc   [_LDRFSDOwner]          ; inc after mini FSD load

          DosInitContext ds,ax
          mov     mFSD_Handle,bx           ; save handle

          mov     ax,bx
          xor     cx,cx                 ; indicate ring0

          call    InitFSCTemplate       ; construct FSC for fsd
          .if     c
            lea   si,tbl_mFSD_failure   ; abort if error
            call  SYIAbort
          .endif

  ;       Call DOSGETPROCADDR to get the addresses of all the procedures
  ;       that are required to be exported by a mFSD module. The returned
  ;       addresses will be placed in the FSCInitTemplate corresponding to
  ;       this FSD.

          mov     bx,offset DOSINITDATA:mfscNameList
          xor     dx,dx
          mov     dl,ds:[bx]              ; length of name
          mov     di,offset DOSINITDATA:mfscInitTemplate
          .while <nonzero dl>
            mov   ax,mFSD_Handle          ; module handle
            inc   bx                      ; ES:DI -> null terminated procname
            SaveReg <dx,bx,di>
            push  ds                      ; place the address...
            pop   es
            mov   di,bx                   ; ... to the procname on the stack
            CALLFAR w_getprocaddr
            .if     c                      ; did the getprocaddr fail?
              lea   si,tbl_mFSD_failure    ; Yes, handle the failure
              call  SYIAbort
            .endif

      save_addr2:
            DosInitContext ds
            RestoreReg <di>
            mov     ds:[di],ax              ; place the address dx:ax
            mov     ds:[di+2],dx            ; ... to the procaddr on the stack

            RestoreReg <bx,dx>
            add   di,4                    ; skip over to the next procaddr
            add   bx,dx                   ; skip over to the next procname
            mov   dl,ds:[bx]
          .endwhile

 ;*     the mini FSD code objects are ring 0 conforming
 ;*     the mini FSD data objects have DPL=3

          mov     ax,GSEL GDT_mFSD
          CALLFAR SegFree

          DosContext es
          mov     [_IsMiniIFS],0
        .endif
        popa
        RestoreReg <es,ds>
        LeaveProc
        ret
EndProc syiMiniFSD


;***LP  syiCheckMemorySize - Check memory size
;
;       Make sure there is enough memory to initialize the operating system.
;
;       ENTRY    ABIOS_present   indicates whether or not ABIOS is
;                                supported on this machine
;                CFG_DiskCache   contains the size of the disk cache
;                                buffers (in bytes)
;                CFG_ProtectOnly contains the PROTECTONLY=YES|NO flag
;                _SMswapping     contains the MEMMAN=SWAP|NOSWAP flag
;                                environment (in K bytes)
;                syiHighMem contains the high memory size
;                                (in K bytes)
;                syiLowMem       contains the low memory size
;                                (in K bytes)
;       EXIT    NONE
;       USES    Flags
;
;       memory requirement = 1024
;       if (swapping is turned off)
;           add 128 to memory requirement
;
;       total available memory = low memory + high memory
;
;       if (memory requirement > total available memory)
;           call SYIAbort(insufficient memory) to stop the system
;
;       if (the machine supports ABIOS and DISKCACHE was specified)
;           if (memory requirement + disk cache size > total memory)
;               call SYISaveMessage(cannot allocate disk cache)
;               set DISKCACHE value to 0

Procedure syiCheckMemorySize,,local
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

        SaveReg <ds,es>
        pusha

;       Calculate minimum memory requirement
;       BX = 1024 + 128 (if no swapping)

        DosContext es
        DosInitContext ds

        mov     bx,1024
        .if     <_SMswapping eq 0>
          add   bx,128
        .endif

;       Calculate total memory size
;       CX = low memory size + high memory size

        mov     cx,syiLowMem
        add     cx,syiHighMem

;       Make sure there is enough memory to start the system

        .if     <bx a cx>
          lea   si,tbl_insufficient_memory
          call  SYIAbort
        .endif

;       If DISKCACHE was specified, make sure there will still be
;       enough memory after the cache buffer is allocated

          mov   ax,CFG_DiskCache.lsw  ; convert DISKCACHE to K bytes
          mov   dx,CFG_DiskCache.msw
          div   w1024
          add   bx,ax
          .if   <bx a cx>
            lea si,tbl_diskcache_too_big
            call SYISaveMessage
            mov CFG_DiskCache.msw,0   ; indicate no diskcache requested
            mov CFG_DiskCache.lsw,0
            sub bx,ax
          .endif

        popa
        RestoreReg <es,ds>
        ret
EndProc syiCheckMemorySize


;***LP  syiInitOS2Components - Initialize CP/DOS components
;
;       Initialize the Kernel components of the operating system>
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    Flags
;
;       call InitLIDTable to initialize the Device Helper Manager
;       call InitTempBuffers to initialize the Temporary Buffer Manager
;       call INTInit to initialize the Interrupt Manager
;       call InitNMI to initialize the Non-Maskable Interrupt Manager
;       call ModeSWInit to initialize the Mode Switch Manager
;       call InitSem to initialize the Semaphore Manager
;       call InitNPX to initialize the Numeric Processor Extension Manager
;       call DBCSTableInit to initialize DBCS tables
;       call MONINIT to initialize the Monitor Dispatcher
;       call RASSTIP(size of trace buffer,event code array) to initialize
;            RAS System Trace
;       call ProcDataResize to resize the Kernel Data Segment (NOTE: This call
;            must follow the call to SchedInit)
;       call InitDeviceMgr to initialize the Device Manager (which loads and
;            initializes the base device drivers)
;       call syiTermSIFS to free all data areas allocated by the
;            System Initialization Mini File System
;       call SegFree(selector) to free the DOSCODE segment
;       call InitFileSystem(number of application buffers, maximum amount of
;            path cache memory) to initialize the File System (NOTE: This call
;            must follow the call to InitDeviceMgr which loads the base device
;            drivers)
;       ////call LoadInit to initialize the Dynamic Loader
;
;       if (any of the above routines returns a message ID)
;           call SYISaveMessageID(message ID) to save the identifier of the
;                message so it can be printed later

Procedure syiInitOS2Components
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:TASKAREA

        SaveReg <ds,es>
        pusha

        call    InitLIDTable          ; Initialize Device Helper Manager
        .if     c                     ; is there an error message?
          call  SYISaveMessageID ; yes, save the message ID
        .endif

        call    InitTempBuffers       ; Initialize the Temporary Buffer

        FlatContext <ds,es>,ax
        CCALL32 INTInit               ; Initialize the Interrupt Manager
    assume ds:nothing,es:nothing

        call    InitNMI               ; Initialize the NMI Manager
        .if     c                     ; is there an error message?
          call  SYISaveMessageID ; yes, save the message ID
        .endif

        call    ModeSWInit            ; Initialize the Mode Switch Managager
        .if     c                     ; is there an error message?
          call  SYISaveMessageID ; yes, save the message ID
        .endif

        call    InitSem               ; Initialize the Semaphore Manager

        SaveReg     <ds,es>
        FlatContext <ds>,ax
        CALLF32 InitNPX               ; Initialize the NPX Manager
        RestoreReg  <es,ds>
    assume ds:nothing,es:nothing
        .if     c                     ; is there an error message?
          call  SYISaveMessageID ; yes, save the message ID
        .endif

        call    DBCSTableInit         ; Initialize DBCS tables

        call    MONINIT               ; Initialize the Monitor Dispatcher

if RAS
        DosInitContext ds
        mov     ax,CFG_TraceBuf       ; AX = size of trace buffer
        lea     dx,CFG_TraceBits      ; DS:DX = address of trace event
        call    RASSTIP               ; Initialize RAS Trace
                                      ;         code table
    assume ds:nothing,es:nothing

        DosContext ds
        mov     ax,ras_stda_addr      ; copy STDA addresses to SAS
        mov     [SAS_RAS_area].SAS_RAS_STDA_p,ax
        mov     ax,ras_stda_phys
        mov     [SAS_RAS_area].SAS_RAS_STDA_r,ax

endif ;RAS

    assume ds:nothing,es:nothing

        DosContext ds
        call    ProcDataResize        ; resize the Kernel Data Segment

; Call LDRSetMiniFIleIO to give the loader the addresses to
; SysInit SIRead, SIOpen, SIClose, SIReadAt routines
SaveReg <esi,fs,gs>

;DosInitContext fs
;assume fs:DOSINITDATA

mov             si,DOSGDTDATA
mov             gs,si
mov             si,DOSINITDATA              ; get DOSINITDATA
mov             al,gs:[si].d_hiaddr         ; get bits 23..16 of base
mov             ah,gs:[si].d_extaddr        ; get bits 31..17 of base
shl             eax,10h                     ; position high 16 bits of base
mov             ax,gs:[si].d_loaddr         ; get bits 15..0 of base

mov             esi,eax                     ; save DOSINITDATA base
lea             eax,SIFSRoutines
;movzx           eax,offset SIFSRoutines
add             eax,esi                          ; add base
RestoreReg      <gs,fs,esi>

push            es
push            ds
FlatContext     <es,ds>

CCALL32         LDRSetMiniFileIO,eax
pop             ds
pop             es
    assume ds:nothing,es:nothing

        FlatContext <ds,es>,ax
;;;     CALLF32 LoadInit              ; Initialize the Dynamic Loader

        call    InitDeviceMgr         ; Initialize the Device Manager
                                      ;   and load the base device drivers
        .if     c                     ; is there an error message?
          call  SYISaveMessageID ; yes, save the message ID
        .endif

; Call LDRUnSetMiniFIleIO to unset addresses to
; SysInit _SIRead, _SIOpen, _SIClose, _SIReadAt routines

        SaveReg  <ds,es>
        FlatContext <ds,es>
        CALLF32 LDRUnSetMiniFileIO
        RestoreReg <es,ds>
        assume ds:nothing,es:nothing

        CALLFAR syiTermSIFS      ; Terminate the System Initialization
                                      ;   Mini File System

        DosInitContext ds
        mov     ax,[CFG_Buffers]
        xor     cx,cx
        call    InitFileSystem        ; Initialize the File System
    assume ds:nothing,es:nothing


        ;; turn on KI hooks if the Pentium instruction counter  ; D159047
        ;; is suppored or 8254 timer chip is installed.         ; D159047
        SaveReg <ds, es>                                        ; D159047
        FlatContext <ds,es>, ax                                 ; D159047
        CALLF32 _KIEnableInit                                   ; D159047
        RestoreReg <es, ds>                                     ; D159047


;       Add this FSD's FSC to the FSC segment.
        DosContext ds
        mov     [MFSD_Stage],2
        cmp     [mFSD_FLAG],0          ; Does it exist mini-FSD?
        jz      no_mfsd                 ; no, jump

        DosInitContext ds
        DosContext es
        SaveReg <ds>
        push    0
        push    0
        push    [DevHlp].msw
        push    [DevHlp].lsw        ; Push pointer to DevHelp call-gate
        push    0
        push    0
        mov     si,offset DOSINITDATA:fscInitTemplate
        call    DWORD ptr ds:[si].FS_INIT
    assume es:nothing
        RestoreReg <ds>
        .if     <nonzero ax>
          Panic <"Inidinit: Mini_FSD FS_INIT">
        .endif

        mov     sicg_packet_9_d.si9_funcnum,SICG_FSCADD ; perform fscAdd
        mov     si,offset DOSINITDATA:sicg_packet_9
                            ; ds:si = address of packet
        CALLFAR w_SICG
        .if     <nonzero ax>
          Panic <"Inidinit: SICG_FSCADD">
        .endif

        DosContext ds
        test    [mFSD_FLAG],2           ; Remote IPL ?
        jz      no_mfsd                 ; no, skip around reserving drives
        mov     cl,[NumIORipl]
        DosInitContext ds
        xor     ch,ch
        jcxz    no_mfsd

        xor     ax,ax
        sub     sp,FSA_ArgWords
        mov     bp,sp
        mov     [bp].lsw,ax             ; initialize reserved dword to 0
        mov     [bp].msw,ax
        mov     [bp].FSA_iOpFlag,ax     ; attach function
        mov     [bp].FSA_cbDataLength,ax; 0 data length
        mov     [bp].FSA_pDataBuffer.Offst,ax
        mov     [bp].FSA_pDataBuffer.Segmt,ax
        DosInitContext es
        mov     di,offset DOSINITDATA:RiplDeviceName
        mov     [bp].FSA_szDeviceName.Offst,di
        mov     [bp].FSA_szDeviceName.Segmt,ds

; Initialize drive to drive set up by MFS_INIT

        DosContext ds                                        ; @PAA04757A
        mov     ax,ds:[SISData].SIS_BootDrv                  ; @PAA04757A
        DosInitContext ds                                    ; @PAA04757A
        add     ax, "A" - 1                                  ; @PAA04757A
        mov     byte ptr [di], al       ; es:di->device name ; @PAA04757A
        mov     byte ptr [di+1],":"
        mov     byte ptr [di+2],0

        ; Get FSD name pointer and store it in the structure

        mov     si,offset DOSINITDATA:fscInitTemplate
        lds     si,ds:[si].FS_NAME
    assume ds:nothing
        mov     [bp].FSA_szFSDName.Offst,si
        mov     [bp].FSA_szFSDName.Segmt,ds
        mov     bx,bp                   ; ss:bx->FSAAttachStruc
next_attach:                            ; ds:si->FSDName
        xor     ax,ax                   ; attach function
        SaveReg <cx,es,di,ds,bx>        ; es:di->DeviceName
        CALLFAR w_FSAttach
        RestoreReg <bx,ds,di,es,cx>
        .if     <c>
          Panic <"Inidinit: w_FSAttach">
        .endif
        DosInitContext ds
        inc     byte ptr es:[di]        ; Next drive Number
        loop    next_attach
        add     sp,FSA_ArgWords

no_mfsd:
    assume ds:nothing,es:nothing

        popa
        RestoreReg <es,ds>
        ret
EndProc syiInitOS2Components

;***LP  syiInitInt13Thread - Initialize System Initialization process    ;@xxxx
;                                                                        ;@xxxx
;       Initiates creation of mini VDM to provide Int 13 I/O Services.   ;@xxxx
;       Currently called from INITDSK(DSKINIT.ASM).                      ;@xxxx
;                                                                        ;@xxxx
;                                                                        ;@xxxx
;       ENTRY                                                            ;@xxxx
;       EXIT                                                             ;@xxxx
;       USES    EAX, EBX, ECX, EDX, ESI, EDI, DS, ES, FS, GS, Flags      ;@xxxx
;       EFFECTS                                                          ;@xxxx
                                                                         ;@xxxx
Procedure syiInitInt13Thread                                             ;@xxxx
                                                                         ;@xxxx
    assume ds:DOSGROUP, es:nothing, fs:nothing, gs:nothing, ss:TASKAREA  ;@xxxx
                                                                         ;@xxxx
        LocalVar  ResultCode, DWORD                                      ;@xxxx
                                                                         ;@xxxx
        EnterProc                                                        ;@xxxx
                                                                         ;@xxxx
        SaveReg     <ds,es>                                              ;@xxxx
;                                                                        ;@xxxx
;       Some obscure field in the PTDA (seltss) is set                   ;@xxxx
;       by this worker routine!                                          ;@xxxx
;                                                                        ;@xxxx
        call    ProcInit                                                 ;@xxxx
                                                                         ;@xxxx
;       Initialize the process handle table (JFN) in the PTDA for the    ;@xxxx
;       System Initialization Process                                    ;@xxxx
                                                                         ;@xxxx
        mov     ss:[JFN_Length],FILPERPROC ; number of table entries     ;@xxxx
                                                                         ;@xxxx
        mov     ss:[JFN_pTable].msw,ss  ; point to JFN table             ;@xxxx
        mov     ss:[JFN_pTable].lsw,offset TASKAREA:JFN_Table            ;@xxxx
                                                                         ;@xxxx
        mov     ss:[JFN_Flg_Ptr].msw,ss                                  ;@xxxx
        mov     ss:[JFN_Flg_Ptr].lsw,offset TASKAREA:JFN_Flags           ;@xxxx
                                                                         ;@xxxx
        RestoreReg  <es,ds>                                              ;@xxxx
        LeaveProc                                                        ;@xxxx
        ret                                                              ;@xxxx
                                                                         ;@xxxx
EndProc syiInitInt13Thread

;***LP  syiInitProcess - Initialize System Initialization process
;
;       Establish the multitasking environment, start the Scheduler running,
;       and set up to invoke System Initialization Process
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    EAX, EBX, ECX, EDX, ESI, EDI, DS, ES, FS, GS, Flags
;       EFFECTS Stack set up for a RETURN FAR to invoke the SysInit Process
;
;       initialize process handle table (JFN table)
;       call ProcInit to intialize threads 0 and 1
;       call _SCHSlotSetPriority to set thrd1 priority regular class, level 0
;       call syiCreateEnvironment to create the sysinit environment
;       call SegAlloc(stack size,ring 3 data,LDT descriptor,current PTDA) to
;            allocate a stack segment for the System Initialization Process
;       if (the allocate request fails)
;           call IntErr ('Inidinit: SegAlloc failed') to halt the system
;       put the SS and SP values for the stack segment on the stack

Procedure syiInitProcess
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:TASKAREA

        ArgVar sip_sef,<SIZE sef_s>     ; sef stack frame put by KMEnterKmdeCallgate
        ArgVar sip_esp,dword
        ArgVar sip_ss,dword
        LocalVar sip_bp,bp              ; Caller's BP
        LocalVar sip_ptcb,DWORD         ; Place to return TCB pointer
        LocalVar sip_ti,<SIZE tkthrd_s> ; Thread info buffer

        EnterProc

        DosContext ds
        mov     ax,[SISData].SIS_BootDrv ;put boot/default drive number
        dec     al                      ; into the PTDA
        mov     ss:[LCurDrv],al
        mov     ss:[PCurDrv],al

        mov     al,GlobalAutoFail       ; put AUTOFAIL from CONFIG.SYS
        .if <nonzero al>                ;  into the PTDA
          or    al,DOSERR_INHERIT
          or    al,DOSERR_EXCEPTION_FLAG
        .endif
        mov     ss:[AutoFail],al

;**@xxxx;       Initialize the process handle table (JFN) in the PTDA for the
;**@xxxx;       System Initialization Process
;**@xxxx
;**@xxxx        mov     ss:[JFN_Length],FILPERPROC ; number of table entries
;**@xxxx
;**@xxxx        mov     ss:[JFN_pTable].msw,ss  ; point to JFN table
;**@xxxx        mov     ss:[JFN_pTable].lsw,offset TASKAREA:JFN_Table
;**@xxxx
;**@xxxx        mov     ss:[JFN_Flg_Ptr].msw,ss
;**@xxxx        mov     ss:[JFN_Flg_Ptr].lsw,offset TASKAREA:JFN_Flags

;       Initialize threads 0 (dummy) and 1 (System Initialization)

;**@xxxx        call    ProcInit

;       Make the sysinit thread priority regular class level 0

        FlatContext <ds,es>,ax
        CCALL32 _SCHSlotSetPriority,<1, 0200h>

;       Create TSD daemon

        xor     eax,eax
        mov     sip_ti.ti_fs,ax         ; Internal thread
        mov     sip_ti.ti_pbuf,eax      ; No argument base
        mov     sip_ti.ti_cbbuf,eax     ; No bytes to copy
        mov     sip_ti.ti_ustart.ptr_flat,offset FLAT:_tkTSDDaemon

        SSToDS  edx,sip_ti              ; (EDX) = thread info pointer
        CCALL32 _TKCreateThread,<[_pPTDACur], edx, \
                                 <offset FLAT:_ptcbtkTSDDaemon>, STATE_READY>

        or      eax,eax                 ; Success?
        jnz     sispie                  ;  no, internal error

;       Create global context hook daemon

        xor     eax,eax
        mov     sip_ti.ti_fs,ax         ; Internal thread
        mov     sip_ti.ti_pbuf,eax      ; No argument base
        mov     sip_ti.ti_cbbuf,eax     ; No bytes to copy
        mov     sip_ti.ti_ustart.ptr_flat,offset FLAT:_kmCTXHDaemon

        SSToDS  ecx,[sip_ptcb]          ; (ECX) = thread TCB pointer
        SSToDS  edx,[sip_ti]            ; (EDX) = thread info pointer
        CCALL32 _TKCreateThread,<[_pPTDACur], edx, ecx, STATE_READY>

        or      eax,eax                 ; Success?
        jnz     sispie                  ;  no, internal error

ifdef PMDEBUG
;       Create KDB daemon

        mov     sip_ti.ti_fs,ax         ; Internal thread
        mov     sip_ti.ti_pbuf,eax      ; No argument base
        mov     sip_ti.ti_cbbuf,eax     ; No bytes to copy
        mov     sip_ti.ti_ustart.ptr_flat,offset FLAT:_tkKDBDaemon

        SSToDS  ecx,[sip_ptcb]          ; (ECX) = thread TCB pointer
        SSToDS  edx,[sip_ti]            ; (EDX) = thread info pointer
        CCALL32 _TKCreateThread,<[_pPTDACur], edx, ecx, STATE_READY>

        or      eax,eax                 ; Success?
        jnz     sispie                  ;  no, internal error
endif
        DosInitContext ds
        mov     ax,[CFG_DiskCache.lsw]
        or      ax,[CFG_DiskCache.msw]
        jz      sisp2
        FlatContext <ds,es>,ax
        xor     eax,eax
        mov     sip_ti.ti_fs,ax         ; Internal thread
        mov     sip_ti.ti_pbuf,eax      ; No argument base
        mov     sip_ti.ti_cbbuf,eax     ; No bytes to copy
        mov     sip_ti.ti_ustart.ptr_flat,offset FLAT:_LazyWriter

        SSToDS  ecx,[sip_ptcb]          ; (ECX) = thread TCB pointer
        SSToDS  edx,sip_ti              ; (EDX) = thread info pointer
        CCALL32 _TKCreateThread,<[_pPTDACur], edx, ecx, STATE_READY>

        or      eax,eax                 ; Success?
        jnz     sispie                  ;  no, internal error
        mov     eax,[sip_ptcb]          ;  save the lazywrite tcb for
        DosContext es                   ;  reporting errors
        mov     es:[pLAZCur],eax
        ASSUME ES:NOTHING
        FlatContext <es>

sisp1:  xor     eax,eax
        mov     sip_ti.ti_fs,ax         ; Internal thread
        mov     sip_ti.ti_pbuf,eax      ; No argument base
        mov     sip_ti.ti_cbbuf,eax     ; No bytes to copy
        mov     sip_ti.ti_ustart.ptr_flat,offset FLAT:_AsyncRead

        SSToDS  ecx,[sip_ptcb]          ; (ECX) = thread TCB pointer
        SSToDS  edx,sip_ti              ; (EDX) = thread info pointer
        CCALL32 _TKCreateThread,<[_pPTDACur], edx, ecx, STATE_READY>

        or      eax,eax                 ; Success?
        jnz     sispie                  ;  no, internal error
sisp2:

;       Create the aging thread.  We must use thread 1 (the currently
;       running thread) for the ager so we don't kill our thread 1 when the
;       rest of sysinit dies.

        FlatContext <ds,es>,ax
        xor     eax,eax
        mov     sip_ti.ti_fs,ax         ; Internal thread (so we lie sometimes)
        mov     edx,_pTSDCur            ; (EDX) = current TSD
        lea     edx,[edx].TSDUserSS+4   ; (EDX) = top of stack
                                        ; BUGBUG: should be
                                        ; "add edx,TCBUserSS+4" but MASM
                                        ; forgets to put the override in
        mov     ax,bp                   ; (AX) = base of arguments
        sub     ax,sp                   ; (AX) = number of bytes of locals
        push    ax                      ; Save on stack
        movzx   eax,sp                  ; (EAX) = stack pointer
        SSToDS  eax                     ; (EAX) = FLAT base of locals
        mov     sip_ti.ti_pbuf,eax      ; Set argument base
        sub     edx,eax                 ; (EDX) = count of bytes to copy
        mov     sip_ti.ti_cbbuf,edx     ; Save count of bytes to copy
        mov     sip_ti.ti_ustart.ptr_flat,offset FLAT:SysInitThread3Thunk

        SSToDS  ecx,[sip_ptcb]          ; (ECX) = thread TCB pointer
        SSToDS  edx,[sip_ti]            ; (EDX) = thread info pointer
        CCALL32 _TKCreateThread,<[_pPTDACur], edx, ecx, STATE_READY>
        or      eax,eax                 ; Successful?
        jnz     short sispie            ;  no, internal error

        push    es                                             ;D1357
        DosContext      es                                     ;D1357
        mov   ax,es:[SISData].SIS_BootDrv ;get the boot drive  ;D1357
        mov    dx,1A1FH                 ;DX= row,col (default) ;D1357
        cmp   ax,1                                             ;D1357
        jne   sis_notadrive                                    ;D1357
        CALLFAR syiResetVideoMode                              ;D1357
        mov     edx, 031FH              ;DX= row,col (from A:) ;D1357
        CALLFAR syiBMPStandBy                                  ;D1357
sis_notadrive:                                                 ;D1357
        CALLFAR syiBMPRestoreBIOSData                          ;D1357
        pop    es                                              ;D1357

        mov     eax,sip_ptcb            ; (DS:EAX) = TCB pointer
        mov     ax,[eax].TCBOrdinal     ; Get thread ordinal
        DosInitContext <es>,si
    ASSUME      DS:NOTHING
        mov     SysInitThreadID,ax      ; Save thread ordinal
        FlatContext es,ax
        JMP32   _PGAgerInit             ; Go do aging
    ASSUME      ES:NOTHING

sispie: Panic <"syiInitOS2Comp: create thread">

;       SYSINIT THREAD 3 STARTS HERE

Entry SysInitThread3,far16,local,nocheck
        ASSUME  DS:NOTHING, ES:NOTHING

        pop     bp                      ; (BP) = number of bytes of locals
        add     bp,sp                   ; (BP) = base of arguments on new stack

;       let adapter device drivers know we're switching from microfs to minifs.
;       we'll be using disk adds rather than the real mode int13 loader.

        call    syiReinitAdds

;       Create and initialize the SysInit Environment

        call    syiCreateEnvironment

;       Allocate a segment for the SysInit Process's stack
;       Call SegAlloc(stack size,ring 3 data,LDT selector,current PTDA)
;         (WARNING: AX, BX, CX, DX, DI, SI, DS, and ES are modified)

        xor     ax,ax                 ; AX:BX = size
        mov     bx,stack_size
        mov     ch,D_DATA3            ; CH = access rights (ring 3 data)
        mov     cl,SA_LDT             ; CL = SFlags (LDT selector)
        xor     dx,dx                 ; DX = PTDA handle (current PTDA)
        xor     si,si                 ; SI = HFlags (movable)
        mov     di,ss:[ptda_handle]   ; DI = owner (current PTDA)
        CALLFAR SegAlloc
        .if     c
          Panic <"Inidinit: stack SegAlloc">
        .endif
        mov     [sip_ss].lsw,bx      ; put SS onto stack
        mov     [sip_esp].lsw,stack_size ; put SP onto stack (msw is already 0)

;       put CS:IP onto stack

        mov     ax,DOSINITR3CODE
        or      al,RPL_RING3
        mov     [sip_sef].sef_cs,ax
        MOVFAROFFSET [sip_sef].sef_eip.loword,syiProcess,DOSINITR3CODE
        or      [sip_sef].sef_eflag,F_INTERRUPT

;       Return to caller with everything set up to enter the
;       System Initialization Process

        LeaveProc
        ret
EndProc syiInitProcess


;***    syiSetCharDevTable - Set initial entries in char device table
;
;       Set up the entries in the character device table for the devices
;       installed so far - this means all the base character device drivers.
;       We need to do this since we will be trying to access them in the
;       next phase of boot-up.
;
;       ENTRY   NONE
;       EXIT    'C' clear
;                   Table entries set up
;               'C' set
;                   Ran out of memory (BMP_Get failed)
;       USES    BX, CX, DX, SI, DI, DS, ES, Flags
;
;       Go through the call-gate to call SetPMCharDevEntries.

Procedure syiSetCharDevTable
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        DosInitContext ds
        mov     si,offset DOSINITDATA:sicg_packet_10
        CALLFAR w_SICG
        ret
EndProc syiSetCharDevTable


;***LP  syiCreateEnvironment - create the SysInit Environment segment
;
;       Create the SysInit process environment.
;
;       ENTRY   The SysInit PTDA must already exist.
;               (SS) = TASKAREA
;       EXIT    NONE
;       EFFECTS A null environment is built and linked into the PTDA.
;               syiEnvironSelector is initialized
;
;       Allocate a segment for the environment
;       call SegAlloc(2 bytes,ring 3 data,LDT selector,current PTDA)
;       Zero-initialize the segment
;       Put the handle in the PTDA to make the segment the environment
;       Save the selector in syiEnvironSelector

Procedure syiCreateEnvironment
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:TASKAREA
    LocalVar Potential_Match WORD

        push    ds
        push    es
        pusha

;       Allocate a segment for the SysInit Environment
;       Call SegAlloc(2 bytes,ring 3 data,LDT selector,current PTDA)
;         (WARNING: AX, BX, CX, DX, DI, SI, DS, and ES are modified)

        xor     ax,ax                 ; AX:BX = size (2 bytes)
        mov     bx,2
        mov     ch,D_DATA3            ; CH = access rights (ring 3 data)
        mov     cl,SA_LDT             ; CL = SFlags (LDT selector)
        xor     dx,dx                 ; DX = PTDA handle (current PTDA)
        xor     si,si                 ; SI = HFlags (movable)
        mov     di,ss:[ptda_handle]   ; DI = owner (current PTDA)
        CALLFAR SegAlloc
        .if     c
          Panic <"Inidinit: env SegAlloc">
        .endif

        mov     es,bx
        mov     word ptr es:0,0        ; zero-initialize the segment

        mov     ss:[ptda_environ],ax   ; make the segment the environment

        DosInitContext ds
        mov     syiEnvironSelector,bx  ; save the environment selector

;Handle Extended LIBPATHs
        mov     ds,Config_Sys_Data
        assume  ds:nothing

;152533 push    es
        DosInitContext es

        mov     bx,ds:[0].CFG_Set.CFG_Head
                                       ;Get the head of the SET
        .while <nonzero bx>                 ;While packets exist
            mov     si,ds:[bx].CFG_EnvStr   ;DS:SI -> environment string

            call    syiR0ParseEnvironmentString
                                            ;Parse the environment string

            .if     nc near                 ;If the string is valid
                call syiProcExtLIBPATH          ;Go set the extended libpath
                call syiSetDosModeFlag                                  ;152533
            .endif
            mov     bx,ds:[bx].CFG_Next         ;DS:BX -> next SET packet
        .endwhile
;152533 pop     es

;End handle extended LIBPATHs
        popa
        pop     es
        pop     ds
        ret
EndProc syiCreateEnvironment


;
; SUBROUTINE NAME: syiR0ParseEnvironmentString
;
; DESCRIPTIVE NAME: Parse and environment string
;
; FUNCTION:      To parse and modify a string for the environment
;
; NOTES:         This is a mirror to the ring 3 routine
;                syiParseEnvironmentString in iniproc2.asm.  If
;                that routine needs to be modified because of
;                changes to the environment area, so does this one.
;
;                The string must consist of a non-null environment
;                variable name, an equal sign, and an optional
;                envrionment variable value (text).  Leading white
;                space is stripped off the variable name.  Imbedded
;                white space is left intact.  The variable name is
;                folded to upper case without regard for DBCS.  The
;                remainder of the string is not modified.
;
; ENTRY POINT: syiR0ParseEnvironmentString
;    LINKAGE:    Call (near)
;
; INPUT:         ES addresses DOSINITDATA
;                DS:SI => String to add to environment
;
; EXIT-NORMAL: Carry clear
;                The string is parsed into the environment buffer
;                Environ_Keyword_Length = length of keyword
;                Environ_Argument_Length = length of entire string
;
; EXIT-ERROR:    Carry set
;
; EFFECTS:       All registers except AX are preserved
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: None
;
;
; Procedure syiR0ParseEnvironmentString (string)
;
; Strip of leading white space
; Repeat
;     Get a character
;     If end of string then set carry and abort loop
;     If leading "=" then set carry and abort loop
;     If string is too long for buffer then set carry and abort loop
;     Upshift character
;     Store character in buffer
;     Keep count of string length
; Until "=" encountered
; Repeat
;     If string is too long for buffer then set carry and abort loop
;     Copy character to buffer
;     Keep count of string length
; Until end of string encountered
;

Procedure syiR0ParseEnvironmentString
    assume ds:nothing, es:DOSINITDATA, fs:nothing, gs:nothing, ss:nothing

        push    si
        push    di


        mov     di,offset Environ_Buffer        ;Address the parsing buffer
        mov     Environ_Keyword_Length,0        ;Initialize keyword length to 0
        cld

; Strip of leading white space
        .repeat                                 ;Repeat
            lodsb                                   ;Consume a character
        .until <al ne ' '> and                  ;Until non-white space encountered
        .until <al ne 09h>
        dec     si                              ;Backup because we have gone too far

; Parse environment variable into buffer.
        .repeat                                 ;Repeat
            lodsb                                   ;Get a character

            .if <zero al>                           ;If null (premature end of string)
                stc                                     ;Set carry (this is an error)
                .leave                                  ;Abort the loop
            .endif                                  ;Endif

            .if <al eq '='> and                     ;If char is an equal sign (end of keyword) and
            .if <Environ_Keyword_Length eq 0>       ;If keyword is null (no keyword)
                stc                                     ;Set carry (this is an error)
                .leave                                  ;Abort the loop
            .endif                                  ;Endif

                                                    ;If the buffer is full (keyword too long)
            .if <Environ_Keyword_Length ae Environ_String_Max>
                stc                                     ;Set carry (this is an error)
                .leave                                  ;Abort the loop
            .endif                                  ;Endif

            .if <al ae 'a'> and                     ;If char is lowercase
            .if <al be 'z'>
                add     al,'A'-'a'                      ;Upshift it
            .endif                                  ;Endif

            stosb                                   ;Store the char in the buffer
            inc     Environ_Keyword_Length          ;Update the keyword length
        .until <al eq '='>                      ;Until equal sign encountered

;Get the remainder of the environment string
        .if     nc                              ;If no error was encountered
            mov     ax,Environ_Keyword_Length       ;Initialize string length to keyword length
            mov     Environ_Argument_Length,ax

            .repeat                                 ;Repeat
                                                        ;If no room in buffer
                .if <Environ_Argument_Length ae Environ_String_Max>
                    stc                                     ;Set carry (this is an error)
                    .leave                                  ;Abort the loop
                .endif                                  ;Endif
                lodsb                                   ;Copy character to buffer
                stosb
                inc     Environ_Argument_Length         ;Update string length
            .until <zero al>                        ;Until end of string
        .endif                                  ;Endif

        pop     di
        pop     si
        ret
EndProc syiR0ParseEnvironmentString

;
; SUBROUTINE NAME: syiProcExtLIBPATH
;
; DESCRIPTIVE NAME: Process Setting the External LIBPATH
;
; FUNCTION:      Set the BeginLIPBATH or EndLIBPATH in the PTDA with
;                the value supplied by the CONFIG.SYS
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiProcExtLIBPATH
;    LINKAGE:    Call (near)
;
; INPUT:
;                ES addresses DOSINITDATA
;                Environment_Buffer holds parsed string
;                BP is correct to address Potential_Match
;                  and Potential_Match is 0
;
; EXIT-NORMAL: Carry Clear
;
; EXIT-ERROR:  Carry Set
;
; EFFECTS:       ESI, EDI, EAX can be modified, all others preserved
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: None
;
;
; Procedure syiProcExtLIBPATH(string)
;
; Compare the Environ_Buffer Keywork to BeginLIBPATH
; Assume we will match BeginLIBATH
; If they do not match
;   Set Potential Match to -1
;
; If Potential Match is -1
;   Assume we will match EndLIBPATH
;   Set Potential Match back to 0
;   Compare the Environ_Buffer Keywork to EndLIBPATH
;   If they do not match
;     Set Potential Match to -1
;
; If Potential Match is not -1
;   Call w_nt_SetExtLIBPATH to set the extended libpath to the
;     string in Environ_Buffer after the keywork
;   If w_nt_SetExtLIBPATH returns an error
;     Set the carry
;

Procedure syiProcExtLIBPATH
    assume ds:nothing, es:DOSINITDATA, fs:nothing, gs:nothing, ss:nothing

    push    cx
    push    ds
    push    es
    DosInitContext ds                  ;Set DS  so DS:SI will
                                       ; be able to point to program variables

    mov     si,offset BeginLibpath
    mov     di,offset Environ_Buffer   ;Compare environment keywords
    mov     ecx,1                      ;Assume we will match on begin libpath
    lodsb                              ;Get the first character
    .repeat                                 ;Repeat
        scasb                                   ;Compare characters
        .if ne                                  ;If they are different
            mov     Potential_Match,-1              ;We do not have a match
            .leave                                  ;Abort this loop
        .endif                                  ;Endif
        lodsb                                   ;Get next character
        .leave <al eq 0 >                       ;If char is a null we have a match
                                                ;   and exit this loop
    .until                                  ;Forever
    .if <Potential_Match eq -1>             ;If a match was not found
        mov     si,offset EndLibpath
        mov     di,offset Environ_Buffer    ;Compare environment keywords
        mov     Potential_Match,0           ;Reset Potential_Match
        mov     ecx,2                       ;Assume we will match on end libpath
        lodsb                               ;Get the first character
        .repeat                                 ;Repeat
            scasb                                   ;Compare characters
            .if ne                                  ;If they are different
                mov     Potential_Match,-1              ;We do not have a match
                .leave                                  ;Abort this loop
            .endif                                  ;Endif
            lodsb                                   ;Get next character
            .leave <al eq 0 >                       ;If char is a null we have a match
                                                    ;   and exit this loop
        .until                                  ;Forever
    .endif


    .if <Potential_Match ne -1>
        mov     esi,offset FLAT:Environ_Buffer  ;Address of the input string
        add     si,Environ_Keyword_Length       ; offset by keyword


        FlatContext <ds,es>                     ; set up for C calls
        CCALL32 _w_nt_SetExtLIBPATH,<esi,ecx>
        .if     <nonzero ax>                    ;If call failed
                stc
        .endif
    .endif                                  ;Need to set extended libpath

    pop     es
    pop     ds
    pop     cx
    ret
EndProc syiProcExtLIBPATH

;                                                               ;152533 Start
; SUBROUTINE NAME: syiSetDosModeFlag
;
; DESCRIPTIVE NAME: Search the Environ_Buffer for 'DOS_MODE'
;
; FUNCTION:      Disable hybernation if DOS_MODE=NO is specified
;                in the CONFIG.SYS
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiValidateDosMode
;    LINKAGE:    Call (near)
;
; INPUT:
;                ES = DOSINITDATA context
;                ES:[Environ_Buffer] = SET environment variables
;
; EXIT-NORMAL:   reset _fhybernation flag if DOS_MODE=NO
;
; EXIT-ERROR:    None
;
; EFFECTS:       ESI, EDI, EAX can be modified, all others preserved
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: None
;
;
; Procedure syiSetDosModeFlag()
;
; Search for 'DOS_MODE=' in the Environ_Buffer
; If a match occurs
;   If it is set to 'NO'
;     reset _fhybernation flag to zero
;   If it is set to 'YES' or NULL
;     set   _fhybernation flag to one
;

Procedure syiSetDosModeFlag
    assume ds:nothing, es:DOSINITDATA, fs:nothing, gs:nothing, ss:nothing

    push    ebx
    push    ecx
    push    ds
    DosInitContext ds                  ; DS, ES = DOSINITDATA

    lea     si, DosMode                ; 'DOS_MODE' string
    lea     di, Environ_Buffer         ; current environment string
    mov     cx, 8                      ; length of 'DOS_MODE' string
    repz    cmpsb                      ; look for a match
    jnz     short sDM_exit             ; mismatch, exit now

    ; skip blanks until '=' is found
    mov     cx, Environ_String_Max - 8 ; max length to search
    mov     al, '='
    repnz   scasb

    mov     al, byte ptr es:[di]
    cmp     al, ' '                    ; need to skip blanks?
    jnz     short sDM_check_null

    ; skip until non-blank space
    repz    scasb
    dec     di                         ; compensate for SCASB advancing DI

sDM_check_null:

    ; Enable _fhybernation flag when only 'DOS_MODE=' is specified
    cmp     byte ptr es:[di],0
    jz      short sDM_Enable

    ; Look for NO then YES parameter in that order
sDM_check:
    push    di                         ; save the current parm offset
    lea     bx, DOSINITDATA:YesNoTable ; offset to Yes/No table
    mov     si, ds:[bx].TokenString    ; offset to 'NO' string
    call    Config_CompareStrings
    pop     di                         ; restore the parm offset

    mov     eax, 0                     ; disable hybernation (DON'T CLEAR ZF)
    jz      short sDM_update           ; 'NO' string found

    add     bx, size TokenStruc        ; next record in the Yes/No table
    mov     si, ds:[bx].TokenString    ; offset to 'YES' string
    call    Config_CompareStrings
    jnz     short sDM_exit             ; invalid parm, exit

sDM_Enable:                            ; 'YES' or 'DOS_MODE=' string found
    mov     eax, 1                     ; enable hybernation (DON'T CLEAR ZF)

sDM_update:
    FlatContext <ds>,esi
    mov     _fhybernation, eax

sDM_exit:
    pop     ds
    pop     ecx
    pop     ebx
    ret
EndProc syiSetDosModeFlag                                       ;152533 End

;***LP  syiDosHlpFix32 - fix 32-bit DosHlp addresses
;
;       Convert 16:16 address for 32-bit DosHlp functions to 0:32 FLAT address
;
;       ENTRY   The SysInit PTDA must already exist.
;               Paging must be enabled
;               (SS) = TASKAREA
;       EXIT    NONE
;       USES    Flags
;       Process non-discardable DosHlp functions
;           Get DOSHLP_CODESEL base address from GDT, add offsets of each
;           function, saving the result
;       Process discardable DosHlp functions
;           Get selSysInitCode base address from GDT, add offsets of each
;           function, saving the result

Procedure syiDosHlpFix32
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

        SaveReg <eax,esi,fs,gs>

        DosContext fs
    assume fs:DOSGROUP

        ; Process non-discardable functions

        mov     si,DOSGDTDATA
        mov     gs,si
        mov     si,DOSHLP_CODESEL           ; get DOSHLP_CODESEL
        mov     al,gs:[si].d_hiaddr         ; get bits 23..16 of base
        mov     ah,gs:[si].d_extaddr        ; get bits 31..17 of base
        shl     eax,10h                     ; position high 16 bits of base
        mov     ax,gs:[si].d_loaddr         ; get bits 15..0 of base

        mov     esi,eax                     ; save DOSHLP_CODESEL base

        movzx   eax,word ptr fs:DHF.DosHlpSetIRQMask
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpSetIRQMask,eax      ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpSendEOI
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpSendEOI,eax         ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpClrBusyNPX
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpClrBusyNPX,eax      ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpAckIntNPX
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpAckIntNPX,eax       ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpWaitNPX
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpWaitNPX,eax         ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpValidNPXSwitch
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpValidNPXSwitch,eax  ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpVNPXReset
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpVNPXReset,eax       ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpVNPXClrBusy
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpVNPXClrBusy,eax     ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpWhyNMI
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpWhyNMI,eax          ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpAckNMI
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpAckNMI,eax          ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpTmr32QueryTime
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpTmr32QueryTime,eax  ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpTmrSetRollover
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpTmrSetRollover,eax  ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpResetWatchdogNMI
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpResetWatchdogNMI,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpGetErrorLogPtr
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpGetErrorLogPtr,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpWriteErrorLog
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpWriteErrorLog,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpReadErrorLog
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpReadErrorLog,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpDisableCache
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpDisableCache,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpFindParity
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpFindParity,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpEnableCache
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpEnableCache,eax; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpResetParity
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpResetParity,eax; save linear address


        ; Process discardable functions

        mov     si,selSysInitCode           ; get selSysInitCode
        mov     al,gs:[si].d_hiaddr         ; get bits 23..16 of base
        mov     ah,gs:[si].d_extaddr        ; get bits 31..17 of base
        shl     eax,10h                     ; position high 16 bits of base
        mov     ax,gs:[si].d_loaddr         ; get bits 15..0 of base

        mov     esi,eax                     ; save GDT_Sysinit base

        movzx   eax,word ptr fs:DHF.DosHlpInitInterrupts
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpInitInterrupts,eax  ; save linear address

        movzx   eax,word ptr fs:DHF.DosHlpInitNPX
        add     eax,esi                          ; add base
        mov     fs:DHF.DosHlpInitNPX,eax         ; save linear address

        RestoreReg <gs,fs,esi,eax>
        ret
EndProc syiDosHlpFix32


;***LP  syiReinitAdds  - tell ADDS that microFSD is no longer being used.
;
;
;       ENTRY   NONE (microFSD is no longer being used)
;       EXIT    NONE
;       USES    Flags

Procedure syiReinitAdds
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        EnterProc
        pushad
        SaveReg <es,ds>

        xor    cx,cx
        DosContext ds,ax
        DosInitContext es,ax
        mov     si,offset DOSGROUP:DiskDCTable
        mov     dx,ds:[si].DCCount
        mov     si,offset DOSGROUP:DiskDCTable.DCTableEntries
nextadd:
        cmp     cx, dx
        je      sra_x

        xor     eax,eax
        mov     es:newIORB.UnitHandle,ax
        mov     es:newIORB.RequestControl,ax
        mov     es:newIORB.Status,ax
        mov     es:newIORB.ErrorCode,ax
        mov     es:newIORB.Timeout,eax
        mov     es:newIORB.StatusBlockLen,ax
        mov     es:newIORB.pStatusBlock,ax
        mov     es:newIORB.pNxtIORB,eax
        mov     es:newIORB.NotifyAddress,eax
        mov     es:newIORB.pDeviceTable,eax
        mov     es:newIORB.DeviceTableLen,ax

        mov     es:newIORB.IORBLength, SIZE IORB_CONFIGURATION
        mov     es:newIORB.CommandCode,1
        mov     es:newIORB.CommandModifier,2

        push    eax
        mov     eax,ds:[si]    ; check to see if entry has been zero'ed out,
        cmp     eax,0          ; perhaps by a filter add.
        pop     eax
        je      sra_skip

        SaveReg <es,ds,si,cx,dx>

        push    es
        push    offset DOSINITDATA:newIORB
        call    DWORD ptr ds:[si]
        add     esp,4


        RestoreReg <dx,cx,si,ds,es>

sra_skip:

        add     si,SIZE DevClassTableEntry
        inc     cx
        jmp     nextadd

sra_x:
        RestoreReg <ds,es>
        popad
        LeaveProc
        ret
EndProc syiReinitAdds


;***LP  syiCheckForAltF1
;
;       This procedure is called before CONFIG.SYS processing to check
;       for an ALT-F1 key combination.  If ALT-F1 key is pressed, then
;       set a flag which will tell Sysinit to use an alternate CONFIG.SYS
;       and to replace the OS2.INI and OS2SYS.INI files with the copies
;       under \OS2\INSTALL.
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    Flags
Procedure syiCheckForAltF1
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
;   int     3
      EnterProc
      pushad
      SaveReg <gs,fs,es,ds>                 ;Feature 74378
      NullContext <es,fs,gs>,ax
      DosContext <ds>,ax

      pushf                                 ;save interrupt state
      cli                                   ;disable interrupts for the duration
      call   RealModeIC
      push    es

      DosContext ds
      mov     es,[RealInitDS]         ; (ES) = DOSINITDATA paragraph



;159589      mov     bp,offset WRTSTRING  ; Have es:bp point to string of blanks
;159589      mov     cx,09h               ; String has a count of 4 characters
;159589      xor     dx,dx                ; Write string at cursur position 0,0
;159589      mov     bx,dx                ; Page Number 0
;159589      mov     ax,01302h            ; Function 13, sub-function 2
;159589      int     10h                  ; write the string to the screen
      pop     es

      mov    ah,01h
      int    16H

      call   ProtModeIC
      popf                                  ;restore interrupt state

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;     Auto recovery code -- User can set a default that the ALT-F1 screen
;          comes up every boot and also the amount of time the screen stays
;          displayed. 'Timeout' refers to this period of time of the screen.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      xor     bx,bx                ; Set infinite timeout
      push    bx                   ; Save timeout
      push    ax                   ; Save scan code

      DosInitContext <es>
      lea     di,DOSINITDATA:ALTF1ARCH_filespec ; open ARCHBASE.$$$ file
      call    SYIOpenFile
      .if     <nc>
          mov     bx,512                       ; Buffer Size to allocate (512)
          xor     ax, ax                       ;    for reading ARCHBASE.$$$
          mov     cl, SA_GDT                   ; flags
          mov     ch, D_DATA0                  ; access rights
          mov     si, HF_MOVABLE+HF_LOWMEM     ; flags
          mov     di, INITOWNER                ; owner -
          xor     dx,dx                        ; ptda handle
          CALLFAR SegAlloc        ; returns (bx) = selector (ax) = handle

          DosInitContext <es>
          mov     ax,bx           ; set up for syireadfile .....
          xor     bx,bx           ; ax:bx = seg:offset of buffer to read into
          mov     cx,bx           ; cx:dx = amount to be read (0=whole file)
          mov     dx,bx           ;
          call SYIReadFile        ; read in whole (up to 512 bytes) file
          mov     ds,ax           ; save selector for later use
          mov     ax,ds:[217]     ;
          cmp     cx,ax           ; ax = selector; 217 = 1st 2 bytes of
                                  ;   file indicator. We'll check if it = 0.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;         Check  offset for enabling auto-recover
; 4bytes -offset 216(decimal) -- if not zero then timer set
; 4bytes -offset 220(decimal) -- value of timer... 0 = forever (no timer; wait
;                                until user hits keystroke; else value from
;                                1 - 999 , in seconds).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          .if < nz >
              pop    ax            ; Pop old scan code off stack
              .if   <ah ne 68h>    ; Did they press ALT-F1?

                  pop  bx          ;Clear old timeout value off stack (trash)
                  mov  bx,ds:[221] ;
                  push bx          ; Timer value
;;;                  mov  eax,ds:[221] ; set up for call to Int2Ascii
;;;                  lea     di,DOSINITDATA:AltF1ScrTimerValue
;;;                  call Int2Ascii   ; converts number to ASCII and puts in
;;;                                   ;   AltF1ScrTimerValue field.
              .endif
              mov    ah,68h        ; 68h = alt-F1 keystroke (in ASCII)
              push   ax            ; Pretend they pressed ALT-F1
          .endif                   ;  (whether they did or not)
          mov  ax,ds               ; set up to free segalloc buffer
          CALLFAR   SegFree        ;   return buffer
          call SYICloseFile        ; close ARCHIVE.$$$ file
      .endif

      pop     ax                   ; Restore keystroke entered
      pop     bx                   ; Restore timeout value

         DosInitContext <ds>
      .if   <ah eq 68h>                     ; AH = ALT-F1 Scan code?
         mov  AltFxKeyPressed,1
	 mov  savAltFxKeyPressed,1     ;159589
         ; BX = timeout, (0=infinite)
         call syiProcessALTF1File           ;Feature 74378
      .elseif   <ah eq 69h>                 ; AH = ALT-F2 Scan code?
         mov  AltFxKeyPressed,2        
         mov  savAltFxKeyPressed,2     ;159589
      .endif

      RestoreReg <ds,es,fs,gs>              ;Feature 74378
      popad
      LeaveProc
      ret
EndProc syiCheckForAltF1

;;;;;;;;;;;;;;;;;; Start of Feature 74378 changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;***LP  syiProcessALTF1File
;
;       This procedure is called before CONFIG.SYS processing to check
;       for an ALT-F1 key combination.  If ALT-F1 key is pressed, then
;       set a flag which will tell Sysinit to use an alternate CONFIG.SYS
;       and to replace the OS2.INI and OS2SYS.INI files with the copies
;       under \OS2\INSTALL.
;
;       ENTRY   BX=timeout (0=infinite)
;       EXIT    NONE
;       USES    Flags
Procedure syiProcessALTF1File
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        LocalVar        _AF_SEG,WORD            ; Address of buffer's segment
        LocalVar        _AF_SEL,WORD            ; Address of buffer's selector
        LocalVar        _AF_SIZE,WORD           ; Count of Number of bytes
                                                ;  read into screen output
                                                ;  buffer.
        LocalVar        _AF_KEY,WORD            ; Key pressed in response to
                                                ;  ALTF1 screen.
        LocalVar        _AF_TIMEOUT,WORD        ; Timeout value, passed in

;;;;;;int     3          ;<<<DEBUG>>>
      EnterProc
      pushad
      SaveReg <gs,fs,es,ds>

      mov     _AF_TIMEOUT,bx                    ; Save timeout value

      DosContext <ds>,ax
      DosInitContext <es>

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       If ALTF1SEC.CMD file exists in the \OS2\BOOT directory, it means that
;       we have OS/2 Security hooks installed (perhaps not enabled in
;       config.sys though), and we will not display the
;       ALTF1*.SCR files. We will use \OS2\BOOT\CONFIG.SEC as our
;       alternate config.sys file. Any other files to restore should
;       be specified/copied in ALTF1SEC.CMD.                            @SEC
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;int     3          ;<<<DEBUG>>>                                 ; @SEC
      lea     di, DOSINITDATA:AltF1SecFile                            ; @SEC

      call    SYIOpenFile             ; Returns size in BX:AX         ; @SEC

      .if nc near                     ; File exists                     @SEC
          call    SYICloseFile        ;                               ; @SEC
          or      AltF1Flags,ALTF1_USE_ALTF1SEC ; Security installed.   @SEC
          mov     AltFxKeyPressed,1   ; Pretend key was pressed.        @SEC

          mov     ConfigSysFilename[7],'S'                            ; @SEC
          mov     ConfigSysFilename[8],'E'                            ; @SEC
          mov     ConfigSysFilename[9],'C'                            ; @SEC

          lea     di, ConfigSysFilename    ; Try to open it.            @SEC
          call    SYIOpenFile                                         ; @SEC

          .if nc                           ; File exists                @SEC
              call    SYICloseFile         ;  so close it               @SEC
              or      AltF1Flags,ALTF1_USE_ALTERNATE_CONFIGSYS        ; @SEC
          .else                            ; Use original config.sys  ; @SEC
              or      AltF1Flags,ALTF1_USE_CURRENT_CONFIGSYS          ; @SEC
              mov     ConfigSysFilename[7],'S'                        ; @SEC
              mov     ConfigSysFilename[8],'Y'                        ; @SEC
              mov     ConfigSysFilename[9],'S'                        ; @SEC
          .endif                                                      ; @SEC

          jmp AllDone                 ; Don't display menu.             @SEC
      .endif                                                          ; @SEC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       Realistically, the biggest that we "should" see is
;       80X25 characters, = 2000 bytes.  We'll fit as much as
;       we can from the ALTF1*.SCR files into 2K and ignore
;       the rest.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

      mov     _AF_SIZE,0      ; Nothing read into buffer yet

      mov     bx,ALTF1SCREENMAX            ; Buffer Size to allocate
      xor     ax, ax
      mov     cl, SA_GDT                   ; flags
      mov     ch, D_DATA0                  ; access rights
      mov     si, HF_MOVABLE+HF_LOWMEM     ; flags
      mov     di, INITOWNER                ; owner -
      xor     dx,dx                        ; ptda handle
      CALLFAR SegAlloc        ; returns (bx) = selector (ax) = handle

      DosContext <ds>         ; ds restored after SegAlloc clobbers it
      DosInitContext <es>     ; es restored after SegAlloc clobbers it

      mov     _AF_SEL, bx     ; bx = paragraph (selector) on entry

      CALLFAR SelToSeg        ; (ax) = paragraph (segment) on exit

      mov     _AF_SEG, ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;     OK, now we have a buffer. Let's try reading in the 3 files needed
;         for output of the ALTF1 screen.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

      lea     di, DOSINITDATA:ALTF1TOP_filespec
      xor     ax,ax                   ; Indicate first file

paff_ReadNextFile:
      push    ax                      ; Save file indicator
;     int     3          ;<<<DEBUG>>>
      mov     cx,_AF_SIZE             ; CX=bytes already read into buffer
      mov     dx,ALTF1SCREENMAX-1     ; total size of buffer (zero-orig)
      sub     dx,cx                   ; DX= bytes remaining in buffer

      call    SYIOpenFile             ; Returns size in BX:AX

      .if nc near                     ; File exists

          .if <zero ax> and near       ; ... and it's not > 64k
          .if <nonzero bx> and near    ; ... but it's > 0 bytes
          .if <dx g 0 >                ; > 0 bytes left in buffer ??

              .if <dx ge bx>          ; Is file =< remaining space in buffer?
                  xor    dx,dx        ;  Yes, so indicate to read in whole file
                  add    _AF_SIZE,bx  ;  Add file size to count of buffer bytes
              .else                   ; else just read in DX-dumber of bytes
                  add    _AF_SIZE,dx  ;  Add DX-number of bytes to buffer count
              .endif                  ;

              mov     ax,_AF_SEL      ; ax:bx = seg:off of buffer to read into
              mov     bx,cx           ; cx    = offset to start reading into
              xor     cx,cx           ; CX:DX = amount to read (0=whole file)
              call    SYIReadFile

              push    ds
              mov     ax,_AF_SEL
              mov     ds,ax
              movzx   eax,_AF_SIZE
              dec     eax
              mov     al,ds:[eax]      ; Get last character read
              pop     ds

             .if <al eq 01AH>          ; Was it a CTRL-Z?
                  dec  _AF_SIZE        ; Don't read Ctrl-Z at end
             .endif

          .endif
          call    SYICloseFile

          pop     ax                  ; ax indicates which file was just read
                                      ;  into buffer (TOP, MID or BOT).
          inc     ax                  ; increment (zero-based)

paff_SetNextFile:
         .if <_AF_SIZE lt ALTF1SCREENMAX>
            .if <ax e 1>
               lea     di, DOSINITDATA:ALTF1MID_filespec
               jmp     paff_ReadNextFile
            .endif
            .if <ax e 2>
               lea     di, DOSINITDATA:ALTF1BOT_filespec
               jmp     paff_ReadNextFile
            .endif
;;;            .if <_AF_TIMEOUT g 0>
;;;              push    es                             ; save es
;;;              push    ds                             ; save ds
;;;              mov     ax,_AF_SEL                     ; selector for ALT-F1
;;;              mov     es,ax                          ;   screen buffer
;;;              mov     di,_AF_SIZE                    ; current offset in buffer
;;;              DosInitContext <ds>
;;;              lea     si,AltF1ScrTimerStart          ; Start of timer message
;;;              mov     cx,L_TimerMsg                  ; Size of message
;;;              cld                                    ; clear direction indicator
;;;              add     _AF_SIZE,cx                    ;   for movsb instruction
;;;        rep   movsb                                  ; Move in msg
;;;              pop     ds                             ; restore selectors
;;;              pop     es                             ;  ....
;;;            .endif
         .endif

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;     At this point all ALTF1 output files have been read into buffer.
;        Now we can throw this buffer onto the screen and give the user
;        their choices.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Retry:
          DosContext ds
          NullContext  <es,fs,gs>,ax
          call    RealModeIC             ; switch to real mode
                                         ;  for KBD and screen I/O
          DosContext ds

          mov     es,[RealInitDS]         ; (ES) = DOSINITDATA paragraph
          mov     ds,[RealInitDS]         ; (DS) = DOSINITDATA paragraph

;         int     3          ;<<<DEBUG>>>
      assume ds:DOSINITDATA, es:DOSINITDATA

flush:                                    ; Flush the keyboard buffer

          mov     ah,1                    ; Check for key available
          int     16h                     ; Look for key
          jz      setscr

          xor     ah,ah                   ; Read available key
          int     16h                     ; Get the key
          jmp     short flush

setscr:
          mov     ax,0600h                ; ah=06 - scroll up; al=0 - blank page
          xor     cx,cx                   ; start location (0,0)
          mov     dx,184fh                ; dh=24 - last row; dl=79 - last column
          mov     bh,1Fh                  ; Normal attribute
          int     10H                     ; blank the page

          mov     ah,0bh                  ; set blue border
          mov     bx,0001h
          int     10H

          mov     ah,02h                  ; set cursor position at upper left
          xor     dx,dx                   ;   corner .... (dh,dl = 0,0)
          mov     bh,00h                  ; page number (0 based) ....
          int     10H

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;         Set up registers to put buffer out to screen 1 byte at time
;             via int 10h.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          mov     si,_AF_SEG
          mov     es,si
          xor     si,si
          mov     cx,_AF_SIZE
          dec     cx
      assume  es:NOTHING

          ; Message pointed to by es:si
          ; Length in cx

          .repeat
              mov     ah,0Eh                  ; write teletype
              mov     al,byte ptr es:[si]     ; character to output
              mov     bl,1Fh                  ; Normal attribute
              int     10h
              inc     si
              dec     cx                      ; Any more chars to output ?
          .until  <zero cx>

          mov     ax,0200h                ; move cursor to top left corner
          xor     bx,bx                   ; BH = 0      (page number)
          mov     dx,bx                   ; DH,DL = 0,0 (Row,Column)
          int     10h

          mov     ax,0100h                ; Set Cursor Type
          mov     cx,3f00h                ;  .. set to no cursor (erase it)
          int     10h

          ; Make a sound with the speaker.
          ; The delay used is a constant, thus beep duration will vary
          ; with CPU performance.  At this low level, precise duration is more
          ; trouble than its worth - this beep only happens once during initial
          ; installation.


          in      al,PORT_SYSB            ; get current setting
          kIODelay   cx
          or      al,SYSB_SPKENABLE + SYSB_SPKGATE    ; set speaker bits on
          out     PORT_SYSB,al            ; turn the speaker on


          mov     cx,0BFFFh               ; delay
          .repeat
             kIODelay   dx                ; Additional delay
             dec cx
          .until <zero cx>

          in      al,PORT_SYSB            ; get current setting
          kIODelay   cx
          and     al, not(SYSB_SPKENABLE + SYSB_SPKGATE)  ; turn speaker bits off
          out     PORT_SYSB,al            ; turn off speaker

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;         User now has ALTF1 screen displayed. Let's wait for him to input
;           a keystroke in response to this screen.
;
;     Check if timer value is to be used with screen. If value is not
;     zero (zero means keep screen up until keystroke entered), then time
;     the screen.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

          mov     bx,_AF_TIMEOUT
          inc     bx                      ; set up for waiting loop below ...
          .if < bx e 1 >                  ; if bx input was 0, wait forever ..
             mov    bx,0ffffh              ; put max value to indicate
                                          ;   to wait forever for key-input ..
          .else
             mov     dx,4000h             ; set up for int15 (WAIT) ...we'll
             mov     cx,0fh                ;   wait for 1 sec then check if
          .endif                          ;   to wait forever for key-input ..
                                          ;   user hit keystroke.
                                          ; cx:dx = f4000 hex (1 sec)

wait2:                                    ; Wait for key pressed

;         check to see if we've timed out
;         if we have, put the escape value in _AF_KEY
;         and jump to fake_esc (pretend they pressed escape)

          cmp bx,0ffffh                    ; keep screen up forever?
          je  chkkey                      ;  yes, keep waiting for keystroke!

          dec     bx                      ; bx = seconds to wait
          .if < bx e 0 >                  ; finished waiting?
             mov   al,1bh                 ; yes... pretend that 'esc' entered
             jmp   fake_esc               ;   and leave loop .....
          .endif

          mov     ah,86h                  ; 'wait' for cx:dx time (1 sec)
          int     15h                     ; OK , go wait

chkkey:
          mov     ah,1                    ; Check for key available
          int     16h                     ; Look for key
          jz      wait2                   ; no key (z), loop back

          xor     ah,ah                   ; Read available key
          int     16h                     ; Get the key
fake_esc:
          mov     _AF_KEY,ax              ; save key

          ;blank the screen
          mov     ah,06h                  ; scroll up
          mov     al,0                    ; blank page
          xor     cx,cx                   ; start location (0,0)
          mov     dl,79                   ; last column
          mov     dh,24                   ; last row
          mov     bh,07h                  ; load color attribute
          int     10h                     ; blank the page

          mov     ah,0bh                  ; set black border
          mov     bh,0
          mov     bl,00h
          int     10h

          push    ds
          pop     es

          call         ProtModeIC         ;switch back to protect mode
;          int     3          ;<<<DEBUG>>>

;         DosContext <es> ; take this out?
          DosInitContext ds
          mov     ax,_AF_KEY

          ;100364  The French (and Belgium) keyboard has the ";" and
          ;100364  "m" reversed.  Because of this, we must accept either
          ;100364  "m" or ";".

          .if     <al eq ';'>     ;100364
              mov    al,'M'       ;100364
          .endif                  ;100364

          .if     <al eq 1Bh>             ;If user pressed ESC key
              mov     AltF1Parm,0         ; Make like it never happened ...
              mov     AltFxKeyPressed,0   ;   never happened ......
          .else NEAR
             .if <al ae 'a'> AND          ;If key entered is a...z,
             .if <al be 'z'>
                 add    al,'A'-'a'           ;Convert to upper
             .endif
; 150691     .if     <al b '1'> OR           ;Is key entered out of range?
             .if     <al b '0'> OR           ;Is key entered out of range? ; 150691
             .if     <al a '9'>              ;Not 0..9?
                .if     <al b  'A'> OR       ;Not A...Z?
                .if     <al a  'Z'>          ;  if yes, then illegal keystroke,
                   .if      <ah b 3Ch> OR    ;Not a function key 2 - 8     ; 150691
                   .if      <ah a 42h> OR    ;                             ; 150691
                   .if      <al ne 0>        ;if yes, then illegal keystroke, ; 150691
                      jmp     Retry            ;     Retry (which will beep)
                   .endif                                                  ; 150691
                .endif
             .endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;            At this point, key entered is valid (0-9 or A-Z or F2 to F8)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 150691 start
            ; The following key: V, M, X are not Valid
            .if <al eq 'V'> OR
            .if <al eq 'M'> OR
            .if <al eq 'X'>
                jmp     Retry         ;     Retry (which will beep)
            .endif
            ;
            ; Get Correct Char X for function keys F2 - F4
            ; or '0' to use for Config.X file name
            ;
            .if <ax eq  3C00h>              ;Q: If F2 key?
               mov     al, 'C'              ; Y: set Char to 'C'
               jmp     ContinueRecovery     ; continue w/recovery
            .endif
            .if <ax eq  3D00h>              ;Q: If F3 key?
               mov     al, 'V'              ; Y: set Char to 'V'
               jmp     ContinueRecovery     ; continue w/recovery
            .endif
            .if <ax eq  3E00h>              ;Q: If F4 key?
               mov     al, 'M'              ; Y: set Config.sys Char to 'M'
               jmp     ContinueRecovery     ; continue w/recovery
            .endif
            .if <al eq  '0'>                ;Q: If 'X' key?
               mov     al, 'X'              ; Y: set Config.sys Char to '0'
               jmp     ContinueRecovery     ; continue w/recovery
            .endif
            ;
            ; Check if Snooplevel Choices?
            ;
            .if <ax eq 3F00h>               ;Q: If F5 key?
               mov      RMSysCmdLine[4],'4' ; Y: Enable Hdw Detection SNP_HIGH_RISK
               mov      AltF1Parm,0         ; Make like it never happened ...
               mov      AltFxKeyPressed,0   ;   never happened ......
               jmp      RecoverSel
            .endif
            .if <ax eq 4000h>               ;Q: If F6 key?
               mov      RMSysCmdLine[4],'0' ; Y: Disable Hdw Detection SNP_WARP_RISK
               mov      AltF1Parm,0         ; Make like it never happened ...
               mov      AltFxKeyPressed,0   ;   never happened ......
               jmp      RecoverSel
            .endif
            .if <ax eq 4100h>               ;Q: If F7 key?
               mov      RMSysCmdLine[4],'2' ; Y: Remove Card SNP_LOW_RISK
               mov      AltF1Parm,0         ; Make like it never happened ...
               mov      AltFxKeyPressed,0   ;   never happened ......
               jmp      RecoverSel
            .endif
            .if <ax eq 4200h>               ;Q: If F8 key?
               mov      RMSysCmdLine[4],'3' ; Y: Add Card SNP_MEDIUM_RISK
               mov      AltF1Parm,0         ; Make like it never happened ...
               mov      AltFxKeyPressed,0   ;   never happened ......
               jmp      RecoverSel
            .endif

ContinueRecovery:           ; continue w/recovery

; 150691 end


             DosInitContext es                ; set up for SYIOpenFile ...
             mov     AltF1Parm,al             ; Initialize AltF1Parm to key

             mov     AltF1xFile[5],al         ; Initialize ALTF1?.CMD to key

             mov     ax,_AF_KEY               ; Restore pressed key ; 150691

; 150691     .if   <al eq "C">                   ; If "C", use install
             .if <ax eq 3C00h>                   ;Q: If F2? Use Install ; 150691
                mov     ConfigSysFilename[7],'X' ; version of CONFIG.SYS
                mov     ConfigSysFilename[8],0   ;     we'll check if config.al
                mov     ConfigSysFilename[9],0   ;        exists ....

; 150691     .elseif <al ne "V">                 ; If 'V', use root config.sys
             .elseif <ax ne 3D00h>               ;Q: If F3? use root config.sys ;150691
                mov     al,AltF1Parm             ; Get Character       ; 150691
                mov     ConfigSysFilename[7],al  ;  all other cases
                mov     ConfigSysFilename[8],0   ;     we'll check if config.al
                mov     ConfigSysFilename[9],0   ;        exists ....
                mov     ax,_AF_KEY               ; Restore Key Pressed ; 150691
             .endif


;            int     3
             lea     di, ConfigSysFilename    ; Try to open CONFIG.'al'
             call    SYIOpenFile

             .if nc                           ; File exists
                 call    SYICloseFile         ;  so close it
; 150691         .if <al ne "V">              ; if 'V' we're using root version
                 .if <ax ne 3D00h>            ;Q: If F3? we're using root version ;150691
                    or      AltF1Flags,ALTF1_USE_ALTERNATE_CONFIGSYS  ;non-root
                 .else
                    or      AltF1Flags,ALTF1_USE_CURRENT_CONFIGSYS    ;root
                 .endif
             .else
                mov     ConfigSysFilename[7],'S' ; Doesn't exist, so
                mov     ConfigSysFilename[8],'Y' ; reset extension and retry
                mov     ConfigSysFilename[9],'S'
             .endif

             lea     di, AltF1xFile           ; Try to open ALTF1?.CMD
             call    SYIOpenFile

             .if nc                           ; File exists
                 call    SYICloseFile         ;  so close it
                 or      AltF1Flags, ALTF1_USE_ALTF1xCMD    ; and set flag

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;  If ALTF?.CMD file does NOT exist, then make sure ALTF1.CMD exists.
;     We want to use the keystroke entered as an input parm to ALTF1.CMD if
;     ALTF1?.CMD does NOT exist.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

             .else                            ; ALTF?.CMD Doesn't exist, check
                 lea     di,AltF1File         ; make sure that ALTF1.CMD exists
                 mov     AltF1FileSpace,0     ; Null terminate filename
                 call    SYIOpenFile          ;   try to open it
                 .if c                        ; If c, ALTF1.CMD Doesn't exist
                     or      AltF1Flags, ALTF1_NO_ALTF1CMD  ;  so set flag
                     mov     AltF1Parm,0      ; Don't display parm in MSG ...
                     lea     si,tbl_no_altf1_screen         ; display a message
                     call    syiDisplayMessage
                     mov     [error_messages_displayed],1
                     call    syiPauseOnError
                 .else
                     call    SYICloseFile     ; ALTF1.CMD opened, now close it
                 .endif                       ; ends check if ALTF1.CMD exists
                 mov     AltF1FileSpace,' '   ; Put space back

             .endif                           ; ends check if ALTF1?.CMD exists

             mov al,AltF1Flags         ; Check if any flags set ....
             test   al, ALTF1_USE_ALTERNATE_CONFIGSYS+ ALTF1_USE_ALTF1xCMD+ ALTF1_USE_CURRENT_CONFIGSYS
                                              ; found Config file or ALTF1.. file?
             jz     Retry              ; .. no ,so go ask user again ....
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;            At this point we have found either a config.'al' or
;               altf1'al'.cmd file so the input appears reasonable.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 150691     mov   al,AltF1Parm
; 150691     .if   <al eq "C">                   ; If "C" was pressed,
             mov   ax,_AF_KEY                    ; Restore pressed key      ; 150691
             .if   <ax eq 3C00h>                 ;Q: If F2 key was pressed? ; 150691
                ;Reset parms for ALTF1.CMD and ALTF1?.cmd because
                ;It's quicker than checking.
                mov     AltF1CmdParms[1],'K'     ; Tell CMD.EXE to hang around
                mov     AltF1CmdParms[2],0       ; don't give it parameters
                mov     AltF1xCmdParms[1],'K'    ; Tell CMD.EXE to hang around
                mov     AltF1xCmdParms[2],0      ; don't give it parameters

             .endif

          .endif

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;     The next else indicates that one of TOP,MID or BOT ALtF1 screens
;         doesn't exist. Put out message to user that there is a problem
;         if TOP or BOT doesn't exist; if MID go back and finish
;         output to screen.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      .else
       ASSUME ES:nothing
       DosInitContext <ds>
         pop  ax                       ; get the file indicator from stack
         .if <ax e 1>                  ; ax = 1 means middle screen not found
            inc   ax                   ; if middle screen, increment file
            jmp   paff_SetNextFile     ; indicator and go do next file.
         .endif
         xor  ax,ax                    ; ax NOT equal to 1; tell user we can't
         mov  AltF1Flags,al            ; proceed .....
         mov  AltF1Parm,al
         mov  AltFxKeyPressed,al

         lea     si,tbl_no_altf1mid_screen     ; display a message
         call    syiDisplayMessage
         mov     [error_messages_displayed],1
         call    syiPauseOnError

      .endif

RecoverSel:                                                            ; 150691
      mov     ax,_AF_SEL      ; recover selector into ax
      CALLFAR  SegFree        ; free segment, selector in ax

AllDone:                                                               ; @SEC
      RestoreReg <ds,es,fs,gs>
      popad
      LeaveProc
      ret
EndProc syiProcessALTF1File
;;;;;;;;;;;;;;;;;;;; End of Feature 74378 changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;; Start of Feature 26214 changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;***LP  syiDMQS
;
;       This procedure is called to determine if XGA DMQS information is
;       available.  If the XGA DMQS info is available, a selector is
;       is allocated from the low (below 1M) kernel heap, a mode switch
;       is occured, and CBIOS is called to fill in the XGA DMQS info.
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    Flags
Procedure syiDMQS,<near>
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
;
;       Switch to real mode and find size of DMQS data area (XGA)
;

        LocalVar        DMQS_Seg,WORD            ; DMQS Segment
        LocalVar        pDMQS,DWORD              ; DMQS Physical address
        LocalVar vmac,<SIZE VMAC>                ;
        EnterProc
        pushad
        SaveReg         <ds,es>

        NullContext es
        DosContext  ds

        call    RealModeIC

        xor     bx,bx
        mov     ax,1F00H               ; AH=1FH, AL=00H read DMQS data length
        int     10H

        call    ProtModeIC

        cmp     al,1FH                 ; function supported?
        jne     syiDMQS_not_supported  ; no, go blank the fields
        cmp     bx,00                  ; zero length?
        je      syiDMQS_not_supported  ; yes, go blank the fields

        movzx   ecx,bx                 ; ecx = size
        FlatContext <ds,es>,eax        ; set up for C calls
        SSToDS  eax,vmac

;       Allocate the memory segment:
;       rc = SELAllocKHB(hkh, cb, fl, flselmgr, hobowner, pac)

        CCALL32 _SELAllocKHB,<VM_HKH_PUB_RES1MRW, \
                ecx, \
                <PG_RESIDENT+PG_U+PG_CONTIG+PG_1M+VMAC_ALIGNPAGE>, \
                <D_DATA+D_DPL3>, \
                DEVHLPOWNER, \
                eax>
        DosContext      <ds>
        or      eax,eax
        .if     nz                     ; did the SELAllocKHB fail?
           Panic <"syiDMQS: SELAllocKHB failed"> ; yes, halt the system
        .endif

        mov     bx,vmac.ac_sel         ; BX = SEL

        mov     DMQS_Sel, bx           ; Initialize DMQS selector
                                ;bx = selector
        CALLFAR SelToSeg        ; convert selector to segment

        .if     c
           Panic <"syiDMQS:SelToSeg">
        .endif

        mov     DMQS_Seg, ax


;
;       Switch to real mode and read the DMQS data
;

        call    RealModeIC

        mov     es,DMQS_Seg
        xor     di,di            ; ES:DI -> DMQS buffer
        mov     ax,1F01H         ; AH=1FH, AL=01H read DMQS data
        int     10H

        call    ProtModeIC


        cmp     al,1FH           ; function supported?
        je      syiDMQS_x        ; yes, return


        DosContext      <ds>
        movzx   eax, DMQS_Sel
        xor     ebx,ebx
        FlatContext <ds,es>

        CCALL32 _SELFreeKHB,<VM_HKH_PUB_RES1MRW,ebx,eax>


syiDMQS_not_supported:
        ;Dummy the fields
        DosContext      <ds>
        mov     DMQS_Sel, 00
        mov     DMQS_Seg, 00

syiDMQS_x:
        RestoreReg <es,ds>
        popad
        LeaveProc
        RET

EndProc syiDMQS
;;;;;;;;;;;;;;;;;; End   of Feature 26214 changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;***LP  syiAPM -  Determine if Advanced Power Management is supported
;
;       Determine if Advanced Power Management is supported and fill in
;       the APM info for APM device driver (available via DevHlp_GetDosVar
;
;       ENTRY   CX = 0, query APM presence
;               CX = 1, query APM presence and establish connection
;
;       EXIT    NONE
;
;       USES    NONE
;

Procedure syiAPM,faronly
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

        pushad
        SaveReg <ds,es,gs,fs>

        NullContext <es,fs,gs>
        DosContext <ds>,ax

        cmp    APM_CodeSeg,0    ; Already established connection?
        jne    APM_x            ; yes, just exit

        pushf                   ; save interrupt state
        cli                     ; disable interrupts for the duration
        RM     ax,bx            ; Switch to Real Mode

    ;-- Establish addressibility to APM_* vbls.

        DosContext  ds

        push    cx              ; save CX

    ;-- Query BIOS for presence of APM capability.

        mov     ax, 5300h
        xor     bx, bx
        int     15h             ; Query APM Presence.
        jc      short APM_error
        cmp     bx, 504Dh       ; ASCII "PM", Power Mgmt signiture.
        jnz     APM_error
        mov     APM_Level, ax   ; Save APM revision level.
        mov     APM_Flags, cx   ; Save APM capability flags.

        pop     cx              ; get a copy of CX from stack
        push    cx              ; leave it on the stack

        cmp     cx,0            ; just query?
        je      APM_error       ; yes, don't establish connection

        test    APM_Flags, 0001h ; 16-bit interface supported?
        jnz     syiAPM1         ; yes.
        test    APM_Flags, 0002h ; 32-bit interface supported?
        jnz     syiAPM2         ; yes.
        jmp     short APM_error ; exit, error.

    ;-- APM is present on the machine.  Fetch the 16:16 interface.

syiAPM1:
        mov     ax, 5302h
        xor     bx, bx
        int     15h             ; Request 16:16 conntect.
        jc      short APM_error
        mov     APM_CodeSeg, ax
        mov     APM_Offset,  bx
        mov     APM_DataSeg, cx


        mov     APM_CSegLength, si   ;d151440
        mov     APM_DSegLength, di   ;d151440

        jmp     short APM_error

    ;-- APM is present on the machine.  Fetch the 16:32 interface.

syiAPM2:
        mov     ax, 5303h
        xor     bx, bx
        int     15h             ; Request 16:32 connect.
        jc      short APM_error
        mov     APM_CodeSeg, cx
        mov     APM_Offset,  bx
        mov     APM_DataSeg, dx
        mov     APM_32CodeSeg, ax
        mov     APM_32Offset, ebx

        mov     APM_CSegLength, si   ;d151440
        mov     APM_DSegLength, di   ;d151440

    ;-- Now, the APM BIOS cannot automatically power down devices
    ;   without the handshake provided by the APM device driver.
    ;   Hence, APM DD must be loaded before any power conservation
    ;   can be done.

APM_error:
        pop    cx                             ; remove CX from stack
        PM     ax                             ; Switch to Protect Mode
        popf                                  ;restore interrupt state
APM_x:
        RestoreReg <fs,gs,es,ds>
        popad

        ret
EndProc syiAPM

;Start of LieList changes

;***LP  syiOS2VER -  Read OS2VER file if available
;
;
;       ENTRY   NONE
;
;       EXIT    NONE
;
;       USES    NONE
;

Procedure syiOS2VER,near
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        pusha
        push  ds
        push  es

        DosInitContext <es>
        lea     di, DOSINITDATA:OS2VER_filespec
        call    SYIOpenFile

        .if nc and near                 ; File is found
        .if <zero ax> and near          ; not over 64K
        .if <nonzero bx> near           ; but not 0 bytes

            push    bx              ; save size

            xor     ax, ax
            mov     cl, SA_GDT                   ; flags
            mov     ch, D_DATA0                  ; access rights
            mov     si, HF_MOVABLE+HF_LOWMEM     ; flags
            mov     di, LDRLIELISTOWNER          ; owner
            xor     dx,dx                        ; ptda handle
            CALLFAR SegAlloc        ; returns (bx) = selector (ax) = handle

            mov     ax,bx           ; ax:bx = seg:off of buffer to read into
            xor     bx,bx
            xor     cx,cx           ; read whole file
            xor     dx,dx
            push    ax
            call    SYIReadFile

            call    SYICloseFile

            pop     ax              ; recover selector into ax
            pop     cx              ; recover size into cx
            movzx   ecx,cx
            CALLF32 ldrLieListAlloc ; will return selector in ax

            CALLFAR  SegFree        ; free segment, selector in ax

        .endif

        pop   es
        pop   ds
        popa
        ret
EndProc syiOS2VER

;End of LieList changes

INITCODE ends


        FARCODE HIGH32
CINIT_TEXT segment


;**LP   SysInitThread3Thunk - 32-bit thunk to jump to 16-bit code
;
;       This procedure is entered only as a result of a _TKCreateThread
;       call.  It jumps to SysInitThread3 where the real work is done
;       in 16-bit code.
;
;       ENTRY   NONE
;       EXIT    * DOES NOT RETURN *
;       USES    NONE

Procedure SysInitThread3Thunk,near,local
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        add     esp,4                   ; Toss the return to tkIThrdRetError()
        JMP16   SysInitThread3
EndProc SysInitThread3Thunk


CINIT_TEXT ends
        end
