;
; XMS.ASM - External Assembler Routines for XMS.PAS
;
; Paul Willmott
;
; 1.1 - 24.07.89
;

.MODEL TPASCAL

.DATA

                                      EXTRN XMSControl : DWORD
                                      EXTRN XMSStatus  : BYTE

DATA                                  ENDS

.CODE

;
; This MACRO Handles the Setting of XMSStatus after All Operations
;

SetXMSStatus                          MACRO
                                           LOCAL Fail
                                           CMP AX,0000H
                                           JE Fail
                                           XOR BL,BL
Fail:                                      MOV XMSStatus,BL
                                      ENDM

;
; This Function is called by default if the program hasn't called
; _XMSInstalled or if no XMS driver is found.
;

_XMSNotInitialised                    PROC FAR
                                      PUBLIC _XMSNotInitialised

                                      XOR AX,AX
                                      MOV BL,80H
                                      RET

_XMSNotInitialised                    ENDP

;
; FUNCTION _XMSInstalled:BYTE
;
; This Function Returns 80h iff Driver Is Installed
;

_XMSInstalled                         PROC NEAR
                                      PUBLIC _XMSInstalled

;
;    Check XMS Driver Installed
;

                                      MOV AX,4300H
                                      INT 2FH
                                      CMP AL,80H
                                      JNE NoXMSDriver

;
;    Get the Address of the XMS Driver's Control Function
;

                                      MOV AX,4310H
                                      INT 2FH
                                      MOV WORD PTR [XMSControl],BX
                                      MOV WORD PTR [XMSControl+2],ES

;
;    Set Return Value
;

                                      MOV AL,80H

NoXMSDriver:                          RET

_XMSInstalled                         ENDP

;
; FUNCTION _XMSVersionNumber:WORD
;
; This Function Returns a 16-Bit BCD Number representing the revision
; of the DOS Extended Memory Specification which the Driver implements.
;

_XMSVersionNumber                     PROC NEAR
                                      PUBLIC _XMSVersionNumber

                                      MOV AH,00H
                                      CALL [XMSControl]
                                      MOV XMSStatus,00H
                                      RET

_XMSVersionNumber                     ENDP

;
; FUNCTION _XMSInternalRevisionNumber:WORD
;
; This Function Returns a 16-Bit BCD Number representing the driver's
; internal revision number.
;

_XMSDriverInternalRevisionNumber      PROC NEAR
                                      PUBLIC _XMSDriverInternalRevisionNumber

                                      MOV AH,00H
                                      CALL [XMSControl]
                                      MOV AX,BX
                                      MOV XMSStatus,00H
                                      RET

_XMSDriverInternalRevisionNumber      ENDP

;
; FUNCTION _XMSHMAExists:WORD
;
; This Function Returns 0001H if the HMA exists, 0000H otherwise.
;

_XMSHMAExists                         PROC NEAR
                                      PUBLIC _XMSHMAExists

                                      MOV AH,00H
                                      CALL [XMSControl]
                                      MOV AX,DX
                                      MOV XMSStatus,00H
                                      RET

_XMSHMAExists                         ENDP

;
; PROCEDURE XMSRequestHMA
;
; This procedure attempts to reserve the 64K-16 byte high memory area
; for the caller.
;

XMSRequestHMA                         PROC FAR
                                      PUBLIC XMSRequestHMA

                                      MOV AH,01H
                                      MOV DX,0FFFFH
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSRequestHMA                         ENDP

;
; PROCEDURE XMSReleaseHMA
;
; This procedure releases the high memory area and allows other programs
; to use it. Programs which use the HMA must release it before exiting.
; When the HMA has been released, any code or data stored in it becomes
; invalid and should not be accessed.
;

XMSReleaseHMA                         PROC FAR
                                      PUBLIC XMSReleaseHMA

                                      MOV AH,02H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSReleaseHMA                         ENDP

;
; PROCEDURE XMSGlobalEnableA20
;
; This procedure attempts to enable the A20 line. It should only be used
; by programs which have control of the HMA. The A20 line should be turned
; off before a program releases control of the system.
;

XMSGlobalEnableA20                    PROC FAR
                                      PUBLIC XMSGlobalEnableA20

                                      MOV AH,03H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSGlobalEnableA20                    ENDP

;
; PROCEDURE XMSGlobalDisableA20
;
; This function attempts to disable the A20 line. It should only be used
; by programs which have control of the HMA. The A20 line should be
; disabled before a program releases control of the system.
;

XMSGlobalDisableA20                   PROC FAR
                                      PUBLIC XMSGlobalDisableA20

                                      MOV AH,04H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSGlobalDisableA20                   ENDP

;
; PROCEDURE XMSLocalEnableA20
;
; This procedure attempts to enable the A20 line. It should only be used
; by programs which need direct access to extended memory.
;

XMSLocalEnableA20                     PROC FAR
                                      PUBLIC XMSLocalEnableA20

                                      MOV AH,05H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSLocalEnableA20                     ENDP

;
; PROCEDURE XMSLocalDisableA20
;
; This procedure attempts to Disable the A20 line. It should only be used
; by programs which need direct access to extended memory.
;

XMSLocalDisableA20                    PROC FAR
                                      PUBLIC XMSLocalDisableA20

                                      MOV AH,06H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSLocalDisableA20                    ENDP

;
; FUNCTION _XMSQueryA20
;
; This function returns 0001H if the A20 line is physically enabled,
; 0000H otherwise.
;

_XMSQueryA20                          PROC NEAR
                                      PUBLIC _XMSQueryA20

                                      MOV AH,07H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

_XMSQueryA20                          ENDP

;
; FUNCTION XMSLargestFreeEMB:WORD
;
; This function returns the largest free extended memory block in K-bytes.
;

XMSLargestFreeEMB                     PROC FAR
                                      PUBLIC XMSLargestFreeEMB

                                      MOV AH,08H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSLargestFreeEMB                     ENDP


;
; FUNCTION XMSTotalFreeEM:WORD
;
; This function returns the Total amount of free extended memory block
; in K-bytes.
;

XMSTotalFreeEM                        PROC FAR
                                      PUBLIC XMSTotalFreeEM

                                      MOV AH,08H
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      MOV AX,DX
                                      RET

XMSTotalFreeEM                        ENDP

;
; FUNCTION XMSAllocEMB(Amount:WORD):WORD
;
; This function attempts to allocate a block of the given size out of the
; pool of free extended memory. If a block is availiable, it is reserved
; for the caller and a 16-bit handle to that block is returned. The handle
; returned should be used in all subsequent extended memory calls. If no
; memory was allocated, the returned handle is null.
;

XMSAllocEMB                           PROC FAR Amount:WORD
                                      PUBLIC XMSAllocEMB

                                      MOV AH,09H
                                      MOV DX,Amount
                                      CALL [XMSControl]
                                      CMP AX,0001H
                                      JNE L1
                                      MOV AX,DX
                                      XOR BL,BL
L1:                                   MOV XMSStatus,BL
                                      RET

XMSAllocEMB                           ENDP

;
; PROCEDURE XMSFreeEMB(Handle:WORD)
;
; This procedure frees a block of extended memory. Programs which allocate
; extended memory should free their memory blocks before exiting. When
; an extended memory buffer is freed, its handle and all data stored in
; it become invalid and should not be accessed.
;

XMSFreeEMB                            PROC FAR Handle:WORD
                                      PUBLIC XMSFreeEMB

                                      MOV AH,0AH
                                      MOV DX,Handle
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSFreeEMB                            ENDP

;
; PROCEDURE _XMSMoveEMB(ExtMemStructPtr:POINTER) ;
;
; This function attempts to transfer a block of data from one location
; to another. (see XMS.PAS)
;

_XMSMoveEMB                           PROC NEAR ExtMemStructPtr:DWORD
                                      PUBLIC _XMSMoveEMB

                                      LDS SI,ExtMemStructPtr
                                      MOV AH,0BH
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

_XMSMoveEMB                           ENDP

;
; PROCEDURE _XMSLockEMB(Handle:WORD)
;
; This function locks an extended memory block and returns its base address
; as a 32-bit linear address. Locked blocks are guaranteed not to move. The
; 32-bit pointer is only valid while the block is locked. Locked blocks
; should be unlocked as soon as possible.
;

XMSLockEMB                            PROC FAR Handle:WORD
                                      PUBLIC XMSLockEMB

                                      MOV AH,0CH
                                      MOV DX,Handle
                                      CALL [XMSControl]
                                      CMP AX,0001H
                                      JNE L2
                                      MOV AX,BX
                                      XOR BL,BL
L2:                                   MOV XMSStatus,BL
                                      RET

XMSLockEMB                            ENDP

;
; PROCEDURE XMSUnLockEMB(Handle:WORD)
;
; This procedure unlocks a locked extended memory block. Any 32-Bit
; pointers into the block become invalid and should no longer be used.
;

XMSUnLockEMB                          PROC FAR Handle:WORD
                                      PUBLIC XMSUnLockEMB

                                      MOV AH,0DH
                                      MOV DX,Handle
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSUnLockEMB                          ENDP

;
; FUNCTION XMSGetEMBLockCount(Handle:WORD):BYTE
;
; This Function returns the Block's Lock Count

XMSGetEMBLockCount                    PROC FAR Handle:WORD
                                      PUBLIC XMSGetEMBLockCount

                                      MOV AH,0EH
                                      MOV DX,Handle
                                      CALL [XMSControl]
                                      CMP AX,0001H
                                      JNE L3
                                      MOV AL,BH
                                      XOR BL,BL
L3:                                   MOV XMSStatus,BL
                                      RET

XMSGetEMBLockCount                    ENDP

;
; FUNCTION XMSGetFreeEMBHandles(Handle:WORD):BYTE
;
; This Function returns the Number of free EMB Handles in system.

XMSGetFreeEMBHandles                  PROC FAR Handle:WORD
                                      PUBLIC XMSGetFreeEMBHandles

                                      MOV AH,0EH
                                      MOV DX,Handle
                                      CALL [XMSControl]
                                      CMP AX,0001H
                                      JNE L4
                                      MOV AL,BL
                                      XOR BL,BL
L4:                                   MOV XMSStatus,BL
                                      RET

XMSGetFreeEMBHandles                  ENDP

;
; FUNCTION XMSGetEMBLength(Handle:WORD):WORD
;
; This Function returns the block's length in K-Bytes.

XMSGetEMBLength                       PROC FAR Handle:WORD
                                      PUBLIC XMSGetEMBLength

                                      MOV AH,0EH
                                      MOV DX,Handle
                                      CALL [XMSControl]
                                      CMP AX,0001H
                                      JNE L5
                                      MOV AX,DX
                                      XOR BL,BL
L5:                                   MOV XMSStatus,BL
                                      RET

XMSGetEMBLength                       ENDP

;
; PROCEDURE XMSReAllocEMB(Handle,NewSize:WORD)
;
; This procedure attempts to reallocate an unlocked memory block so that
; it becomes the newly specified size. If the new size is smaller than
; the old block's size, all data at the upper end of the old block is lost
;

XMSReAllocEMB                         PROC FAR Handle,NewSize:WORD
                                      PUBLIC XMSReAllocEMB

                                      MOV AH,0FH
                                      MOV DX,Handle
                                      MOV BX,NewSize
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSReAllocEMB                         ENDP

;
; FUNCTION XMSRequestUMB(VAR Amount:WORD):WORD
;
; This function attempts to allocate an upper memory block to the caller.
; if the function fails, the size of the largest free UMB is returned in
; Amount otherwise the actual size of the block is returned.
; The function returns the segment number of the UMB.
;

XMSRequestUMB                         PROC FAR Amount:PTR WORD
                                      PUBLIC XMSRequestUMB

                                      MOV AH,10H
                                      MOV DX,[Amount]
                                      CALL [XMSControl]
                                      MOV [Amount],DX
                                      CMP AX,0001H
                                      JNE L6
                                      MOV AX,BX
                                      XOR BL,BL
L6:                                   MOV XMSStatus,BL
                                      RET

XMSRequestUMB                         ENDP

;
; PROCEDURE XMSReleaseUMB(SegmentNumber:WORD)
;
; This procedure frees a previously allocated upper memory block. When an
; UMB has been released, any code or data stored in it becomes invalid and
; should not be accessed.
;

XMSReleaseUMB                         PROC FAR SegmentNumber:WORD
                                      PUBLIC XMSReleaseUMB

                                      MOV AH,11H
                                      MOV DX,SegmentNumber
                                      CALL [XMSControl]
                                      SetXMSStatus
                                      RET

XMSReleaseUMB                         ENDP

                                      ENDS

                                      END
