;       SCCSID = @(#)inidin1.asm        6.9 91/12/11
        page    78,132
        title   inidin1, Initialize OS2 - Part 1

SCCSID  equ     "@(#)inidin1.asm        6.9 91/12/11"

;       IBM/Microsoft Confidential
;
;       Copyright (c) IBM Corporation 1987, 1989
;       Copyright (c) Microsoft Corporation 1987, 1989
;
;       All Rights Reserved

; SOURCE FILE NAME: Inidin1
;
; DESCRIPTIVE NAME: Initialize Dos - Part 1
;
; STATUS: CP/DOS version 1.1
;
; FUNCTION: To initialize the CP/DOS Kernel
;
; NOTES:
;   DEPENDENCIES: None
;   RESTRICTIONS: None
;
; ENTRY POINTS: SYIInitOS2
;
; EXTERNAL REFERENCES:
;                KMEnterKModeCallGate - macro to enter kernel mode
;                KMExitKModeCallGate - macro to exit kernel mode
;                GDTAlloc        - Allocate a GDT selector
;                SELInitRM       - Initialize the GDT
;                InitDiskTable   - Initialize disk configuration
;                                  data table
;                IntErr          - Display a fatal message and halt
;                                  the system
;                INTMaskAllInterrupts - Disable all interrupts
;                ProtMode        - Switch to protected mode
;                syiDisplayMessage - Display the system
;                                  version message
;                syiInitComponents - Initialize OS2 components
;                syiInitDataStructures - Initialize OS2 data structures
;                syiInitProcess - Initialize the
;                                  System Initialization Process
;                syiPreInitSIFS - Pre-Initialize the System
;                                  Initialization File System
;                Int 11h         - Equipment determine
;                Int 15h         - Miscellaneous BIOS functions
;---------------------------------------------------------------------------
; Revision History:
; ID    Date     Description
; ----  -------- ------------------------------------------------------------
; D1357 9/3/91   DCR 1357 Suppress boot messages
; 64012 03/16/93 BJH
;                 Setup CMOS location of century byte for
;                 CLOCK01.SYS. This info is put in the
;                 DevConfigTbl in the SAS and is based
;                 upon info received from OS2LDR.
; 148779 03/04/96 CRS
;                 set up CR4 register for debug extensions
; 150371 04/01/96 DR Brown
;                 System Anchor Block
; 152870 05/18/96 Fix regression introduced by defect 148779, trashing AX
; 155985 07/08/96 Turn diskette drive light off for 3 disk boot (BHM)
; 156040 07/17/96 nls: diskette(s) created from utility don't work(BAA)
; 160364 07/17/96 bhm: enable dma and interrupts in digital output register
; 158260 07/23/96 bhm: Turn diskette drive light off when invalid diskette.
; 157841 07/30/96 ajr: Add detection code for cyrix processors.  
;---------------------------------------------------------------------------

        .sall
        .xlist
        .xcref
;;;     include devhdr.inc            ; 149691
        include dosseg.inc            ; Kernel segments
        include basemaca.inc          ; Kernel macros
        include fnoinit.inc
        include osmaca.inc            ; Kernel macros
        include mi.inc
        include basemid.inc           ; Message number equates
        include config.inc            ; DevConfigTbl data structure
        include inisms.inc            ; SysInit Message Segment
        include infoseg.inc           ; Information segment
        include pmode.inc             ; Protect mode data structures
        include struc.inc             ; Structured assembler macros
        include sysinvar.inc          ; Initialization data structure
        include doshlp.inc            ; DosHlp's info
        include tkexport.inc          ; for kmode.inc
        include kmode.inc             ; Enter/Exit Kmode
        include ostypes.inc
        include osconst.inc
        include dossymc.inc
        include sigdef.inc
        include except.inc
        include pgexport.inc
        include vmowner.inc
        include vmexport.inc
        include selxport.inc
        include curdir.inc
        include dirent.inc
        include find.inc
        include screen.inc
        include sem.inc
        include tkptda.inc
        include bpb.inc
        include int.inc                  ; 6.3
        include initmac.inc
        include devsym.inc               ;149691
        .cref
        .list

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)

        ModName  , FNO_INIDIN1_ASM
        CpuMode 386

        ReferGDT        GDT_POOL,WORD             ; Marks start of GDT pool
        ReferGDT        GDT_POOLEND,WORD          ; Marks end of GDT pool
        ReferGDT        GDT_IDT,WORD

        ReferInitGlobal _SELGDTLaddrTmp,dword

        ReferGlobal     _Pentium_Feature_Flags, DWORD           ; 148688

        ReferGlobal     cNMI, DWORD
        ReferGlobal     ABIOS_present,BYTE
        ReferGlobal     DevConfigTbl
        ReferGlobal     _CpuType,BYTE
        ReferGlobal     Header,BYTE
        ReferGlobal     RAS_BIOS_data,BYTE      ; Saved BIOS data
        ReferGlobal     SISData,BYTE            ; Global information segment
        ReferGlobal     OEMdev,BYTE             ; device list
        ReferGlobal     _Sis2,BYTE              ; system infoseg copy
        ReferGlobal     _Lis2,BYTE              ; local infoseg copy
        ReferGlobal     BootBPB,BYTE            ; Boot BPB structure
        ReferGlobal     FileReadBuffer,WORD     ; buffer to read into
        ReferGlobal     _CpuVendor,dword        ; 157841 Intel/Cyrix

        ReferFlat       _BasicHWConfig,word      ; pd
        ReferFlat       _SELGDTLaddr,dword
        ReferFlat       _pTCBCur,dword
        ReferFlat       _pPTDACur,dword


ifdef INFOSTRICT
        ReferFlat       InfoSegsValid,byte
endif

;       External Routines Called or Referenced

        EXTRN32         _SELFreeGDT
        EXTRN32         _SELVirtToLin
        EXTRN32         _TKSetSSBase

        EXTRNF32        _SELEndInit
        EXTRNF32        _TKSetSSBase
        EXTRNF32        KMExitKmodeEvents

        EXTRNFAR        __TKSetSSBase                   ;#94979
        EXTRNFAR        syiSetupForBMP           ;D1357
        EXTRNFAR        AllocateGDTSelector
        EXTRNFAR        PhysToGDTSel
        EXTRNFAR        DosHlpErr
        EXTRNFAR        ExitCritSecUnHoldSig
        EXTRNFAR        WrtToScrnClr
        EXTRNFAR        syiResetVideoMode
        EXTRNFAR        syiBMPRestoreBIOSData   ;149691
        EXTRNFAR        VirtToPhys              ;see virtphys.asm
        EXTRNFAR        w_CallPddIoctl          ;@V2.0SEN01
        EXTRNFAR        GetDescInfo

        extrn           _VMDonateKHB:near
        extrn           KFGotoReal:far
        extrn           KFGotoProt:far
        extrn           CpuStepping:near
        extrn           InitDiskTable:near
        extrn           INTMaskAllInterrupts:near
        extrn           _LDRInitOTE:near
        extrn           ProtMode:near
        extrn           SELInitRM:near
        extrn           syiDisplayMessage:near
        extrn           syiInitOS2Components:near
        extrn           syiInitDataStructures:near
        extrn           syiInitProcess:near
        extrn           syiPreInitSIFS:near
        extrn           syiSetCharDevTable:near
        extrn           TRAPInitRM:near
        extrn           intIRQRouter:near
        extrn           RsrcInit:near
        extrn           ProtModeIC:near
        extrn           RealModeIC:near
        extrn           syiInitSIFS:near
        extrn           syiTermSIFS:near
IFDEF   PMDEBUG
        extrn           DebugInitializeRM:near
        extrn           DebugInitializeDM:near
        extrn           DebugReInitialize:near
ENDIF

        page

INITDATA segment

;       Message table to display the system version message

        extrn           tbl_syibanner:byte

;Table of items accessed in the doshlps

KernelAccessTable       label   dword
        DDFAR   AllocateGDTSelector
        DDFAR   PhysToGDTSel
        DD      KFGotoReal
        DD      KFGotoProt
        DD      offset FLAT:_TKSetSSBase
        DD      offset FLAT:intIRQRouter
        DD      offset FLAT:_SELVirtToLin
        DW      GSEL GDT_IDT
        DD      offset FLAT:cNMI
        DDFAR   w_CallPddIoctl                  ;@V2.0SEN01 16:16 ptr to worker routine
        DDFAR   __TKSetSSBase                   ;#94979
EndKernelAccessTable

;149691   NOTE: dsklabel will be changed each time SyiSwapDiskette is
;149691    called.  dsklabel[5] is also used as a parameter for
;149691    MSG_NEXT_DISKETTE for the diskette number
dsklabel        db      'DISK 1     '
dsklabelsp      db      'SP DISK 2  '
FileBuffAddr    dd      0
tries           db      0
CallsTosyiSwapDiskette  db      0               ;2.88 boot diskette (156040)
KBDSYSName db      "KBD$    "      ;149691

INITDATA ends



INITBSS segment

;       Number of lost messages

        public  syiLostMessages
syiLostMessages dw    0

;       High and low memory sizes

        public  syiLowMem,syiHighMem,syiExtendMem                    ; 159603

syiLowMem       dw    ?               ; size of low memory (in K)
syiHighMem      dw    ?               ; size of high memory (in K)
syiExtendMem    dd    ?               ; size of extend memory (in K) ; 159603

        public  HardDriveCount
HardDriveCount  db      0               ; Number of hard disks attached

        public  OEM_config
OEM_config      dw      ?               ; configuration flags

        public  pBanner
pBanner         dd      ?               ; Pointer to system banner message

        public iKBDCall                           ;149691
                EVEN                              ;149691
iKBDCall        Packet  <>                        ;149691
                db      LENGenIOCTL dup (?)       ;149691
iKBDCall_Data   db      10 dup (0)                ;149691
iKBDCall_Parm   dw      ?                         ;149691

INITBSS ends


CONSTANTS segment
        public  LastDPB
LastDPB         dd      ?               ; Pointer to last DPB in chain

; The following is the jump table used to access the doshlp functions
        public  DHF
DHF     DosHlpFunction  <>              ; DosHlp Function Table
CONSTANTS ends


DATA segment
        public  ArenaInfo, RealInitDS
ArenaInfo       dd      ?               ; pointer to initial arena info
RealInitDS      dw      ?               ; paragraph of DOSINITDATA

        public  ABIOS_Revision
        public  _ABIOS_Revision
_ABIOS_Revision label   byte            ; 'C' interface
ABIOS_Revision  db  ?                   ; BIOS revision level

        public ACHK_FLAG                ;### B730476
ACHK_FLAG       db      0
        public _mFSD_FLAG, mFSD_FLAG
_mFSD_FLAG      label   BYTE                    ; D150371
mFSD_FLAG       db      0
        public _pMiniFSD, pMiniFSD
_pMiniFSD       label   DWORD                   ; D150371
pMiniFSD        dd      0

        public _ulPICMask                       ;6.3
_ulPICMask      dd      0

;       Math coprocessor type

        PUBLIC  NPX_Type
        PUBLIC  _NPX_Type
_NPX_Type   label   byte            ; 'C' interface
NPX_Type            db      0       ; ABIOS presence flag

public  _twodiskboot
_twodiskboot    dw   0


DATA ends

;       Equates for areas saved for RAS Dump

rasintseg       equ 0                 ; segment for interrupt vectors
rasintoff       equ 0                 ; offset for first interrupt vector
rasintlen       equ 80h               ; number of bytes to save

rasromseg       equ 40h               ; segment for ROM data area
rasromoff       equ 0                 ; offset for ROM data area
rasromlen       equ 100h              ; number of bytes to save

;       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


;***EP  SYIInitOS2 - Initialize OS/2
;
;       Intialize the O/S and start the System Initialization Process
;
;       NOTES:   SYIInitOS2 starts running in real mode, then switches to
;       protected mode, ring 0.  It runs  partly in User Mode, and partly in
;       Kernel Mode.  SYIInitOS2 does not return to its caller. It exits
;       directly to the System Initialization Process.
;
;       Note that it is now impossible to address any non-tiled segment until
;       we've gone protected!  All real mode init code is in DOSCODE, but
;       DBPRTs and debugger calls are sure to cause problems.
;
;       LINKAGE Jump (far) from OS2LDR
;       ENTRY   (SS:BX) = address of parameter packet containing:
;                   mi_pArenaInfo = Pointer to arena info array
;                   mi_pbpb       = Pointer to boot BPB
;                   mi_Drive      = Default Drive
;                   mi_BootFlags  = Boot flags
;                   mi_DosHlpSeg  = DosHlp segment
;                   mi_DosHlpLen  = Length of DosHlp segment
;                   mi_DosHlpAddr = Pointer to DosHlp Table
;                   mi_BreakChar  = poosible debugger break char
;                   mi_OEMStra    = strategy address for OEMHLP$
;               CX = _twodiskboot flag (0 = no, 1=yes)
;       EXIT    Exits to syiProcess
;
;       disable interrupts
;       save boot flags in mFSD_FLAG
;       copy DosHlp function table from bios into DHF
;
;       if (this is a debugging Kernel)
;           call DebugInitializeRM to init. the Kernel Debugger for real mode
;
;       call syiPreInitSIFS(BPB) to save the BPB for the boot disk/diskette
;       copy data from parameter list to local variables
;       call DHInit to initialize DosHlps
;       copy low storage information for RAS DUMP
;
;       call SELInitRM(GDT selector base,GDT selector increment,
;       arena information array) to initialize the GDT
;       call syiDetermineHardwareConfiguration to determine the
;       hardware configuration of the machine
;       call INTMaskAllInterrupts to disable all hardware interrupts until
;       device driver register to handle specific interrupts
;       call ProtMode to switch to protected mode
;
;       if (this is a debugging Kernel)
;           call DebugInitializeDM to init. the Kernel Debugger for dual mode
;
;       call syiDisplayMessage(banner msg) to display system version message
;
;       call syiInitDataStructures to initialize major Kernel data structures
;
;       if (this is a debugging Kernel)
;           call DebugReInitialize to reinitialize the Kernel Debugger
;
;       call syiInitOS2Components to initialize all OS2 components
;
;       call syiInitProcess to initialize the System Initialization Process
;
;       call syiSetCharDevTable to set up the character device table with
;       entries for the devices installed so far. We'll need to use them soon.
;
;       exit to the System Initialization Process

Procedure SYIInitOS2,far
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

        cli                           ; disable interrupts
        cld

        DosContext es
;       Copy table of DosHlp offsets passed by the boot loader to the function
;       table of dword pointers
;
;       (ES)    = DOSGROUP
;       (SS:BX) = address of boot loader parameter packet

        lds     si,ss:[bx].mi_DosHlpAddr
        cmp     word ptr [si],DOSHLPVERSION
        je      sid10
        ret                             ; Return to os2ldr if version
                                        ; does not match

sid10:
        mov     es:_twodiskboot,cx

        mov     di,offset DOSGROUP:DHF
        mov     cx,(size DosHlpFunction)/2
        .errnz ((size DosHlpFunction) and 1)
        rep movsw

;       (SS:BX) = address of boot loader parameter packet


        mov     di,ss:[bx].mi_pArenaInfo.lsw    ; arenainfo array

ifdef PMDEBUG

;       The debugger is no longer tiled.  To set up real mode addressibility
;       to the debugger, we must pass in the following:
;
;       ((SS:DI)) = ArenaInfo array

        mov     al,ss:[bx].mi_BreakChar ; pass in break char read by os2ldr
        call    DebugInitializeRM       ; initialize debugger for 386 real mode
endif

        push    ss                      ; (es:di) = arenainfo array
        pop     es
    assume es:nothing

;       (SS:BX) = address of boot loader parameter packet

        DosContext es
        mov     al,ss:[bx].mi_BootFlags
        mov     [mFSD_FLAG],al          ; save mini-FSD/boot flags
        mov     [ACHK_FLAG],al          ; save mini-FSD/boot flags ;### b730476

        mov     dl,ss:[bx].mi_Drive
        lds     si,ss:[bx].mi_pbpb
    assume ds:nothing

;       (DL)    = Boot drive number (0-based)
;       (DS:SI) = address of BPB for boot disk/diskette
;       (ES)    = DOSGROUP
;       (SS:BX) = address of boot loader parameter packet

        push    word ptr ds:[si].PHYDRV  ; save the phys and logical drive
                                         ; picks up CURHD field as logical
                                         ; drive. this is passed in bpb

        call    syiPreInitSIFS  ; save BootBPB

;       Copy data from the parameter list to local variables

        DosContext ds                 ; Use DS to access DOSGROUP

        pop     cx                 ; get logical (in high byte)
        .if     <bit ch and 80h>   ; only if it is really there
          mov   dl, ch             ; put it in dl for following code
        .endif

        test    dl,80h          ; convert BIOS drive id to 1-based number
        jz      short sid20
        and     dl,7fh
        add     dl,2
sid20:  inc     dl
        xor     dh,dh
        mov     [SISData].SIS_BootDrv,dx

;       Initialize the GDT
;       call SELInitRM(arena information array)
;       (eax= R0DS base address, ebx= AI offset w.r.t. R0DS in Protected Mode
;       ds=DOSGROUP, es=DOSINITDATA) = SELInitRM(ES:DI=AI array)
;       (WARNING: EAX, EBX, ECX, EDX, ESI, EDI, DS, ES, FS and GS are modified)
;
;       (DS)    = DOSGROUP
;       (SS:BX) = address of boot loader parameter packet

        ; save the original state of the PIC Mask for VPIC
        ; 6.3 Generic Hardware support
        xor     eax,eax
        in      al,PIC2_PORT1                    ; mask from PIC2
        mov     ah,al
        in      al,PIC1_PORT1                    ; mask from PIC1
        mov     [_ulPICMask],eax                 ; save away

        push    ss                      ; (ES:DI) = ArenaInfo pointer
        pop     es
    assume es:nothing
        mov     di,ss:[bx].mi_pArenaInfo.lsw    ; arenainfo array
        mov     [ArenaInfo].lsw,di
;
; Setup OEMHLP device driver header
;
        mov     si,word ptr ss:[bx].mi_DosHlpSeg    ; si = tiled DOSHELP Seg
        mov     OEMdev.SDevRealCS,si
        mov     OEMdev.SDevRealDS,si                    ; These are all tiled
        mov     OEMdev.SDevProtCS,si
        add     si,8                                    ; Data selector is code
        mov     OEMdev.SDevProtDS,si                    ;  selector plus 8
        mov     si,word ptr ss:[bx].mi_OEMDDStra
        mov     OEMdev.SDevStrat,si
        mov     OEMdev.SDevInt,si

        call    SELInitRM               ; SELInitRM(es:di=ArenaInfo)
    assume es:DOSINITDATA
        DosContext ds                   ; Use DS to access DOSGROUP
        SaveReg <eax, ebx>
        call    TRAPInitRM              ; initialize the IDT (and trap manager)

        RestoreReg <ebx, eax>


;       eax and ebx must be preserved for _PGInit
;
;       (EAX) = R0DS base address
;       (EBX) = R0DS-relative arenainfo pointer
;       (DS)  = DOSGROUP paragraph address
;       (ES)  = DOSINITDATA paragraph address

        mov     [RealInitDS],es         ; save DOSINITDATA paragraph
        push    ds
        pop     fs
    assume fs:DOSGROUP
        push    es
        pop     ds
    assume ds:DOSINITDATA
        push    ax                      ; save ax
        lea     si, KernelAccessTable
        call    DHF.DosHlpInit          ; initialize dosHlps
        mov     OEM_config, ax          ; save configuration flags
        mov     word ptr pBanner, di    ; save pointer to system banner
        mov     word ptr pBanner + 2, es
        pop     ax                      ; restore ax

;       Save interrupt vectors and ROM data areas for RAS Dump
;       NOTE: This must be done before we have a chance to change
;             any of the interrupt vectors or ROM data areas

        DosContext es
    assume es:DOSGROUP, fs:nothing
        lea     di,RAS_BIOS_data      ; ES:DI = address of save area
        push    rasintseg             ; DS:SI = address of interrupt
        pop     ds                    ;         vectors
    assume ds:nothing
        mov     si,rasintoff
        mov     cx,rasintlen/2        ; CX = number of words to save
        rep     movsw                 ; save interrupt vectors

        push    rasromseg             ; DS:SI = address of ROM data
        pop     ds
    assume ds:nothing
        mov     si,rasromoff
        mov     cx,rasromlen/2        ; CX = number of words to save
        rep     movsw                 ; save ROM data

;       Build the Device Configuration Table

;       Save eax and ebx for _PGInit
        push    eax                     ; save R0DS base address
        push    ebx                     ; save R0DS-relative arenainfo pointer

        call    syiDetermineHardwareConfiguration

        call    CpuStepping             ; verify and set cpu stepping

;       Switch to protected mode

        call    ProtMode
    assume ds:nothing, es:nothing, ss:nothing

;       Disable all interrupts

        call    INTMaskAllInterrupts

;       install hardware interrupt handlers in IDT
;
;       Note:
;               We must install hardware interrupt handlers in the IDT
;               immediately after switching to protect mode for the first
;               time.  This is necessary, because of a work around for
;               a 486 bug.  The work around (the "interrupt stretcher")
;               resulted in a situation where a hardware interrupt
;               may become pending at the INTR pin of the 486, after all
;               IRQs have been masked at the pic.  This results in
;               an interrupt at the next STI.  Since the PIC did not
;               expect to have generated an interrupt, it reports a spurious
;               interrupt.
;
;               To solve this, we install a handler that simply IRETs in
;               the descriptor for each hardware interrupt.
;
;               It is important to note that this solution will
;               only work for spurious interrupts.  If a real interrupt
;               occurs, and we just IRET, the system will probably hang
;               while booting, since we did not send an EOI for the interrupt.
;               We will not worry about this at this point since it would
;               take really broken hardware to generate a genuine interrupt
;               with all IRQs masked.  If we decide to solve this problem,
;               it is important to remember that the solution must be
;               guaranteed to not drop any interrupts, or RIPL will be
;               broken.
;

        DosContext <ds>,ax
        call    DHF.DosHlpInstallIRET

;       Initialize the Kernel Debugger

IFDEF PMDEBUG
        call    DebugInitializeDM
ENDIF

;       set up linear stack base variable

        FlatContext <ds,es>,ax
        CALLF32 _TKSetSSBase            ; _TKSSBase = physical addr of ss base

        pop     ebx                     ; (ebx) = R0DS-relative arenainfo ptr
        push    ebx

        CCALL32 _LDRInitOTE,<ebx>       ; _LDRInitOTE(parenainfo)

        DosInitContext ds
        mov     ax,OEM_config           ; pd
      ;;;Pentium check start
        DosContext  es
        cmp     _CpuVendor, CPU_CYRIX   ; 157841 test to see if this is cyrix
        jz      short sid50             ; 157841 yes IBM/Cyrix, can't do cr4
        cmp     [_CpuType],CPU_PENTIUM  ; check for Pentium
        jne     short sid50
        or      ax,CFG_PENTIUM_CPU      ;Turn on the Pentium bit
        mov     OEM_config,ax           ; Update OEM_Config
        push    ax                                                      ;152870
.386p                                                                                   ; 148688
;       mov     eax, cr4                ;                                               ; 148688
        db      00fh,020h,0e0h          ;                                               ; 148688
        mov     edx, _Pentium_Feature_Flags                                             ; 148688
ifdef PMDEBUG                           ;                                               ; 148688
@@:     test    edx, DE_SUPPORTED       ;                                               ; 148688
        jz      @F                      ;                                               ; 148688
        or      eax, CR4_DE             ;                                               ; 148688
endif                                   ;                                               ; 148688
@@:                                     ;                                               ; 148688
;       mov     cr4,eax                 ;                                               ; 148688
        db      00fh,022h,0e0h          ;                                               ; 148688
        pop     ax                                                      ;152870
sid50:
        FlatContext  es
      ;;;Pentium check end
        mov     _BasicHWConfig,ax       ; pd
        mov     eax,[_SELGDTLaddrTmp]
        mov     [_SELGDTLaddr],eax
        DosContext es
        mov     [ArenaInfo].msw,ss      ; save new SS selector value

;       Display the system version message

        lea     si,tbl_syibanner
;D1357  call    syiDisplayMessage
        xor     cx,cx
        CALLFAR WrtToScrnClr            ;Set flag for next WrtToScrn

;       Initialize the system data structures

        pop     ebx                     ; restore R0DS-relative arenainfo ptr
        pop     eax                     ; restore R0DS base address

;       Initialize the major system components.
;       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 this routine)    (low)

        call    syiInitDataStructures

;       Running on the ptda stack.  The asterisked values will be replaced
;       with sysinit's stack and entry point prior to executing the RETFD
;       in the KMExitKmodeCallGate macro at the end of this routine. The
;       stack now contains a sef_s structure.
;
;       WARNING: Nothing should be pushed on the stack before the following
;       call to syiInitProcess.
;       syiInitProcess depends on sef stack frame.

;       Reinitialize the Kernel Debugger

IFDEF PMDEBUG
        call    DebugReInitialize
ENDIF

        DosContext ds,cx
        mov  cx,_twodiskboot
        .if <cx eq 0>                   ; _twodiskboot?
           CALLFAR syiSetupForBMP                ;D1357
        .endif

        call    syiInitOS2Components

;       Initialize the System Initialization Process

        DosInitContext  ds
        DosContext      es

        call    syiInitProcess

;       Initialize the character device table with the entries for the
;       character devices installed so far. This is necessary since we
;       will be needing them soon.

        call    syiSetCharDevTable

        CALL    RsrcInit                ; Init huge resource for LDR

;       Copy the global infoseg into the shared arena.

        DosContext ds,ax
    assume es:nothing
        mov     es,[_Sis2].is_sel               ; get selector of infoseg copy
        xor     di,di
        mov     si,offset DOSGROUP:SISData      ; ds:si = system infoseg
        mov     cx,SIS_LEN SHR 2
        rep     movsd
        mov     cx,SIS_LEN AND 3
        rep     movsb

;       Copy the local infoseg into the shared arena.

        mov     es,[_Lis2].is_sel
        xor     di,di
        mov     si,offset TKOPTDA.ptda_infoseg
        mov     cx,LIS_LEN shr 2
B1EMac  rep     movs dword ptr es:[di], dword ptr ss:[si]
;;B1EMac movs     word ptr es:[di], word ptr ss:[si]  ;; only needed if seg
                                                      ;;  is odd-word length
        .errnz  (LIS_LEN mod 4)

ifdef INFOSTRICT
        FlatContext ds,ax
        mov     [InfoSegsValid],TRUE            ; infosegs are now valid
endif

;       Exit Kmode which will clean the stack
;
;       Exit to the System Initialization Process
;
;       Note: The stack is now set up for a RETURN FAR instruction
;             to make the processor think we are returning from a
;             ring 0 segment (which we are) to a ring 3 segment
;             (which is the code segment for the System Initialization
;             Process).
;
;             The RETURN FAR instruction in the KMExitKmodeCallGate macro
;             which follows loads CS:EIP from the stack (which gets us to
;             syiProcess) and loads SS:ESP (which points to stack
;             segment allocated for the System Initialization Process.

        FlatContext <ds,es>,ax
        KMExitKmodeCallGate 0,noretval,PASCAL,nocheck   ; cbargs is zero

EndProc SYIInitOS2


;***LP  syiDetermineHardwareConfiguration - determine hardware configuration
;
;       Determine the hardware characteristics of the machine we're running on.
;
;       NOTES    syiDetermineHardwareConfiguration runs in real mode.
;       ENTRY   NONE
;       EXIT    NONE
;       USES    Flags
;       EFFECTS Interrupts are disabled
;               DevConfigTbl is initialized with the hardware configuration
;               ABIOS_Revision indicates the BIOS revision level
;               ABIOS_present indicates whether or not ABIOS is supported
;               syiLowMem indicates the number of 1K blocks of memory < 1Meg
;               syiHighMem indicates the number of 1K blocks of memory >= 1Meg
;
;       call DHF.DosHlpConfig & save the following information in DevConfigTbl:
;           Number of printers attached
;           Number of serial ports attached
;           Number of diskette drives attached
;           Type of primary display adapter
;           system model and type values into DevConfigTbl
;       put the BIOS revision level into ABIOS_Revision
;       call DHF.DosHlpSizeMem to determine # of 1k block above and below 1M
;       Check OEM flag to see of ABIOS is present
;       call InitDiskTable to build the disk configuration data table

Procedure syiDetermineHardwareConfiguration
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        SaveReg <ds,es>
        pusha
;       RMONLY                        ; must be called in real mode

;       Determine the equipment configuration

        DosContext ds

        call    DHF.DosHlpConfig      ; Get config info form OEM
                                      ; DL = Number Hard Drives
                                      ; AX = H/W Config
                                      ; BX:CH = Rom Info
                                      ; CL = mono/other video
                                      ; DH = CPU and NPX type
        push    dx                      ; save cpu and npx type
        and     dh, 0fh                 ; isolate CPU type

        test    dh, CPU_CYRIX_MASK      ; 157841 test Cyrix bit
        jz      syidhc10                ; 157841 not Cyrix save cpu type
        and     dh, 7                   ; 157841 mask Cyrix bit
        mov     _CpuVendor, CPU_CYRIX   ; 157841 save Cyrix information
syidhc10:                               ; 157841

        mov     _CpuType,dh             ; save CPU type

        mov     DevConfigTbl.Config_model,bh ; put machine model and
        mov     DevConfigTbl.Config_type,bl  ; type into configuration
                                             ; table
        mov     ABIOS_Revision,ch     ; save BIOS revision level

        mov     bx, ax          ; put equipment flags in safe place
        shr     ax, 13          ; get number of printers in AL
        mov     DevConfigTbl.Config_printers,al
        mov     ax, bx
        shr     ax, 8           ; number of serial cards
        and     al, 1fh         ; mask off unneeded bits
        mov     DevConfigTbl.Config_serial_ports,al
        mov     al,bl
        and     al,0fh          ; Get number of diskettes in al
        mov     DevConfigTbl.Config_diskettes,al
        mov     DevConfigTbl.Config_primary_display,cl

        mov     es,[RealInitDS]         ; (ES) = DOSINITDATA paragraph
    assume es:DOSINITDATA

        ; begin 64012
        .if     <bit OEM_config nand CFG_ABIOS_SUPPORTED>       ; if ABIOS is NOT supported
          mov   ax, bx
          .if   <bit ax and CFGAX_PS2_CENTURY_BYTE>     ; if century byte at PS/2 location
            mov al, CENTURY_BYTE_PS2
          .else                         ; else century byte at AT location
            mov al, CENTURY_BYTE_AT
          .endif
        .else                           ; else ABIOS present
          xor   al, al
        .endif
        mov   DevConfigTbl.Config_century_location, al
        ; end 64012

;       Save the number of Hard Drives

        mov     HardDriveCount,dl       ; DL = Number of Hard Drives

;       Save NPX type

        pop     dx                      ; restore dh= cpu and npx type
        and     dh,0f0h                 ; isolate NPX type
        shr     dh, 4
        mov     NPX_Type, dh  ; save NPX type

;       Determine the low and high memory sizes

        call    DHF.DosHlpSizeMem       ;
        mov     syiLowMem,ax
        mov     syiHighMem,bx
        mov     syiExtendMem,edx        ; 159603

;       Build the disk configuration data table

        call    InitDiskTable

;       Return to caller

        popa
        RestoreReg <es,ds>

        ret

EndProc syiDetermineHardwareConfiguration


;***LP  syiDiscardDosHlp - discard initialization only doshlps
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    AX, BX, CX, DI, DS, ES, Flags
;
;       Inform DosHlp module that Discard is being done.
;       Invalidate the code and data selector for the loader image.
;       call _SELEndInit() to free the memory the loader image occupies.
;       Patch the entries in the DosHlp function table that point to discarded
;       DosHlps to point to DosHlpErr

Procedure syiDiscardDosHlp
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing
        SaveReg <ds,es,gs,eax,ebx,esi>
        DosContext  ds
        call    DHF.DosHlpDiscard       ; inform DosHlp module of discard

        FlatContext <ds,es>,ax          ; prepare for calls

        CCALL32 _SELFreeGDT,<selSysInitCode>    ; free selSysInitCode selector
        CCALL32 _SELFreeGDT,<selSysInitData>    ; free selSysInitData selector

;       call _SELEndInit to Free GDT_SysInit.

        CALLF32 _SELEndInit

        DosContext  ds
        pushad
        mov     di, word ptr  DHF.DosHlpReboot + 2
        xor     dx, dx
;Returns limit to be donated in CX:DX
        CALLFAR GetDescInfo
        jc      cant_donate                      ; error
        movzx   eax, ax              ; set high word of base addr
        shl     eax, 16
        mov     ax,  bx              ; set low word of base addr

        movzx   ebx, cx              ; set high word of limit
        shl     ebx, 16
        mov     bx,  dx              ; set low word of limit

        add     eax, ebx             ; add limit to base addr

        mov     ebx, PAGESIZE        ; ebx = 1000 - (addr & 0xfff)
        mov     dx,  ax
        and     dh,  15
        movzx   edx, dx
        sub     ebx, edx

        FlatContext  ds                          ; prepare for calls
        CCALL32 _VMDonateKHB <eax, ebx, PG_R>
cant_donate:
        popad

; patch up entries in DosHlp function table

        DosContext  ds

        mov     si,DOSGDTDATA
        mov     gs,si
        mov     si,DOSCODE                  ; get DOSCODE

        mov     bl,gs:[si].d_hiaddr         ; get bits 23..16 of base
        mov     bh,gs:[si].d_extaddr        ; get bits 31..17 of base
        shl     ebx,10h                     ; position high 16 bits of base
        mov     bx,gs:[si].d_loaddr         ; get bits 15..0 of base
        MOVFAROFFSET eax,DosHlpErr,DOSCODE      ; 16-bit offset
        add     ebx,eax                         ; add offset - linear addr

; The registers contain the following
;
;       ax      offset of FAR DosHlpErr
;       si      selector of DosHlpErr
;       ebx     linear address of FAR DosHlpErr for 32-bit calls

        mov     word ptr  DHF.DosHlpInit, ax
        mov     word ptr  DHF.DosHlpInit + 2, si
        mov     word ptr  DHF.DosHlpSizeMem, ax
        mov     word ptr  DHF.DosHlpSizeMem + 2, si
        mov     dword ptr DHF.DosHlpInitNPX, ebx
        mov     word ptr  DHF.DosHlpBaseDDList, ax
        mov     word ptr  DHF.DosHlpBaseDDList + 2, si
        mov     dword ptr DHF.DosHlpInitInterrupts, ebx
        mov     word ptr  DHF.DosHlpConfig, ax
        mov     word ptr  DHF.DosHlpConfig + 2, si
        mov     word ptr  DHF.DosHlpGetDriveParms, ax
        mov     word ptr  DHF.DosHlpGetDriveParms + 2, si
        mov     word ptr  DHF.DosHlpReadSectors, ax
        mov     word ptr  DHF.DosHlpReadSectors + 2, si
        mov     word ptr  DHF.DosHlpRealGetMessage, ax
        mov     word ptr  DHF.DosHlpRealGetMessage + 2, si
        mov     word ptr  DHF.DosHlpRegisterTmrDD, ax
        mov     word ptr  DHF.DosHlpRegisterTmrDD + 2, si

        RestoreReg <esi,ebx,eax,gs,es,ds>
        ret
EndProc syiDiscardDosHlp

;***LP  syiSwapDiskette - Prompt user to insert second disk of two-disk boot
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    flags
;

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

;
;      Add this call if we ever decide to swap diskettes after
;      loading the base device drivers in the BASEDDLIST.
;
        CALLFAR    syiResetVideoMode          ;149691
        CALLFAR    syiBMPRestoreBIOSData      ;149691

        push    es                            ; 2.88 boot (156040)
        DosContext es,di                                         ;156040
        mov     di,offset DOSGROUP:BootBPB ; (es:di) -> [BootBPB];156040
                                                                 ;156040
        mov     ax,es:[di].BPB_SectorsPerTrack                   ;156040
        DosInitContext es,di                                     ;156040
                                                                 ;156040
        movzx   di,CallsTosyiSwapDiskette                        ;156040
                                                                 ;156040
        pop     es                                               ;156040
    assume es:nothing                                            ;156040
        cmp      ax,36                                           ;156040
        jne      do_swapwork                                     ;156040
        or       di,di                                           ;156040
        jnz      do_swapwork                                     ;156040
        jmp      firstcall_288                                   ;156040
                                                                 ;156040
do_swapwork:                                                     ;156040
        DosContext   DS,si
        mov             ds,FileReadBuffer       ;ds:si -> directory buffer
        assume ds:nothing
        xor             si,si
        CALLFAR         VirtToPhys              ;ax:bx = physical address
        .if     <c>
          InternalError  <SwapDisk: can not get address of buffer>
        .endif

        test            ax,0FFF0h               ;check for low memory
        .if     <nz>
          InternalError  <SwapDisk: buffer is above the 1M boundary>
        .endif

        ; convert physical address to paragraph aligned segment:offset
        mov di, bx            ; preserve value
        and di, 0fff0h        ; remove low nibble
        or  ax,di             ; high 3 nibbles from low to high word
        ror ax,PARASHIFT      ; get low nibble of phys addr and put in high nibble of segment
        and bx, 0fh           ; save low nibble only, which is in paragraph range

        DosInitContext ds
        mov             FileBuffAddr.msw,ax
        mov             FileBuffAddr.lsw,bx


        DosContext ds
        NullContext  <es,fs,gs>,ax
        call    RealModeIC             ; switch to real mode

        DosContext ds

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

    assume ds:DOSINITDATA, es:DOSINITDATA

	mov     dx, 3f2h                ; turn diskette drive light off (155985)
        mov     al, 0ch                 ; 160364
        out     dx, al                  ; 155985

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,0200h                ; move cursur to top of screen ;149691
        xor     bx,bx                   ; page number                  ;149691
        xor     dx,dx                   ; dh dl are coordinates        ;149691
        int     10H                     ; blank the page               ;149691

        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


        push    ds                      ;save DS
        DosContext ds,ax
        mov     ax,MSG_NEXT_DISKETTE

        call    DHF.DosHlpRealGetMessage; get message pointer DS:SI

        mov     bp,si
        push    ds
        pop     es                      ; segment of message
        pop     ds                      ;restore ds
    assume ds:DOSINITDATA

        mov     cx,word ptr es:[bp]     ; Message length
        inc     bp
        inc     bp

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

nextch:
        mov     ah,0Eh                  ; write teletype
        mov     al,byte ptr es:[bp]     ; character to output

        ;149691  begins
        .if     <al eq '%'>             ; check for fill-in item (%n)
            inc   bp
            dec   cx
            ; mov     al,byte ptr es:[bp] ; pick up the next character
            ; ;At this point, we really should check to make sure al='1',
            ; ;but there's only one fill-in item, so what's the point?
            mov   al, dsklabel[5]
        .endif
        ;149691  ends

        mov     bl,1Fh                  ; Normal attribute
        int     10h
        inc     bp
        dec     cx                      ; Any more chars to output ?
        jnz     nextch

        mov     ax,0920h                ; hide the cursor
        mov     bx,0011h
        mov     cx,1
        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.

    assume  es:NOTHING

disk2:
        mov     byte ptr tries,0
        in      al,PORT_SYSB            ; get current setting
        or      al,SYSB_SPKENABLE + SYSB_SPKGATE    ; set speaker bits on
        out     PORT_SYSB,al            ; turn the speaker on
        mov     cx,0BFFFh               ; delay
hold:   loop    hold

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

;149691 start
        mov          al, CallsTosyiSwapDiskette        ; 2.88 boot (156040)
        cmp     al,0                                             ;156040
        je      trykey_int
      ; This is where we need to switch to prot mode and
      ; Read Keyboard
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        SaveReg  <es,ds>
        call         ProtModeIC         ;switch back to protect mode
        NullContext  <es,ds>,ax
        SaveReg <es,ds,bx,cx,dx,di,si>

      ; 151492
      ; We need to initialize infoseg for the keyboard driver
        DosContext ds,ax
    assume es:nothing
        push    es                       ; save current es
        push    ax
        xor     ax,ax
        mov     es,[_Lis2].is_sel        ; get local infoseg selector
        mov     es:LIS_CurProcID,ax      ; initialize CurProcID to 0
        mov     es:LIS_CurScrnGrp,ax     ; initialize CurScrnGrp to 0
        mov     es:LIS_ProcType,al       ; initialize ProcType to 0
        pop     ax
        pop     es                       ; restore es

        DosInitContext  <ds,es>,ax
        mov     iKBDCall_Parm, 1
        mov     bx,offset iKBDCall
        mov     es:[bx].PktCmd,CMDGenIOCTL
        mov     es:[bx].PktLen,PktHeadSize+LENGenIOCTL
        mov     es:[bx].PktUnit,0
        mov     es:[bx].GIOCategory,04h
        mov     es:[bx].GIOFunction,74h
        mov     ax,ds
        mov     word ptr es:[bx].GIOParaPack.Offst,OFFSET iKBDCall_Parm
        mov     word ptr es:[bx].GIOParaPack.Segmt,ax
        mov     word ptr es:[bx].GIODataPack.Offst,OFFSET iKBDCall_Data
        mov     word ptr es:[bx].GIODataPack.Segmt,ax
        mov     es:[bx].PktStatus,0             ; initialize status
        lea     di,KBDSYSName
        CALLFAR w_CallPddIoctl

        RestoreReg <si,di,dx,cx,bx,ds,es>
        call    RealModeIC             ; switch to real mode
        RestoreReg <ds,es>
    assume ds:DOSINITDATA
        or      ax,ax
        jz      end_trykey   ; if (ax != 0) then error, assume kbd not loaded)
;       jmp     end_trykey
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

trykey_int: ; Wait for a key to be pressed
        mov     ah,0                    ; Read available key
        int     16h                     ; look for key
end_trykey:
;149691 end

dreset: inc     byte ptr tries
        cmp     byte ptr tries,3
        je      disk2

        mov     ah,0                    ; Reset Diskette
        mov     dl,0                    ; drive 0 = a:
        int     13h

; [See if correct diskette label]
        push    es
        DosContext es,di
        mov     di,offset DOSGROUP:BootBPB ; (es:di) -> [BootBPB]

        mov     ax,es:[di].BPB_SectorsPerTrack

        pop     es
    assume es:nothing

;   When we boot from diskette, we must assume the label is the first
;   entry in the root directory.
;   *NOTE* Sector is !NOT! zero based, RBA is
;   *NOTE* 1.2 media RBA is different because FAT's are 2 sectors smaller
;
;    Media  Sect/Track | Cylinder    Head    Sector          RBA
;     1.2       15     |   0          1        1           00000015
;     1.44      18     |   0          1        2           00000019
;     2.88      36     |   0          0       20           00000019
;                      |
;
       ;assume head=1 (most common case)
        mov     dh,1                    ; Head

        cmp     ax,15
        jne     not12
;1.2 media
        mov     cl,1                    ; sector
        jmp short read
not12:
        cmp     ax,18
        jne     not144
;1.4 media
        mov     cl,2                    ; sector
        jmp short read
not144:
;not 1.44, assume 2.88
        mov     dh,0                    ; Head
        mov     cl,20                   ; sector

read:
        mov     ax,FileBuffAddr.msw
        mov     bx,FileBuffAddr.lsw     ; offset of data area
        mov es,ax

  ; es:bx now paragraph:offset

                                        ; CL = Sector # (!NOT! zero based)
                                        ; DH = Head #  (zero based)
        mov     ah,2                    ; Tell BIOS to read
        mov     ch,0                    ; track  (zero based)
        mov     dl,0                    ; drive A:
        mov     al,1                    ; # sectors to read
        int     13h                     ; do the read
        jc      dreset

	mov     dx, 3f2h                ; turn diskette drive light off (158260)
        mov     al, 0ch                 ; 160364
        out     dx, al                  ; 155985

        cld                             ; clear direction
  ;Is it the correct disk (Disk #1, Disk #2, etc, based on the ;149691
  ;number of calls to syiSwapDiskette                          ;149691
        mov     si,offset dsklabel      ; label
        mov     di,FileBuffAddr.lsw     ; disk read buffer
        mov     cx,0Bh                  ; length of volume
        repz    cmpsb                   ; right volume?
        jz      rtvol

  ;Is it Service Pack Disk #2?
        mov     si,offset dsklabelsp    ; label
        mov     di,FileBuffAddr.lsw     ; disk read buffer
        mov     cx,0Bh                  ; length of volume
        repz    cmpsb                   ; right volume?
        jnz     disk2
;####

; got the right volume
rtvol:  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

        inc     dsklabel[5]              ;D1Space Setup for next call  ;149691
        inc     dsklabelsp[8]            ;D1Space (and work for CSD's) ;149691

        push    ds
        pop     es
        call         ProtModeIC         ;switch back to protect mode
        call         syiTermSIFS
        call         syiInitSIFS

firstcall_288:                          ;2.88 boot (156040)
        ; should only be called on the first time thru          ;149691
        ; since we already incr dsklabel[5] check for 2 not 1   ;149691
        DosInitContext  <ds>,ax                                 ;149691
        inc     CallsTosyiSwapDiskette                          ;156040
        mov     al, CallsTosyiSwapDiskette                      ;156040
        cmp     al,1                                            ;156040
        jne     not1d                                           ;149691

doBMP:                                                          ;156040
 
        CALLFAR      syiSetupForBMP

not1d:                                                          ;149691
        popad
        RestoreReg   <ds,es>
        LeaveProc
        ret
EndProc syiSwapDiskette



INITCODE ends
        end
