;************************************************
;***                                          ***
;***    Contains definitions for XMS routines ***
;***                                          ***
;************************************************

;
;   Define the extended function interrupt which gives us the
;   XMS handler address:
;
XFunc       equ     2fh

;
;   Define the function code for XMS, and the two sub-codes:
;
XFuncXMS        equ     43h
XFuncXMSPres    equ     0h
XFuncXMSEntry   equ     10h

;
;   Define the XMSPresent response:
;
XMSPresent      equ     80h


;
;   Now define the 2.0 XMS function codes.
;   These are 8 bit values which are loaded into
;   AH before calling the XMS handler (the address of which
;   was determined using XFuncXMSEntry int).
;
XMSGetVersion   equ     00h
XMSAllocHMA     equ     01h
XMSFreeHMA      equ     02h
XMSGlobEnabA20  equ     03h
XMSGlobDisabA20 equ     04h
XMSLocEnabA20   equ     05h
XMSLocDisabA20  equ     06h
XMSGetA20State  equ     07h
XMSGetFreeXM    equ     08h
XMSAllocXM      equ     09h
XMSFreeXM       equ     0ah
XMSMoveXM       equ     0bh
XMSLockXM       equ     0ch
XMSUnlockXM     equ     0dh
XMSGetHandInfo  equ     0eh
XMSResizeXM     equ     0fh
XMSAllocUM      equ     10h
XMSFreeUM       equ     11h


;
;   Now define the XMS error codes:
;
XMSErrOK        equ     00h     ; No error
XMSErrUnimp     equ     80h     ; Unimplemented function
XMSErrVDISK     equ     81h     ; VDISK device detected
XMSErrA20       equ     82h     ; A20 error
XMSErrNoHMA     equ     90h     ; HMA does not exist
XMSErrHMAInUse  equ     91h     ; HMA already in use
XMSErrHMAMin    equ     92h     ; HMA space req. < /HMAMIN= parameter
XMSErrHMANotAll equ     93h     ; HMA not allocated
XMSErrA20Enab   equ     94h     ; A20 still enabled
XMSErrNoXMLeft  equ     0A0h    ; All XM allocated
XMSErrNoHandles equ     0A1h    ; All handles are allocated
XMSErrHandInv   equ     0A2h    ; Invalid handle
XMSErrSHandInv  equ     0A3h    ; Invalid Source Handle
XMSErrSOffInv   equ     0A4h    ; Invalid Source Offset
XMSErrDHandInv  equ     0A5h    ; Invalid Dest Handle
XMSErrDOffInv   equ     0A6h    ; Invalid Dest Offset
XMSErrLenInv    equ     0A7h    ; Invalid Length
XMSErrOverlap   equ     0A8h    ; Invalid move overlap
XMSErrParity    equ     0A9h    ; Parity error
XMSErrNoLock    equ     0AAh    ; Handle not locked
XMSErrLock      equ     0ABh    ; Handle Locked
XMSErrLockOvflo equ     0ACh    ; Lock count overflo
XMSErrLockFail  equ     0ADh    ; Lock fail
XMSErrSmUMB     equ     0B0h    ; Smaller UMB available
XMSErrNoUMB     equ     0B1h    ; No UMB's available
XMSErrUMBInv    equ     0B2h    ; Invalid UMB segment


;
;   Define the Bios interrupt and function codes
;
XMSBios         equ     15h

;
;   Define the two function codes
;
XMSBiosXMMove   equ     87h     ; Move a block of XMS
XMSBiosXMSize   equ     88h     ; Get size of extended memory

;
;   Define the access byte
;
XMSBiosAccess   equ     93h     ; The "correct" access byte


;**************************************************************
;***                                                        ***
;***    int xms_init()                                      ***
;***                                                        ***
;***    Initializes the XMS interface. Returns a zero       ***
;***    if interface successfully initialized.              ***
;***                                                        ***
;**************************************************************

;--------------------------------------
;
; Declare memory model and language
;

        .Model  Large,C     

;--------------------------------------
;
; Declare error WORD as extrn to this
; module
;

        extrn   errno:WORD 

;--------------------------------------
;
; Declare function as PUBLIC
;

        public  xms_init
        public  xmsHandler

        .Data

;
;   Define the xmsHandler address which will be used
;   for calls to XMS.
;
xmsHandler      dd      xms_defaultHandler

;--------------------------------------
;
; Begin code segment
;

        .Code

xms_init    proc

        mov     ah,XFuncXMS     ; XMS functions
        mov     al,XFuncXMSPres ; Determine is XMS present
        int     XFunc           ; Call extended functions

        cmp     al,XMSPresent   ; See if it's there
        jne     noXMS           ; Nope, return an error

    ;
    ;   It's there, so let's get the handler address:
    ;
        mov     ah,XFuncXMS     ; XMS functions
        mov     al,XFuncXMSEntry; Get handler entry point
        int     XFunc           ; Call extended functions

        mov     word ptr xmsHandler,bx      ; Handler offset
        mov     word ptr xmsHandler+2,es    ; Handler segment

        mov     ax,XMSErrOK     ; no error
        ret

noXMS:
        mov     ax,XMSErrUnimp  ; No XMS (Unimplemented function)
        mov     errno,ax        ; Copy to errno
        ret

xms_init    endp                ; end of procedure

;
;   The xms_default_handler is used so that a call to
;   xmsHandler before XMS is initialized will return an
;   error. This is replaced by the actual handler when
;   xms_init is called.
;
xms_defaultHandler      proc

        xor     ax,ax           ; ax to zero means error
        mov     bl,XMSErrUnimp  ; Unimplemented function
        ret

xms_defaultHandler      endp



;**************************************************************
;***                                                        ***
;***    int xms_allocHMA(WORD hmaBytes)                     ***
;***                                                        ***
;***    Allocates the High Memory Area to the program.      ***
;***    HmaBytes specifies the amount of HMA which the      ***
;***    the program intends to use. If it asks for a        ***
;***    sufficient amount, the request will be granted.     ***
;***                                                        ***
;**************************************************************

        .model  large,C   

        extrn   errno:WORD  

;
;   Define entry point
;
        public  xms_allocHMA

        .code

xms_allocHMA    proc    hmaBytes:Word

        mov     dx,hmaBytes         ; Amount the app expects to use
        mov     ah,XMSAllocHMA      ; Function code
        call    xmsHandler          ; call the guy

        or      ax,ax               ; AX=0 means error
        jz      errorReturn

        mov     ax,XMSErrOK         ; No error
        ret

errorReturn:
        mov     al,bl               ; Move error code to AL
        xor     ah,ah               ; Zero extend to 16 bits
        mov     errno,ax            ; Copy to errno
        ret

xms_allocHMA    endp                ; end of procedure


;**************************************************************
;***                                                        ***
;***    int xms_freeHMA()                                   ***
;***                                                        ***
;***    Frees the High Memory Area.                         ***
;***                                                        ***
;**************************************************************

        .model  large,C   

        extrn   errno:WORD  

;
;   Define entry point
;
        public  xms_freeHMA

        .code

xms_freeHMA     proc

        mov     ah,XMSFreeHMA       ; Function code
        call    xmsHandler          ; call the guy

        or      ax,ax               ; AX=0 means error
        jz      errorReturn

        mov     ax,XMSErrOK         ; No error
        ret

xms_freeHMA     endp                ; end of procedure


;**************************************************************
;***                                                        ***
;***    int xms_globEnabA20()                               ***
;***                                                        ***
;***    Enables the A20 address line allowing 21 bit        ***
;***    addressing and access to the HMA                    ***
;***                                                        ***
;**************************************************************

        .model  large,C   

        extrn   errno:WORD  

;
;   Define entry point
;
        public  xms_globEnabA20

        .code

xms_globEnabA20 proc

        mov     ah,XMSGlobEnabA20   ; Function code
        call    xmsHandler          ; call the guy

        or      ax,ax               ; AX=0 means error
        jz      errorReturn

        mov     ax,XMSErrOK         ; No error
        ret

xms_globEnabA20 endp                ; end of procedure



;**************************************************************
;***                                                        ***
;***    int xms_globDisabA20()                              ***
;***                                                        ***
;***    Disables the A20 address line.                      ***
;***                                                        ***
;**************************************************************

        .model  large,C   

        extrn   errno:WORD  

;
;   Define entry point
;
        public  xms_globDisabA20

        .code

xms_globDisabA20    proc

        mov     ah,XMSGlobDisabA20  ; Function code
        call    xmsHandler          ; call the guy

        or      ax,ax               ; AX=0 means error
        jz      errorReturn

        mov     ax,XMSErrOK         ; No error
        ret

xms_globDisabA20    endp            ; end of procedure



;**************************************************************
;***                                                        ***
;***    int xms_getA20State(WORD *a20State)                 ***
;***                                                        ***
;***    Returns the enable status of the A20 line.          ***
;***    A20State is TRUE (1) on return if A20 is enabled,   ***
;***    otherwise it is FALSE (0).                          ***
;***                                                        ***
;**************************************************************

        .model  large,C   


        extrn   errno:WORD  

;
;   Define entry point
;
        public  xms_getA20State

        .code

xms_getA20State proc    a20State:Far Ptr Word

        mov     ah,XMSGetA20State   ; Function code
        call    xmsHandler          ; call the guy

        or      ax,ax               ; AX=0 may mean error
        jnz     goodReturn          ; AX<>0 means A20 enabled
        or      bl,bl               ; BL<>0 means error
        jnz     errorReturn

goodReturn:
        les     bx,a20State         ; Address to return result
        mov     es:[bx],ax          ; Flag gives A20 state
        mov     ax,XMSErrOK         ; No error
        ret

xms_getA20State endp                ; end of procedure

        End
