Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1572 lines
32 KiB

;/* himem2.asm
; *
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1988-1991
; * All Rights Reserved.
; *
; * Modification History
; *
; * Sudeepb 14-May-1991 Ported for NT XMS support
; *
; * williamh 25-Sept-1992 added UMB initialization
; */
page 95,160
title 'HIMEM2 - Initialization code'
funky segment word public 'funky'
extrn textseg:word ; in high segment
extrn KiddValley:word
extrn KiddValleyTop:word
extrn cHandles:word
extrn pack_and_truncate:near
extrn end_of_funky_seg:byte
extrn LEnblA20:word
extrn LDsblA20:word
funky ends
.xlist
include himem.inc ; get structures, equ's, etc.
; and open segment
include xmssvc.inc
.list
; public f000
public InitInterrupt
public MachineNum
;************************************************************************
;* *
;* Global Variables *
;* *
;************************************************************************
extrn pPPFIRET:word
extrn dd_int_loc:word
extrn Interrupt:near
extrn hiseg:word
extrn call_hi_in_di:near
extrn fCanChangeA20:byte
extrn fHMAMayExist:byte
ifndef NEC_98
extrn fVDISK:byte
extrn IsVDISKIn:near
endif ;NEC_98
extrn A20Handler:near
extrn EnableCount:word
extrn MemCorr:word
extrn MinHMASize:word
extrn pReqHdr:dword
extrn PrevInt2f:dword
extrn TopOfTextSeg:word
extrn AddMem:near
extrn InstallA20:near
extrn Int2fHandler:near
; extrn Is6300Plus:near
extrn IsA20On:near
extrn SignOnMsg:byte
extrn ROMDisabledMsg:byte
extrn UnsupportedROMMsg:byte
extrn ROMHookedMsg:byte
extrn BadDOSMsg:byte
extrn NowInMsg:byte
extrn On8086Msg:byte
extrn NoExtMemMsg:byte
extrn FlushMsg:byte
extrn StartMsg:byte
extrn HandlesMsg:byte
extrn HMAMINMsg:byte
extrn KMsg:byte
extrn NoHMAMsg:byte
extrn A20OnMsg:byte
extrn HMAOKMsg:byte
ifndef NEC_98
extrn VDISKInMsg:byte
extrn BadArgMsg:byte
endif ;NEC_98
extrn DevAttr:word
extrn Int15MemSize:word
extrn EndText:byte
extrn A20State:byte
extrn DOSTI:near
extrn DOCLI:near
ifdef NEC_98
extrn fAltA20Routine:byte
extrn LocalDisableA20:near
extrn LocalEnableA20:near
extrn cant_ena20_msg:byte
extrn cant_dia20_msg:byte
endif ;NEC_98
;************************************************************************
;* *
;* Code/Data below here will be discarded after driver initialization *
;* *
;************************************************************************
; Discardable Initialization Data
public fShadowOff, f1stWasWarning
fShadowOff db 0 ; NZ if shadow RAM should be disabled,
; 0/1 set by command line switch, 0FFh
; set if little extended and hope to disable
f1stWasWarning db 0 ; NZ if 1st attempt to diddle A20 generated
; a warning (and not an error)
public fA20Control
fA20Control db 0ffh ; NZ if himem should take control of A20, even
; it was already on when himem loaded.
ifndef NEC_98
public fCPUClock
fCPUClock db 0 ; NZ if himem should try to preserve CPU clock
; speed when gating A20
endif ;NEC_98
public StringParm, MachineNum, MachineName
StringParm db 13 DUP (' ')
MachineNum dw -1
; Note: the following table MUST be in the same order as the entries in the
; A20_Scan_Table! If you add entries here, also add one there!
MachineName label byte
db 'ptlcascade',0 ; Phoenix Cascade BIOS
db 'att6300plus',0 ; AT&T 6300 Plus
db 'ps2',0 ; IBM PS/2
db 'hpvectra',0 ; HP 'Classic' Vectra (A & A+)
db 'acer1100',0 ; Acer 1100
db 'toshiba',0 ; Toshiba 1600 & 1200XE
db 'wyse',0 ; Wyse 12.5 MHz 286 machine
ifndef NEC_98
db 'tulip',0 ; Tulip machines
db 'zenith',0 ; Zenith ZBIOS
db 'at1',0 ; IBM AT/delay 0
db 'at2',0 ; IBM AT/delay 1
db 'at3',0 ; IBM AT/delay 2
db 'philips',0 ; Philips machines
db 'css',0 ; CSS Lab machines
db 'fasthp',0 ; Single byte method for HP Vectras
db 'ibm7552',0 ; IBM 7552 Industrial Computer
db 'bullmicral',0 ; Bull Micral 60 M004
endif ;NEC_98
db 'at',0 ; IBM AT
db 0FFh ; end of table
;NOTE: there is code in GetParms which depends on AltNameTbl coming
; after MachineName table.
ifndef NEC_98
public AltName1, AltName2, AltName3, AltName4, AltName5
public AltName6, AltName7, AltName8, AltName9, AltName10
public AltName11, AltName12, AltName13, AltName14, AltName15
public AltName16 ;M004
else ;NEC_98
public AltName1, AltName2, AltName3, AltName4, AltName5
public AltName6, AltName7, AltName8
endif ;NEC_98
AltNameTbl label byte
AltName3 db '3',0 ; Phoenix Cascade BIOS
AltName5 db '5',0 ; AT&T 6300 Plus
AltName2 db '2',0 ; IBM PS/2
AltName4 db '4',0 ; HP 'Classic' Vectra (A & A+)
AltName6 db '6',0 ; Acer 1100
AltName7 db '7',0 ; Toshiba 1600 & 1200XE
AltName8 db '8',0 ; Wyse 12.5 Mhz 286 machine
ifndef NEC_98
AltName9 db '9',0 ; Tulip machine
AltName10 db '10',0 ; Zenith ZBIOS
AltName11 db '11',0 ; IBM AT/delay 0
AltName12 db '12',0 ; IBM AT/delay 1
AltName13 db '13',0 ; IBM AT/delay 2
db '13',0 ; Philips machines (same as AT3)
db '12',0 ; CSS machines
AltName14 db '14',0 ; Single byte HP Vectra m/cs
AltName15 db '15',0 ; IBM 7552 Industrial Computer
AltName16 db '16',0 ; Bull Micral 60 M004
endif ;NEC_98
AltName1 db '1',0 ; IBM AT
db 0FFh ; end of table
ifdef debug_tsr ;-----------------------------------------------
;*----------------------------------------------------------------------*
;* *
;* ExeStart - *
;* *
;* Entry point when himem is invoked as an .EXE. *
;* *
;*----------------------------------------------------------------------*
lpCmdLine dd 81h ; far ptr to command tail
public ExeStart
ExeStart:
mov word ptr cs:[lpCmdLine+2],es ; save PSP segment in pointer
mov ax,cs ; Setup segment regs to all be the same
mov ds,ax
mov es,ax
call InitDriver ; Initialize...
mov ax,TopOfTextSeg ; TopOfTextSeg == 0 is error installing
or ax,ax
jnz @f
mov ax,4C03h ; error, so just terminate
int 21h
@@:
mov di,offset pack_and_truncate
jmp call_hi_in_di ; terminate and stay resident
endif ;------------------------------------------------
;*----------------------------------------------------------------------*
;* *
;* InitInterrupt - *
;* *
;* Called by MS-DOS immediately after Strategy routine *
;* *
;* ARGS: None *
;* RETS: Return code in Request Header's Status field *
;* REGS: Preserved *
;* *
;* This entry point is used only during initialization. *
;* It replaces itself with a much shorter version which only *
;* serves to report the appropriate errors when this driver *
;* is called in error. *
;* *
;*----------------------------------------------------------------------*
InitInterrupt proc far
; Save the registers including flags.
push ax ; We cannot use pusha\popa because
push bx ; we could be on an 8086 at this point
push cx
push dx
push ds
push es
push di
push si
push bp
pushf
push cs ; Set DS=CS for access to global variables.
pop ds
les di,[pReqHdr] ; ES:DI = Request Header
mov bl,es:[di].Command ; Get Function code in BL
or bl,bl ; Only Function 00h (Init) is legal
jz IInit
cmp bl,16 ; Test for "legal" DOS functions
jle IOtherFunc
IBogusFunc:
mov ax,8003h ; Return "Unknown Command"
jmp short IExit
IOtherFunc:
xor ax,ax ; Return zero for unsupported functions
jmp short IExit
IInit:
call InitDriver ; Initialize the driver
les di,[pReqHdr] ; Restore es:di = Request Header
IExit:
or ax,0100h ; Turn on the "Done" bit
mov es:[di].Status,ax ; Store return code
popff ; restore the registers
pop bp
pop si
pop di
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
mov dd_int_loc,offset Interrupt ; replace Interrupt with
ret ; tiny permanent stub
InitInterrupt endp
;*----------------------------------------------------------------------*
;* *
;* InitDriver - *
;* *
;* Called when driver is Initialized. *
;* *
;* ARGS: ES:DI = Address of the Request Header *
;* RETS: pHdr.Address = Bottom of resident driver code *
;* REGS: AX, CX and Flags are clobbered *
;* *
;*----------------------------------------------------------------------*
ifndef NEC_98
public InitDriver
endif ;NEC_98
InitDriver proc near
cld
ifndef debug_tsr
call LocateHiSeg ; locate the hiseg in low memory properly
mov ax,cs
push es
mov es,hiseg
assume es:funky
add textseg,ax ; relocate text segment pointer
add LEnblA20+2, ax ; update ptrs to enble & disable a20 rtns
add LDsblA20+2, ax
pop es
assume es:nothing
endif
; mov ah,9 ; display signon message
; mov dx,offset SignOnMsg
; int 21h
mov ah,30h ; make sure we've got DOS 3.00 or higher
int 21h ; Get DOS versions number
cmp al,3
jae IDCheckXMS
mov dx,offset BadDOSMsg
jmp IDFlushMe
IDCheckXMS:
ifndef NEC_98
mov ax,(INT2F_ID SHL 8) OR INT2F_INS_CHK
int 2Fh ; make sure there's no other XMS installed
else ;NEC_98
mov ax,4300h ; make sure there's no other XMS installed
int 2Fh
endif ;NEC_98
cmp al,80h ; Is INT 2F hooked?
jne IDNotInYet
mov dx,offset NowInMsg
jmp IDFlushMe
IDNotInYet:
ifdef NEC_98
xor ax,ax
mov es,ax
test byte ptr es:[501h],40h ; we're on an V30/V50
jz @f
jmp IDFlushMe ; so give out
@@:
call GetInt15Memory ; If Int 15h/88h reports < 384k of
mov dx,offset NoExtMemMsg
or ax,ax ; we have extend memory ?
jnz @f
jmp IDFlushMe ; so give out
@@:
test byte ptr es:[0501h],08h ; Q : HIRES CRT ?
jz @f ; N : continue
mov ah,byte ptr es:[501h] ; BIOS_FLG
mov al,ah ; save
and ah,07h ; get main memory size
cmp ah,4 ; main memory > 512 ?
jb @f ; no. don't need to init RAMWindow
test byte ptr es:[458h],80h ; NPC ?
jnz not_XA ; yes
test al,30h ; system type = 0 ?
jnz not_XA ; no. other than XA
call Init_RamWindow_XA
jmp short @f
not_XA:
call Init_RamWindow
@@:
endif ;NEC_98
call GetParms ; process command line parameters
;; don't call IsA20On at this moment because we haven't init it yet
mov ax, 2
XMSSVC XMS_A20
;;;; call IsA20On ; Is A20 already enabled?
or ax,ax ; (may zap cx, si, di)
jz IDInsA20 ; no, go install A20 handler
mov dx,offset A20OnMsg ; "A20 already on" message
cmp fA20Control,0 ; should we take control of A20 anyway?
jne IDInsA20 ; yes, go muck with it
mov [fCanChangeA20],0 ; no, don't allow changing of A20
mov ah,9 ; and tell user about it
int 21h
jmp short IDAfterA20
IDInsA20:
call InstallA20 ; install proper A20 handler
jc IDFlushMe ; CY means fatal error
; Note: A side affect of the previous InstallA20 is that MemCorr
; is set to reflect the adjustment factor if we're on an AT&T 6300+
IDAfterA20:
call InitHandles ; initialize handle table
call GetInt15Memory ; how much extended memory is installed?
cmp ax,64 ; Is there >= 64K of extended?
ifndef NEC_98
jae IDHMAOK
else ;NEC_98
jb @f
cmp Int15MemSize, 0 ; has the hma been allocated to INT 15 ?
jz IDHMAOK ; no, HMA is available
@@:
endif ;NEC_98
push es
mov es,hiseg
assume es:funky
mov bx,[KiddValley] ; get size of memory we already have in tables
mov cx,[cHandles]
IDAnyMem:
cmp [bx].Flags,FREEFLAG
jnz IDAnyMem_1 ; brif not a valid free block
add ax,[bx].Len ; accumulate total
IDAnyMem_1:
add bx,SIZE Handle
loop IDAnyMem
pop es
assume es:nothing
mov dx,offset NoHMAMsg
or ax,ax ; no HMA, any other memory to control?
jnz disp_hma_msg ; jmp if some memory
; We can't find any memory to manage.
mov dx,offset NoExtMemMsg
; Display the message in DX followed by the "Flush" message.
IDFlushMe:
mov ah,9
int 21h
mov dx,offset FlushMsg
mov ah,9
int 21h
xor ax,ax ; discard the driver
mov [TopOfTextSeg],ax
ifndef debug_tsr ;-------------------------------
les di,[pReqHdr]
mov es:[di].Units,al
and cs:DevAttr,not 8000h ; clr bit 15 in attrib of driver header
endif
jmp short IDReturn ;-------------------------------
IDHMAOK:
mov [fHMAMayExist],1
mov dx,offset HMAOKMsg
disp_hma_msg:
; mov ah,9
; int 21h
;; tell xms.lib where our variable is
mov ax, cs
mov bx, offset A20State
XMSSVC XMS_INITUMB
call HookInt2F ; "turn on" the driver
; Initialization finished (or failed) -- return to caller
IDReturn:
ifndef debug_tsr ;-------------------------------
mov di,offset pack_and_truncate
jmp call_hi_in_di ; pack stuff down and terminate
endif ;-------------------------------
ret
InitDriver endp
;
;----------------------------------------------------------------------------
; procedure : LocateHiSeg
;
; Locate the movable segment properly in the low seg.
; taking care of the stripped ORG zeroes. This function
; calculates the segment at which the hiseg should run
; with the ORG. If the segment cvalue goes below zero the
; code is moved up high enough to run the code from a seg value
; of zero.
;
; This function assumes that the 'funky' segment follows
; immediately after the text seg.
;
;----------------------------------------------------------------------------
;
LocateHiSeg proc near
push ds
mov ax, cs ; para start of text seg
mov cx, offset _text:EndText ; end of text seg
add cx, 15 ; para round it
shr cx, 1
shr cx, 1
shr cx, 1
shr cx, 1
add ax, cx ; para start of funky seg
cmp ax, (HISEG_ORG shr 4) ; will the seg go below zero?
jb MoveHiSeg ; yeah, we have to move it
sub ax, (HISEG_ORG shr 4) ; no, it fits in
pop ds
mov hiseg, ax ; update the segment in which
; it is going to run from.
ret
MoveHiSeg:
mov ds, ax ; segment at which funky
; resides without the ORG
xor ax, ax
mov es, ax ; we want to movve the code
; to 0:HISEG_ORG
mov di, offset funky:end_of_funky_seg
mov si, di
sub si, HISEG_ORG
mov cx, si
dec di
dec si
std ; move backward (safe when
; source & dest overlap
rep movsb
cld
pop ds
mov hiseg, 0 ; funky is going to run from
; segment zero
ret
LocateHiSeg endp
;*----------------------------------------------------------------------*
;* *
;* HookInt2F - *
;* *
;* Insert the INT 2F hook *
;* *
;* ARGS: None *
;* RETS: None *
;* REGS: AX, SI, ES and Flags are clobbered *
;* *
;*----------------------------------------------------------------------*
public HookInt2F
HookInt2F proc near
call DOCLI
xor ax,ax
mov es,ax
mov si,2Fh * 4 ; save previous int2f vector
mov ax,offset Int2FHandler ; and exchange with new one
xchg ax,es:[si][0]
mov word ptr [PrevInt2F][0],ax
mov ax,cs
xchg ax,es:[si][2]
mov word ptr [PrevInt2F][2],ax
call DOSTI
ret
HookInt2F endp
;*----------------------------------------------------------------------*
;* *
;* GetInt15Memory - *
;* *
;* Returns the amount of memory INT 15h, Function 88h says is free *
;* *
;* ARGS: None *
;* RETS: AX = Amount of free extended memory in K-bytes *
;* REGS: AX and Flags are clobbered *
;* *
;*----------------------------------------------------------------------*
GetInt15Memory proc near
ifndef NEC_98
IFDEF WHEN_INT15_DONE
mov ah,88h ; snag the int 15h memory
clc
int 15h ; Is Function 88h around?
jnc xret_geti15
xor ax,ax ; No, return 0
xret_geti15:
ifndef NOLIMIT ;M005
cmp ax,15*1024 ; Limit himem.sys to using 15 meg
jb @f ; of extended memory for apps
mov ax,15*1024 ; that don't deal with > 24 bit
@@: ; addresses
endif ;M005
ELSE
XMSSVC XMS_EXTMEM ; return ext-mem in ax5
ENDIF
ret
else ;NEC_98
push es
mov ax,40h
mov es,ax
mov al,byte ptr es:[01h] ; get extend memory size
pop es
sub ah,ah
shl ax,7
ret
endif ;NEC_98
GetInt15Memory endp
;*----------------------------------------------------------------------*
;* *
;* GetParms - *
;* *
;* Get any parameters off of the HIMEM command line *
;* *
;* ARGS: None *
;* RETS: None *
;* REGS: AX, BX, CX, DX, DI, SI, ES and Flags clobbered *
;* *
;* Side Effects: cHandles and MinHMASize may be changed *
;* *
;*----------------------------------------------------------------------*
ifndef NEC_98
GPArgPtr dd ?
endif ;NEC_98
GPRegSave dw ?
public GetParms
GetParms proc near
cld ; better safe than sorry
push ds
ifdef debug_tsr ;-------------------------------
lds si,lpCmdLine
else ;-------------------------------
les di,[pReqHdr] ; Running as a device driver
lds si,es:[di].pCmdLine ; DS:SI points to first char
; after "DEVICE="
ifndef NEC_98
@@: call GPGetChar ; Skip over driver name, up to
jc GPDatsAll ; first blank or / or eol
jz GPNextArg
cmp al,'/'
jnz @b
dec si ; Backup to get / again
endif ;NEC_98
endif ;-------------------------------
assume ds:nothing,es:nothing
; Scan until we see a non-blank or the end of line.
ifndef NEC_98
GPNextArg:
call GPGetChar
jc GPDatsAll ; eol
jz GPNextArg ; blank
mov word ptr cs:[GPArgPtr], si ; save ptr to start of arg
mov word ptr cs:[GPArgPtr+2], ds ; incase we want to complain
dec word ptr cs:[GPArgPtr] ; (GPGetChar points at next)
cmp al,'/' ; better be a / or not a valid arg
jz GPGotOne
; Detected invalid parameter or value, complain to user
GPBadParm:
mov ah,9 ; tell'm something isn't right
push cs
pop ds
mov dx,offset BadArgMsg
int 21h
lds si,cs:[GPArgPtr] ; backup to last parameter
GPBadDisp:
call GPGetChar ; disp arg up to space or eol
jc GPDatsAll ; skips over bad arg while we're at it
jz GPNextArg
cmp al,'/' ; start of next arg?
jnz @f
dec si ; maybe yes, maybe no--might
cmp si,word ptr cs:[GPArgPtr] ; be same arg
jnz GPNextArg ; next, go process new arg
inc si ; same, keep displaying
@@:
mov dl,al
mov ah,2
int 21h
jmp short GPBadDisp
; Finished, we're outta here...
else ;NEC_98
GPBadParm:
GPNextChar:
call GPGetChar
jc GPDatsAll
cmp al,'/'
je GPGotOne
jmp short GPNextChar
endif ;NEC_98
GPDatsAll:
pop ds
ret
; Save what we found and get the number or string after it.
GPGotOne:
lodsb
mov cs:[GPRegSave],ax
; Scan past the rest of the parm for a number, EOL, or a space.
GPNeedParm:
call GPGetChar
ifndef NEC_98
jc GPBadParm
jz GPBadParm ; blank
else ;NEC_98
jc GPDatsAll
cmp al,' '
je GPBadParm
endif ;NEC_98
cmp al,':' ; start of string arg
je GPString
cmp al,'='
jne GPNeedParm
; Read the number at DS:SI into DX
GPNeedNum:
call GPGetChar
jc GPDatsAll
cmp al,'0'
jb GPNeedNum
cmp al,'9'
ja GPNeedNum
xor dx,dx
GPNumLoop:
sub al,'0'
cbw
add dx,ax
call GPGetChar
jc GPNumDone
ifndef NEC_98
jz GPNumDone
else ;NEC_98
cmp al,' '
je GPNumDone
endif ;NEC_98
cmp al,'0'
jb GPBadParm
cmp al,'9'
ja GPBadParm
shl dx,1 ; multiply DX by 10
mov bx,dx
shl dx,1
shl dx,1
add dx,bx
jmp short GPNumLoop
; Move the string arg from ds:si to StringParm
GPString:
mov cx,(SIZE StringParm) - 1
push cs
pop es
mov di,offset _text:StringParm
GPStrLoop:
call GPGetChar
jc GPStrDone
ifndef NEC_98
jz GPStrDone
else ;NEC_98
cmp al,' '
je GPStrDone
endif ;NEC_98
stosb
loop GPStrLoop
GPStrDone:
mov byte ptr es:[di],0 ; Null terminate the string
ifndef NEC_98
mov dx,-1 ; In case parm expects a num, give'm
; a likely invalid one
endif ;NEC_98
; Which parameter are we dealing with here?
GPNumDone:
xchg ax,cs:[GPRegSave]
cmp al,'H' ; HMAMIN= parameter?
jne @f
jmp GPGotMin
@@:
cmp al,'N' ; NUMHANDLES= parameter?
jne @f
jmp GPGotHands
@@: cmp al,'M' ; MACHINE: parameter?
je GPGotMachine
cmp al,'A' ; A20CONTROL: parameter?
je GPGotA20Control
cmp al,'S' ; SHADOWRAM: parameter?
jne @f
jmp GPGotShadow
@@: cmp al, 'I' ; INT15=
jne @f
jmp GPGotInt15
ifndef NEC_98
@@: cmp al, 'C' ; CPUCLOCK:
jne @f
jmp GPGotCPUClock
endif ;NEC_98
@@: jmp GPBadParm
; Process /A20CONTROL: parameter
GPGotA20Control:
mov ax,word ptr [StringParm]
or ax,2020h
mov bl,0FFh
cmp ax,'no' ; ON ? - means we take control
jz GPSetA20
inc bl
cmp ax,'fo' ; OFF ? - means we leave alone if on
jz GPSetA20
ifndef NEC_98
jmp GPBadParm
else ;NEC_98
jmp GPNextParm
endif ;NEC_98
GPSetA20:
mov fA20Control,bl ; Z if A20 should be left alone if
jmp GPNextParm ; it's already on when we're loaded
; Process /MACHINE: parameter.
GPGotMachine:
push si ; save current location
push ds ; in param string
push cs
pop ds
mov di,offset _text:MachineName ; es:di -> MachineName
GPNextTbl:
xor bx,bx
GPNextName:
mov si,offset _text:StringParm ; ds:si -> StringParm
GPChkNext:
cmp byte ptr es:[di],0FFh ; end of name table?
ifndef NEC_98
jz GPNoName
else ;NEC_98
jz GPBadName
endif ;NEC_98
lodsb ; char from StringParm
cmp al,'A' ; force to lower case for match
jb @f ; (might be numeric, so don't just OR)
cmp al,'Z'
ja @f
or al,20h
@@:
cmp al,es:[di] ; match so far?
jnz GPFlushName
or al,al ; finished if matched up to & incl NULL
jz GPFoundName
inc di ; still matches, check next char
jmp short GPChkNext
GPFlushName:
inc bx
GPFN2:
inc di
cmp byte ptr es:[di],0FFh
ifndef NEC_98
jz GPNoName
else ;NEC_98
jz GPBadName
endif ;NEC_98
cmp byte ptr es:[di],0
jnz GPFN2
inc di
jmp short GPNextName
GPFoundName:
mov cs:[MachineNum],bx ; found a match, remember which entry
jmp short GPNameDone ; it is for later
ifndef NEC_98
GPNoName:
cmp di,offset _text:AltNameTbl
ja GPBadName
mov di,offset _text:AltNameTbl
jmp short GPNextTbl
GPNameDone:
pop ds ; recover parm line pointer
pop si
jmp GPNextParm
GPBadName:
pop ds ; clear stack and error out...
pop si
jmp GPBadParm
else ;NEC_98
GPBadName:
cmp di,offset _text:AltNameTbl
ja GPNameDone
mov di,offset _text:AltNameTbl
jmp short GPNextTbl
GPNameDone:
pop ds ; recover parm line pointer
pop si
jmp GPNextParm
endif ;NEC_98
; Process /NUMHANDLES= parameter.
GPGotHands:
cmp dx,MAXHANDLES
jna @f
jmp GPBadParm
@@:
or dx,dx ; Zero?
jnz @f
jmp GPBadParm
@@:
push es
mov es,hiseg
assume es:funky
mov [cHandles],dx ; Store it
pop es
assume es:nothing
mov dx,offset StartMsg ; display descriptive message
call GPPrintIt
push es
mov es,hiseg
assume es:funky
mov ax,[cHandles]
pop es
assume es:nothing
call GPPrintAX
mov dx,offset HandlesMsg
call GPPrintIt
ifndef NEC_98
jmp GPNextParm
else ;NEC_98
jmp short GPNextParm
endif ;NEC_98
GPGotMin:
cmp dx,64 ; process /hmamin= parameter
jna @f
jmp GPBadParm
@@:
push dx
mov cs:[MinHMASize],dx
mov dx,offset HMAMINMsg ; print a descriptive message
call GPPrintIt
mov ax,cs:[MinHMASize]
call GPPrintAX
mov dx,offset KMsg
call GPPrintIt
pop dx
mov cl,10 ; Convert from K to bytes
shl dx,cl
mov cs:[MinHMASize],dx
jmp short GPNextParm
; Process /SHADOWRAM: parameter
GPGotShadow:
mov ax,word ptr [StringParm]
or ax,2020h
xor bl,bl
cmp ax,'no' ; ON ? - means we leave it alone
jz GPSetShadow
inc bl
cmp ax,'fo' ; OFF ? - means we turn it off
jz GPSetShadow
ifndef NEC_98
jmp GPBadParm
else ;NEC_98
jmp short GPNextParm
endif ;NEC_98
GPSetShadow:
mov fShadowOff,bl ; NZ if Shadow RAM should be turned off
jmp short GPNextParm
ifndef NEC_98
; Process /CPUCLOCK: parameter
GPGotCPUClock:
mov ax,word ptr [StringParm]
or ax,2020h
xor bl,bl
cmp ax,'fo' ; OFF ? - means we don't worry about it
jz GPSetClock
inc bl
cmp ax,'no' ; ON ? - means we preserve CPU clock
jz GPSetClock ; rate
jmp GPBadParm
GPSetClock:
mov fCPUClock,bl ; NZ if clock rate preserved
jmp short GPNextParm
endif ;NEC_98
; Process /INT15= parameter
GPGotInt15:
cmp dx, 64 ; atleast 64K
jae @f
jmp GPBadParm
ifndef NEC_98
@@: call GetInt15Memory
cmp ax, dx ; enuf Ext Mem ?
else ;NEC_98
call GetInt15Memory
@@: cmp ax, dx ; enuf Ext Mem ?
endif ;NEC_98
jae @f
jmp GPBadParm
@@: mov [Int15MemSize], dx
; Fall through to GetNextParm
ifdef NEC_98
jmp short GPNextParm
endif ;NEC_98
GPNextParm:
mov ax,cs:[GPRegSave] ; are we at the end of the line?
cmp al,13 ; may not be needed any longer...
je GPExit
cmp al,10
je GPExit
ifndef NEC_98
jmp GPNextArg
else ;NEC_98
jmp GPNextChar
endif ;NEC_98
GPExit:
pop ds
ret
GetParms endp
; Get the next character from DS:SI, set CY if it's an EOL (CR, LF), set
; Z if it's a space
ifndef NEC_98
GPOffEOL dw -1
endif ;NEC_98
public GPGetChar
GPGetChar proc near
ifndef NEC_98
cmp si,cs:[GPOffEOL] ; are we already at EOL?
jnb GPAtEOL
lodsb ; no, get next char
cmp al,10 ; is this the EOL?
je GPHitEOL
cmp al,13
je GPHitEOL
cmp al,' ' ; set Z if blank
clc
ret
GPHitEOL:
mov cs:[GPOffEOL],si ; save EOL offset once
GPAtEOL:
else ;NEC_98
lodsb
cmp al,10
je @f
cmp al,13
je @f
clc
ret
@@:
endif ;NEC_98
stc
ret
GPGetChar endp
;*----------------------------------------------------------------------*
GPPrintIt proc near
push ds ; Save current DS
push cs ; Set DS=CS
pop ds
mov ah,9
int 21h
pop ds ; Restore DS
ret
GPPrintIt endp
;*----------------------------------------------------------------------*
GPPrintAX proc near
mov cx,10
xor dx,dx
div cx
or ax,ax
jz GPAPrint
push dx
call GPPrintAX
pop dx
GPAPrint:
add dl,'0'
mov ah,2
int 21h
ret
GPPrintAX endp
;*----------------------------------------------------------------------*
;* *
;* InitHandles - *
;* *
;* Initialize the Extended Memory Handle Table *
;* *
;* ARGS: None *
;* RETS: None *
;* REGS: AX, BX, CX, and Flags are clobbered *
;* *
;*----------------------------------------------------------------------*
assume ds:_text
public InitHandles
InitHandles proc near
push es
mov es,hiseg
assume es:funky
mov cx,[cHandles]
; Init the Handle table.
mov bx,[KiddValley]
xor ax,ax
IHTabLoop:
mov [bx].Flags,UNUSEDFLAG
mov [bx].cLock,al
mov [bx].Base,ax
mov [bx].Len,ax
if keep_cs
mov [bx].Acs,ax
endif
add bx,SIZE Handle
loop IHTabLoop
mov [KiddValleyTop],bx ; save top for handle validation
pop es
assume es:nothing
ret
InitHandles endp
ifdef NEC_98
;******************************************************************************
; Init_Ram_Window - Initialize Ram Window Memory
;
; MS-DOS
; Ram Window Memory Ram Windows Memory
; 80 100 80 80
; 90 110 90 90
; BO 120 B0 B0
; A0 130 A0 A0
;
;
;
; Author: (sbp)
;
; ENTRY: REAL MODE on 386 processor (CPU ID already performed)
; EXIT:
;
; USED: flags
; STACK:
;------------------------------------------------------------------------------
Init_RamWindow proc near
push ax
push bx
push dx
push ds
cli
mov cs:[save_ss],ss
mov cs:[save_sp],sp
push cs
pop ss
mov sp,offset EISA_stack
mov al, 8
out 37h, al
mov ax, 8000h ; 転送元アドレス
mov bx, 4000h ; 転送先アドレス
mov cx, 4 ; 転送バンク数
call movebank
mov al,08h ; 80 BANK memory
mov dx,91h ; 80 BANK ram windows "
out dx,al ; set RAM WINDOW
mov al,0ah ; A0 BANK memory
mov dx,93h ; A0 BANK ram window "
out dx,al ; set RAM WINDOW
xor ax, ax
mov ds, ax
test byte ptr ds:[481h], 04h ; Q : can use shadow ram ?
jnz @f
call initshadowram
@@:
mov ax, 4000h
mov bx, 8000h
mov cx, 4
call movebank
mov ss, cs:[save_ss]
mov sp, cs:[save_sp]
mov al, 09h
out 37h, al
sti
pop ds
pop dx
pop bx
pop ax
ret
Init_RamWindow endp
;******************************************************************************
; Init_Ram_Window_XA - Initialize Ram Window Memory
;
; MS-DOS Himem
; Ram Window Memory Ram Windows Memory
; 80 100 80 TOM-40 or TOM-20
; 90 110 90 TOM-30 or TOM-10
; BO 120 B0 TOM-20 or 120
; A0 130 A0 TOM-10 or 130
;
; Author: (sbp)
;
; ENTRY: REAL MODE on 286
; AH = main memory size in blocks of 128k
; EXIT:
;
; USED: flags
; STACK:
;------------------------------------------------------------------------------
Init_RamWindow_XA proc near
sub ah,3
cmp byte ptr es:[401h],ah
ja IRX_Start
mov byte ptr es:[401h],0
ret
IRX_Start:
push ax
push bx
push dx
push ds
cli
mov cs:[save_ss],ss
mov cs:[save_sp],sp
push cs
pop ss
mov sp,offset EISA_stack
mov al, 8
out 37h, al
cmp ah,1 ; main memory = 640k ?
je IRX_640
mov ax, 0a000h ; 転送元アドレス
mov bx, 4000h ; 転送先アドレス
mov cx, 2 ; 転送バンク数
call movebank
mov al,byte ptr es:[401h]
dec al
shl al,1
add al,10h ; al = BANK #
mov dx,93h ; A0 BANK ram window "
out dx,al ; set RAM WINDOW
mov ax, 4000h
mov bx, 0a000h
mov cx, 2
call movebank
dec byte ptr es:[401h]
IRX_640:
mov ax, 8000h ; 転送元アドレス
mov bx, 4000h ; 転送先アドレス
mov cx, 2 ; 転送バンク数
call movebank
mov al,byte ptr es:[401h]
dec al
shl al,1
add al,10h ; al = BANK #
mov dx,91h ; 80 BANK ram windows "
out dx,al ; set RAM WINDOW
mov ax, 4000h
mov bx, 8000h
mov cx, 2
call movebank
dec byte ptr es:[401h]
mov ss, cs:[save_ss]
mov sp, cs:[save_sp]
mov al, 09h
out 37h, al
sti
pop ds
pop dx
pop bx
pop ax
ret
Init_RamWindow_XA endp
;-------------------------------------------------------------------
; movebank move bank datat
; entry ax : source seg. address
; bx : dest. seg. address
; cx : bank count
;
;----------------------------------------------------------------
movebank proc near
push es
push ds
push si
push di
@@:
mov ds, ax
mov es, bx
push cx
mov cx, 8000h
cld
xor si, si
xor di, di
rep movsw
pop cx
add ax, 1000h ; get next bank address
add bx, 1000h ; get next bank address
loop @b
pop di
pop si
pop ds
pop es
ret
movebank endp
;*-----------------------------------------------------------
;* initshadowram
;*
;*
;*----------------------------------------------------------
initshadowram proc near
push es
push di
push cx
cld
mov ax, 8000h
mov es, ax
mov cx, 0004h
mov ax,8000h
mov es,ax
mov cx,0004h
l3:
xor di, di
push cx
mov cx, 3333h
l1:
mov ax, 0ff01h
stosw
mov ax, 55aah
stosw
mov al, 00
stosb
loop l1
stosb
xor di, di
mov cx, 3333h
l2:
mov ax,0ff01h
scasw
jnz isr_exit
mov ax,55aah
scasw
jnz isr_exit
mov al,00h
scasb
jnz isr_exit
loop l2
mov ax, es
add ax, 1000h
mov es, ax
pop cx
loop l3
; clean up memory
mov cx, 0004h
l4:
push cx
mov ax, es
sub ax, 1000h
mov es, ax
xor ax, ax
mov di, ax
mov cx, 8000h
rep stosw
pop cx
loop l4
xor ax,ax
jmp short isr_done
isr_exit:
mov ax,0001
isr_done:
pop cx
pop di
pop es
ret
initshadowram endp
;*----------------------------------------------------------------------*
;* *
;* ScanEISA - poll any EISA devices through the BIOS's Int15(0d8h) *
;* and add any memory we find out about to our free memory table. *
;* Note: this code (including a big buffer) gets thrown out after *
;* completion of the initialization sequence. *
;* *
;* Note: The COMPAQ BIOS uses up 1.5K of stack during int15(d80x) *
;* so we'll set up a separate stack while we're here *
;* *
;*----------------------------------------------------------------------*
save_ss dw 0
save_sp dw 0
EISA_Stack:
endif ;NEC_98
_text ends
ifdef debug_tsr
EndStmt equ <end ExeStart>
STACK segment stack 'STACK'
db 1024 dup (?)
STACK ends
else
EndStmt equ <end>
endif
EndStmt