	PAGE	60,132 ;
	TITLE	DEBEMS.ASM - EMS DEBUGGER COMMANDS
;/*
; *                      Microsoft Confidential
; *                      Copyright (C) Microsoft Corporation 1991
; *                      All Rights Reserved.
; */
;======================= START OF SPECIFICATIONS =========================
;
; MODULE NAME: DEBEMS.ASM
;
; DESCRIPTIVE NAME: DEBUGGING TOOL
;
; FUNCTION: PROVIDES USERS WITH ACCESS TO RUDIMENTARY EMS FACILITIES.
;
; ENTRY POINT: ANY CALLED ROUTINE
;
; INPUT: NA
;
; EXIT NORMAL: NA
;
; EXIT ERROR: NA
;
; INTERNAL REFERENCES:
;
; EXTERNAL REFERENCES:
;
;	ROUTINE: DEBCOM2 - CONTAINS ROUTINES CALLED BY DEBUG
;		 DEBCOM3 - CONTAINS ROUTINES CALLED BY DEBUG
;		 DEBASM  - CONTAINS ROUTINES CALLED BY DEBUG
;		 DEBUASM - CONTAINS ROUTINES CALLED BY DEBUG
;		 DEBMES  - CONTAINS ROUTINES CALLED BY DEBUG
;
; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS.
;	 LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+
;	      DEBCONST+DEBDATA+DEBMES
;
; REVISION HISTORY:
;
;	AN000	VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING:
;
;				- IMPLEMENT EMS FUNCTIONS	DSM:6/24/87
;
; COPYRIGHT: "MS DOS DEBUG UTILITY"
;	     "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft"
;	     "LICENSED MATERIAL - PROPERTY OF Microsoft  "
;
;======================= END OF SPECIFICATIONS ===========================
;
;   Change Log:
;
;     Date    Who   #			Description
;   --------  ---  ---	------------------------------------------------------
;   03/21/90  DIC  C04	Fixed Microsoft Bug #744 - A problem involving a
;                   			limitation on the total number of requested EMS memory
;                   			pages to 255.  This limit is now a 4-digit hexadecimal
;                   			number.
;   04/05/90  DIC  C05 MSFT #990 - "XS" command in debug always displays the
;                      default total handle of "FF" instead of the actual
;                      number.  This fix uses  func-54h, sub-func: 02h via
;                      EMS V4.0.
;   04/30/90  DIC  C06 MSFT # 994 - Debug does not use the "approved" means
;                      of checking EMS status.  This version uses a more
;                      traditional method of: (1) Attempting an OPEN on the
;                      guaranteed resource name of: EMMXXXX0 and (2) using
;                      IOCTL sub-functions (0) and (7) to determine if the
;                      name EMMXXXX0 actually represents a file or not.
;
;==============================================================================
INCLUDE DOSSYM.INC
include version.inc		; cas -- missing equates
include debug.inc


CODE	SEGMENT PUBLIC BYTE
CODE	ENDS

CONST	SEGMENT PUBLIC BYTE
CONST	ENDS

CSTACK	SEGMENT STACK
CSTACK	ENDS

DATA	SEGMENT PUBLIC BYTE

	extrn xm_page:word		   ;an000;page count to allocate  ;C04
		      ; allow max of 64K pages to allocate.		  ;C04
		      ; "xm_page" was an 8-bit quantity.		  ;C04

	extrn xm_log:byte			;an000;log. page to map
	extrn xm_phy:byte			;an000;phy. page to map
	extrn xm_handle:word			;an000;handle to map
	extrn xm_handle_ret:word		;an000;handle created

	extrn xm_page_cnt:word			;an000;page count
	extrn xm_handle_pages_buf:byte		;an000;holds handles and pages
	extrn xm_frame:word			;an000;EMS frame value
	extrn xm_deall_han:word 		;an000;handle to deallocate
	extrn xm_alloc_pg:word			;an000;pages allocated
	extrn xm_total_pg:word			;an000;total pages possible
	extrn xm_han_alloc:word 		;an000;handles allocated
	extrn xm_han_total:word 		;an000;total handles possible

	extrn	  xm_han_ret_ptr:word		;an000;prints handle created
	extrn	  xm_mapped_ptr:word		;an000;prints log/phy pages
	extrn	  xm_page_seg_ptr:word		;an000;Frame seg status
	extrn	  xm_deall_ptr:word		;an000;Handle deallocation
	extrn	  xm_unall_ptr:word		;an000;prints page status
	extrn	  xm_han_alloc_ptr:word 	;an000;print handle status

	extrn	  xm_err80_ptr:word		;an000;ems error message
	extrn	  xm_err83_ptr:word		;an000;ems error message
	extrn	  xm_err84_ptr:word		;an000;ems error message
	extrn	  xm_err85_ptr:word		;an000;ems error message
	extrn	  xm_err86_ptr:word		;an000;ems error message
	extrn	  xm_err87_ptr:word		;an000;ems error message
	extrn	  xm_err88_ptr:word		;an000;ems error message
	extrn	  xm_err89_ptr:word		;an000;ems error message
	extrn	  xm_err8a_ptr:word		;an000;ems error message
	extrn	  xm_err8b_ptr:word		;an000;ems error message
	extrn	  xm_err8d_ptr:word		;an000;ems error message
	extrn	  xm_err8e_ptr:word		;an000;ems error message
	extrn	  xm_errff_ptr:word		;an000;ems error message
	extrn	  xm_err_gen_ptr:word		;an000;ems error message
	extrn	  xm_parse_err_ptr:word 	;an000;input error message
	extrn	  xm_status_ptr:word		;an000;prints status of EMS

DATA	ENDS

DG	GROUP	CODE,CONST,CSTACK,DATA

CODE	SEGMENT PUBLIC BYTE
ASSUME	CS:DG,DS:DG,ES:DG,SS:DG

	public	  debems			;an000;entry point
	extrn	  std_printf:near		;an000;message retriever
	extrn	  gethx:near			;an000;ASCII to bin conversion
	extrn	  inbuf:near			;an000;input command line
	extrn	  scanb:near			;an000;scan off blanks
	extrn	  scanp:near			;an000;scan for parm
	extrn	  perr:near			;an000;print ^ error
	extrn	  geteol:near
	extrn	  crlf:near			;an000;prints a cr,lf

	IF	SYSVER
	ENDIF

DEBEMS: 					;an000;entry to module

	call SCANP				;an000;scan for M or S parm
;	$if  z					;an000;no parms found
	JNZ $$IF1
	     call XM_PARSE_ERROR		;an000;tell user of error
;	$else					;an000;
	JMP SHORT $$EN1
$$IF1:
	     mov  al,[si]			;an000;grab parm
	     cmp  al,"M"			;an000;is it MAP?
;	     $if  e				;an000;yes
	     JNE $$IF3
		  inc  si			;an000;point to next byte
		  call XM_EMS_MAP		;an000;
;	     $else				;an000;
	     JMP SHORT $$EN3
$$IF3:
		  cmp  al,"S"			;an000;is it a status check?
;		  $if  e			;an000;yes
		  JNE $$IF5
		       inc  si			;an000;point to next byte
		       call XM_EMS_STATUS	;an000;
;		  $else 			;an000;
		  JMP SHORT $$EN5
$$IF5:
		       cmp  al,"D"		;an000;Deallocate pages?
;		       $if  e			;an000;yes
		       JNE $$IF7
			    inc   si		;an000;point to next byte
			    call  XM_EMS_DEALL	;an000;
;		       $else			;an000;
		       JMP SHORT $$EN7
$$IF7:
			    cmp  al,"A" 	;an000;Allocate pages?
;			    $if  e		;an000;yes
			    JNE $$IF9
				 inc  si	;an000;point to next byte
				 call XM_EMS_ALLOC    ;an000;
;			    $else		;an000;
			    JMP SHORT $$EN9
$$IF9:
				call GETEOL	;an000;check out parm
;			    $endif		;an000;
$$EN9:
;		       $endif			;an000;
$$EN7:
;		  $endif			;an000;
$$EN5:
;	    $endif				;an000;
$$EN3:
;	$endif					;an000;
$$EN1:

	ret					;an000;return to caller



;=========================================================================
; XM_EMS_ALLOC	  :    This function will provide the user the
;		       capability to set and change EMS logical and
;		       physical pages within page frame 0.
;
;	Inputs:   none
;
;	Outputs:  EMS page frames set or altered
;
;	Date:	  6/24/87
;=========================================================================

XM_EMS_ALLOC	proc	near			;an000;XM functions

	call XM_GET_MAN_STATUS			;an000;see if EMS active
;	$if  nc 				;an000;EMS active
	JC $$IF16
	     call XM_PAGE_PROMPT		;an000;get pages to allocate
	     call XM_GET_HAN_ALLOC		;an000;allocate pages
	     mov  dg:XM_HANDLE_RET,dx		;an000;save handle returned
;	     $if  z				;an000;good return
	     JNZ $$IF17
		  pushf 			;an000;save our flags
		  call XM_DISP1 		;an000;tell user results
		  popf				;an000;restore our flags
;	     $else				;an000;
	     JMP SHORT $$EN17
$$IF17:
		  call XM_ERROR 		;an000;print error message
;	     $endif				;an000;
$$EN17:
;	$else					;an000;EMS not active
	JMP SHORT $$EN16
$$IF16:
	     call XM_ERROR			;an000;say why not active
;	$endif					;an000;
$$EN16:

	ret					;an000;return to caller

XM_EMS_ALLOC	  endp				;an000;


;=========================================================================
; XM_EMS_MAP	  :    This function will provide the user the
;		       capability to set and change EMS logical and
;		       physical pages within page frame 0.
;
;	Inputs:   none
;
;	Outputs:  EMS page frames set or altered
;
;	Date:	  6/24/87
;=========================================================================

XM_EMS_MAP	proc	near			;an000;XM functions

	call XM_GET_MAN_STATUS			;an000;see if EMS active
;	$if  nc 				;an000;EMS active
	JC $$IF22
	     call XM_LOG_PROMPT 		;an000;get logical page
	     call XM_PHY_PROMPT 		;an000;get physical page
	     call XM_HAN_PROMPT 		;an000;get handle
	     call XM_MAP_MEMORY 		;an000;map the page
;	     $if  z				;an000;good return
	     JNZ $$IF23
		  pushf 			;an000;save our flags
		  call XM_DISP2 		;an000;tell user results
		  popf				;an000;restore our flags
;	     $else				;an000;
	     JMP SHORT $$EN23
$$IF23:
		   call XM_ERROR		;an000;tell error
;	     $endif				;an000;
$$EN23:
;	$else					;an000;EMS not active
	JMP SHORT $$EN22
$$IF22:
	     call XM_ERROR			;an000;say why not active
;	$endif					;an000;
$$EN22:

	ret					;an000;return to caller

XM_EMS_MAP	  endp				;an000;

;=========================================================================
; XM_GET_MAN_STATUS :  This routine will determine if EMS is active for
;		       this session.
;
;	Called Procs:  none
;
;	Inputs:        none
;
;	Outputs:       Z  - no error
;		       NZ - error
;		       AH - error message number
;
;	Date:	       6/24/87
; C06 - DIC    4/30/90 This routine has been updated in order to employ
;                      a slightly more traditional method to determine the
;                      existence or absence of EMS.
;=========================================================================

std_emm_name   db      "EMMXXXX0",0     ;  C06 - Standard device name for the
                                        ;  C06 - Expanded Memory Manager.

XM_GET_MAN_STATUS proc near			;an000;see if EMS active

;   C06   	push	ds				;an000;save ds - we stomp it
;   C06   	mov	ax,00h				;an000;set ax to 0
;   C06   	mov	ds,ax				;an000;set ds to 0
;   C06   	cmp	ds:word ptr[067h*4+0],0 	;an000;see if int 67h is there
;   C06   	pop	ds				;an000;restore ds
;   C06   ;	$if	e				;an000;EMS not installed
;   C06   	JNE $$IF28
;   C06   		stc				;an000;flag no ems
;   C06   		mov	ah,XM_NOT_INST		;an000;signal EMS not installed
;   C06   ;	$else					;an000;
;   C06   	JMP SHORT $$EN28
;   C06   $$IF28:
;   C06   		call	XM_INSTALL_CHECK	;an000;see if EMS installed
;   C06   ;		$if	z			;AN000;IS EMS INSTALLED
;   C06   		JNZ $$IF30
;   C06   			clc			;AN000;EMS INSTALLED - FLAG IT
;   C06   ;		$else				;an000;
;   C06   		JMP SHORT $$EN30
;   C06   $$IF30:
;   C06   			stc			;AN000;FLAG EMS NOT INSTALLED
;   C06   			mov  ah,XM_NOT_INST	;an000;signal EMS not installed
;   C06   ;		$endif				;an000;
;   C06   $$EN30:
;   C06   ;	$endif					;an000;
;   C06   $$EN28:
;   C06   
;   C06   	RET					;AN000;RETURN TO CALLER

           push    ds                        ;  C06
           push    cs                        ;  C06
           pop     ds                        ;  C06
           mov     dx,offset std_emm_name    ;  C06 - Attempt to OPEN the 
           mov     ax,3d00h                  ;  C06 - Standard (guaranteed) EMM driver
           int     21h                       ;  C06 - name.  It might actually be a file.
           jc      emm_not_present           ;  C06 - If EMM driver is not present.
           
           ;  Otherwise, the name: EMMXXXX0 does exist, but it might turn out   C06
           ;  to be a file instead of the name of a device driver.              C06

           mov     bx,ax                     ;  C06 - Handle from the OPEN operation.
           mov     ax,4400h                  ;  C06 - Get device information
           int     21h                       ;  C06 - using traditional MSDOS method.
           jc      emm_not_present           ;  C06 - If error, then assume EMM does not exist.
           and     dx,80h                    ;  C06 - Is it a character device ?
           jz      emm_not_present           ;  C06 - NO--> Assume EMM is not present
           mov     ax,4407h                  ;  C06 - Request OUTPUT status
           int     21h                       ;  C06 - via traditional MSDOS method.
           jc      emm_not_present           ;  C06 - interpret as EMM-not-present.
           or      al,al                     ;  C06 - Device status ?
           jz      emm_not_present           ;  C06 - if EMM is not available
           
           ; since these tests have been passed, we can assume            C06
           ; that the EMMXXXX0 drive does indeed exist.                   C06

           mov     ah,03eh                   ;  C06 - Close out the EMM device handle
           int     21h                       ;  C06
           jc      emm_not_present           ;  C06 - Failure here is interpreted as:
                                             ;  C06 - EMM not available.
           call    XM_INSTALL_CHECK          ;  C06 - Do std EMS installation check.
           jnz     emm_not_present           ;  C06 - If EMS does not exist.
           clc                               ;  C06 - Successful return
           pop     ds                        ;  C06 - He gets restored.
           ret                               ;  C06

emm_not_present:

           stc                               ;  C06
           mov     ah,XM_NOT_INST            ;  C06 - error number
           pop     ds                        ;  C06
           ret                               ;  C06

XM_GET_MAN_STATUS endp				;an000;

;=========================================================================
; XM_PAGE_PROMPT :     This routine prompts the user for the number of
;		       pages to be allocated, if he desires a new handle.
;		       This routine will determine whether or not the other
;		       prompt messages will be displayed.
;
;	Called Procs:  STD_PRINTF
;		       XM_PARSE
;
;	Inputs:        none
;
;	Outputs:       XM_PAGE_FLAG
;		       XM_PAGE_BUF
;		       XM_PAGE
;
;	Date:	       6/24/87
;=========================================================================

XM_PAGE_PROMPT	  proc near			;an000;prompt user for number
						;      of pages to allocate
	call SCANB				;an000;see if parm entered
;	$if  nz 				;an000;if parm found
	JZ $$IF34
;C04	     mov  cx,02 			;an000;bytes to parse
	     mov  cx,04 			;an000;bytes to parse	   ;C04
						;   (maximum entry of 64K) ;C04
	     call GETHX 			;an000;get hex value
;	     $if  c				;an000;no an error occurred
	     JNC $$IF35
		  call PERR			;an000;display ^ error
;	     $else				;an000;
	     JMP SHORT $$EN35
$$IF35:
;C04		  mov  dg:XM_PAGE,dl		;an000;save page count
		  mov  word ptr dg:XM_PAGE,dx	;save page cnt (max=64K)  ;C04
;	     $endif				;an000;
$$EN35:
;	$else					;an000;
	JMP SHORT $$EN34
$$IF34:
	     call PERR				;an000;display ^ error
;	$endif					;an000;
$$EN34:

	ret					;an000;return to caller

XM_PAGE_PROMPT	  endp				;an000;


;=========================================================================
; XM_LOG_PROMPT :      This routine prompts the user for the number of the
;		       logical page that is to be mapped in EMS.  This
;		       routine will not be performed if a page count
;		       was specified.
;
;	Called Procs:  STD_PRINTF
;		       XM_PARSE
;
;	Inputs:        none
;
;	Outputs:       XM_LOG_BUF
;		       XM_LOG
;
;	Date:	       6/24/87
;=========================================================================


XM_LOG_PROMPT	  proc near			;an000;prompt user for the
						;      logical page to be
						;      mapped
	call SCANB				;an000;see if parm entered
;	$if  nz 				;an000;parm entered
	JZ $$IF40
	     mov  cx,02 			;an000;bytes to parse
	     call GETHX 			;an000;get hex value
;	     $if  c				;an000;no an error occurred
	     JNC $$IF41
		  call PERR			;an000;display ^ error
;	     $else				;an000;
	     JMP SHORT $$EN41
$$IF41:
		  mov  dg:XM_LOG,dl		;an000;save logical page
;	     $endif				;an000;
$$EN41:
;	$else					;an000;
	JMP SHORT $$EN40
$$IF40:
	     call PERR				;an000;display ^ error
;	$endif					;an000;
$$EN40:

	ret					;an000;return to caller

XM_LOG_PROMPT	  endp				;an000;


;=========================================================================
; XM_PHY_PROMPT :      This routine prompts the user for the number of the
;		       physical page that is to be mapped in EMS.  This
;		       routine will not be performed if a page count
;		       was specified.
;
;	Called Procs:  STD_PRINTF
;		       XM_PARSE
;
;	Inputs:        none
;
;	Outputs:       XM_PHY_BUF
;		       XM_PHY
;
;	Date:	       6/24/87
;=========================================================================


XM_PHY_PROMPT	  proc near			;an000;prompt user for the
						;      physical page to be
						;      mapped
	call SCANB				;an000;see if parm entered
;	$if  nz 				;an000;parm found
	JZ $$IF46
	     mov  cx,02 			;an000;bytes to parse
	     call GETHX 			;an000;get hex value
;	     $if  c				;an000;no an error occurred
	     JNC $$IF47
		  call PERR			;an000;display ^ error
;	     $else				;an000;
	     JMP SHORT $$EN47
$$IF47:
		  mov  dg:XM_PHY,dl		;an000;save logical page
;	     $endif				;an000;
$$EN47:
;	$else					;an000;
	JMP SHORT $$EN46
$$IF46:
	     call PERR				;an000;
;	$endif					;an000;
$$EN46:

	ret					;an000;return to caller

XM_PHY_PROMPT	  endp				;an000;


;=========================================================================
; XM_HAN_PROMPT :      This routine prompts the user for the number of the
;		       handle that the mapping is to occur on. This
;		       routine will not be performed if a page count
;		       was specified.
;
;	Called Procs:  STD_PRINTF
;		       XM_PARSE
;
;	Inputs:        none
;
;	Outputs:       XM_HAN_BUF
;		       XM_HAN
;
;	Date:	       6/24/87
;=========================================================================


XM_HAN_PROMPT	  proc near			;an000;prompt user for the
						;      handle to be mapped
	call SCANB				;an000;see if parm entered
;	$if  nz 				;an000;prompt found
	JZ $$IF52
	     mov  cx,04 			;an000;bytes to parse
	     call GETHX 			;an000;get hex value
;	     $if  c				;an000;no an error occurred
	     JNC $$IF53
		  call PERR			;an000;display ^ error
;	     $else				;an000;
	     JMP SHORT $$EN53
$$IF53:
		  mov  dg:XM_HANDLE,dx		;an000;save logical page
;	     $endif				;an000;
$$EN53:
;	$else					;an000;
	JMP SHORT $$EN52
$$IF52:
	     call PERR				;an000;display ^ error
;	$endif					;an000;
$$EN52:

	ret					;an000;return to caller

XM_HAN_PROMPT	  endp				;an000;



;=========================================================================
; XM_GET_HAN_ALLOC :   This routine will get a handle and allocate the
;		       requested number of pages to that handle.
;
;	Called Procs:  none
;
;	Inputs:        XM_PAGE - number of pages to allocate to handle
;
;	Outputs:       Z  - no error
;		       NZ - error
;		       DX - handle allocated
;
;	Date:	       6/24/87
;=========================================================================

XM_GET_HAN_ALLOC  proc near			;an000;create handle and alloc.
						;      requested pages.
	push bx 				;an000;save regs.
	mov  ah,EMS_HAN_ALLOC			;an000;function 43h
;C04	xor  bh,bh				;an000;clear byte
;C04	mov  bl,dg:XM_PAGE			;an000;number of pages to
	mov  bx,word ptr dg:XM_PAGE		;num of pages (64K limit) to;C04
						;      allocate
	int  67h				;an000;call EMS
	or   ah,ah				;an000;was there an error
	pop  bx 				;an000;restore regs.

	ret					;an000;return to caller

XM_GET_HAN_ALLOC  endp				;an000;

;=========================================================================
; XM_MAP_MEMORY :      This routine will map the requested logical page
;		       to the requested physical page in EMS.
;
;	Called Procs:  none
;
;	Inputs:        XM_PHY - physical page to map to
;		       XM_HAN - logical page to map
;
;	Outputs:       Z  - no error
;		       NZ - error
;		       page mapped
;
;	Date:	       6/24/87
;=========================================================================

XM_MAP_MEMORY	  proc near			;an000;map a logical page to
						;      a physical page in
						;      EMS
	push bx 				;an000;save regs.
	push dx 				;an000;
	mov  ah,EMS_MAP_MEMORY			;an000;function 44h
	mov  al,dg:XM_PHY			;an000;physical page to map
	xor  bh,bh				;an000;zero byte
	mov  bl,dg:XM_LOG			;an000;logical page to map
	mov  dx,dg:XM_HANDLE			;an000;handle to map page to
	int  67h				;an000;call EMS
	or   ah,ah				;an000;was there an error
	pop  dx 				;an000;restore regs.
	pop  bx 				;an000;

	ret					;an000;return to caller

XM_MAP_MEMORY	  endp				;an000;


;=========================================================================
; XM_DISP1 :	       This routine displays the current page frame and
;		       the handle created as a result of the allocate pages.
;
;	Called Procs:  STD_PRINTF
;
;	Inputs:        XM_FRAME_SEG	- page frame segment
;		       XM_HANDLE_RET	- created handle
;		       XM_PG_FRAME_PTR	- pointer to message
;		       XM_HAN_RET_PTR	- pointer to message
;
;	Outputs:       "Page Frame Segment : %1",0d,0a
;		       "Handle Created     : %1",0d,0a
;
;	Date:	       6/24/87
;=========================================================================

XM_DISP1	  proc near			;an000;display messages

	mov  dx,offset dg:XM_HAN_RET_PTR	;an000;"Handle Created    : "
	call STD_PRINTF 			;an000;call message ret.

	ret					;an000;return to caller

XM_DISP1	  endp				;an000;


;=========================================================================
; XM_DISP2 :	       This routine displays the logical page mapped and
;		       the physical page it was mapped to.
;
;	Called Procs:  STD_PRINTF
;
;	Inputs:        XM_MAPPED_PTR	- pointer to message
;		       XM_LOG		- logical page mapped
;		       XM_PHY		- physical page mapped
;
;	Outputs:       "Logical page %1 mapped to physical page %2",0d0a
;
;	Date:	       6/24/87
;=========================================================================

XM_DISP2	  proc near			;an000;display messages

	mov  dx,offset dg:XM_MAPPED_PTR 	;an000;"Logical page %1 mapped
						;	to physical page %2"
	call STD_PRINTF 			;an000;call message ret.

	ret					;an000;return to caller

XM_DISP2	  endp				;an000;

;=========================================================================
; XM_ERROR:	  This routine will determine what error we have by
;		  querying the result in the AH register.  It will then
;		  report the error to the user through STD_PRINTF
;
;	Called Procs:  STD_PRINTF
;
;	Inputs:        AH - error code
;
;	Outputs:       error message
;
;	Date:	       6/24/87
;=========================================================================

XM_ERROR	  proc near			;an000;error message printer

	mov	dx,offset dg:XM_ERR80_PTR	;an000;point to message
	cmp	ah,XM_ERR80			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR83_PTR	;an000;point to message
	cmp	ah,XM_ERR83			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR84_PTR	;an000;point to message
	cmp	ah,XM_ERR84			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR85_PTR	;an000;point to message
	cmp	ah,XM_ERR85			;an000;error message
	je	XM_ERROR_CONT			; print error


	mov	dx,offset dg:XM_ERR86_PTR	;an000;point to message
	cmp	ah,XM_ERR86			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR87_PTR	;an000;point to message
	cmp	ah,XM_ERR87			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR88_PTR	;an000;point to message
	cmp	ah,XM_ERR88			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR89_PTR	;an000;point to message
	cmp	ah,XM_ERR89			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR8A_PTR	;an000;point to message
	cmp	ah,XM_ERR8A			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR8B_PTR	;an000;point to message
	cmp	ah,XM_ERR8B			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR8D_PTR	;an000;point to message
	cmp	ah,XM_ERR8D			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR8E_PTR	;an000;point to message
	cmp	ah,XM_ERR8E			;an000;error message
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERRFF_PTR	;an000;point to message
	cmp	ah,XM_NOT_INST			;an000;EMS not installed
	je	XM_ERROR_CONT			; print error

	mov	dx,offset dg:XM_ERR_GEN_PTR	;an000;general error message

XM_ERROR_CONT:

	jmp STD_PRINTF 				;an000;call message ret.


XM_ERROR	  endp				;an000;

;=========================================================================
; XM_PARSE_ERROR :     This routine will display that an error has occurred
;		       on the input of the requested data.
;
;	Called Procs:  STD_PRINTF
;
;	Inputs:        XM_PARSE_ERR_PTR - error message
;
;	Outputs:       "Invalid value for parameter",0d,0a
;
;	Date:	       6/24/87
;=========================================================================

XM_PARSE_ERROR	  proc near			;an000;input error message

	mov  dx,offset dg:XM_PARSE_ERR_PTR	;an000;error message
	call STD_PRINTF 			;an000;call message ret.
	ret					;an000;return to caller

XM_PARSE_ERROR	  endp				;an000;



;=========================================================================
; XM_EMS_STATUS   :    This function will provide the user with
;		       a report the the current status of EMS.
;
;	Inputs:   none
;
;	Outputs:  EMS page frames set or altered
;
;	Date:	  6/24/87
;=========================================================================

XM_EMS_STATUS	proc	near			;an000;XM functions

	call XM_GET_MAN_STATUS			;an000;see if EMS active
;	$if  nc 				;an000;EMS active
	JC $$IF84
	     call XM_CURR_STATUS		;an000;current status of EMS
;	$else					;an000;EMS not active
	JMP SHORT $$EN84
$$IF84:
	     call XM_ERROR			;an000;say why not active
;	$endif					;an000;
$$EN84:

	ret					;an000;return to caller

XM_EMS_STATUS	  endp				;an000;


;=========================================================================
; XM_CURR_STATUS :	This routine will display the current status of
;			all active EMS handles.
;
;	Inputs	 :	none
;
;	Outputs  :	Current status of all active EMS handles
;			"Handle %1 has %2 pages allocated"
;
;			Physical page with it associated frame segment
;			"Physical page %1 = Frame segment %2"
;
;	Date:	       8/05/86
;=========================================================================

XM_CURR_STATUS		proc	near		;an000;current EMS status

	mov  ah,EMS_HANDLE_PAGES		;an000;get handle pages
	mov  di,offset dg:XM_HANDLE_PAGES_BUF	;an000;point to the buffer
	int  67h				;an000;

	or   ah,ah				;an000;see if an error occurred
;	$if  z					;an000;no error
	JNZ $$IF87
;	     $do				;an000;do while data in buffer
$$DO88:
		  cmp  bx,0			;an000;end of buffer?
;		  $leave  e			;an000;yes
		  JE $$EN88
		       mov  ax,word ptr es:[di] ;an000;page handle
		       mov  dg:XM_HANDLE_RET,ax ;an000;save in var
		       mov  ax,word ptr es:[di+02];an000;page count
		       mov  dg:XM_PAGE_CNT,ax	;an000;save in var
		       mov  dx,offset dg:XM_STATUS_PTR ;an000;point to message
		       call STD_PRINTF		;an000;print it
		       add  di,04h		;an000;next record
		       dec  bx			;an000;decrement counter
;	     $enddo				;an000;
	     JMP SHORT $$DO88
$$EN88:

	     call  CRLF 			;an000;place a blank line
						;      between reports

	     call  XM_FRAME_BUFFER		;an000;get frame buffer
						;ES:DI points to frame buffer
;	     $do				;an000;while cx not = 0
$$DO91:
		  cmp  cx,00			;an000;at end?
;		  $leave e			;an000;yes
		  JE $$EN91
		       call  XM_GET_FRAME_SEG	;an000;obtain page and seg
		       mov   dx,offset dg:XM_PAGE_SEG_PTR  ;an000;message
		       call  STD_PRINTF 	;an000;print it
		       dec   cx 		;an000;decrease counter
		       add   di,04		;an000;adjust pointer
;	     $enddo				;an000;
	     JMP SHORT $$DO91
$$EN91:

	     call  XM_UNALL_COUNT		;an000;display page status
	     call  XM_HANDLE_COUNT		;an000;display handle status

;	$else
	JMP SHORT $$EN87
$$IF87:
	     call  XM_ERROR			;an000;display the error
;	$endif					;an000;
$$EN87:
	ret					;an000;

XM_CURR_STATUS		endp			;an000;

;=========================================================================
; XM_UNALL_COUNT :	This routine generates a line of the status report
;			displaying the number of pages allocated out of
;			the total possible
;
;	Inputs	 :	none
;
;	Outputs  :	Current status of allocated pages
;			"%1 of a total %2 EMS pages have been allocated"
;
;	Date:	       8/05/86
;=========================================================================

XM_UNALL_COUNT		proc	near		;an000;

	mov	ah,EMS_UNALL_PG_CNT		;an000;see how many pages
						;      remaining
	int	67h				;an000;
	or	ah,ah				;an000;see if error

;	$if	z				;an000;no error
	JNZ $$IF96
		push	bx			;an000;save bx
		push	dx			;an000;save dx
		call	CRLF			;an000;
		pop	dx			;an000;restore dx
		pop	bx			;an000;restore bx
		mov	ax,dx			;an000;total page count
		sub	ax,bx			;an000;get pages allocated
		mov	dg:XM_ALLOC_PG,ax	;an000;save allocated pages
		mov	dg:XM_TOTAL_PG,dx	;an000;save total page count
		mov	dx,offset dg:XM_UNALL_PTR ;an000;"%1 of a total %2 EMS
						;      pages have been allocated",cr,lf
		call	STD_PRINTF		;an000;print it
;	$endif					;an000;
$$IF96:

	ret					;an000;

XM_UNALL_COUNT		endp			;an000;


;=========================================================================
; XM_HANDLE_COUNT:	This routine generates a line of the status report
;			displaying the number of handles allocated out of
;			the total possible.
;
;	Inputs	 :	none
;
;	Outputs  :	Current status of allocated pages
;			"%1 of a total %2 EMS handles have been allocated"
;
;	Date:	       8/05/86
;=========================================================================

XM_HANDLE_COUNT 	proc	near		;an000;

	mov	ah,EMS_HANDLE_CNT		;an000;see how many handles
                  						;      possible
 int 67h                ; C05 - Request total currently allocated.
 or  ah,ah              ; C05 - 
 jnz $$IF98             ; C05 - If error
 mov word ptr dg:XM_HAN_ALLOC,bx ; C05 - save total number of active handles.
 mov ax,EMS_TOT_HANDLES         ; C05 - Request total handles possible for
                                ; C05 - EMS 4.0
	int	67h				;an000;
	or	ah,ah				;an000;see if error

;	$if	z				;an000;no error
	JNZ $$IF98
;C05      		mov	ax,EMS_HANDLE_TOTAL	;an000;total possible handles
  mov ax,bx                     ;C05 - Total possible handles for EMS 4.0

		mov	dg:XM_HAN_TOTAL,ax	;an000;save total page count
;C05      		mov	dg:XM_HAN_ALLOC,bx	;an000;save allocated pages
  mov bx,dg:XM_HAN_ALLOC           ; C05 - This may not be needed.
		mov	dx,offset dg:XM_HAN_ALLOC_PTR
						;an000;"%1 of a total %2 EMS
						;      handles have been allocated",cr,lf
		call	STD_PRINTF		;an000;print it
;	$endif					;an000;
$$IF98:

	ret					;an000;

XM_HANDLE_COUNT 	endp			;an000;


;=========================================================================
; XM_FRAME_SEG	 :	This routine accesses the vector created by
;			function 58h, int 67h.	It obtains a physical
;			page of EMS and its segment from this vector
;
;	Inputs	 :	ES:DI - points to frame buffer
;
;	Outputs  :	XM_PHY - a physical page in EMS
;			XM_FRAME - segment corresponding to the physical page
;
;	Date:	       8/05/86
;=========================================================================


XM_GET_FRAME_SEG	proc	near		;an000;find the frame segment

	mov	al,byte ptr es:[di+2]		;an000;get physical page
	mov	dg:XM_PHY,al			;an000;place in print var
	mov	ax,word ptr es:[di]		;an000;get frame segment
	mov	dg:XM_FRAME,ax			;an000;place in print var

	ret					;an000;

XM_GET_FRAME_SEG	endp			;an000;

;=========================================================================
; XM_INSTALL_CHECK:	This routine performs function 51h, int 67h to
;			determine if EMS is indeed active.
;
;	Inputs	 :	XM_FRAME_BUFFER - used to receive physical page
;					  and segment data for EMS.
;
;	Outputs  :	XM_FRAME_BUFFER - buffer holds physical page
;					  and segment data for EMS.
;
;	Date:	       8/05/86
;=========================================================================

XM_INSTALL_CHECK	proc	near		;an000;see if EMS installed

	MOV	AH,EMS_GET_MAN_STAT		;AN000;GET EMS STATUS
	XOR	AL,AL				;an000;clear low byte
	INT	67h				;an000;
	OR	AH,AH				;an000;check for error
;	$IF	Z				;an000;no error
	JNZ $$IF100
		MOV	AH,EMS_VERSION		;an000;get version number
		INT	67h			;an000;
		CMP	AL,EMS_LIM_40		;an000;LIM 4.0 ?
;		$IF	AE			;an000;4.0 or greater
		JNAE $$IF101
			MOV	AH,00h		;an000;set up for flag pass
			OR	AH,AH		;an000;set flag to ZR
;		$ELSE				;an000;below 4.0
		JMP SHORT $$EN101
$$IF101:
			MOV	AH,01h		;an000;set up for flag pass
			OR	AH,AH		;an000;set flag to NZ
;		$ENDIF				;an000;
$$EN101:
;	$ENDIF					;an000;
$$IF100:

	ret					;an000;

XM_INSTALL_CHECK	endp			;an000;




;=========================================================================
; XM_EMS_DEALL	:	This routine deallocates handles from EMS.
;
;	Inputs	 :	DX - Handle supplied by XM_DEALL_PROMPT
;
;	Outputs  :	Good return - "Handle %1 deallocated"
;			Bad return  - message describing error
;
;	Date:	       8/05/86
;=========================================================================

XM_EMS_DEALL		proc	near		;an000;deallocate EMS pages

	call XM_GET_MAN_STATUS			;an000;see if EMS installed
;	$if  nc 				;an000;error?
	JC $$IF105
	     call XM_DEALL_PROMPT		;an000;prompt user for handle
	     mov  ah,EMS_PAGE_DEALL		;an000;function 45h, int 67h
	     int  67h				;an000;

	     or   ah,ah 			;an000;error?
;	     $if  nz				;an000;yes
	     JZ $$IF106
		  call XM_ERROR 		;an000;say why
;	     $else				;an000;
	     JMP SHORT $$EN106
$$IF106:
		  mov  dx,offset dg:XM_DEALL_PTR;an000;"Handle %1 deallocated"
		  call STD_PRINTF		;an000;print message
;	     $endif				;an000;
$$EN106:
;	$else					;an000;
	JMP SHORT $$EN105
$$IF105:
	     call XM_ERROR			;an000;print type of error
;	$endif					;an000;
$$EN105:

	ret					;an000;

XM_EMS_DEALL		endp			;an000;

;=========================================================================
; XM_DEALL_PROMPT :	This routine prompts the user for the handle to be
;			deallocated.  It converts the handle entered to
;			binary and passes it back to the caller in DX.
;
;	Inputs	 :	none
;
;	Outputs  :	DX - Handle to be deallocated.
;
;	Date:	       8/05/86
;=========================================================================

XM_DEALL_PROMPT 	proc	near		;an000;prompt user for handle
						;      to deallocate
	call SCANB				;an000;see if parm entered
;	$if  nz 				;an000;parm found
	JZ $$IF111
	     mov  cx,04 			;an000;bytes to parse
	     call GETHX 			;an000;get hex value
;	     $if  c				;an000;no an error occurred
	     JNC $$IF112
		  call PERR			;an000;display ^ error
;	     $else				;an000;
	     JMP SHORT $$EN112
$$IF112:
		  mov  dg:XM_DEALL_HAN,dx	;an000;save handle to deallocate
;	     $endif				;an000;
$$EN112:
;	$else					;an000;
	JMP SHORT $$EN111
$$IF111:
	     call PERR				;an000;display ^ error
;	$endif					;an000;
$$EN111:

	ret					;an000;return to caller

XM_DEALL_PROMPT 	endp			;an000;


;=========================================================================
; XM_FRAME_BUFFER	:	This routine obtains the frame buffer
;				of EMS pages.
;
;	Inputs	:	none
;
;	Outputs :	ES:DI - Pointer to frame array
;			CX    - Number of elements in array
;=========================================================================

XM_FRAME_BUFFER 	proc	near		;an000;

	mov	ax,EMS_PG_FRAME 		;an000;get frame buffer
	int	67h				;an000;

	ret					;an000;

XM_FRAME_BUFFER 	endp			;an000;


CODE	ENDS
	END	DEBEMS
