.386p
	page 58,132
;=============================================================================
	title   H I G H D E L L - HIGHSCAN for DELL systems
;=============================================================================
;==
;== (C) Copyright MICROSOFT Corp. 1993
;==
;==     Title:  EMM386.EXE - MICROSOFT Expanded Memory Manager 386 Driver
;==
;==     Module: HighDell - searches for EMS and UMB windows in DELL system ROM
;==
;==     Version: 1.00
;==
;==     Date:   6-May-1993
;==
;==     Based on information and code from DELL Computer Corp.
;==
;=============================================================================
;==
;==     Change Log:
;==
;==     DATE     REVISION       Description
;==     -------- --------       --------------------------------------------
;==     05/06/93 0.00           Original
;==
;==
;=============================================================================

;=============================================================================
;==     E X T E R N A L  D E C L A R A T I O N S
;=============================================================================
LAST    segment

	extrn   HighSet:word

LAST    ends

;=============================================================================
;==     L O C A L   C O N S T A N T S
;=============================================================================

	include vdmseg.inc
	include emm386.inc
	include emmdata.inc

XB_SIG_LEN      equ     10      ; XBIOS Signature Length
XB_NULL         equ     0       ; XBIOS NULL (End-Of-List)
XB_CHAIN        equ     -1      ; XBIOS CHAIN Entry

XB_FUNCTION equ 00020h          ; Dell XBIOS Function number
XB_SUBFUNC  equ 00000h          ; Dell XBIOS Subfunction number

;=============================================================================
;==     C O D E  S E G M E N T
;=============================================================================
LAST    segment
	assume  cs:LAST,ds:_DATA,gs:R_CODE

;=============================================================================
;==     L O C A L   D A T A
;=============================================================================


;--------------- Dell XBIOS variables -------------

XBIOS_PTR   dd  ?               ; Pointer to XBIOS routine

;***************************************************************************
;
; DELL_HighScan - Call the DELL XBIOS interface to find mappable region
;                 in DELL system ROM
;
; On entry:
;
; On exit:      
;    CF clear => We found a DELL machine, and have decided whether or
;                not there is ROM space available.  If space was found,
;                HighSet is updated, and no further HighScan tests need
;                to be performed.
;
;    CF set   => This is not a DELL machine.  Continue with remaining
;                HighScan tests.

	public  DELL_HighScan

DELL_HighScan PROC  near

	push    ax              ; Save registers
	push    bx              ; ...
	push    dx              ; ...
	push    di              ; ...
	push    es              ; ...

; Address the system BIOS

	mov     ax,0f000h       ; Address the System BIOS
	mov     es,ax           ; ... via ES
	assume  es:nothing      ; Tell the assembler about it

; Address the Dell XBIOS header

	les     di,es:[0ed00h]  ; Address the Dell XBIOS header
	assume  es:nothing      ; Tell the assembler about it

	mov     ax,es           ; Get XBIOS segment
	cmp     ax,0f000h       ; Is it the system BIOS?
	jne     EXIT_NO_XBIOS   ; Jump if not (sanity check)

; Check for Dell XBIOS signature
; Signature is 'DELLXBIOS'

	cmp     word ptr es:[di]+0,'ED' ; Signature check
	jne     EXIT_NO_XBIOS           ; Jump if signature doesn't match

	cmp     word ptr es:[di]+2,'LL' ; Signature check
	jne     EXIT_NO_XBIOS           ; Jump if signature doesn't match

	cmp     word ptr es:[di]+4,'BX' ; Signature check
	jne     EXIT_NO_XBIOS           ; Jump if signature doesn't match

	cmp     word ptr es:[di]+6,'OI' ; Signature check
	jne     EXIT_NO_XBIOS           ; Jump if signature doesn't match

	cmp     byte ptr es:[di]+8,'S'  ; Signature check
	jne     EXIT_NO_XBIOS           ; Jump if signature doesn't match

	add     di,XB_SIG_LEN+2 ; Skip over signature and version number

; This looks like a DELL XBIOS system.  We are now committed to either using
; the DELL XBIOS call to identify the HIGHSCAN area, or not claiming the
; area at all.  DELL requested that EMM386 not claim the F000-F7FF region
; on its machines which do not implement the XBIOS space function.  Prior
; versions of the ROM had widely scattered code and data and there were
; no reliable methods of claiming the ROM space.

; Scan next entry in List for 'our' entry

NEXT_XB_ENTRY:
	mov     ax,es:[di]      ; Get ID word
	add     di,2            ; Skip to next entry
	cmp     ax,XB_FUNCTION  ; Is this the correct XBIOS entry?
	je      ENTRY_FOUND     ; Jump if so

; This entry is not the one we're looking for
; If it is the last entry, we're all done
; If it is a chain entry, skip over the gap in the chain
; If it is a standard entry, skip over it and try the next entry

	cmp     ax,XB_NULL      ; End of the XBIOS chain?
	je      EXIT_NO_SPACE   ; Jump if so (no XBIOS entry found)

	cmp     ax,XB_CHAIN     ; Chain entry?
	jne     NOT_CHAIN       ; Jump if not

	les     di,es:[di+2]    ; Follow gap in the chain
	assume  es:nothing      ; Tell the assembler

	jmp     NEXT_XB_ENTRY   ; Process next XBIOS entry

NOT_CHAIN:
	mov     ax,es:[di]      ; Get Attribute word
	add     di,6            ; Skip over attr and ptr entries
	test    al,110000b      ; Are there any optional bytes following?
	jz      NEXT_XB_ENTRY   ; Jump if not

; This is an extended length entry
; Determine length of this entry, and skip over it to the next entry

	mov     bx,ax           ; Get attribute word
	and     bx,10000b       ; Isolate optional keystroke trigger
	shr     bx,1            ; Move to second bit position
	shr     bx,1            ; ...
	shr     bx,1            ; ...
	add     di,bx           ; Skip over keystroke trigger (if present)
	test    al,100000b      ; Is there an optional appendix?
	jz      NEXT_XB_ENTRY   ; Jump if not

	mov     ax,[di]         ; Get appendix length
	add     di,2            ; Skip over length indicator
	add     di,ax           ; Skip over variable length appendix
	jmp     NEXT_XB_ENTRY   ; Process next XBIOS entry

; We have found the 'BIOS start' entry
; Caclulate pointer (it might be linear of in seg:off form)

ENTRY_FOUND:
	mov     ax,es:[di]      ; Get attributes
	add     di,2            ; Skip over attribute entry
	and     ax,1000b        ; Isolate linear format flag
	jz      LINEAR_PTR      ; Jump if ptr is not in linear format

	les     di,es:[di]      ; Load Seg:Off from XBIOS table
	assume  es:nothing      ; Tell the assembler about it

	jmp     ADDRESS_FOUND   ; Join common code

LINEAR_PTR:
	mov     ax,es:[di+2]    ; Get upper 16 bits of linear address
	mov     di,es:[di]      ; Get lower 16 bits of linear adderss

	mov     cl,12           ; Convert upper 16 bits to segment
	shl     ax,cl           ; ...
	mov     es,ax           ; Get XBIOS entry point segment
	assume  es:nothing      ; Tell the assembler about it

ADDRESS_FOUND:
	mov     word ptr XBIOS_PTR[0],di ; Save XBIOS Offset
	mov     word ptr XBIOS_PTR[2],es ; ...        Segment

	mov     ax,XB_SUBFUNC           ; Sub function number (0)
	call    XBIOS_PTR               ; Call the XBIOS routine
					; Returns AX = BIOS Start (with SETUP)
					;         BX = BIOS Start (w/o SETUP)

	; The return values are the ROM's starting paragraph address.  The
	; value in AX indicates where the ROM SETUP code starts.  EMM386
	; wants all the UMB space possible, so we use BX which maps over
	; the setup code.

	cmp     bx, 0F100h              ; Must be at least 4k available to
	jb      short EXIT_NO_SPACE     ;   be useful

	mov     bl, 0                   ; Round down to last complete 4k page
	dec     bx

	movzx   di, byte ptr cs:[HighSet]
	add     byte ptr cs:[HighSet], 4
	mov     word ptr cs:[HighSet][di], 0f000h       ; from F000h
	mov     word ptr cs:[HighSet][di+2], bx         ;   to F?FFh

EXIT_NO_SPACE:
	clc                             ; Indicate ROM area taken, or should
					;   not be taken.

	jmp     short EXIT              ; Join common exit code

EXIT_NO_XBIOS:
	stc                             ; Indicate not a Dell machine.
EXIT:
	pop     es              ; Restore registers
	pop     di              ; ...
	pop     dx              ; ...
	pop     bx              ; ...
	pop     ax              ; ...
	assume  es:nothing      ; Tell the assembler about it

	ret                     ; Return to caller

DELL_HighScan   endp            ; End DELL_XBIOS procedure


LAST    ENDS
	END
