PAGE ,132 ; ; SCCSID = @(#)sysconf.asm 0.0 86/10/20 TITLE BIOS SYSTEM INITIALIZATION %OUT ...SYSCONF ;============================================================================== ;REVISION HISTORY: ;AN000 - New for DOS Version 4.00 - J.K. ;AC000 - Changed for DOS Version 4.00 - J.K. ;AN00x - PTM number for DOS Version 4.00 - J.K. ;============================================================================== ;AN001; P132 Multiple character device installation problem. 06/27/87 J.K. ;AN002; D24 MultiTrack= command added. 06/29/87 J.K. ;AN003; D41 REM command in CONFIG.SYS. 07/6/87 J.K. ;AN004; D184 Set DEVMARK for MEM command 08/25/87 J.K. ;AN005; P568 CONFIG.SYS parsing error with FCBS=10,15 08/31/87 J.K. ;AN006; P887 STACKS=0 does not show "ERROR in CONFIG.SYS..." 09/09/87 J.K. ;AN007; D246, P976 Show "Bad command or parameters - ..." msg 09/22/87 J.K. ;AN008; P1299 Set the second entry of DEVMARK for MEM command 09/25/87 J.K. ;AN009; P1326 New Extended attribute 09/28/87 J.K. ;AN010; P1820 New message SKL file 10/20/87 J.K. ;AN011; P1970 AUTOTEST FCBS= command error msg inconsistent 10/23/87 J.K. ;AN012; P2211 Setting the EA=7 for ANSI.SYS hangs the system 11/02/87 J.K. ;AN013; P2342 REM not allowed after INSTALL command 11/09/87 J.K. ;AN014; P2546 DEVICE= command still allowed after IFS= 11/17/87 J.K. ;AN015; D358 New device driver INIT function package 12/03/87 J.K. ;AN016; D285 Undo the extended error handling 12/17/87 J.K. ;AN017; P3170 Do not call block device driver when drive # > 26 01/20/88 J.K. ;AN018; P3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. ;AN019; D479 New option to disable extended INT 16h function call 02/12/88 J.K. ;AN020; P3607 MEM does not give correct filename 02/24/88 J.K. ;AN021; D493 Undo D358 & do not show error message for device driv 02/24/88 J.K. ;AN022; P3807 Single buffer unprotected - System hangs 03/10/88 J.K. ;AN023; P3797 An INSTALL cmd right after Bad cmd is not executed 03/10/88 J.K. ;AN024; D503 Version change to 4.0 - IBMCACHE.SYS is an exception 03/15/88 J.K. ;AN025; D474 Change BUFFERS= /E option to /X for expanded memory 03/16/88 J.K. ;AN026; D506 Take out the order dependency of the IFS= 03/28/88 J.K. ;AN027; P3957 Undo D503 - IBMCACHE.SYS version check problem 03/30/88 J.K. ;AN028; P4086 Memory allocation error when loading share.exe 03/31/88 J.K. ;AN029; D528 Install XMAEM.SYS first before everything else 04/29/88 J.K. ;AN030; P4759 INT2f, INT 67h handlers for XMA 05/11/88 J.K. ;AN031; P4889 Should check the validity of INT 67h call 05/17/88 G.A. ;AN032; P4934 P4759 INT 2fh number should be changed to 1Bh 05/20/88 J.K. ;AN033; P5002 EMS w/single page allocated now works 05/20/88 G.A. ;AN034; P5128 EMS INT 2FH HANDLER BUG 06/24/88 ;============================================================================== TRUE EQU 0FFFFh FALSE EQU 0 LF equ 10 CR equ 13 TAB equ 9 SEMICOLON equ ';' IBMVER EQU TRUE IBM EQU IBMVER STACKSW EQU TRUE ;Include Switchable Hardware Stacks IBMJAPVER EQU FALSE ;If TRUE set KANJI true also MSVER EQU FALSE ALTVECT EQU FALSE ;Switch to build ALTVECT version KANJI EQU FALSE HAVE_INSTALL_CMD equ 00000001b ;AN018; CONFIG.SYS has INSTALL= commands HAS_INSTALLED equ 00000010b ;AN018; SYSINIT_BASE installed. IS_IFS equ 00000001b ;IFS command? NOT_IFS equ 11111110b ; ;AN016; Undo the extended attribute handling ;;Extended attribute value ;EA_UNSPECIFIED equ 0 ;AN009; ;EA_DEVICE_DRIVER equ 6 ;AN009; ;EA_IFS_DRIVER equ 7 ;AN009; DEFAULT_FILENUM = 8 ; IF IBMJAPVER NOEXEC EQU TRUE ELSE NOEXEC EQU FALSE ENDIF DOSSIZE EQU 0A000H ;dossize equ 0C000H ;J.K. for the debugging version of IBMDOS. .xlist ; INCLUDE dossym.INC include smdossym.inc ;J.K. Reduced version of DOSSYM.INC INCLUDE devsym.INC include ioctl.INC include BIOSTRUC.INC include smifssym.inc ;AN000; Reduced version of IFSSYM.INC. include DEVMARK.inc ;AN004; include version.inc .list IF NOT IBMJAPVER EXTRN RE_INIT:FAR ENDIF ; ;J.K. 6/29/87 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. CODE segment public 'code' EXTRN MulTrk_flag:word ;AN002; extrn KEYRD_Func:byte ;AN019; extrn KEYSTS_Func:byte ;AN019; CODE ends ;J.K. 6/29/87 End of Multi-track definition. SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' 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 BADSIZ_POST:BYTE,BADLD_POST:BYTE EXTRN BADSTACK:BYTE,BADCOUNTRYCOM:BYTE EXTRN SYSSIZE:BYTE,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 DeviceParameters:byte EXTRN MEMORY_SIZE:word EXTRN BUFFERS:word EXTRN FILES:byte,NUM_CDS:byte EXTRN DOSINFO:dword,ENTRY_POINT: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 ;AN000; extrn Install_Flag:word ;AN000; extrn BadOrder:byte ;AN000; extrn Errorcmd:byte ;AN000; extrn LineCount:word ;AN000; extrn ShowCount:byte ;AN000; extrn Buffer_LineNum:word ;AN000; extrn IFS_Flag:word ;AN000; extrn IFS_RH:byte ;AN000; extrn H_Buffers:word ;AN000; extrn Buffer_Slash_X:byte ;AN000;AN025; extrn Badparm:byte ;AN007; extrn ConfigMsgFlag:Word ;AN015; extrn Org_Count:Word ;AN018; extrn Multi_Pass_Id:byte ;AN026; 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 ;AN018; extrn SetDevMark:NEAR ;AN030; ;AN016; Undo the extended attribute handling ; extrn Get_Ext_Attribute:near ;AN009; 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 extrn stack_count:word extrn stack_size:word extrn stack_addr:dword ENDIF PUBLIC DOCONF PUBLIC GETCHR public Multi_Pass ;AN018;AN026; public MultDeviceFlag MultDeviceFlag db 0 ;AN001; public DevMark_Addr DevMark_Addr dw ? ;AN004;Segment address for DEVMARK. public SetDevMarkFlag SetDevMarkFlag db 0 ;AN004;Flag used for DEVMARK EMS_Stub_Installed db 0 ;AN030; Badparm_Ptr label dword Badparm_Off dw 0 ;AN007; Badparm_Seg dw 0 ;AN007; XMAEM_file db 'XMAEM.SYS',0 ;AN029; ;IBMCACHE_file db 'IBMCACHE.SYS',0;AN024;AN026;To cope with the IBMCACHE.SYS ; problem of DOS version checking. ;****************************************************************************** ;Take care of Config.sys file. ;SYSTEM parser data and code. ;****************************************************************************** .xlist include PSOPTION.INC ;Parsing options for SYSCONF. include PARSE.ASM ;together with PSDATA.INC .list ;Control block definitions for PARSER. ;--------------------------------------------------- ; BUFFER = [n | n,m] {/E} Buf_Parms label byte ;AN000; dw Buf_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; Buf_Parmsx label byte ;AN000; db 1,2 ;AN000; Min 1, Max 2 positional dw Buf_Pos1 ;AN000; dw Buf_Pos2 ;AN000; db 1 ;AN000; 1 switch dw SW_X_Ctrl ;AN000;AN025; /X control db 0 ;AN000; no keywords Buf_Pos1 label word ;AN000; dw 8000h ;AN000; Numeric value dw 0 ;AN000; no function dw Result_Val ;AN000; Result value buffer dw Buf_Range_1 ;AN000; value list db 0 ;AN000; no switches/keywords Buf_Range_1 label byte ;AN000; value definition db 1 ;AN000; range definition db 1 ;AN000; 1 definition of range db 1 ;AN000; item tag for this range dd 1,10000 ;AN000; from 1 to 10000 Buf_Pos2 label word ;AN000; dw 8001h ;AN000; Numeric value, Optional dw 0 ;AN000; no function dw Result_Val ;AN000; Result value buffer dw Buf_Range_2 ;AN000; value list db 0 ;AN000; no switches/keywords Buf_Range_2 label byte ;AN000; value definition db 1 ;AN000; range definition db 1 ;AN000; 1 definition of range db 1 ;AN000; item tag for this range dd 0,8 ;AN000; from 0 to 8. SW_X_Ctrl label word ;AN000;AN025; dw 0 ;AN000; no matching flag dw 0 ;AN000; no function dw Result_Val ;AN000; return value dw NoVal ;AN000; no value definition db 1 ;AN000; # of switches Switch_X label byte ;AN000;AN025; db '/X',0 ;AN000;AN025; ;local variables P_Buffers dw 0 ;AN000; P_H_Buffers dw 0 ;AN000; P_Buffer_Slash_X db 0 ;AN000;AN025; Buffer_Pre_Scan db 0 ;AN030; ;Common definitions ------------- NoVal db 0 ;AN000; Result_Val label byte ;AN000; db ? ;AN000; type returned db ? ;AN000; item tag returned dw ? ;AN000; ES:offset of the switch defined RV_Byte label byte ;AN000; RV_Dword label dword ;AN000; dd ? ;AN000; value if number, or seg:offset to string. ;-------------------------------- ; BREAK = [ ON | OFF ] Brk_Parms label byte ;AN000; dw Brk_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; Brk_Parmsx label byte ;AN000; db 1,1 ;AN000; Min 1, Max 1 positional dw Brk_Pos ;AN000; db 0 ;AN000; no switches db 0 ;AN000; no keywords Brk_Pos label word ;AN000; dw 2000h ;AN000; Simple string dw 0 ;AN000; No functions dw Result_Val ;AN000; dw On_Off_String ;AN000; ON,OFF string descriptions db 0 ;AN000; no keyword/switch synonyms On_Off_String label byte ;AN000; db 3 ;AN000; signals that there is a string choice db 0 ;AN000; no range definition db 0 ;AN000; no numeric values choice db 2 ;AN000; 2 strings for choice db 1 ;AN000; the 1st string tag dw On_String ;AN000; db 2 ;AN000; the 2nd string tag dw Off_String ;AN000; On_String db "ON",0 ;AN000; Off_String db "OFF",0 ;AN000; ;local variable P_Ctrl_Break db 0 ;AN000; local variable ;-------------------------------- ; COUNTRY = n {m {path}} ; or ; COUNTRY = n,,path Cntry_Parms label byte ;AN000; dw Cntry_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; Cntry_Parmsx label byte ;AN000; db 1,3 ;AN000; Min 1, Max 3 positional dw Cntry_Pos1 ;AN000; dw Cntry_Pos2 ;AN000; dw Cntry_Pos3 ;AN000; db 0 ;AN000; no switches db 0 ;AN000; no keywords Cntry_Pos1 label word ;AN000; control definition for positional 1 dw 8000h ;AN000; Numeric value dw 0 ;AN000; no functions dw Result_Val ;AN000; dw Cntry_Codepage_Range ;AN000; country id code range description db 0 ;AN000; no switch/keyword synonyms Cntry_Codepage_Range label byte ;AN000; db 1 ;AN000; # of value definitions db 1 ;AN000; # of ranges db 1 ;AN000; Tag for this range dd 1,999 ;AN000; Cntry_Pos2 label word ;AN000; control definition for positional 2 dw 8001h ;AN000; Numeric value, optional dw 0 ;AN000; no functions dw Result_Val ;AN000; dw Cntry_Codepage_Range ;AN000; code page range descriptions. db 0 ;AN000; no switch/keyword synonyms Cntry_Pos3 label word ;AN000; control definition for positional 3 dw 0201h ;AN000; File spec, optional dw 0 ;AN000; No functions. Don't need to CAP. dw Result_Val ;AN000; dw NoVal ;AN000; no value list db 0 ;AN000; no switch/keyword synonyms ;Local variables P_Cntry_Code dw 0 ;AN000; P_Code_Page dw 0 ;AN000; ;-------------------------------- ; FILES = n Files_Parms label byte ;AN000; dw Files_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; Files_Parmsx label byte ;AN000; db 1,1 ;AN000; Min 1, Max 1 positional dw Files_Pos ;AN000; db 0 ;AN000; no switches db 0 ;AN000; no keywords Files_Pos label byte ;AN000; dw 8000h ;AN000; Numeric value dw 0 ;AN000; no functions dw Result_Val ;AN000; dw Files_Range ;AN000; Files range description db 0 ;AN000; no switch/keyword synonyms Files_Range label byte ;AN000; db 1 ;AN000; # of value definitions db 1 ;AN000; # of ranges db 1 ;AN000; Tag for this range dd 8,255 ;AN000; ;local variable P_Files db 0 ;AN000; ;-------------------------------- ; FCBS = n,m FCBS_Parms label byte ;AN000; dw FCBS_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; FCBS_Parmsx label byte ;AN000; db 2,2 ;AN000; Min 2, Max 2 positional dw FCBS_Pos_1 ;AN000; dw FCBS_Pos_2 ;AN000; db 0 ;AN000; no switches db 0 ;AN000; no keywords FCBS_Pos_1 label byte ;AN000; dw 8000h ;AN000; Numeric value dw 0 ;AN000; no functions dw Result_Val ;AN000; dw FCBS_Range ;AN000; FCBS range descriptions db 0 ;AN000; no switch/keyword synonyms FCBS_Range label byte ;AN000; db 1 ;AN000; # of value definitions db 1 ;AN000; # of ranges db 1 ;AN000; Tag for this range dd 1,255 ;AN000; FCBS_Pos_2 label byte ;AN000; dw 8000h ;AN000; Numeric value dw 0 ;AN000; no functions dw Result_Val ;AN000; dw FCBS_Keep_Range ;AN000; FCBS KEEP range descriptions db 0 ;AN000; no switch/keyword synonyms FCBS_Keep_Range label byte ;AN000; db 1 ;AN000; # of value definitions db 1 ;AN000; # of ranges db 1 ;AN000; Tag for this range dd 0,255 ;AN000; ;local variable P_Fcbs db 0 ;AN000; P_Keep db 0 ;AN000; ;-------------------------------- ; LASTDRIVE = x LDRV_Parms label byte ;AN000; dw LDRV_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; LDRV_Parmsx label byte ;AN000; db 1,1 ;AN000; Min 1, Max 1 positional dw LDRV_Pos ;AN000; db 0 ;AN000; no switches db 0 ;AN000; no keywords LDRV_Pos label byte ;AN000; dw 0110h ;AN000; Drive only, Ignore colon. dw 0010h ;AN000; Remove colon at end dw Result_Val ;AN000; dw NoVal ;AN000; No value list db 0 ;AN000; no switch/keyword synonyms ;local variable P_Ldrv db 0 ;AN000; ;-------------------------------- ; STACKS = n,m STKS_Parms label byte ;AN000; dw STKS_Parmsx ;AN000; db 1 ;AN000; An extra delimeter list db 1 ;AN000; length is 1 db SEMICOLON ;AN000; STKS_Parmsx label byte ;AN000; db 2,2 ;AN000; Min 2, Max 2 positional dw STKS_Pos_1 ;AN000; dw STKS_Pos_2 ;AN000; db 0 ;AN000; no switches db 0 ;AN000; no keywords STKS_Pos_1 label byte ;AN000; dw 8000h ;AN000; Numeric value dw 0 ;AN000; no functions dw Result_Val ;AN000; dw STKS_Range ;AN000; number of stack range descriptions db 0 ;AN000; no switch/keyword synonyms STKS_Range label byte ;AN000; db 1 ;AN000; # of value definitions db 1 ;AN000; # of ranges db 1 ;AN000; Tag for this range dd 0,64 ;AN000; STKS_Pos_2 label byte ;AN000; dw 8000h ;AN000; Numeric value dw 0 ;AN000; no functions dw Result_Val ;AN000; dw STK_SIZE_Range ;AN000; stack size range descriptions db 0 ;AN000; no switch/keyword synonyms STK_SIZE_Range label byte ;AN000; db 1 ;AN000; # of value definitions db 1 ;AN000; # of ranges db 1 ;AN000; Tag for this range dd 0,512 ;AN000; ;local variables P_Stack_Count dw 0 ;AN000; P_Stack_Size dw 0 ;AN000; ;-------------------------------- ; MULTITRACK = [ ON | OFF ] MTrk_Parms label byte ;AN002; dw MTrk_Parmsx ;AN002; db 1 ;AN002; An extra delimeter list db 1 ;AN002; length is 1 db SEMICOLON ;AN002; MTrk_Parmsx label byte ;AN002; db 1,1 ;AN002; Min 1, Max 1 positional dw MTrk_Pos ;AN002; db 0 ;AN002; no switches db 0 ;AN002; no keywords MTrk_Pos label word ;AN002; dw 2000h ;AN002; Simple string dw 0 ;AN002; No functions dw Result_Val ;AN002; dw On_Off_String ;AN002; ON,OFF string descriptions db 0 ;AN002; no keyword/switch synonyms ;local variables P_Mtrk db 0 ;AN002; ;-------------------------------- ; CPSW = [ ON | OFF ] CPSW_Parms label byte ;AN002; dw CPSW_Parmsx ;AN002; db 1 ;AN002; An extra delimeter list db 1 ;AN002; length is 1 db SEMICOLON ;AN002; CPSW_Parmsx label byte ;AN002; db 1,1 ;AN002; Min 1, Max 1 positional dw CPSW_Pos ;AN002; db 0 ;AN002; no switches db 0 ;AN002; no keywords CPSW_Pos label word ;AN002; dw 2000h ;AN002; Simple string dw 0 ;AN002; No functions dw Result_Val ;AN002; dw On_Off_String ;AN002; ON,OFF string descriptions db 0 ;AN002; no keyword/switch synonyms ;local variables P_CPSW db 0 ;AN002; ;-------------------------------- ; SWITCHES=/K Swit_Parms label byte ;AN019; dw Swit_Parmsx ;AN019; db 1 ;AN019; An extra delimeter list db 1 ;AN019; length is 1 db SEMICOLON ;AN019; Swit_Parmsx label byte ;AN019; db 0,0 ;AN019; No positionals db 1 ;AN019; 1 switch for now. dw Swit_K_Ctrl ;AN019; /K control db 0 ;AN019; no keywords Swit_K_Ctrl label word ;AN019; dw 0 ;AN019; no matching flag dw 0 ;AN019; no function dw Result_Val ;AN019; return value dw NoVal ;AN019; no value definition db 1 ;AN019; # of switches Swit_K label byte ;AN019; db '/K',0 ;AN019; ;local variables P_Swit_K db 0 ;AN019; ;****************************************************************************** DOCONF: 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 ; JC ENDCONF ;Wasn't there, or couldn't open (sickness) jc No_Config_sys ;AN028; JMP NOPROB ;PROBLEM WITH OPEN No_Config_sys: ;AN028; mov Multi_Pass_Id, 11 ;AN028; set it to unreasonable number ENDCONF: return BADOP: MOV DX,OFFSET BADOPM ;WANT TO PRINT COMMAND ERROR "Unrecognized command..." invoke PRINT call Error_Line ;show "Error in CONFIG.SYS ..." . JMP COFF Badop_p proc near ;AN000; ;Same thing as BADOP, but will make sure to set DS register back to SYSINITSEG ;and return back to the calller. push cs pop ds ;set ds to CONFIGSYS seg. mov dx, offset badopm invoke PRINT call Error_Line ret Badop_p endp Badparm_p proc near ;AN007; ;Show "Bad command or parameters - xxxxxx" ;In Badparm_seg, Badparm_off -> xxxxx ; cmp cs:Buffer_Pre_Scan, 1 ;AN030; Pre scanning Buffers ... /X? je BadParmp_Ret ;AN030; then do not show any message. push ds ;AN007; push dx ;AN007; push si ;AN007; push cs ;AN007; pop ds ;AN007; mov dx, offset Badparm ;AN007; invoke PRINT ;AN007;"Bad command or parameters - " lds si, Badparm_ptr ;AN007; Badparm_Prt: ;AN007;print "xxxx" until CR. mov dl, byte ptr [si] ;AN007; mov ah,STD_CON_OUTPUT ;AN007; int 21h ;AN007; inc si ;AN007; cmp dl, CR ;AN007; jne Badparm_Prt ;AN007; push cs ;AN007; pop ds ;AN007; mov dx, offset CRLFM ;AN007; invoke PRINT ;AN007; call Error_Line ;AN007; pop si ;AN007; pop dx ;AN007; pop ds ;AN007; BadParmp_Ret: ;AN030; ret ;AN007; Badparm_p endp 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,CS mov dx, [ConfBot] ;AN022;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. SaveReg 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 ; CR MOV AL,LF STOSB ; LF SUB DI,DX ; difference moved MOV Count,DI ; new count ; ; Restore registers ; RestoreReg 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:JMP ENDCONF Multi_Pass: ;AN018;AN026; called to execute IFS=, INSTALL= commands push cs ;AN018; pop ds ;AN018; cmp Multi_Pass_id, 10 ;J.K. jae Endconv ;J.K. Do nothing. Just return. push Confbot ;AN018; pop es ;AN018; ES -> Confbot mov si, Org_Count ;AN018; mov Count, si ;AN018; set Count xor si,si ;AN018; mov Chrptr, si ;AN018; reset Chrptr, LineCount mov LineCount, si ;AN018; call GetChr ;AN018; jmp Conflp ;AN018; GETCOM: invoke ORGANIZE ;ORGANIZE THE FILE CALL GETCHR CONFLP: JC ENDCONV call Reset_DOS_Version ;AN024;AN026; Still need to reset version even IBMDOS handles this through ; function 4Bh call, since IBMDOS does not know when Load/Overlay call finishes. IF NOT BUFFERFLAG call EMS_Stub_handler ;AN030; ENDIF inc LineCount ;AN000; Increase LineCount. mov Buffer_Pre_Scan, 0 ;AN030; Reset Buffer_Pre_Scan. mov MultDeviceFlag,0 ;AN001; Reset MultDeviceFlag. mov SetDevMarkFlag,0 ;AN004; Reset SetDevMarkFlag. cmp al, LF ;AN000; LineFeed? je Blank_Line ;AN000; then ignore this line. MOV AH,AL CALL GETCHR jnc TryI ;AN000; cmp Multi_Pass_ID, 2 ;AN026; jae Endconv ;AN026;Do not show Badop again for multi_pass. JMP BADOP COFF: PUSH CS POP DS invoke NEWLINE JMP CONFLP Blank_Line: ;AN000; call Getchr ;AN000; jmp CONFLP ;AN000; COFF_P: push cs pop ds ;J.K. 1/27/88 ;;;;;;;;;;;;;;;;;; ;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 ;AN029; the initial pass for XMAEM.SYS je Multi_Try_XMAEM ;AN029; and BUFFERS= ... /X pre scan. cmp Multi_Pass_Id, 2 ;AN026; the second pass for IFS= ? je Multi_Try_J ;AN026; cmp Multi_Pass_Id, 3 ;AN026; the third pass for INSTALL= ? je Multi_Try_I ;AN026; cmp ah, 'I' ;AN018; INSTALL= command? jne TryB ;AN018; the first pass is for normal operation. or Install_Flag, HAVE_INSTALL_CMD ;AN018; Set the flag jmp coff ;AN018; and handles the next command Multi_Try_XMAEM: ;AN029; cmp ah, 'D' ;AN029; device= command? jne Multi_Try_Buff ;AN029; no skip it. call Chk_XMAEM ;AN029; is it for XMAEM.SYS? jnz Multi_Pass_FIlter ;AN029; no skip it. mov byte ptr es:[si-1], 0FFh ;AN029; mark this command as a Null command for the next pass. jmp TryDJ ;AN029; execute this command. Multi_Try_Buff: ;AN030; cmp ah, 'B' ;AN030; Buffers= command? jne Multi_Pass_Filter ;AN030; mov Buffer_Pre_Scan, 1 ;AN030; Set Buffer_Pre_Scan jmp TryB ;AN030; TryB will set P_Buffer_Slash_X to non-zero value. Multi_Try_J: ;AN026; cmp ah, 'J' ;AN026; IFS= command? jne Multi_Pass_Filter ;AN026; No. Ignore this. jmp GotJ ;AN026; Handles IFS= command. Multi_Try_I: ;AN026; cmp ah, 'I' ;AN026; INSTALL= command? jne Multi_Pass_Filter ;AN026; No. Ignore this. call Do_Install_Exec ;Install it. jmp Coff ;to handle next Install= command. Multi_Pass_Filter: ;AN023;AN026; cmp ah, 'Y' ;AN023; Comment? je Multi_Pass_Adjust ;AN023; cmp ah, 'Z' ;AN023; Bad command? je Multi_Pass_Adjust ;AN023; cmp ah, '0' ;AN023; REM? jne Multi_Pass_Coff ;AN023; ignore the rest of the commands. Multi_Pass_Adjust: ;AN023; These commands need to dec Chrptr ;AN023; adjust chrptr, count inc Count ;AN023; for NEWLINE proc. Multi_Pass_Coff: ;AN023; jmp Coff ;AN018; To handle next INSTALL= commands. ;------------------------------------------------------------------------------ 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 ;AN007;Save the pointer to the parm mov cs:Badparm_Off,si ;AN007; we are about to parse for Badparm msg. mov dx, 0 call SysParse cmp ax, $P_NO_ERROR ;no error ; $IF E,OR JE $$LL1 cmp ax, $P_RC_EOL ;or the end of line? ; $IF E JNE $$IF1 $$LL1: clc ; $ELSE JMP SHORT $$EN1 $$IF1: stc ; $ENDIF $$EN1: pop ds pop es ;restore es,ds ret Sysinit_Parse endp ;------------------------------------------------------------------------------ ; 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' ;BUFFER COMMAND? ; JNZ TRYC ; invoke GETNUM ; JZ TryBBad ; Gotta have at least one ; CMP AX,100 ; check for max number ; JB SaveBuf ;TryBBad:JMP BadOp ;SaveBuf: ; MOV [BUFFERS],AX ;CoffJ1: JMP COFF TryB: CMP AH,'B' JNZ TryC mov P_Buffer_Slash_X, 0 ;AN000;AN025; mov di, offset Buf_Parms ;AN000; xor cx, cx ;AN000; mov dx, cx ;AN000; ; $SEARCH ;AN000; $$DO4: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse Error, JNC $$IF4 call Badparm_p ;AN007; and Show messages and end the search loop. ; $ORELSE ;AN000; JMP SHORT $$SR4 $$IF4: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then jmp to $Endloop for semantic check. JE $$EN4 cmp Result_Val.$P_SYNONYM_PTR, offset Switch_X ;AN000;AN025; ; $IF E ;AN000; JNE $$IF8 mov P_Buffer_Slash_X, 1 ;AN000;AN025; set the flag ; $ELSE ;AN000; JMP SHORT $$EN8 $$IF8: mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; cmp cx, 1 ;AN000; ; $IF E ;AN000; JNE $$IF10 mov P_Buffers, ax ;AN000; ; $ELSE ;AN000; JMP SHORT $$EN10 $$IF10: mov P_H_Buffers, ax ;AN000; ; $ENDIF ;AN000; $$EN10: ; $ENDIF ;AN000; $$EN8: ; $ENDLOOP ;AN000; JMP SHORT $$DO4 $$EN4: cmp P_Buffers, 99 ;AN000; ; $IF A,AND ;AN000; JNA $$IF15 cmp P_Buffer_Slash_X, 0 ;AN000;AN025; ; $IF E ;AN000; JNE $$IF15 call Badparm_p ;AN000; mov P_H_Buffers, 0 ;AN000; ; $ELSE ;AN000; JMP SHORT $$EN15 $$IF15: mov ax, P_Buffers ;AN000; We don't have any problem. mov Buffers, ax ;AN000; Now, let's set it really. mov ax, P_H_Buffers ;AN000; mov H_Buffers, ax ;AN000; mov al, P_Buffer_Slash_X ;AN000;AN025; mov Buffer_Slash_X, al ;AN000;AN025; mov ax, LineCount ;AN000; mov Buffer_LineNum, ax ;AN000; Save the line number for the future use. ; $ENDIF ;AN000; $$EN15: ; $ENDSRCH ;AN000; $$SR4: jmp Coff ;------------------------------------------------------------------------------ ; 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' ; JZ GOTC ; JMP TRYDJ ;GOTC: ; CMP AL,'O' ;FIRST LETTER OF "ON" or "OFF" ; JNZ TryCBad ; CALL GETCHR ; JC TryCBad ; CMP AL,'N' ;SECOND LETTER OF "ON" ; JNZ TryCoff ; MOV AH,SET_CTRL_C_TRAPPING ;TURN ON CONTROL-C CHECK ; MOV AL,1 ; MOV DL,AL ; INT 21H ;CoffJ2: JMP Coff ;TryCOff:CMP AL,'F' ; JNZ TryCBad ; Check for "OFF" ; CALL GetChr ; JC TryCBad ; CMP AL,'F' ; JZ COffJ2 ;TryCBad:JMP BadOp ; TryC: CMP AH,'C' JNZ TRYM mov di, offset Brk_Parms ;AN000; xor cx,cx ;AN000; mov dx,cx ;AN000; ; $SEARCH ;AN000; $$DO19: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse error JNC $$IF19 call Badparm_p ;AN007; Show message and end the serach loop. ; $ORELSE ;AN000; JMP SHORT $$SR19 $$IF19: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then end the $ENDLOOP JE $$EN19 cmp Result_Val.$P_ITEM_TAG, 1 ;AN000; ; $IF E ;AN000; JNE $$IF23 mov P_Ctrl_Break, 1 ;AN000; Turn it on ; $ELSE ;AN000; JMP SHORT $$EN23 $$IF23: mov P_Ctrl_Break, 0 ;AN000; Turn it off ; $ENDIF ;AN000; $$EN23: ; $ENDLOOP ;AN000; we actually set the ctrl break JMP SHORT $$DO19 $$EN19: mov ah, SET_CTRL_C_TRAPPING ;AN000; if we don't have any parse error. mov al, 1 ;AN000; mov dl, P_Ctrl_Break ;AN000; Int 21h ;AN000; ; $ENDSRCH ;AN000; $$SR19: 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: ;AN002; CMP AH,'M' ;AN002; JNZ TRYW ;AN002; mov di, offset Mtrk_Parms ;AN002; xor cx,cx ;AN002; mov dx,cx ;AN002; ; $SEARCH ;AN002; $$DO28: call Sysinit_Parse ;AN002; ; $EXITIF C ;AN002; Parse error JNC $$IF28 call Badparm_p ;AN007; Show message and end the serach loop. ; $ORELSE ;AN002; JMP SHORT $$SR28 $$IF28: cmp ax, $P_RC_EOL ;AN002; End of Line? ; $LEAVE E ;AN002; then end the $ENDLOOP JE $$EN28 cmp Result_Val.$P_ITEM_TAG, 1 ;AN002; ; $IF E ;AN002; JNE $$IF32 mov P_Mtrk, 1 ;AN002; Turn it on temporarily. ; $ELSE ;AN002; JMP SHORT $$EN32 $$IF32: mov P_Mtrk, 0 ;AN002; Turn it off temporarily. ; $ENDIF ;AN002; $$EN32: ; $ENDLOOP ;AN002; we actually set the MulTrk_Flag here. JMP SHORT $$DO28 $$EN28: push ds ;AN002; mov ax, Code ;AN002; mov ds, ax ;AN002; assume ds:Code cmp P_Mtrk, 0 ;AN002; ; $IF E ;AN002; JNE $$IF36 mov MulTrk_Flag, MULTRK_OFF2 ;AN002; 0001h ; $ELSE ;AN002; JMP SHORT $$EN36 $$IF36: mov MulTrk_Flag, MULTRK_ON ;AN002; 8000h ; $ENDIF ;AN002; $$EN36: pop ds ;AN002; assume ds:SYSINITSEG ; $ENDSRCH ;AN002; $$SR28: jmp Coff ;AN002; ;------------------------------------------------------------------------------ ; CPSW command ;------------------------------------------------------------------------------ ;******************************************************************************* ; * ; Function: Parse the parameters of CPSW= command. * ; * ; Input : * ; ES:SI -> parameters in command line. * ; Output: * ; Turn CPSW on or off. * ; * ; Subroutines to be called: * ; Sysinit_Parse * ; Logic: * ; { * ; Set DI to CPSW_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_CPSW, on; * ; else /*OFF */ * ; Set P_CPSW, off; * ; else {Show message;Error_Exit}; * ; }; * ; If (no error) then * ; DOS function call to set CPSW according to P_CPSW. * ; }; * ; * ;******************************************************************************** TryW: ;AN002; CMP AH,'W' ;AN002; JNZ TRYDJ ;AN002; mov di, offset CPSW_Parms ;AN002; xor cx,cx ;AN002; mov dx,cx ;AN002; ; $SEARCH ;AN002; $$DO40: call Sysinit_Parse ;AN002; ; $EXITIF C ;AN002; Parse error JNC $$IF40 call Badparm_p ;AN007; Show message and end the serach loop. ; $ORELSE ;AN002; JMP SHORT $$SR40 $$IF40: cmp ax, $P_RC_EOL ;AN002; End of Line? ; $LEAVE E ;AN002; then end the $ENDLOOP JE $$EN40 cmp Result_Val.$P_ITEM_TAG, 1 ;AN002; ; $IF E ;AN002; JNE $$IF44 mov P_CPSW, 1 ;AN002; Turn it on temporarily. ; $ELSE ;AN002; JMP SHORT $$EN44 $$IF44: mov P_CPSW, 0 ;AN002; Turn it off temporarily. ; $ENDIF ;AN002; $$EN44: ; $ENDLOOP ;AN002; we actually set the MulTrk_Flag here. JMP SHORT $$DO40 $$EN40: mov ah, SET_CTRL_C_TRAPPING ;AN000; The same function number as Ctrl_Break mov al, 4 ;AN000; Set CPSW state function mov dl, P_CPSW ;AN000; 0=off, 1=on Int 21h ;AN000; ; $ENDSRCH ;AN002; $$SR40: jmp Coff ;AN002; ;------------------------------------------------------------------------------ ; Device command ;------------------------------------------------------------------------------ TRYDJ: and cs:IFS_Flag, NOT_IFS ;AN000; Reset the flag CMP AH,'D' JZ GOTDJ CMP AH,'J' jz GOTJ JMP TRYQ GOTJ: ;AN000; IFS= command. or cs:[IFS_Flag], IS_IFS ;AN000; set the flag. cmp Multi_Pass_Id, 2 ;second pass? je GOTDJ ;then proceed jmp Coff ;else ignore this until the second pass. ; jmp GOTDJ_Cont ;GOTD: ; test cs:[IFS_Flag], HAD_IFS ;AN000; Cannot have DEVICE= command after IFS= command. ; jz GOTDJ_Cont ;AN000; ; call Incorrect_Order ;AN000; Display "Incorrect order ..." msg. ; jmp COFF ;AN000; GOTDJ: MOV BX,CS ;DEVICE= or IFS= command. MOV DS,BX MOV WORD PTR [BPB_ADDR],SI MOV WORD PTR [BPB_ADDR+2],ES ;J.K. In case it is for IFS=, then set the parameter pointer. mov word ptr [ifs_rh.IFSR_PARMS@], SI ;AN000; for IFS mov word ptr [ifs_rh.IFSR_PARMS@+2], ES ;AN000; CALL ROUND ;J.K. Set up the DEVMARK entries here for MEM command. ;J.K. Only the DEVMARK_ID and DEVMARK_FILENAME will be set. ;J.K. DEVMARK_SIZE should be set after a successful process of this file. call Set_DevMark ;AN004; inc [MEMHI] ;AN004;Size of DEVMARK is a paragraph!! ;Don't forget decrease MEMHI ; with an unsuccessful process of this file!!. XOR AX,AX MOV WORD PTR [ENTRY_POINT],AX MOV AX,[MEMHI] MOV WORD PTR [ENTRY_POINT+2],AX ;SET ENTRY POINT IF NOT NOEXEC MOV [LDOFF],AX ;SET LOAD OFFSET ENDIF 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 ; We are going to open the cdevice driver and size it as is done ; in LDFIL. The reason we must do this is that EXEC does NO checking ; for us. We must make sure there is room to load the device without ; trashing SYSINIT. This code is not ; perfect (for instance .EXE device drivers are possible) because ; it does its sizing based on the assumption that the file being loaded ; is a .COM file. It is close enough to correctness to be usable. MOV ES,AX ;ES:0 is LOAD addr MOV AX,OPEN SHL 8 ;OPEN THE FILE STC ;IN CASE OF INT 24 INT 21H JC BADLDRESET MOV BX,AX ;Handle in BX ;AN016; UNDO THE EXTENDED ATTRIBUTE HANDLING ; call Get_Ext_Attribute ;AN009; ; jc BadLdReset ;AN009; ; test cs:[IFS_Flag], IS_IFS ;AN009; ; jnz Chk_Ext_Attr_IFS ;AN009; ; cmp al, EA_UNSPECIFIED ;AN009;Check the extended attr. for device driver ; je Ext_Attr_Ok ;AN009; Allow 0 and EA_DEVICE_DRIVER ; cmp al, EA_DEVICE_DRIVER ;AN009; ; je Ext_Attr_Ok ;AN009; ; stc ;AN012;BadLdReset depends on the carry bit. ; jmp BadLdReset ;AN009; ;Chk_Ext_Attr_IFS: ;AN009; ; cmp al, EA_IFS_DRIVER ;AN009; ; je Ext_Attr_Ok ;AN012; ; stc ;AN012; ; jmp BadLdReset ;AN012; ;Ext_Attr_Ok: ;AN009; PUSH DX ; Save pointer to name XOR CX,CX XOR DX,DX MOV AX,(LSEEK SHL 8) OR 2 STC ;IN CASE OF INT 24 INT 21H ; Get file size in DX:AX JNC GO_AHEAD_LOAD MOV AH,CLOSE ; Close file INT 21H POP DX ; Clean stack STC ; Close may clear carry JMP SHORT BADLDRESET GO_AHEAD_LOAD: ; Convert size in DX:AX to para in AX ADD AX,15 ; Round up size for conversion to para ADC DX,0 MOV CL,4 SHR AX,CL MOV CL,12 SHL DX,CL ; Low nibble of DX to high nibble OR AX,DX ; AX is now # of para for file MOV CX,ES ; CX:0 is xaddr ADD CX,AX ; New device will take up to here JC MEM_ERRJY ; WOW!!!! CMP CX,CS:[ALLOCLIM] JB OKLDX MEM_ERRJY: JMP MEM_ERR OKLDX: POP DX ; Recover name pointer MOV AH,CLOSE ; Close file INT 21H MOV BX,CS MOV ES,BX MOV BX,OFFSET PRMBLK ;ES:BX POINTS TO PARAMETERS MOV AL,3 MOV AH,EXEC STC ;IN CASE OF INT 24 INT 21H ;LOAD IN THE DEVICE DRIVER ENDIF BADLDRESET: PUSH DS POP ES ;ES:SI BACK TO CONFIG.SYS PUSH CS POP DS ;DS BACK TO SYSINIT ASSUME DS:SYSINITSEG JNC GOODLD BADBRK: test cs:[SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, jnz Skip0_ResetMEMHI ;AN004; then do not dec cs:[MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. Skip0_ResetMEMHI: cmp byte ptr es:[si], CR ;file name is CR? (Somebody entered "device=" without filename) jne BADBRK_1 jmp BADOP ;show "Unrecognized command in CONFIG.SYS" BADBRK_1: invoke BADLOAD JMP COFF GOODLD: ;J.K. If it is IFS=, then we should set IFS_DOSCALL@ field in IFSHEADER. test cs:[IFS_Flag], IS_IFS ;AN000; jz Skip_IFSHEADER_Set ;AN000; push es ;AN000; push di ;AN000; push ds ;AN000; mov bx, word ptr cs:[ENTRY_POINT+2] ;AN000; mov ds, bx ;AN000; DS:0 will be the header les di, cs:[DosInfo] ;AN000; mov bx, word ptr es:[di.SYSI_IFS_DOSCALL@] ;AN000; mov word ptr ds:[IFS_DOSCALL@], bx ;AN000; mov bx, word ptr es:[di.SYSI_IFS_DOSCALL@]+2 ;AN000; mov word ptr ds:[IFS_DOSCALL@]+2, bx ;AN000; pop ds ;AN000; pop di ;AN000; pop es ;AN000; Skip_IFSHEADER_Set: ;AN000; SaveReg ;INITIALIZE THE DEVICE ; call Chk_IBMCACHE ;AN024 IBMCACHE.SYS problem.;AN026;IBMDOS will handles this thru 4Bh call. Restore:MOV BL,ES:[SI] ; while ((c=*p) != 0) OR BL,BL JZ Got INC SI ; p++; JMP Restore Got: MOV BYTE PTR ES:[SI],' ' ; *p = ' '; SaveReg PUSH CS POP ES test cs:[IFS_Flag], IS_IFS ;AN000; jz Got_Device_Com ;AN000; mov bx, IFS_CALL@ ;AN000; offset from the start of IFSHEADER call CallIFS ;AN000; jmp short End_Init_Call Got_Device_Com: push ds ;AN017; push si ;AN017; lds si, cs:[ENTRY_POINT] ;AN017; Peeks the header attribute test word ptr ds:[si.SDEVATT], DEVTYP ;AN017;Block device driver? jnz Got_Device_Com_Cont ;AN017;No. lds si, cs:[DOSINFO] ;AN017; DS:SI -> SYS_VAR cmp ds:[si.SYSI_NUMIO], 26 ;AN017; No more than 26 drive number jb Got_Device_Com_Cont ;AN017; pop si ;AN017; pop ds ;AN017; pop si ;AN017;clear the stack pop es ;AN017; jmp BadNumBlock ;AN017; Got_Device_Com_Cont: ;AN017; pop si ;AN017; pop ds ;AN017; MOV BX,SDEVSTRAT invoke CALLDEV ; CallDev (SDevStrat); MOV BX,SDEVINT invoke CALLDEV ; CallDev (SDevInt); End_Init_Call: RestoreReg MOV BYTE PTR [SI],0 ; *p = 0; PUSH CS POP DS test [IFS_Flag], IS_IFS ;AN000; jz Was_Device_Com ;AN000; cmp [ifs_rh.IFSR_RETCODE], 0 ;AN000; Was a success ? jne Erase_Dev_do ;AN000; pop si ;AN000; restore es:si to clean up the pop es ;AN000; stack for Set_Break call. mov ax, word ptr [Entry_Point+2] ;AN000; Get the loaded segment add ax, word ptr [ifs_rh.IFSR_RESSIZE] ;AN000; mov word ptr [Break_addr], 0 ;AN000; mov word ptr [Break_addr+2], ax ;AN000; or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN004; invoke Set_Break ;AN000; Will also check the memory size too. push es ;AN000; Save it again, in case, for Erase_Dev_Do. push si ;AN000; jc Erase_Dev_do ;AN000; Link_IFS: ;AN000; les di, cs:[dosinfo] ;AN000; mov cx, word ptr es:[di.SYSI_IFS] ;AN000; save old pointer mov dx, word ptr es:[di.SYSI_IFS+2] ;AN000; lds si, cs:[Entry_Point] ;AN000; mov word ptr es:[di.SYSI_IFS],si ;AN000; mov word ptr es:[di.SYSI_IFS+2], ds ;AN000; mov word ptr ds:[si], cx ;AN000; We don't permit multiple IFSs. mov word ptr ds:[si+2], dx ;AN000; pop si ;AN000; Restore es:si for the next command. pop es ;AN000; ; mov cs:[IFS_Flag], HAD_IFS ;AN014; Set the flag. jmp COFF ;AN000; ERASE_DEV_do: ;AC000;; Modified to show message "Error in CONFIG.SYS..." pop si pop es push cs pop ds test [SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, jnz Skip1_ResetMEMHI ;AN004; then do not dec [MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. Skip1_ResetMEMHI: cmp ConfigMsgFlag, 0 ;AN015; je No_Error_Line_Msg ;AN015; call Error_Line ;AN021; No "Error in CONFIG.SYS" msg for device driver. DCR D493 mov ConfigMsgFlag, 0 ;AN015;AN021;Set the default value again. No_Error_Line_Msg: ;AN015; JMP Coff Was_Device_Com: ;AN000; MOV AX,WORD PTR [BREAK_ADDR+2] CMP AX,[MEMORY_SIZE] JB BREAKOK POP SI POP ES JMP BADBRK BREAKOK: LDS DX,[ENTRY_POINT] ;SET DS:DX TO HEADER MOV SI,DX ADD SI,SDEVATT ;DS:SI POINTS TO ATTRIBUTES LES DI,CS:[DOSINFO] ;ES:DI POINT TO DOS INFO MOV AX,DS:[SI] ;GET ATTRIBUTES TEST AX,DEVTYP ;TEST IF BLOCK DEV JZ ISBLOCK or cs:[SetDevMarkFlag],FOR_DEVMARK ;AN004; invoke Set_Break ; Go ahead and alloc mem for device jc Erase_Dev_do ;device driver's Init routien failed. TEST AX,ISCIN ;IS IT A CONSOLE IN? JZ TRYCLK MOV WORD PTR ES:[DI.SYSI_CON],DX MOV WORD PTR ES:[DI.SYSI_CON+2],DS TRYCLK: TEST AX,ISCLOCK ;IS IT A CLOCK DEVICE? JZ GOLINK MOV WORD PTR ES:[DI+SYSI_CLOCK],DX MOV WORD PTR ES:[DI+SYSI_CLOCK+2],DS GOLINK: JMP LINKIT ISBLOCK: MOV AL,CS:[UNITCOUNT] ;IF NO UNITS FOUND, erase the device OR AL,AL jz Erase_Dev_do ; JNZ PERDRV ; MOV AX, -1 ; JMP ENDDEV PERDRV: CBW ; WARNING NO DEVICE > 127 UNITS MOV CX,AX MOV DH,AH MOV DL,ES:[DI.SYSI_NUMIO] ;GET NUMBER OF DEVICES MOV AH,DL ADD AH,AL ; Check for too many devices CMP AH,26 ; 'A' - 'Z' is 26 devices JBE OK_BLOCK BadNumBlock: ;AN017; PUSH CS POP DS MOV DX,OFFSET BADBLOCK invoke PRINT JMP ERASE_DEV_do OK_BLOCK: or cs:[SetDevMarkFlag],FOR_DEVMARK ;AN004; invoke SET_BREAK ; Alloc the device ADD ES:[DI.SYSI_NUMIO],AL ;UPDATE THE AMOUNT ADD CS:DriveNumber,AL ; remember amount for next device LDS BX,CS:[BPB_ADDR] ;POINT TO BPB ARRAY PERUNIT: LES BP,CS:[DOSINFO] LES BP,DWORD PTR ES:[BP.SYSI_DPB] ;GET FIRST DPB SCANDPB:CMP WORD PTR ES:[BP.DPB_NEXT_DPB],-1 JZ FOUNDPB LES BP,ES:[BP.DPB_NEXT_DPB] JMP SCANDPB FOUNDPB: MOV AX,CS:[MEMLO] MOV WORD PTR ES:[BP.DPB_NEXT_DPB],AX MOV AX,CS:[MEMHI] MOV WORD PTR ES:[BP.DPB_NEXT_DPB+2],AX LES BP,DWORD PTR CS:[MEMLO] ADD WORD PTR CS:[MEMLO],DPBSIZ or cs:[SetDevMarkFlag], FOR_DEVMARK ;AN004;Add DPB area for this unit CALL ROUND ;Check for alloc error MOV WORD PTR ES:[BP.DPB_NEXT_DPB],-1 MOV ES:[BP.DPB_FIRST_ACCESS],-1 MOV SI,[BX] ;DS:SI POINTS TO BPB INC BX INC BX ;POINT TO NEXT GUY MOV WORD PTR ES:[BP.DPB_DRIVE],DX MOV AH,SETDPB ;HIDDEN SYSTEM CALL INT 21H MOV AX,ES:[BP.DPB_SECTOR_SIZE] PUSH ES LES DI,CS:[DOSINFO] ;ES:DI POINT TO DOS INFO CMP AX,ES:[DI.SYSI_MAXSEC] POP ES ja Bad_BPB_Size_Sector PUSH DS PUSH DX LDS DX,CS:[ENTRY_POINT] MOV WORD PTR ES:[BP.DPB_DRIVER_ADDR],DX MOV WORD PTR ES:[BP.DPB_DRIVER_ADDR+2],DS POP DX POP DS INC DX INC DH LOOP PERUNIT PUSH CS POP DS CALL TEMPCDS ; Set CDS for new drives LINKIT: LES DI,CS:[DOSINFO] ;ES:DI = DOS TABLE MOV CX,WORD PTR ES:[DI.SYSI_DEV] ;DX:CX = HEAD OF LIST MOV DX,WORD PTR ES:[DI.SYSI_DEV+2] LDS SI,CS:[ENTRY_POINT] ;DS:SI = DEVICE LOCATION 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:[ENTRY_POINT],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 ;AN001; Possibly multiple device driver. JMP GOODLD ;OTHERWISE PRETEND WE LOADED IT IN COFFJ3: mov cs:MultDeviceFlag, 0 ;AN001; Reset the flag JMP COFF Bad_BPB_Size_Sector: POP SI POP ES MOV DX,OFFSET BADSIZ_PRE ; MOV BX,OFFSET BADSIZ_POST mov bx, offset CRLFM ;AN???; invoke PRNERR test [SetDevMarkFlag],SETBRKDONE ;AN004;If already Set_Break is done, jnz Skip2_ResetMEMHI ;AN004; then do not dec [MEMHI] ;AN004;Adjust MEMHI by a paragrah of DEVMARK. Skip2_ResetMEMHI: JMP COFF ;------------------------------------------------------------------------------ ; Country command ; J.K. 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: ; invoke GETNUM ; JZ TryQBad ; 0 is never a valid code, or number is ; ; bad ; MOV BX,AX ; Country code in BX ; ; ;J.K. 5/26/86 ; MOV DX,0 ; assume no code page id ; ; invoke skip_delim ;skip the delimeters after the first num ; jc TryQ_Def_File ;no more characters left? then use default file ; cmp al, CR ; ; je TryQ_Def_File ; cmp al, LF ; jne TRYQ_YES_EXTENDED ; inc [COUNT] ;This is for NEWLINE routine in COFF. ; dec [CHRPTR] ;COFFJ41: ; JMP TryQ_Def_File ;O.K. no code page, no path specified. Use default path. ; ;TRYQ_YES_EXTENDED: ; cmp al, ',' ;was the second comma? ; jne TryQ_GETNUM ; invoke skip_delim ;Yes, skip ',' and other possible delim ; jmp short TRYQ_PATH ;and No code page id entered. ;TRYQ_GETNUM: ; invoke GETNUM ; jc TryQBadCOM ;"Country=xxx,path" will not be accepted. ;; jc TRYQ_PATH ;Codepage is not specified. No code page. ;; ;At this point, AL already contain the ;; ;first char of the PATH. ; jz TryQBad ;codepage=0 entered. Error ; mov DX, AX ;save code page in DX ; invoke skip_delim ;move CHRPTR to the path string ; jc TryQ_Def_File ;no more char? then use default filename ; cmp al, CR ; je TryQ_Def_File ; cmp al, LF ; jne TryQ_PATH ;path entered. ; inc [COUNT] ; dec [CHRPTR] ;TryQ_Def_File: ; push dx ;save code page ; mov cs:CNTRY_DRV, 0 ;flag that the default path has been used!!! ; mov dx, offset CNTRY_ROOT ;the default path ; jmp TRYQ_OPEN ; ;TryQBad: ;"Invalid country code or code page" ; STC ; MOV DX,OFFSET BADCOUNTRY ; jmp TryQChkErr ; ;TryQBadCOM: ;Error in COUNTRY command ; STC ; MOV DX,OFFSET BADCOUNTRYCOM ; jmp TryQChkErr ; ;TRYQ_PATH: ;DS - sysinitseg, ES - CONFBOT, ; mov CX, [COUNT] ;AL - the first char of path ; inc CX ;BX - country id, DX - codepage id, 0 = No code page ; mov DI, SI ;TRYQ_PATH_LOOP: ;find the end of path to put 0 after that. ; mov AL, byte ptr ES:[DI] ; call delim ; jz TRYQ_PATH_END ; cmp al, 13 ; jz TRYQ_PATH_END ; inc DI ; jmp short TRYQ_PATH_LOOP ;TryQBad_Brg:jmp short TryQBad ;TRYQ_PATH_END: ; mov es:byte ptr [di], 0 ;make it a ASCIIZ string. (Organize did not handle this string) ; push ds ;switch ds,es ; push es ; pop ds ; pop es ; ; mov di, offset CNTRY_DRV ;move the user specified path to CNTRY_DRV ; call Move_ASCIIZ ; ; push ds ;restore ds,es ; push es ; pop ds ; pop es ; ;; call Set_Country_Path ;set CNTRY_DRV ; ; push dx ;save DX ; mov dx, offset CNTRY_DRV ;Now DS:DX -> CNTRY_DRV mov Cntry_Drv, 0 ;AN000; Reset the drive,path to default value. mov P_Code_Page,0 ;AN000; mov di, offset Cntry_Parms ;AN000; xor cx,cx ;AN000; mov dx,cx ;AN000; ; $SEARCH ;AN000; $$DO49: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse error, check the error code and JNC $$IF49 call Cntry_Error ;AN000; Show message and end the serach loop. mov P_Cntry_Code, -1 ;AN000; Signals that parse error. ; $ORELSE ;AN000; JMP SHORT $$SR49 $$IF49: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then end the $SEARCH LOOP JE $$EN49 cmp Result_Val.$P_TYPE, $P_NUMBER ;AN000; Numeric? ; $IF E ;AN000; JNE $$IF53 mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; cmp cx, 1 ;AN000; ; $IF E ;AN000; JNE $$IF54 mov P_Cntry_Code, ax ;AN000; ; $ELSE ;AN000; JMP SHORT $$EN54 $$IF54: mov P_Code_Page, ax ;AN000; ; $ENDIF ;AN000; $$EN54: ; $ELSE ;AN000; Path entered. JMP SHORT $$EN53 $$IF53: push ds ;AN000; push es ;AN000; push si ;AN000; push di ;AN000; push cs ;AN000; pop es ;AN000; lds si, RV_Dword ;AN000; Move the path to known place. mov di, offset CNTRY_Drv ;AN000; call Move_ASCIIZ ;AN000; pop di ;AN000; pop si ;AN000; pop es ;AN000; pop ds ;AN000; ; $ENDIF ;AN000; $$EN53: ; $ENDLOOP JMP SHORT $$DO49 $$EN49: ; $ENDSRCH ;AN000; $$SR49: cmp P_Cntry_Code, -1 ;AN000; Had a parse error? jne TRYQ_OPEN ;AN000; jmp Coff ;AN000; TryQBad: ;"Invalid country code or code page" STC MOV DX,OFFSET BADCOUNTRY jmp TryQChkErr TRYQ_OPEN: cmp CNTRY_Drv, 0 ;AC000; je TRYQ_Def ;AC000; mov dx, offset CNTRY_Drv ;AC000; jmp TryQ_Openit ;AC000; TRYQ_Def: ;AC000; mov dx, offset CNTRY_Root ;AC000; 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 ;AN000; mov dx, cs:P_Code_Page ;AN000; Now, AX=country id, bx=filehandle ; xchg ax, bx ;now, AX = country id, BX = file handle mov cx, cs:[MEMHI] add cx, 128 ;I need 2K buffer to handle COUNTRY.SYS 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 ;AN000; pop es ;AN000; cmp cs:CNTRY_DRV,0 ;Is the default file used? je TryQDefBad ; mov si, cs:[CONFBOT] ; mov es, si ; mov si, cs:[CHRPTR] ; dec si ;ES:SI -> path in CONFBOT mov si, offset CNTRY_Drv jmp short TryQBADLOAD TryQDefBad: ;Default file has been used. ; push cs ; pop es 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 invoke PRINT ;else show error message call Error_Line ;AN000; 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 ; $IF E JNE $$IF61 mov dx, offset BadCountry ;"Invalid country code or code page" ; $ELSE JMP SHORT $$EN61 $$IF61: mov dx, offset BadCountryCom ;"Error in CONTRY command" ; $ENDIF $$EN61: invoke 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 ; invoke GETNUM ; CMP AX,5 ;j.k. change it to 8!!!!!!!! ; JB TryFBad ; Gotta have at least 5 ; CMP AX,256 ; JAE TryFBad ; Has to be a byte ; MOV [FILES],AL ;CoffJ5: JMP COFF ;TryFBad:JMP BadOp mov di, offset Files_Parms ;AN000; xor cx, cx ;AN000; mov dx, cx ;AN000; ; $SEARCH ;AN000; $$DO64: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse Error, JNC $$IF64 call Badparm_p ;AN007; and Show messages and end the search loop. ; $ORELSE ;AN000; JMP SHORT $$SR64 $$IF64: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then end the $ENDLOOP JE $$EN64 mov al, byte ptr Result_Val.$P_PICKED_VAL ;AN000; mov P_Files, al ;AN000; Save it temporarily ; $ENDLOOP ;AN000; JMP SHORT $$DO64 $$EN64: mov al, P_Files ;AN000; mov Files, al ;AN000; No error. Really set the value now. ; $ENDSRCH ;AN000; $$SR64: 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 ; OR AL,020h ; SUB AL,'a' ; JB TryLBad ; INC AL ; CMP AL,26 ; a-z are allowed ; JA TryLBad ; MOV [NUM_CDS],AL ;CoffJ6: JMP COFF ;TryLBad:JMP BadOp mov di, offset LDRV_Parms ;AN000; xor cx, cx ;AN000; mov dx, cx ;AN000; ; $SEARCH ;AN000; $$DO70: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse Error, JNC $$IF70 call Badparm_p ;AN007; and Show messages and end the search loop. ; $ORELSE ;AN000; JMP SHORT $$SR70 $$IF70: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then end the $ENDLOOP JE $$EN70 mov al, RV_Byte ;AN000; Pick up the drive number mov P_Ldrv, al ;AN000; Save it temporarily ; $ENDLOOP ;AN000; JMP SHORT $$DO70 $$EN70: mov al, P_Ldrv ;AN000; ; sub al, 'A' ;AN000; Convert it to drive number ; inc al ;AN000; make it to be a number of drives. mov Num_CDS, al ;AN000; No error. Really set the value now. ; $ENDSRCH ;AN000; $$SR70: jmp Coff ;------------------------------------------------------------------------------- ; Setting Drive Parameters ;------------------------------------------------------------------------------- TRYP: CMP AH,'P' JNZ TRYK invoke PARSELINE JC TryPBad invoke SETPARMS INVOKE 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 ; MOV SepChr,',' ; INVOKE GetNum ; Get number of stacks ; MOV SepChr,0 ; cmp ax, 0 ;J.K. 5/5/86 ; je TRYK_0 ;J.K. Let's accept 0. ; CMP AX, MinCount ; 8 <= Number of Stacks <= 64 ; JB TryKBad ; CMP AX, MaxCount ; JA TryKBad ;TRYK_0: ; MOV [STACK_COUNT], AX ; ; Skip delimiters after the first number. ; ; invoke Skip_delim ;J.K. ; JC TryKBad ; ; INVOKE GetNum ; Get size of individual stack ; JC TryKBad ; Number bad ; ; cmp ax, 0 ;J.K. 5/5/86 ; je TRYK_SIZE0 ;J.K. 5/5/86. Accept 0 ; ; CMP AX, MinSize ; 32 <= Stack Size <= 512 ; JB TryKBad ; CMP AX, MaxSize ; JA TryKBad ;TRYK_SIZE0: ; MOV [STACK_SIZE], AX ; cmp ax,0 ; je TRYK_BOTH0 ;TRYK_OK: ; mov word ptr [stack_addr], -1 ;set the flag that the user entered stacks= command. ; JMP COFF ;TRYK_BOTH0: ; cmp [STACK_COUNT],0 ;stack_size = 0. Stack_Count = 0 too? ; je TRYK_OK ;yes. accepted. ;TryKBad: ; MOV DX, OFFSET BADSTACK ;J.K. 5/26/86 "Invalid stack parameter" ; invoke PRINT ; JMP COFF Do_TryK: mov di, offset STKS_Parms ;AN000; xor cx, cx ;AN000; mov dx, cx ;AN000; ; $SEARCH ;AN000; $$DO76: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse Error, JNC $$IF76 mov dx, offset BadStack ;AN000; "Invalid stack parameter" call Print ;AN000; and Show messages and end the search loop. call Error_Line ;AN006; ; $ORELSE ;AN000; JMP SHORT $$SR76 $$IF76: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then end the $ENDLOOP JE $$EN76 mov ax, word ptr Result_Val.$P_PICKED_VAL ;AN000; cmp cx, 1 ;AN000; ; $IF E ;AN000; JNE $$IF80 mov P_Stack_Count, ax ;AN000; ; $ELSE ;AN000; JMP SHORT $$EN80 $$IF80: mov P_Stack_Size, ax ;AN000; ; $ENDIF ;AN000; $$EN80: ; $ENDLOOP ;AN000; JMP SHORT $$DO76 $$EN76: cmp P_Stack_Count, 0 ;AN000; ; $IF NE ;AN000; JE $$IF84 cmp P_Stack_Count, MINCOUNT ;AN000; ; $IF B,OR ;AN000; JB $$LL85 cmp P_Stack_Size, MINSIZE ;AN000; ; $IF B ;AN000; JNB $$IF85 $$LL85: mov P_Stack_Count, -1 ;AN000; Invalid ; $ENDIF ;AN000; $$IF85: ; $ELSE ;AN000; JMP SHORT $$EN84 $$IF84: cmp P_Stack_Size, 0 ;AN000; ; $IF NE ;AN000; JE $$IF88 mov P_Stack_Count, -1 ;AN000; Invalid ; $ENDIF ;AN000; $$IF88: ; $ENDIF ;AN000; $$EN84: cmp P_Stack_Count, -1 ;AN000; Invalid? ; $IF E ;AN000; JNE $$IF91 mov Stack_Count, DEFAULTCOUNT ;AN000;Reset to default value. mov Stack_Size, DEFAULTSIZE ;AN000; mov word ptr STACK_ADDR, 0 ;AN000; mov dx, offset BadStack ;AN000; call Print ;AN000; call Error_Line ;AN006; ; $ELSE ;AN000; JMP SHORT $$EN91 $$IF91: mov ax, P_Stack_Count ;AN000; mov Stack_Count, ax ;AN000; mov ax, P_Stack_Size ;AN000; mov Stack_Size, ax ;AN000; mov word ptr Stack_Addr, -1 ;AN000;STACKS= been accepted. ; $ENDIF ;AN000; $$EN91: ; $ENDSRCH ;AN000; $$SR76: jmp Coff ENDIF ;------------------------------------------------------------------------------ ; Switch command ;No longer supported. ;------------------------------------------------------------------------------ ;TRYW: ; CMP AH,'W' ; JNZ TRYA ; JMP BadOp ; no longer implemented ; MOV DL,AL ; MOV AX,(CHAR_OPER SHL 8) OR 1 ;SET SWITCH CHARACTER ; MOV [COMMAND_LINE+1],DL ; INT 21H ; JMP COFF ;------------------------------------------------------------------------------ ; Availdev command ;No longer supported. ;------------------------------------------------------------------------------ ;TRYA: ; CMP AH,'A' ; JNZ TRYS ; JMP BadOp ; NO LONGER IMPLEMENTED ; CMP AL,'F' ;FIRST LETTER OF "FALSE" ; JNZ COFFJ7 ; MOV AX,(CHAR_OPER SHL 8) OR 3 ;TURN ON "/DEV" PREFIX ; XOR DL,DL ; INT 21H ;COFFJ7: JMP COFF ;------------------------------------------------------------------------------ ; 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 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 ; invoke GETNUM ; JZ TryXBad ; gotta have at least one ; CMP AX,256 ; JAE TryXBad ; Can't be more than 8 bits worth ; MOV [FCBS],AL ; ; Skip delimiters after the first number including "," ; ; invoke Skip_delim ;J.K. ; jc tryxbad ; invoke GetNum ; JC TryXBad ; Number bad (Zero is OK here) ; CMP AX,256 ; JAE TryXBad ; CMP AL,FCBS ; JA TryXBad ; MOV Keep,AL ; JMP COFF ;TryXBad:JMP BadOp mov di, offset FCBS_Parms ;AN000; xor cx, cx ;AN000; mov dx, cx ;AN000; ; $SEARCH ;AN000; $$DO95: call Sysinit_Parse ;AN000; ; $EXITIF C ;AN000; Parse Error, JNC $$IF95 call Badparm_p ;AN007; and Show messages and end the search loop. ; $ORELSE ;AN000; JMP SHORT $$SR95 $$IF95: cmp ax, $P_RC_EOL ;AN000; End of Line? ; $LEAVE E ;AN000; then end the $ENDLOOP JE $$EN95 mov al, byte ptr Result_Val.$P_PICKED_VAL ;AN000; cmp cx, 1 ;AN000; The first positional? ; $IF E ;AN000; JNE $$IF99 mov P_Fcbs, al ;AN000; ; $ELSE ;AN000; JMP SHORT $$EN99 $$IF99: mov P_Keep, al ;AN000; ; $ENDIF ;AN000; $$EN99: ; $ENDLOOP ;AN000; JMP SHORT $$DO95 $$EN95: mov al, P_Fcbs ;AN005;make sure P_Fcbs >= P_Keep cmp al, P_Keep ;AN005; ; $IF B ;AN005; JNB $$IF103 ; call Badop_p ;AN005; call Badparm_p ;AN011;show "Bad parameter -" msg. mov P_Keep, 0 ;AN005; ; $ELSE ;AN005; JMP SHORT $$EN103 $$IF103: mov Fcbs, al ;AN000; No error. Really set the value now. mov al, P_Keep ;AN000; mov Keep, al ;AN000; ; $ENDIF ;AN005; $$EN103: ; $ENDSRCH ;AN000; $$SR95: jmp Coff ;------------------------------------------------------------------------------ ; Comment= Do nothing. Just decrese CHRPTR, and increase COUNT for correct ; line number ;------------------------------------------------------------------------------ TRYY: ;AN000; cmp ah, 'Y' ;AN000; jne Try0 ;AN000; DoNothing: dec CHRPTR ;AN000; inc COUNT ;AN000; jmp COFF ;AN000; ;------------------------------------------------------------------------------ ; REM command ;------------------------------------------------------------------------------ Try0: ;AN003;do nothing with this line. cmp ah, '0' ;AN003; je DoNothing ;AN003; ;------------------------------------------------------------------------------ ; 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' ;AN019;Switches= command entered? jne Tryz ;AN019; mov di, offset Swit_Parms ;AN019; xor cx, cx ;AN019; mov dx, cx ;AN019; ; $SEARCH ;AN019; $$DO107: call Sysinit_Parse ;AN019; ; $EXITIF C ;AN019; Parse Error, JNC $$IF107 call Badparm_p ;AN019; and Show messages and end the search loop. ; $ORELSE ;AN019; JMP SHORT $$SR107 $$IF107: cmp ax, $P_RC_EOL ;AN019; End of Line? ; $LEAVE E ;AN019; then jmp to $Endloop for semantic check. JE $$EN107 cmp Result_Val.$P_SYNONYM_PTR, offset Swit_K ;AN019; ; $IF E ;AN019; JNE $$IF111 mov P_Swit_K, 1 ;AN019; set the flag ; $ENDIF ;AN019; $$IF111: ; $ENDLOOP ;AN019; JMP SHORT $$DO107 $$EN107: cmp P_Swit_K, 1 ;AN019;If /K entered, push ds ;AN019; mov ax, Code ;AN019; mov ds, ax ;AN019; assume ds:Code ;AN019; ; $IF E ;AN019; JNE $$IF114 mov KEYRD_Func, 0 ;AN019;Use the conventional keyboard functions mov KEYSTS_Func, 1 ;AN019; ; $ENDIF ;AN019; $$IF114: pop ds ;AN019; assume ds:SYSINITSEG ;AN019; ; $ENDSRCH ;AN019; $$SR107: jmp Coff ;AN019; ;------------------------------------------------------------------------------ ; Bogus command ;------------------------------------------------------------------------------ TRYZ: cmp ah, 0FFh ;AN029; je TryFF ;AN029; dec CHRPTR inc COUNT JMP BADOP ;------------------------------------------------------------------------------ ; Null command ;------------------------------------------------------------------------------ TryFF: ;AN029;Skip this command. jmp DoNothing ;AN029; GETCHR: PUSH CX MOV CX,COUNT JCXZ NOCHAR MOV SI,CHRPTR MOV AL,ES:[SI] DEC COUNT INC CHRPTR CLC GET_RET: POP CX return NOCHAR: STC JMP SHORT GET_RET Incorrect_Order proc near ;AN000; ;Show "Incorrect order in CONFIG.SYS ..." message. mov dx, offset BADORDER ;AN000; call print ;AN000; call ShowLineNum ;AN000; ret ;AN000; Incorrect_Order endp ;AN000; ; public Error_Line Error_Line proc near ;AN000; ;Show "Error in CONFIG.SYS ..." message. push cs ;AN000; pop ds ;AN000; mov dx, offset ErrorCmd ;AN000; call print ;AN000; call ShowLineNum ;AN000; ret ;AN000; Error_Line endp ;AN000; ; ShowLineNum proc near ;AN000; ;J.K. 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. push es ;AN000; push ds ;AN000; push di ;AN000; push cs ;AN000; pop es ;AN000; es=cs push cs ;AN000; pop ds ;AN000; ; mov ax, ' ' ; mov di, offset ShowCount ;clean it up. ; stosw ; stosw ; stosb ;lenght of ShowCount is 5. ; dec di ;let DI points to the least significant ASCII field. mov di, offset ShowCount+4 ;AN000; DI -> the least significant decimal field. mov cx, 10 ;AN000; decimal devide factor mov ax, cs:LineCount ;AN000; SLN_Loop: ;AN000; cmp ax, 10 ;AN000; < 10? jb SLN_Last ;AN000; xor dx,dx ;AN000; div cx ;AN000; or dl, 30h ;AN000; add "0" (= 30h) to make it an ascii. mov [di],dl ;AN000; dec di ;AN000; jmp SLN_Loop ;AN000; SLN_Last: ;AN000; or al, 30h ;AN000; mov [di],al ;AN000; mov dx, di ;AN000; call print ;AN000; show it. pop di ;AN000; pop ds ;AN000; pop es ;AN000; ret ;AN000; ShowLineNum endp ;AN000; CallIFS proc near ;AN000; ;******************************************************************************* ; Function: Interface to IFS call. This procedure will call IFS_CALL@ * ; * ; Input : * ; Entry_Point - Segment:Offset of loaded IFS. * ; BX = IFS_CALL@ (offset of IFS_CALL@ from the IFS header) * ; ES = Segment of IFS request header * ; IFS_Packet - IFS Request packet * ; * ; Output: Nothing * ;******************************************************************************* push ax ;AN000; mov ds, word ptr cs:[Entry_Point+2] ;AN000; add bx, word ptr cs:[Entry_Point] ;AN000; DS:[BX] = Real IFS_CALL@ addr. mov ax, ds:[bx] ;AN000; save it push word ptr cs:[Entry_Point] ;AN000; save Entry point offset mov word ptr cs:[Entry_Point], ax ;AN000; set for the call mov bx, offset IFS_RH ;AN000; Now, ES:BX -> Request packet call cs:[Entry_Point] ;AN000; Far call pop word ptr cs:[Entry_Point] ;AN000; Restore Entry point offset pop ax ;AN000; ret ;AN000; CallIFS endp ;AN000; Set_DevMark proc near ;AN004; ;******************************************************************************* ; 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 ;AN004; push si ;AN004; push es ;AN004; push di ;AN004; mov di, cs:[MEMHI] ;AN004; mov ds, di ;AN004; assume ds:nothing ;AN004; mov [DevMark_Addr], di ;AN004; save the DEVMARK address for the future. test [IFS_Flag], IS_IFS ;AN004; jnz SDVMK_IFS ;AN004; mov al, DEVMARK_DEVICE ;AN004; ='D' jmp short SDVMK_ID ;AN004; SDVMK_IFS: mov al, DEVMARK_IFS ;AN004; ='I' SDVMK_ID: ;AN004; mov ds:[DEVMARK_ID], al ;AN004; inc di ;AN008; mov ds:[DEVMARK_SEG], di ;AN008; xor al,al ;AN004; push si ;AN004; pop di ;AN004; now es:si = es:di = [path]filename,0 mov cx, 128 ;AN004; Maximum 128 char repnz scasb ;AN004; find 0 dec di ;AN020; Now es:di-> 0 SDVMK_Backward: ;AN004; find the pointer to the start of the filename. mov al, byte ptr es:[di] ;AN004;;AN020;We do this by check es:di backward until cmp al, '\' ;AN004;;AN020; DI = SI or DI -> '\' or DI -> ':'. je SDVMK_GotFile ;AN004;;AN020; cmp al, ':' ;AN004; je SDVMK_GotFile ;AN004; cmp di, si ;AN004; je SDVMK_FilePtr ;AN004; dec di ;AN004; jmp SDVMK_BackWard ;AN004; SDVMK_GotFile: ;AN004; inc di ;AN004; SDVMK_FilePtr: ;AN004; now es:di -> start of file name push di ;AN004; pop si ;AN004; save di to si. push ds ;AN004; switch es, ds push es ;AN004; pop ds ;AN004; pop es ;AN004; now, ds:si -> start of filename mov di, DEVMARK_FILENAME ;AN004; push di ;AN004; mov al, ' ' ;AN004; mov cx, 8 ;AN004; rep stosb ;AN004; Clean up Memory. pop di ;AN004; mov cx, 8 ;AN004; Max 8 char. only SDVMK_Loop: ;AN004; lodsb ;AN004; cmp al, '.' ;AN004; je SDVMK_Done ;AN004; cmp al, 0 ;AN004; je SDVMK_Done ;AN004; stosb ;AN004; loop SDVMK_Loop ;AN004; SDVMK_Done: ;AN004; pop di ;AN004; pop es ;AN004; pop si ;AN004; pop ds ;AN004; ret ;AN004; Set_DevMark endp ;AN004; Chk_XMAEM proc near ;AN029; ;Function: Check XMAEM.SYS file name. ;In: ES:SI -> path, filename, 0 ;out: if XMAEM.SYS, then zero flag set. push es ;AN029; push si ;AN029; push ds ;AN029; push di ;AN029; push cx ;AN029; mov di, si ;AN029;save current starting pointer CX_Cmp: ;AN029; cmp byte ptr es:[si], 0 ;AN029; je CX_Endfile ;AN029; inc si ;AN029; jmp CX_Cmp ;AN029; CX_Endfile: ;AN029; dec si ;AN029; cmp byte ptr es:[si], '\' ;AN029; je CX_Got_Tail ;AN029; cmp byte ptr es:[si], ':' ;AN029; je CX_Got_Tail ;AN029; cmp di, si ;AN029; je CX_Got_Tail0 ;AN029; jmp CX_Endfile ;AN029; CX_Got_Tail: ;AN029; inc si ;AN029; CX_Got_Tail0: ;AN029; push cs ;AN029; pop ds ;AN029; push si ;AN029; pop di ;AN029;now es:di -> filename,0 mov cx, 9 ;AN029; mov si, offset XMAEM_File ;AN029;ds:si -> XMAEM.SYS,0 repe cmpsb ;AN029; CX_Ret: ;AN029; pop cx ;AN029; pop di ;AN029; pop ds ;AN029; pop si ;AN029; pop es ;AN029; ret ;AN029; Chk_XMAEM endp ;Chk_IBMCACHE proc near ;AN024;AN026; Don't need this any more. ; IBMDOS is going to handle this through 4Bh call. ;Function: IBMCACHE.SYS does not handle a DOS version 4.0 or above. ; So, this procedure will check if the device driver is IBMCACHE.SYS. ; If it is, through new INT 2fh interface "Set/Restore DOS version" ; AX=122Fh ; DX= 0 ; reset ; otherwise ; DH = minor version, DL = major version ; INT 2fh ;In: ES:SI -> path, filename, 0 ;out: if IBMCACHE.SYS, then DOS version changed to 4.00 temporarily. ; Reset_Dos_Version proc will later reset it back to current DOS version 4.0. ; push es ;AN024; ; push si ;AN024; ; push ds ;AN024; ; push di ;AN024; ; push cx ;AN024; ; mov di, si ;AN024;save current starting pointer ;CIC_Cmp: ;AN024; ; cmp byte ptr es:[si], 0 ;AN024; ; je CIC_Endfile ;AN024; ; inc si ;AN024; ; jmp CIC_Cmp ;AN024; ;CIC_Endfile: ;AN024; ; dec si ;AN024; ; cmp byte ptr es:[si], '\' ;AN024; ; je CIC_Got_Tail ;AN024; ; cmp byte ptr es:[si], ':' ;AN024; ; je CIC_Got_Tail ;AN024; ; cmp di, si ;AN024; ; je CIC_Got_Tail0 ;AN024; ; jmp CIC_Endfile ;AN024; ;CIC_Got_Tail: ;AN024; ; inc si ;AN024; ;CIC_Got_Tail0: ;AN024; ; push cs ;AN024; ; pop ds ;AN024; ; push si ;AN024; ; pop di ;AN024;now es:di -> filename,0 ; mov cx, 12 ;AN024; ; mov si, offset IBMCACHE_File ;AN024;ds:si -> IBMCACHE.SYS,0 ; repe cmpsb ;AN024; ; jnz CIC_ret ;AN024; ; mov ax, 122Fh ;AN024;Change DOS version to ; mov dx, 2803h ;AN024; DOS 3.4 temporarily. ; int 2fh ;AN024; ;CIC_Ret: ;AN024; ; pop cx ;AN024; ; pop di ;AN024; ; pop ds ;AN024; ; pop si ;AN024; ; pop es ;AN024; ; ret ;AN024; ;Chk_IBMCACHE endp ; Reset_DOS_Version proc near ;AN024; ;Function: issue AX=122Fh, DX=0, INT 2fh to restore the DOS version. push ax ;AN024; push dx ;AN024; mov ax, 122Fh ;AN024; mov dx, 0 ;AN024; int 2fh ;AN024; pop dx ;AN024; pop ax ;AN024; ret ;AN024; Reset_DOS_Version endp ;Int 2F EMS handler + Int 67h handler for EMS ;========================================================================= ; Int_2F_EMS - This routine provides support for VDISK, ; FASTOPEN, and BUFFERS to determine the physical ; EMS pages available for their usage. ; ; Inputs : AH - Function code (18h) to return available phys. page ; DI - FEh (Signals to return useable page for VDISK & FASTOPEN) ; FFh (Signals to return useable page for BUFFERS) ; ; AL = 0 is for installation check. - J.K. ; ; Outputs : ES - Segment value for physical page ; DI - Physical Page number ; AH - Non-zero (physical page not available) ; Zero (valid physical page data returned) ; ; For installation check, AL = 0FFh for being present. - J.K. ; For the other functions, AX = 0 for successful op. ; AX = -1 for an error. ; ; Date : 5/5/88 ; Release : DOS 4.0 ;========================================================================= ;Int_2F_Handler proc ;traps Int_2f and checks for EMS ;an000; dms; EMS_STUB_START label byte ;AN030;J.K. ;Dummy DEVICE HEADER for other dummy ;AN031; Symphony assumes int 67h handler seg as a device driver! DD -1 ;AN031;becomes pointer to next device header DW 0C040H ;AN031;attribute (character device) DW 0000 ;AN031;pointer to harzard area. System will hang. DW 0000 ;AN031;pointer to harzard area. System will hang. DB 'EMMXXXX0' ;AN031;device name INTV2F equ $-EMS_STUB_START ;AN030;J.K.pointer to old 2Fh handler ;an000; dms; IntV2FO DW ? ;AN030;;offset ;an000; dms; IntV2FS DW ? ;AN030;;segment ;an000; dms; OLDINT67_VECTOR equ $-EMS_STUB_START ;AN030;J.K. OldInt67 dd ? ;AN030;; save pointer to old INT 67 handler here IF BUFFERFLAG LOCKFLAG equ $-EMS_STUB_START LOCK_FLAG db ? ELSE EMSPAGE_CNT equ $-EMS_STUB_START ;AN030;J.K. EMSPageCount dw ? ;AN030;; save count of EMS mappable pages here EMSReservedArray_X label word ;AN030;;J.K. For initialization routine EMSRESERVEDARRAY equ $-EMS_STUB_START ;AN030;;J.K. dw 0ffffh,0ffffh ;AN030;; array of reserved pages dw 0ffffh,0ffffh ;AN030;; phys_page_segment, phys_page_number * 2 entries MappableArray_X label word ;AN030;;J.K. for initialization routine MAPPABLEARRAY equ $-EMS_STUB_START ;AN030;;J.K. dw 64 dup (0,0) ;AN030;; table to get addresses from old INT 67 handler ENDIF ; 64 entries * 2 words NEWEMS2F_OFF equ $-EMS_STUB_START;AN030; Int_2F_EMS: ;AN030;;J.K. Name changed. cmp ah,1Bh ;AN030;;AN032;2Fh trap for Mappable Phys. Add. Array ;an000; dms; je Int_2F_EMS_MINE ;AN030;;This one we want ;an000; dms; jmp dword ptr cs:IntV2F ;AN030;;go to old interrupt handler ;an000; dms; Int_2F_EMS_MINE: ;AN030; or al, al ;AN030;;J.K. Installation check? jnz Int_2F_5800_Func ;AN030;;J.K. mov al, 0FFh ;AN030;;J.K. Yes, I am here! iret ;AN030;;J.K. Int_2F_5800_Func: ;AN030; IF BUFFERFLAG ; int 3 cmp di, 80h jne st_flag mov byte ptr cs:LOCKFLAG, 0 jmp Int_2f_5800_Good_Exit st_flag: cmp di, 81h jne Int_2f_5800_Err_Exit mov byte ptr cs:LOCKFLAG, 1 jmp Int_2f_5800_Good_Exit ELSE push si ;AN030;; ;an000; dms; ; mov si,offset EMSReservedArray ;point to array containing pages ;an000; dms; mov si, EMSRESERVEDARRAY ;AN030;;J.K. cmp di,0feh ;AN030;;VDISK or FASTOPEN request? ;an000; dms; jne Int_2F_5800_Buff_Ck ;AN030;;no - check for buffers ;an000; dms; cmp word ptr cs:[si],0ffffh ;AN030;;valid entry? ;an000; dms; je Int_2F_5800_Err_Exit ;AN030;;no - exit ;an000; dms; mov es,word ptr cs:[si] ;AN030;;get segment value ;an000; dms; mov di,word ptr cs:[si+2] ;AN030;;get physical page value ;an000; dms; jmp Int_2F_5800_Good_Exit ;AN030;;exit routine ;an000; dms; Int_2F_5800_Buff_Ck: ;AN030; cmp di,0ffh ;AN030;;BUFFERS request? ;an000; dms; jne Int_2F_5800_Err_Exit ;AN030;;no - exit with error ;an000; dms; add si,4 ;AN030;;point to second element in array ;an000; dms; cmp word ptr cs:[si],0ffffh ;AN034;;valid entry? ;an000; dms; je Int_2F_5800_Err_Exit ;AN034;;no - exit ;an000; dms; mov es,word ptr cs:[si] ;AN030;;get segment value ;an000; dms; mov di,word ptr cs:[si+2] ;AN030;;get physical page value ;an000; dms; ENDIF Int_2F_5800_Good_Exit: ;AN030; xor ax,ax ;AN030;;signal good return ;an000; dms; jmp Int_2F_Exit ;AN030;;exit routine ;an000; dms; Int_2F_5800_Err_Exit: ;AN030; mov ax,0ffffh ;AN030;;signal error ;an000; dms; Int_2F_Exit: ;AN030; IF NOT BUFFERFLAG pop si ;AN030;;restore regs ;an000; dms; ENDIF iret ;AN030;;return to caller ;an000; dms; ;------------------------------------------------------------------- ; ; INT 67h Filter ; ; This routine filters INT 67's looking for AH=58h. When initialized, ; the original INT 67 handler is called and the mappable address array ; is changed to "reserve" two pages for DOS use. This new array is ; then returned to the calling program when INT 67 AH=58h is found. ; ; Information about the two pages "reserved" for DOS is returned ; via an unpublished INT 2Fh interface. ; ; 5/10/88 for DOS 4.0. ;------------------------------------------------------------------- IF NOT BUFFERFLAG GetMappableArray equ 58h ; INT 67 function code for Get Mappable Array GetPageFrame equ 41h ; function code for getting the page frame address null equ 0 ; zero value I67Error8F equ 8fh ;AN031;; invalid sub-function error ENDIF ;------------------------------------------------------------------- NEW67_OFFSET equ $-EMS_STUB_START ;J.K. Int67Filter: ;AN030; IF BUFFERFLAG ; int 3 cmp byte ptr cs:LOCKFLAG, 1 jne PassThru mov ah, 80h stc iret ELSE cmp ah,GETMAPPABLEARRAY ;AN030;; is this the INT 67 call we are interested in? jne PassThru ;AN030;; no, pass it to old INT 67 handler ;AN030;; yes ... cmp al,0 ;AN031;; AL=0 return count and table je I67Fcn0 cmp al,1 ;AN031;; AL=1 return count only jne I67Error ;AN031;; otherwise, error ; return count of mappable pages sti ;AN031;; turn interrupts on mov cx,word ptr cs:EMSPAGE_CNT ;AN031;J.K. get number of mappable pages in fake table xor ah,ah ;AN031;; good return code iret ; return invalid sub-function code I67Error: sti ;AN031;; turn interrupts on mov ah,I67Error8F ;AN031;; invalid sub-function error iret I67Fcn0: ;AN031 ; copy the fake table to user's buffer sti ;AN030;; turn interrupts on push ds ;AN030; save some regs push di ;AN030; push si ;AN030; mov cx,word ptr cs:EMSPAGE_CNT ;AN030;J.K. get number of mappable pages in fake table shl cx,1 ;AN030;; count * 2 = number of words to copy push cs ;AN030;; point DS:SI to fake table pop ds ;AN030; ; lea si,MappableArray mov si, MAPPABLEARRAY ;AN030;;J.K. rep movsw ;AN030;; copy CX words from DS:SI to ES:DI xor ah,ah ;AN030;; good return code mov cx,word ptr cs:EMSPAGE_CNT ;AN030;; page count returned to user in CX pop si ;AN030;; restore some regs pop di ;AN030; pop ds ;AN030; iret ;AN030;; end of INT 67 filter routine ENDIF ;------------------------------------------------------------------- ; ; PassThru - send request to old INT 67 handler ; ;------------------------------------------------------------------- PassThru: jmp dword ptr cs:OldINT67_VECTOR ;AN030;;J.K. jump to old INT 67 handler ; (IRET will return to calling program) EMS_STUB_END label byte ;AN030; ;------------------------------------------------------------------- IF NOT BUFFERFLAG ;------------------------------------------------------------------- ; ; Int67FilterInit - This routine is called to initialize the INT 67 ; filter. It should be called as soon as possible after installation. ; ;------------------------------------------------------------------- Int67FilterInit: ;AN030; push es ;AN030;; save caller's ES:DI push di ;AN030; push cs ;AN030;; make ES:DI point to our array pop es ;AN030; mov di,offset MappableArray_X ;AN030; ; call dword ptr cs:OldInt67 ; get mappable array from EMS DD mov ah, GetMappableArray ;AN030; xor al,al ;AN030; int 67h ;AN030;;J.K. ;------------------------ ; scan table looking for highest phys_page_number xor ax,ax ;AN030;; cmp cx,0 ;AN033;; are the any pages left? je NoMoreEMSPages ;AN033;; no, don't bother looking any more call GetHighestPage ;AN030;; get highest entry from table mov EMSReservedArray_X+4,bx ;AN030;; phys_page_segment mov EMSReservedArray_X+6,ax ;AN030;; phys_page_number cmp cx,0 ;AN033;; are the any pages left? je NoMoreEMSPages ;AN033;; no, don't bother looking any more call GetHighestPage ;AN030;; get next highest entry from table mov EMSReservedArray_X+0,bx ;AN030;; phys_page_segment mov EMSReservedArray_X+2,ax ;AN030;; phys_page_number NoMoreEMSPages: ;AN033;; mov EMSPageCount,cx ;AN030;; save new page count for INT 67 filter pop di pop es ret ;AN030;; return to calling program page ;------------------------------------------------------------------- ; ; GetHighestPage - returns highest physical page number in AX ; and segment for it in BX. A -1 means no valid page found. ; ;------------------------------------------------------------------- GetHighestPage: xor ax,ax ;AN030;; zero candidate register mov bx,ax ;AN030;; zero pointer to candidate page push cx ;AN030;; save count push dx ;AN030; push di ;AN030;; save pointer PageScanLoop: ;AN030; cmp ax,ES:[di+2] ;AN030;; get phys_page_number ja LookAtNextPage ;AN030;; this one is lower than the one we are holding cmp es:[di], 0a000h ; Only reserve pages in memory above 640K.. jb LookAtNextPage ; fix for ps2emm and m20emm with motherboard ; disabled. 7/25/88. HKN. mov ax,ES:[di+2] ;AN030;; this one is higher, make it new candidate mov bx,di ;AN030;; pointer to new candidate page, used to zero ; it later so we don't get the same one again mov dx,cx ;AN030;; save count where we found candidate LookAtNextPage: ;AN030; add di,4 ;AN030;; point to next entry in mappable table loop PageScanLoop ;AN030;; look at next entry cmp bx,null ;AN030;; did we find any pages? jne FoundOne ;AN030;; yes, exit jmp ReturnError ;AN030; ;------------------------ FoundOne: ;AN030; cmp ax,3 ;AN030;; could the one we found be part of a page frame ja NotFrame ;AN030;; no, carry on ; yes, find out if it is part of frame push ax ;AN030;; save physical page number push bx ;an030;; dms; bx destroyed by call mov ah,GetPageFrame ;AN030;; function code to get page frame ... ; call dword ptr cs:OldInt67 ; ... from the EMS DD int 67h ;AN030;;J.K. or ah,ah ;an030;;dms; error? pop bx ;an030;;dms; restore bx pop ax ;AN030;; restore phys page number jnz NotFrame ;AN030;; no frame available, carry on ; there is a frame, this page is part of frame, so return -1's ReturnError: ;AN030; mov ax,0ffffh ;AN030;; indicate failure mov bx,ax ;AN030;; ax and bx = -1 pop di ;AN030;; restore pointer pop dx pop cx ;AN030;; restore count jmp GHPExit ;AN030; ;------------------------ ; Found a page, and it is not part of a page frame, so re-pack table ; and return info. The entry we "reserve" for DOS must be removed ; from the table and the other entries moved up to repack the table. ; The count must be reduced by 1 to reflect this change. Notframe: ;AN030; mov di,bx ;AN030;; make ES:DI point to highest page table entry mov bx,ES:[di] ;AN030;; get segment address of page mov cx,dx ;AN030;; get count from candidate page push ax ;AN030; PackLoop: ;AN030; mov ax, es:[di+4] ;AN030; mov es:[di+0], ax ;AN030; mov ax, es:[di+6] ;AN030; mov es:[di+2], ax ;AN030; add di, 4 ;AN030; loop PackLoop ;AN030;; do it until done pop ax ;AN030; pop di ;AN030;; restore pointer pop dx ;AN030; pop cx ;AN030;; restore count sub cx,1 ;AN030;; reduce count by one, one less page in table now GHPExit: ;AN030; ret ;AN030;; return to caller ENDIF ;========================================================================= ; EMS_Install_Check : THIS MODULE DETERMINES WHETHER OR NOT EMS IS ; INSTALLED FOR THIS SESSION. ; ; INPUTS : NONE ; ; OUTPUTS : ES:BX - FRAME ARRAY ; CY - EMS NOT AVAILABLE ; NC - EMS AVAILABLE ; ; Date : 5/6/88 ;========================================================================= EMS_Install_Check proc near ;AN030;; check if EMS is installed ;an000; dms; push ax ;AN030;; save regs ;an000; dms; push ds ;AN030;; save ds ;an000; dms; xor ax,ax ;AN030;; set ax to 0 ;an000; dms; mov ds,ax ;AN030;; set ds to 0 ;an000; dms; cmp ds:word ptr[067h*4+0],0 ;AN030;; see if int 67h is there ;an000; dms; pop ds ;AN030;; restore ds ;an000; dms; je EMS_Install_Ck_Err_Exit ;AN030;; exit routine - EMS not loaded ;an000; dms; mov ah,40h ;AN030;; Get Status function ;an000; dms; xor al,al ;AN030;; clear al ;an000; dms; int 67h ;AN030;; ;an000; dms; or ah,ah ;AN030;; EMS installed? ;an000; dms; jnz EMS_Install_Ck_Err_Exit ;AN030;; exit routine - EMS not loaded ;an000; dms; mov ah,46h ;AN030;; Get Version number ;an000; dms; xor al,al ;AN030;; clear al ;an000; dms; int 67h ;AN030;; ;an000; dms; cmp al,40h ;AN030;; Version 4.0? ;an000; dms; jb EMS_Install_Ck_Err_Exit ;AN030;; exit routine - wrong EMS loaded ;an000; dms; clc ;AN030;; signal EMS loaded ;an000; dms; jmp EMS_Install_Ck_Exit ;AN030;; exit routine ;an000; dms; EMS_Install_Ck_Err_Exit: ;AN030; stc ;AN030;; signal EMS not loaded ;an000; dms; EMS_Install_Ck_Exit: ;AN030; pop ax ;AN030;; restore regs ;an000; dms; ret ;AN030;; return to caller ;an000; dms; EMS_Install_Check endp ; ;an000; dms; EMS_Stub_Handler proc near ;AN030; ;At the request of Architecture Group, this logic is implemented. ;Function: If (Buffer_Slash_X <> 0 and EMS_Stub_Installed == 0), ; then { call Chk_EMS; ; if EMS is there, then install EMS_Stub dynamically ; and initialize it.} ; Note: EMS_Stub consists of INT 2fh EMS handler and INT 67h handler. ; When EMS_Stub is installed, EMS_Stub_Installed will be set to 1. push es ;AN030; push si ;AN030; push ds ;AN030; push di ;AN030; push ax ;AN030; push cx ;AN030; cmp EMS_Stub_Installed, 0 ;AN030; je EMS_Stub_X ;AN030; jmp EMS_SH_Ret ;AN030; EMS_Stub_X: ;AN030; cmp Buffer_Slash_X, 0 ;AN030; je EMS_SH_Ret ;AN030; call EMS_Install_Check ;AN030; jc EMS_SH_Ret ;AN030; ;Install EMS_Stub. ;AN030; EMS_Stub_Do: push es ;AN030; xor ax,ax ;AN030;save current Int 2fh, 67h vectors. mov es, ax ;AN030; mov ax, word ptr es:[2fh*4] ;AN030; mov IntV2FO, ax ;AN030; mov ax, word ptr es:[2fh*4+2] ;AN030; mov IntV2FS, ax ;AN030; mov ax, word ptr es:[67h*4] ;AN030; mov word ptr cs:[OldInt67], ax ;AN030; mov ax, word ptr es:[67h*4+2] ;AN030; mov word ptr cs:[OldInt67+2], ax ;AN030; pop es ;AN030; IF NOT BUFFERFLAG ;initalize tables in INT 67h handler call Int67FilterInit ;AN030; cmp ax, 0ffffh ; if the page found was part of a lim 4.0 page frame je EMS_SH_ret ; do not install stub. 7/24/88. HKN ENDIF call Round ;AN030; mov ax, DEVMARK_EMS_STUB ;AN030; call SetDevMark ;AN030; mov ax, [memhi] ;AN030; mov es, ax ;AN030; assume es:nothing ;AN030; xor di, di ;AN030; push cs ;AN030; pop ds ;AN030; mov cx, offset EMS_STUB_END ;AN030; mov si, offset EMS_STUB_START ;AN030; sub cx, si ;AN030;cx = size in byte mov [memlo], cx ;AN030; rep movsb ;AN030; or [SetDevMarkFlag], FOR_DEVMARK ;AN030;set the devmark_size for MEM command. call Round ;AN030;and get the next [memhi] avaiable. mov EMS_Stub_Installed, 1 ;AN030; xor ax, ax ;AN030; mov ds, ax ;AN030; cli ;AN030; mov word ptr ds:[2Fh*4],NEWEMS2F_OFF;AN030;set the new int 2fh, 67h vectors. mov word ptr ds:[2Fh*4+2], es ;AN030; mov word ptr ds:[67h*4],NEW67_OFFSET;AN030; mov word ptr ds:[67h*4+2], es ;AN030; sti ;AN030; EMS_SH_Ret: ;AN030; pop cx ;AN030; pop ax ;AN030; pop di ;AN030; pop ds ;AN030; pop si ;AN030; pop es ;AN030; ret ;AN030; EMS_Stub_Handler endp ;AN030; SYSINITSEG ENDS END