From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DEV/DRIVER/DRIVER.ASM | 1296 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1296 insertions(+) create mode 100644 v4.0/src/DEV/DRIVER/DRIVER.ASM (limited to 'v4.0/src/DEV/DRIVER/DRIVER.ASM') diff --git a/v4.0/src/DEV/DRIVER/DRIVER.ASM b/v4.0/src/DEV/DRIVER/DRIVER.ASM new file mode 100644 index 0000000..4832e07 --- /dev/null +++ b/v4.0/src/DEV/DRIVER/DRIVER.ASM @@ -0,0 +1,1296 @@ + PAGE 64,132 ; +; SCCSID = @(#)driver.asm 4.13 85/10/15 +; SCCSID = @(#)driver.asm 4.13 85/10/15 +; +; External block device driver +; Hooks into existing routines in IBMBIO block driver via Int 2F mpx # 8. +; This technique minimizes the size of the driver. +; + +; Revised Try_h: to test for flagheads as msg was being displayed on FormFactor +; this caused the FormFactor to be set in the Head +; Revised the # of sectors/cluster for F0h to 1 +;============================================================================== +;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 - d55 Unable the fixed disk accessibility of DRIVER.SYS. 7/7/87 J.K. +;AN002 - p196 Driver.sys does not signal init. failure 8/17/87 J.K. +;AN003 - p267 "No driver letter..." message 8/19/87 J.K. +;AN004 - p268 "Too many parameter..." message 8/20/87 J.K. +;AN005 - p300 "Bad 1.44MB BPB information..." 8/20/87 J.K. +;AN006 - p490 Driver should reject identical parms 8/28/87 J.K. +;AN007 - p921 Parser.ASM problem 9/18/87 J.K. +;AN008 - d493 New init request structure 2/25/88 J.K. +;============================================================================== + +code segment byte public +assume cs:code,ds:code,es:code + +;AN000; +.xlist +include SYSMSG.INC ;equates and macros +.list +MSG_UTILNAME + +iTEST = 0 +;--------------------------------------------------- +; +; Device entry point +; +DSKDEV LABEL WORD + DW -1,-1 ; link to next device + DW 0000100001000000B ; bit 6 indicates DOS 3.20 driver + DW STRATEGY + DW DSK$IN +DRVMAX DB 1 + +; +; Various equates +; +CMDLEN equ 0 ;LENGTH OF THIS COMMAND +UNIT equ 1 ;SUB UNIT SPECIFIER +CMD equ 2 ;COMMAND CODE +STATUS equ 3 ;STATUS +MEDIA equ 13 ;MEDIA DESCRIPTOR +TRANS equ 14 ;TRANSFER ADDRESS +COUNT equ 18 ;COUNT OF BLOCKS OR CHARACTERS +START equ 20 ;FIRST BLOCK TO TRANSFER +EXTRA equ 22 ;Usually a pointer to Vol Id for error 15 +CONFIG_ERRMSG equ 23 ;AN009; To set this field to Non-zero + ; to display "Error in CONFIG.SYS..." + +PTRSAV DD 0 + + +STRATP PROC FAR + +STRATEGY: + MOV WORD PTR CS:[PTRSAV],BX + MOV WORD PTR CS:[PTRSAV+2],ES + RET + +STRATP ENDP + +DSK$IN: + push es + push bx + push ax + les bx,cs:[ptrsav] + cmp byte ptr es:[bx].cmd,0 + jnz Not_Init + jmp DSK$INIT + +not_init: +; Because we are passing the call onto the block driver in IBMBIO, we need to +; ensure that the unit number corresponds to the logical (DOS) unit number, as +; opposed to the one that is relevant to this device driver. + mov al,byte ptr cs:[DOS_Drive_Letter] + mov byte ptr es:[bx].UNIT,al + mov ax,0802H + int 2fH +; +; We need to preserve the flags that are returned by IBMBIO. YUK!!!!! +; + pushf + pop bx + add sp,2 + push bx + popf + +exitp proc far +DOS_Exit: + pop ax + POP BX + POP ES + RET ;RESTORE REGS AND RETURN +EXITP ENDP + +include msbds.inc ; include BDS structures +;include versiona.inc + +BDS DW -1 ;Link to next structure + DW -1 + DB 1 ;Int 13 Drive Number + DB 3 ;Logical Drive Letter +FDRIVE: + DW 512 ;Physical sector size in bytes + DB -1 ;Sectors/allocation unit + DW 1 ;Reserved sectors for DOS + DB 2 ;No. allocation tables + DW 64 ;Number directory entries + DW 9*40 ;Number sectors (at 512 bytes ea.) + DB 00000000B ;Media descriptor, initially 00H. + DW 2 ;Number of FAT sectors + DW 9 ;Sector limit + DW 1 ;Head limit + DW 0 ;Hidden sector count + dw 0 ;AN000; Hidden sector count (High) + dw 0 ;AN000; Number sectors (low) + dw 0 ;AN000; Number sectors (high) + DB 0 ; TRUE => Large fats +OPCNT1 DW 0 ;Open Ref. Count + DB 2 ;Form factor +FLAGS1 DW 0020H ;Various flags + DW 80 ;Number of cylinders in device +RecBPB1 DW 512 ; default is that of 3.5" disk + DB 2 + DW 1 + DB 2 + DW 70h + DW 2*9*80 + DB 0F9H + DW 3 + DW 9 + DW 2 + DW 0 + dw 0 ;AN000; + dw 0 ;AN000; + dw 0 ;AN000; + db 6 dup (0) ;AC000; +TRACK1 DB -1 ;Last track accessed on this drive +TIM_LO1 DW -1 ;Keep these two contiguous (?) +TIM_HI1 DW -1 +VOLID1 DB "NO NAME ",0 ;Volume ID for this disk +VOLSER dd 0 ;AN000; +FILE_ID db "FAT12 ",0 ;AN000; + +DOS_Drive_Letter db ? ; Logical drive associated with this unit + +ENDCODE LABEL WORD ; Everything below this is thrown away + ; after initialisation. + +DskDrv dw offset FDRIVE ; "array" of BPBs + +;AN000; For system parser; + +FarSW equ 0 ; Near call expected + +DateSW equ 0 ; Check date format + +TimeSW equ 0 ; Check time format + +FileSW equ 0 ; Check file specification + +CAPSW equ 0 ; Perform CAPS if specified + +CmpxSW equ 0 ; Check complex list + +NumSW equ 1 ; Check numeric value + +KeySW equ 0 ; Support keywords + +SwSW equ 1 ; Support switches + +Val1SW equ 1 ; Support value definition 1 + +Val2SW equ 1 ; Support value definition 2 + +Val3SW equ 0 ; Support value definition 3 + +DrvSW equ 0 ; Support drive only format + +QusSW equ 0 ; Support quoted string format +;--------------------------------------------------- +;.xlist +assume ds:nothing ;AN007;!!!Parse.ASM sometimes assumes DS + ; to access its own variable!!! + include PARSE.ASM ;together with PSDATA.INC +assume ds:code ;AN007; +;.list +;Control block definitions for PARSER. +;--------------------------------------------------- +Parms label byte + dw Parmsx ;AN000; + db 0 ;AN000;No extras + +Parmsx label byte ;AN000; + db 0,0 ;AN000;No positionals + db 5 ;AN000;5 switch control definitions + dw D_Control ;AN000;/D + dw T_Control ;AN000;/T + dw HS_Control ;AN000;/H, /S + dw CN_Control ;AN000;/C, /N + dw F_Control ;AN000;/F + db 0 ;AN000;no keywords + +D_Control label word ;AN000; + dw 8000h ;AN000;numeric value + dw 0 ;AN000;no functions + dw Result_Val ;AN000;result buffer + dw D_Val ;AN000;value defintions + db 1 ;AN000;# of switch in the following list +Switch_D label byte ;AN000; + db '/D',0 ;AN000; + +D_Val label byte ;AN000; + db 1 ;AN000;# of value defintions + db 1 ;AN000;# of ranges + db 1 ;AN000;Tag value when match +; dd 0,255 ;AN000; + dd 0,127 ;AN001;Do not allow a Fixed disk. + +Result_Val label byte ;AN000; + db ? ;AN000; +Item_Tag label byte ;AN000; + db ? ;AN000; +Synonym_ptr label word ;AN000; + dw ? ;AN000;es:offset -> found Synonym +RV_Byte label byte ;AN000; +RV_Word label word ;AN000; +RV_Dword label dword ;AN000; + dd ? ;AN000;value if number, or seg:off to string + +T_Control label word ;AN000; + dw 8000h ;AN000;numeric value + dw 0 ;AN000;no functions + dw Result_Val ;AN000;result buffer + dw T_Val ;AN000;value defintions + db 1 ;AN000;# of switch in the following list +Switch_T label byte ;AN000; + db '/T',0 ;AN000; + +T_Val label byte ;AN000; + db 1 ;AN000;# of value defintions + db 1 ;AN000;# of ranges + db 1 ;AN000;Tag value when match + dd 1,999 ;AN000; + +HS_Control label word ;AN000; + dw 8000h ;AN000;numeric value + dw 0 ;AN000;no function flag + dw Result_Val ;AN000;Result_buffer + dw HS_VAL ;AN000;value definition + db 2 ;AN000;# of switch in following list +Switch_H label byte ;AN000; + db '/H',0 ;AN000; +Switch_S label byte ;AN000; + db '/S',0 ;AN000; + +HS_Val label byte ;AN000; + db 1 ;AN000;# of value defintions + db 1 ;AN000;# of ranges + db 1 ;AN000;Tag value when match + dd 1,99 ;AN000; + +CN_Control label word ;AN000; + dw 0 ;AN000;no match flags + dw 0 ;AN000;no function flag + dw Result_Val ;AN000;no values returned + dw NoVal ;AN000;no value definition +; db 2 ;AN000;# of switch in following list + db 1 ;AN001; +Switch_C label byte ;AN000; + db '/C',0 ;AN000; +;Switch_N label byte ;AN000; +; db '/N',0 ;AN000; + +Noval db 0 ;AN000; + +F_Control label word ;AN000; + dw 8000h ;AN000;numeric value + dw 0 ;AN000;no function flag + dw Result_Val ;AN000;Result_buffer + dw F_VAL ;AN000;value definition + db 1 ;AN000;# of switch in following list +Switch_F label byte ;AN000; + db '/F',0 ;AN000; + +F_Val label byte ;AN000; + db 2 ;AN000;# of value definitions (Order dependent) + db 0 ;AN000;no ranges + db 4 ;AN000;# of numeric choices +F_Choices label byte ;AN000; + db 1 ;AN000;1st choice (item tag) + dd 0 ;AN000;0 + db 2 ;AN000;2nd choice + dd 1 ;AN000;1 + db 3 ;AN000;3rd choice + dd 2 ;AN000;2 + db 4 ;AN000;4th choice + dd 7 ;AN000;7 + + +;AN000;System messages handler data +;AN000;Put the data here +.sall +MSG_SERVICES + +;AN000;Place the messages here +MSG_SERVICES + +;AN000;Put messages handler code here. +MSG_SERVICES +.xall + +; +; Sets ds:di -> BDS for this drive +; +SetDrive: + push cs + pop ds + mov di,offset BDS + ret + +; +; Place for DSK$INIT to exit +; +ERR$EXIT: + MOV AH,10000001B ;MARK ERROR RETURN + lds bx, cs:[ptrsav] + mov byte ptr ds:[bx.MEDIA], 0 ;AN002; # of units + mov word ptr ds:[bx.CONFIG_ERRMSG], -1 ;AN009;Show IBMBIO error message too. + JMP SHORT ERR1 + +Public EXIT +EXIT: MOV AH,00000001B +ERR1: LDS BX,CS:[PTRSAV] + MOV WORD PTR [BX].STATUS,AX ;MARK OPERATION COMPLETE + +RestoreRegsAndReturn: + POP DS + POP BP + POP DI + POP DX + POP CX + POP AX + POP SI + jmp dos_exit + + +drivenumb db 5 +cyln dw 80 +heads dw 2 +ffactor db 2 +slim dw 9 + +Switches dw 0 + +Drive_Let_Sublist label dword + db 11 ;AN000;length of this table + db 0 ;AN000;reserved + dw D_Letter;AN000; +D_Seg dw ? ;AN000;Segment value. Should be CS + db 1 ;AN000;DRIVER.SYS has only %1 + db 00000000b ;AN000;left align(in fact, Don't care), a character. + db 1 ;AN000;max field width 1 + db 1 ;AN000;min field width 1 + db ' ' ;AN000;character for pad field (Don't care). + +D_Letter db "A" + +if iTEST +Message: + push ax + push ds + push cs + pop ds + mov ah,9 + int 21h + pop ds + pop ax + ret +extrn nodrive:byte,loadokmsg:byte,letter:byte, badvermsg:byte +endif + + +if iTEST +%OUT Testing On +initmsg db "Initializing device driver",13,10,"$" +stratmsg db "In strategy of driver",10,13,"$" +dskinmsg db "In DSKIN part of driver",10,13,"$" +outinitmsg db "Out of init code ",10,13,"$" +exitmsg db "Exiting from driver",10,13,"$" +parsemsg db "Parsing switches",10,13,"$" +errmsg db "Error occurred",10,13,"$" +linemsg db "Parsed line",10,13,"$" +int2fokmsg db "****************Int2f loaded**************",10,13,"$" +mediamsg db "Media check ok",10,13,"$" +getbpbmsg db "getbpb ok",10,13,"$" +iookmsg db "Successful I/O",10,13,"$" +parseokmsg db "Parsing done fine",10,13,"$" +nummsg db "Number read is " +number db "00 ",10,13,"$" +drvmsg db "Process drive " +driven db "0",10,13,"$" +cylnmsg db "Process cylinder ",10,13,"$" +slimmsg db "Process sec/trk ",10,13,"$" +hdmsg db "Process head " +hdnum db "0",10,13,"$" +ffmsg db "Process form factor " +ffnum db "0",10,13,"$" +nxtmsg db "Next switch ",10,13,"$" +msg48tpi db "Got a 48 tpi drive",10,13,"$" + +ENDIF + +DSK$INIT: + PUSH SI + PUSH AX + PUSH CX + PUSH DX + PUSH DI + PUSH BP + PUSH DS + + LDS BX,CS:[PTRSAV] ;GET POINTER TO I/O PACKET + + MOV AL,BYTE PTR DS:[BX].UNIT ;AL = UNIT CODE + MOV AH,BYTE PTR DS:[BX].MEDIA ;AH = MEDIA DESCRIP + MOV CX,WORD PTR DS:[BX].COUNT ;CX = COUNT + MOV DX,WORD PTR DS:[BX].START ;DX = START SECTOR + + LES DI,DWORD PTR DS:[BX].TRANS + + PUSH CS + POP DS + + ASSUME DS:CODE + + cld + push cs ;AN000; Initialize Segment of Sub list. + pop [D_Seg] ;AN000; + call SYSLOADMSG ;AN000; linitialize message handler + jnc GoodVer ;AN000; Error. Do not install driver. + mov cx, 0 ;AN000; No substitution + mov dh, -1 ;AN000; Utility message + call Show_Message ;AN000; Show message + jmp err$exitj2 ;AN000; and exit + +;; check for correct DOS version +; mov ah,30h +; int 21H + +; cmp ax,expected_version +; je GoodVer + +; cmp al,DOSVER_HI +; jnz BadDOSVer +; cmp ah,DOSVER_LO +; jz GoodVer + +;BadDOSVer: +; Mov dx,offset BadVerMsg +; call message +; jmp err$exitj2 ; do not install driver + +GoodVer: + mov ax,0800H + int 2fH ; see if installed + cmp al,0FFH + jnz err$exitj2 ; do not install driver if not present + lds bx,[ptrsav] + mov si,word ptr [bx].count ; get pointer to line to be parsed + mov ax,word ptr [bx].count+2 + mov ds,ax + call Skip_Over_Name ; skip over file name of driver + mov di,offset BDS ; point to BDS for drive + push cs + pop es ; es:di -> BDS + Call ParseLine + jc err$exitj2 + LDS BX,cs:[PTRSAV] + mov al,byte ptr [bx].extra ; get DOS drive letter + mov byte ptr es:[di].DriveLet,al + mov cs:[DOS_Drive_Letter],al + add al,"A" +; mov cs:[letter],al ; set up for printing final message + mov cs:[D_Letter], al ;AN000; + call SetDrvParms ; Set up BDS according to switches + jc err$exitj2 + mov ah,8 ; Int 2f multiplex number + mov al,1 ; install the BDS into the list + push cs + pop ds ; ds:di -> BDS for drive + mov di,offset BDS + int 2FH + lds bx,dword ptr cs:[ptrsav] + mov ah,1 + mov cs:[DRVMAX],ah + mov byte ptr [bx].media,ah + mov ax,offset ENDCODE + mov word ptr [bx].TRANS,AX ; set address of end of code + mov word ptr [bx].TRANS+2,CS + mov word ptr [bx].count,offset DskDrv + mov word ptr [bx].count+2,cs + + push dx + push cs + pop ds + mov si, offset Drive_Let_SubList ;AC000; + mov ax, LOADOK_MSG_NUM ;load ok message + mov cx, 1 ;AN000; 1 substitution + mov dh, -1 ;AN000; utility message + call Show_Message +; mov dx,offset loadokmsg +; call message + pop dx + jmp EXIT + +err$exitj2: + stc + jmp err$exit + +; +; Skips over characters at ds:si until it hits a `/` which indicates a switch +; J.K. If it hits 0Ah or 0Dh, then will return with SI points to that character. +Skip_Over_Name: + call scanblanks +loop_name: + lodsb + cmp al,CR ;AN003; + je End_SkipName ;AN003; + cmp al,LF ;AN003; + je End_SkipName ;AN003; + cmp al,'/' + jnz loop_name +End_SkipName: ;AN003; + dec si ; go back one character + RET + +;ParseLine: +; push di +; push ds +; push si +; push es +;Next_Swt: +;IF iTEST +; mov dx,offset nxtmsg +; call message +;ENDIF +; call ScanBlanks +; lodsb +; cmp al,'/' +; jz getparm +; cmp al,13 ; carriage return +; jz done_line +; CMP AL,10 ; line feed +; jz done_line +; cmp al,0 ; null string +; jz done_line +; mov ax,-2 ; mark error invalid-character-in-input +; stc +; jmp short exitparse +; +;getparm: +; call Check_Switch +; mov cs:Switches,BX ; save switches read so far +; jnc Next_Swt +; cmp ax,-1 ; mark error number-too-large +; stc +; jz exitparse +; mov ax,-2 ; mark invalid parameter +; stc +; jmp short exitparse +; +;done_line: +; test cs:Switches,flagdrive ; see if drive specified +; jnz okay +; push dx +; mov ax, 2 +; call Show_Message +; mov dx,offset nodrive +; call message +; pop dx +; mov ax,-3 ; mark error no-drive-specified +; stc +; jmp short exitparse +; +;okay: +; call SetDrive ; ds:di points to BDS now. +; mov ax,cs:Switches +; and ax,fChangeline+fNon_Removable ; get switches for Non_Removable and Changeline +; or ds:[di].flags,ax +; xor ax,ax ; everything is fine +; +;; +;; Can detect status of parsing by examining value in AX. +;; 0 ==> Successful +;; -1 ==> Number too large +;; -2 ==> Invalid character in input +;; -3 ==> No drive specified +; +; clc +;exitparse: +; pop es +; pop si +; pop ds +; pop di +; ret + + + +ParseLine proc near +;In) DS:SI -> Input string +; ES = CS +; ES:DI -> BDS table inside this program +; +;Out) +; if successfule, then { AX will be set according to the switch +; flag value. BDS.Flag, Drivenumb, cylin, +; slim, heads ffactor are set } +; else +; { +; If (no drive specified) then { display messages }; +; Set carry; +; } +; +;Subroutine to be called: +; SYSPARSE:NEAR, SHOW_MESSAGE:NEAR, GET_RESULT:NEAR +; +;Logic: +;{ While (Not end_of_Line) +; { +; SYSPARSE (); +; if (no error) then +; GET_RESULT () +; else +; Set carry; +; }; +; +; if (carry set) then Exit; /* Initialization failed */ +; if (No drive number entered) /* Drive number is a requirement */ +; then { Show_Message (); +; exit; +; }; +; + assume ds:nothing ;AN000;make sure + push di ;AN000;save BDS pointer + mov di, offset PARMS ;AN000;now, es:di -> parse control definition +SysP_While: ;AN000; + xor cx, cx ;AN004; I don't have positionals. + xor dx, dx ;AN000; + call SYSPARSE ;AN000; + cmp ax, $P_RC_EOL ;AN000;end of line? + je SysP_End ;AN000; + cmp ax, $P_NO_ERROR ;AN000;no error? + jne SysP_Fail ;AN000; + call Get_Result ;AN000; + jmp SysP_While ;AN000; +SysP_End: ;AN000; + test Switches, FLAGDRIVE ;AN000;drive number specified? + jnz SysP_Ok ;AN000;Drive number is a requirement + push ds ;AN000; + mov ax, NODRIVE_MSG_NUM ;AN000;no drive specification + mov cx, 0 ;AN000;no substitutions + mov dh, -1 ;AN000;utility message + call Show_Message ;AN000; + pop ds ;AN000; + jmp short SysP_Err ;AN003; +SysP_Fail: ;AN000; + mov dh, 2 ;AN000; parse error + mov cx, 0 ;AN000; + call Show_Message ;AN000; Show parse error +SysP_Err: ;AN003; + stc ;AN000; + jmp short PL_Ret ;AN000; +SysP_Ok: ;AN000; + clc ;AN000; +PL_Ret: ;AN000; + pop di ;AN000;restore BDS pointer + ret ;AN000; +ParseLine endp + +; +Get_Result proc near +;In) A successful result of SYSPARSE in Result_Val +; es = cs, ds = command line segment +;Out) +; Switches set according to the user option. +; Drivenumb, Cyln, Heads, Slim, ffactor set if specified. +;Logic) +; Switch (Synonym_Ptr) +; { case Switch_D: Switches = Switches | FLAGDRIVE; /* Set switches */ +; Drivenumb = Reg_DX.Value_L; +; break; +; +; case Switch_T: Switches = Switches | Flagcyln; +; Cyln = Reg_DX.Value_L; +; break; +; +; case Switch_H: Switches = Switches | Flagheads; +; Heads = Reg_DX.Value_L; +; break; +; +; case Switch_S: Switches = Switches | FlagSecLim; +; Slim = Reg_DX.Value_L; +; break; +; +; case Switch_C: Switches = Switches | fChangeline; +; break; +; +;; case Switch_N: Switches = Switches | fNon_Removable; +;; break; +; +; case Switch_F: Switches = Switches | Flagff; +; Reg_DX = (Reg_DX.ITEM_Tag - 1)*5;/*Get the offset of +; /*the choice. +; ffactor = byte ptr (F_Choices + DX + 1); +; /*Get the value of it */ +; break; +; +; } +; + + + mov ax, Synonym_Ptr ;AN000; + push ax ;AN006; save Synonym_ptr + cmp ax, offset Switch_D ;AN000; + jne Stch_T ;AN000; + or Switches, FLAGDRIVE ;AN000; + mov al, RV_Byte ;AN000; + mov Drivenumb, al ;AN000; + jmp GR_Ret ;AN000; +Stch_T: ;AN000; + cmp ax, offset Switch_T ;AN000; + jne Stch_H ;AN000; + or Switches, FLAGCYLN ;AN000; + mov ax, RV_Word ;AN000; + mov Cyln, ax ;AN000; + jmp GR_Ret ;AN000; +Stch_H: ;AN000; + cmp ax, offset Switch_H ;AN000; + jne Stch_S ;AN000; + or Switches, FLAGHEADS ;AN000; + mov ax, RV_Word ;AN000; + mov Heads, ax ;AN000; + jmp GR_Ret ;AN000; +Stch_S: ;AN000; + cmp ax, offset Switch_S ;AN000; + jne Stch_C ;AN000; + or Switches, FLAGSECLIM ;AN000; + mov ax, RV_Word ;AN000; + mov Slim, ax ;AN000; + jmp GR_Ret ;AN000; +Stch_C: ;AN000; + cmp ax, offset Switch_C ;AN000; +; jne Stch_N ;AN000; + jne Stch_F ;AN001; + or Switches, fCHANGELINE ;AN000; + jmp GR_Ret ;AN000; +;Stch_N: ;AN000; +; cmp ax, offset Switch_N ;AN000; +; jne Stch_F ;AN000; +; or Switches, fNON_REMOVABLE ;AN000; +; jmp GR_Ret ;AN000; +Stch_F: ;AN000; + cmp ax, offset Switch_F ;AN000; + jne GR_Not_Found_Ret ;AN000;error in SYSPARSE + or Switches, FLAGFF ;AN000; + push si ;AN004; + mov si, offset F_Choices ;AN000; + xor ax, ax ;AN000; + mov al, Item_Tag ;AN000; + dec al ;AN000; + mov cl, 5 ;AN000; + mul cl ;AN000; + add si, ax ;AN000; + mov al, byte ptr es:[si+1] ;AN000;get the result of choices + mov ffactor, al ;AN000;set form factor + pop si ;AN004; +GR_Ret: ;AN000; + pop ax ;AN006; Restore Synonym ptr + push di ;AN006; Save di + push ax ;AN006; + pop di ;AN006; + mov byte ptr es:[di], ' ' ;AN006;We don't have this switch any more. + pop di ;AN006; + jmp short Gr_Done_Ret ;AN006; +GR_Not_Found_Ret: + pop ax ;AN006;adjust stack +GR_Done_Ret: + ret ;AN000; +Get_Result endp + + +; +; Scans an input line for blank or tab characters. On return, the line pointer +; will be pointing to the next non-blank character. +; +ScanBlanks: + lodsb + cmp al,' ' + jz ScanBlanks + cmp al,9 ; Tab character + jz ScanBlanks + dec si + ret + +; +; Gets a number from the input stream, reading it as a string of characters. +; It returns the number in AX. It assumes the end of the number in the input +; stream when the first non-numeric character is read. It is considered an error +; if the number is too large to be held in a 16 bit register. In this case, AX +; contains -1 on return. +; +;GetNum: +; push bx +; push dx +; xor ax,ax +; xor bx,bx +; xor dx,dx +; +;next_char: +; lodsb +; cmp al,'0' ; check for valid numeric input +; jb num_ret +; cmp al,'9' +; ja num_ret +; sub al,'0' +; xchg ax,bx ; save intermediate value +; push bx +; mov bx,10 +; mul bx +; pop bx +; add al,bl +; adc ah,0 +; xchg ax,bx ; stash total +; jc got_large +; cmp dx,0 +; jz next_char +;got_large: +; mov ax,-1 +; jmp short get_ret +; +;num_ret: +; mov ax,bx +; dec si ; put last character back into buffer +; +;get_ret: +; pop dx +; pop bx +; ret + + +; +; Processes a switch in the input. It ensures that the switch is valid, and +; gets the number, if any required, following the switch. The switch and the +; number *must* be separated by a colon. Carry is set if there is any kind of +; error. +; +;Check_Switch: +; lodsb +; and al,0DFH ; convert it to upper case +; cmp al,'A' +; jb err_swtch +; cmp al,'Z' +; ja err_swtch +; mov cl,cs:switchlist ; get number of valid switches +; mov ch,0 +; push es +; push cs +; pop es ; set es:di -> switches +; push di +; mov di,1+offset switchlist ; point to string of valid switches +; repne scasb +; pop di +; pop es +; jnz err_swtch +; mov ax,1 +; shl ax,cl ; set bit to indicate switch +; mov bx,cs:switches +; or bx,ax ; save this with other switches +; mov cx,ax +; test ax,7cH ; test against switches that require number to follow +; jz done_swtch +; lodsb +; cmp al,':' +; jnz reset_swtch +; call ScanBlanks +; call GetNum +; cmp ax,-1 ; was number too large? +; jz reset_swtch +;IF iTEST +; push ax +; add al,'0' +; add ah,'0' +; mov cs:number,ah +; mov cs:number+1,al +; mov dx,offset nummsg +; call message +; pop ax +;ENDIF +; call Process_Num +; +;done_swtch: +; ret +; +;reset_swtch: +; xor bx,cx ; remove this switch from the records +;err_swtch: +; stc +; jmp short done_swtch + +; +; This routine takes the switch just input, and the number following (if any), +; and sets the value in the appropriate variable. If the number input is zero +; then it does nothing - it assumes the default value that is present in the +; variable at the beginning. +; +;Process_Num: +; push ds +; push cs +; pop ds +; test Switches,cx ; if this switch has been done before, +; jnz done_ret ; ignore this one. +; test cx,flagdrive +; jz try_f +; mov drivenumb,al +;IF iTEST +; add al,"0" +; mov driven,al +; mov dx,offset drvmsg +; call message +;ENDIF +; jmp short done_ret +; +;try_f: +; test cx,flagff +; jz try_t +; mov ffactor,al +;IF iTEST +; add al,"0" +; mov ffnum,al +; mov dx,offset ffmsg +; call message +;ENDIF +; +;try_t: +; cmp ax,0 +; jz done_ret ; if number entered was 0, assume default value +; test cx,flagcyln +; jz try_s +; mov cyln,ax +;IF iTEST +; mov dx,offset cylnmsg +; call message +;ENDIF +; jmp short done_ret +; +;try_s: +; test cx,flagseclim +; jz try_h +; mov slim,ax +;IF iTEST +; mov dx,offset slimmsg +; call message +;ENDIF +; jmp short done_ret +; +;; Switch must be one for number of Heads. +;try_h: +; test cx,flagheads +; jz done_ret +; mov heads,ax +;IF iTEST +; add al,"0" +; mov hdnum,al +; mov dx,offset hdmsg +; call message +;ENDIF +; +;done_ret: +; pop ds +; ret + +; +; SetDrvParms sets up the recommended BPB in each BDS in the system based on +; the form factor. It is assumed that the BPBs for the various form factors +; are present in the BPBTable. For hard files, the Recommended BPB is the same +; as the BPB on the drive. +; No attempt is made to preserve registers since we are going to jump to +; SYSINIT straight after this routine. +; +SetDrvParms: + push cs + pop es + xor bx,bx + call SetDrive ; ds:di -> BDS + ;test cs:switches,flagff ; has formfactor been specified? + ;jz formfcont + mov bl,cs:[ffactor] + mov byte ptr [di].formfactor,bl ; replace with new value +formfcont: + mov bl,[di].FormFactor +;AC000; The followings are redundanat since there is no input specified for Hard file. +; cmp bl,ffHardFile +; jnz NotHardFF +; mov ax,[di].DrvLim +; cmp ax, 0 ;AN000;32 bit sector number? +; push ax +; mov ax,word ptr [di].hdlim +; mul word ptr [di].seclim +; mov cx,ax ; cx has # sectors per cylinder +; pop ax +; xor dx,dx ; set up for div +; div cx ; div #sec by sec/cyl to get # cyl +; or dx,dx +; jz No_Cyl_Rnd ; came out even +; inc ax ; round up +;No_Cyl_Rnd: +; mov cs:[cyln],ax +; mov si,di +; add si,BytePerSec ; ds:si -> BPB for hard file +; jmp short Set_RecBPB +;NotHardFF: +;AC000; End of deletion. + cmp bl,ff48tpi + jnz Got_80_cyln +IF iTEST + mov dx,offset msg48tpi + call message +ENDIF + mov cx,40 + mov cs:[cyln],cx +Got_80_cyln: + shl bx,1 ; bx is word index into table of BPBs + mov si,offset BPBTable + mov si,word ptr [si+bx] ; get address of BPB +Set_RecBPB: + add di,RBytePerSec ; es:di -> Recommended BPB + mov cx,BPBSIZ + cld + repe movsb ; move BPBSIZ bytes + + call Handle_Switches ; replace with 'new' values as + ; specified in switches. +; +; We need to set the media byte and the total number of sectors to reflect the +; number of heads. We do this by multiplying the number of heads by the number +; of 'sectors per head'. This is not a fool-proof scheme!! +; + mov ax,[di].Rdrvlim ; this is OK for two heads + sar ax,1 ; ax contains # of sectors/head + mov cx,[di].Rhdlim + dec cl ; get it 0-based + sal ax,cl + jc Set_All_Done_BRG ; We have too many sectors - overflow!! + mov [di].Rdrvlim,ax + cmp cl,1 +; We use media descriptor byte F0H for any type of medium that is not currently +; defined i.e. one that does not fall into the categories defined by media +; bytes F8H, F9H, FCH-FFH. + + JE HEAD_2_DRV + MOV AL, 1 ;1 sector/cluster + MOV BL, BYTE PTR [DI].Rmediad + CMP BYTE PTR [DI].FormFactor, ffOther + JE GOT_CORRECT_MEDIAD + MOV CH, BYTE PTR [DI].FormFactor + CMP CH, ff48tpi + JE SINGLE_MEDIAD + MOV BL, 0F0h + JMP GOT_CORRECT_MEDIAD +Set_All_Done_BRG:jmp Set_All_Done +SINGLE_MEDIAD: + CMP WORD PTR [DI].RSecLim, 8 ;8 SEC/TRACK? + JNE SINGLE_9_SEC + MOV BL, 0FEh + JMP GOT_CORRECT_MEDIAD +SINGLE_9_SEC: + MOV BL, 0FCh + JMP GOT_CORRECT_MEDIAD +HEAD_2_DRV: + MOV BL, 0F0h ;default 0F0h + MOV AL, 1 ;1 sec/cluster + CMP BYTE PTR [DI].FormFactor, ffOther + JE GOT_CORRECT_MEDIAD + CMP BYTE PTR [DI].FormFactor, ff48tpi + JNE NOT_48TPI + MOV AL, 2 + CMP WORD PTR [DI].RSecLim, 8 ;8 SEC/TRACK? + JNE DOUBLE_9_SEC + MOV BL, 0FFh + JMP GOT_CORRECT_MEDIAD +DOUBLE_9_SEC: + MOV BL, 0FDh + JMP GOT_CORRECT_MEDIAD +NOT_48TPI: + CMP BYTE PTR [DI].FormFactor, ff96tpi + JNE NOT_96TPI + MOV AL, 1 ;1 sec/cluster + MOV BL, 0F9h + JMP GOT_CORRECT_MEDIAD +NOT_96TPI: + CMP BYTE PTR [DI].FormFactor, ffSmall ;3-1/2, 720kb + JNE GOT_CORRECT_MEDIAD ;Not ffSmall. Strange Media device. + MOV AL, 2 ;2 sec/cluster + MOV BL, 0F9h + +;J.K. 12/9/86 THE ABOVE IS A QUICK FIX FOR 3.3 DRIVER.SYS PROB. OLD LOGIC IS COMMENTED OUT. +; mov bl,0F0H ; assume strange media +; mov al,1 ; AL is sectors/cluster - match 3.3 bio dcl. 6/27/86 +; ja Got_Correct_Mediad +;; We check to see if the form factor specified was "other" +; cmp byte ptr [di].FormFactor,ffOther +; jz Got_Correct_Mediad +;; We must have 1 or 2 heads (0 is ignored) +; mov bl,byte ptr [di].Rmediad +; cmp cl,1 +; jz Got_Correct_Mediad +;; We must have one head - OK for 48tpi media +; mov al,1 ; AL is sectors/cluster +; mov ch,byte ptr [di].FormFactor +; cmp ch,ff48tpi +; jz Dec_Mediad +; mov bl,0F0H +; jmp short Got_Correct_Mediad +;Dec_Mediad: +; dec bl ; adjust for one head +;J.K. END OF OLD LOGIC + +Got_Correct_Mediad: + mov byte ptr [di].RSecPerClus,al + mov byte ptr [di].Rmediad,bl +; Calculate the correct number of Total Sectors on medium + mov ax,word ptr [di].Ccyln + mov bx,word ptr [di].RHdLim + mul bx + mov bx,word ptr [di].RSecLim + mul bx +; AX contains the total number of sectors on the disk + mov word ptr [di].RDrvLim,ax +;J.K. For ffOther type of media, we should set Sec/FAT, and # of Root directory +;J.K. accordingly. + cmp byte ptr [di].FormFactor, ffOther ;AN005; + jne Set_All_Ok ;AN005; + xor dx, dx ;AN005; + dec ax ;AN005; DrvLim - 1. + mov bx, 3 ;AN005; Assume 12 bit fat. + mul bx ;AN005; = 1.5 byte + mov bx, 2 ;AN005; + div bx ;AN005; + xor dx, dx ;AN005; + mov bx, 512 ;AN005; + div bx ;AN005; + inc ax ;AN005; + mov [di].RCSecFat, ax ;AN005; + mov [di].RCDir, 0E0h ;AN005; directory entry # = 224 +Set_All_Ok: ;AN005; + clc +Set_All_Done: + RET + +; +; Handle_Switches replaces the values that were entered on the command line in +; config.sys into the recommended BPB area in the BDS. +; NOTE: +; No checking is done for a valid BPB here. +; +Handle_Switches: + call setdrive ; ds:di -> BDS + test cs:switches,flagdrive + jz done_handle ; if drive not specified, exit + mov al,cs:[drivenumb] + mov byte ptr [di].DriveNum,al +; test cs:switches,flagcyln +; jz no_cyln + mov ax,cs:[cyln] + mov word ptr [di].cCyln,ax +no_cyln: + test cs:switches,flagseclim + jz no_seclim + mov ax,cs:[slim] + mov word ptr [di].RSeclim,ax +no_seclim: + test cs:switches,flagheads + jz done_handle + mov ax,cs:[heads] + mov word ptr [di].RHdlim,ax +done_handle: + RET + + +Show_Message proc near +;In) AX = message number +; DS:SI -> Substitution list if necessary. +; CX = 0 or n depending on the substitution number +; DH = -1 FOR UTILITY MSG CLASS, 2 FOR PARSE ERROR +;Out) Message displayed using DOS function 9 with no keyboard input. + push cs ;AN000; + pop ds ;AN000; + mov bx, -1 ;AN000; + mov dl, 0 ;AN000;no input + call SYSDISPMSG ;AN000; + ret ;AN000; +Show_Message endp + +; +; The following are the recommended BPBs for the media that we know of so +; far. + +; 48 tpi diskettes + +BPB48T DW 512 + DB 2 + DW 1 + DB 2 + DW 112 + DW 2*9*40 + DB 0FDH + DW 2 + DW 9 + DW 2 + DW 0 + +; 96tpi diskettes + +BPB96T DW 512 + DB 1 + DW 1 + DB 2 + DW 224 + DW 2*15*80 + DB 0F9H + DW 7 + DW 15 + DW 2 + DW 0 + +BPBSIZ = $-BPB96T + +; 3 1/2 inch diskette BPB + +BPB35 DW 512 + DB 2 + DW 1 ; Double sided with 9 sec/trk + DB 2 + DW 70h + DW 2*9*80 + DB 0F9H + DW 3 + DW 9 + DW 2 + DW 0 + + +BPBTable dw BPB48T ; 48tpi drives + dw BPB96T ; 96tpi drives + dw BPB35 ; 3.5" drives +; The following are not supported, so we default to 3.5" layout + dw BPB35 ; Not used - 8" drives + dw BPB35 ; Not Used - 8" drives + dw BPB35 ; Not Used - hard files + dw BPB35 ; Not Used - tape drives + dw BPB35 ; Not Used - Other + +switchlist db 7,"FHSTDCN" ; Preserve the positions of N and C. + +; The following depend on the positions of the various letters in SwitchList + +flagdrive equ 0004H +flagcyln equ 0008H +flagseclim equ 0010H +flagheads equ 0020H +flagff equ 0040H + +;AN000; +;Equates for message number +NODRIVE_MSG_NUM equ 2 +LOADOK_MSG_NUM equ 3 + +code ends + +end -- cgit v1.2.3