3973 lines
94 KiB
NASM
3973 lines
94 KiB
NASM
page ,160
|
|
title bios system initialization
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Modification history
|
|
;
|
|
; 26-Feb-1991 sudeepb Ported for NT DOSEm
|
|
;----------------------------------------------------------------------------
|
|
|
|
include version.inc ; set version build flags
|
|
include biosseg.inc ; establish bios segment structure
|
|
|
|
lf equ 10
|
|
cr equ 13
|
|
tab equ 9
|
|
|
|
have_install_cmd equ 00000001b ; config.sys has install= commands
|
|
has_installed equ 00000010b ; sysinit_base installed.
|
|
|
|
default_filenum = 8
|
|
|
|
break macro ; dummy empty macro
|
|
endm
|
|
|
|
include sysvar.inc
|
|
include pdb.inc ; M020
|
|
include syscall.inc
|
|
include doscntry.inc
|
|
include devsym.inc
|
|
include devmark.inc
|
|
|
|
include umb.inc
|
|
include dossym.inc
|
|
include dossvc.inc
|
|
include cmdsvc.inc
|
|
include softpc.inc
|
|
|
|
stacksw equ true ;include switchable hardware stacks
|
|
|
|
if ibmjapver
|
|
noexec equ true
|
|
else
|
|
noexec equ false
|
|
endif
|
|
|
|
|
|
|
|
|
|
; external variable defined in ibmbio module for multi-track
|
|
|
|
multrk_on equ 10000000b ;user spcified mutitrack=on,or system turns
|
|
; it on after handling config.sys file as a
|
|
; default value,if multrk_flag = multrk_off1.
|
|
multrk_off1 equ 00000000b ;initial value. no "multitrack=" command entered.
|
|
multrk_off2 equ 00000001b ;user specified multitrack=off.
|
|
|
|
Bios_Data segment
|
|
extrn multrk_flag:word
|
|
extrn keyrd_func:byte
|
|
extrn keysts_func:byte
|
|
Bios_Data ends
|
|
|
|
; end of multi-track definition.
|
|
|
|
sysinitseg segment
|
|
|
|
assume cs:sysinitseg,ds:nothing,es:nothing,ss:nothing
|
|
|
|
extrn badopm:byte,crlfm:byte,badcom:byte,badmem:byte,badblock:byte
|
|
extrn badsiz_pre:byte,badld_pre:byte
|
|
extrn badstack:byte,badcountrycom:byte
|
|
extrn badcountry:byte,insufmemory:byte
|
|
extrn condev:byte,auxdev:byte,prndev:byte,commnd:byte,config:byte
|
|
extrn cntry_drv:byte,cntry_root:byte,cntry_path:byte
|
|
extrn memory_size:word
|
|
extrn buffers:word
|
|
extrn files:byte,num_cds:byte
|
|
extrn dosinfo:dword
|
|
extrn fcbs:byte,keep:byte
|
|
extrn confbot:word,alloclim:word,command_line:byte
|
|
extrn zero:byte,sepchr:byte
|
|
extrn count:word,chrptr:word,cntryfilehandle:word
|
|
extrn memlo:word,memhi:word,prmblk:word,ldoff:word
|
|
extrn packet:byte,unitcount:byte,break_addr:dword
|
|
extrn bpb_addr:dword,drivenumber:byte,sysi_country:dword
|
|
extrn config_size:word
|
|
extrn install_flag:word
|
|
extrn badorder:byte
|
|
extrn errorcmd:byte
|
|
extrn linecount:word
|
|
extrn showcount:byte
|
|
extrn buffer_linenum:word
|
|
extrn h_buffers:word
|
|
extrn badparm:byte
|
|
extrn configmsgflag:word
|
|
extrn org_count:word
|
|
extrn multi_pass_id:byte
|
|
|
|
extrn mem_err:near,setdoscountryinfo:near
|
|
extrn pararound:near,tempcds:near
|
|
extrn set_country_path:near,move_asciiz:near,delim:near
|
|
extrn badfil:near,round:near
|
|
extrn do_install_exec:near
|
|
extrn setdevmark:near
|
|
|
|
extrn print:near,organize:near,newline:near
|
|
extrn parseline:near
|
|
extrn badload:near,calldev:near,prnerr:near
|
|
|
|
extrn runhigh:byte
|
|
extrn IsXMSLoaded:near
|
|
|
|
extrn TryToMovDOSHi:near
|
|
|
|
ifdef DBCS
|
|
extrn testkanj:near
|
|
endif
|
|
|
|
extrn bEchoConfig:byte ; NTVDM flag off\on echo of cfg processing
|
|
|
|
if stacksw
|
|
|
|
; internal stack parameters
|
|
|
|
entrysize equ 8
|
|
|
|
mincount equ 8
|
|
defaultcount equ 9
|
|
maxcount equ 64
|
|
|
|
minsize equ 32
|
|
defaultsize equ 128
|
|
maxsize equ 512
|
|
|
|
DOS_FLAG_OFFSET equ 86h
|
|
|
|
extrn stack_count:word
|
|
extrn stack_size:word
|
|
extrn stack_addr:dword
|
|
|
|
endif
|
|
|
|
public doconf
|
|
public getchr
|
|
public multi_pass
|
|
public AllocUMB
|
|
public AllocUMBLow ; NTVDM
|
|
public multdeviceflag
|
|
multdeviceflag db 0
|
|
public devmark_addr
|
|
devmark_addr dw ? ;segment address for devmark.
|
|
public setdevmarkflag
|
|
setdevmarkflag db 0 ;flag used for devmark
|
|
|
|
ems_stub_installed db 0
|
|
|
|
IFDEF DONT_LOAD_OS2_DD ; M045
|
|
|
|
Os2ChkBuf DD 0 ; Tmp read buffer
|
|
|
|
ENDIF ; M045
|
|
|
|
badparm_ptr label dword
|
|
badparm_off dw 0
|
|
badparm_seg dw 0
|
|
|
|
;******************************************************************************
|
|
;take care of config.sys file.
|
|
;system parser data and code.
|
|
;******************************************************************************
|
|
|
|
;*******************************************************************
|
|
; parser options set for msbio sysconf module
|
|
;*******************************************************************
|
|
;
|
|
;**** default assemble swiches definition **************************
|
|
|
|
ifndef farsw
|
|
farsw equ 0 ; near call expected
|
|
endif
|
|
|
|
ifndef datesw
|
|
datesw equ 0 ; check date format
|
|
endif
|
|
|
|
ifndef timesw
|
|
timesw equ 0 ; check time format
|
|
endif
|
|
|
|
ifndef filesw
|
|
filesw equ 1 ; check file specification
|
|
endif
|
|
|
|
ifndef capsw
|
|
capsw equ 0 ; perform caps if specified
|
|
endif
|
|
|
|
ifndef cmpxsw
|
|
cmpxsw equ 0 ; check complex list
|
|
endif
|
|
|
|
ifndef numsw
|
|
numsw equ 1 ; check numeric value
|
|
endif
|
|
|
|
ifndef keysw
|
|
keysw equ 0 ; support keywords
|
|
endif
|
|
|
|
ifndef swsw
|
|
swsw equ 1 ; support switches
|
|
endif
|
|
|
|
ifndef val1sw
|
|
val1sw equ 1 ; support value definition 1
|
|
endif
|
|
|
|
ifndef val2sw
|
|
val2sw equ 0 ; support value definition 2
|
|
endif
|
|
|
|
ifndef val3sw
|
|
val3sw equ 1 ; support value definition 3
|
|
endif
|
|
|
|
ifndef drvsw
|
|
drvsw equ 1 ; support drive only format
|
|
endif
|
|
|
|
ifndef qussw
|
|
qussw equ 0 ; support quoted string format
|
|
endif
|
|
|
|
|
|
include parse.asm ;together with psdata.inc
|
|
|
|
;control block definitions for parser.
|
|
;---------------------------------------------------
|
|
; buffer = [n | n,m] {/e}
|
|
|
|
p_parms struc
|
|
dw ?
|
|
db 1 ; an extra delimiter list
|
|
db 1 ; length is 1
|
|
db ';' ; delimiter
|
|
p_parms ends
|
|
|
|
p_pos struc
|
|
dw ? ; numeric value??
|
|
dw ? ; function
|
|
dw ? ; result value buffer
|
|
|
|
; note: by defining result_val before this structure, we could remove
|
|
; the "result_val" from every structure invocation
|
|
|
|
dw ? ; value list
|
|
db 0 ; no switches/keywords
|
|
p_pos ends
|
|
|
|
p_range struc
|
|
db 1 ; range definition
|
|
db 1 ; 1 definition of range
|
|
db 1 ; item tag for this range
|
|
dd ? ; numeric min
|
|
dd ? ; numeric max
|
|
p_range ends
|
|
|
|
buf_parms p_parms <buf_parmsx>
|
|
buf_parmsx dw 201h,buf_pos1,buf_pos2 ; min 1, max 2 positionals
|
|
db 1 ; one switch
|
|
dw sw_x_ctrl
|
|
db 0 ; no keywords
|
|
|
|
buf_pos1 p_pos <8000h,0,result_val,buf_range_1> ; numeric
|
|
buf_range_1 p_range <,,,1,99> ; M050
|
|
buf_pos2 p_pos <8001h,0,result_val,buf_range_2> ; optional num.
|
|
buf_range_2 p_range <,,,0,8>
|
|
|
|
sw_x_ctrl p_pos <0,0,result_val,noval,1> ; followed by one switch
|
|
switch_x db '/X',0 ; M016
|
|
|
|
p_buffers dw 0 ; local variables
|
|
p_h_buffers dw 0
|
|
p_buffer_slash_x db 0
|
|
|
|
;common definitions ------------
|
|
noval db 0
|
|
|
|
result_val label byte
|
|
db ? ; type returned
|
|
db ? ; item tag returned
|
|
dw ? ; es:offset of the switch defined
|
|
rv_byte label byte
|
|
rv_dword dd ? ; value if number,or seg:offset to string.
|
|
;-------------------------------
|
|
|
|
; break = [ on | off ]
|
|
|
|
brk_parms p_parms <brk_parmsx>
|
|
|
|
brk_parmsx dw 101h,brk_pos ; min,max = 1 positional
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
brk_pos p_pos <2000h,0,result_val,on_off_string> ; simple string
|
|
|
|
on_off_string label byte
|
|
db 3 ; signals that there is a string choice
|
|
db 0 ; no range definition
|
|
db 0 ; no numeric values choice
|
|
db 2 ; 2 strings for choice
|
|
db 1 ; the 1st string tag
|
|
dw on_string
|
|
db 2 ; the 2nd string tag
|
|
dw off_string
|
|
|
|
on_string db "ON",0
|
|
off_string db "OFF",0
|
|
|
|
p_ctrl_break db 0 ; local variable
|
|
|
|
;--------------------------------
|
|
|
|
; country = n {m {path}}
|
|
; or
|
|
; country = n,,path
|
|
|
|
cntry_parms p_parms <cntry_parmsx>
|
|
|
|
cntry_parmsx dw 301h,cntry_pos1,cntry_pos2,cntry_pos3 ; min 1, max 3 pos.
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
cntry_pos1 p_pos <8000h,0,result_val,cc_range> ; numeric value
|
|
cc_range p_range <,,,1,999>
|
|
cntry_pos2 p_pos <8001h,0,result_val,cc_range> ; optional num.
|
|
cntry_pos3 p_pos <201h,0,result_val,noval> ; optional filespec
|
|
|
|
p_cntry_code dw 0 ; local variable
|
|
p_code_page dw 0 ; local variable
|
|
|
|
;--------------------------------
|
|
|
|
; files = n
|
|
|
|
files_parms p_parms <files_parmsx>
|
|
|
|
files_parmsx dw 101h,files_pos ; min,max 1 positional
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
files_pos p_pos <8000h,0,result_val,files_range,0> ; numeric value
|
|
files_range p_range <,,,8,255>
|
|
|
|
p_files db 0 ; local variable
|
|
|
|
;-------------------------------
|
|
|
|
; fcbs = n,m
|
|
|
|
fcbs_parms p_parms <fcbs_parmsx>
|
|
|
|
fcbs_parmsx dw 201h,fcbs_pos_1,fcbs_pos_2 ; min,max = 2 positional
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
fcbs_pos_1 p_pos <8000h,0,result_val,fcbs_range> ; numeric value
|
|
fcbs_range p_range <,,,1,255>
|
|
fcbs_pos_2 p_pos <8000h,0,result_val,fcbs_keep_range> ; numeric value
|
|
fcbs_keep_range p_range <,,,0,255>
|
|
|
|
p_fcbs db 0 ; local variable
|
|
p_keep db 0 ; local variable
|
|
|
|
;-------------------------------
|
|
; lastdrive = x
|
|
|
|
ldrv_parms p_parms <ldrv_parmsx>
|
|
|
|
ldrv_parmsx dw 101h,ldrv_pos ; min,max = 1 positional
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
ldrv_pos p_pos <110h,10h,result_val,noval> ; drive only, ignore colon
|
|
; remove colon at end
|
|
p_ldrv db 0 ; local variable
|
|
|
|
;-------------------------------
|
|
|
|
; stacks = n,m
|
|
|
|
stks_parms p_parms <stks_parmsx>
|
|
|
|
stks_parmsx dw 202h,stks_pos_1,stks_pos_2 ; min,max = 2 positionals
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
stks_pos_1 p_pos <8000h,0,result_val,stks_range> ; numeric value
|
|
stks_range p_range <,,,0,64>
|
|
stks_pos_2 p_pos <8000h,0,result_val,stk_size_range> ; numeric value
|
|
stk_size_range p_range <,,,0,512>
|
|
|
|
p_stack_count dw 0 ; local variable
|
|
p_stack_size dw 0 ; local variable
|
|
|
|
;-------------------------------
|
|
|
|
; multitrack = [ on | off ]
|
|
|
|
mtrk_parms p_parms <mtrk_parmsx>
|
|
|
|
mtrk_parmsx dw 101h,mtrk_pos ; min,max = 1 positional
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
mtrk_pos p_pos <2000h,0,result_val,on_off_string> ; simple string
|
|
|
|
p_mtrk db 0 ; local variable
|
|
|
|
;-------------------------------
|
|
; switches=/k
|
|
|
|
swit_parms p_parms <swit_parmsx>
|
|
|
|
swit_parmsx dw 0 ; no positionals
|
|
db 3 ; 2 switches for now. M059 M063
|
|
dw swit_k_ctrl ; /k control
|
|
dw swit_t_ctrl ; /t control M059
|
|
dw swit_w_ctrl ; /w control M063
|
|
db 0 ; no keywords
|
|
|
|
swit_k_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows
|
|
swit_k db '/K',0
|
|
swit_t_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows M059
|
|
swit_t db '/T',0 ; M059
|
|
swit_w_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows M063
|
|
swit_w db '/W',0 ; M063
|
|
|
|
p_swit_k db 0 ; local variable
|
|
p_swit_t db 0 ; local variable M059
|
|
p_swit_w db 0 ; local variable M063
|
|
|
|
;-------------------------------
|
|
|
|
; DOS = [ high | low ]
|
|
|
|
dos_parms p_parms <dos_parmsx>
|
|
|
|
dos_parmsx db 1 ; min parameters
|
|
db 2 ; max parameters
|
|
dw dos_pos ;
|
|
dw dos_pos ;
|
|
db 0 ; no switches
|
|
db 0 ; no keywords
|
|
|
|
dos_pos p_pos <2000h,0,result_val,dos_strings> ; simple string
|
|
p_pos <2000h,0,result_val,dos_strings> ; simple string
|
|
|
|
dos_strings label byte
|
|
db 3 ; signals that there is a string choice
|
|
db 0 ; no range definition
|
|
db 0 ; no numeric values choice
|
|
db 4 ; 4 strings for choice
|
|
db 1 ; the 1st string tag
|
|
dw hi_string
|
|
db 2 ; the 2nd string tag
|
|
dw lo_string
|
|
db 3
|
|
dw umb_string
|
|
db 4
|
|
dw noumb_string
|
|
|
|
hi_string db "HIGH",0
|
|
lo_string db "LOW",0
|
|
umb_string db "UMB",0
|
|
noumb_string db "NOUMB",0
|
|
|
|
p_dos_hi db 0 ; local variable
|
|
; BUGBUG : I dont know whether PARSER uses
|
|
; this variable or not
|
|
|
|
|
|
|
|
;******************************************************************************
|
|
|
|
public DevEntry
|
|
|
|
DevSize dw ? ; size of the device driver being loaded(paras)
|
|
DevLoadAddr dw ? ; Mem addr where the device driver is 2 b loaded
|
|
DevLoadEnd dw ? ; MaxAddr to which device can be loaded
|
|
DevEntry dd ? ; Entry point to the device driver
|
|
DevBrkAddr dd ? ; Break address of the device driver
|
|
;
|
|
DevUMB db 0 ; byte indicating whether to load DDs in UMBs
|
|
DevUMBAddr dw 0 ; cuurent UMB used fro loading devices (paras)
|
|
DevUMBSize dw 0 ; Size of the current UMB being used (paras)
|
|
DevUMBFree dw 0 ; Start of free are in the current UMB (paras)
|
|
;
|
|
DevXMSAddr dd ?
|
|
;
|
|
DevExecAddr dw ? ; Device load address parameter to Exec call
|
|
DevExecReloc dw ? ; Device load relocation factor
|
|
;
|
|
DeviceHi db 0 ; Flag indicating whther the current device
|
|
; is being loaded into UMB
|
|
DevSizeOption dw ? ; SIZE= option
|
|
;
|
|
Int12Lied db 0 ; did we trap int 12 ?
|
|
OldInt12Mem dw ? ; value in 40:13h (int 12 ram)
|
|
ThreeComName db 'PROTMAN$' ; 3Com Device name
|
|
;
|
|
FirstUMBLinked db 0
|
|
DevDOSData dw ? ; segment of DOS Data
|
|
DevCmdLine dd ? ; Current Command line
|
|
DevSavedDelim db ? ; The delimiter which was replaced with null
|
|
; to use the file name in the command line
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : doconf
|
|
;
|
|
; Config file is parsed intitially with this routine. For the
|
|
; Subsequent passes 'multi_pass' entry is used .
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
doconf proc near
|
|
push cs
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
mov ax,(char_oper shl 8) ;get switch character
|
|
int 21h
|
|
mov [command_line+1],dl ; set in default command line
|
|
|
|
mov dx,offset config ;now pointing to file description
|
|
mov ax,open shl 8 ;open file "config.sys"
|
|
stc ;in case of int 24
|
|
int 21h ;function request
|
|
jnc noprob ; brif opened okay
|
|
mov multi_pass_id,11 ; set it to unreasonable number
|
|
ret
|
|
noprob: ;get file size (note < 64k!!)
|
|
mov bx,ax
|
|
xor cx,cx
|
|
xor dx,dx
|
|
mov ax,(lseek shl 8) or 2
|
|
int 21h
|
|
mov [count],ax
|
|
|
|
xor dx,dx
|
|
mov ax,lseek shl 8 ;reset pointer to beginning of file
|
|
int 21h
|
|
|
|
mov dx,[confbot] ;use current confbot value
|
|
mov ax,[count]
|
|
mov [config_size],ax ;save the size of config.sys file.
|
|
call pararound
|
|
sub dx,ax
|
|
sub dx,11h ;room for header
|
|
mov [confbot],dx ; config starts here. new conbot value.
|
|
call tempcds ; finally get cds to "safe" location
|
|
assume ds:nothing,es:nothing
|
|
|
|
mov dx,[confbot]
|
|
mov ds,dx
|
|
mov es,dx
|
|
xor dx,dx
|
|
mov cx,[count]
|
|
mov ah,read
|
|
stc ;in case of int 24
|
|
int 21h ;function request
|
|
pushf
|
|
|
|
; find the eof mark in the file. if present,then trim length.
|
|
|
|
push ax
|
|
push di
|
|
push cx
|
|
mov al,1ah ; eof mark
|
|
mov di,dx ; point ro buffer
|
|
jcxz puteol ; no chars
|
|
repnz scasb ; find end
|
|
jnz puteol ; none found and count exahusted
|
|
|
|
; we found a 1a. back up
|
|
|
|
dec di ; backup past 1a
|
|
|
|
; just for the halibut,stick in an extra eol
|
|
|
|
puteol:
|
|
mov al,cr
|
|
stosb
|
|
mov al,lf
|
|
stosb
|
|
sub di,dx ; difference moved
|
|
mov count,di ; new count
|
|
|
|
pop cx
|
|
pop di
|
|
pop ax
|
|
|
|
push cs
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
push ax
|
|
mov ah,close
|
|
int 21h
|
|
pop ax
|
|
popf
|
|
jc conferr ;if not we've got a problem
|
|
cmp cx,ax
|
|
jz getcom ;couldn't read the file
|
|
|
|
conferr:
|
|
mov dx,offset config ;want to print config error
|
|
call badfil
|
|
endconv:
|
|
ret
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; entry : multi_pass
|
|
;
|
|
; called to execute device=,install= commands
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
multi_pass:
|
|
push cs
|
|
pop ds
|
|
|
|
cmp multi_pass_id,10
|
|
jae endconv ; do nothing. just return.
|
|
|
|
push confbot
|
|
pop es ; es -> confbot
|
|
|
|
mov si,org_count
|
|
mov count,si ; set count
|
|
xor si,si
|
|
mov chrptr,si ; reset chrptr,linecount
|
|
mov linecount,si
|
|
call getchr
|
|
jmp short conflp
|
|
|
|
getcom:
|
|
call organize ;organize the file
|
|
call getchr
|
|
|
|
conflp: jc endconv
|
|
|
|
;*** call reset_dos_version ; still need to reset version even ibmdos handles this through
|
|
;*** ; function 4bh call,since ibmdos does not know when load/overlay call finishes.
|
|
|
|
inc linecount ; increase linecount.
|
|
mov multdeviceflag,0 ; reset multdeviceflag.
|
|
mov setdevmarkflag,0 ; reset setdevmarkflag.
|
|
cmp al,lf ; linefeed?
|
|
je blank_line ; then ignore this line.
|
|
|
|
mov ah,al
|
|
call getchr
|
|
jnc tryi
|
|
|
|
cmp multi_pass_id,2
|
|
jae endconv ;do not show badop again for multi_pass.
|
|
jmp badop
|
|
|
|
coff: push cs
|
|
pop ds
|
|
call newline
|
|
jmp conflp
|
|
|
|
blank_line:
|
|
call getchr
|
|
jmp conflp
|
|
|
|
coff_p:
|
|
push cs
|
|
pop ds
|
|
|
|
|
|
;to handle install= commands,we are going to use multi-pass.
|
|
;the first pass handles the other commands and only set install_flag when
|
|
;it finds any install command. the second pass will only handle the
|
|
;install= command.
|
|
|
|
;------------------------------------------------------------------------------
|
|
;install command
|
|
;------------------------------------------------------------------------------
|
|
tryi:
|
|
cmp multi_pass_id,0 ; the initial pass for DOS=HI
|
|
je multi_try_doshi
|
|
|
|
cmp multi_pass_id,2 ; the second pass was for ifs=
|
|
je coff ; now it is NOPs
|
|
; This pass can be made use of if
|
|
; we want do some config.sys process
|
|
; after device drivers are loaded
|
|
; and before install= commands
|
|
; are processed
|
|
|
|
cmp multi_pass_id,3 ; the third pass for install= ?
|
|
je multi_try_i
|
|
cmp ah, 'H'
|
|
je coff
|
|
cmp ah, 'E'
|
|
je coff
|
|
cmp ah,'I' ; install= command?
|
|
jne tryb ; the first pass is for normal operation.
|
|
or install_flag,have_install_cmd ; set the flag
|
|
jmp coff ; and handles the next command
|
|
|
|
multi_try_i:
|
|
cmp ah,'I' ; install= command?
|
|
jne multi_pass_filter ; no. ignore this.
|
|
call do_install_exec ;install it.
|
|
jmp coff ;to handle next install= command.
|
|
|
|
multi_pass_filter:
|
|
cmp ah,'Y' ; comment?
|
|
je multi_pass_adjust
|
|
cmp ah,'Z' ; bad command?
|
|
je multi_pass_adjust
|
|
cmp ah,'0' ; rem?
|
|
jne coff ; ignore the rest of the commands.
|
|
|
|
multi_pass_adjust: ; these commands need to
|
|
dec chrptr ; adjust chrptr,count
|
|
inc count ; for newline proc.
|
|
|
|
multi_pass_coff:
|
|
jmp coff ; to handle next install= commands.
|
|
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; DOS=HIGH/LOW command
|
|
;
|
|
; EchoConfig command turns on con echo for config processing
|
|
; NTVDM 14-Aug-1992 Jonle
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
multi_try_doshi:
|
|
cmp ah, 'H'
|
|
je it_is_h
|
|
cmp ah, 'E'
|
|
jne multi_pass_filter
|
|
|
|
mov cs:bEchoConfig, ah ; init console
|
|
CMDSVC SVC_CMDINITCONSOLE
|
|
jmp coff
|
|
|
|
|
|
it_is_h: ; M003 - removed initing DevUMB
|
|
; & runhigh
|
|
mov di,offset dos_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
h_do_parse:
|
|
call sysinit_parse
|
|
jnc h_parse_ok ; parse error
|
|
h_badparm:
|
|
call badparm_p ; show message and end the serach loop.
|
|
jmp short h_end
|
|
|
|
h_parse_ok:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz h_end ; then end the $endloop
|
|
call ProcDOS
|
|
jmp short h_do_parse
|
|
h_end:
|
|
jmp coff
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; buffer command
|
|
;------------------------------------------------------------------------------
|
|
;*******************************************************************************
|
|
; *
|
|
; function: parse the parameters of buffers= command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; buffers set *
|
|
; buffer_slash_x flag set if /x option chosen. *
|
|
; h_buffers set if secondary buffer cache specified. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di points to buf_parms; /*parse control definition*/ *
|
|
; set dx,cx to 0; *
|
|
; reset buffer_slash_x; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; if (result_val.$p_synonym_ptr == slash_e) then /*not a switch *
|
|
; buffer_slash_x = 1 *
|
|
; else if (cx == 1) then /* first positional */ *
|
|
; buffers = result_val.$p_picked_val; *
|
|
; else h_buffers = result_val.$p_picked_val; *
|
|
; else {show error message;error exit} *
|
|
; }; *
|
|
; if (buffer_slash_x is off & buffers > 99) then show_error; *
|
|
; }; *
|
|
; *
|
|
;*******************************************************************************
|
|
|
|
tryb:
|
|
cmp ah,'B'
|
|
jnz tryc
|
|
|
|
; NTVDM - buffers command is ignored
|
|
; 15-Aug-1992 Jonle
|
|
jmp coff
|
|
|
|
if 0
|
|
mov p_buffer_slash_x,0
|
|
mov di,offset buf_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
|
|
do7:
|
|
call sysinit_parse
|
|
jnc if7 ; parse error,
|
|
call badparm_p ; and show messages and end the search loop.
|
|
jmp short sr7
|
|
|
|
if7:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en7 ; then jmp to $endloop for semantic check
|
|
cmp result_val.$p_synonym_ptr,offset switch_x
|
|
jnz if11
|
|
|
|
; mov p_buffer_slash_x,1 ; set the flag M016
|
|
jmp short en11
|
|
|
|
if11:
|
|
mov ax,word ptr result_val.$p_picked_val
|
|
cmp cx,1
|
|
jnz if13
|
|
|
|
mov p_buffers,ax
|
|
jmp short en11
|
|
|
|
if13:
|
|
mov p_h_buffers,ax
|
|
en11:
|
|
jmp do7
|
|
|
|
en7:
|
|
cmp p_buffers,99
|
|
jbe if18
|
|
; cmp p_buffer_slash_x,0 ; M016
|
|
; jnz if18
|
|
|
|
call badparm_p
|
|
mov p_h_buffers,0
|
|
jmp short sr7
|
|
|
|
if18:
|
|
mov ax,p_buffers ; we don't have any problem.
|
|
mov buffers,ax ; now,let's set it really.
|
|
|
|
mov ax,p_h_buffers
|
|
mov h_buffers,ax
|
|
|
|
; mov al,p_buffer_slash_x ; M016
|
|
; mov buffer_slash_x,al
|
|
|
|
mov ax,linecount
|
|
mov buffer_linenum,ax ; save the line number for the future use.
|
|
|
|
sr7:
|
|
jmp coff
|
|
endif
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; break command
|
|
;------------------------------------------------------------------------------
|
|
;****************************************************************************
|
|
; *
|
|
; function: parse the parameters of break = command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; turn the control-c check on or off. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di to brk_parms; *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; if (result_val.$p_item_tag == 1) then /*on */ *
|
|
; set p_ctrl_break,on; *
|
|
; else /*off */ *
|
|
; set p_ctrl_break,off; *
|
|
; else {show message;error_exit}; *
|
|
; }; *
|
|
; if (no error) then *
|
|
; dos function call to set ctrl_break check according to *
|
|
; }; *
|
|
; *
|
|
;****************************************************************************
|
|
|
|
tryc:
|
|
cmp ah,'C'
|
|
jnz trym
|
|
mov di,offset brk_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
do22:
|
|
call sysinit_parse
|
|
jnc if22 ; parse error
|
|
call badparm_p ; show message and end the serach loop.
|
|
jmp short sr22
|
|
|
|
if22:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en22 ; then end the $endloop
|
|
cmp result_val.$p_item_tag,1
|
|
jnz if26
|
|
|
|
mov p_ctrl_break,1 ; turn it on
|
|
jmp short en26
|
|
|
|
if26:
|
|
mov p_ctrl_break,0 ; turn it off
|
|
en26:
|
|
jmp short do22 ; we actually set the ctrl break
|
|
|
|
en22:
|
|
mov ah,set_ctrl_c_trapping ; if we don't have any parse error.
|
|
mov al,1
|
|
mov dl,p_ctrl_break
|
|
int 21h
|
|
sr22:
|
|
jmp coff
|
|
|
|
;------------------------------------------------------------------------------
|
|
; multitrack command
|
|
;------------------------------------------------------------------------------
|
|
;******************************************************************************
|
|
; *
|
|
; function: parse the parameters of multitrack= command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; turn multrk_flag on or off. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di to brk_parms; *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; if (result_val.$p_item_tag == 1) then /*on */ *
|
|
; set p_mtrk,on; *
|
|
; else /*off */ *
|
|
; set p_mtrk,off; *
|
|
; else {show message;error_exit}; *
|
|
; }; *
|
|
; if (no error) then *
|
|
; dos function call to set multrk_flag according to p_mtrk. *
|
|
; *
|
|
; }; *
|
|
; *
|
|
;******************************************************************************
|
|
|
|
trym:
|
|
cmp ah,'M'
|
|
jnz tryu
|
|
|
|
mov di,offset mtrk_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
do31:
|
|
call sysinit_parse
|
|
jnc if31 ; parse error
|
|
call badparm_p ; show message and end the serach loop.
|
|
jmp short sr31
|
|
if31:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en31 ; then end the $endloop
|
|
|
|
cmp result_val.$p_item_tag,1
|
|
jnz if35
|
|
|
|
mov p_mtrk,1 ; turn it on temporarily.
|
|
jmp short en35
|
|
|
|
if35:
|
|
mov p_mtrk,0 ; turn it off temporarily.
|
|
en35:
|
|
jmp short do31 ; we actually set the multrk_flag here
|
|
|
|
en31:
|
|
push ds
|
|
mov ax,Bios_Data
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
|
|
cmp p_mtrk,0
|
|
jnz if39
|
|
|
|
mov multrk_flag,multrk_off2 ; 0001h
|
|
jmp short en39
|
|
|
|
if39:
|
|
mov multrk_flag,multrk_on ; 8000h
|
|
en39:
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
sr31:
|
|
jmp coff
|
|
|
|
|
|
;
|
|
;-----------------------------------------------------------------------------
|
|
; devicehigh command
|
|
;-----------------------------------------------------------------------------
|
|
;
|
|
assume ds:nothing
|
|
tryu:
|
|
cmp ah, 'U'
|
|
jne tryd
|
|
mov badparm_off, si ; stash it there in case of an error
|
|
mov badparm_seg, es
|
|
call ParseSize ; process the size= option
|
|
jnc @f
|
|
call badparm_p
|
|
jmp coff
|
|
@@:
|
|
push si
|
|
push es
|
|
@@:
|
|
mov al, es:[si]
|
|
cmp al, cr
|
|
je @f
|
|
cmp al, lf
|
|
je @f
|
|
call delim
|
|
jz @f
|
|
inc si
|
|
jmp @b
|
|
@@:
|
|
mov DevSavedDelim, al ; Save the delimiter before replacing
|
|
; it with null
|
|
mov byte ptr es:[si], 0
|
|
pop es
|
|
pop si
|
|
|
|
mov DeviceHi, 0
|
|
cmp DevUMB, 0 ; do we support UMBs
|
|
je LoadDevice ; no, we don't
|
|
mov DeviceHi, 1
|
|
jmp short LoadDevice
|
|
;
|
|
;------------------------------------------------------------------------------
|
|
; device command
|
|
;------------------------------------------------------------------------------
|
|
|
|
assume ds:nothing
|
|
tryd:
|
|
cmp ah,'D'
|
|
jz gotd
|
|
jmp tryq
|
|
gotd:
|
|
mov DeviceHi, 0 ; not to be loaded in UMB ;M007
|
|
mov DevSizeOption, 0
|
|
mov DevSavedDelim, ' ' ; In case of DEVICE= the null has to
|
|
; be replaced with a ' '
|
|
|
|
LoadDevice:
|
|
mov bx,cs ;device= or devicehigh= command.
|
|
mov ds,bx
|
|
|
|
mov word ptr [bpb_addr],si ; pass the command line to the dvice
|
|
mov word ptr [bpb_addr+2],es
|
|
|
|
mov word ptr DevCmdLine, si ; save it for ourself
|
|
mov word ptr DevCmdLine+2, es
|
|
|
|
call round
|
|
|
|
call SizeDevice
|
|
jc BadFile
|
|
|
|
call InitDevLoad
|
|
|
|
mov ax, DevLoadAddr
|
|
add ax, DevSize
|
|
jc NoMem
|
|
cmp DevLoadEnd, ax
|
|
jae LoadDev
|
|
|
|
NoMem:
|
|
jmp mem_err
|
|
|
|
BadFile:
|
|
cmp byte ptr es:[si], cr
|
|
jne @f
|
|
jmp badop
|
|
@@:
|
|
call badload
|
|
jmp coff
|
|
|
|
LoadDev:
|
|
push es
|
|
pop ds
|
|
assume ds:nothing
|
|
mov dx,si ;ds:dx points to file name
|
|
|
|
if noexec
|
|
les bx,dword ptr cs:[memlo]
|
|
call ldfil ;load in the device driver
|
|
|
|
else
|
|
|
|
call ExecDev ; load device driver using exec call
|
|
|
|
endif
|
|
|
|
badldreset:
|
|
push ds
|
|
pop es ;es:si back to config.sys
|
|
push cs
|
|
pop ds ;ds back to sysinit
|
|
jc BadFile
|
|
goodld:
|
|
push es
|
|
push si ; ???
|
|
|
|
call RemoveNull
|
|
|
|
push es
|
|
push si
|
|
|
|
push cs
|
|
pop es
|
|
|
|
|
|
;NTVDM: block device drivers are not supported.
|
|
; Putup user warning popup for unsupported device driver
|
|
; 29-Sep-1992 Jonle
|
|
;
|
|
push ds
|
|
push si
|
|
lds si, DevEntry ; peek the header attribute
|
|
test word ptr ds:[si.sdevatt],devtyp ; IS block device driver?
|
|
pop si
|
|
pop ds
|
|
jnz got_device_com_cont ; no!
|
|
|
|
pop si ;clear the stack
|
|
pop es
|
|
|
|
mov ax, NOSUPPORT_DRIVER
|
|
BOP BOP_NOSUPPORT
|
|
jmp short erase_dev_do
|
|
|
|
got_device_com_cont:
|
|
|
|
call LieInt12Mem
|
|
call UpdatePDB ; update the PSP:2 value M020
|
|
|
|
cmp cs:multdeviceflag, 0 ; Pass limit only for the 1st device
|
|
; driver in the file ; M027
|
|
jne skip_pass_limit ; ; M027
|
|
|
|
mov word ptr break_addr, 0 ; pass the limit to the DD
|
|
mov bx, DevLoadEnd
|
|
mov word ptr break_addr+2, bx
|
|
skip_pass_limit: ; M027
|
|
mov bx,sdevstrat
|
|
call calldev ; calldev (sdevstrat);
|
|
mov bx,sdevint
|
|
call calldev ; calldev (sdevint);
|
|
|
|
call TrueInt12Mem
|
|
|
|
mov ax, word ptr break_addr ; move break addr from the req packet
|
|
mov word ptr DevBrkAddr, ax
|
|
mov ax, word ptr break_addr+2
|
|
mov word ptr DevBrkAddr+2, ax
|
|
|
|
assume ds:nothing
|
|
|
|
cmp DevUMB, 0
|
|
jz @f
|
|
call AllocUMB
|
|
@@:
|
|
|
|
;
|
|
;------ If we are waiting to be moved into hma lets try it now !!!
|
|
;
|
|
cmp runhigh, 0ffh
|
|
jne @f
|
|
|
|
call TryToMovDOSHi ; move DOS into HMA if reqd
|
|
@@:
|
|
|
|
pop si
|
|
pop ds
|
|
mov byte ptr [si],0 ; *p = 0;
|
|
|
|
push cs
|
|
pop ds
|
|
|
|
jmp short was_device_com
|
|
|
|
|
|
erase_dev_do: ; modified to show message "error in config.sys..."
|
|
pop si
|
|
pop es
|
|
|
|
push cs
|
|
pop ds
|
|
|
|
; test [setdevmarkflag],setbrkdone ;if already set_break is done,
|
|
; jnz skip1_resetmemhi ; then do not
|
|
; dec [memhi] ;adjust memhi by a paragrah of devmark.
|
|
|
|
skip1_resetmemhi:
|
|
cmp configmsgflag,0
|
|
je no_error_line_msg
|
|
|
|
call error_line ; no "error in config.sys" msg for device driver. dcr d493
|
|
mov configmsgflag,0 ;set the default value again.
|
|
|
|
no_error_line_msg:
|
|
jmp coff
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
was_device_com:
|
|
mov ax,word ptr [DevBrkAddr+2]
|
|
cmp ax,DevLoadEnd
|
|
jbe breakok
|
|
|
|
pop si
|
|
pop es
|
|
jmp BadFile
|
|
|
|
breakok:
|
|
lds si,DevEntry ;ds:si points to header
|
|
les di,cs:[dosinfo] ;es:di point to dos info
|
|
mov ax,ds:[si.sdevatt] ;ax Dev attributes
|
|
;
|
|
;------ lets deal with character devices,
|
|
; NTVDM: removed check for block drivers, jonle
|
|
;
|
|
ischardev:
|
|
or cs:[setdevmarkflag],for_devmark
|
|
call DevSetBreak ; go ahead and alloc mem for device
|
|
jc erase_dev_do ;device driver's init routine failed.
|
|
|
|
test ax,iscin ;is it a console in?
|
|
jz tryclk
|
|
|
|
mov word ptr es:[di.sysi_con],si
|
|
mov word ptr es:[di.sysi_con+2],ds
|
|
|
|
tryclk: test ax,isclock ;is it a clock device?
|
|
jz linkit
|
|
|
|
mov word ptr es:[di+sysi_clock],si
|
|
mov word ptr es:[di+sysi_clock+2],ds
|
|
|
|
linkit:
|
|
|
|
mov cx,word ptr es:[di.sysi_dev] ;dx:cx = head of list
|
|
mov dx,word ptr es:[di.sysi_dev+2]
|
|
|
|
mov word ptr es:[di.sysi_dev],si ;set head of list in dos
|
|
mov word ptr es:[di.sysi_dev+2],ds
|
|
mov ax,ds:[si] ;get pointer to next device
|
|
mov word ptr cs:[DevEntry],ax ;and save it
|
|
|
|
mov word ptr ds:[si],cx ;link in the driver
|
|
mov word ptr ds:[si+2],dx
|
|
|
|
enddev:
|
|
pop si
|
|
pop es
|
|
inc ax ;ax = ffff (no more devs if yes)?
|
|
jz coffj3
|
|
|
|
inc cs:multdeviceflag ; possibly multiple device driver.
|
|
call DevBreak ; M009
|
|
jmp goodld ; otherwise pretend we loaded it in
|
|
|
|
coffj3: mov cs:multdeviceflag,0 ; reset the flag
|
|
call DevBreak
|
|
jmp coff
|
|
|
|
bad_bpb_size_sector:
|
|
pop si
|
|
pop es
|
|
mov dx,offset badsiz_pre
|
|
mov bx,offset crlfm
|
|
call prnerr
|
|
|
|
; test [setdevmarkflag],setbrkdone ;if already set_break is done,
|
|
; jnz skip2_resetmemhi ; then do not
|
|
; dec [memhi] ;adjust memhi by a paragrah of devmark.
|
|
|
|
skip2_resetmemhi:
|
|
jmp coff
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; country command
|
|
; the syntax is:
|
|
; country=country id {,codepage {,path}}
|
|
; country=country id {,,path} :default codepage id in dos
|
|
;------------------------------------------------------------------------------
|
|
|
|
tryq:
|
|
cmp ah,'Q'
|
|
jz tryq_cont
|
|
jmp tryf
|
|
tryq_cont:
|
|
|
|
mov cntry_drv,0 ; reset the drive,path to default value.
|
|
mov p_code_page,0
|
|
mov di,offset cntry_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
do52:
|
|
call sysinit_parse
|
|
jnc if52 ; parse error,check error code and
|
|
|
|
call cntry_error ; show message and end the search loop.
|
|
mov p_cntry_code,-1 ; signals that parse error.
|
|
jmp short sr52
|
|
|
|
if52:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz sr52 ; then end the search loop
|
|
|
|
cmp result_val.$p_type,$p_number ; numeric?
|
|
jnz if56
|
|
|
|
mov ax,word ptr result_val.$p_picked_val
|
|
cmp cx,1
|
|
jnz if57
|
|
|
|
mov p_cntry_code,ax
|
|
jmp short en57
|
|
|
|
if57:
|
|
mov p_code_page,ax
|
|
en57:
|
|
jmp short en56 ; path entered
|
|
|
|
if56:
|
|
push ds
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
push cs
|
|
pop es
|
|
|
|
lds si,rv_dword ; move the path to known place.
|
|
mov di,offset cntry_drv
|
|
call move_asciiz
|
|
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop ds
|
|
|
|
en56:
|
|
jmp do52
|
|
|
|
sr52:
|
|
cmp p_cntry_code,-1 ; had a parse error?
|
|
jne tryq_open
|
|
jmp coff
|
|
|
|
tryqbad: ;"invalid country code or code page"
|
|
stc
|
|
mov dx,offset badcountry
|
|
jmp tryqchkerr
|
|
|
|
tryq_open:
|
|
cmp cntry_drv,0
|
|
je tryq_def
|
|
mov dx,offset cntry_drv
|
|
jmp short tryq_openit
|
|
|
|
tryq_def:
|
|
mov dx,offset cntry_root
|
|
tryq_openit:
|
|
mov ax,3d00h ;open a file
|
|
stc
|
|
int 21h
|
|
jc tryqfilebad ;open failure
|
|
|
|
mov cs:cntryfilehandle,ax ;save file handle
|
|
mov bx,ax
|
|
mov ax,cs:p_cntry_code
|
|
mov dx,cs:p_code_page ; now,ax=country id,bx=filehandle
|
|
mov cx,cs:[memhi]
|
|
add cx,384 ; need 6k buffer to handle country.sys
|
|
; M023
|
|
cmp cx,cs:[alloclim]
|
|
ja tryqmemory ;cannot allocate the buffer for country.sys
|
|
|
|
mov si,offset cntry_drv ;ds:si -> cntry_drv
|
|
cmp byte ptr [si],0 ;default path?
|
|
jne tryq_set_for_dos
|
|
|
|
inc si
|
|
inc si ;ds:si -> cntry_root
|
|
|
|
tryq_set_for_dos:
|
|
les di,cs:sysi_country ;es:di -> country info tab in dos
|
|
push di ;save di
|
|
add di,ccpath_countrysys
|
|
call move_asciiz ;set the path to country.sys in dos.
|
|
pop di ;es:di -> country info tab again.
|
|
|
|
mov cx,cs:[memhi]
|
|
mov ds,cx
|
|
xor si,si ;ds:si -> 2k buffer to be used.
|
|
call setdoscountryinfo ;now do the job!!!
|
|
jnc tryqchkerr ;read error or could not find country,code page combination
|
|
|
|
cmp cx,-1 ;could not find matching country_id,code page?
|
|
je tryqbad ;then "invalid country code or code page"
|
|
|
|
tryqfilebad:
|
|
push cs
|
|
pop es
|
|
cmp cs:cntry_drv,0 ;is the default file used?
|
|
je tryqdefbad
|
|
|
|
mov si,offset cntry_drv
|
|
jmp short tryqbadload
|
|
|
|
tryqdefbad: ;default file has been used.
|
|
mov si,offset cntry_root ;es:si -> \country.sys in sysinit_seg
|
|
tryqbadload:
|
|
call badload ;ds will be restored to sysinit_seg
|
|
mov cx,cs:[confbot]
|
|
mov es,cx ;restore es -> confbot.
|
|
jmp short coffj4
|
|
|
|
tryqmemory:
|
|
mov dx,offset insufmemory
|
|
tryqchkerr:
|
|
mov cx,cs:[confbot]
|
|
mov es,cx ;restore es -> confbot seg
|
|
push cs
|
|
pop ds ;retore ds to sysinit_seg
|
|
jnc coffj4 ;if no error,then exit
|
|
|
|
call print ;else show error message
|
|
call error_line
|
|
|
|
coffj4:
|
|
mov bx,cntryfilehandle
|
|
mov ah,3eh
|
|
int 21h ;close a file. don't care even if it fails.
|
|
jmp coff
|
|
|
|
cntry_error proc near
|
|
|
|
;function: show "invalid country code or code page" messages,or
|
|
; "error in country command" depending on the error code
|
|
; in ax returned by sysparse;
|
|
;in: ax - error code
|
|
; ds - sysinitseg
|
|
; es - confbot
|
|
;out: show message. dx destroyed.
|
|
|
|
cmp ax,$p_out_of_range
|
|
jnz if64
|
|
mov dx,offset badcountry ;"invalid country code or code page"
|
|
jmp short en64
|
|
|
|
if64:
|
|
mov dx,offset badcountrycom ;"error in contry command"
|
|
en64:
|
|
call print
|
|
call error_line
|
|
ret
|
|
cntry_error endp
|
|
|
|
;------------------------------------------------------------------------------
|
|
; files command
|
|
;------------------------------------------------------------------------------
|
|
;*******************************************************************************
|
|
; function: parse the parameters of files= command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; variable files set. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di points to files_parms; *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; files = result_val.$p_picked_val *
|
|
; else *
|
|
; error exit; *
|
|
; }; *
|
|
; }; *
|
|
; *
|
|
;*******************************************************************************
|
|
tryf:
|
|
cmp ah,'F'
|
|
jnz tryl
|
|
|
|
mov di,offset files_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
|
|
do67:
|
|
call sysinit_parse
|
|
jnc if67 ; parse error
|
|
call badparm_p ; and show messages and end the search loop.
|
|
jmp short sr67
|
|
|
|
if67:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en67 ; then end the $endloop
|
|
mov al,byte ptr result_val.$p_picked_val
|
|
mov p_files,al ; save it temporarily
|
|
jmp short do67
|
|
|
|
en67:
|
|
mov al,p_files
|
|
SVC SVC_DEMWOWFILES ; For WOW VDM Set the file= to max.
|
|
mov files,al ; no error. really set the value now.
|
|
|
|
sr67:
|
|
jmp coff
|
|
|
|
;------------------------------------------------------------------------------
|
|
; lastdrive command
|
|
;------------------------------------------------------------------------------
|
|
;*******************************************************************************
|
|
; function: parse the parameters of lastdrive= command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; set the variable num_cds. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di points to ldrv_parms; *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; set num_cds to the returned value; *
|
|
; else /*error exit*/ *
|
|
; error exit; *
|
|
; }; *
|
|
; }; *
|
|
; *
|
|
;*******************************************************************************
|
|
|
|
tryl:
|
|
cmp ah,'L'
|
|
jnz tryp
|
|
jmp coff
|
|
|
|
;NTVDM Ignore the lastdrive command. Dos will figure this from the host OS.
|
|
; 17-Aug-1992 Jonle
|
|
if 0
|
|
|
|
mov di,offset ldrv_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
|
|
do73:
|
|
call sysinit_parse
|
|
jnc if73 ; parse error
|
|
call badparm_p ; and show messages and end the search loop.
|
|
jmp short sr73
|
|
|
|
if73:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en73 ; then end the $endloop
|
|
mov al,rv_byte ; pick up the drive number
|
|
mov p_ldrv,al ; save it temporarily
|
|
jmp do73
|
|
|
|
en73:
|
|
mov al,p_ldrv
|
|
mov num_cds,al ; no error. really set the value now.
|
|
sr73:
|
|
jmp coff
|
|
endif
|
|
|
|
|
|
;--------------------------------------------------------------------------
|
|
; setting drive parameters
|
|
;--------------------------------------------------------------------------
|
|
|
|
tryp:
|
|
cmp ah,'P'
|
|
jnz tryk
|
|
jmp coff
|
|
|
|
; sudeepb 04-Mar-1991 : Ignoring DRIVEPARM command
|
|
; call parseline
|
|
; jc trypbad
|
|
;
|
|
; call setparms
|
|
; call diddleback
|
|
; jc trypbad
|
|
; jmp coff
|
|
;trypbad:jmp badop
|
|
|
|
;--------------------------------------------------------------------------
|
|
; setting internal stack parameters
|
|
; stacks=m,n where
|
|
; m is the number of stacks (range 8 to 64,default 9)
|
|
; n is the stack size (range 32 to 512 bytes,default 128)
|
|
; j.k. 5/5/86: stacks=0,0 implies no stack installation.
|
|
; any combinations that are not within the specified limits will
|
|
; result in "unrecognized command" error.
|
|
;--------------------------------------------------------------------------
|
|
|
|
;****************************************************************************
|
|
; *
|
|
; function: parse the parameters of stacks= command. *
|
|
; the minimum value for "number of stacks" and "stack size" is *
|
|
; 8 and 32 each. in the definition of sysparse value list,they *
|
|
; are set to 0. this is for accepting the exceptional case of *
|
|
; stacks=0,0 case (,which means do not install the stack.) *
|
|
; so,after sysparse is done,we have to check if the entered *
|
|
; values (stack_count,stack_size) are within the actual range, *
|
|
; (or if "0,0" pair has been entered.) *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; set the variables stack_count,stack_size. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di points to stks_parms; *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; { if (cx == 1) then /* first positional = stack count */ *
|
|
; p_stack_count = result_val.$p_picked_val; *
|
|
; if (cx == 2) then /* second positional = stack size */ *
|
|
; p_stack_size = result_val.$p_picked_val; *
|
|
; } *
|
|
; else /*error exit*/ *
|
|
; error exit; *
|
|
; }; *
|
|
; here check p_stack_count,p_stack_size if it meets the condition; *
|
|
; if o.k.,then set stack_count,stack_size; *
|
|
; else error_exit; *
|
|
; }; *
|
|
;****************************************************************************
|
|
|
|
tryk:
|
|
cmp ah,'K'
|
|
je do_tryk
|
|
jmp trys
|
|
|
|
if stacksw
|
|
|
|
do_tryk:
|
|
mov di,offset stks_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
|
|
do79:
|
|
call sysinit_parse
|
|
jnc if79 ; parse error
|
|
|
|
mov dx,offset badstack ; "invalid stack parameter"
|
|
call print ; and show messages and end the search loop.
|
|
call error_line
|
|
jmp sr79
|
|
|
|
if79:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en79 ; then end the $endloop
|
|
|
|
mov ax,word ptr result_val.$p_picked_val
|
|
cmp cx,1
|
|
jnz if83
|
|
|
|
mov p_stack_count,ax
|
|
jmp short en83
|
|
|
|
if83:
|
|
mov p_stack_size,ax
|
|
en83:
|
|
jmp do79
|
|
|
|
en79:
|
|
cmp p_stack_count,0
|
|
jz if87
|
|
|
|
cmp p_stack_count,mincount
|
|
jb ll88
|
|
cmp p_stack_size,minsize
|
|
jnb if88
|
|
|
|
ll88:
|
|
mov p_stack_count,-1 ; invalid
|
|
if88:
|
|
jmp short en87
|
|
|
|
if87:
|
|
cmp p_stack_size,0
|
|
jz en87
|
|
mov p_stack_count,-1 ; invalid
|
|
en87:
|
|
cmp p_stack_count,-1 ; invalid?
|
|
jnz if94
|
|
|
|
mov stack_count,defaultcount ;reset to default value.
|
|
mov stack_size,defaultsize
|
|
mov word ptr stack_addr,0
|
|
|
|
mov dx,offset badstack
|
|
call print
|
|
call error_line
|
|
jmp short sr79
|
|
|
|
if94:
|
|
mov ax,p_stack_count
|
|
mov stack_count,ax
|
|
mov ax,p_stack_size
|
|
mov stack_size,ax
|
|
mov word ptr stack_addr,-1 ; stacks= been accepted.
|
|
sr79:
|
|
jmp coff
|
|
|
|
endif
|
|
|
|
;------------------------------------------------------------------------
|
|
; shell command
|
|
;------------------------------------------------------------------------
|
|
|
|
trys:
|
|
cmp ah,'S'
|
|
jnz tryx
|
|
|
|
mov [command_line+1],0
|
|
mov di,offset commnd + 1
|
|
mov [di-1],al
|
|
|
|
storeshell:
|
|
call getchr
|
|
or al,al
|
|
jz getshparms
|
|
|
|
cmp al," "
|
|
jb endsh
|
|
|
|
mov [di],al
|
|
inc di
|
|
jmp storeshell
|
|
|
|
endsh:
|
|
mov byte ptr [di],0
|
|
; push di
|
|
; mov di,offset commnd
|
|
; SVC SVC_SETSHELLNAME
|
|
; pop di
|
|
|
|
call getchr
|
|
cmp al,lf
|
|
jnz conv
|
|
|
|
call getchr
|
|
conv: jmp conflp
|
|
|
|
getshparms:
|
|
mov byte ptr [di],0
|
|
mov di,offset command_line+1
|
|
|
|
parmloop:
|
|
call getchr
|
|
cmp al," "
|
|
jb endsh
|
|
mov [di],al
|
|
inc di
|
|
jmp parmloop
|
|
|
|
;------------------------------------------------------------------------
|
|
; fcbs command
|
|
;------------------------------------------------------------------------
|
|
|
|
;************************************************************************
|
|
; function: parse the parameters of fcbs= command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; set the variables fcbs,keep. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di points to fcbs_parms; *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysparse; *
|
|
; if (no error) then *
|
|
; { if (cx == 1) then /* first positional = fcbs */ *
|
|
; fcbs = result_val.$p_picked_val; *
|
|
; if (cx == 2) then /* second positional = keep */ *
|
|
; keep = result_val.$p_picked_val; *
|
|
; } *
|
|
; else /*error exit*/ *
|
|
; error exit; *
|
|
; }; *
|
|
; }; *
|
|
;************************************************************************
|
|
|
|
tryx:
|
|
cmp ah,'X'
|
|
jnz tryy
|
|
|
|
mov di,offset fcbs_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
|
|
do98:
|
|
call sysinit_parse
|
|
jnc if98 ; parse error
|
|
call badparm_p ; and show messages and end the search loop.
|
|
jmp short sr98
|
|
|
|
if98:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en98 ; then end the $endloop
|
|
|
|
mov al,byte ptr result_val.$p_picked_val
|
|
cmp cx,1 ; the first positional?
|
|
jnz if102
|
|
mov p_fcbs,al
|
|
jmp short en102
|
|
|
|
if102:
|
|
mov p_keep,al
|
|
en102:
|
|
jmp do98
|
|
|
|
en98:
|
|
mov al,p_fcbs ; M017
|
|
mov fcbs,al ; M017
|
|
mov keep,0 ; M017
|
|
sr98:
|
|
jmp coff
|
|
|
|
;-------------------------------------------------------------------------
|
|
; comment= do nothing. just decrese chrptr,and increase count for correct
|
|
; line number
|
|
;-------------------------------------------------------------------------
|
|
|
|
tryy:
|
|
cmp ah,'Y'
|
|
jne try0
|
|
|
|
donothing:
|
|
dec chrptr
|
|
inc count
|
|
jmp coff
|
|
|
|
;------------------------------------------------------------------------
|
|
; rem command
|
|
;------------------------------------------------------------------------
|
|
|
|
try0: ;do nothing with this line.
|
|
cmp ah,'0'
|
|
je donothing
|
|
|
|
;-----------------------------------------------------------------------
|
|
; switches command
|
|
;-----------------------------------------------------------------------
|
|
;****************************************************************************
|
|
; *
|
|
; function: parse the option switches specified. *
|
|
; note - this command is intended for the future use also. when we need to *
|
|
; to set system data flag,use this command. *
|
|
; *
|
|
; input : *
|
|
; es:si -> parameters in command line. *
|
|
; output: *
|
|
; p_swit_k set if /k option chosen. *
|
|
; *
|
|
; subroutines to be called: *
|
|
; sysinit_parse *
|
|
; logic: *
|
|
; { *
|
|
; set di points to swit_parms; /*parse control definition*/ *
|
|
; set dx,cx to 0; *
|
|
; while (end of command line) *
|
|
; { sysinit_parse; *
|
|
; if (no error) then *
|
|
; if (result_val.$p_synonym_ptr == swit_k) then *
|
|
; p_swit_k = 1 *
|
|
; endif *
|
|
; else {show error message;error exit} *
|
|
; }; *
|
|
; }; *
|
|
; *
|
|
;****************************************************************************
|
|
|
|
cmp ah,'1' ;switches= command entered?
|
|
je do_try1
|
|
jmp tryt
|
|
do_try1:
|
|
mov di,offset swit_parms
|
|
xor cx,cx
|
|
mov dx,cx
|
|
|
|
do110:
|
|
call sysinit_parse
|
|
jnc if110 ; parse error
|
|
call badparm_p ; and show messages and end the search loop.
|
|
jmp short sr110
|
|
|
|
if110:
|
|
cmp ax,$p_rc_eol ; end of line?
|
|
jz en110 ; then jmp to $endloop for semantic check
|
|
|
|
cmp result_val.$p_synonym_ptr,offset swit_k
|
|
jnz if115 ; ;M059
|
|
mov p_swit_k,1 ; set the flag
|
|
jmp do110
|
|
if115: ;M059
|
|
cmp result_val.$p_synonym_ptr, offset swit_t ;M059
|
|
jne if116 ;M059 M063
|
|
mov p_swit_t, 1 ;M059
|
|
jmp do110 ;M059
|
|
if116:
|
|
cmp result_val.$p_synonym_ptr, offset swit_w ;M063
|
|
jne do110 ;M063
|
|
mov p_swit_w, 1 ;M063
|
|
jmp do110 ;M063
|
|
en110:
|
|
cmp p_swit_k,1 ;if /k entered,
|
|
|
|
push ds
|
|
mov ax,Bios_Data
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
jnz if117
|
|
mov keyrd_func,0 ;use the conventional keyboard functions
|
|
mov keysts_func,1
|
|
if117:
|
|
; mov al, p_swit_t ;M059
|
|
; mov t_switch, al ;M059
|
|
|
|
cmp p_swit_w, 0 ;M063
|
|
je skip_dos_flag ;M063
|
|
push es
|
|
push bx
|
|
mov ah, GET_IN_VARS ;M063
|
|
int 21h ;M063
|
|
or byte ptr es:[DOS_FLAG_OFFSET], SUPPRESS_WINA20 ;M063
|
|
pop bx
|
|
pop es
|
|
skip_dos_flag: ;M063
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
sr110:
|
|
jmp coff
|
|
|
|
;------------------------------------------------------------------------
|
|
; NTCMDPROMPT command. This command forces SCS functionality to use
|
|
; cmd.exe prompt rather than command.com's prompt on shelling out
|
|
; and on finding a TSR.
|
|
;------------------------------------------------------------------------
|
|
tryt:
|
|
cmp ah,'T'
|
|
je tryt_5
|
|
jmp short tryo
|
|
|
|
tryt_5:
|
|
push si
|
|
push bp
|
|
xor ax,ax
|
|
mov bp,ax
|
|
mov si,ax
|
|
mov al,4
|
|
mov ah,setdpb
|
|
int 21h
|
|
pop bp
|
|
pop si
|
|
jmp coff
|
|
|
|
;------------------------------------------------------------------------
|
|
; DOSONLY command. This command forces only DOS binaries to run from
|
|
; command.com prompt. non_dos binaries will putup the stub message
|
|
; of unable to run it under DOS.
|
|
;------------------------------------------------------------------------
|
|
tryo:
|
|
cmp ah,'O'
|
|
je tryo_5
|
|
jmp short tryz
|
|
|
|
tryo_5:
|
|
push si
|
|
push bp
|
|
xor ax,ax
|
|
mov bp,ax
|
|
mov si,ax
|
|
mov al,6
|
|
mov ah,setdpb
|
|
int 21h
|
|
pop bp
|
|
pop si
|
|
jmp coff
|
|
|
|
;------------------------------------------------------------------------
|
|
; bogus command
|
|
;------------------------------------------------------------------------
|
|
|
|
tryz:
|
|
cmp ah,0ffh
|
|
je tryff
|
|
|
|
dec chrptr
|
|
inc count
|
|
jmp short badop
|
|
|
|
;------------------------------------------------------------------------
|
|
; null command
|
|
;------------------------------------------------------------------------
|
|
|
|
tryff: ;skip this command.
|
|
jmp donothing
|
|
|
|
doconf endp
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
sysinit_parse proc
|
|
;set up registers for sysparse
|
|
;in) es:si -> command line in confbot
|
|
; di -> offset of the parse control defintion.
|
|
;
|
|
;out) calls sysparse.
|
|
; carry will set if parse error.
|
|
; *** the caller should check the eol condition by looking at ax
|
|
; *** after each call.
|
|
; *** if no parameters are found,then ax will contain a error code.
|
|
; *** if the caller needs to look at the synomym@ of the result,
|
|
; *** the caller should use cs:@ instead of es:@.
|
|
; cx register should be set to 0 at the first time the caller calls this
|
|
; procedure.
|
|
; ax - exit code
|
|
; bl - terminated delimeter code
|
|
; cx - new positional ordinal
|
|
; si - set to pase scanned operand
|
|
; dx - selected result buffer
|
|
|
|
push es ;save es,ds
|
|
push ds
|
|
|
|
push es
|
|
pop ds ;now ds:si -> command line
|
|
|
|
push cs
|
|
pop es ;now es:di -> control definition
|
|
|
|
mov cs:badparm_seg,ds ;save the pointer to the parm
|
|
mov cs:badparm_off,si ; we are about to parse for badparm msg.
|
|
mov dx,0
|
|
call sysparse
|
|
cmp ax,$p_no_error ;no error
|
|
|
|
;**cas note: when zero true after cmp, carry clear
|
|
|
|
jz ll4
|
|
cmp ax,$p_rc_eol ;or the end of line?
|
|
jnz if4
|
|
|
|
ll4:
|
|
clc
|
|
jmp short en4
|
|
|
|
if4:
|
|
stc
|
|
en4:
|
|
pop ds
|
|
pop es
|
|
ret
|
|
sysinit_parse endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : badop_p
|
|
;
|
|
; same thing as badop,but will make sure to set ds register back
|
|
; to sysinitseg and return back to the caller.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
badop_p proc near
|
|
|
|
|
|
push cs
|
|
pop ds ;set ds to configsys seg.
|
|
mov dx,offset badopm
|
|
call print
|
|
call error_line
|
|
ret
|
|
|
|
badop_p endp
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; label : badop
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
badop: mov dx,offset badopm ;want to print command error "unrecognized command..."
|
|
call print
|
|
call error_line ;show "error in config.sys ..." .
|
|
jmp coff
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : badparm_p
|
|
;
|
|
; show "bad command or parameters - xxxxxx"
|
|
; in badparm_seg,badparm_off -> xxxxx
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
badparm_p proc near
|
|
|
|
|
|
push ds
|
|
push dx
|
|
push si
|
|
|
|
push cs
|
|
pop ds
|
|
|
|
mov dx,offset badparm
|
|
call print ;"bad command or parameters - "
|
|
lds si,badparm_ptr
|
|
|
|
; print "xxxx" until cr.
|
|
|
|
do1:
|
|
mov dl,byte ptr [si] ; get next character
|
|
cmp dl,cr ; is a carriage return?
|
|
jz en1 ; exit loop if so
|
|
|
|
mov ah,std_con_output ; function 2
|
|
int 21h ; display character
|
|
inc si ; next character
|
|
jmp do1
|
|
en1:
|
|
push cs
|
|
pop ds
|
|
|
|
mov dx,offset crlfm
|
|
call print
|
|
call error_line
|
|
|
|
pop si
|
|
pop dx
|
|
pop ds
|
|
badparmp_ret:
|
|
ret
|
|
badparm_p endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : getchr
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
getchr proc near
|
|
push cx
|
|
mov cx,count
|
|
jcxz nochar
|
|
|
|
mov si,chrptr
|
|
mov al,es:[si]
|
|
dec count
|
|
inc chrptr
|
|
clc
|
|
get_ret:
|
|
pop cx
|
|
ret
|
|
|
|
nochar: stc
|
|
jmp short get_ret
|
|
getchr endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : incorrect_order
|
|
;
|
|
; show "incorrect order in config.sys ..." message.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
incorrect_order proc near
|
|
|
|
mov dx,offset badorder
|
|
call print
|
|
call showlinenum
|
|
ret
|
|
|
|
incorrect_order endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : error_line
|
|
;
|
|
; show "error in config.sys ..." message.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
public error_line
|
|
error_line proc near
|
|
|
|
|
|
push cs
|
|
pop ds
|
|
mov dx,offset errorcmd
|
|
call print
|
|
call showlinenum
|
|
ret
|
|
|
|
error_line endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : showlinenum
|
|
;
|
|
; convert the binary linecount to decimal ascii string in showcount
|
|
;and display showcount at the current curser position.
|
|
;in.) linecount
|
|
;
|
|
;out) the number is printed.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
showlinenum proc near
|
|
|
|
|
|
push es
|
|
push ds
|
|
push di
|
|
|
|
push cs
|
|
pop es ; es=cs
|
|
|
|
push cs
|
|
pop ds
|
|
|
|
mov di,offset showcount+4 ; di -> the least significant decimal field.
|
|
mov cx,10 ; decimal devide factor
|
|
mov ax,cs:linecount
|
|
|
|
sln_loop:
|
|
cmp ax,10 ; < 10?
|
|
jb sln_last
|
|
|
|
xor dx,dx
|
|
div cx
|
|
or dl,30h ; add "0" (= 30h) to make it an ascii.
|
|
mov [di],dl
|
|
dec di
|
|
jmp sln_loop
|
|
|
|
sln_last:
|
|
or al,30h
|
|
mov [di],al
|
|
mov dx,di
|
|
call print ; show it.
|
|
pop di
|
|
pop ds
|
|
pop es
|
|
ret
|
|
showlinenum endp
|
|
|
|
comment ^
|
|
set_devmark proc near
|
|
;***************************************************************************
|
|
; function: set a paragraph of informations infront of a device file or *
|
|
; an ifs file to be loaded for mem command. *
|
|
; the structure is: *
|
|
; devmark_id byte "d" for device,"i" for ifs *
|
|
; devmark_size size in para for the device loaded *
|
|
; devmark_filename 11 bytes. filename *
|
|
; *
|
|
; input : *
|
|
; [memhi] = address to set up devmark. *
|
|
; [memlo] = 0 *
|
|
; es:si -> pointer to [drive][path]filename,0 *
|
|
; [ifs_flag] = is_ifs bit set if ifs= command. *
|
|
; *
|
|
; output: devmark_id,devmark_filename set *
|
|
; cs:[devmark_addr] set. *
|
|
; ax,cx register destroyed. *
|
|
;***************************************************************************
|
|
|
|
push ds
|
|
push si
|
|
push es
|
|
push di
|
|
|
|
mov di,cs:[memhi]
|
|
mov ds,di
|
|
assume ds:nothing
|
|
mov [devmark_addr],di ; save the devmark address for the future.
|
|
mov ds:[devmark_id],devmark_device ; 'd'
|
|
inc di
|
|
mov ds:[devmark_seg],di
|
|
xor al,al
|
|
push si
|
|
pop di ; now es:si = es:di = [path]filename,0
|
|
mov cx,128 ; maximum 128 char
|
|
repnz scasb ; find 0
|
|
dec di ; now es:di-> 0
|
|
sdvmk_backward: ; find the pointer to the start of the filename.
|
|
mov al,byte ptr es:[di] ; we do this by check es:di backward until
|
|
cmp al,'\' ; di = si or di -> '\' or di -> ':'.
|
|
je sdvmk_gotfile
|
|
cmp al,':'
|
|
je sdvmk_gotfile
|
|
cmp di,si
|
|
je sdvmk_fileptr
|
|
dec di
|
|
jmp sdvmk_backward
|
|
sdvmk_gotfile:
|
|
inc di
|
|
sdvmk_fileptr: ; now es:di -> start of file name
|
|
push di ; cas - holy sh*t!!! CODE!
|
|
pop si ; save di to si.
|
|
|
|
push ds ; switch es,ds
|
|
push es
|
|
pop ds
|
|
pop es ; now,ds:si -> start of filename
|
|
|
|
mov di,devmark_filename
|
|
push di
|
|
mov al,' '
|
|
mov cx,8
|
|
rep stosb ; clean up memory.
|
|
pop di
|
|
mov cx,8 ; max 8 char. only
|
|
sdvmk_loop:
|
|
lodsb
|
|
cmp al,'.'
|
|
je sdvmk_done
|
|
cmp al,0
|
|
je sdvmk_done
|
|
stosb
|
|
loop sdvmk_loop
|
|
|
|
sdvmk_done:
|
|
pop di
|
|
pop es
|
|
pop si
|
|
pop ds
|
|
ret
|
|
set_devmark endp
|
|
^
|
|
; =========================================================================
|
|
;reset_dos_version proc near
|
|
;
|
|
;;function: issue ax=122fh,dx=0,int 2fh to restore the dos version.
|
|
;
|
|
; push ax
|
|
; push dx
|
|
; mov ax,122fh
|
|
; mov dx,0
|
|
; int 2fh
|
|
; pop dx
|
|
; pop ax
|
|
; ret
|
|
;reset_dos_version endp
|
|
;
|
|
;
|
|
; =========================================================================
|
|
|
|
IFDEF DONT_LOAD_OS2_DD ; M045
|
|
|
|
EXE_SIG EQU 5a4dh ; .EXE file signature
|
|
OS2_SIG EQU 454eh ; OS2 .EXE file signature
|
|
|
|
SIGNATURE_LEN EQU 2 ; Lenght of .EXE signature in bytes
|
|
SIZE_DWORD EQU 4
|
|
|
|
SEG_SIG_OFFSET EQU 18h ; Offset of segmented .EXE signature
|
|
SEG_EXE_SIG EQU 40h ; Signature of a segmented .EXE file
|
|
SEG_HEADER_PTR EQU 3ch ; Offsets of ptr to segmented header
|
|
|
|
; =========================================================================
|
|
; CheckForOS2 PROC
|
|
;
|
|
; Examines an open file to see if it is really an OS2 executable file.
|
|
;
|
|
; REGISTERS: AX - Open file handle
|
|
; RETURNS: Carry - Carry set if file is an OS2 executable or error.
|
|
; DESTROYS: NOTHING
|
|
; NOTE: The file ptr is assumed to be set to start of file
|
|
; on entry and is not reset to begining of the file
|
|
; on exit.
|
|
;
|
|
; Strategy: If word value at 00h == 454eh file is OS2
|
|
; else if word value at 00h == 5a4dh and
|
|
; (word value at 18h == 40h and the dword ptr at 3ch
|
|
; points to word value of 454eh) file is OS2.
|
|
;
|
|
; =========================================================================
|
|
|
|
CheckForOS2 PROC NEAR
|
|
|
|
push AX
|
|
push BX
|
|
push CX
|
|
push DX
|
|
push DS
|
|
push BP
|
|
|
|
push CS ; BUGBUG
|
|
pop DS ; NOT ROM DOS COMPATIBLE
|
|
|
|
mov BX,AX ; Put open file handle in BX
|
|
mov BP,offset DS:Os2ChkBuf ; Save buff offset for latter
|
|
|
|
; First we need to read in the first 2 bytes of the file
|
|
; to see if it's an OS2 .EXE file and if not see if
|
|
; it is a DOS .EXE file.
|
|
|
|
mov AX,(read shl 8) ; AH = DOS read function
|
|
mov CX,SIGNATURE_LEN ; CX = size of word value
|
|
mov DX,BP ; DS:DX --> tmp buffer
|
|
int 21h
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
dec AX ; Check number of byte read
|
|
dec AX
|
|
jnz NotOs2 ; Must be at end of file
|
|
|
|
mov AX, WORD PTR DS:Os2ChkBuf
|
|
cmp AX, OS2_SIG ; Check for 454eh
|
|
je IsOS2 ; Return is OS2 if match
|
|
cmp AX, EXE_SIG ; Now see if it's a DOS .EXE
|
|
jne NotOS2 ; If no match can't be OS2
|
|
|
|
; Here we know the file has a valid DOS .EXE signature so
|
|
; now we need to see if it's a segmented .EXE file by looking
|
|
; for the segmented .EXE signature at file offset 18h
|
|
|
|
mov AX,(lseek shl 8) ; AX = Seek from begining
|
|
xor CX,CX
|
|
mov DX,SEG_SIG_OFFSET ; CX:DX = offset of segmented
|
|
int 21h ; Seek to offset 18h
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
mov AX,read shl 8 ; AX = Read file
|
|
mov CX,SIGNATURE_LEN ; CX = size of word value
|
|
mov DX,BP ; Restore buffer offset
|
|
int 21h ; DS:DX -> buffer
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
dec AX ; Check number of byte read
|
|
dec AX
|
|
jnz NotOs2 ; Must be at end of file
|
|
|
|
cmp WORD PTR DS:Os2ChkBuf,SEG_EXE_SIG ; Chk for segmented .EXE file
|
|
jne NotOS2 ; Can't be OS2 if no match
|
|
|
|
; Here we know we have a segmented .EXE file so we have
|
|
; to get the offset of the start of the segmented header
|
|
; from offset 3ch in the file.
|
|
|
|
mov AX,(lseek shl 8) ; AX = Seek from begining
|
|
xor CX,CX
|
|
mov DX,SEG_HEADER_PTR ; CX:DX = offset of head ptr
|
|
int 21h ; Seek to offset 3ch
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
mov AX,(read shl 8) ; AX = Read file
|
|
mov CX,SIZE_DWORD ; CX = size of dword (4 bytes)
|
|
mov DX,BP ; Restore buffer offset
|
|
int 21h ; Read in 4 byte offset
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
cmp AX,SIZE_DWORD ; Check number of byte read
|
|
jne NotOs2 ; Must be at end of file
|
|
|
|
; At this point OS2ChkBuf has a 4 byte offset into the file
|
|
; to the start of a segmented .EXE header so we need to read
|
|
; the 2 bytes at this location to see if they are 454eh
|
|
|
|
mov DX,WORD PTR DS:Os2ChkBuf
|
|
mov CX,WORD PTR DS:Os2ChkBuf[2] ; CX:DX = offset of new header
|
|
mov AX,(lseek shl 8) ; AX = Seek from begining
|
|
int 21h ; Seek to offset 3ch
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
mov AX,(read shl 8) ; AX = Read file
|
|
mov CX,SIGNATURE_LEN ; CX = size of word (2 bytes)
|
|
mov DX,BP ; DS:DX --> Os2ChkBuf
|
|
int 21h ; Read in 4 byte offset
|
|
jc OS2ChkExit ; Return carry on error
|
|
|
|
dec AX ; Check number of byte read
|
|
dec AX
|
|
jnz NotOs2 ; Must be at end of file
|
|
|
|
; We have the segmented .EXE header in OS2ChkBuf so all
|
|
; we have left to do is see if it's a .EXE signature.
|
|
|
|
cmp WORD PTR DS:OS2ChkBuf,OS2_SIG ; Check for 454eh
|
|
jne NotOs2 ; Not OS2 if it doesn't match
|
|
|
|
IsOs2:
|
|
stc ; Signal error or OS2 .EXE
|
|
jmp SHORT OS2ChkExit
|
|
NotOs2:
|
|
clc ; Signal no err and not OS2
|
|
|
|
OS2ChkExit:
|
|
pop BP
|
|
pop DS
|
|
pop DX
|
|
pop CX
|
|
pop BX
|
|
pop AX
|
|
ret
|
|
|
|
CheckForOS2 ENDP
|
|
|
|
ENDIF ; M045
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : ProcDOS
|
|
;
|
|
; Process the result of DOS= parsing
|
|
;
|
|
; result_val.$p_item_tag = 1 for DOS=HIGH
|
|
; = 2 for DOS=LOW
|
|
; = 3 for DOS=UMB
|
|
; = 4 for DOS=NOUMB
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
ProcDOS proc near
|
|
assume ds:nothing, es:nothing
|
|
xor ah, ah
|
|
mov al, result_val.$p_item_tag
|
|
dec ax
|
|
jz pd_hi
|
|
dec ax
|
|
jz pd_lo
|
|
dec ax
|
|
jz pd_umb
|
|
mov DevUMB, 0
|
|
ret
|
|
pd_umb:
|
|
mov DevUMB, 0ffh
|
|
ret
|
|
pd_lo:
|
|
mov runhigh, 0
|
|
ret
|
|
pd_hi:
|
|
mov runhigh, 0ffh
|
|
ret
|
|
ProcDOS endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : LieInt12Mem
|
|
;
|
|
; Input : DevEntry points to Device Start address (offset == 0)
|
|
; alloclim set to the limit of low memory.
|
|
;
|
|
; Output : none
|
|
;
|
|
; Changes the ROM BIOS variable which stores the total low memory
|
|
; If a 3com device driver (any character device with name 'PROTMAN$')
|
|
; is being loaded alloclim is converted into Ks and stored in 40:13h
|
|
; Else if a device driver being loaded into UMB the DevLoadEnd is
|
|
; converted into Ks and stored in 40:13h
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
LieInt12Mem proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov ax, alloclim ; lie INT 12 as alloclim
|
|
; assuming that it is 3Com
|
|
call IsIt3Com? ; Is it 3Com driver?
|
|
je lim_set ; yes, lie to him differently
|
|
cmp DeviceHi, 0 ; Is the DD being loaded in UMB
|
|
je limx ; no, don't lie
|
|
mov ax, DevLoadEnd ; lie INT 12 as end of UMB
|
|
lim_set:
|
|
call SetInt12Mem
|
|
limx:
|
|
ret
|
|
LieInt12Mem endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : SetInt12Mem
|
|
;
|
|
; Input : AX = Memory size to be set (in paras)
|
|
; Output : none
|
|
;
|
|
; Sets the variable 40:13 to the memory size passed in AX
|
|
; It saves the old value in 40:13 in OldInt12Mem,
|
|
; It also sets a flag Int12Lied to 0ffh, which is checked before
|
|
; restoring the value of 40:13
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
SetInt12Mem proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
push ds
|
|
mov bx, 40h
|
|
mov ds, bx ; ROM BIOS Data Segment
|
|
mov bx, word ptr ds:[13h] ; INT 12 memory variable
|
|
mov OldInt12Mem, bx ; save it
|
|
mov cl, 6
|
|
shr ax, cl ; convert paras into Ks
|
|
mov word ptr ds:[13h], ax ; Lie
|
|
mov Int12Lied, 0ffh ; mark that we are lying
|
|
pop ds
|
|
ret
|
|
SetInt12Mem endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : TrueInt12Mem
|
|
;
|
|
; Input : Int12Lied = 0 if we are not lying currently
|
|
; = 0ffh if we are lying
|
|
; OldInt12Mem = Saved value of 40:13h
|
|
;
|
|
; Output : none
|
|
;
|
|
; Resets the INT 12 Memory variable if we were lying about int 12
|
|
; and resets the flag which indicates that we were lying
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
TrueInt12Mem proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
cmp Int12Lied, 0 ; were we lying so far?
|
|
mov Int12Lied, 0 ; reset it anyway
|
|
je timx ; no, we weren't
|
|
push ds
|
|
mov ax, 40h
|
|
mov ds, ax
|
|
mov ax, OldInt12Mem
|
|
mov word ptr ds:[13h], ax ; restore INT 12 memory
|
|
pop ds
|
|
timx:
|
|
ret
|
|
TrueInt12Mem endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : IsIt3Com?
|
|
;
|
|
; Input : DevEntry = Seg:0 of device driver
|
|
; Output : Zero flag set if device name is 'PROTMAN$'
|
|
; else Zero flag is reset
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
IsIt3Com? proc near
|
|
assume ds:nothing, es:nothing, ss:nothing
|
|
push ds
|
|
push es
|
|
push si
|
|
lds si, DevEntry ; ptr to device header
|
|
add si, sdevname ; ptr device name
|
|
push cs
|
|
pop es
|
|
mov di, offset ThreeComName
|
|
mov cx, 8 ; name length
|
|
rep cmpsb
|
|
pop si
|
|
pop es
|
|
pop ds
|
|
ret
|
|
IsIt3Com? endp
|
|
|
|
;M020 : BEGIN
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
UpdatePDB proc near
|
|
assume ds:nothing
|
|
push ds
|
|
mov ah, 62h
|
|
int 21h
|
|
mov ds, bx
|
|
mov bx, alloclim
|
|
mov ds:[PDB_Block_Len], bx
|
|
pop ds
|
|
ret
|
|
UpdatePDB endp
|
|
;
|
|
; M020 : END
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : InitDevLoad
|
|
;
|
|
; Input : DeviceHi = 0 indicates load DD in low memory
|
|
; = 1 indicates load in UMB
|
|
; DevSize = Size of the device driver file in paras
|
|
;
|
|
; Output : none
|
|
;
|
|
; Initializes DevLoadAddr, DevLoadEnd & DevEntry.
|
|
; Also sets up a header for the Device driver entry for mem utility
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
InitDevLoad proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
cmp DeviceHi, 0 ; Are we loading in UMB
|
|
je InitForLo ; no, init for lo mem
|
|
call SpaceInUMB? ; Do we have space left in the
|
|
; current UMB ?
|
|
jnc InitForHi ; yes, we have
|
|
call ShrinkUMB ; shrink the current UMB in use
|
|
call GetUMBForDev ; else try to allocate new UMB
|
|
jc InitForLo ; we didn't succeed, so load
|
|
; in low memory
|
|
InitForHi:
|
|
mov ax, DevUMBFree ; get Para addr of free mem
|
|
mov dx, DevUMBAddr ; UMB start addr
|
|
add dx, DevUMBSize ; DX = UMB End addr
|
|
jmp short idl1
|
|
|
|
InitForLo:
|
|
mov DeviceHi, 0 ; in case we failed to load
|
|
; into UMB indicate that we
|
|
; are loading low
|
|
mov ax, memhi ; AX = start of Low memory
|
|
mov dx, alloclim ; DX = End of Low memory
|
|
idl1:
|
|
call DevSetMark ; setup a sub-arena for DD
|
|
mov DevLoadAddr, ax ; init the Device load address
|
|
mov DevLoadEnd, dx ; init the limit of the block
|
|
mov word ptr DevEntry, 0 ; init Entry point to DD
|
|
mov word ptr DevEntry+2, ax
|
|
ret
|
|
InitDevLoad endp
|
|
|
|
|
|
;------------------------------------------------------------------
|
|
; NTVDM 08-Dec-1992 Jonle
|
|
;
|
|
; AllocUMBLow- Allocates a chunk from memory from UMB area
|
|
; or from low memory area in case UMB memory
|
|
; is unavailable.
|
|
;
|
|
; The arena is marked as
|
|
;
|
|
; Input: es:di addr of arena name to copy
|
|
; cx size to allocate
|
|
;
|
|
; Output: es:di points to memory allocated
|
|
;
|
|
;------------------------------------------------------------------
|
|
AllocUMBLow proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov ax, cx ; convert size to paras
|
|
add ax, 18 ; extra for dummy dev header for mem.exe
|
|
call pararound
|
|
mov DevSize, ax
|
|
|
|
mov word ptr [bpb_addr], di ; fake cmd line for dev name
|
|
mov word ptr [bpb_addr+2], es
|
|
|
|
mov al, DevUMB ; we want UMB
|
|
mov DeviceHi, al
|
|
|
|
call InitDevLoad
|
|
|
|
mov ax, word ptr DevEntry+2 ; mark arena for mem.exe
|
|
dec ax
|
|
mov es, ax
|
|
mov byte ptr es:[devmark_id], devmark_spc
|
|
|
|
inc ax ; mark final size
|
|
add ax, DevSize
|
|
mov word ptr DevBrkAddr+2,ax
|
|
mov word ptr DevBrkAddr, 0
|
|
call DevBreak
|
|
|
|
mov di, word ptr DevEntry ; es:di -> deventry
|
|
mov ax, word ptr DevEntry+2
|
|
mov es, ax
|
|
|
|
AllocUMBLow endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : SpaceInUMB?
|
|
;
|
|
; Input : DevUMBAddr, DevUMBSize, DevUMBFree & DevSize
|
|
; Output : Carry set if no space in UMB
|
|
; Carry clear if Space is available for the device in
|
|
; current UMB
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
SpaceInUMB? proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov ax, DevUMBSize
|
|
add ax, DevUMBAddr ; End of UMB
|
|
sub ax, DevUMBFree ; - Free = Remaining space
|
|
or ax, ax ; Nospace ?
|
|
jnz @f
|
|
stc
|
|
ret
|
|
@@:
|
|
dec ax ; space for sub-arena
|
|
cmp ax, DevSize ; do we have space ?
|
|
ret
|
|
SpaceInUMB? endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : GetUMBForDev
|
|
;
|
|
; Input : DevSize
|
|
; Output : Carry set if couldn't allocate a UMB to fit the
|
|
; the device.
|
|
; If success carry clear
|
|
;
|
|
; Allocates the biggest UMB for loading devices and updates
|
|
; DevUMBSize, DevUMBAddr & DevUMBFree if it succeeded in allocating
|
|
; UMB.
|
|
;
|
|
; This routine relies on the fact that all of the low memory
|
|
; is allocated, and any DOS alloc calls should return memory
|
|
; from the UMB pool.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
GetUMBForDev proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
if 0
|
|
;;
|
|
mov bx, 0ffffh
|
|
mov ax, 4800h
|
|
int 21h
|
|
|
|
or bx, bx
|
|
jz gufd_err
|
|
|
|
dec bx
|
|
cmp DevSize, bx
|
|
ja gufd_err
|
|
inc bx
|
|
mov ax, 4800h
|
|
int 21h
|
|
jc gufd_err
|
|
|
|
push ds
|
|
dec ax
|
|
mov ds, ax
|
|
mov word ptr ds:[arena_owner], 8
|
|
mov word ptr ds:[arena_name], 'DS'
|
|
inc ax
|
|
pop ds
|
|
|
|
mov DevUMBSize, bx ; update the UMB Variables
|
|
mov DevUMBAddr, ax
|
|
mov DevUMBFree, ax
|
|
clc ; mark no error
|
|
ret
|
|
gufd_err:
|
|
xor ax, ax
|
|
mov DevUMBSize, ax ; erase the previous values
|
|
mov DevUMBAddr, ax
|
|
mov DevUMBFree, ax
|
|
stc
|
|
ret
|
|
else
|
|
;; we changed the allocation strategy to best-fit for NT. This is because
|
|
;; we want to reserve bigger blocks for loadhigh command. In most case,
|
|
;; device drivers are smaller than TSR(ran from loadhigh). This change give
|
|
;; us a better chance to load the big tsr like DOSX.EXE to UMB and
|
|
;; give applications more free conventional memory.
|
|
;; The following implementation seems slow because every time we need an
|
|
;; UMB, we go through the chain. This is done because each request has
|
|
;; different size - We can grab all UMBs from the very beginning and put
|
|
;; them in a list, but we have to maintain the list. -williamh
|
|
push cx
|
|
push dx
|
|
push es
|
|
xor cx, cx ;; allocated count = 0
|
|
mov dx, DevSize
|
|
inc dx ;; minimum size in paras
|
|
;; bios needs its sub-arena
|
|
search_for_best_block:
|
|
mov bx, 0ffffh ;; get largest block size
|
|
mov ah, 48h ;; so far
|
|
int 21h
|
|
cmp bx, dx ;; will this satisfy ours?
|
|
jb allocate_the_block ;; no, break
|
|
mov ah, 48h ;; allocate this block
|
|
int 21h
|
|
jc allocate_the_block ;; failed, use the previous one
|
|
inc cx ;; we have one more allocated
|
|
push bx ;; save the size
|
|
push ax ;; save the address
|
|
jmp short search_for_best_block
|
|
|
|
allocate_the_block:
|
|
;; the block saved on the top of the stack is the best fit one
|
|
;; grab it if there is one
|
|
jcxz gufd_err ;; no block found, error
|
|
pop ax ;; get the address
|
|
pop DevUMBSize ;; and size
|
|
mov DevUMBAddr, ax
|
|
mov DevUMBFree, ax
|
|
dec ax
|
|
push ds
|
|
mov ds, ax
|
|
mov word ptr ds:[arena_owner], 8
|
|
mov word ptr ds:[arena_name], 'DS'
|
|
pop ds
|
|
dec cx
|
|
;; now free those unnecessary blocks
|
|
jcxz allocate_done
|
|
free_allocated_blocks:
|
|
pop es ;; get the address
|
|
add sp, 2 ;; discard the size
|
|
mov ah, 49h ;; free it
|
|
int 21h
|
|
loop free_allocated_blocks
|
|
allocate_done:
|
|
clc ; mark no error
|
|
jmp short GetUMBForDevExit
|
|
gufd_err:
|
|
xor ax, ax
|
|
mov DevUMBSize, ax ; erase the previous values
|
|
mov DevUMBAddr, ax
|
|
mov DevUMBFree, ax
|
|
stc
|
|
GetUMBForDevExit:
|
|
pop es
|
|
pop dx
|
|
pop cx
|
|
ret
|
|
endif
|
|
|
|
GetUMBForDev endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : DevSetMark
|
|
;
|
|
; Input : AX - Free segment were device is going to be loaded
|
|
; Output : AX - Segment at which device can be loaded (AX=AX+1)
|
|
;
|
|
; Creates a sub-arena for the device driver
|
|
; puts 'D' marker in the sub-arena
|
|
; Put the owner of the sub-arena as (AX+1)
|
|
; Copies the file name into sub-arena name field
|
|
;
|
|
; Size field of the sub-arena will be set only at succesful
|
|
; completion of Device load.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
DevSetMark proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
push es
|
|
push di
|
|
push ds
|
|
push si
|
|
mov es, ax
|
|
mov byte ptr es:[devmark_id], devmark_device ; 'D'
|
|
inc ax
|
|
mov word ptr es:[devmark_seg], ax
|
|
;
|
|
;-------------- Copy file name
|
|
;
|
|
push ax ; save load addr
|
|
lds si, bpb_addr ; command line is still there
|
|
;M004 - BEGIN
|
|
mov di, si
|
|
cld
|
|
dsm_again:
|
|
lodsb
|
|
cmp al, ':'
|
|
jne isit_slash
|
|
mov di, si
|
|
jmp dsm_again
|
|
isit_slash:
|
|
cmp al, '\'
|
|
jne isit_null
|
|
mov di, si
|
|
jmp dsm_again
|
|
isit_null:
|
|
|
|
ifdef DBCS
|
|
call testkanj
|
|
jz @f ; if this is not lead byte
|
|
lodsb ; get tail byte
|
|
@@:
|
|
endif
|
|
|
|
or al, al
|
|
jnz dsm_again
|
|
mov si, di
|
|
;M004 - END
|
|
mov di, devmark_filename
|
|
mov cx, 8 ; maximum 8 characters
|
|
dsm_next_char:
|
|
lodsb
|
|
or al, al
|
|
jz blankout
|
|
cmp al, '.'
|
|
jz blankout
|
|
stosb
|
|
loop dsm_next_char
|
|
blankout:
|
|
jcxz dsm_exit
|
|
mov al, ' '
|
|
rep stosb ; blank out the rest
|
|
dsm_exit:
|
|
pop ax ; restore load addr
|
|
pop si
|
|
pop ds
|
|
pop di
|
|
pop es
|
|
ret
|
|
DevSetMark endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : SizeDevice
|
|
;
|
|
; Input : ES:SI - points to device file to be sized
|
|
;
|
|
; Output : Carry set if file cannot be opened or if it is an OS2EXE file
|
|
;
|
|
; Calculates the size of the device file in paras and stores it
|
|
; in DevSize
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
SizeDevice proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
push es
|
|
pop ds
|
|
mov dx, si ; ds:dx -> file name
|
|
mov ax, 3d00h ; open
|
|
int 21h
|
|
jc sd_err ; open failed
|
|
|
|
IFDEF DONT_LOAD_OS2_DD ; M045
|
|
call CheckForOS2 ; is it a OS2 EXE file ?
|
|
jc sd_close ; yeah, we dont load them
|
|
ENDIF ; M045
|
|
|
|
mov bx, ax ; BX - file handle
|
|
mov ax, 4202h ; seek
|
|
xor cx, cx
|
|
mov dx, cx ; to end of file
|
|
int 21h
|
|
jc sd_close ; did seek fail (impossible)
|
|
add ax, 15 ; para convert
|
|
adc dx, 0
|
|
test dx, 0fff0h ; size > 0ffff paras ?
|
|
jz @f ; no
|
|
mov DevSize, 0ffffh ; invalid device size
|
|
; assuming that we fail later
|
|
jmp short sd_close
|
|
@@:
|
|
mov cl, 4 ; conver it to paras
|
|
shr ax, cl
|
|
mov cl, 12
|
|
shl dx, cl
|
|
or ax, dx ;
|
|
cmp ax, DevSizeOption
|
|
ja @f
|
|
mov ax, DevSizeOption
|
|
@@:
|
|
mov DevSize, ax ; save file size
|
|
clc
|
|
sd_close:
|
|
pushf ; let close not spoil our
|
|
; carry flag
|
|
mov ax, 3e00h ; close
|
|
int 21h ; we are not checking for err
|
|
popf
|
|
sd_err:
|
|
ret
|
|
SizeDevice endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : ExecDev
|
|
;
|
|
; Input : ds:dx -> device to be executed
|
|
; DevLoadAddr - contains where device has to be loaded
|
|
;
|
|
; Output : Carry if error
|
|
; Carry clear if no error
|
|
;
|
|
; Loads a device driver using the 4b03h function call
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
ExecDev proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov bx, DevLoadAddr
|
|
mov DevExecAddr, bx ; Load the parameter block
|
|
; block for exec with
|
|
; Load address
|
|
mov DevExecReloc, bx
|
|
mov bx,cs
|
|
mov es,bx
|
|
mov bx,offset DevExecAddr ;es:bx points to parameters
|
|
mov al,3
|
|
mov ah,exec
|
|
int 21h ;load in the device driver
|
|
ret
|
|
ExecDev endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : RemoveNull
|
|
;
|
|
; Input : ES:SI points to a null terminated string
|
|
;
|
|
; Output : none
|
|
;
|
|
; Replaces the null at the end of a string with blank
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
RemoveNull proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
rn_next:
|
|
mov bl, es:[si]
|
|
or bl, bl ; null ?
|
|
jz rn_gotnull
|
|
inc si ; advance the pointer
|
|
jmp rn_next
|
|
rn_gotnull:
|
|
mov bl, DevSavedDelim
|
|
mov byte ptr es:[si], bl ; replace null with blank
|
|
ret
|
|
RemoveNull endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : RoundBreakAddr
|
|
;
|
|
; Input : DevBrkAddr
|
|
; Output : DevBrkAddr
|
|
;
|
|
; Rounds DevBrkAddr to a para address so that it is of the form xxxx:0
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
RoundBreakAddr proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov ax, word ptr DevBrkAddr
|
|
call pararound
|
|
add word ptr DevBrkAddr+2, ax
|
|
mov word ptr DevBrkAddr, 0
|
|
mov ax, DevLoadEnd
|
|
cmp word ptr DevBrkAddr+2, ax
|
|
jbe rba_ok
|
|
jmp mem_err
|
|
rba_ok:
|
|
ret
|
|
RoundBreakAddr endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : DevSetBreak
|
|
;
|
|
; Input : DevBrkAddr
|
|
; Output : Carry set if Device returned Init failed
|
|
; Else carry clear
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
DevSetBreak proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
push ax
|
|
|
|
mov ax,word ptr [DevBrkAddr+2] ;remove the init code
|
|
cmp multdeviceflag, 0
|
|
jne set_break_continue ;do not check it.
|
|
cmp ax, DevLoadAddr
|
|
jne set_break_continue ;if not same, then o.k.
|
|
|
|
cmp word ptr [DevBrkAddr],0
|
|
je break_failed ;[DevBrkAddr+2]=[memhi] & [DevBrkAddr]=0
|
|
|
|
set_break_continue:
|
|
call RoundBreakAddr
|
|
pop ax
|
|
clc
|
|
ret
|
|
break_failed:
|
|
pop ax
|
|
stc
|
|
ret
|
|
DevSetBreak endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : DevBreak
|
|
;
|
|
; Input : DevLoadAddr & DevBrkAddr
|
|
; Output : none
|
|
;
|
|
; Marks a succesful install of a device driver
|
|
; Sets device size field in sub-arena &
|
|
; Updates Free ptr in UMB or adjusts memhi
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
DevBreak proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
push ds
|
|
mov ax, DevLoadAddr
|
|
mov bx, word ptr [DevBrkAddr+2]
|
|
dec ax ; seg of sub-arena
|
|
mov ds, ax
|
|
inc ax ; Back to Device segment
|
|
sub ax, bx
|
|
neg ax ; size of device in paras
|
|
mov ds:[devmark_size], ax ; store it in sub-arena
|
|
cmp DeviceHi, 0
|
|
je db_lo
|
|
mov DevUMBFree, bx ; update Free ptr in UMB
|
|
jmp short db_exit
|
|
db_lo:
|
|
mov memhi, bx
|
|
mov memlo, 0
|
|
db_exit:
|
|
pop ds
|
|
ret
|
|
DevBreak endp
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : ParseSize
|
|
;
|
|
; Parses the command line for SIZE= command
|
|
;
|
|
; ES:SI = command line to parsed
|
|
;
|
|
; returns ptr to command line after SIZE= option in ES:SI
|
|
; updates the DevSizeOption variable with value supplied
|
|
; in SIZE=option
|
|
; Returns carry if the SIZE option was invalid
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
ParseSize proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov DevSizeOption, 0 ; init the value
|
|
mov word ptr DevCmdLine, si
|
|
mov word ptr DevCmdLine+2, es
|
|
call SkipDelim
|
|
cmp word ptr es:[si], 'IS'
|
|
jne ps_no_size
|
|
cmp word ptr es:[si+2], 'EZ'
|
|
jne ps_no_size
|
|
mov al, es:[si+4]
|
|
call delim
|
|
jne ps_no_size
|
|
add si, 5
|
|
call GetHexNum
|
|
jc ps_err
|
|
mov DevSizeOption, ax
|
|
call SkipDelim
|
|
ps_no_size:
|
|
clc
|
|
ret
|
|
ps_err:
|
|
stc
|
|
ret
|
|
ParseSize endp
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : SkipDelim
|
|
;
|
|
; Skips delimiters in the string pointed to by ES:SI
|
|
; Returns ptr to first non-delimiter character in ES:SI
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
SkipDelim proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
sd_next_char:
|
|
mov al, es:[si]
|
|
call delim
|
|
jnz sd_ret
|
|
inc si
|
|
jmp sd_next_char
|
|
sd_ret:
|
|
ret
|
|
SkipDelim endp
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : GetHexNum
|
|
;
|
|
; Converts an ascii string terminated by a delimiter into binary.
|
|
; Assumes that the ES:SI points to a Hexadecimal string
|
|
;
|
|
; Returns in AX the number number of paras equivalent to the
|
|
; hex number of bytes specified by the hexadecimal string.
|
|
;
|
|
; Returns carry in case it encountered a non-hex character or
|
|
; if it encountered crlf
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
GetHexNum proc near
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
xor ax, ax
|
|
xor dx, dx
|
|
ghn_next:
|
|
mov bl, es:[si]
|
|
cmp bl, cr
|
|
je ghn_err
|
|
cmp bl, lf
|
|
je ghn_err
|
|
push ax
|
|
mov al, bl
|
|
call Delim
|
|
pop ax
|
|
jz ghn_into_paras
|
|
call GetNibble
|
|
jc ghn_err
|
|
mov cx, 4
|
|
ghn_shift1:
|
|
shl ax, 1
|
|
rcl dx, 1
|
|
loop ghn_shift1
|
|
or al, bl
|
|
inc si
|
|
jmp ghn_next
|
|
ghn_into_paras:
|
|
add ax, 15
|
|
adc dx, 0
|
|
test dx, 0fff0h
|
|
jnz ghn_err
|
|
mov cx, 4
|
|
ghn_shift2:
|
|
clc
|
|
rcr dx, 1
|
|
rcr ax, 1
|
|
loop ghn_shift2
|
|
clc
|
|
ret
|
|
ghn_err:
|
|
stc
|
|
ret
|
|
GetHexNum endp
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : GetNibble
|
|
;
|
|
; Convert one nibble (hex digit) in BL into binary
|
|
;
|
|
; Retruns binary value in BL
|
|
;
|
|
; Returns carry if BL contains non-hex digit
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
GetNibble proc near
|
|
cmp bl, '0'
|
|
jb gnib_err
|
|
cmp bl, '9'
|
|
ja is_it_hex
|
|
sub bl, '0' ; clc
|
|
ret
|
|
is_it_hex:
|
|
cmp bl, 'A'
|
|
jb gnib_err
|
|
cmp bl, 'F'
|
|
ja gnib_err
|
|
sub bl, 'A'- 10 ; clc
|
|
ret
|
|
gnib_err:
|
|
stc
|
|
ret
|
|
GetNibble endp
|
|
;
|
|
;
|
|
;============================================================================
|
|
;============================================================================
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : AllocUMB
|
|
;
|
|
; Allocate all UMBs and link it to DOS arena chain
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
AllocUMB proc near
|
|
call InitAllocUMB ; link in the first UMB
|
|
jc au_exit ; quit on error
|
|
au_next:
|
|
call umb_allocate ; allocate
|
|
jc au_coalesce
|
|
call umb_insert ; & insert till no UMBs
|
|
jmp short au_next
|
|
au_coalesce:
|
|
call umb_coalesce ; coalesce all UMBs
|
|
au_exit:
|
|
ret
|
|
AllocUMB endp
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : InitAllocUMB
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
InitAllocUMB proc near
|
|
call IsXMSLoaded
|
|
jnz iau_err ; quit on no XMS driver
|
|
mov ah, 52h
|
|
int 21h ; get DOS DATA seg
|
|
mov DevDOSData, es ; & save it for later
|
|
mov ax, 4310h
|
|
int 2fh
|
|
mov word ptr DevXMSAddr, bx ; get XMS driver address
|
|
mov word ptr DevXMSAddr+2, es
|
|
cmp FirstUMBLinked, 0 ; have we already linked a UMB?
|
|
jne @f ; quit if we already did it
|
|
call LinkFirstUMB ; else link the first UMB
|
|
jc iau_err
|
|
mov FirstUMBLinked, 0ffh ; mark that 1st UMB linked
|
|
@@:
|
|
clc
|
|
ret
|
|
iau_err:
|
|
stc
|
|
ret
|
|
InitAllocUMB endp
|
|
|
|
;-------------------------------------------------------------------------
|
|
;
|
|
; Procedure Name : umb_allocate
|
|
;
|
|
; Inputs : DS = data
|
|
;
|
|
; Outputs : if UMB available
|
|
; Allocates the largest available UMB and
|
|
; BX = segment of allocated block
|
|
; DX = size of allocated block
|
|
; NC
|
|
; else
|
|
; CY
|
|
;
|
|
; Uses : BX, DX
|
|
;
|
|
;-------------------------------------------------------------------------
|
|
|
|
umb_allocate proc near
|
|
|
|
push ax
|
|
mov ah, XMM_REQUEST_UMB
|
|
mov dx, 0ffffh ; try to allocate largest
|
|
; possible
|
|
call dword ptr DevXMSAddr
|
|
; dx now contains the size of
|
|
; the largest UMB
|
|
or dx, dx
|
|
jz ua_err
|
|
|
|
mov ah, XMM_REQUEST_UMB
|
|
call dword ptr DevXMSAddr
|
|
|
|
cmp ax, 1 ; Q: was the reqst successful
|
|
jne ua_err ; N: error
|
|
|
|
clc
|
|
|
|
ua_done:
|
|
pop ax
|
|
ret
|
|
|
|
ua_err:
|
|
stc
|
|
jmp short ua_done
|
|
|
|
umb_allocate endp
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
; Procedure Name : umb_insert
|
|
;
|
|
; Inputs : DOSDATA:UMB_HEAD = start of umb chain
|
|
; : BX = seg address of UMB to be linked in
|
|
; : DX = size of UMB to be linked in paras
|
|
; ; DS = data
|
|
;
|
|
; Outputs : links the UMB into the arena chain
|
|
;
|
|
; Uses : AX, CX, ES, DX, BX
|
|
;
|
|
;---------------------------------------------------------------------------
|
|
|
|
|
|
umb_insert proc near
|
|
|
|
push ds
|
|
|
|
mov ds, [DevDOSData]
|
|
mov ds, ds:[UMB_ARENA] ; es = UMB_HEAD
|
|
mov ax, ds
|
|
mov es, ax
|
|
|
|
ui_next:
|
|
cmp ax, bx ; Q: is current block above
|
|
; new block
|
|
ja ui_insert ; Y: insert it
|
|
; Q: is current block the
|
|
; last
|
|
cmp es:[arena_signature], arena_signature_end
|
|
jz ui_append ; Y: append new block to chain
|
|
; N: get next block
|
|
|
|
mov ds, ax ; M005
|
|
call get_next ; ax = es = next block
|
|
jmp short ui_next
|
|
|
|
ui_insert:
|
|
|
|
mov cx, ds ; ds = previous arena
|
|
inc cx ; top of previous block
|
|
|
|
sub cx, bx
|
|
neg cx ; cx = size of used block
|
|
mov ds:[arena_signature], arena_signature_normal
|
|
mov ds:[arena_owner], 8 ; mark as system owned
|
|
mov ds:[arena_size], cx
|
|
mov word ptr ds:[arena_name], 'CS'
|
|
|
|
; prepare the arena at start of new block
|
|
|
|
mov es, bx
|
|
mov es:[arena_signature], arena_signature_normal
|
|
mov es:[arena_owner], arena_owner_system
|
|
; mark as free
|
|
sub dx, 2 ; make room for arena at
|
|
; start & end of new block
|
|
mov es:[arena_size], dx
|
|
|
|
; prepare arena at end of new block
|
|
|
|
add bx, dx
|
|
inc bx
|
|
mov es, bx ; es=arena at top of new block
|
|
inc bx ; bx=top of new block
|
|
|
|
; ax contains arena just above
|
|
; this block
|
|
sub ax, bx ; ax = size of used block
|
|
|
|
mov es:[arena_signature], arena_signature_normal
|
|
mov es:[arena_owner], 8 ; mark as system owned
|
|
mov es:[arena_size], ax
|
|
mov word ptr es:[arena_name], 'CS'
|
|
|
|
jmp short ui_done
|
|
|
|
ui_append:
|
|
|
|
; es = arena of last block
|
|
|
|
add ax, es:[arena_size] ; ax=top of last block-1 para
|
|
sub es:[arena_size], 1 ; reflect the space we are
|
|
; going to rsrv on top of this
|
|
; block for the next arena.
|
|
mov es:[arena_signature], arena_signature_normal
|
|
|
|
mov cx, ax ; cx=top of prev block-1
|
|
inc ax
|
|
sub ax, bx ; ax=top of prev block -
|
|
; seg. address of new block
|
|
|
|
neg ax
|
|
|
|
mov es, cx ; ds = arena of unused block
|
|
|
|
|
|
mov es:[arena_signature], arena_signature_normal
|
|
mov es:[arena_owner], 8 ; mark as system owned
|
|
mov es:[arena_size], ax
|
|
mov word ptr es:[arena_name], 'CS'
|
|
|
|
; prepare the arena at start of new block
|
|
|
|
mov es, bx
|
|
mov es:[arena_signature], arena_signature_end
|
|
mov es:[arena_owner], arena_owner_system
|
|
; mark as free
|
|
dec dx ; make room for arena
|
|
mov es:[arena_size], dx
|
|
|
|
ui_done:
|
|
pop ds
|
|
ret
|
|
|
|
umb_insert endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
;** umb_coalesce - Combine free blocks ahead with current block
|
|
;
|
|
; Coalesce adds the block following the argument to the argument block,
|
|
; iff it's free. Coalesce is usually used to join free blocks, but
|
|
; some callers (such as $setblock) use it to join a free block to it's
|
|
; preceeding allocated block.
|
|
;
|
|
; EXIT 'C' clear if OK
|
|
; (ds) unchanged, this block updated
|
|
; (ax) = address of next block, IFF not at end
|
|
; 'C' set if arena trashed
|
|
; USES cx, di, ds, es
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
umb_coalesce proc near
|
|
|
|
|
|
|
|
xor di, di
|
|
|
|
mov es, [DevDOSData]
|
|
mov es, es:[UMB_ARENA] ; es = UMB_HEAD
|
|
|
|
uc_nextfree:
|
|
mov ax, es
|
|
mov ds, ax
|
|
cmp es:[arena_owner], di ; Q: is current arena free
|
|
jz uc_again ; Y: try to coalesce with next block
|
|
; N: get next arena
|
|
call get_next ; es, ax = next arena
|
|
jc uc_done
|
|
jmp short uc_nextfree
|
|
uc_again:
|
|
call get_next ; ES, AX <- next block
|
|
jc uc_done
|
|
uc_check:
|
|
cmp es:[arena_owner],di ; Q: is arena free
|
|
jnz uc_nextfree ; N: get next free arena
|
|
; Y: coalesce
|
|
mov cx,es:[arena_size] ; cx <- next block size
|
|
inc cx ; cx <- cx + 1 (for header size)
|
|
add ds:[arena_size],cx ; current size <- current size + cx
|
|
mov cl,es:[di] ; move up signature
|
|
mov ds:[di],cl
|
|
jmp short uc_again ; try again
|
|
uc_done:
|
|
ret
|
|
|
|
umb_coalesce endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
;** get_next - Find Next item in Arena
|
|
;
|
|
; ENTRY dS - pointer to block head
|
|
; EXIT AX,ES - pointers to next head
|
|
; 'C' set iff arena damaged
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
get_next proc near
|
|
|
|
cmp byte ptr ds:[0], arena_signature_end
|
|
je gn_err
|
|
|
|
mov ax,ds ; ax=current block
|
|
add ax,ds:[arena_size] ; ax=ax + current block length
|
|
inc ax ; remember that header!
|
|
mov es, ax
|
|
clc
|
|
ret
|
|
gn_err:
|
|
stc
|
|
ret
|
|
|
|
get_next endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : LinkFirstUMB
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
LinkFirstUMB proc near
|
|
|
|
call umb_allocate
|
|
jc lfu_err
|
|
|
|
; bx = segment of allocated UMB
|
|
; dx = size of UMB
|
|
|
|
int 12h ; ax = size of memory
|
|
mov cl, 6
|
|
shl ax, cl ; ax = size in paragraphs
|
|
|
|
mov cx, ax ; cx = size in paras
|
|
sub ax, bx ; ax = - size of unused block
|
|
|
|
neg ax
|
|
|
|
sub cx, 1 ; cx = first umb_arena
|
|
mov es, cx ; es = first umb_arena
|
|
|
|
mov es:[arena_signature], arena_signature_normal
|
|
mov es:[arena_owner], 8 ; mark as system owned
|
|
|
|
mov es:[arena_size], ax
|
|
mov word ptr es:[arena_name], 'CS'
|
|
|
|
|
|
; put in the arena for the first UMB
|
|
|
|
mov es, bx ; es has first free umb seg
|
|
mov es:[arena_signature], arena_signature_end
|
|
mov es:[arena_owner], arena_owner_system
|
|
; mark as free
|
|
dec dx ; make room for arena
|
|
mov es:[arena_size], dx
|
|
|
|
|
|
mov es, [DevDOSData]
|
|
mov di, UMB_ARENA
|
|
mov es:[di], cx ; initialize umb_head in DOS
|
|
; data segment with the arena
|
|
; just below Top of Mem
|
|
|
|
; we must now scan the arena chain and update the size of the last
|
|
; arena
|
|
|
|
mov di, DOS_ARENA
|
|
mov es, word ptr es:[di] ; es = start arena
|
|
xor di, di
|
|
|
|
|
|
scan_next:
|
|
cmp byte ptr es:[di], arena_signature_end
|
|
jz got_last
|
|
|
|
mov ax, es
|
|
add ax, es:[arena_size]
|
|
inc ax
|
|
mov es, ax
|
|
jmp short scan_next
|
|
|
|
got_last:
|
|
;; -williamh- we reserved the last paragraph for UMB_HEAD already.
|
|
;; refer to sysinit1.asm!goinit
|
|
;; The following instruction was commentted out for this reason.
|
|
;; sub es:[arena_size], 1
|
|
;;
|
|
mov es:[arena_signature], arena_signature_normal
|
|
clc
|
|
ret
|
|
|
|
lfu_err:
|
|
stc
|
|
ret
|
|
LinkFirstUMB endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : ShrinkUMB
|
|
;
|
|
; Shrinks the current UMB in use, so that the unused portions
|
|
; of the UMB is given back to the DOS free mem pool
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
public ShrinkUMB
|
|
|
|
ShrinkUMB proc near
|
|
cmp DevUMBAddr, 0
|
|
je su_exit
|
|
push es
|
|
push bx
|
|
mov bx, DevUMBFree
|
|
sub bx, DevUMBAddr
|
|
mov es, DevUMBAddr
|
|
mov ax, 4a00h
|
|
int 21h
|
|
mov ax, es
|
|
dec ax
|
|
mov es, ax
|
|
mov word ptr es:[arena_owner], 8
|
|
pop bx
|
|
pop es
|
|
su_exit:
|
|
ret
|
|
ShrinkUMB endp
|
|
|
|
;M002 - BEGIN
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : UnlinkUMB
|
|
;
|
|
; Unlinks the UMBs from the DOS arena chain
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
public UnlinkUMB
|
|
|
|
UnlinkUMB proc near
|
|
push ds
|
|
push es
|
|
cmp FirstUMBLinked, 0
|
|
je ulu_x ; nothing to unlink
|
|
mov es, DevDOSData ; get DOS data seg
|
|
mov ds, es:[DOS_ARENA]
|
|
mov di, es:[UMB_ARENA]
|
|
ulu_next:
|
|
call get_next
|
|
jc ulu_x
|
|
cmp di, ax ; is the next one UMB ?
|
|
je ulu_found
|
|
mov ds, ax
|
|
jmp ulu_next
|
|
ulu_found:
|
|
mov ds:[arena_signature], 'Z'
|
|
ulu_x:
|
|
pop es
|
|
pop ds
|
|
ret
|
|
UnlinkUMB endp
|
|
|
|
;M002 - END
|
|
|
|
; =========================================================================
|
|
;
|
|
sysinitseg ends
|
|
end
|