home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xmm12.zip / XMS20.ZIP / OEMSRC.ZIP / HIMEM.ASM < prev    next >
Assembly Source File  |  1989-02-07  |  84KB  |  2,828 lines

  1. ;*****************************************************************************
  2. ;*                                         *
  3. ;*  HIMEM.ASM -                            Chip Anderson    *
  4. ;*                                         *
  5. ;*    Extended Memory Specification Driver -                     *
  6. ;*        Copyright 1988, Microsoft Corporation                 *
  7. ;*                                         *
  8. ;*    The HMA was originally envisioned by Ralph Lipe.             *
  9. ;*    Original XMS spec designed by Aaron Reynolds, Chip Anderson, and     *
  10. ;*    Tony Gosling.  Additional spec suggestions by Phil Barrett and David *
  11. ;*    Weise of Microsoft, Ed McNierney of Lotus and Bob Smith of Qualitas. *
  12. ;*                                         *
  13. ;*    MoveExtMemory function written by Tony Gosling.                 *
  14. ;*                                         *
  15. ;*    AT&T 6300 support added by Bill Hall, Olivetti ATC, Cupertino, CA    *
  16. ;*    HP Vectra support added by Ralph Peterson, Hewlett Packard Corp.     *
  17. ;*                                         *
  18. ;*****************************************************************************
  19.  
  20. XMSVersion    equ    0200h
  21. HimemVersion    equ    0206h
  22.  
  23. ; Version -
  24. ;
  25. ;   1.00    - Written                    4/17/88
  26. ;   1.01    - Added Global/Temporary Enable of A20        4/18/88
  27. ;   1.02    - Don't use DOS to change interrupts        4/19/88
  28. ;        - Return 1 for success in Disable cases        4/19/88
  29. ;        - Prevent disables if A20 enabled at start    4/19/88
  30. ;        - Added INT 2F handler check            4/19/88
  31. ;        - Used smarter hooking routine            4/19/88
  32. ;   1.03    - Optimized some code                4/20/88
  33. ;        - Temporarily Disable properly            4/20/88
  34. ;        - Disable INT's while changing vars        4/20/88
  35. ;   1.04    - Check to see if A20 works during init        4/23/88
  36. ;        - Fixed PS/2 support                4/23/88
  37. ;   1.05    - Added QueryExtMemory and AllocExtMemory    4/25/88
  38. ;   1.06    - Never remove the INT 15h hook once it is in    4/27/88
  39. ;        - Changed ExtMemory calls to provide "full" MM    4/27/88
  40. ;        - Force A20 line off on PS2's at init time    4/27/88
  41. ;   1.07    - Added Multiple A20 Handler support        5/01/88
  42. ;        - Added popff macro                5/01/88
  43. ;        - REP MOVSW words not bytes            5/04/88
  44. ;   1.08    - Made popff relocateable            5/04/88
  45. ;        - Added support for the AT&T 6300 Plus        5/05/88
  46. ;        - Added support for the HP Vectra        5/06/88
  47. ;   1.09    - Added CEMM recognition code            5/16/88
  48. ;        - Don't automatically trash BX in HMMControl    5/17/88
  49. ;   1.10    - Change PS/2 ID routine to use Watchdog timer    6/02/88
  50. ;        - Changed CEMM recognition string to just VDISK 6/07/88
  51. ;        - Fixed 2 instance bug                6/14/88
  52. ;   1.11    - Changed INT 2F multiplex number to 43h    6/23/88
  53. ;        - Fixed HP Vectra support for older Vectras    6/23/88
  54. ;        - Fixed Block Move register trashing bug    6/25/88
  55. ;   2.00    - Updated to XMS v2.00                7/10/88
  56. ;        - Reworked initialization code            7/12/88
  57. ;        - Reworked reentrancy issues            7/13/88
  58. ;        - Finialized A20 handling            7/14/88
  59. ;        - Added parameter support            7/14/88
  60. ;   2.01    - Official version with Vecta and 6300 support    7/15/88
  61. ;   2.02    - Removed INT 1 from MoveExtMemory        7/19/88
  62. ;        - Fixed minor problems in QueryExtMemory    7/19/88
  63. ;   2.03    - Added 386 Big Mode MoveBlock            8/04/88
  64. ;        - Added Compaq "Built-In" Memory support    8/05/88
  65. ;        - Fixed 64K-free Installation bug        8/05/88
  66. ;        - Change PS/2 detection code yet again        8/08/88
  67. ;   2.04    - Fixed "A20 On" Message bug (ugh)        8/09/88
  68. ;        - Fixed A20 Init testing code            8/09/88
  69. ;        - Cleaned up for publication            8/09/88
  70. ;   2.05    - Bug Fix: Subtract 64K from first EMB for HMA 11/30/88
  71. ;        - Bug Fix: Check for NUMHANDLES=0 case           12/14/88
  72. ;   2.06    - Source code update                2/07/89
  73.  
  74.         name    Himem
  75.         title   'HIMEM.SYS - Microsoft XMS Device Driver'
  76.  
  77. ;*--------------------------------------------------------------------------*
  78. ;*    EQUATES                                    *
  79. ;*--------------------------------------------------------------------------*
  80.  
  81. DEFHANDLES        equ    32        ; Default # of EMB handles
  82. MAXHANDLES        equ    128        ; Max # of EMB handles
  83.  
  84. cXMSFunctions        equ    12h        ; = # of last function+1!
  85.  
  86. FREEFLAG        equ    00000001b    ; EMB Flags
  87. USEDFLAG        equ    00000010b
  88. UNUSEDFLAG        equ    00000100b
  89.  
  90. ; XMS Error Codes.
  91. ERR_NOTIMPLEMENTED    equ    080h
  92. ERR_VDISKFOUND        equ    081h
  93. ERR_A20            equ    082h
  94. ERR_GENERAL        equ    08Eh
  95. ERR_UNRECOVERABLE    equ    08Fh
  96.  
  97. ERR_HMANOTEXIST        equ    090h
  98. ERR_HMAINUSE        equ    091h
  99. ERR_HMAMINSIZE        equ    092h
  100. ERR_HMANOTALLOCED    equ    093h
  101.  
  102. ERR_OUTOMEMORY        equ    0A0h
  103. ERR_OUTOHANDLES        equ    0A1h
  104. ERR_INVALIDHANDLE    equ    0A2h
  105. ERR_SHINVALID        equ    0A3h
  106. ERR_SOINVALID        equ    0A4h
  107. ERR_DHINVALID        equ    0A5h
  108. ERR_DOINVALID        equ    0A6h
  109. ERR_LENINVALID        equ    0A7h
  110. ERR_OVERLAP        equ    0A8h
  111. ERR_PARITY        equ    0A9h
  112. ERR_EMBUNLOCKED        equ    0AAh
  113. ERR_EMBLOCKED        equ    0ABh
  114. ERR_LOCKOVERFLOW    equ    0ACh
  115. ERR_LOCKFAIL        equ    0ADh
  116.  
  117. ERR_UMBSIZETOOBIG    equ    0B0h
  118. ERR_NOUMBS        equ    0B1h
  119. ERR_INVALIDUMB        equ    0B2h
  120.  
  121. .386p
  122.  
  123. ; In order to address memory above 1 MB on the AT&T 6300 PLUS, it is
  124. ; necessary to use the special OS-MERGE hardware to activate lines
  125. ; A20 to A23.  However, these lines can be disabled only by resetting
  126. ; the processor.  The address to which to return after reset are placed
  127. ; at 40:A2, noted here as RealLoc1.
  128.  
  129. BiosSeg SEGMENT USE16 AT 40h          ; Used to locate 6300 PLUS reset address
  130.  
  131.         org    00A2h
  132. RealLoc1    dd    0
  133.  
  134. BiosSeg ends
  135.  
  136.  
  137. ; Macro to avoid the 286 POPF bug.  Performs a harmless IRET to simulate a
  138. ;   popf.  Some 286s allow interrupts to sneak in during a real popf.
  139.  
  140. popff        macro
  141.         push    cs
  142.         call    pPPFIRet    ; Defined as the offset of any IRET
  143.         endm
  144.  
  145. ;*--------------------------------------------------------------------------*
  146. ;*        SEGMENT DEFINITION                            *
  147. ;*--------------------------------------------------------------------------*
  148.  
  149. CODE        SEGMENT PARA PUBLIC USE16 'CODE'
  150.  
  151.         assume  cs:code,ds:code,es:code
  152.  
  153.         org        0
  154.  
  155. ; The Driver Header definition.
  156. Header        dd    -1        ; Link to next driver, -1 = end of list
  157.         dw    1010000000000000b
  158.                     ; Device attributes, Non-IBM bit set
  159.         dw    Strategy    ; "Stategy" entry point
  160.         dw    Interrupt   ; "Interrupt" entry point
  161.         db    'XMSXXXX0'  ; Device name
  162.  
  163.  
  164. ;****************************************************************************
  165. ;*                                        *
  166. ;*  Data Structures and Global Variables -                    *
  167. ;*                                        *
  168. ;****************************************************************************
  169.  
  170. ; The driver Request Header structure definition.
  171. ReqHdr struc
  172.     ReqLen    db    ?
  173.     Unit    db    ?
  174.     Command    db    ?
  175.     Status    dw    ?
  176.     Reserved    db    8 dup (?)
  177.     Units    db    ?
  178.     Address    dd    ?
  179.     pCmdLine    dd    ?
  180. ReqHdr ends
  181.  
  182. ; An EMB Handle structure definition.
  183. Handle struc            ; Handle Table Entry
  184.     Flags    db    ?    ; Unused/InUse/Free
  185.     cLock    db    ?    ; Lock count
  186.     Base    dw    ?    ; 32-bit base address in K
  187.     Len        dw    ?    ; 32-bit length in K
  188. Handle ends
  189.  
  190. ; Extended Memory Move Block structure definition.
  191. MoveExtendedStruc struc
  192.     bCount        dd    ?    ; Length of block to move
  193.     SourceHandle    dw    ?    ; Handle for souce
  194.     SourceOffset    dd    ?    ; Offset into source
  195.     DestHandle        dw    ?    ; Handle for destination
  196.     DestOffset        dd    ?    ; Offset into destination
  197. MoveExtendedStruc ends
  198.  
  199. ; The Global variables.
  200. pPPFIRet    dw    PPFIRet ; The offset of an IRET for the POPFF macro
  201. pReqHdr        dd    ?    ; Pointer to MSDOS Request Header structure
  202. pInt15Vector    dw    15h*4,0 ; Pointer to the INT 15 Vector
  203. PrevInt15    dd    0    ; Original INT 15 Vector
  204. PrevInt2F    dd    0    ; Original INT 2F Vector
  205. fHMAInUse    db    0    ; High Memory Control Flag, != 0 -> In Use
  206. fCanChangeA20    db    0    ; A20 Enabled at start?
  207. fHMAMayExist    db    0    ; True if the HMA could exist at init time
  208. fHMAExists    db    0    ; True if the HMA exists
  209. fVDISK        db    0    ; True if a VDISK device was found
  210. EnableCount    dw    0    ; A20 Enable/Disable counter
  211. fGlobalEnable    dw    0    ; Global A20 Enable/Disable flag
  212. KiddValley    dw    0    ; The address of the handle table 
  213. KiddValleyTop    dw    0    ; Points to the end of the handle table
  214. MinHMASize    dw    0        ; /HMAMIN= parameter value
  215. cHandles    dw    DEFHANDLES  ; # of handles to allocate
  216.  
  217. cImplementedFuncs db    cXMSFunctions-3        ; Omit the UMB functions
  218.                         ; and ReallocEMB
  219.  
  220. A20Handler    dw    0    ; Offset of the A20 Handler
  221.  
  222. BIMBase     dw    0    ; Base address and Lenght of remaining Compaq
  223. BIMLength    dw    0    ;   Built-In Memory (set at Init time)
  224.  
  225. MemCorr        dw    0    ; KB of memory at FA0000 on AT&T 6300 Plus.
  226.                 ;      This is used to correct INT 15h,
  227.                 ;      Function 88h return value.
  228. OldStackSeg    dw    0    ; Stack segment save area for 6300 Plus.
  229.                 ;      Needed during processor reset.
  230.  
  231. ;*--------------------------------------------------------------------------*
  232. ;*                                        *
  233. ;*  Strategy -                                    *
  234. ;*                                        *
  235. ;*    Called by MS-DOS when ever the driver is accessed.            *
  236. ;*                                        *
  237. ;*  ARGS:   ES:BX = Address of Request Header                    *
  238. ;*  RETS:   Nothing                                *
  239. ;*  REGS:   Preserved                                *
  240. ;*                                        *
  241. ;*--------------------------------------------------------------------------*
  242.  
  243. Strategy    proc    far
  244.  
  245.         ; Save the address of the request header.
  246.         mov        word ptr cs:[pReqHdr],bx
  247.         mov        word ptr cs:[pReqHdr][2],es
  248.         ret
  249.  
  250. Strategy    endp
  251.  
  252.  
  253. ;*--------------------------------------------------------------------------*
  254. ;*                                        *
  255. ;*  Interrupt -                                    *
  256. ;*                                        *
  257. ;*    Called by MS-DOS immediately after Strategy routine            *
  258. ;*                                        *
  259. ;*  ARGS:   None                                *
  260. ;*  RETS:   Return code in Request Header's Status field            *
  261. ;*  REGS:   Preserved                                *
  262. ;*                                        *
  263. ;*--------------------------------------------------------------------------*
  264.  
  265. Interrupt   proc    far
  266.  
  267.         ; Save the registers including flags.
  268.         push    ax            ; We cannot use pusha\popa because
  269.         push    bx            ;    we could be on an 8086 at this point
  270.         push    cx
  271.         push    dx
  272.         push    ds
  273.         push    es
  274.         push    di
  275.         push    si
  276.         push    bp
  277.         pushf
  278.  
  279.         ; Set DS=CS for access to global variables.
  280.         push    cs
  281.         pop        ds
  282.  
  283.         les        di,[pReqHdr]    ; ES:DI = Request Header
  284.  
  285.         mov     bl,es:[di.Command]    ; Get Function code in BL
  286.  
  287.         or        bl,bl        ; Only Function 00h (Init) is legal
  288.         jz        short IInit
  289.  
  290.         cmp     bl,16        ; Test for "legal" DOS functions
  291.         jle     short IOtherFunc
  292.  
  293. IBogusFunc: mov     ax,8003h        ; Return "Unknown Command"
  294.         jmp     short IExit
  295.  
  296. IOtherFunc: xor     ax,ax        ; Return zero for unsupported functions
  297.         jmp     short IExit
  298.  
  299.         ; Initialize the driver.
  300. IInit:        call    InitDriver
  301.  
  302.         les        di,[pReqHdr]    ; Restore ES:DI = Request Header
  303.  
  304. IExit:        or        ax,0100h        ; Turn on the "Done" bit
  305.         mov        es:[di.Status],ax    ; Store return code
  306.  
  307.         ; Restore the registers.
  308.         popff
  309.         pop        bp
  310.         pop        si
  311.         pop        di
  312.         pop        es
  313.         pop        ds
  314.         pop        dx
  315.         pop        cx
  316.         pop        bx
  317.         pop        ax
  318.         ret
  319.  
  320. Interrupt   endp
  321.  
  322.  
  323. ;*--------------------------------------------------------------------------*
  324. ;*                                        *
  325. ;*  Int2FHandler -                                *
  326. ;*                                        *
  327. ;*    Hooks Function 43h, Subfunction 10h to return the            *
  328. ;*    address of the High Memory Manager Control function.            *
  329. ;*    Also returns 80h if Function 43h, Subfunction 0h is requested.        *
  330. ;*                                        *
  331. ;*  ARGS:   AH = Function, AL = Subfunction                    *
  332. ;*  RETS:   ES:BX = Address of XMMControl function (if AX=4310h)        *
  333. ;*        AL = 80h (if AX=4300)                        *
  334. ;*  REGS:   Preserved except for ES:BX (if AX=4310h)                *
  335. ;*        Preserved except for AL    (if AX=4300h)                *
  336. ;*                                        *
  337. ;*--------------------------------------------------------------------------*
  338.  
  339. Int2FHandler proc   far
  340.  
  341.         sti                    ; Flush any queued interrupts
  342.  
  343.         cmp        ah,43h            ; Function 43h?
  344.         jne     short I2FNextInt
  345.         or        al,al            ; Subfunction 0?
  346.         jne     short I2FNextSub        ; No, continue
  347.  
  348.         ; Indicate that an XMS driver is installed.
  349.         mov        al,80h            ; Return 80h in AL
  350. PPFIRet:    iret                ; Label sets up the POPFF macro
  351.  
  352. I2FNextSub: cmp        al,10h            ; Subfunction 10?
  353.         jne     short I2FNextInt        ; No, goto next handler
  354.  
  355.         ; Return the address of the XMS Control function in ES:BX.
  356.         push    cs
  357.         pop        es
  358.         mov        bx,offset XMMControl
  359.         iret
  360.  
  361.         ; Continue down the Int 2F chain.
  362. I2FNextInt: cli                    ; Disable interrupts again
  363.         jmp        cs:[PrevInt2F]
  364.  
  365. Int2FHandler endp
  366.  
  367.  
  368. ;*--------------------------------------------------------------------------*
  369. ;*                                        *
  370. ;*  ControlJumpTable -                                *
  371. ;*                                        *
  372. ;*    Contains the address for each of the XMS Functions.            *
  373. ;*                                        *
  374. ;*--------------------------------------------------------------------------*
  375.  
  376. ControlJumpTable label word
  377.         dw        Version            ; Function 00h
  378.         dw        RequestHMA            ; Function 01h
  379.         dw        ReleaseHMA            ; Function 02h
  380.         dw        GlobalEnableA20        ; Function 03h
  381.         dw        GlobalDisableA20        ; Function 04h
  382.         dw        LocalEnableA20        ; Function 05h
  383.         dw        LocalDisableA20        ; Function 06h
  384.         dw        IsA20On            ; Function 07h
  385.         dw        QueryExtMemory        ; Function 08h
  386.         dw        AllocExtMemory        ; Function 09h
  387.         dw        FreeExtMemory        ; Function 0Ah
  388.         dw        MoveBlock            ; Function 0Bh
  389.         dw        LockExtMemory        ; Function 0Ch
  390.         dw        UnlockExtMemory        ; Function 0Dh
  391.         dw        GetExtMemoryInfo        ; Function 0Eh
  392.  
  393.         ; We don't implement Realloc in this version.
  394. ;        dw        ReallocExtMemory        ; Function 0Fh
  395.  
  396.         ; We don't implement the UMB functions.
  397. ;        dw        RequestUMB            ; Function 14
  398. ;        dw        ReleaseUMB            ; Function 15
  399.  
  400.  
  401. ;*--------------------------------------------------------------------------*
  402. ;*                                        *
  403. ;*  XMMControl -                                *
  404. ;*                                        *
  405. ;*    Main Entry point for the Extended Memory Manager            *
  406. ;*                                        *
  407. ;*  ARGS:   AH = Function, AL = Optional parm                    *
  408. ;*  RETS:   AX = Function Success Code, BL = Optional Error Code        *
  409. ;*  REGS:   AX, BX, DX and ES may not be preserved depending on function    *
  410. ;*                                        *
  411. ;*  INTERNALLY REENTRANT                            *
  412. ;*                                        *
  413. ;*--------------------------------------------------------------------------*
  414.  
  415. XMMControl  proc   far
  416.  
  417.         jmp        short XCControlEntry    ; For "hookability"
  418.         nop                    ; NOTE: The jump must be a 
  419.         nop                    ;  short jump to indicate
  420.         nop                    ;  the end of any hook chain.
  421.                         ;  The nop's allow a far jump
  422.                         ;  to be patched in.
  423. XCControlEntry:
  424.         ; Preserve the following registers.
  425.         push    cx
  426.         push    si
  427.         push    di
  428.         push    ds
  429.         push    es
  430.         pushf
  431.  
  432.         ; Save DS in ES.
  433.         push    ds
  434.         pop        es            ; NOTE: ES cannot be used for parms!
  435.         
  436.         ; Set DS equal to CS.
  437.         push    cs
  438.         pop        ds
  439.         
  440.         ; Preserve the current function number.
  441.         push    ax
  442.  
  443.         ; Is this a call to "Get XMS Version"?
  444.         or        ah,ah
  445.         jz        short XCCallFunc      ; Yes, don't hook INT 15h yet
  446.         
  447.         ; Is this a valid function number?
  448.         cmp        ah,[cImplementedFuncs]
  449.         jb        short XCCheckHook
  450.         pop        ax            ; No, Un-preserve AX and return an error
  451.         xor        ax,ax
  452.         mov        bl,ERR_NOTIMPLEMENTED
  453.         jmp        short XCExit
  454.  
  455.         ; Is INT 15h already hooked?
  456. XCCheckHook:pushf
  457.         cli                ; This is a critical section
  458.         
  459.         cmp        word ptr [PrevInt15][2],0    ; Is the segment non-zero?
  460.         jne     short XCCheckVD
  461.  
  462.         ; Try to claim all remaining extended memory.
  463.         call    HookInt15
  464.  
  465.         ; Was a VDISK device found?
  466. XCCheckVD:  popff            ; End of critical section
  467.         cmp        [fVDISK],0
  468.         je        short XCCallFunc
  469.         pop        ax            ; Yes, Un-preserve AX and return an error
  470.         xor        ax,ax
  471.         mov        bl,ERR_VDISKFOUND
  472.         xor        dx,dx
  473.         jmp        short XCExit
  474.  
  475.         ; Call the appropriate API function.        
  476. XCCallFunc: pop        ax            ; Restore AX
  477.         mov        al,ah
  478.         xor        ah,ah
  479.         shl        ax,1
  480.         mov        di,ax        ; NOTE: DI cannot be used for parms!
  481.         
  482.         call    word ptr [ControlJumpTable+di]
  483.  
  484.         ; Restore the preserved registers.
  485. XCExit:        popff            ; NOTE: Flags must be restored immediately
  486.         pop        es            ;    after the call to the API functions.
  487.         pop        ds
  488.         pop        di
  489.         pop        si
  490.         pop        cx
  491.         ret
  492.  
  493. XMMControl  endp
  494.  
  495.  
  496. ;*--------------------------------------------------------------------------*
  497. ;*                                        *
  498. ;*  Get XMS Version Number -                    FUNCTION 00h    *
  499. ;*                                        *
  500. ;*    Returns the XMS version number                        *
  501. ;*                                        *
  502. ;*  ARGS:   None                                *
  503. ;*  RETS:   AX = XMS Version Number                        *
  504. ;*        BX = Internal Driver Version Number                    *
  505. ;*        DX = 1 if HMA exists, 0 if it doesn't                *
  506. ;*  REGS:   AX, BX and DX are clobbered                        *
  507. ;*                                        *
  508. ;*  INTERNALLY REENTRANT                            *
  509. ;*                                        *
  510. ;*--------------------------------------------------------------------------*
  511.  
  512. Version        proc    near
  513.  
  514.         mov        ax,XMSVersion
  515.         mov        bx,HimemVersion
  516.         xor        dh,dh
  517.  
  518.         ; Is Int 15h hooked?
  519.         cmp        word ptr [PrevInt15][2],0    ; Is the segment non-zero?
  520.         jne     short VHooked
  521.         mov        dl,[fHMAMayExist]        ; No, return the status at
  522.         ret                    ;  init time.
  523.  
  524. VHooked:    mov        dl,[fHMAExists]        ; Yes, return the real status
  525.         ret
  526.  
  527. Version        endp
  528.  
  529.  
  530. ;*--------------------------------------------------------------------------*
  531. ;*                                        *
  532. ;*  HookInt15 -                                    *
  533. ;*                                        *
  534. ;*    Insert the INT 15 hook                            *
  535. ;*                                        *
  536. ;*  ARGS:   None                                *
  537. ;*  RETS:   None                                *
  538. ;*  REGS:   AX, BX, CS, DI, SI, and Flags are clobbered                *
  539. ;*                                        *
  540. ;*  EXTERNALLY NON-REENTRANT                            *
  541. ;*    Interrupts must be disabled before calling this function.        *
  542. ;*                                        *
  543. ;*--------------------------------------------------------------------------*
  544.  
  545. HookInt15   proc    near
  546.  
  547.         push    es
  548.     
  549.         ; Has a VDISK device been installed?        
  550.         call    IsVDISKIn
  551.         cmp        [fVDISK],0
  552.         je        short HINoVD    ; No, continue
  553.         pop        es            ; Yes, return without hooking
  554.         ret
  555.         
  556. HINoVD:        mov        ah,88h        ; Is 64K of Extended memory around?
  557.         int        15h
  558.         sub        ax,[MemCorr]    ; 6300 Plus may have memory at FA0000h
  559.         cmp        ax,64
  560.         jb        short HIInitMemory    ; Less than 64K free?  Then no HMA.
  561.         mov        [fHMAExists],1
  562.  
  563. HIInitMemory:
  564.         ; Init the first handle to be one huge free block.
  565.         mov        bx,[KiddValley]
  566.         mov        [bx.Flags],FREEFLAG
  567.         mov        [bx.Len],ax
  568.         mov     [bx.Base],1024
  569.  
  570.         ; Reserve room for the HMA if it exists.    11-30-88 ChipA
  571.         cmp        [fHMAExists],0
  572.         je        short HICont
  573.         add     [bx.Base],64
  574.         sub     [bx.Len],64
  575.  
  576.         ; See if any Compaq "Built In Memory" exists.
  577. HICont:     mov     ax,[BIMBase]
  578.         or        ax,ax
  579.         jz        short HIHookEmHorns
  580.  
  581.         mov     cx,[BIMLength]
  582.  
  583.         ; Fill out the next handle entry.
  584.         add     bx,size Handle
  585.         mov        [bx.Flags],FREEFLAG
  586.         mov     [bx.Len],cx
  587.         mov     [bx.Base],ax
  588.  
  589.         ; Save the current INT 15 vector.
  590. HIHookEmHorns:
  591.         les     si,dword ptr pInt15Vector
  592.  
  593.         ; Exchange the old vector with the new one.
  594.         mov        ax,offset Int15Handler
  595.         xchg    ax,es:[si][0]
  596.         mov        word ptr [PrevInt15][0],ax
  597.         mov        ax,cs
  598.         xchg    ax,es:[si][2]
  599.         mov        word ptr [PrevInt15][2],ax
  600.         
  601.         pop        es
  602.         ret
  603.  
  604. HookInt15   endp
  605.  
  606.  
  607. ;*--------------------------------------------------------------------------*
  608. ;*                                        *
  609. ;*  IsVDISKIn -                                    *
  610. ;*                                        *
  611. ;*    Looks for drivers which use the IBM VDISK method of allocating        *
  612. ;*  Extended Memory.  XMS is incompatible with the VDISK method.        *
  613. ;*                                        *
  614. ;*  ARGS:   None                                *
  615. ;*  RETS:   None.  Sets "fVDISK" accordingly                    *
  616. ;*  REGS:   AX, CX, SI, DI and Flags are clobbered                *
  617. ;*                                        *
  618. ;*  INTERNALLY REENTRANT                            *
  619. ;*                                        *
  620. ;*--------------------------------------------------------------------------*
  621.  
  622. pVDISK        label   dword
  623.         dw        00013h
  624.         dw        0FFFFh
  625.         
  626. szVDISK        db        'VDISK'           
  627.  
  628. IsVDISKIn   proc    near
  629.  
  630.         ; Look for "VDISK" starting at the 4th byte of extended memory.
  631.         call    LocalEnableA20        ; Turn on A20
  632.  
  633.         push    ds
  634.         push    es
  635.  
  636.         ; Set up the comparison.
  637.         lds        si,cs:pVDISK
  638.         push    cs
  639.         pop        es
  640.         mov        di,offset szVDISK
  641.         mov        cx,5
  642.         cld
  643.         rep     cmpsb            ; Do the comparison
  644.  
  645.         pop     es                ; Restore ES and DS
  646.         pop     ds
  647.  
  648.         jz        short IVIFoundIt
  649.         mov     [fVDISK],0            ; No VDISK device found
  650.         jmp        short IVIExit
  651.         
  652.         ; "VDISK" was found.
  653. IVIFoundIt: mov        [fVDISK],1
  654.  
  655. IVIExit:    call    LocalDisableA20
  656.         ret                 ; Turn off A20
  657.  
  658. IsVDISKIn   endp
  659.  
  660.  
  661. ;*--------------------------------------------------------------------------*
  662. ;*                                        *
  663. ;*  Int15Handler -                                *
  664. ;*                                        *
  665. ;*    Hooks Function 88h to return zero as the amount of extended        *
  666. ;*    memory available in the system.                        *
  667. ;*                                        *
  668. ;*    Hooks Function 87h and preserves the state of A20 across the        *
  669. ;*    block move.                                *
  670. ;*                                        *
  671. ;*  ARGS:   AH = Function, AL = Subfunction                    *
  672. ;*  RETS:   AX = 0 (if AH == 88h)                        *
  673. ;*  REGS:   AX is clobbered                            *
  674. ;*                                        *
  675. ;*--------------------------------------------------------------------------*
  676.  
  677. I15RegSave  dw        ?
  678.  
  679. Int15Handler proc   far
  680.  
  681.         ; Is this a request for the amount of free extended memory?
  682.         cmp        ah,88h
  683.         jne     short I15HCont    ; No, continue
  684.  
  685.         xor     ax,ax        ; Yes, return zero
  686.         iret
  687.  
  688.         ; Is it a Block Move?
  689. I15HCont:   cmp        ah,87h
  690.         jne     short I15HNext    ; No, continue
  691.  
  692.         ; Int 15h Block Move:
  693.         cli             ; Make sure interrupts are off
  694.  
  695.         ; Store the A20 line's state.
  696.         pusha            ; Preserve the registers
  697.         call    IsA20On
  698.         mov        cs:[I15RegSave],ax
  699.         popa            ; Restore the registers
  700.  
  701.         ; Call the previous Int 15h handler.
  702.         pushf            ; Simualate an interrupt
  703.         call    cs:[PrevInt15]
  704.         pusha            ; Preserve previous handler's return
  705.  
  706.         ; Was A20 on before?
  707.         cmp        cs:[I15RegSave],0
  708.         je        short I15HExit    ; No, continue
  709.         mov     ax,1
  710.         call    cs:[A20Handler]    ; Yes, turn A20 back on
  711.  
  712. I15HExit:   popa            ; Restore the previous handler's return
  713.         iret
  714.  
  715.         ; Continue down the Int 15h chain.
  716. I15HNext:   jmp     cs:[PrevInt15]
  717.  
  718. Int15Handler endp
  719.  
  720.  
  721. ;*--------------------------------------------------------------------------*
  722. ;*                                        *
  723. ;*  RequestHMA -                        FUNCTION 01h    *
  724. ;*                                        *
  725. ;*    Give caller control of the High Memory Area if it is available.        *
  726. ;*                                        *
  727. ;*  ARGS:   DX = HMA space requested in bytes                    *
  728. ;*  RETS:   AX = 1 if the HMA was reserved, 0 otherwise.  BL = Error Code   *
  729. ;*  REGS:   AX, BX and Flags clobbered                        *
  730. ;*                                        *
  731. ;*  INTERNALLY NON-REENTRANT                            *
  732. ;*                                        *
  733. ;*--------------------------------------------------------------------------*
  734.  
  735. RequestHMA  proc   near
  736.  
  737.         cli                ; This is a non-reentrant function.
  738.                     ;    Flags are restored after the return.        
  739.         mov        bl,ERR_HMAINUSE
  740.         cmp        [fHMAInUse],1   ; Is the HMA already allocated?
  741.         je        short RHRetErr
  742.  
  743.         mov        bl,ERR_HMANOTEXIST
  744.         cmp        [fHMAExists],0  ; Is the HMA available?
  745.         je        short RHRetErr
  746.  
  747.         mov        bl,ERR_HMAMINSIZE
  748.         cmp        dx,[MinHMASize] ; Is this guy allowed in?
  749.         jb        short RHRetErr
  750.  
  751.         mov        ax,1
  752.         mov        [fHMAInUse],al  ; Reserve the High Memory Area
  753.         xor     bl,bl        ; Clear the error code
  754.         ret
  755.  
  756. RHRetErr:   xor     ax,ax        ; Return failure with error code in BL
  757.         ret
  758.  
  759. RequestHMA  endp
  760.  
  761.  
  762. ;*--------------------------------------------------------------------------*
  763. ;*                                        *
  764. ;*  ReleaseHMA -                        FUNCTION 02h    *
  765. ;*                                        *
  766. ;*    Caller is releasing control of the High Memory area            *
  767. ;*                                        *
  768. ;*  ARGS:   None                                *
  769. ;*  RETS:   AX = 1 if control is released, 0 otherwise.     BL = Error Code    *
  770. ;*  REGS:   AX, BX and Flags clobbered                        *
  771. ;*                                        *
  772. ;*  INTERNALLY NON-REENTRANT                            *
  773. ;*                                        *
  774. ;*--------------------------------------------------------------------------*
  775.  
  776. ReleaseHMA  proc   near
  777.  
  778.         cli                ; This is a non-reentrant function
  779.         
  780.         ; Is the HMA currently in use?
  781.         mov        al,[fHMAInUse]
  782.         or        al,al
  783.         jz        short RLHRetErr ; No, return error
  784.         
  785.         ; Release the HMA and return success.
  786.         mov        [fHMAInUse],0
  787.         mov        ax,1
  788.         xor        bl,bl
  789.         ret
  790.         
  791. RLHRetErr:  xor        ax,ax
  792.         mov        bl,ERR_HMANOTALLOCED
  793.         ret           
  794.  
  795. ReleaseHMA  endp
  796.  
  797.  
  798. ;*--------------------------------------------------------------------------*
  799. ;*                                        *
  800. ;*  GlobalEnableA20 -                        FUNCTION 03h    *
  801. ;*                                        *
  802. ;*    Globally enable the A20 line                        *
  803. ;*                                        *
  804. ;*  ARGS:   None                                *
  805. ;*  RETS:   AX = 1 if the A20 line is enabled, 0 otherwise.  BL = Error        *
  806. ;*  REGS:   AX, BX and Flags clobbered                        *
  807. ;*                                        *
  808. ;*  INTERNALLY NON-REENTRANT                            *
  809. ;*                                        *
  810. ;*--------------------------------------------------------------------------*
  811.  
  812. GlobalEnableA20 proc near
  813.  
  814.         cli                ; This is a non-reentrant function
  815.  
  816.         ; Is A20 already globally enabled?
  817.         cmp        [fGlobalEnable],1
  818.         je        short GEARet
  819.  
  820.         ; Attempt to enable the A20 line.
  821.         call    LocalEnableA20
  822.         or        ax,ax
  823.         jz        short GEAA20Err
  824.  
  825.         ; Mark A20 as globally enabled.
  826.         mov        [fGlobalEnable],1
  827.  
  828.         ; Return success.
  829. GEARet:        mov        ax,1
  830.         xor        bl,bl
  831.         ret
  832.  
  833.         ; Some A20 error occured.
  834. GEAA20Err:  mov        bl,ERR_A20
  835.         xor        ax,ax
  836.         ret
  837.  
  838. GlobalEnableA20 endp
  839.  
  840.  
  841. ;*--------------------------------------------------------------------------*
  842. ;*                                        *
  843. ;*  GlobalDisableA20 -                        FUNCTION 04h    *
  844. ;*                                        *
  845. ;*    Globally disable the A20 line                        *
  846. ;*                                        *
  847. ;*  ARGS:   None                                *
  848. ;*  RETS:   AX = 1 if the A20 line is disabled, 0 otherwise.  BL = Error    *
  849. ;*  REGS:   AX, BX and Flags are clobbered                    *
  850. ;*                                        *
  851. ;*  INTERNALLY NON-REENTRANT                            *
  852. ;*                                        *
  853. ;*--------------------------------------------------------------------------*
  854.  
  855. GlobalDisableA20 proc near
  856.  
  857.         cli                ; This is a non-reentrant function
  858.  
  859.         ; Is A20 already globally disabled?
  860.         cmp        [fGlobalEnable],0
  861.         je        short GDARet
  862.  
  863.         ; Attempt to disable the A20 line.
  864.         call    LocalDisableA20
  865.         or        ax,ax
  866.         jz        short GDAA20Err
  867.  
  868.         ; Mark A20 as globally disabled.
  869.         mov        [fGlobalEnable],0
  870.  
  871.         ; Return success.
  872. GDARet:        mov        ax,1
  873.         xor        bl,bl
  874.         ret
  875.  
  876.         ; Some A20 error occured.
  877. GDAA20Err:  mov        bl,ERR_A20
  878.         xor        ax,ax
  879.         ret
  880.  
  881. GlobalDisableA20 endp
  882.  
  883.  
  884. ;*--------------------------------------------------------------------------*
  885. ;*                                        *
  886. ;*  LocalEnableA20 -                        FUNCTION 05h    *
  887. ;*                                        *
  888. ;*    Locally enable the A20 line                        *
  889. ;*                                        *
  890. ;*  ARGS:   None                                *
  891. ;*  RETS:   AX = 1 if the A20 line is enabled, 0 otherwise.  BL = Error        *
  892. ;*  REGS:   AX, BX and Flags clobbered                        *
  893. ;*                                        *
  894. ;*  INTERNALLY NON-REENTRANT                            *
  895. ;*                                        *
  896. ;*--------------------------------------------------------------------------*
  897.  
  898. LocalEnableA20 proc near
  899.  
  900.         cli                ; This is a non-reentrant function
  901.         
  902.         cmp        [fCanChangeA20],1    ; Can we change A20?
  903.         jne     short LEARet    ; No, don't touch A20
  904.  
  905.         ; Only actually enable A20 if the count is zero.
  906.         cmp        [EnableCount],0
  907.         jne     short LEAIncIt
  908.  
  909.         ; Attempt to enable the A20 line.
  910.         mov        ax,1
  911.         call    [A20Handler]    ; Call machine-specific A20 handler
  912.         or        ax,ax
  913.         jz        short LEAA20Err
  914.  
  915. LEAIncIt:   inc        [EnableCount]
  916.  
  917.         ; Return success.
  918. LEARet:        mov        ax,1
  919.         xor        bl,bl
  920.         ret
  921.  
  922.         ; Some A20 error occurred.
  923. LEAA20Err:  mov        bl,ERR_A20
  924.         xor        ax,ax
  925.         ret
  926.         
  927. LocalEnableA20 endp
  928.  
  929.  
  930. ;*--------------------------------------------------------------------------*
  931. ;*                                        *
  932. ;*  LocalDisableA20 -                        FUNCTION 06h    *
  933. ;*                                        *
  934. ;*    Locally disable the A20 line                        *
  935. ;*                                        *
  936. ;*  ARGS:   None                                *
  937. ;*  RETS:   AX = 1 if the A20 line is disabled, 0 otherwise.  BL = Error    *
  938. ;*  REGS:   AX, BX and Flags are clobbered                    *
  939. ;*                                        *
  940. ;*  INTERNALLY NON-REENTRANT                            *
  941. ;*                                        *
  942. ;*--------------------------------------------------------------------------*
  943.  
  944. LocalDisableA20 proc near
  945.  
  946.         cli                ; This is a non-reentrant function
  947.         
  948.         cmp        [fCanChangeA20],0    ; Can we change A20?
  949.         je        short LDARet    ; No, don't touch A20
  950.  
  951.         ; Make sure the count's not zero.
  952.         cmp        [EnableCount],0
  953.         je        short LDAA20Err
  954.  
  955.         ; Only actually disable if the count is one.
  956.         cmp        [EnableCount],1
  957.         jne     short LDADecIt
  958.  
  959.         xor        ax,ax
  960.         call    [A20Handler]    ; Call machine-specific A20 handler
  961.         or        ax,ax
  962.         jz        short LDAA20Err
  963.  
  964. LDADecIt:   dec        [EnableCount]
  965.  
  966.         ; Return success.
  967. LDARet:        mov        ax,1
  968.         xor        bl,bl
  969.         ret
  970.  
  971.         ; Some A20 error occurred.
  972. LDAA20Err:  mov     bl,ERR_A20
  973.         xor     ax,ax
  974.         ret
  975.             
  976. LocalDisableA20 endp
  977.  
  978.  
  979. ;*--------------------------------------------------------------------------*
  980. ;*                                        *
  981. ;*  IsA20On -                            FUNCTION 07h    *
  982. ;*                                        *
  983. ;*    Returns the state of the A20 line                    *
  984. ;*                                        *
  985. ;*  ARGS:   None                                *
  986. ;*  RETS:   AX = 1 if the A20 line is enabled, 0 otherwise            *
  987. ;*  REGS:   AX, CX, DI, SI and Flags clobbered                    *
  988. ;*                                        *
  989. ;*  INTERNALLY REENTRANT                            *
  990. ;*                                        *
  991. ;*--------------------------------------------------------------------------*
  992.  
  993. LowMemory   label   dword        ; Set equal to 0000:0080
  994.         dw        00080h
  995.         dw        00000h
  996.  
  997. HighMemory  label   dword
  998.         dw        00090h        ; Set equal to FFFF:0090
  999.         dw        0FFFFh
  1000.  
  1001. IsA20On        proc    near
  1002.  
  1003.         push    ds
  1004.         push    es
  1005.  
  1006.         lds        si,cs:LowMemory    ; Compare the four words at 0000:0080
  1007.         les        di,cs:HighMemory    ;   with the four at FFFF:0090
  1008.         mov        cx,4
  1009.         cld
  1010.         repe    cmpsw
  1011.  
  1012.         pop        es
  1013.         pop        ds
  1014.         xor        ax,ax
  1015.  
  1016.         jcxz    short IAONoWrap ; Are the two areas the same?
  1017.         inc        ax            ; No, return A20 Enabled
  1018.  
  1019. IAONoWrap:  xor     bl,bl
  1020.         ret                ; Yes, return A20 Disabled
  1021.  
  1022. IsA20On        endp
  1023.  
  1024.  
  1025. ;*--------------------------------------------------------------------------*
  1026. ;*                                        *
  1027. ;*  QueryExtMemory -                        FUNCTION 08h    *
  1028. ;*                                        *
  1029. ;*    Returns the size of the largest free extended memory block in K        *
  1030. ;*                                        *
  1031. ;*  ARGS:   None                                *
  1032. ;*  RETS:   AX = Size of largest free block in K.  BL = Error code        *
  1033. ;*        DX = Total amount of free extended memory in K            *
  1034. ;*  REGS:   AX, BX, DX, DI, SI and Flags clobbered                *
  1035. ;*                                        *
  1036. ;*  INTERNALLY REENTRANT                            *
  1037. ;*                                        *
  1038. ;*--------------------------------------------------------------------------*
  1039.  
  1040. QueryExtMemory proc near
  1041.  
  1042.         ; Init the error code in DL.
  1043.         mov        dl,ERR_OUTOMEMORY
  1044.     
  1045.         ; Scan for the largest block marked FREE.
  1046.         xor        di,di            ; DI = Max. size found so far
  1047.         xor        si,si            ; SI = Total amount of free memory
  1048.         mov        bx,KiddValley
  1049.         mov     cx,[cHandles]        ; Loop through the handle table
  1050. QEMLoop:    cmp        [bx.Flags],FREEFLAG
  1051.         jne     short QEMBottom
  1052.  
  1053.         ; Add this free block to the total.
  1054.         add     si,[bx.Len]         ; CHANGED 7/19/88
  1055.  
  1056.         ; Is this block larger?
  1057.         mov        ax,[bx.Len]
  1058.         cmp        di,ax
  1059.         jae     short QEMBottom        ; CHANGED 7/19/88
  1060.         
  1061.         ; Yes, save it away.
  1062.         mov        di,ax
  1063.         xor     dl,dl            ; We ain't Out o' Memory
  1064.         
  1065. QEMBottom:  add        bx,SIZE Handle
  1066.         loop    QEMLoop
  1067.  
  1068.         ; Setup the return.
  1069.         mov        ax,di
  1070.         mov        bl,dl            ; Retrieve the error code
  1071.         mov     dx,si            ; CHANGED 7/19/88
  1072.         ret
  1073.  
  1074. QueryExtMemory endp
  1075.  
  1076.  
  1077. ;*--------------------------------------------------------------------------*
  1078. ;*                                        *
  1079. ;*  AllocExtMemory -                        FUNCTION 09h    *
  1080. ;*                                        *
  1081. ;*    Reserve a block of extended memory                    *
  1082. ;*                                        *
  1083. ;*  ARGS:   DX = Amount of K being requested                    *
  1084. ;*  RETS:   AX = 1 of successful, 0 otherwise.    BL = Error Code            *
  1085. ;*        DX = 16-bit handle to the allocated block                *
  1086. ;*  REGS:   AX, BX, DX and Flags clobbered                    *
  1087. ;*                                        *
  1088. ;*  INTERNALLY NON-REENTRANT                            *
  1089. ;*                                        *
  1090. ;*--------------------------------------------------------------------------*
  1091.  
  1092. ; Algorithm -
  1093. ;
  1094. ;   Scan the Handle Table looking for BOTH an unused handle and
  1095. ;    a free block which is large enough:
  1096. ;
  1097. ;   1.    If both are found -
  1098. ;        Mark the free block as used and adjust its size.
  1099. ;        Make the unused handle a free block containing the remaining
  1100. ;        unallocated portion of the original free block.
  1101. ;
  1102. ;   2.    If only an unused handle is found -
  1103. ;        We're out of memory.
  1104. ;
  1105. ;   3.    If only a properly sized free block is found -
  1106. ;        We only have one handle left.
  1107. ;        Mark the free block as used.  The requester gets all of the
  1108. ;        block's memory.
  1109. ;
  1110. ;   4.    If neither are found -
  1111. ;        We're out of memory.
  1112.  
  1113. hFreeBlock    dw  ?
  1114. hUnusedBlock    dw  ?
  1115.  
  1116. AllocExtMemory proc near
  1117.  
  1118.         cli             ; This is a non-reentrant function
  1119.         
  1120.         ; Scan the handle table looking for BOTH an unused handle and 
  1121.         ;    a free block which is large enough.
  1122.         xor        ax,ax
  1123.         mov        [hFreeBlock],ax
  1124.         mov        [hUnusedBlock],ax
  1125.         mov        bx,KiddValley
  1126.         mov     cx,[cHandles]    ; Loop through the handle table
  1127.  
  1128.         ; Have we already found a free block which is large enough?
  1129. AEMhLoop:   cmp     [hFreeBlock],0
  1130.         jne     short AEMUnused    ; Yes, see if this one is unused
  1131.         
  1132.         ; Is this block free?
  1133.         cmp     [bx.Flags],FREEFLAG
  1134.         jne     short AEMUnused    ; No, see if it is unused
  1135.         
  1136.         ; Is it large enough?
  1137.         cmp        dx,[bx.Len]
  1138.         ja        short AEMNexth    ; No, get the next handle
  1139.  
  1140.         ; Save this guy away.
  1141.         mov        [hFreeBlock],bx
  1142.         jmp        short AEMBottom
  1143.         
  1144. AEMUnused:  ; Have we already found an unused handle?
  1145.         cmp     [hUnusedBlock],0
  1146.         jne     short AEMNexth    ; Yes, get the next handle
  1147.  
  1148.         ; Is this block unused?
  1149.         cmp     [bx.Flags],UNUSEDFLAG
  1150.         jne     short AEMNexth    ; No, get the next handle
  1151.         
  1152.         ; Save this guy away.
  1153.         mov        [hUnusedBlock],bx
  1154.             
  1155.         ; Have we found what we are looking for?
  1156.         cmp        [hFreeBlock],0
  1157.         je        short AEMNexth
  1158. AEMBottom:  cmp        [hUnusedBlock],0
  1159.         jne     short AEMGotBoth    ; Yes, continue
  1160.         
  1161. AEMNexth:   ; Get the next handle
  1162.         add        bx,SIZE Handle
  1163.         loop    AEMhLoop
  1164.         
  1165.         ; We are at the end of the handle table and we didn't find both
  1166.         ; things we were looking for.  Did we find a free block?
  1167.         mov     si,[hFreeBlock]
  1168.         or        si,si
  1169.         jnz     short AEMRetSuc    ; Yes, Case 3 - Alloc the entire block
  1170.         
  1171.         ; Did we find an unused handle?
  1172.         cmp        [hUnusedBlock],0
  1173.         je        short AEMOOHandles    ; No, Case 4 - We're out of handles
  1174.         
  1175.         ; Case 2 - Is this a request for a zero-length handle?
  1176.         or        dx,dx
  1177.         jnz     short AEMOOMemory    ; No, we're out of memory
  1178.         
  1179.         ; Reserve the zero-length handle.
  1180.         mov        si,[hUnusedBlock]
  1181.         mov        [hFreeBlock],si
  1182.         jmp        short AEMRetSuc
  1183.         
  1184. AEMGotBoth: ; We're at Case 1 above.
  1185.         ;    Mark the free block as used (done below) and adjust its size.
  1186.         ;    Make the unused handle a free block containing the remaining
  1187.         ;       unallocated portion of the original free block.
  1188.         mov        si,[hFreeBlock]
  1189.         mov        di,[hUnusedBlock]
  1190.         
  1191.         ; Unused.Base = Old.Base + request
  1192.         mov        ax,[si].Base
  1193.         add        ax,dx
  1194.         mov        [di].Base,ax
  1195.         
  1196.         ; New.Len = request
  1197.         mov        ax,dx
  1198.         xchg    [si].Len,ax
  1199.         
  1200.         ; Unused.Len = Old.Len - request
  1201.         sub        ax,dx
  1202.         mov        [di].Len,ax
  1203.         mov        [di].Flags,FREEFLAG        ; Unused.Flags = FREE
  1204.         
  1205. AEMRetSuc:  ; Complete the allocation.
  1206.         mov        [si].Flags,USEDFLAG        ; New.Flags = USED
  1207.         mov        dx,[hFreeBlock]
  1208.         mov        ax,1
  1209.         xor        bl,bl
  1210.         ret
  1211.  
  1212. AEMOOMemory:mov        bl,ERR_OUTOMEMORY
  1213.         jmp        short AEMErrRet
  1214.         
  1215. AEMOOHandles:
  1216.         mov        bl,ERR_OUTOHANDLES
  1217. AEMErrRet:  xor        ax,ax            ; Return failure
  1218.         mov        dx,ax
  1219.         ret               
  1220.         
  1221. AllocExtMemory endp
  1222.  
  1223.  
  1224. ;*--------------------------------------------------------------------------*
  1225. ;*                                        *
  1226. ;*  ValidateHandle -                                *
  1227. ;*                                        *
  1228. ;*    Validates an extended memory block handle                *
  1229. ;*                                        *
  1230. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1231. ;*  RETS:   Carry is set if the handle is valid                    *
  1232. ;*  REGS:   Preserved except the carry flag                    *
  1233. ;*                                        *
  1234. ;*--------------------------------------------------------------------------*
  1235.  
  1236. ValidateHandle proc near
  1237.  
  1238.         pusha                ; Save everything
  1239.         mov        bx,dx            ; Move the handle into BX
  1240.  
  1241.         ; The handle must be equal to or above "KiddValley".
  1242.         cmp        bx,[KiddValley]
  1243.         jb        short VHOne
  1244.         
  1245.         ; The handle must not be above "KiddValleyTop".
  1246.         cmp        bx,[KiddValleyTop]
  1247.         ja        short VHOne
  1248.         
  1249.         ; (The handle-"KiddValley") must be a multiple of a handle's size.
  1250.         sub        dx,[KiddValley]
  1251.         mov        ax,dx
  1252.         xor        dx,dx
  1253.         mov        cx,SIZE Handle
  1254.         div        cx                
  1255.         or        dx,dx            ; Any remainder?        
  1256.         jnz     short VHOne         ; Yup, it's bad
  1257.  
  1258.         ; Does the handle point to a currently USED block?
  1259.         cmp        [bx.Flags],USEDFLAG
  1260.         jne     short VHOne         ; This handle is not being used.
  1261.         
  1262.         ; The handle looks good to me...
  1263.         popa                ; Restore everything
  1264.         stc                 ; Return success
  1265.         ret
  1266.  
  1267. VHOne:        ; It's really bad.
  1268.         popa                ; Restore everything
  1269.         clc                 ; Return failure
  1270.         ret
  1271.         
  1272. ValidateHandle endp
  1273.  
  1274.  
  1275. ;*--------------------------------------------------------------------------*
  1276. ;*                                        *
  1277. ;*  FreeExtMemory -                        FUNCTION 0Ah    *
  1278. ;*                                        *
  1279. ;*    Frees a block of extended memory which was allocated via AllocExt   *
  1280. ;*                                        *
  1281. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1282. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1283. ;*  REGS:   AX, BX, CX, DX, SI, DI and Flags clobbered                *
  1284. ;*                                        *
  1285. ;*  INTERNALLY NON-REENTRANT                            *
  1286. ;*                                        *
  1287. ;*--------------------------------------------------------------------------*
  1288.  
  1289. FreeExtMemory proc near
  1290.  
  1291.         cli                 ; This is a non-reentrant function
  1292.         
  1293.         ; Make sure that the handle is valid.
  1294.         call    ValidateHandle
  1295.         jnc     short FEMBadh
  1296.         mov        si,dx            ; Move the handle into SI
  1297.         
  1298.         ; Make sure that the handle points to a FREE block.
  1299.         cmp        [si].cLock,0
  1300.         jne     short FEMLockedh
  1301.         
  1302.         ; Mark the block as FREE and cancel any locks.
  1303.         mov        [si].Flags,FREEFLAG
  1304.         mov        [si].cLock,0
  1305.         
  1306.         ; Is an adjacent block also free?
  1307. FEMScanIt:  mov        bx,[si].Base        ; BX = Bottom of block
  1308.         mov        ax,bx
  1309.         add        ax,[si].Len            ; AX = Top of block
  1310.         
  1311.         ; Search for an adjacent FREE block.
  1312.         mov        di,[KiddValley]        ; DI = Handle being scanned
  1313.         
  1314.         mov     cx,cHandles         ; Loop through the handle table
  1315. FEMLoopTop: cmp        [di].Flags,FREEFLAG        ; Is this block free?
  1316.         jne     short FEMNexth        ; No, continue
  1317.  
  1318.         ; Is this block just above the one we are freeing?
  1319.         mov        dx,[di].Base
  1320.         cmp     dx,ax
  1321.         je        short FEMBlockAbove     ; Yes, coaless upwards
  1322.  
  1323.         ; Is it just below?
  1324.         add        dx,[di].Len
  1325.         cmp     dx,bx
  1326.         je        short FEMBlockBelow     ; Yes, coaless downwards
  1327.         
  1328. FEMNexth:   add        di,SIZE Handle
  1329.         loop    FEMLoopTop
  1330.  
  1331.         ; No adjacent blocks to coaless.
  1332.         mov     ax,1            ; Return success
  1333.         xor        bl,bl
  1334.         ret
  1335.  
  1336.         ; Exchange the pointer to the "upper" and "lower" blocks.
  1337. FEMBlockBelow:
  1338.         xchg    si,di
  1339.  
  1340.         ; Move the free block above into the current handle.
  1341. FEMBlockAbove:
  1342.         mov        dx,[si].Len
  1343.         add     dx,[di].Len         ; Combine the lengths
  1344.         mov        [si].Len,dx
  1345.         mov     [di].Flags,UNUSEDFLAG   ; Mark old block's handle as UNUSED
  1346.         jmp        short FEMScanIt        ; Rescan the list
  1347.  
  1348. FEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1349.         jmp        short FEMErrExit
  1350.         
  1351. FEMLockedh: mov        bl,ERR_EMBLOCKED
  1352. FEMErrExit: xor     ax,ax            ; Return failure
  1353.         ret
  1354.         
  1355. FreeExtMemory endp          
  1356.  
  1357.  
  1358. ;*--------------------------------------------------------------------------*
  1359. ;*                                        *
  1360. ;*  LockExtMemory -                        FUNCTION 0Ch    *
  1361. ;*                                        *
  1362. ;*    Locks a block of extended memory                    *
  1363. ;*                                        *
  1364. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1365. ;*  RETS:   AX = 1 of successful, 0 otherwise.    BL = Error code            *
  1366. ;*        DX:BX = 32-bit linear address of the base of the memory block   *
  1367. ;*  REGS:   AX, BX, DX and Flags clobbered                    *
  1368. ;*                                        *
  1369. ;*  INTERNALLY NON-REENTRANT                            *
  1370. ;*                                        *
  1371. ;*--------------------------------------------------------------------------*
  1372.  
  1373. LockExtMemory proc near
  1374.  
  1375.         cli                 ; This is a non-reentrant function
  1376.         
  1377.         ; Is the handle valid?
  1378.         call    ValidateHandle
  1379.         jnc     short LEMBadh
  1380.         mov     bx,dx            ; Move the handle into BX
  1381.  
  1382.         ; Are we at some preposterously large limit?
  1383.         cmp        [bx.cLock],0FFh
  1384.         je        short LEMOverflow
  1385.  
  1386.         ; Lock the block.
  1387.         inc        [bx.cLock]
  1388.         
  1389.         ; Return the 32-bit address of its base.
  1390.         mov        dx,[bx.Base]
  1391.         mov        bx,dx
  1392.         shr        dx,6
  1393.         shl        bx,10
  1394.  
  1395.         ; Return success.
  1396.         mov        ax,1
  1397.         ret
  1398.         
  1399. LEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1400.         jmp        short LEMErrExit
  1401.  
  1402. LEMOverflow:mov        bl,ERR_LOCKOVERFLOW
  1403. LEMErrExit: xor     ax,ax            ; Return failure
  1404.         mov        dx,ax
  1405.         ret 
  1406.         
  1407. LockExtMemory endp
  1408.  
  1409.  
  1410. ;*--------------------------------------------------------------------------*
  1411. ;*                                        *
  1412. ;*  UnlockExtMemory -                        FUNCTION 0Dh    *
  1413. ;*                                        *
  1414. ;*    Unlocks a block of extended memory                    *
  1415. ;*                                        *
  1416. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1417. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1418. ;*  REGS:   AX, BX and Flags clobbered                        *
  1419. ;*                                        *
  1420. ;*  INTERNALLY NON-REENTRANT                            *
  1421. ;*                                        *
  1422. ;*--------------------------------------------------------------------------*
  1423.  
  1424. UnlockExtMemory proc near
  1425.  
  1426.         cli                ; This is a non-reentrant function
  1427.     
  1428.         ; Is the handle valid?
  1429.         call    ValidateHandle
  1430.         jnc     short UEMBadh
  1431.         mov        bx,dx        ; Move the handle into BX
  1432.  
  1433.         ; Does the handle point to a locked block?
  1434.         cmp        [bx.cLock],0
  1435.         je        short UEMUnlocked    ; No, return error
  1436.  
  1437.         ; Unlock the block.
  1438.         dec        [bx.cLock]
  1439.  
  1440.         mov     ax,1        ; Return success
  1441.         xor     bl,bl
  1442.         ret
  1443.         
  1444. UEMUnlocked:mov        bl,ERR_EMBUNLOCKED
  1445.         jmp        short UEMErrExit
  1446.  
  1447. UEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1448. UEMErrExit: xor        ax,ax
  1449.         ret           
  1450.  
  1451. UnlockExtMemory endp
  1452.  
  1453.  
  1454. ;*--------------------------------------------------------------------------*
  1455. ;*                                        *
  1456. ;*  GetExtMemoryInfo -                        FUNCTION 0Eh    *
  1457. ;*                                        *
  1458. ;*    Gets other information about an extended memory block            *
  1459. ;*                                        *
  1460. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1461. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1462. ;*        BH = EMB's lock count                        *
  1463. ;*        BL = Total number of unused handles in the system            *
  1464. ;*        DX = EMB's length                            *
  1465. ;*  REGS:   AX, BX, CX, DX and Flags clobbered                    *
  1466. ;*                                        *
  1467. ;*  INTERNALLY NON-REENTRANT                            *
  1468. ;*                                        *
  1469. ;*--------------------------------------------------------------------------*
  1470.  
  1471. GetExtMemoryInfo proc    near
  1472.  
  1473.         cli                 ; This is a non-reentrant function
  1474.         
  1475.         ; Is the handle valid?
  1476.         call    ValidateHandle
  1477.         jnc     short GEMBadh
  1478.         mov     si,dx            ; Move the handle into SI
  1479.  
  1480.         ; Count the number of handles which are not currently being used.
  1481.         xor     al,al
  1482.         mov     bx,[KiddValley]
  1483.         mov     cx,[cHandles]        ; Loop through the handle table
  1484. GEMLoop:    cmp     [bx.Flags],USEDFLAG     ; Is this handle in use?
  1485.         je        short GEMNexth          ; Yes, continue
  1486.         inc     al                ; No, increment the count
  1487. GEMNexth:   add     bx,SIZE Handle
  1488.         loop    GEMLoop
  1489.  
  1490.         ; Setup the return.
  1491.         mov     dx,[si.Len]         ; Length in DX
  1492.         mov     bh,[si.cLock]        ; Lock count in BH
  1493.         mov     bl,al
  1494.         mov        ax,1
  1495.         ret
  1496.         
  1497. GEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1498.         xor        ax,ax
  1499.         ret
  1500.  
  1501. GetExtMemoryInfo endp
  1502.         
  1503.  
  1504. ;*--------------------------------------------------------------------------*
  1505. ;*                                        *
  1506. ;*  ReallocExtMemory -                        FUNCTION 0Fh    *
  1507. ;*                                        *
  1508. ;*    Reallocates a block of extended memory                    *
  1509. ;*                                        *
  1510. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1511. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1512. ;*  REGS:                                    *
  1513. ;*                                        *
  1514. ;*  INTERNALLY NON-REENTRANT                            *
  1515. ;*                                        *
  1516. ;*--------------------------------------------------------------------------*
  1517.  
  1518. ; FUNCTION NOT YET IMPLEMENTED
  1519.  
  1520.  
  1521. ;*--------------------------------------------------------------------------*
  1522. ;*                                        *
  1523. ;*  NOTE: RequestUMB and ReleaseUMB will not be implemented by HIMEM.        *
  1524. ;*                                        *
  1525. ;*--------------------------------------------------------------------------*
  1526.  
  1527.  
  1528. ;*--------------------------------------------------------------------------*
  1529. ;*                                        *
  1530. ;*  MoveExtMemory -                        FUNCTION 0Bh    *
  1531. ;*                                        *
  1532. ;*    Copys a block of memory from anywhere to anywhere            *
  1533. ;*                                        *
  1534. ;*  ARGS:   ES:SI = Pointer to an Extended Memory Block Move Structure        *
  1535. ;*        (NOTE: Originally passed in as DS:SI)                *
  1536. ;*  RETS:   AX = 1 of successful, 0 otherwise.    BL = Error code.        *
  1537. ;*  REGS:   Everybody clobbered                            *
  1538. ;*                                        *
  1539. ;*  INTERNALLY REENTRANT (believe it or not)                    *
  1540. ;*                                        *
  1541. ;*--------------------------------------------------------------------------*
  1542.  
  1543. EVEN                ; Must be word aligned.
  1544.  
  1545. MoveBlock:
  1546.  
  1547. MEM3_Data    label    byte    ; Start of MoveBlock data
  1548. MoveBlock286:
  1549.  
  1550. include xm286.asm
  1551.  
  1552. EndMoveBlock286:
  1553.  
  1554. ;*--------------------------------------------------------------------------*
  1555.  
  1556. MoveBlock386:
  1557.  
  1558. include xm386.asm
  1559.  
  1560. EndMoveBlock386:
  1561.  
  1562.  
  1563. ;****************************************************************************
  1564. ;*                                        *
  1565. ;* A20 Handler Section:                             *
  1566. ;*                                        *
  1567. ;* The Init code copies the proper A20 Handler in place just below the        *
  1568. ;*   proper MoveBlock routine.                            *
  1569. ;*                                        *
  1570. ;* NOTE: A20 HANDLERS MUST ONLY HAVE RELATIVE JUMPS!  HOWEVER ANY CALLS TO  *
  1571. ;*     FUNCTIONS OUTSIDE OF THE HANDLER MUST BE NON-RELATIVE!     The best   *
  1572. ;*     method is to call thru a variable such as ControlJumpTable[n].        *
  1573. ;*                                        *
  1574. ;****************************************************************************
  1575.  
  1576. ;*--------------------------------------------------------------------------*
  1577. ;*                                        *
  1578. ;*  AT_A20Handler -                        HARDWARE DEP.   *
  1579. ;*                                        *
  1580. ;*    Enable/Disable the A20 line on non-PS/2 machines            *
  1581. ;*                                        *
  1582. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1583. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1584. ;*  REGS:   AX, CX and Flags clobbered                        *
  1585. ;*                                        *
  1586. ;*--------------------------------------------------------------------------*
  1587.  
  1588. AT_A20Handler proc   near
  1589.  
  1590.         or        ax,ax
  1591.         jz        short AAHDisable
  1592.  
  1593. AAHEnable:  call    Sync8042    ; Make sure the Keyboard Controller is Ready
  1594.         jnz     short AAHErr
  1595.  
  1596.         mov        al,0D1h    ; Send D1h
  1597.         out        64h,al
  1598.         call    Sync8042
  1599.         jnz     short AAHErr
  1600.  
  1601.         mov        al,0DFh    ; Send DFh
  1602.         out        60h,al
  1603.         call    Sync8042
  1604.         jnz     short AAHErr
  1605.  
  1606.         ; Wait for the A20 line to settle down (up to 20usecs)
  1607.         mov        al,0FFh    ; Send FFh (Pulse Output Port NULL)
  1608.         out        64h,al
  1609.         call    Sync8042
  1610.         jnz     short AAHErr
  1611.         jmp        short AAHExit
  1612.  
  1613. AAHDisable: call    Sync8042    ; Make sure the Keyboard Controller is Ready
  1614.         jnz     short AAHErr
  1615.  
  1616.         mov        al,0D1h    ; Send D1h
  1617.         out        64h,al
  1618.         call    Sync8042
  1619.         jnz     short AAHErr
  1620.  
  1621.         mov        al,0DDh    ; Send DDh
  1622.         out        60h,al
  1623.         call    Sync8042
  1624.         jnz     short AAHErr
  1625.  
  1626.         ; Wait for the A20 line to settle down (up to 20usecs)
  1627.         mov        al,0FFh    ; Send FFh (Pulse Output Port NULL)
  1628.         out        64h,al
  1629.         call    Sync8042
  1630.         
  1631. AAHExit:    mov        ax,1
  1632.         ret
  1633.         
  1634. AAHErr:        xor        ax,ax
  1635.         ret
  1636.         
  1637. AT_A20Handler endp
  1638.  
  1639.  
  1640. ;*--------------------------------------------------------------------------*
  1641.  
  1642. Sync8042    proc    near
  1643.  
  1644.         xor        cx,cx
  1645. S8InSync:   in        al,64h
  1646.         and        al,2
  1647.         loopnz  S8InSync
  1648.         ret
  1649.  
  1650. Sync8042    endp
  1651.  
  1652. EndAT_A20Handler:
  1653.  
  1654.  
  1655. ;*--------------------------------------------------------------------------*
  1656. ;*                                        *
  1657. ;*  PS2_A20Handler -                        HARDWARE DEP.   *
  1658. ;*                                        *
  1659. ;*    Enable/Disable the A20 line on PS/2 machines                *
  1660. ;*                                        *
  1661. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1662. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1663. ;*  REGS:   AX, CX and Flags clobbered                        *
  1664. ;*                                        *
  1665. ;*--------------------------------------------------------------------------*
  1666.  
  1667. PS2_PORTA   equ        0092h
  1668. PS2_A20BIT  equ        00000010b
  1669.  
  1670. PS2_A20Handler proc   near
  1671.  
  1672.         or        ax,ax
  1673.         jz        short PAHDisable
  1674.  
  1675. PAHEnable:  in        al,PS2_PORTA    ; Get the current A20 state
  1676.         test    al,PS2_A20BIT   ; Is A20 already on?
  1677.         jnz     short PAHErr
  1678.  
  1679.         or        al,PS2_A20BIT   ; Turn on the A20 line
  1680.         out        PS2_PORTA,al
  1681.  
  1682.         xor        cx,cx        ; Make sure we loop for awhile
  1683. PAHIsItOn:  in        al,PS2_PORTA    ; Loop until the A20 line comes on
  1684.         test    al,PS2_A20BIT
  1685.         loopz   PAHIsItOn
  1686.         jz        short PAHErr    ; Unable to turn on the A20 line
  1687.         jmp        short PAHExit
  1688.  
  1689. PAHDisable: in        al,PS2_PORTA    ; Get the current A20 state
  1690.         and        al,NOT PS2_A20BIT    ; Turn off the A20 line
  1691.         out        PS2_PORTA,al
  1692.  
  1693.         xor        cx,cx        ; Make sure we loop for awhile
  1694. PAHIsItOff: in        al,PS2_PORTA    ; Loop until the A20 line goes off
  1695.         test    al,PS2_A20BIT
  1696.         loopnz  PAHIsItOff
  1697.         jnz     short PAHErr    ; Unable to turn off the A20 line
  1698.  
  1699. PAHExit:    mov        ax,1
  1700.         ret
  1701.         
  1702. PAHErr:        xor        ax,ax
  1703.         ret           
  1704.  
  1705. PS2_A20Handler endp
  1706.  
  1707. EndPS2_A20Handler:
  1708.  
  1709.  
  1710. ;*--------------------------------------------------------------------------*
  1711. ;*                                        *
  1712. ;*  $6300Plus_A20Handler -                    HARDWARE DEP.   *
  1713. ;*                                        *
  1714. ;*     Enable/Disable address lines A20-A23 on AT&T 6300 Plus            *
  1715. ;*                                        *
  1716. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1717. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1718. ;*  REGS:   AX, BX, and Flags clobbered                        *
  1719. ;*                                        *
  1720. ;*  Note:   Don't want to do two back to back disables on PLUS,            *
  1721. ;*        so we call IsA20On to see if it is necessary.            *
  1722. ;*  Warning:  The calcuation of the ReturnBack label depends on the        *
  1723. ;*          expectation that this routine is being moved at init time.    *
  1724. ;*                                        *
  1725. ;*--------------------------------------------------------------------------*
  1726.  
  1727. PLUS_PORT   equ        03F20h
  1728. PLUS_STATUS equ     03FA0h
  1729. PLUS_SET    equ     10000000b    ; Turn on A20-A23
  1730. PLUS_RESET  equ     00010000b    ; Turn off A20-A23 and point to our routine
  1731.  
  1732. $6300PLUS_A20Handler proc   near
  1733.             mov     bx,ax
  1734.             push    dx
  1735.             mov     dx,PLUS_STATUS
  1736.             in      al,dx
  1737.             pop     dx
  1738.             and     ax,1
  1739.             cmp     ax,bx
  1740.             jne     short $6AHEnable
  1741.         mov     ax,1
  1742.             ret                             ; No, just return
  1743.  
  1744. $6AHEnable: 
  1745.             pushf
  1746.             sti
  1747.             mov     al,PLUS_SET
  1748.             or      bx,bx                   ; Zero if disable
  1749.             jnz     short $6AHNext
  1750.             mov     al,PLUS_RESET
  1751.  
  1752. $6AHNext:   push    dx                      ; Set/reset the port
  1753.             mov     dx,PLUS_PORT
  1754.             out     dx,al
  1755.             pop     dx
  1756.             or      bx,bx
  1757.             jnz     short $6AHNext1
  1758.             call    $6300Reset              ; Reset the processor
  1759. $6AHNext1:
  1760.             popff
  1761.             mov ax,1
  1762.             ret
  1763.  
  1764. $6300Plus_A20Handler endp
  1765.  
  1766.  
  1767. ;*--------------------------------------------------------------------------*
  1768. ;*                                        *
  1769. ;* $6300Reset -                           HARDWARE DEP.    *
  1770. ;*                                        *
  1771. ;* Reset the 80286 in order to turn off the address lines on the 6300 PLUS. *
  1772. ;* This is the only way to do this on the current hardware.            *
  1773. ;* The processor itself is reset by reading or writing port 03F00h.        *
  1774. ;*                                        *
  1775. ;*  Uses flags.                                    *
  1776. ;*                                        *
  1777. ;*--------------------------------------------------------------------------*
  1778.  
  1779. $6300Reset  proc    near
  1780.  
  1781.         pusha                ; Save world
  1782.         push    ds                ; Save segments
  1783.         push    es
  1784.         mov        ax,BiosSeg            ; Point to the BIOS segment
  1785.         mov        ds,ax            ; ds -> 40h
  1786.  
  1787.         ; Setup the reset return address.
  1788. assume ds:nothing
  1789.         push    word ptr ds:[RealLoc1]  ; Save what might have been here
  1790.         push    word ptr ds:[RealLoc1+2]
  1791.  
  1792.             ; Load our return address, remembering that we will be relocated
  1793.             ;   at init time.
  1794.             mov     word ptr ds:[RealLoc1+2],cs
  1795.             mov     ax,cs:[A20Handler]
  1796.             add     ax,offset ReturnBack-offset $6300Plus_A20Handler
  1797.             mov     word ptr ds:[RealLoc1],ax 
  1798.             mov     cs:[OldStackSeg],ss     ; Save the stack segment, too
  1799.  
  1800.         ; Reset the processor - turning off A20 in the process.
  1801.         mov        dx,03F00h
  1802.         in        ax,dx
  1803.  
  1804.         ; We shouldn't get here.  Halt the machine if we do.
  1805.         nop
  1806.         nop
  1807.         nop
  1808.         nop
  1809.         cli
  1810.         hlt
  1811.  
  1812. ReturnBack: mov        ss,cs:[OldStackSeg]        ; Start the recovery
  1813.         pop        word ptr ds:[RealLoc1+2]    ; ROM code has set ds->40h
  1814.         pop        word ptr ds:[RealLoc1]
  1815.         pop        es
  1816.         pop        ds
  1817.  
  1818. assume ds:code
  1819.             xor     al,al
  1820.             mov     dx,PLUS_PORT
  1821.             out     dx,al
  1822.             popa
  1823.             ret
  1824.  
  1825. $6300Reset endp
  1826.  
  1827. End6300Plus_Handler:
  1828.  
  1829.  
  1830. ;*--------------------------------------------------------------------------*
  1831. ;*                                        *
  1832. ;*  HP_A20Handler -                        HARDWARE DEP.   *
  1833. ;*                                        *
  1834. ;*    Enable/Disable the A20 line on HP Vectra machines            *
  1835. ;*                                        *
  1836. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1837. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1838. ;*  REGS:   AX, CX and Flags clobbered                        *
  1839. ;*                                        *
  1840. ;*--------------------------------------------------------------------------*
  1841.  
  1842. HP_A20Handler proc   near
  1843.  
  1844.         or        ax,ax
  1845.         jz        short HAHDisable
  1846.  
  1847. HAHEnable:  call    HPSync8042    ; Make sure the Keyboard Controller is ready
  1848.         jnz     short HAHErr
  1849.  
  1850.         mov        al,0DFh    ; Send DFh
  1851.         out        64h,al
  1852.         call    HPSync8042
  1853.         jnz     short HAHErr
  1854.  
  1855.         mov        al,0DFh    ; Send second DFh
  1856.         out        64h,al
  1857.         call    HPSync8042
  1858.         jnz     short HAHErr
  1859.         jmp        short HAHExit
  1860.  
  1861. HAHDisable: call    HPSync8042      ; Make sure the Keyboard Controller is Ready
  1862.         jnz     short HAHErr
  1863.  
  1864.         mov        al,0DDh    ; Send DDh
  1865.         out        64h,al
  1866.         call    HPSync8042
  1867.         jnz     short HAHErr
  1868.  
  1869.         mov        al,0DDh    ; Send second DDh
  1870.         out        64h,al
  1871.         call    HPSync8042
  1872.         jnz     short HAHErr
  1873.  
  1874. HAHExit:    mov        ax,1
  1875.         ret
  1876.  
  1877. HAHErr:        xor        ax,ax
  1878.         ret
  1879.         
  1880. HP_A20Handler endp
  1881.  
  1882.  
  1883. ;*--------------------------------------------------------------------------*
  1884.  
  1885. HPSync8042  proc    near
  1886.  
  1887.         xor        cx,cx
  1888. H8InSync:   in        al,64h
  1889.         and        al,2
  1890.         loopnz  H8InSync
  1891.         ret
  1892.  
  1893. HPSync8042  endp
  1894.  
  1895. EndHP_A20Handler:
  1896.  
  1897.  
  1898. ;*--------------------------------------------------------------------------*
  1899. ;*                                        *
  1900. ;*  Extended Memory Handle Table -                        *
  1901. ;*                                        *
  1902. ;*--------------------------------------------------------------------------*
  1903.  
  1904. ; Actually, the handle table will be located just after the end of whichever
  1905. ; A20 Handler is installed and will overwrite the others.  In large cases
  1906. ; however, it could extend beyond all of these guys and crunch the Init code.
  1907. ; Hence this buffer.  If the driver ever gets over 64K (heaven forbid) this
  1908. ; scheme should be reworked.
  1909.  
  1910. ; Guarantee space for all handles.  Kinda overkill but any extra will be 
  1911. ; discarded with the Init code.
  1912.  
  1913. HandleFiller        dw        MAXHANDLES * SIZE Handle DUP(?)
  1914.  
  1915.  
  1916. ;****************************************************************************
  1917. ;*                                        *
  1918. ;*  NOTE: Code below here will be discarded after driver initialization.    *
  1919. ;*                                        *
  1920. ;****************************************************************************
  1921.  
  1922. ;*--------------------------------------------------------------------------*
  1923. ;*                                        *
  1924. ;*  InitDriver -                                *
  1925. ;*                                        *
  1926. ;*    Called when driver is Initialized.                    *
  1927. ;*                                        *
  1928. ;*  ARGS:   ES:DI = Address of the Request Header                *
  1929. ;*  RETS:   AX = 0, pHdr.Address = Bottom of resident driver code        *
  1930. ;*  REGS:   AX, CX and Flags are clobbered                    *
  1931. ;*                                        *
  1932. ;*--------------------------------------------------------------------------*
  1933.  
  1934. InitLine    dw        MoveBlock        ; The line which defines what will be dis-
  1935.                     ;    carded after the driver is initialized
  1936. InitDriver  proc    near
  1937.  
  1938.         ; Display the sign on message.
  1939.         mov        ah,9h
  1940.         mov        dx,offset SignOnMsg
  1941.         int        21h
  1942.  
  1943.         ; Is this DOS 3.00 or higher?
  1944.         mov        ah,30h
  1945.         int        21h            ; Get DOS versions number
  1946.         cmp        al,3
  1947.         jae     short IDCheckXMS
  1948.         
  1949.         mov        dx,offset BadDOSMsg
  1950.         jmp     short IDFlushMe2
  1951.             
  1952.         ; Is another XMS driver already installed?
  1953. IDCheckXMS: mov     ax,4300h
  1954.         int        2Fh
  1955.         cmp        al,80h        ; Is INT 2F hooked?
  1956.         jne     short IDNotInYet
  1957.         mov        dx,offset NowInMsg
  1958.         jmp     short IDFlushMe2
  1959.  
  1960.         ; What kind of processor are we on?
  1961. IDNotInYet: call    MachineCheck
  1962.         cmp        ax,1        ; Is it an 8086/8088?
  1963.         jne     short IDProcOK
  1964.         mov        dx,offset On8086Msg
  1965.         jmp     short IDFlushMe
  1966.  
  1967.         ; Is there any Compaq BIM?
  1968. IDProcOK:
  1969.         call    GetBIMMemory
  1970.         or        ax,ax
  1971.         jz        short IDNoBIM
  1972.  
  1973.         ; How much extended memory is installed?
  1974.         call    GetInt15Memory
  1975.         cmp     ax,64        ; Is there >= 64K of extended?
  1976.         jb        short IDNoHMA    ; Nope - No HMA
  1977.         jmp     short IDHMAOK    ; Yup - continue
  1978.  
  1979.         ; How much extended memory is installed?
  1980. IDNoBIM:    call    GetInt15Memory
  1981.         cmp     ax,64        ; Is there >= 64K of extended?
  1982.         jae     short IDHMAOK    ; Yup - continue
  1983.  
  1984.         or        ax,ax        ; Is there any extended?
  1985.         jnz     short IDNoHMA    ; Yup - No HMA
  1986.  
  1987.         ; We can't find any memory to manage.
  1988.         mov        dx,offset NoExtMemMsg
  1989. IDFlushMe2: jmp     short IDFlushMe
  1990.         
  1991.         ; There isn't enough for the HMA, but there is some extended
  1992.         ; memory which we can manage.
  1993. IDNoHMA:    mov     dx,offset NoHMAMsg
  1994.         mov        ah,9h
  1995.         int        21h
  1996.         jmp     short IDFinalInit
  1997.  
  1998. IDHMAOK:    mov     [fHMAMayExist],1
  1999.  
  2000.         ; Install the proper MoveBlock function.
  2001. IDFinalInit:call    InstallMoveBlock
  2002.  
  2003.         ; Install the proper A20 handler.
  2004.         call    InstallA20
  2005.         
  2006.         ; Was A20 on already?
  2007.         call    IsA20On
  2008.         xor        ax,1
  2009.         mov        [fCanChangeA20],al    ; Yes, don't ever disable it
  2010.         cmp     al,0
  2011.         jne     short IDDiddler
  2012.         
  2013.         ; Display the "A20 Already On" message.
  2014.         mov        dx,offset A20OnMsg
  2015.         mov     ah,9h        ; CHANGED - 8/9/88
  2016.         int        21h
  2017.         
  2018.         ; Can we successfully diddle A20?    CHANGED - 8/9/88
  2019. IDDiddler:  call    LocalEnableA20    ; Try to enable A20
  2020.         or        ax,ax        ; Did we do it?
  2021.         jz        short IDBadA20    ; Nope - phoosh ourselves
  2022.  
  2023.         call    IsA20On        ; Is A20 on?
  2024.         or        ax,ax
  2025.         jz        short IDBadA20    ; Nope - phoosh ourselves
  2026.  
  2027.         call    LocalDisableA20    ; Try to disable A20
  2028.         or        ax,ax        ; Did we do it?
  2029.         jnz     short IDA20Cont    ; Yup - continue
  2030.  
  2031.         cmp     [fCanChangeA20],1    ; Has A20 been permenantly enabled?
  2032.         je        short IDGetParms    ; Yup - continue
  2033.         jmp     short IDBadA20    ; Nope - phoosh ourselves
  2034.         
  2035. IDA20Cont:  call    IsA20On        ; Is A20 off?
  2036.         or        ax,ax
  2037.         jz        short IDGetParms    ; Yup - continue
  2038.  
  2039.         ; A20 ain't doing it.
  2040. IDBadA20:   mov        dx,offset BadA20Msg
  2041.  
  2042.         ; Display the message in DX followed by the "Flush" message.
  2043. IDFlushMe:  mov        ah,9h
  2044.         int        21h
  2045.         mov        dx,offset FlushMsg
  2046.         mov        ah,9h
  2047.         int        21h
  2048.         
  2049.         ; Discard the entire driver.
  2050.         xor        ax,ax
  2051.         mov        [InitLine],ax
  2052.         les        di,[pReqHdr]
  2053.         mov        es:[di.Units],al
  2054.         jmp        short IDReturn
  2055.         
  2056.         ; Process the command line parameters.
  2057. IDGetParms: call    GetParms
  2058.         
  2059.         ; Initialize the Handle Table.
  2060.         call    InitHandles
  2061.  
  2062.         ; Display the success messages.
  2063.         cmp        [fHMAMayExist],0
  2064.         je        short IDIgnition
  2065.         mov        dx,offset HMAOKMsg
  2066.         mov        ah,9h
  2067.         int        21h
  2068.  
  2069.         ; "Turn On" the driver.
  2070. IDIgnition: call    HookInt2F
  2071.  
  2072.         ; Discard the initialization code.
  2073. IDReturn:   les        di,[pReqHdr]
  2074.         mov        ax,[InitLine]
  2075.         mov        word ptr es:[di.Address][0],ax
  2076.         mov        word ptr es:[di.Address][2],cs
  2077.  
  2078.         ; Return success.
  2079.         xor        ax,ax
  2080.         ret
  2081.  
  2082. InitDriver  endp
  2083.  
  2084.         
  2085. ;*--------------------------------------------------------------------------*
  2086. ;*                                        *
  2087. ;*  HookInt2F -                                    *
  2088. ;*                                        *
  2089. ;*    Insert the INT 2F hook                            *
  2090. ;*                                        *
  2091. ;*  ARGS:   None                                *
  2092. ;*  RETS:   None                                *
  2093. ;*  REGS:   AX, SI, ES and Flags are clobbered                    *
  2094. ;*                                        *
  2095. ;*  EXTERNALLY NON-REENTRANT                            *
  2096. ;*    Interrupts must be disabled before calling this function.        *
  2097. ;*                                        *
  2098. ;*--------------------------------------------------------------------------*
  2099.  
  2100. HookInt2F   proc    near
  2101.  
  2102.         ; Save the current INT 2F vector
  2103.         cli
  2104.         xor        ax,ax
  2105.         mov        es,ax
  2106.         mov        si,2Fh * 4            ; ES:SI = Address of 2F vector
  2107.  
  2108.         ; Exchange the old vector with the new one
  2109.         mov        ax,offset Int2FHandler
  2110.         xchg    ax,es:[si][0]
  2111.         mov        word ptr [PrevInt2F][0],ax
  2112.         mov        ax,cs
  2113.         xchg    ax,es:[si][2]
  2114.         mov        word ptr [PrevInt2F][2],ax
  2115.         sti
  2116.         ret
  2117.  
  2118. HookInt2F   endp
  2119.  
  2120.  
  2121. ;*--------------------------------------------------------------------------*
  2122. ;*                                        *
  2123. ;*  MachineCheck -                                *
  2124. ;*                                        *
  2125. ;*    Determines the CPU type.                        *
  2126. ;*                                        *
  2127. ;*  ARGS:   None                                *
  2128. ;*  RETS:   AX = 1 if we're on an 8086/8088 or an 80186, 0 otherwise        *
  2129. ;*  REGS:   AX and Flags are clobbered                        *
  2130. ;*                                        *
  2131. ;*--------------------------------------------------------------------------*
  2132.  
  2133. ; NOTE: This is the "official" Intel method for determining CPU type.
  2134.  
  2135. MachineCheck proc   near
  2136.  
  2137.         xor     ax,ax        ; Move 0 into the Flags register
  2138.         push    ax
  2139.         popf
  2140.         pushf            ; Try and get it back out
  2141.         pop     ax
  2142.         and     ax,0F000h        ; If the top four bits are set...
  2143.         cmp     ax,0F000h
  2144.         je        short MC_8086    ; ...it's an 8086 machine
  2145.  
  2146.         mov     ax,0F000h        ; Move F000h into the Flags register
  2147.         push    ax
  2148.         popf
  2149.         pushf            ; Try and get it back out
  2150.         pop     ax
  2151.         and     ax,0F000h        ; If the top four bits aren't set...
  2152.         jz        short MC_80286    ; ...it's an 80286 machine
  2153.  
  2154.         ; We're on an 80386 machine
  2155.         mov     ax,3
  2156.         ret
  2157.  
  2158. MC_80286:   ; We're on an 80286 machine
  2159.         mov     ax,2
  2160.         ret
  2161.  
  2162. MC_8086:    ; We're on an 8086 machine
  2163.         mov     ax,1
  2164.         ret
  2165.         
  2166. MachineCheck endp
  2167.  
  2168.         
  2169. ;*--------------------------------------------------------------------------*
  2170. ;*                                        *
  2171. ;*  GetBIMMemory -                                *
  2172. ;*                                        *
  2173. ;*    Look for Compaq 'Built In Memory' and add it to the pool of        *
  2174. ;*  available memory                                *
  2175. ;*                                        *
  2176. ;*  ARGS:   None                                *
  2177. ;*  RETS:   AX = Amount of BIM memory found                    *
  2178. ;*  REGS:   AX, BX, CX, and Flags are clobbered                    *
  2179. ;*                                        *
  2180. ;*--------------------------------------------------------------------------*
  2181.  
  2182. ; "Built In Memory" (BIM) starts at FE00:0000h and grows downward.  It is
  2183. ; controlled by a data structure at F000:FFE0h.  Changing the data structure
  2184. ; involves un-write-protecting the ROMs (!) by flipping bit 1 of 80C00000.
  2185.  
  2186. pBIMSTRUCT  equ     0FFE0h
  2187. AVAILABLE   equ     0        ; Set to -1 if BIM isn't around
  2188. TOTALBIM    equ     2        ; Total amount of BIM in the system
  2189. AVAILBIM    equ     4        ; Amount of BIM available in paragraphs
  2190. LASTUSED    equ     6        ; Paragraph address of last (lowest) used
  2191.                 ;  paragraph of BIM
  2192.  
  2193. pCOMPAQ     label   dword
  2194.         dw        0FFE8h
  2195.         dw        0F000h
  2196.         
  2197. szCOMPAQ    db        '03COMPAQ'
  2198.  
  2199. pRAMRELOC   label   dword
  2200.         dw        00000h
  2201.         dw        080C0h
  2202.  
  2203. GDT_TYPE    struc
  2204.         dw        0,0,0,0
  2205.         dw        0,0,0,0
  2206.  
  2207. S_LIMIT     dw        1
  2208. S_BASE_LOW  dw        0
  2209. S_BASE_HI   db        0
  2210. S_RIGHTS    db        93h
  2211. S_RESERVED  dw        0
  2212.  
  2213. D_LIMIT     dw        1
  2214. D_BASE_LOW  dw        0000h
  2215. D_BASE_HI   db        0C0h
  2216. D_RIGHTS    db        93h
  2217. D_RES386    db        0
  2218. D_BASE_XHI  db        080h
  2219.  
  2220.         dw        0,0,0,0
  2221.         dw        0,0,0,0
  2222. GDT_TYPE    ends
  2223.  
  2224. BIMGDT        GDT_TYPE <>
  2225.  
  2226. BIMBuffer   dw        ?
  2227.  
  2228.  
  2229. GetBIMMemory proc near
  2230.  
  2231.         xor     ax,ax
  2232.  
  2233.         ; Are we on a Compaq 386 machine?
  2234.         push    es
  2235.  
  2236.         ; Set up the comparison.
  2237.         les     di,cs:pCOMPAQ
  2238.         mov     si,offset szCOMPAQ
  2239.         mov     cx,8
  2240.         cld
  2241.         rep     cmpsb            ; Do the comparison
  2242.  
  2243.         jne     short FCMNoMem2        ; Nope, return
  2244.  
  2245.         ; Is there a 32-bit memory board installed?
  2246.         mov     bx,pBIMSTRUCT
  2247.         mov     bx,es:[bx]            ; De-reference the pointer
  2248.         mov     dx,es:[bx+AVAILABLE]    ; -1 means no board is installed
  2249.         inc     dx
  2250.         jz        short FCMNoMem2        ; Nope, return
  2251.  
  2252.         ; How much memory is available and where does it start?
  2253.         mov     dx,es:[bx+AVAILBIM]     ; Size in paragraphs
  2254.         or        dx,dx            ; Any left?
  2255.         jz        short FCMNoMem
  2256.         mov     cx,dx            ; CX = Size in paragraphs
  2257.         mov     ax,es:[bx+LASTUSED]
  2258.         sub     ax,cx            ; AX = Starting location - F0000h
  2259.                         ;         in paragraphs
  2260.         push    es                ; Save for a rainy day...
  2261.         push    bx
  2262.         push    ax
  2263.  
  2264.         ; Change AX to the starting location in K.
  2265.         shr     ax,4
  2266.         add     ax,0F000h
  2267.         shr     ax,2
  2268.  
  2269.         ; Change CX to the size in K.
  2270.         shr     cx,6
  2271.  
  2272.         ; Store away for use by HookInt15().
  2273.         mov     [BIMBase],ax
  2274.         mov     [BIMLength],cx
  2275.  
  2276.         ; Un-WriteProtect the ROMs.
  2277.         mov     si,offset BIMGDT            ; Set up the BlockMove GDT
  2278.         mov     ax,cs
  2279.         mov     es,ax
  2280.         mov     cx,16
  2281.         mul     cx
  2282.         add     ax,offset BIMBuffer
  2283.         adc     dl,0
  2284.         mov     [si.S_BASE_LOW],ax
  2285.         mov     [si.S_BASE_HI],dl
  2286.         mov     cx,1
  2287.  
  2288.         mov     word ptr [BIMBuffer],0FEFEh     ; FEh unlocks the ROMs
  2289.  
  2290.         mov     ah,87h                ; Do the BlockMove
  2291.         int     15h
  2292.         or        ah,ah                ; Was there an error?
  2293.         jz        short FCMReserve            ; Nope - continue
  2294.  
  2295.         ; Return error.
  2296.         pop     ax                    ; Clean up
  2297.         pop     bx
  2298.         pop     es
  2299.         xor     ax,ax
  2300.         mov     [BIMBase],ax
  2301.         mov     [BIMLength],ax
  2302. FCMNoMem2:  jmp     short FCMNoMem
  2303.  
  2304.         ; Change the ROM values to reserve the BIM stuff.
  2305. FCMReserve: pop     ax
  2306.         pop     bx
  2307.         pop     es
  2308.         mov     word ptr es:[bx+AVAILBIM],0      ; Reserve all remaining BIM
  2309.         mov     word ptr es:[bx+LASTUSED],ax
  2310.  
  2311.         ; Re-WriteProtect the ROMs.
  2312.         push    cs
  2313.         pop     es
  2314.         mov     si,offset BIMGDT            ; Set up the BlockMove GDT
  2315.  
  2316.         mov     word ptr [BIMBuffer],0FCFCh     ; FCh unlocks the ROMs
  2317.  
  2318.         mov     ah,87h                ; Do the BlockMove
  2319.         int     15h
  2320.  
  2321.         mov     ax,1                ; Return success
  2322.  
  2323. FCMNoMem:   pop     es
  2324.         ret
  2325.  
  2326. GetBIMMemory endp
  2327.  
  2328.  
  2329. ;*--------------------------------------------------------------------------*
  2330. ;*                                        *
  2331. ;*  GetInt15Memory -                                *
  2332. ;*                                        *
  2333. ;*    Returns the amount of memory INT 15h, Function 88h says is free        *
  2334. ;*                                        *
  2335. ;*  ARGS:   None                                *
  2336. ;*  RETS:   AX = Amount of free extended memory in K-bytes            *
  2337. ;*  REGS:   AX and Flags are clobbered                        *
  2338. ;*                                        *
  2339. ;*--------------------------------------------------------------------------*
  2340.         
  2341. GetInt15Memory proc near
  2342.  
  2343.         ; Check for 6300 Plus (to set "MemCorr").
  2344.         call    Is6300Plus
  2345.  
  2346.         ; Get the amount of extended memory Int 15h says is around.
  2347.         mov        ah,88h
  2348.         clc
  2349.         int        15h            ; Is Function 88h around?
  2350.         jnc     short GIM100
  2351.         xor        ax,ax        ; No, return 0
  2352.         ret
  2353.         
  2354. GIM100:        sub        ax,[MemCorr]    ; Compensate for 6300 Plus machines
  2355.         ret
  2356.  
  2357. GetInt15Memory endp               
  2358.         
  2359.         
  2360. ;*--------------------------------------------------------------------------*
  2361. ;*                                        *
  2362. ;*  InstallMoveBlock -                        HARDWARE DEP.   *
  2363. ;*                                        *
  2364. ;*    Attempt to install the proper MoveBlock function.            *
  2365. ;*                                        *
  2366. ;*  ARGS:   None                                *
  2367. ;*  RETS:   None                                *
  2368. ;*  REGS:   AX, CX, DI, SI, ES and Flags are clobbered                *
  2369. ;*                                        *
  2370. ;*--------------------------------------------------------------------------*
  2371.  
  2372. InstallMoveBlock proc near
  2373.  
  2374.         ; Are we on a 386 machine?
  2375.         call    MachineCheck
  2376.         cmp     ax,3
  2377.         je        short IMBOn386        ; Yes, install the 386 routine
  2378.  
  2379.         ; Install the 286 MoveBlock routine.
  2380.         mov     [InitLine],offset EndMoveBlock286
  2381.         ret
  2382.  
  2383.         ; Install the 386 MoveBlock routine.
  2384. IMBOn386:   mov     si,offset MoveBlock386
  2385.         mov     cx,(offset EndMoveBlock386 - offset MoveBlock386)
  2386.  
  2387.         ; REP MOV the routine into position.
  2388.         cld
  2389.         push    cs
  2390.         pop        es
  2391.         mov     di,offset MoveBlock
  2392.         add     [InitLine],cx
  2393.         rep movsb
  2394.         call    InitMoveBlock386
  2395.         ret
  2396.  
  2397. InstallMoveBlock endp
  2398.  
  2399.  
  2400. ;*--------------------------------------------------------------------------*
  2401. ;*                                        *
  2402. ;*  InitMoveBlock386 -                        HARDWARE DEP.   *
  2403. ;*                                        *
  2404. ;*    Initializes the 386 MoveBlock routine                    *
  2405. ;*                                        *
  2406. ;*  ARGS:   None                                *
  2407. ;*  RETS:   None                                *
  2408. ;*  REGS:   AX, CX, DX and Flags are clobbered                    *
  2409. ;*                                        *
  2410. ;*--------------------------------------------------------------------------*
  2411.  
  2412. InitMoveBlock386 proc near
  2413.  
  2414.         mov     ax,cs            ; dx has CS of codeg
  2415.         mov     [patch3],ax         ; Patch code
  2416.         mov     cx,16
  2417.         mul     cx
  2418.         mov     [descCS].LO_apDesc386,ax    ; Set up selector for our CS
  2419.         mov     [descCS].MID_apDesc386,dl
  2420.         add     ax,offset code:OurGDT    ; Calculate Base of GDT
  2421.         adc     dx,0
  2422.         mov     [GDTPtr.LO_apBaseGdt],ax
  2423.         mov     [GDTPtr.HI_apBaseGdt],dx
  2424.         mov     ax,offset code:MoveExtended386+MEM3_Offset
  2425.         mov     ControlJumpTable[0Bh*2],ax
  2426.         ret
  2427.  
  2428. InitMoveBlock386 endp
  2429.  
  2430.  
  2431. ;*--------------------------------------------------------------------------*
  2432. ;*                                        *
  2433. ;*  InstallA20 -                        HARDWARE DEP.   *
  2434. ;*                                        *
  2435. ;*    Attempt to install the proper A20 Handler                *
  2436. ;*                                        *
  2437. ;*  ARGS:   None                                *
  2438. ;*  RETS:   None                                *
  2439. ;*  REGS:   AX, CX, DI, SI, ES and Flags are clobbered                *
  2440. ;*                                        *
  2441. ;*--------------------------------------------------------------------------*
  2442.  
  2443. InstallA20  proc near
  2444.         
  2445.         ; Are we on a 6300 Plus?
  2446.         call    Is6300Plus
  2447.         or        ax,ax
  2448.         jz        short IAChkPS2
  2449.  
  2450.         ; Yes, relocate 6300 Plus A20 handler.
  2451.         mov        si,offset $6300PLUS_A20Handler
  2452.         mov        cx,(offset End6300PLUS_Handler - offset $6300PLUS_A20Handler)
  2453.         jmp        short IAMoveIt
  2454.  
  2455.         ; Are we on a PS/2?
  2456. IAChkPS2:   call    IsPS2Machine
  2457.         cmp        ax,1
  2458.         jne     short IACheckHP
  2459.  
  2460.         ; Yes, relocate the PS/2 A20 handler.
  2461.         mov        si,offset PS2_A20Handler
  2462.         mov        cx,(offset EndPS2_A20Handler - offset PS2_A20Handler)
  2463.         jmp        short IAMoveIt
  2464.  
  2465.         ; Are we on a HP Vectra?
  2466. IACheckHP:  call    IsHPMachine
  2467.         cmp        ax,1
  2468.         jne     short IAOnAT
  2469.  
  2470.         ; Yes, relocate the HP A20 handler.
  2471.         mov        si,offset HP_A20Handler
  2472.         mov     cx,(offset EndHP_A20Handler - offset HP_A20Handler)
  2473.         jmp     short IAMoveIt
  2474.  
  2475. IAOnAT:     mov     si,offset AT_A20Handler
  2476.         mov     cx,(offset EndAT_A20Handler - offset AT_A20Handler)
  2477.  
  2478.         ; REP MOV the proper handler into position.
  2479. IAMoveIt:   cld
  2480.         push    cs
  2481.         pop        es
  2482.         mov     di,[InitLine]
  2483.         mov     [A20Handler],di
  2484.         add        [InitLine],cx
  2485.         rep movsb
  2486.         ret
  2487.  
  2488. InstallA20  endp
  2489.  
  2490.  
  2491. ;*--------------------------------------------------------------------------*
  2492. ;*                                        *
  2493. ;*  GetParms -                                    *
  2494. ;*                                        *
  2495. ;*    Get any parameters off of the HIMEM command line            *
  2496. ;*                                        *
  2497. ;*  ARGS:   None                                *
  2498. ;*  RETS:   None                                *
  2499. ;*  REGS:   AX, BX, CX, DX, DI, SI, ES and Flags clobbered            *
  2500. ;*                                        *
  2501. ;*  Side Effects:   cHandles and MinHMASize may be changed            *
  2502. ;*                                        *
  2503. ;*--------------------------------------------------------------------------*
  2504.  
  2505. GPRegSave   dw        ?
  2506.  
  2507. GetParms    proc    near
  2508.  
  2509.         push    ds
  2510.  
  2511.         cld
  2512.         les        di,[pReqHdr]
  2513.         lds        si,es:[di.pCmdLine]        ; DS:SI points to first char
  2514.                         ; after "DEVICE="
  2515.         ; Scan until we see a frontslash or the end of line.
  2516. GPBadParm:          
  2517. GPNextChar: lodsb
  2518.         cmp        al,'/'
  2519.         je        short GPGotOne
  2520.         cmp        al,13
  2521.         jne     short GPNextChar
  2522. GPDatsAll:  pop        ds
  2523.         ret
  2524.  
  2525.         ; Save what we found and get the number after it.
  2526. GPGotOne:   lodsb
  2527.         mov        cs:[GPRegSave],ax
  2528.         
  2529.         ; Scan past the rest of the parm for a number, EOL, or a space.
  2530. GPNeedNum:  lodsb
  2531.         cmp        al,' '
  2532.         je        short GPBadParm
  2533.         cmp        al,13
  2534.         je        short GPBadParm
  2535.         cmp        al,'0'
  2536.         jb        short GPNeedNum
  2537.         cmp        al,'9'
  2538.         ja        short GPNeedNum
  2539.         
  2540.         ; Read the number at DS:SI into DX.
  2541.         xor        dx,dx
  2542. GPNumLoop:  sub        al,'0'
  2543.         cbw
  2544.         add        dx,ax
  2545.         lodsb
  2546.         cmp        al,' '
  2547.         je        short GPNumDone
  2548.         cmp        al,13
  2549.         je        short GPNumDone
  2550.         cmp        al,'0'
  2551.         jb        short GPBadParm
  2552.         cmp        al,'9'
  2553.         ja        short GPBadParm
  2554.         shl        dx,1            ; Stupid multiply DX by 10
  2555.         mov        bx,dx
  2556.         shl        dx,1
  2557.         shl        dx,1
  2558.         add        dx,bx
  2559.         jmp        short GPNumLoop
  2560.         
  2561.         ; Which parameter are we dealing with here?
  2562. GPNumDone:  xchg    ax,cs:[GPRegSave]
  2563.         cmp        al,'H'            ; HMAMIN= parameter?
  2564.         je        short GPGotMin
  2565.         cmp        al,'N'            ; NUMHANDLES= parameter?
  2566.         jne     short GPBadParm
  2567.  
  2568.         ; Process /NUMHANDLES= parameter.
  2569. GPGotHands: cmp        dx,MAXHANDLES
  2570.         ja        short GPBadParm
  2571.  
  2572.         or        dx,dx            ; Zero?
  2573.         jz        short GPBadParm
  2574.  
  2575.         mov     cs:[cHandles],dx        ; Store it
  2576.  
  2577.         ; Print descriptive message.
  2578.         mov        dx,offset StartMsg
  2579.         call    GPPrintIt
  2580.         mov        ax,cs:[cHandles]
  2581.         call    GPPrintAX
  2582.         mov        dx,offset HandlesMsg
  2583.         call    GPPrintIt
  2584.         jmp        short GPNextParm
  2585.  
  2586.         ; Process /HMAMIN= parameter.
  2587. GPGotMin:   cmp        dx,64
  2588.         ja        short GPBadParm
  2589.  
  2590.         push    dx
  2591.         mov        cs:[MinHMASize],dx
  2592.  
  2593.         ; Print a descriptive message.
  2594.         mov        dx,offset HMAMINMsg
  2595.         call    GPPrintIt
  2596.         mov        ax,cs:[MinHMASize]
  2597.         call    GPPrintAX
  2598.         mov        dx,offset KMsg
  2599.         call    GPPrintIt
  2600.  
  2601.         pop        dx
  2602.         mov        cl,10            ; Convert from K to bytes
  2603.         shl        dx,cl
  2604.         mov        cs:[MinHMASize],dx
  2605.  
  2606.         ; Were we at the end of the line?
  2607. GPNextParm: mov        ax,cs:[GPRegSave]
  2608.         cmp        al,13
  2609.         je        short GPExit
  2610.         jmp     GPNextChar
  2611.  
  2612. GPExit:        pop        ds
  2613.         ret
  2614.         
  2615. GetParms    endp
  2616.  
  2617. ;*--------------------------------------------------------------------------*
  2618.  
  2619. GPPrintIt   proc    near
  2620.  
  2621.         push    ds                ; Save current DS
  2622.         push    cs                ; Set DS=CS
  2623.         pop        ds
  2624.         mov        ah,9h
  2625.         int        21h
  2626.         pop        ds                ; Restore DS
  2627.         ret
  2628.  
  2629. GPPrintIt   endp
  2630.  
  2631. ;*--------------------------------------------------------------------------*
  2632.  
  2633. GPPrintAX   proc    near
  2634.  
  2635.         mov        cx,10
  2636.         xor        dx,dx
  2637.         div        cx
  2638.         or        ax,ax
  2639.         jz        short GPAPrint
  2640.         push    dx
  2641.         call    GPPrintAX
  2642.         pop        dx
  2643. GPAPrint:   add        dl,'0'
  2644.         mov        ah,2h
  2645.         int        21h
  2646.         ret
  2647.  
  2648. GPPrintAX   endp
  2649.  
  2650.  
  2651. ;*--------------------------------------------------------------------------*
  2652. ;*                                        *
  2653. ;*  InitHandles -                                *
  2654. ;*                                        *
  2655. ;*    Initialize the Extended Memory Handle Table                *
  2656. ;*                                        *
  2657. ;*  ARGS:   None                                *
  2658. ;*  RETS:   None                                *
  2659. ;*  REGS:   AX, BX, CX, and Flags are clobbered                    *
  2660. ;*                                        *
  2661. ;*--------------------------------------------------------------------------*
  2662.  
  2663. InitHandles proc    near
  2664.  
  2665.         ; Allocate room for the Handle table at the end.
  2666.         mov        ax,[InitLine]
  2667.         mov        [KiddValley],ax
  2668.         mov        ax,SIZE Handle
  2669.         mov        cx,[cHandles]
  2670.         mul        cx
  2671.         add        [InitLine],ax
  2672.         
  2673.         ; Init the Handle table.
  2674.         mov        bx,KiddValley
  2675.         xor        ax,ax
  2676.         mov        cx,[cHandles]
  2677. IHTabLoop:  mov        [bx.Flags],UNUSEDFLAG
  2678.         mov        [bx.cLock],al
  2679.         mov        [bx.Base],ax
  2680.         mov        [bx.Len],ax
  2681.         add        bx,SIZE Handle
  2682.         loop    IHTabLoop
  2683.  
  2684.         ; Store away the top of the table for handle validation.
  2685.         mov        [KiddValleyTop],bx
  2686.         ret
  2687.         
  2688. InitHandles endp
  2689.  
  2690.  
  2691. ;*--------------------------------------------------------------------------*
  2692. ;*                                        *
  2693. ;*  Is6300Plus                           HARDWARE DEP.    *
  2694. ;*                                        *
  2695. ;*    Check for AT&T 6300 Plus                        *
  2696. ;*                                        *
  2697. ;*  ARGS:   None                                *
  2698. ;*  RETS:   AX = 1 if we're on an AT&T 6300 Plus, 0 otherwise            *
  2699. ;*  REGS:   AX, flags used.                            *
  2700. ;*                                        *
  2701. ;*  Side Effects:   MemCorr value updated to 384 if necessary.            *
  2702. ;*                                        *
  2703. ;*--------------------------------------------------------------------------*
  2704.  
  2705. Is6300Plus  proc near
  2706.  
  2707.         xor        ax,ax
  2708.         push    bx
  2709.         mov        bx,0FC00h            ; Look for 'OL' at FC00:50
  2710.         mov        es,bx
  2711.         cmp        es:[0050h],'LO'
  2712.         jne     short I6PNotPlus        ; Not found
  2713.         mov        bx,0F000h
  2714.         mov        es,bx
  2715.         cmp        word ptr es:[0FFFDh],0FC00h        ; Look for 6300 PLUS
  2716.         jne     short I6PNotPlus
  2717.  
  2718.         in        al,66h            ; Look for upper extended memory
  2719.         and        al,00001111b
  2720.         cmp        al,00001011b
  2721.         jne     short I6PNoMem
  2722.         mov        [MemCorr],384        ; Save value
  2723.  
  2724. I6PNoMem:   mov        ax,1            ; We found a PLUS
  2725. I6PNotPlus: pop        bx
  2726.         ret
  2727.  
  2728. Is6300Plus  endp
  2729.  
  2730.  
  2731. ;*--------------------------------------------------------------------------*
  2732. ;*                                        *
  2733. ;*  IsPS2Machine                        HARDWARE DEP.   *
  2734. ;*                                        *
  2735. ;*    Check for PS/2 machine                            *
  2736. ;*                                        *
  2737. ;*  ARGS:   None                                *
  2738. ;*  RETS:   AX = 1 if we're on a valid PS/2 machine, 0 otherwise        *
  2739. ;*  REGS:   AX    and Flags clobbered                        *
  2740. ;*                                        *
  2741. ;*--------------------------------------------------------------------------*
  2742.  
  2743. IsPS2Machine proc   near
  2744.  
  2745.         mov     ah,0C0h        ; Get System Description Vector
  2746.         stc
  2747.         int        15h
  2748.         jc        short IPMNoPS2  ; Error?  Not a PS/2.
  2749.  
  2750.         ; Do we have a "Micro Channel" computer?
  2751.         mov     al,byte ptr es:[bx+5]   ; Get "Feature Information Byte 1"
  2752.         test    al,00000010b    ; Test the "Micro Channel Implemented" bit
  2753.         jz        short IPMNoPS2
  2754.  
  2755. IPMFoundIt: xor        ax,ax        ; Disable A20. Fixes PS2 Ctl-Alt-Del bug
  2756.         call    PS2_A20Handler
  2757.         mov        ax,1
  2758.         ret
  2759.  
  2760. IPMNoPS2:   xor        ax,ax
  2761.         ret
  2762.  
  2763. IsPS2Machine endp
  2764.  
  2765.  
  2766. ;*--------------------------------------------------------------------------*
  2767. ;*                                        *
  2768. ;*  IsHPMachine                            HARDWARE DEP.   *
  2769. ;*                                        *
  2770. ;*    Check for HP Vectra Machine                        *
  2771. ;*                                        *
  2772. ;*  ARGS:   None                                *
  2773. ;*  RETS:   AX = 1 if we're on a HP Vectra machine, 0 otherwise            *
  2774. ;*  REGS:   AX, ES and Flags clobbered                        *
  2775. ;*                                        *
  2776. ;*--------------------------------------------------------------------------*
  2777.  
  2778. IsHPMachine proc   near
  2779.  
  2780.         mov        ax,0F000h
  2781.         mov        es,ax
  2782.         mov        ax,word ptr es:[0F8h]
  2783.         cmp        ax,'PH'
  2784.         je        short IHMFoundIt
  2785.         xor        ax,ax
  2786.         ret
  2787.  
  2788. IHMFoundIt: mov        ax,1
  2789.         ret
  2790.  
  2791. IsHPMachine endp
  2792.  
  2793.  
  2794. ;*--------------------------------------------------------------------------*
  2795. ;*    DRIVER MESSAGES                                *
  2796. ;*--------------------------------------------------------------------------*         
  2797.  
  2798. SignOnMsg   db    13,10,'HIMEM: DOS XMS Driver, Version 2.06 - 2/07/89'
  2799.         db    13,10,'Copyright 1988,1989 Microsoft Corp.'
  2800.         db    13,10,'$'
  2801.  
  2802. BadDOSMsg   db    13,10,'ERROR: HIMEM.SYS requires DOS 3.00 or higher.$'
  2803. NowInMsg    db    13,10,'ERROR: An Extended Memory Manager is already installed.$'
  2804. On8086Msg   db    13,10,'ERROR: HIMEM.SYS requires an 80x86-based machine.$'
  2805. NoExtMemMsg db    13,10,'ERROR: No available extended memory was found.$'
  2806. BadA20Msg   db    13,10,'ERROR: Unrecognized A20 hardware.$'
  2807. FlushMsg    db    13,10,'          XMS Driver not installed.',13,10,13,10,'$'
  2808.  
  2809. StartMsg    db    13,10,'$'
  2810. HandlesMsg  db    ' extended memory handles available.$'
  2811. HMAMINMsg   db    13,10,'Minimum HMA size set to $'
  2812. KMsg        db    'K.$'
  2813.  
  2814. NoHMAMsg    db    13,10,'WARNING: The High Memory Area is unavailable.',13,10,'$'
  2815. A20OnMsg    db    13,10,'WARNING: The A20 Line was already enabled.',13,10,'$'
  2816.  
  2817. HMAOKMsg    db    13,10,'64K High Memory Area is available.',13,10,13,10,'$'
  2818.  
  2819.         db    'This program is the property of Microsoft Corporation.'
  2820.         
  2821.         db    64 dup(0)            ; For internationalization
  2822.  
  2823. ;*==========================================================================*
  2824.  
  2825. code        ends
  2826.  
  2827.         end
  2828.