3 ; SCCSID = @(#)format.asm 1.26 85/10/20
4 ; SCCSID = @(#)format.asm 1.26 85/10/20
5 ;***************************************************************
7 ; 86-DOS FORMAT DISK UTILITY
9 ; This routine formats a new disk,clears the FAT and DIRECTORY then
10 ; optionally copies the SYSTEM and COMMAND.COM to this new disk
12 ; SYNTAX: FORMAT [drive][/switch1][/switch2]...[/switch16]
14 ; Regardless of the drive designator , the user will be prompted to
15 ; insert the diskette to be formatted.
17 ;***************************************************************
19 ; 5/12/82 ARR Mod to ask for volume ID
20 ; 5/19/82 ARR Fixed rounding bug in CLUSCAL:
22 ; Added rev number message
23 ; Added dir attribute to DELALL FCB
27 ; 5/1/83 ARR Re-do to transfer system on small memory systems
29 ; 6/17/83 system size re-initialization bug -- mjb001
31 ; 8/31/83 16-bit fat insertion
33 ; 11/2/83 MZ fix signed compare problems for bad sectors
35 ; 11/8/83 EE current directories are always saved and restored
37 ; 11/9/83 NP Printf and changed to an .EXE file
39 ; 11/11/83 ARR Fixed ASSIGN detection to use NameTrans call to see
40 ; if drive letter remapped. No longer IBM only
42 ; 11/13/83 ARR SS does NOT = CS, so all use of BP needs CS override
44 ; 12/27/83 ARR REP STOSB instruction at Clean: changed to be
50 code segment public para
'CODE'
55 data segment public para
'DATA'
58 End_Of_Memory
segment public para
'BUFFERS'
62 code segment public para
'CODE'
64 assume
cs:code,ds:nothing
,es:nothing
66 ;-------------------------------------------------------------------------------
67 ; Define as public for debugging
71 public AddToSystemSize
72 public Phase1Initialisation
75 public Phase2Initialisation
78 public DisplayCurrentTrack
79 public WriteFileSystem
81 public CurrentLogicalSector
82 public PrintErrorAbort
83 public GetDeviceParameters
84 public SetDeviceParameters
85 public Multiply_32_Bits
154 ; public TESTSYSDISK ; dcl 8/23/86
172 public GotDeviceParameters
173 public LoadSectorTable
174 public NotBigTotalSectors
178 public ContinueFormat
179 public ReportBadTrack
183 public ControlC_Handler
199 public systemDriveLetter
213 public sectorsInRootDirectory
214 public directorySector
215 public printStringPointer
228 public currentCylinder
229 public PercentComplete
230 public Formatted_Tracks_High
231 public Formatted_Tracks_Low
234 public deviceParameters
237 ;-------------------------------------------------------------------------------
239 data segment public para
'DATA'
240 extrn msgAssignedDrive
:byte
241 extrn msgBadDosVersion
:byte
242 extrn msgDirectoryWriteError
:byte
243 extrn msgFormatComplete
:byte
244 extrn msgFormatNotSupported
:byte
245 extrn msgFATwriteError
:byte
246 extrn msgInvalidDeviceParameters
:byte
247 extrn msgLabelPrompt
:byte
248 extrn msgNeedDrive
:byte
249 extrn msgNoSystemFiles
:byte
250 extrn msgNetDrive
:byte
251 extrn msgInsertDisk
:byte
252 extrn msgHardDiskWarning
:byte
253 extrn msgSystemTransfered
:byte
254 extrn msgFormatAnother?
:byte
255 extrn msgBadCharacters
:byte
256 extrn msgBadDrive
:byte
257 extrn msgInvalidParameter
:byte
258 extrn msgParametersNotSupported
:byte
259 extrn msgReInsertDisk
:byte
260 extrn msgInsertDosDisk
:byte
261 extrn msgFormatFailure
:byte
262 extrn ContinueMsg
:Byte
263 extrn msgNotSystemDisk
:byte
264 extrn msgDiskUnusable
:byte
265 extrn msgOutOfMemory
:byte
266 extrn msgCurrentTrack
:byte
267 extrn msgWriteProtected
:byte
268 extrn msgInterrupt
:byte
270 extrn Fatal_Error
:Byte
271 extrn Read_Write_Relative
:Byte
272 extrn PSP_Segment
:Word
273 extrn Parse_Error_Msg
:Byte
274 extrn Extended_Error_Msg
:Byte
300 ;-------------------------------------------------------------------------------
301 ; And this is the actual data
303 data segment public para
'DATA'
304 public deviceParameters
310 validSavedDeviceParameters db 0
311 savedDeviceParameters a_DeviceParameters
<>
312 deviceParameters a_DeviceParameters
<>
314 Disk_Access A_DiskAccess_Control
<> ;an000; dms;
316 formatPacket a_FormatPacket
<>
317 RWPacket a_TrackReadWritePacket
<>
318 RW_TRF_Area db 512 dup(0)
329 Formatted_Tracks_Low dw 0
330 Formatted_Tracks_High dw 0
333 public NumSectors
,TrackCnt
336 PercentComplete dw 0FFFFh ;Init non-zero so msg will display first time
342 fLastChance db FALSE
; Flags reinvocation from
343 ; LastChanceToSaveIt. Used by DSKPRM
345 sectorsInRootDirectory dw ?
351 printStringPointer dw 0
353 ; Exit status defines
359 ExitDriveNotReady equ
6 ;an017; dms;drive not ready error
360 ExitWriteProtect equ
7 ;an017; dms;write protect error
364 DBLFLG DB 0 ;Initialize flags to zero
366 MSTART DW ? ; Start of sys file buffer (para#)
367 MSIZE DW ? ; Size of above in paragraphs
369 FILSTAT DB ? ; In memory status of files
370 ; XXXXXX00B BIOS not in
371 ; XXXXXX01B BIOS partly in
372 ; XXXXXX10B BIOS all in
373 ; XXXX00XXB DOS not in
374 ; XXXX01XXB DOS partly in
375 ; XXXX10XXB DOS all in
376 ; XX00XXXXB COMMAND not in
377 ; XX01XXXXB COMMAND partly in
378 ; XX10XXXXB COMMAND all in
380 USERDIRS DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory
382 Paras_Per_Fat dw 0000h ;an000;holds fat para count
383 Fat_Init_Value dw 0000h ;an000;initializes the FAT
385 bios a_FileStructure <>
386 BiosAttributes EQU attr_hidden + attr_system + attr_read_only
388 dos a_FileStructure <>
389 DosAttributes EQU attr_hidden + attr_system + attr_read_only
391 command a_FileStructure <>
392 CommandAttributes EQU 0
393 CommandFile DB "X
:\COMMAND
.COM
",0
394 CommandFile_Buffer DB 127 dup(0) ;an000;allow room for copy
396 Command_Com DB "COMMAND
.COM
",0
398 VOLFCB DB -1,0,0,0,0,0,8
404 DelFCB DB -1,0,0,0,0,0,8
406 DelNAM DB "???????????
"
410 TRANSRC DB "A
:CON
",0,0 ; Device so we don't hit the drive
411 TRANDST DB "A
:\",0,0,0,0,0,0,0,0,0,0
428 systemDriveLetter db "x"
430 CTRL_BREAK_VECTOR dd ?
;ac010; dms;Holds CTRL-Break
433 Command_Path dd ?
;an011; dms;hold pointer to
436 Comspec_ID db "COMSPEC=",00 ;an011; dms;Comspec target
439 Environ_Segment dw ?
;an011; dms;hold segment of
441 ;======== Disk Table ========== ;an012; dms;
442 ;Used if NumberOfFATs in BPB
445 DiskTable dw 0, 32680, 0803h, 512, 0
446 dw 4h
, 0000h, 0402h, 512, Fbig
447 dw 8h
, 0000h, 0803h, 512, Fbig
448 dw 10h
, 0000h, 1004h
, 512, Fbig
449 dw 20h
, 0000h, 2005h
, 512, Fbig
451 public Org_AX
;an000; dms;make it known
452 Org_AX dw ?
;an000; dms;AX on entry
454 Cluster_Boundary_Adj_Factor dw ?
;an000; dms;
455 Cluster_Boundary_SPT_Count dw ?
;an000; dms;
456 Cluster_Boundary_Flag db False
;an000; dms;
457 Cluster_Boundary_Buffer_Seg dw ?
;an000; dms;
459 Relative_Sector_Low dw ?
;an000; dms;
460 Relative_Sector_High dw ?
;an000; dms;
462 FAT_Flag db ?
;an000; dms;
463 Tracks_To_Format dw ?
;an015; dms;
464 Track_Count dw ?
;an015; dms;
465 Format_End db FALSE
;an015; dms;
467 public Msg_Allocation_Unit_Val
469 Msg_Allocation_Unit_Val dd ?
;an019; dms;
474 ;For FORPROC and FORMES modules
476 public secsiz
,clussiz
,inbuff
478 PUBLIC crlf
,std_printf
480 public switchmap
,drive
,driveLetter
,fatSpace
481 public fBigFat
, PrintString
,currentHead
,currentCylinder
482 extrn CheckSwitches
:near,LastChanceToSaveIt
:near
484 extrn WriteBootSector
:near,OemDone
:near
485 extrn AccessDisk
:near
488 extrn Write_Disk
:near
490 data segment public para
'DATA'
491 extrn BiosFile
:byte,DosFile
:byte
496 EXTRN FormatAnother?
:near,Yes?
:near,REPORT
:NEAR,USER_STRING
:NEAR
497 data segment public para
'DATA'
498 extrn syssiz
:dword,biosiz
:dword
501 DOSVER_LOW EQU
0300H+20
502 DOSVER_HIGH EQU
0300H+20
504 RECLEN EQU fcb_RECSIZ
+7
507 PSP_Environ equ 2
ch ;an011; dms;location of
511 Fbig equ
0ffh ;an000; dms;flag for big FAT
516 Set_Data_Segment
; ;AC000;
517 mov Org_AX
,ax ;an000; dms;save ax on entry
518 jmp Main_Init
; ;AC000;
521 Main_Routine: ; ;AN000;
522 ; Set memory requirements
523 mov bx,PSP_Segment
;Shrink to free space for FAT ;AC000;
525 mov bx,End_Of_Memory
; ;AC000;
526 sub bx,PSP_Segment
; ;AC000;
527 DOS_Call Setblock
; ;AC000;
529 call Get_Disk_Access
;an014; dms;
530 cmp Disk_Access
.DAC_Access_Flag
,0ffh ;an014; dms;is access already allowed?
531 ; $if ne ;an014; dms;no, don't change status
533 lea dx,Disk_Access
;an014; dms;point to parm block
534 mov Disk_Access
.DAC_Access_Flag
,01h ;an014; dms;signal disk access
535 call Set_Disk_Access_On_Off
;an014;dms;allow disk access
536 ; $endif ;an014; dms;
539 CALL Phase1Initialisation
542 Message msgFormatFailure
; ;AC000;
548 Message msgOutOfMemory
; ;AC000;
554 TEST SWITCHMAP
,SWITCH_S
560 JZ MEMERRJ
;No memory
566 JMP MEMERR
;No memory
572 mov bios
.fileSizeInParagraphs
,0 ;mjb001 initialize file size
573 mov dos
.fileSizeInParagraphs
,0 ;mjb001 ...
574 mov command
.fileSizeInParagraphs
,0 ;mjb001 ...
575 CALL READDOS
;Read BIOS and DOS
576 JNC INITCALL
;OK -- read next file
578 CALL SYSPRM
;Prompt for system disk
579 JMP RDFRST
;Try again
582 CALL Phase2Initialisation
589 ;Must intialize for each iteration
591 MOV WORD PTR SYSSIZ
,0
592 MOV WORD PTR SYSSIZ
+2,0
593 MOV BYTE PTR DBLFLG
,0
594 mov ExitStatus
, ExitOK
596 MOV SWITCHMAP
,DX ;Restore original Switches
597 ; DiskFormat will handle call for new disk
598 CALL DISKFORMAT
;Format the disk
602 test SwitchMap
,Switch_Select
;an017; dms;SELECT option?
603 ; $if z ;an017; dms;no - display message
605 Message msgFormatFailure
; ;AC000;
606 mov ExitStatus
, ExitFatal
;an017; dms;
607 ; $endif ;an017; dms;
609 CALL MORE
;See if more disks to format
612 ;Mark any bad sectors in the FATs
613 ;And keep track of how many bytes there are in bad sectors
616 CALL BADSECTOR
;Do bad track fix-up
617 JC FRMTPROB
;Had an error in Formatting - can't recover
618 CMP AX,0 ;Are we finished?
619 JNZ TRKFND
;No - check error conditions
622 mov bx,word ptr Relative_Sector_Low
;get the low word of the sector ;an000; dms;
623 CMP BX,STARTSECTOR
;Are any sectors in the system area bad?
624 JAE CLRTEST
; MZ 2.26 unsigned compare
625 Message msgDiskUnusable
; ;AC000;
626 JMP FRMTPROB
;Bad disk -- try again
628 MOV SECTORS
,AX ;Save the number of sectors on the track
629 TEST SWITCHMAP
,SWITCH_S
;If system requested calculate size
631 CMP BYTE PTR DBLFLG
,0 ;Have we already calculated System space?
632 JNZ CMPTRKS
;Yes -- all ready for the compare
633 INC BYTE PTR DBLFLG
;No -- set the flag
634 CALL GETBIOSIZE
; Get the size of the BIOS
635 MOV DX,WORD PTR SYSSIZ
+2
636 MOV AX,WORD PTR SYSSIZ
637 MOV WORD PTR BIOSIZ
+2,DX
638 MOV WORD PTR BIOSIZ
,AX
641 MOV DX,WORD PTR BIOSIZ
+2
642 MOV AX,WORD PTR BIOSIZ
643 DIV deviceParameters
.DP_BPB
.BPB_BytesPerSector
645 MOV SYSTRKS
,AX ;Space FAT,Dir,and system files require
647 mov bx,word ptr Relative_Sector_Low
;get the low word of the sector ;an000; dms;
649 JA BAD100
; MZ 2.26 unsigned compare
650 mov ExitStatus
, ExitFatal
651 Message msgNotSystemDisk
; ;AC000;
652 AND SWITCHMAP
,NOT SWITCH_S
;Turn off system transfer switch
653 MOV WORD PTR SYSSIZ
+2,0 ;No system to transfer
654 MOV WORD PTR SYSSIZ
,0 ;No system to transfer
657 CMP deviceParameters
.DP_DeviceType
, DEV_HARDDISK
;an000; dms;hard disk?
658 ; $if e ;an000; dms; yes
660 call Get_Bad_Sector_Hard
;an000; dms;see if a sector is bad
661 ; $else ;an000; dms;floppy disk
664 call Get_Bad_Sector_Floppy
;an000; dms;mark entire track bad
665 ; $endif ;an000; dms;
670 ; Inputs: BX = Cluster number
671 ; Outputs: The given cluster is marked as invalid
672 ; Zero flag is set if the cluster was already marked bad
673 ; Registers modified: DX,SI
674 ; No other registers affected
676 ;=========================================================================
677 ; BADCLUS : Marks off a bad cluster in the FAT
678 ; If a cluster has already been marked bad it
679 ; will return with ZR.
681 ; Inputs : DX:AX - Cluster Number
683 ; Outputs : Cluster is marked invalid
684 ; ZR set if cluster already marked bad
685 ;=========================================================================
687 BadClus proc
near ;an000; mark bad clusters
689 push di ;an000; save affected regs
696 mov es, word ptr fatSpace
+ 2 ;an005; obtain seg of FAT
697 CMP fBigFat
,TRUE
;an005; 16 bit fat?
698 ; $if ne ;an005; no - 12-bit fat
700 push ax ;an000; save ax - contains low cluster number
701 mov si,dx ;an000; pick up high word of cluster
702 mov di,ax ;an000; pick up low word of cluster
703 mov cx,2 ;an000; divide by 2
704 call Divide_32_Bits
;an000; 32 bit divide
706 add ax,di ;an000; add in low word of result
707 adc dx,si ;an000; pick up low word carry
708 ;cluster = cluster * 1.5
709 add ax,word ptr fatspace
;an005; add 0
710 adc dx,0 ;an000; pick up carry
712 mov bx,dx ;an000; get high word for adjust
713 mov cx,es ;an005; place seg in ax
714 call BadClus_Address_Adjust
;an000; adjust segment offset
715 mov es,cx ;an000; new segment
716 mov si,ax ;an000; new offset
718 MOV DX,0FF7h ;an005; bad cluster flag
719 MOV AX,0FFFh ;an005; mask value
721 pop cx ;an000; restore ax in cx - low cluster number
722 test cx,1 ;an000; is old clus num odd?
725 mov cl,4 ;an005; set shift count
726 SHL AX,cl ;an005; get only 12 bits - fff0
727 mov cl,4 ;an005; set shift count
728 SHL DX,cl ;an005; get 12 bits - ff70
731 ; $else ;an005; 16-bit fats here
734 xor si,si ;an005; clear si
735 mov bx,dx ;an000; get high word for multiply
736 mov cx,2 ;an000; multiply by 2
737 call Multiply_32_Bits
;an000; 32 bit multiply
739 ; FAT cell. This gives
740 ; us an offset into the
743 mov cx,es ;an005; place seg in cx
744 call BadClus_Address_Adjust
;an000; adjust segment:offset
745 mov es,cx ;an000; new segment
746 mov si,ax ;an000; new offset
748 MOV DX,0FFF7h ;an005; bad cluster value
749 MOV AX,0FFFFh ;an005; mask value
753 MOV CX,es:[SI] ;an005; get contents of fat cell
754 AND CX,AX ;an005; make it 12 or 16 bit
755 ; depending on value in AX
756 NOT AX ;an005; set AX to 0
757 AND es:[SI],AX ;an005; clear FAT entry
758 OR es:[SI],DX ;an005; flag it a bad cluster
759 CMP DX,CX ; return op == badval;
772 TEST SWITCHMAP
,SWITCH_S
;If system requested, calculate size
774 CMP BYTE PTR DBLFLG
,0 ;Have we already calculated System space?
776 INC BYTE PTR DBLFLG
;No -- set the flag
777 CALL GETSIZE
;Calculate the system size
779 call Ctrl_Break_Save
;ac010; dms;save CTRL-Break
788 call Reset_Ctrl_Break
;ac010; dms;restore CTRL-Break
789 Message msgDiskUnusable
; ;AC000;
804 JZ LOUSEP
;Something BAD has happened
805 MOV [BX.dpb_next_free
],0 ; Reset allocation to start of disk
806 MOV [BX.dpb_free_cnt
],-1 ; Force free space to be computed
808 TEST SWITCHMAP
,SWITCH_S
;System desired
811 call AccessDisk
; note what is current logical drive
812 CALL WRITEDOS
;Write the BIOS & DOS
814 Message msgNotSystemDisk
; ;AC000;
815 MOV WORD PTR SYSSIZ
+2,0 ;No system transfered
816 MOV WORD PTR SYSSIZ
,0 ;No system transfered
822 test SwitchMap
,(Switch_Select
or SWITCH_AUTOTEST
) ;Don't display if EXEC'd by ;AN000;
823 ; $IF Z ; Select ;AN000;
825 Message msgSystemTransfered
; ;AC000;
830 call Reset_Ctrl_Break
;ac010; dms;restore CTRL-Break
839 CALL DONE
;Final call to OEM module
841 JMP FRMTPROB
;Report an error
846 ;TEMP FIX for /AUTOTEST
848 test SwitchMap
,(Switch_Autotest
or Switch_8
) ;TEMP
854 test SwitchMap
,(Switch_Select
or SWITCH_AUTOTEST
) ;Need to shut down the report? ;AN000;
855 ; $IF Z ;If exec'd by Select, we do ;AN000;
857 CALL REPORT
;Print report
860 CALL MORE
;See if more disks to format
861 JMP SYSLOOP
;If we returned from MORE then continue
863 ;******************************************
864 ; Calculate the size in bytes of the system rounded up to sector and
865 ; cluster boundries, Answer in SYSSIZ
875 MOV AX,WORD PTR bios
.fileSizeInBytes
876 MOV DX,WORD PTR bios
.fileSizeInBytes
+2
882 MOV AX,WORD PTR dos
.fileSizeInBytes
883 MOV DX,WORD PTR dos
.fileSizeInBytes
+2
889 MOV AX,WORD PTR command
.fileSizeInBytes
890 MOV DX,WORD PTR command
.fileSizeInBytes
+2
895 ;Calculate the number of sectors used for the system
896 PUBLIC AddToSystemSize
897 AddToSystemSize proc
near
899 DIV deviceParameters
.DP_BPB
.BPB_BytesPerSector
902 INC AX ; Round up to next sector
907 mov bl, deviceParameters
.DP_BPB
.BPB_SectorsPerCluster
914 ADD AX,DX ; Round up sector count to cluster
917 MUL deviceParameters
.DP_BPB
.BPB_BytesPerSector
918 ADD WORD PTR SYSSIZ
,AX
919 ADC WORD PTR SYSSIZ
+2,DX
926 mov Formatted_Tracks_Low
,0 ;Reinit the track counter ;AN000;
927 mov Formatted_Tracks_High
,0 ; in case of another format ;AN000;
928 test SwitchMap
,(Switch_Select
or SWITCH_AUTOTEST
) ;Don't display if EXEC'd by ;AN000;
929 jnz ExitProgram
; Select ;AN000;
931 CMP deviceParameters
.DP_DeviceType
, DEV_HARDDISK
933 test SwitchMap
,(SWITCH_Select
or SWITCH_AUTOTEST
) ;If exec'd from select, then;AN000;
934 jnz ExitProgram
; don't give user choice ;AN000;
935 CALL FormatAnother?
;Get yes or no response
942 Set_Data_Segment
;Make sure have addressability ;AN000;
943 mov ExitStatus
,ExitFatal
946 test validSavedDeviceParameters
, 0ffH
947 jz DoNotRestoreDeviceParameters
948 mov savedDeviceParameters
.DP_SpecialFunctions
, TRACKLAYOUT_IS_GOOD
949 lea dx, savedDeviceParameters
950 call SetDeviceParameters
951 DoNotRestoreDeviceParameters:
953 call Format_Access_Wrap_Up
;determine access status ;an000; dms;determine access status
954 mov al,ExitStatus
;Get Errorlevel ;AN000;
955 DOS_Call Exit
;Exit program ;AN000;
956 int 20h
;If other exit fails ;AN000;
958 ; Prompt the user for a system diskette in the default drive
960 MOV AH,GET_DEFAULT_DRIVE
;Will find out the default drive
961 INT 21H
;Default now in AL
964 ADD AL,41H
;Now in Ascii
965 MOV systemDriveLetter
,AL ;Text now ok
969 ; Media is non-removable. Switch sys disk to drive A. Check, though, to see
970 ; if drive A is removable too.
973 MOV BYTE PTR [systemDriveLetter
],AL
980 Message msgNoSystemFiles
; ;AC000;
985 mov al, systemDriveLetter
988 Message msgInsertDOSDisk
; ;AC000;
990 ;lea dx, ptr_msgInsertDosDisk
991 ;CALL std_printf ;Print first line
992 CALL USER_STRING
;Wait for a key
1000 Message MsgInsertDisk
; ;AC000;
1001 Message ContinueMsg
;
1002 ;lea DX, ptr_msgInsertDisk
1003 ;CALL std_printf ;Print first line
1004 CALL USER_STRING
;Wait for a key
1009 ; Determine if the drive indicated in BX is removable or not.
1011 ; Inputs: BX has drive (0=def, 1=A)
1012 ; Outputs: Carry clear
1016 ; Registers modified: none
1020 MOV AX,(IOCTL
SHL 8) OR 8 ; Rem media check
1023 MOV AX,(IOCTL
SHL 8) + 9 ; Is it a NET drive?
1025 JC NotRemove
; Yipe, say non-removable
1027 JNZ NotRemove
; Is NET drive, say non-removeable
1028 JMP IsRemove
; Is local, say removable
1044 ; This routine prompts for the insertion of the correct diskette
1045 ; into the Target drive, UNLESS we are being re-entrantly invoked
1046 ; from LastChanceToSaveIt. If the target is a Hardisk we issue a
1050 ; deviceParameters.DP_DeviceType
1055 ; fLastChance := FALSE
1057 ; Registers affected:
1061 CMP fLastChance
,TRUE
1064 CMP deviceParameters
.DP_DeviceType
, DEV_HARDDISK
1066 Message msgHardDiskWarning
; ;AC000;
1067 ;lea dx, ptr_msgHardDiskWarning
1070 jnc OkToFormatHardDisk
1071 mov ExitStatus
, ExitNo
1082 Message msgInsertDisk
; ;AC000;
1083 Message ContinueMsg
;
1084 ;lea dx,ptr_msgInsertDisk
1086 CALL USER_STRING
;Wait for any key
1091 mov fLastChance
, FALSE
1095 ;-------------------------------------------------------------------------------
1100 Message msgInterrupt
; ;AC000;
1101 mov ExitStatus
, ExitCtrlC
1107 mov dx,offset msgCRLF
;CR,LF added to message ;AC000;
1109 ;mov printStringPointer, dx
1110 ;lea dx, PrintStringPointer
1115 call Display_Interface
; ;AC000;
1118 ;-------------------------------------------------------------------------------
1121 ;****************************************
1122 ;Copy IO.SYS, MSDOS.SYS and COMMAND.COM into data area.
1123 ; Carry set if problems
1126 push ax ;save regs ;an025; dms;
1127 push bx ; ;an025; dms;
1128 push es ; ;an025; dms;
1130 mov ah,Get_In_Vars
;Find out boot drive ;an025; dms;
1131 int 21h
; ;an025; dms;
1132 mov al,byte ptr es:[bx].SysI_Boot_Drive
;get 1 based drive ID ;an025; dms;
1133 add al,40h
;Make it ASCII ;an025; dms;
1134 mov [BiosFile
],al ;Stuff it in file specs. ;an025; dms;
1135 mov [DosFile
],al ; ;an025; dms;
1136 mov [CommandFile
],al ; ;an025; dms;
1138 pop es ;restore regs ;an025; dms;
1139 pop bx ; ;an025; dms;
1140 pop ax ; ;an025; dms;
1142 call Get_BIOS
; dcl 8/23/86
1147 MOV BYTE PTR [FILSTAT
],0
1148 MOV BX,[bios
.fileHandle
]
1151 ADD DX,[MSIZE
] ; CX first bad para
1152 MOV [bios
.fileStartSegment
],AX
1153 MOV CX,[bios
.fileSizeInParagraphs
]
1157 MOV BYTE PTR [FILSTAT
],00000001B ; Got part of BIOS
1162 MOV DS,[bios
.fileStartSegment
]
1170 MOV AX,(LSEEK
SHL 8) OR 1
1172 MOV WORD PTR [bios
.fileOffset
],AX
1173 MOV WORD PTR [bios
.fileOffset
+2],DX
1178 ; CALL COMCLS ; dcl 8/23/86
1179 call FILE_CLS
; dcl 8/23/86
1184 MOV BYTE PTR [FILSTAT
],00000010B ; Got all of BIOS
1186 LES SI,[bios
.fileSizeInBytes
]
1190 MOV DS,[bios
.fileStartSegment
]
1197 push ax ; dcl 8/23/86
1198 push dx ; dcl 8/23/86
1199 call File_Cls
; dcl 8/23/86
1200 call Get_DOS
; dcl 8/23/86
1201 pop dx ; dcl 8/23/86
1202 pop ax ; dcl 8/23/86
1204 JNC Found_IBMDOS
;mt 12/8/86 P894
1207 Found_IBMDOS: ;mt 12/8/86
1209 MOV BX,[dos
.fileHandle
]
1210 MOV [dos
.fileStartSegment
],AX
1211 CMP AX,DX ; No room left?
1213 MOV CX,[dos
.fileSizeInParagraphs
]
1217 OR BYTE PTR [FILSTAT
],00000100B ; Got part of DOS
1218 SUB DX,[dos
.fileStartSegment
]
1223 MOV DS,[dos
.fileStartSegment
]
1231 MOV AX,(LSEEK
SHL 8) OR 1
1233 MOV WORD PTR [dos
.fileOffset
],AX
1234 MOV WORD PTR [dos
.fileOffset
+2],DX
1238 OR BYTE PTR [FILSTAT
],00001000B ; Got all of DOS
1240 LES SI,[dos
.fileSizeInBytes
]
1244 MOV DS,[dos
.fileStartSegment
]
1250 CLSALLJ: JNC NOTCLSALL
;PTM P894 mt 12/8/86
1254 push ax ; dcl 8/23/86
1256 push dx ; dcl 8/23/86
1257 call File_cls
; dcl 8/23/86
1258 call Get_Command_Path
;ac011; dms; get path of
1260 call Get_COMMAND
;ac011; dms; Point to COMMAND
1262 pop dx ; dcl 8/23/86
1263 pop ax ; dcl 8/23/86
1265 JNC Found_COMMAND
;mt 12/8/86 P894
1268 Found_COMMAND: ;mt 12/8/86
1269 MOV BX,[command
.fileHandle
]
1270 MOV [command
.fileStartSegment
],AX
1271 CMP AX,DX ; No room left?
1273 MOV CX,[command
.fileSizeInParagraphs
]
1277 OR BYTE PTR [FILSTAT
],00010000B ; Got part of COMMAND
1278 SUB DX,[command
.fileStartSegment
]
1283 MOV DS,[command
.fileStartSegment
]
1291 MOV AX,(LSEEK
SHL 8) OR 1
1293 MOV WORD PTR [command
.fileOffset
],AX
1294 MOV WORD PTR [command
.fileOffset
+2],DX
1298 OR BYTE PTR [FILSTAT
],00100000B ; Got all of COMMAND
1300 LES SI,[command
.fileSizeInBytes
]
1304 MOV DS,[command
.fileStartSegment
]
1311 ;**************************************************
1312 ;Write BIOS DOS COMMAND to the newly formatted disk.
1316 MOV CX,BiosAttributes
1317 MOV DX,OFFSET BiosFile
1319 LES SI,[bios
.fileSizeInBytes
]
1326 TEST BYTE PTR FILSTAT
,00000010B
1328 call Get_BIOS
; dcl 8/23/86
1329 jnc Got_WBIOS
;mt 12/8/86 P894
1335 LES SI,[bios
.fileOffset
]
1338 MOV WORD PTR [IOCNT
],SI
1339 MOV WORD PTR [IOCNT
+2],DI
1347 LES SI,[bios
.fileSizeInBytes
]
1351 MOV DS,[bios
.fileStartSegment
]
1358 MOV CX,bios
.fileTime
1359 MOV DX,bios
.fileDate
1361 MOV CX,DosAttributes
1362 MOV DX,OFFSET DosFile
1364 LES SI,[dos
.fileSizeInBytes
]
1372 TEST BYTE PTR FILSTAT
,00001000B
1374 call Get_DOS
; dcl 8/23/86
1375 jnc Got_WDOS
;mt 12/8/86 P894
1380 TEST BYTE PTR FILSTAT
,00000100B
1382 MOV WORD PTR [dos
.fileOffset
],0
1383 MOV WORD PTR [dos
.fileOffset
+2],0
1390 LES SI,[dos
.fileOffset
]
1393 MOV WORD PTR [IOCNT
],SI
1394 MOV WORD PTR [IOCNT
+2],DI
1401 LES SI,[dos
.fileSizeInBytes
]
1405 MOV DS,[dos
.fileStartSegment
]
1415 MOV CX,CommandAttributes
1416 call Command_Root
;an011; dms;adjust path for
1417 ;COMMAND.COM creation
1418 MOV DX,OFFSET CommandFile
1420 LES SI,[command
.fileSizeInBytes
]
1427 TEST BYTE PTR FILSTAT
,00100000B
1429 call Get_COMMAND
; dcl 8/23/86
1430 jnc Got_WCOM
;mt 12/8/86 P894
1434 MOV BP,OFFSET command
1435 TEST BYTE PTR FILSTAT
,00010000B
1437 MOV WORD PTR [command
.fileOffset
],0
1438 MOV WORD PTR [command
.fileOffset
+2],0
1445 LES SI,[command
.fileOffset
]
1448 MOV WORD PTR [IOCNT
],SI
1449 MOV WORD PTR [IOCNT
+2],DI
1456 LES SI,[command
.fileSizeInBytes
]
1460 MOV DS,[command
.fileStartSegment
]
1467 MOV CX,command
.fileTime
1468 MOV DX,command
.fileDate
1470 ;****************************************************************
1471 ; I don't see the need for the following code!! - RS 3.20
1472 ; CMP BYTE PTR [FILSTAT],00101010B
1475 ; CALL READDOS ; Start back with BIOS
1477 ; CALL SYSPRM ;Prompt for system disk
1478 ; JMP RDFRST2 ;Try again
1480 ;****************************************************************
1484 ;*********************************************
1485 ; Create a file on target disk
1486 ; CX = attributes, DX points to name
1487 ; DI:SI is size file is to have
1489 ; There is a bug in DOS 2.00 and 2.01 having to do with writes
1490 ; from the end of memory. In order to circumvent it this routine
1491 ; must create files with the length in DI:SI
1493 ; On return BX is handle, carry set if problem
1508 INT 21H
; Seek to eventual EOF
1511 INT 21H
; Set size of file to position
1515 INT 21H
; Seek back to start
1519 ; Examine error code in AX to see if it is too-many-open-files.
1520 ; If it is, we abort right here. Otherwise we return.
1523 CMP AX,error_too_many_open_files
1525 Extended_Message
; ;AC006;
1528 ;*********************************************
1529 ; Close a file on the target disk
1530 ; CX/DX is time/date, BX is handle
1533 MOV AX,(FILE_TIMES
SHL 8) OR 1
1539 ;****************************************
1540 ; Transfer system files
1541 ; BP points to data structure for file involved
1542 ; offset is set to current amount read in
1543 ; Start set to start of file in buffer
1544 ; TempHandle is handle to write to on target
1547 MOV AL,[systemDriveLetter
]
1548 CMP AL,[DriveLetter
]
1552 CALL TARGPRM
;Get target disk
1556 ;Enter here if some of file is already in buffer, IOCNT must be set
1557 ; to size already in buffer.
1559 MOV SI,WORD PTR [IOCNT
]
1560 MOV DI,WORD PTR [IOCNT
+2]
1562 MOV DS,ds:[BP.fileStartSegment
]
1564 CALL WRITEFILE
; Write next part
1570 LES AX,ds:[BP.fileOffset
]
1571 CMP AX,WORD PTR ds:[BP.fileSizeInBytes
]
1574 CMP AX,WORD PTR ds:[BP.fileSizeInBytes
+2]
1577 return
; Carry clear from CMP
1580 ;Enter here if none of file is in buffer
1584 MOV AX,[MSTART
] ;Furthur IO done starting here
1585 MOV ds:[BP.fileStartSegment
],AX ;point to start of buffer
1586 MOV AL,[systemDriveLetter
] ;see if we have system disk
1587 CMP AL,[DriveLetter
]
1592 CALL SYSPRM
;Prompt for system disk
1594 ; CALL TESTSYSDISK ; dcl 8/23/86
1596 MOV BX,word ptr DS:[BP.fileHandle
] ; CS over ARR 2.30
1598 LES DX,dword ptr DS:[BP.fileOffset
] ; CS over ARR 2.30
1606 LES SI,dword ptr DS:[BP.fileSizeInBytes
] ; CS over ARR 2.30
1607 MOV DI,ES ;put high word in di
1609 SUB SI,DX ;get low word value
1610 SBB DI,CX ; DI:SI is #bytes to go
1613 ADD SI,15 ;round up 1 para
1614 ADC DI,0 ;pick up carry
1615 CALL DISID4
;div 16 to get para count
1616 MOV AX,SI ;put para count in ax
1617 POP SI ;restore bytes remaining
1618 POP DI ;restore bytes remaining
1619 CMP AX,[MSIZE
] ;enough memory to read remainder?
1625 MOV WORD PTR [IOCNT
],SI ;save byte count for read
1626 MOV WORD PTR [IOCNT
+2],DI
1639 MOV AX,(LSEEK
SHL 8) OR 1
1641 MOV WORD PTR DS:[BP.fileOffset
],AX ; CS over ARR 2.30
1642 MOV WORD PTR DS:[BP.fileOffset
+2],DX ; CS over ARR 2.30
1646 ;*************************************************
1647 ; Test to see if correct system disk. Open handles
1653 ;TESTSYSDISK: ; dcl 8/23/86
1654 Get_BIOS: ; dcl 8/23/86
1656 MOV DX,OFFSET BiosFile
1659 ; call CheckMany ; dcl 8/23/86
1660 jmp CheckMany
; dcl 8/23/86
1663 MOV [Bios
.fileHandle
],AX
1666 CMP [bios
.fileSizeInParagraphs
],0
1668 CMP [bios
.fileSizeInParagraphs
],AX
1672 MOV BX,[Bios
.fileHandle
]
1674 ; JMP CRET12 ; dcl 8/23/86
1678 MOV [bios
.fileSizeInParagraphs
],AX
1679 MOV WORD PTR [bios
.fileSizeInBytes
],SI
1680 MOV WORD PTR [bios
.fileSizeInBytes
+2],DI
1681 MOV [bios
.fileDate
],DX
1682 MOV [bios
.fileTime
],CX
1686 Get_DOS: ; dcl 8/23/86
1688 MOV DX,OFFSET DosFile
1691 ; call CheckMany ; dcl 8/23/86
1692 ; JMP BIOSCLS ; dcl 8/23/86 Checkmany no ret.
1693 jmp CheckMany
; dcl 8/23/86
1696 MOV [dos
.fileHandle
],AX
1699 CMP [dos
.fileSizeInParagraphs
],0
1701 CMP [dos
.fileSizeInParagraphs
],AX
1706 MOV BX,[dos
.fileHandle
]
1708 ; JMP BIOSCLS ; dcl 8/23/86
1712 MOV [dos
.fileSizeInParagraphs
],AX
1713 MOV WORD PTR [dos
.fileSizeInBytes
],SI
1714 MOV WORD PTR [dos
.fileSizeInBytes
+2],DI
1715 MOV [dos
.fileDate
],DX
1716 MOV [dos
.fileTime
],CX
1724 MOV DX,OFFSET CommandFile
1727 ; call CheckMany ; dcl 8/23/86
1728 ; JMP DosCls ; dcl 8/23/86
1729 jmp Checkmany
; dcl 8/23/86
1732 MOV [command
.fileHandle
],AX
1735 CMP [command
.fileSizeInParagraphs
],0
1737 CMP [command
.fileSizeInParagraphs
],AX
1741 MOV BX,[command
.fileHandle
]
1743 ; JMP DOSCLS ; dcl 8/23/86
1747 MOV [command
.fileSizeInParagraphs
],AX
1748 MOV WORD PTR [command
.fileSizeInBytes
],SI
1749 MOV WORD PTR [command
.fileSizeInBytes
+2],DI
1750 MOV [command
.fileDate
],DX
1751 MOV [command
.fileTime
],CX
1755 FILE_CLS: ; dcl 8/23/86
1756 MOV AH,CLOSE
; dcl 8/23/86
1757 INT 21H
; dcl 8/23/86
1760 ;*******************************************
1761 ; Handle in BX, return file size in para in AX
1762 ; File size in bytes DI:SI, file date in DX, file
1766 MOV AX,(LSEEK
SHL 8) OR 2
1772 ADD AX,15 ; Para round up
1774 AND DX,0FH ; If the file is larger than this it
1775 ; is bigger than the 8086 address
1787 MOV AX,FILE_TIMES
SHL 8
1792 ;********************************************
1795 ; DI:SI is byte count to I/O
1797 ; Carry set if screw up
1800 ; I/O 64K - 1 bytes DI times
1805 ; Must preserve AX,DX
1831 CMP AX,CX ; If not =, AX<CX, carry set.
1842 CMP AX,CX ; If not =, AX<CX, carry set.
1857 CMP AX,CX ; If not =, AX<CX, carry set.
1867 CMP AX,CX ; If not =, AX<CX, carry set.
1869 CALL NORMALIZE
; Clears carry
1879 ;*********************************
1880 ; Shift DI:SI left 4 bits
1889 ;*********************************
1890 ; Shift DI:SI right 4 bits
1899 ;********************************
1914 AND DX,0FH ; Clears carry
1917 ;-------------------------------------------------------------------------------
1918 ; Phase1Initialisation:
1919 ; This routine MUST set up fatSpace, and fBigFat
1920 ; It also does most of the other initialisation
1923 ; Open a handle for accessing the drive
1924 ; Get device parameters
1925 ; save device parameters for exit
1926 ; Check switches against parameters
1927 ; Use switches to modify device parameters
1928 ; directorySector = malloc( Bytes Per Sector )
1929 ; fatSpace = malloc( Bytes Per Sector * Sectors Per Fat )
1930 ; Calculate start sector (first sector not used by DOS)
1931 ; fBigFat = (((Total Sectors - StartSector)/Sectors Per Cluster) >= 4086)
1933 Phase1Initialisation proc
near
1935 ; Get device parameters
1936 lea dx, deviceParameters
1937 mov deviceParameters
.DP_SpecialFunctions
, 0
1938 call GetDeviceParameters
1939 jnc GotDeviceParameters
1940 Message msgFormatNotSupported
; ;AC000;
1941 ;lea dx, ptr_msgFormatNotSupported
1944 GotDeviceParameters:
1946 ; Save the device parameters for when we exit
1947 lea si, deviceParameters
1948 lea di, savedDeviceParameters
1949 mov cx, size a_DeviceParameters
1954 ; Ensure that there is a valid number of sectors in the track table
1955 mov savedDeviceParameters
.DP_TrackTableEntries
, 0
1956 mov validSavedDeviceParameters
, 1
1958 ; Initialise this to zero to know if CheckSwitches defined the track layout
1959 mov deviceParameters
.DP_TrackTableEntries
, 0
1961 call Set_BPB_Info
;an000; dms; Check to see if we are on
1962 ; FAT system. If not set BPB to proper
1963 ; values for format.
1966 ; Check switches against parameters and use switches to modify device parameters
1972 test SwitchMap
,Switch_Z
;an000; dms;1 sector/cluster disk?
1973 ; $if nz ;an000; dms;yes
1975 mov DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
,01h ;an000; dms;set BPB accordingly
1976 call Calc_Small_Fat
;an000; dms;calc FAT size
1977 ; $endif ;an000; dms;
1983 cmp deviceParameters
.DP_TrackTableEntries
, 0
1984 jne TrackLayoutSet
; There is a good track layout
1986 ; Store sector table info
1987 mov cx, deviceParameters
.DP_BPB
.BPB_SectorsPerTrack
1988 mov deviceParameters
.DP_TrackTableEntries
, cx
1990 mov bx, deviceParameters
.DP_BPB
.BPB_bytesPerSector
1991 lea di, deviceParameters
.DP_SectorTable
1998 loop LoadSectorTable
2002 ; directorySector = malloc( Bytes Per Sector )
2004 mov bx, deviceParameters
.DP_BPB
.BPB_BytesPerSector
2013 mov word ptr directorySector
+2, ax
2015 mov word ptr directorySector
, ax
2018 ; fatSpace = malloc( Bytes Per Sector * Sectors Per FAT )
2020 mov ax, deviceParameters
.DP_BPB
.BPB_BytesPerSector
2026 mul deviceParameters
.DP_BPB
.BPB_SectorsPerFAT
2027 mov Paras_Per_Fat
,ax ;AN005;128k FAT
2032 mov word ptr fatSpace
+2,ax
2034 mov word ptr fatSpace
,ax
2042 Phase1Initialisation endp
2044 ;-------------------------------------------------------------------------------
2046 SetStartSector proc
near
2048 ; startSector = number of reserved sectors
2049 ; + number of FAT Sectors ( Number of FATS * Sectors Per FAT )
2050 ; + number of directory sectors ( 32* Root Entries / bytes Per Sector )
2051 ; ( above is rounded up )
2053 ; Calculate the number of directory sectors
2054 mov ax, deviceParameters
.DP_BPB
.BPB_RootEntries
2055 mov bx, size dir_entry
2057 add ax, deviceParameters
.DP_BPB
.BPB_bytesPerSector
2060 div deviceParameters
.DP_BPB
.BPB_bytesPerSector
2061 mov sectorsInRootDirectory
,ax
2064 ; Calculate the number of FAT sectors
2065 mov ax, deviceParameters
.DP_BPB
.BPB_SectorsPerFAT
2066 mul deviceParameters
.DP_BPB
.BPB_numberOfFATs
2067 ; Add in the number of boot sectors
2068 add ax, deviceParameters
.DP_BPB
.BPB_ReservedSectors
2075 ;-------------------------------------------------------------------------------
2077 SetfBigFat proc
near
2079 ; fBigFat = ( ( (Total Sectors - Start Sector) / Sectors Per Cluster) >= 4086 )
2081 cmp deviceParameters
.DP_BPB
.BPB_BigTotalSectors
+2,0 ; > 32mb part? ;AN000;
2082 ; $IF NE ;Yes, big FAT ;AC000;
2084 mov fBigFat
, TRUE
;Set flag ;AN000;
2085 ; $ELSE ;Nope, < 32,b ;AC000;
2088 mov ax,deviceParameters
.DP_BPB
.BPB_BigTotalSectors
;Assume this used ;AN000;
2089 cmp ax,0 ;Was this field used? ;AN000;
2090 ; $IF E ;Nope, use the other sector field;AN000;
2092 mov ax, deviceParameters
.DP_BPB
.BPB_TotalSectors
; ;AC000;
2093 ;** Fix for PTM PCDOS P51
2096 sub ax,startSector
;Get sectors in data area
2099 mov bl,deviceParameters
.DP_BPB
.BPB_sectorsPerCluster
2100 div bx ;Get total clusters
2101 cmp ax,BIG_FAT_THRESHOLD
;Is clusters >= 4086?
2104 mov fBigFAT
,TRUE
;16 bit FAT if >=4096
2105 ;** END fix for PTM PCDOS P51
2114 ;-------------------------------------------------------------------------------
2116 ; Phase2Initialisation:
2117 ; Use device parameters to build information that will be
2118 ; required for each format
2121 ; Calculate first head/cylinder to format
2122 ; Calculate number of tracks to format
2123 ; Calculate the total bytes on the disk and save for later printout
2124 ; First initialise the directory buffer
2126 Phase2Initialisation proc
near
2128 ; Calculate first track/head to format (round up - kludge)
2129 mov ax, deviceParameters
.DP_BPB
.BPB_HiddenSectors
2130 mov dx, deviceParameters
.DP_BPB
.BPB_HiddenSectors
+ 2
2131 add ax, deviceParameters
.DP_BPB
.BPB_SectorsPerTrack
2135 div deviceParameters
.DP_BPB
.BPB_SectorsPerTrack
2137 div deviceParameters
.DP_BPB
.BPB_Heads
2138 mov firstCylinder
, ax
2141 ; Calculate the total number of tracks to be formatted (round down - kludge)
2142 mov ax, deviceParameters
.DP_BPB
.BPB_TotalSectors
2144 ; if (TotalSectors == 0) then use BigTotalSectors
2146 jnz NotBigTotalSectors
2147 mov ax, deviceParameters
.DP_BPB
.BPB_BigTotalSectors
2148 mov dx, deviceParameters
.DP_BPB
.BPB_BigTotalSectors
+ 2
2151 div deviceParameters
.DP_BPB
.BPB_SectorsPerTrack
2152 mov tracksPerDisk
, ax
2154 ; Initialise the directory buffer
2155 ; Clear out the Directory Sector before any information is inserted.
2156 mov cx, deviceParameters
.DP_BPB
.BPB_BytesPerSector
2157 les di, directorySector
2161 mov ax, deviceParameters
.DP_BPB
.BPB_BytesPerSector
2163 mov bx, size dir_entry
2167 les bx, directorySector
2168 ; If Old_Dir = TRUE then put the first letter of each directory entry must be 0E5H
2175 add bx, size dir_entry
2180 Phase2Initialisation endp
2182 ;-------------------------------------------------------------------------------
2184 ; SetDeviceParameters:
2185 ; Set the device parameters
2189 ; dx - pointer to device parameters
2191 SetDeviceParameters proc
near
2193 mov ax, (IOCTL
shl 8) or GENERIC_IOCTL
2196 mov cx, (RAWIO
shl 8) or SET_DEVICE_PARAMETERS
2200 SetDeviceParameters endp
2202 ;-------------------------------------------------------------------------------
2204 ; GetDeviceParameters:
2205 ; Get the device parameters
2209 ; dx - pointer to device parameters
2211 GetDeviceParameters proc
near
2213 mov ax, (IOCTL
shl 8) or GENERIC_IOCTL
2216 mov cx, (RAWIO
shl 8) or GET_DEVICE_PARAMETERS
2220 GetDeviceParameters endp
2222 ;-------------------------------------------------------------------------------
2225 ; Format the tracks on the disk
2226 ; Since we do our SetDeviceParameters here, we also need to
2227 ; detect the legality of /N /T if present and abort with errors
2229 ; This routine stops as soon as it encounters a bad track
2230 ; Then BadSector is called to report the bad track, and it continues
2234 ; Initialise in memory FAT
2235 ; current track = first
2237 ; if format track fails
2238 ; DiskFormatErrors = true
2242 DiskFormat proc
near
2246 ; Initialise fatSpace
2252 call Fat_Init
;an000; initialize the FAT
2254 mov di, word ptr fatspace
+2 ;an000; get segment of FAT
2255 mov es, di ;an000; place it in es
2256 mov di, word ptr fatSpace
;Should be 0
2257 mov al, deviceParameters
.DP_BPB
.BPB_MediaDescriptor
2267 ; don't bother to do the formatting if /c was given
2268 test switchmap
, SWITCH_C
2270 jmp FormatDone
;FormatDone is to far away
2273 foofoo
= INSTALL_FAKE_BPB
or TRACKLAYOUT_IS_GOOD
2274 mov deviceParameters
.DP_SpecialFunctions
, foofoo
2275 lea dx, deviceParameters
2277 call SetDeviceParameters
2279 call Cluster_Buffer_Allocate
;an000; dms;get room for retry buffer
2281 call Prompt_User_For_Disk
;an016; dms;
2283 test switchmap
,switch_8
; DCL 5/12/86 avoid Naples AH=18h
2284 jnz stdBpB
; lackof support for 8 sectors/track
2287 ; Always do the STATUS_FOR_FORMAT test, as we don't know if the machine
2288 ; has this support. For 3.2 /N: & /T: were not documented & therefore
2289 ; not fully supported thru the ROM of Aquarius & Naples & Royal Palm
2291 ;test SwitchMap, SWITCH_N or SWITCH_T ; IF ( /N or /T ) ;; DCL 5/12/86
2295 mov formatPacket
.FP_SpecialFunctions
, STATUS_FOR_FORMAT
2296 mov ax, (IOCTL
shl 8) or GENERIC_IOCTL
2299 mov cx, (RAWIO
shl 8) or FORMAT_TRACK
2300 lea dx, formatPacket
2302 ; switch ( FormatStatusCall)
2304 ;cmp FormatPacket.FP_SpecialFunctions, Format_No_ROM_Support
2305 ;jb NTSupported ; 0 returned from IBMBIO
2306 ;ja IllegalComb ; 2 returned - ROM Support
2307 ; Illegal Combination!
2308 cmp FormatPacket
.FP_SpecialFunctions
,0
2310 cmp FormatPacket
.FP_SpecialFunctions
,2
2313 Message msgInvalidParameter
; ;AC000;
2314 mov Fatal_Error
,Yes
;Indicate quittin'type err! ;AN000;
2318 cmp FormatPacket
.FP_SpecialFunctions
,3 ; ; ;
2321 mov ax,Error_Not_Ready
;flag not ready ;an000;dms;
2322 call CheckError
; set error level ;an017; dms;
2323 jmp FrmtProb
; exit program ;an017; dms;
2324 ; $ELSE ; DCL No ROM support is okay ; ;
2327 ; except for /N: & /T: ; ;
2328 test SwitchMap
, SWITCH_N
or SWITCH_T
; DCL 5/12/86 ; ;
2331 Message msgParametersNotSupported
; ;AC000;
2332 mov Fatal_Error
,Yes
;Indicate quittin'type err! ;AN000;
2339 cmp Fatal_Error
,Yes
; ;AN000;
2340 jne StdBPB
; ;AN000;
2343 ; We have the support to carry out the FORMAT
2347 ;call DSKPRM ; prompt user for disk ;; DCL 5/12/86
2348 mov FormatPacket
.FP_SpecialFunctions
, 0
2350 mov formatPacket
.FP_Head
, ax
2351 mov ax, firstCylinder
2352 mov formatPacket
.FP_Cylinder
, ax
2353 mov cx, tracksPerDisk
2355 mov Format_End
,False
;an015; dms;flag not at end of format
2356 call Calc_Max_Tracks_To_Format
;an015; dms;max track count for FormatTrack call
2358 call Format_Loop
;an015; dms;Format until CY occurs
2360 cmp Format_End
,True
;an015; dms;End of Format?
2361 ; $if e ;an015; dms;yes
2363 mov FormatError
,0 ;an015; dms;signal good format
2364 clc ;an015; dms;clear CY
2365 ; $else ;an015; dms;bad format
2368 call CheckError
;an015; dms;determine type of error
2369 ; $if nc ;an015; dms;
2371 call LastChanceToSaveIt
;an015; dms;acceptable error?
2372 ; $if c ;an015; dms;yes
2374 mov FormatError
,1 ;an015; dms;signal error type
2375 clc ;an015; dms;clear CY
2376 ; $else ;an015; dms;not acceptable error
2379 call SetStartSector
;an015; dms;start from scratch
2380 call SetFBigFat
;an015; dms;
2381 push ax ;an015; dms;
2382 call Phase2Initialisation
;an015; dms;
2385 jmp DiskFormat
;an015; dms;try again
2386 ; $endif ;an015; dms;
2388 ; $endif ;an015; dms;
2390 ; $endif ;an015; dms;
2402 ;-------------------------------------------------------------------------------
2405 ; Reports the bad sectors.
2406 ; Reports the track where DiskFormat stopped.
2407 ; From then on it formats until it reaches a bad track, or end,
2411 ; Carry: set --> fatal error
2413 ; ax - The number of consecutive bad sectors encountered
2414 ; ax == 0 --> no more bad sectors
2415 ; bx - The logical sector number of the first bad sector
2418 ; if DiskFormatErrors
2419 ; DiskFormatErrors = false
2420 ; return current track
2424 ; if format track fails
2425 ; return current track
2432 ; don't bother to do the formatting if /c was given
2433 test switchmap
, SWITCH_C
2436 test formatError
, 0ffH
2442 call Adj_Track_Count
;an015; dms;decrease track counter
2443 call NextTrack
;an015; dms;adjust head and cylinder
2444 cmp Format_End
,True
;an015; dms;end of format?
2445 ; $if ne ;an015; dms;no
2447 call Format_Loop
;an015; dms;format until CY
2448 cmp Format_End
,True
;an015; dms;end of format?
2449 ; $if ne ;an015; dms;no
2451 call CheckError
;an015; dms;must be error - which error?
2452 ; $if nc ;an015; dms;non-fatal error?
2454 call CurrentLogicalSector
;an015; dms;yes - get position
2455 mov ax,DeviceParameters
.DP_BPB
.BPB_SectorsPerTrack
;an015; dms; set track size
2456 clc ;an015; dms;signal O.K. to continue
2457 ; $endif ;an015; dms;
2459 ; $else ;an015; dms;
2462 jmp NoMoreTracks
;an015; dms;end of format
2463 ; $endif ;an015; dms;
2465 ; $else ;an015; dms;
2468 jmp NoMoreTracks
;an015; dms;end of format
2469 ; $endif ;an015; dms;
2474 call CurrentLogicalSector
2475 mov ax, deviceParameters
.DP_BPB
.BPB_SectorsPerTrack
2480 test SwitchMap
,(Switch_Select
or SWITCH_AUTOTEST
) ;Don't display done msg;AN000;
2481 ; $IF Z ; if EXEC'd by SELECT ;AN000;
2483 Message msgFormatComplete
; ;AC000;
2494 ;-------------------------------------------------------------------------------
2496 data segment public para
'DATA'
2498 ;ptr_msgCurrentTrack dw offset msgCurrentTrack
2500 currentCylinder dw 0
2504 ;=========================================================================
2505 ; Calc_Current_Head_Cyl : Obtain the current head and cylinder of the
2506 ; track being formatted.
2508 ; Inputs: FP_Cylinder - Cylinder of track being formatted
2509 ; FP_Head - Head of track being formatted
2510 ;=========================================================================
2512 Procedure Calc_Current_Head_Cyl
;an000; dms;
2514 push cx ;an000; dms;save cx
2515 mov cx,FormatPacket
.FP_Cylinder
;an000; dms;get current cylinder
2516 mov CurrentCylinder
,cx ;an000; dms;put into variable
2517 mov cx,FormatPacket
.FP_Head
;an000; dms;get current head
2518 mov CurrentHead
,cx ;an000; dms;put into variable
2519 pop cx ;an000; dms;restore cx
2522 Calc_Current_Head_Cyl endp
;an000; dms;
2525 DisplayCurrentTrack proc
near
2529 push ax ;an015; dms;
2531 mov ax,Tracks_To_Format
;an015; dms;get track count
2533 add Formatted_Tracks_Low
,ax ;Indicate formatted a track ;AN000;
2534 adc Formatted_Tracks_High
,0 ; ;AN000;
2535 mov ax,Formatted_Tracks_Low
; ;AN000;
2536 mov bx,Formatted_Tracks_High
; ;AN000;
2537 mov cx,100 ;Make integer calc for div ;AN000;
2538 call Multiply_32_Bits
; BX:AX = (Cyl * Head *100) ;AN000;
2539 mov dx,bx ;Set up divide ;AN000;
2540 div TracksPerDisk
;% = (Cyl * Head *100)/ # tracks;AN000;
2541 cmp ax,PercentComplete
;Only print message when change ;AN000;
2542 ; $IF NE ;To avoid excess cursor splat ;AN000;
2544 mov PercentComplete
,ax ;Save it if changed ;AN000;
2545 Message msgCurrentTrack
; ;AC000;
2549 pop cx ;Restore register ;AN000;
2553 DisplayCurrentTrack endp
2556 ;-------------------------------------------------------------------------------
2559 ; ax - extended error code
2561 ; carry set if error is fatal
2562 ; Message printed if Not Ready or Write Protect
2564 CheckError proc
near
2565 cmp ax, error_write_protect
2566 je WriteProtectError
2567 cmp ax, error_not_ready
2569 cmp currentCylinder
, 0
2577 cmp ax, error_sector_not_found
2579 cmp ax, error_write_fault
2581 cmp ax, error_read_fault
2583 cmp ax, error_gen_failure
2595 test SwitchMap
,Switch_SELECT
;an017; dms;SELECT option?
2596 ; $if z ;an017; dms;no - display messages
2598 Message msgCRLF
; ;AC006;
2599 Message msgCRLF
; ;AC006;
2600 Extended_Message
; ;AC006;
2601 ; $else ;an017; dms;yes - set error level
2604 mov ExitStatus
,ExitWriteProtect
;an017; dms;signal write protect error
2605 ; $endif ;an017; dms;
2608 stc ;an017; dms;signal fatal error
2609 ret ;an017; dms;return to caller
2612 test SwitchMap
,Switch_SELECT
;an017; dms; SELECT option?
2613 ; $if z ;an017; dms; no - display messages
2615 Message msgCRLF
; ;AC006;
2616 Message msgCRLF
; ;AC006;
2617 Extended_Message
; ;AC006;
2618 ; $else ;an017; dms;yes - set error level
2621 mov ExitStatus
,ExitDriveNotReady
;an017; dms;signal drive not ready
2622 ; $endif ;an017; dms;
2629 Message msgDiskUnusable
; ;AC000;
2635 ;-------------------------------------------------------------------------------
2637 ; Write the boot sector and FATs out to disk
2638 ; Clear the directory sectors to zero
2641 WriteFileSystem proc
near
2644 call WriteBootSector
2647 Set_Data_Segment
;Set DS,ES = DATA ;AN000;
2648 ; Write out each of the FATs
2649 push ds ;ac005; dms;save ds
2651 mov cl, es:deviceParameters
.DP_BPB
.BPB_numberOfFATs
; ;AC000;
2652 mov dx, es:deviceParameters
.DP_BPB
.BPB_ReservedSectors
; ;AC000;
2653 mov al, es:drive
; ;AC000;
2654 mov bx,word ptr es:FatSpace
+2 ;Get segment of memory Fat ;AC000;
2656 mov bx,word ptr es:FatSpace
; ;AN000;
2658 mov si,bx ;ac005; dms;set up for add. calc
2659 call SEG_ADJ
;ac005; dms;get adjusted seg:off
2660 mov bx,si ;ac005; dms;get new off
2661 assume
ds:nothing
,es:data ; ;AN000;
2663 ; $do ;ac005; dms;while FATS > 0
2665 cmp cx,00 ;ac005; dms;FATS remaining?
2666 ; $leave e ;ac005; dms;no
2668 push bx ;ac005; dms;save FAT offset
2669 push ds ;ac005; dms;save FAT segment
2670 push cx ;ac005; dms;save FAT count
2671 push dx ;ac005; dms;reserved FAT sector
2672 call WRITE_FAT
;ac005; dms;write the FAT
2673 pop dx ;ac005; dms;get 1st. FAT sector
2674 pop cx ;ac005; dms;get FAT count
2675 pop ds ;ac005; dms;restore FAT segment
2676 pop bx ;ac005; dms;restore FAT offset
2677 ; $if c ;ac005; dms;an error occurred
2679 Message msgFATwriteError
;ac005; dms;say why failed
2680 jmp FEXIT
;ac005; dms;exit format
2681 ; $endif ;ac005; dms;
2683 add dx, es:deviceParameters
.DP_BPB
.BPB_SectorsPerFAT
; ;AC000;
2684 dec cx ;ac005; dms;decrease FAT count
2685 ; $enddo ;ac005; dms;
2689 pop ds ;ac005; dms;restore ds
2690 assume
ds:data ;ac005; dms;
2693 ; Clear the directory
2695 ; Now write the initialised directory sectors out to disk
2696 mov ax, es:deviceParameters
.DP_BPB
.BPB_SectorsPerFAT
; ;AC000;
2698 push bx ;an000; dms;save bx
2699 xor bx,bx ;an000; dms;clear bx
2700 mov bl,es:DeviceParameters
.DP_BPB
.BPB_NumberOfFATs
;an000; dms;get FAT count
2701 mul bx ;an000; dms;get total FAT sectors
2702 pop bx ;an000; dms;restore bx
2704 mov dx, es:deviceParameters
.DP_BPB
.BPB_ReservedSectors
; ;AC000;
2706 mov cx, es:sectorsInRootDirectory
; ;AC000;
2710 mov al, es:drive
; ;AC000;
2712 lds bx, es:directorySector
; ;AC000;
2714 assume
ds:nothing
,es:data ; ;AN000;
2716 ;Assume dir is alway contined in first 32mb of partition
2718 mov es:Read_Write_Relative
.Start_Sector_High
,0 ; ;AC000;
2719 Call Write_Disk
; ;AN000;
2720 jnc Dir_OK
; ;AC000;
2721 Message msgDirectoryWriteError
; ;AC000;
2729 Set_Data_Segment
;Set DS to DATA segment ;AN000;
2730 ; Ok, we can tell the device driver that we are finished formatting
2731 mov savedDeviceParameters
.DP_TrackTableEntries
, 0
2732 mov savedDeviceParameters
.DP_SpecialFunctions
, TRACKLAYOUT_IS_GOOD
2733 lea dx, savedDeviceParameters
2734 call SetDeviceParameters
2736 MOV AH,DISK_RESET
; Flush any directories in
2742 WriteFileSystem endp
2744 ;=========================================================================
2745 ; WRITE_FAT : This routine writes the logical sector count requested.
2746 ; It will write a maximum of 40h sectors. If more
2747 ; than 40h exists it will continue looping until
2748 ; all sectors have been written.
2750 ; Inputs : AL - Drive letter
2751 ; DS:BX - Segment:offset of transfer address
2755 ; Outputs : Logical sectors written
2756 ;=========================================================================
2760 mov cx, es:deviceParameters
.DP_BPB
.BPB_SectorsPerFAT
; ;AC000;
2762 ; $do ;an000;while sectors left
2764 cmp cx,00h ;an000;any sectors?
2765 ; $leave e ;an000;no
2771 push cx ;an000;save cx
2773 push ax ;an000;save ax
2774 call write_disk
;an000;write it
2775 pop ax ;an000;restore ax
2776 pop cx ;an000;restore cx
2777 jc Write_Exit
;an000;exit if fail
2779 call seg_adj
;an000;adjust segment
2780 mov bx,si ;an000;new offset
2783 ; $else ;an000;< 64k
2786 push ax ;an000;save ax
2787 call write_disk
;an000;write it
2788 pop ax ;an000;restore ax
2789 xor cx,cx ;an000;set cx to 0 - last read
2802 ;=========================================================================
2803 ; SEG_ADJ : This routine adjusts the segment:offset to prevent
2806 ; Inputs : SI - Offset to adjust segment with
2807 ; DS - Segment to be adjusted
2809 ; Outputs : SI - New offset
2810 ; DS - Adjusted segment
2811 ;=========================================================================
2818 mov ax,si ;an000;get offset
2819 mov bx,0010h ;an000;16
2820 xor dx,dx ;an000;clear dx
2821 div bx ;an000;get para count
2822 ; $if c ;an000;overflow?
2824 adc bx,0 ;an000;pick it up
2827 mov bx,ds ;an000;get seg
2828 add bx,ax ;an000;adjust for paras
2829 mov ds,bx ;an000;save new seg
2830 mov si,dx ;an000;new offset
2838 ;-------------------------------------------------------------------------------
2839 ; format is done... so clean up the disk!
2849 ;-------------------------------------------------------------------------------
2850 ; CurrentLogicalSector:
2851 ; Get the current logical sector number
2854 ; current track = tracksPerDisk - tracksLeft
2858 ; BX = logical sector number of the first sector in the track we
2859 ; just tried to format
2861 CurrentLogicalSector proc
near
2863 push ax ;an000; dms;save regs
2864 push bx ;an000; dms;
2865 push dx ;an000; dms;
2867 mov ax, tracksPerDisk
2869 xor dx,dx ;an000; dms;clear dx
2870 mul deviceParameters
.DP_BPB
.BPB_SectorsPerTrack
2871 mov word ptr Relative_Sector_High
,dx ;an000; dms;save high word of sector #
2872 mov word ptr Relative_Sector_Low
,ax ;an000; dms;save low word of sector #
2874 pop dx ;an000; dms;restore regs
2880 CurrentLogicalSector endp
2882 ;-------------------------------------------------------------------------------
2884 ; Print an error message and abort
2887 ; dx - Pointer to error message string
2889 PrintErrorAbort proc
near
2898 PrintErrorAbort endp
2903 ;*****************************************************************************
2904 ;Routine name: Multiply_32_Bits
2905 ;*****************************************************************************
2907 ;Description: A real sleazy 32 bit x 16 bit multiply routine. Works by adding
2908 ; the 32 bit number to itself for each power of 2 contained in the
2909 ; 16 bit number. Whenever a bit that is set in the multiplier (CX)
2910 ; gets shifted to the bit 0 spot, it means that that amount has
2911 ; been multiplied so far, and it should be added into the total
2912 ; value. Take the example CX = 12 (1100). Using the associative
2913 ; rule, this is the same as CX = 8+4 (1000 + 0100). The
2914 ; multiply is done on this principle - whenever a bit that is set
2915 ; is shifted down to the bit 0 location, the value in BX:AX is
2916 ; added to the running total in DI:SI. The multiply is continued
2917 ; until CX = 0. The routine will exit with CY set if overflow
2921 ;Called Procedures: None
2923 ;Change History: Created 7/23/87 MT
2925 ;Input: BX:AX = 32 bit number to be multiplied
2926 ; CX = 16 bit number to be multiplied. (Must be even number)
2928 ;Output: BX:AX = output.
2929 ; CY set if overflow
2934 ; Point at ControlC_Handler routine
2935 ; Set interrupt handler (INT 21h, AX=2523h)
2937 ;*****************************************************************************
2939 Public Multiply_32_Bits
2940 Multiply_32_Bits proc
; ;AN000;
2944 xor di,di ;Init result to zero
2946 cmp cx,0 ;Multiply by 0? ;AN000;
2947 ; $IF NE ;Keep going if not ;AN000;
2949 ; $DO ;This works by adding the result;AN000;
2951 test cx,1 ;Need to add in sum of this bit?;AN000;
2952 ; $IF NZ ;Yes ;AN000;
2954 add si,ax ;Add in the total so far for ;AN000;
2955 adc di,bx ; this bit multiplier (CY oflow);AN000;
2956 ; $ELSE ;Don't split multiplier ;AN000;
2959 clc ;Force non exit ;AN000;
2962 ; $LEAVE C ;Leave on overflow ;AN000;
2964 shr cx,1 ;See if need to multiply value ;AN000;
2965 cmp cx,0 ;by 2 ;AN000;
2966 ; $LEAVE E ;Done if cx shifted down to zero;AN000;
2968 add ax,ax ;Each time cx is shifted, add ;AN000;
2969 adc bx,bx ;value to itself (Multiply * 2) ;AN000;
2970 ; $ENDDO C ;CY set on overflow ;AN000;
2973 ; $IF NC ;If no overflow, add in DI:SI ;AN000;
2975 mov ax,si ; which contains the original ;AN000;
2976 mov bx,di ; value if odd, 0 if even. This ;AN000;
2977 clc ;Set no overflow flag ;AN000;
2985 ; $ENDIF ;Multiply by 0 ;AN000;
2991 Multiply_32_Bits endp
2994 ;=========================================================================
2995 ; Divide_32_Bits - This routine will perform 32bit division
2997 ; Inputs : SI:DI - value to be divided
3000 ; Outputs : SI:DI - result
3002 ;=========================================================================
3004 Procedure Divide_32_Bits
;an000; dms;
3006 push ax ;an000; dms;save regs
3007 push bx ;an000; dms;
3008 push dx ;an000; dms;
3010 xor dx,dx ;an000; dms;clear dx
3011 mov ax,si ;an000; dms;get high word
3012 div cx ;an000; dms;get high word result
3013 mov si,ax ;an000; dms;save high word result
3015 mov ax,di ;an000; dms;get low word
3016 div cx ;an000; dms;get low word result
3017 mov di,ax ;an000; dms;save low word result
3018 mov cx,dx ;an000; dms;pick up remainder
3020 pop dx ;an000; dms;restore regs
3026 Divide_32_Bits endp
;an000; dms;
3031 ;=========================================================================
3032 ; FAT_INIT: This routine initializes the FAT based on the
3033 ; number of paragraphs.
3040 ; output - fat space is initialized
3042 ;=========================================================================
3051 mov di, word ptr FatSpace
+2 ;Get segment of Fat space ;AC000;
3053 mov di, word ptr FatSpace
; ;AN000;
3054 mov bx,Paras_Per_Fat
;an000;get number of paras
3055 mov ax,fat_init_value
;an000;
3056 push dx ;an000;save bx
3057 mov dx,es ;an000;grab es into dx
3060 cmp bx,0 ;an000;do while bx not = 0
3061 ; $leave e ;an000;exit if 0
3063 mov cx,10h
;an000;word move of paragraph
3064 rep stosb ;an000;move the data to FAT
3065 xor di,di ;an000;offset always init to 0
3066 inc dx ;an000;next paragraph
3067 mov es,dx ;an000;put next para in es
3068 dec bx ;an000;loop iteration counter
3081 Fat_Init endp
;an000;
3084 ;=========================================================================
3085 ; Ctrl_Break_Write : This routine takes the control break request
3086 ; an returns. In essence, it disables the CTRL-BREAK.
3087 ; This routine is used during the writing of the
3088 ; FAT, DIR, and SYSTEM.
3089 ;=========================================================================
3091 Ctrl_Break_Write: ;ac010; dms;
3093 iret ;ac010; dms;return to caller
3096 ;=========================================================================
3097 ; Ctrl_Break_Save : This routine gets the current vector of
3098 ; INT 23h and saves it in CTRL_BREAK_VECTOR.
3102 ; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine
3103 ;=========================================================================
3105 Ctrl_Break_Save proc
near ;ac010; dms;
3107 push es ;ac010; dms;save es
3108 push bx ;ac010; dms;save bx
3109 push ax ;ac010; dms;save ax
3111 mov ax,3523h
;ac010; dms;get CTRL-BREAK
3113 int 21h
;ac010; dms;
3115 mov word ptr Ctrl_Break_Vector
,bx ;ac010; dms;get vector offset
3116 mov word ptr Ctrl_Break_Vector
+2,es ;ac010; dms;get vector segment
3118 pop ax ;ac010; dms;restore ax
3119 pop bx ;ac010; dms;restore bx
3120 pop es ;ac010; dms;restore es
3125 Ctrl_Break_Save endp
;ac010; dms;
3128 ;=========================================================================
3129 ; Set_Ctrl_Break : This routine sets the CTRL-Break vector to one
3130 ; defined by the user.
3134 ; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine
3135 ;=========================================================================
3137 Set_Ctrl_Break proc
near ;ac010; dms;
3139 push ds ;ac010; dms;save ds
3140 push ax ;ac010; dms;save ax
3141 push bx ;ac010; dms;save bx
3142 push dx ;ac010; dms;save dx
3144 push cs ;ac010; dms;swap cs with ds
3145 pop ds ;an000; dms;point to code seg
3147 mov dx,offset Ctrl_Break_Write
;ac010; dms;get interrupt vec.
3148 mov ax,2523h
;ac010; dms;set CTRL-BREAK
3150 int 21h
;ac010; dms;
3152 pop dx ;ac010; dms;restore dx
3153 pop bx ;ac010; dms;restore bx
3154 pop ax ;ac010; dms;restore ax
3155 pop ds ;ac010; dms;restore ds
3160 Set_Ctrl_Break endp
;ac010; dms;
3163 ;=========================================================================
3164 ; Reset_Ctrl_Break : This routine resets the CTRL-Break vector to that
3165 ; originally defined.
3167 ; Inputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine
3170 ;=========================================================================
3172 Reset_Ctrl_Break proc
near ;ac010; dms;
3174 push ds ;ac010; dms;save ds
3175 push ax ;ac010; dms;save ax
3176 push bx ;ac010; dms;save bx
3177 push dx ;ac010; dms;save ds
3179 mov ax,word ptr Ctrl_Break_Vector
+2 ;ac010; dms;get seg. of vector
3180 mov bx,word ptr Ctrl_Break_Vector
;ac010; dms;get off. of vector
3181 mov ds,ax ;ac010; dms;get seg.
3182 mov dx,bx ;ac010; dms;get off.
3183 mov ax,2523h
;ac010; dms;set CTRL-BREAK
3185 int 21h
;ac010; dms;
3187 pop dx ;ac010; dms;restore dx
3188 pop bx ;ac010; dms;restore bx
3189 pop ax ;ac010; dms;restore ax
3190 pop ds ;ac010; dms;restore ds
3195 Reset_Ctrl_Break endp
;ac010; dms;
3197 ;=========================================================================
3198 ; Get_Command_Path : This routine finds the path where
3199 ; COMMAND.COM resides based on the
3200 ; environmental vector. Once the
3201 ; path is found it is copied to
3204 ; Inputs : Exec_Block.Segment_Env - Segment of environmental vector
3205 ; Comspec_ID - "COMSPEC="
3207 ; Outputs : CommandFile - Holds path to COMMAND.COM
3208 ;=========================================================================
3210 Procedure Get_Command_Path
;an011; dms;
3212 push ds ;an011; dms;save ds
3213 push es ;an011; dms;save es
3215 Set_Data_Segment
;an011; dms; DS,ES = Data
3216 call Get_PSP_Parms
;an011; dms; gets PSP info.
3217 cld ;an011; dms; clear direction
3218 mov ax,es:Environ_Segment
;an011; dms; get seg. of
3220 mov ds,ax ;an011; dms; put it in DS
3221 assume
ds:nothing
;an011; dms;
3222 xor si,si ;an011; dms; clear si
3223 mov bx,si ;an011; dms; save si
3224 mov di,offset Comspec_ID
;an011; dms; point to target
3225 mov cx,127 ;an011; dms; loop 127 times
3226 ; $do ;an011; dms; while cx not 0
3228 ; and target not found
3229 cmp cx,00h ;an011; dms; end of env.?
3230 ; $leave e ;an011; dms; yes
3233 push cx ;an011; dms; save cx
3234 mov cx,0008h ;an011; dms; loop 8 times
3235 repe cmpsb ;an011; dms; "COMSPEC=" ?
3236 pop cx ;an011; dms; restore cx
3237 ; $if z ;an011; dms; yes
3239 push di ;an011; dms; save di
3240 mov di,offset
es:CommandFile
;an011; dms
3241 lodsb ;an011; dms; priming read
3242 mov dl,al ;an011; dms; prepare for capitalization
3243 call Cap_Char
;an011; dms; capitalize character in DL
3244 cmp dl,es:CommandFile
;an011; dms;COMSPEC same as default drive?
3245 ; $if e ;an000; dms; yes
3247 ; $do ;an011; dms; while AL not = 0
3249 cmp al,00h ;an011; dms; at end?
3250 ; $leave e ;an011; dms; yes
3252 stosb ;an011; dms; save it
3253 lodsb ;an011; dms; get character
3257 ; $endif ;an011; dms;
3259 pop di ;an011; dms; restore di
3260 mov cx,0ffffh ;an011; dms; flag target found
3261 ; $endif ;an011; dms;
3264 cmp cx,0ffffh ;an011; dms; target found?
3265 ; $leave e ;an011; dms; yes
3268 mov di,offset Comspec_ID
;an011; dms; point to target
3269 mov si,bx ;an011; dms; restore si
3270 inc si ;an011; dms; point to next byte
3271 mov bx,si ;an011; dms; save si
3273 dec cx ;an011; dms; decrease counter
3274 ; $enddo ;an011; dms;
3278 pop es ;an011; dms; restore es
3279 pop ds ;an011; dms; restore ds
3283 Get_Command_Path endp
;an011; dms;
3287 ;****************************************************************************
3289 ;****************************************************************************
3295 Procedure Get_PSP_Parms
; ;AC000;
3298 mov ax,PSP_Segment
;Get segment of PSP ;AN000;
3299 mov ds,ax ; " " " " ;AN000;
3302 ;Setup segment of Environment string, get from PSP ; ;
3304 mov ax,ds:PSP_Environ
; ; ;
3305 mov es:Environ_Segment
,ax ; ; ;
3310 Get_PSP_Parms endp
; ;AN000;
3313 ;=========================================================================
3314 ; Command_Root : This routine sets up CommandFile so that the
3315 ; COMMAND.COM will be written to the root.
3316 ; It does this by copying at offset 3 of CommandFile
3317 ; the literal COMMAND.COM. This effectively
3318 ; overrides the original path, but maintains the
3319 ; drive letter that is to be written to.
3321 ; Inputs : CommandFile - Holds full path to default COMMAND.COM
3322 ; Outputs : CommandFile - Holds modified path to new COMMAND.COM
3324 ;=========================================================================
3326 Procedure Command_Root
;an011; dms;
3328 push ds ;an011; dms; save ds
3329 push es ;an011; dms; save es
3330 push di ;an011; dms; save di
3331 push si ;an011; dms; save si
3332 push cx ;an011; dms; save cx
3333 Set_Data_Segment
;an011;
3335 mov di,offset CommandFile
+3 ;an011; dms; point to path
3337 mov si,offset Command_Com
;an011; dms; holds the literal
3339 mov cx,000ch ;an011; dms; len. of literal
3340 rep movsb ;an011; dms; move it
3342 pop cx ;an011; dms; restore cx
3343 pop si ;an011; dms; restore si
3344 pop di ;an011; dms; restore di
3345 pop es ;an011; dms; restore es
3346 pop ds ;an011; dms; restore ds
3350 Command_Root endp
;an011; dms;
3353 ;=========================================================================
3354 ; Set_BPB_Info : When we have a FAT count of 0, we must calculate
3355 ; certain parts of the BPB. The following code
3356 ; will do just that.
3358 ; Inputs : DeviceParameters
3360 ; Outputs : BPB information
3361 ;=========================================================================
3363 Procedure Set_BPB_Info
;an012; dms;calc new BPB
3365 Set_Data_Segment
;an012; dms;set up addressibility
3366 cmp DeviceParameters
.DP_BPB
.BPB_NumberOfFats
,00h ;an012; dms;see if we have 0 FATS specified
3367 ; $if e ;an012; dms;yes, 0 FATS specified
3369 call Scan_Disk_Table
;an012; dms;access disk table
3370 mov bl,byte ptr ds:[si+8] ;an012; dms;get FAT type
3371 mov cx,word ptr ds:[si+4] ;an012; dms;get sectors/cluster
3372 mov dx,word ptr ds:[si+6] ;an012; dms;number of entries for the root DIR
3374 mov DeviceParameters
.DP_BPB
.BPB_RootEntries
,dx ;an012; dms;save root entries
3375 mov DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
,ch ;an012; dms;save sectors/cluster
3376 mov DeviceParameters
.DP_BPB
.BPB_BytesPerSector
,0200h ;an012; dms;save bytes/sector
3377 mov DeviceParameters
.DP_BPB
.BPB_ReservedSectors
,0001h ;an012; dms;save reserved sectors
3378 mov DeviceParameters
.DP_BPB
.BPB_NumberOfFats
,02h ;an012; dms;FAT count
3380 cmp bl,FBIG
;an012; dms;Big FAT?
3381 ; $if e ;an012; dms;yes
3383 call Calc_Big_FAT
;an012; dms;calc big FAT info
3384 ; $else ;an012; dms;
3387 call Calc_Small_FAT
;an012; dms;calc small FAT info
3388 ; $endif ;an012; dms;
3390 ; $endif ;an012; dms;
3395 Set_BPB_Info endp
;an012; dms;
3399 ;=========================================================================
3400 ; Scan_Disk_Table : Scans the table containing information on
3401 ; the disk's attributes. When it finds the
3402 ; applicable data, it returns a pointer in
3403 ; DS:SI for reference by the calling proc.
3405 ; Inputs : DiskTable - Contains data about disk types
3407 ; Outputs : DS:SI - Points to applicable disk data
3408 ;=========================================================================
3410 Procedure Scan_Disk_Table
;an012; dms;
3412 cmp DeviceParameters
.DP_BPB
.BPB_TotalSectors
,00h ;an012; dms;small disk?
3413 ; $if ne ;an012; dms;yes
3415 mov dx,00h ;an012; dms;set high to 0
3416 mov ax,word ptr DeviceParameters
.DP_BPB
.BPB_TotalSectors
;an012; dms;get sector count
3417 ; $else ;an012; dms;
3420 mov dx,word ptr DeviceParameters
.DP_BPB
.BPB_BigTotalSectors
[+2] ;an012; dms;get high count
3421 mov ax,word ptr DeviceParameters
.DP_BPB
.BPB_BigTotalSectors
[+0] ;an012; dms;get low count
3422 ; $endif ;an012; dms;
3425 mov si,offset DiskTable
;an012; dms;point to disk data
3428 cmp dx,word ptr ds:[si] ;an012; dms;below?
3429 jb Scan_Disk_Table_Exit
;an012; dms;yes, exit
3430 ja Scan_Next
;an012; dms;no, continue
3431 cmp ax,word ptr ds:[si+2] ;an012; dms;below or equal?
3432 jbe Scan_Disk_Table_Exit
;an012; dms;yes, exit
3436 add si,5*2 ;an012; dms;adjust pointer
3437 jmp Scan
;an012; dms;continue scan
3439 Scan_Disk_Table_Exit:
3443 Scan_Disk_Table endp
;an012; dms;
3447 ;=========================================================================
3448 ; Calc_Big_FAT : Calculates the sectors per FAT for a 16 bit FAT.
3450 ; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or
3451 ; DeviceParameters.DP_BPB.BPB_TotalSectors
3453 ; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat
3454 ;=========================================================================
3456 Procedure Calc_Big_FAT
;an012; dms;
3458 cmp DeviceParameters
.DP_BPB
.BPB_TotalSectors
,00h ;an012; dms;small disk?
3459 ; $if ne ;an012; dms;yes
3461 mov dx,00h ;an012; dms;set high to 0
3462 mov ax,word ptr DeviceParameters
.DP_BPB
.BPB_TotalSectors
;an012; dms;get sector count
3463 ; $else ;an012; dms;
3466 mov dx,word ptr DeviceParameters
.DP_BPB
.BPB_BigTotalSectors
[+2] ;an012; dms;get high count
3467 mov ax,word ptr DeviceParameters
.DP_BPB
.BPB_BigTotalSectors
[+0] ;an012; dms;get low count
3468 ; $endif ;an012; dms;
3471 mov cl,04h ;an012; dms;16 DIR entries per sector
3472 push dx ;an012; dms;save total sectors (high)
3473 mov dx,DeviceParameters
.DP_BPB
.BPB_RootEntries
;an012; dms;get root entry count
3474 shr dx,cl ;an012; dms;divide by 16
3475 sub ax,dx ;an012; dms;
3476 pop dx ;an012; dms;restore dx
3477 sbb dx,0 ;an012; dms;
3478 sub ax,1 ;an012; dms;AX = T - R - D
3479 sbb dx,0 ;an012; dms;
3480 mov bl,02h ;an012; dms;
3481 mov bh,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an012; dms;get sectors per cluster
3482 add ax,bx ;an012; dms;AX = T-R-D+256*SPC+2
3483 adc dx,0 ;an012; dms;
3484 sub ax,1 ;an012; dms;AX = T-R-D+256*SPC+1
3485 sbb dx,0 ;an012; dms;
3486 div bx ;an012; dms; sec/FAT = CEIL((TOTAL-DIR-RES)/
3487 ; (256*SECPERCLUS+2)
3488 mov word ptr DeviceParameters
.DP_BPB
.BPB_SectorsPerFAT
,ax ;an012; dms;Sectors/cluster
3491 Calc_Big_FAT endp
;an012; dms;
3494 ;=========================================================================
3495 ; Calc_Small_FAT: Calculates the sectors per FAT for a 12 bit FAT.
3497 ; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or
3498 ; DeviceParameters.DP_BPB.BPB_TotalSectors
3500 ; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat
3501 ;=========================================================================
3503 Procedure Calc_Small_FAT
;an012; dms;
3505 cmp DeviceParameters
.DP_BPB
.BPB_TotalSectors
,00h ;an012; dms;small disk?
3506 ; $if ne ;an012; dms;yes
3508 mov dx,00h ;an012; dms;set high to 0
3509 mov ax,word ptr DeviceParameters
.DP_BPB
.BPB_TotalSectors
;an012; dms;get sector count
3510 ; $else ;an012; dms;
3513 mov dx,word ptr DeviceParameters
.DP_BPB
.BPB_BigTotalSectors
[+2] ;an012; dms;get high count
3514 mov ax,word ptr DeviceParameters
.DP_BPB
.BPB_BigTotalSectors
[+0] ;an012; dms;get low count
3515 ; $endif ;an012; dms;
3518 xor bx,bx ;an012; dms;clear bx
3519 mov bl,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an012; dms;get sectors/cluster
3521 ; now multiply by 3/2
3522 mov bx,3 ;an012; dms;
3523 mul bx ;an012; dms;div by log 2 of sectors/cluster
3524 mov bx,2 ;an012; dms;
3526 xor dx,dx ;an012; dms;
3528 mov bx,512 ;an012; dms;
3531 ; dx:ax contains number of FAT sectors necessary
3532 mov DeviceParameters
.DP_BPB
.BPB_SectorsPerFAT
,ax ;an012; dms;save sectors/FAT
3535 Calc_Small_FAT endp
;an012; dms;
3537 ;=========================================================================
3538 ; Get_Bad_Sector_Hard : Determine the bad sector.
3540 ; Inputs : Head of failing track
3541 ; Cylinder of failing track
3542 ; Relative_Sector_Low - 1st. sector in track
3543 ; Relative_Sector_High
3545 ; Cluster_Boundary_Adj_Factor - The number of sectors
3546 ; that are to be read
3548 ; Cluster_Boundary_SPT_Count - Used by Calc_Cluster_Boundary
3549 ; to track how many sectors
3551 ; Cluster_Boundary_Flag - True (Use cluster buffer)
3552 ; - False (Use internal buffer)
3553 ; Cluster_Boundary_Buffer_Seg - Segment of buffer
3555 ; Outputs : Marked cluster as bad
3556 ;=========================================================================
3558 Procedure Get_Bad_Sector_Hard
;an000; dms;
3560 push cx ;an000; dms;save cx
3561 mov cx,0001h ;an000; dms;set counter to start at 1
3562 mov Cluster_Boundary_SPT_Count
,00h ;an000; dms;clear sector counter
3563 mov Cluster_Boundary_Adj_Factor
,01h ;an000; dms;default value
3564 ; $do ;an000; dms;while sectors left
3566 cmp cx,DeviceParameters
.DP_BPB
.BPB_SectorsPerTrack
;an000; dms;at end?
3567 ; $leave a ;an000; dms;yes,exit
3569 push cx ;an000; dms;save cx
3571 cmp Cluster_Boundary_Flag
,True
;an000; dms;full buffer there?
3572 ; $if e ;an000; dms;yes
3574 call Calc_Cluster_Boundary
;an000; dms;see if on boundary
3575 mov ax,Cluster_Boundary_Buffer_Seg
3576 mov word ptr RWPacket
.TRWP_TransferAddress
[0],0 ;an000; dms;point to transfer area
3577 mov word ptr RWPacket
.TRWP_TransferAddress
[2],ax ;an000; dms;
3578 ; $else ;an000; dms;default to internal buffer
3581 mov word ptr RWPacket
.TRWP_TransferAddress
[0],offset RW_TRF_Area
;an000; dms;point to transfer area
3582 mov word ptr RWPacket
.TRWP_TransferAddress
[2],DS ;an000; dms;
3583 ; $endif ;an000; dms;
3586 call Verify_Structure_Set_Up
;an019; dms; set up verify vars
3588 mov ax,(IOCTL
shl 8) or GENERIC_IOCTL
;an000; dms;
3589 xor bx,bx ;an000; dms;clear bx
3590 mov bl,drive
;an000; dms;get drive
3591 inc bl ;an000; dms;adjust it
3592 mov cx,(IOC_DC
shl 8) or READ_TRACK
;an000; dms;read track
3593 lea dx,RWPacket
;an000; dms;point to parms
3594 int 21h
;an000; dms;
3596 pop cx ;an000; dms;restore cx
3598 push cx ;an000; dms;save cx
3600 ; $if c ;an000; dms;an error occurred
3602 call Calc_Cluster_Position
;an000; dms;determine which cluster
3603 call BadClus
;an000; dms;mark the cluster as bad
3604 ; $endif ;an000; dms;
3607 pop cx ;an000; dms;restore cx
3609 add cx,Cluster_Boundary_Adj_Factor
;an000; dms;adjust loop counter
3610 mov ax,Cluster_Boundary_Adj_Factor
;an000; dms;get adjustment factor
3611 xor dx,dx ;an000; dms;clear dx
3612 add ax,Relative_Sector_Low
;an000; dms;add in low word
3613 adc dx,Relative_Sector_High
;an000; dms;pick up carry in high word
3614 mov Relative_Sector_Low
,ax ;an000; dms;save low word
3615 mov Relative_Sector_High
,dx ;an000; dms;save high word
3618 ; $enddo ;an000; dms;
3622 pop cx ;an000; dms;restore cx
3626 Get_Bad_Sector_Hard endp
;an000; dms;
3629 ;=========================================================================
3630 ; Verify_Structure_Set_Up : Set up the fields for the Read IOCTL
3631 ; to verify the sectors in a failing
3632 ; track. Also, it displays the
3633 ; message notifying the user of the
3634 ; sectors it is verifying.
3635 ;=========================================================================
3637 Procedure Verify_Structure_Set_Up
;an019; dms;set up verify structure
3639 mov RWPacket
.TRWP_SpecialFunctions
,00h ;an000; dms;reset special functions
3641 mov ax,FormatPacket
.FP_Head
;an000; dms;get current head
3642 mov RWPacket
.TRWP_Head
,ax ;an000; dms;get current head
3644 mov ax,FormatPacket
.FP_Cylinder
;an000; dms;get current cylinder
3645 mov RWPacket
.TRWP_Cylinder
,ax ;an000; dms;get current cylinder
3647 dec cx ;an000; dms;make sector 0 based
3648 mov RWPacket
.TRWP_FirstSector
,cx ;an000; dms;get sector to read
3650 mov ax,Cluster_Boundary_Adj_Factor
;an000; dms;get # of sectors to read
3651 mov RWPacket
.TRWP_SectorsToReadWrite
,ax ;an000; dms;read only # sector(s)
3653 call Calc_Cluster_Position
;an019; dms;determine cluster number
3654 mov word ptr Msg_Allocation_Unit_Val
[+2],dx ;an019; dms;save high word of cluster
3655 mov word ptr Msg_Allocation_Unit_Val
[+0],ax ;an019; dms;save low word of cluster
3660 Verify_Structure_Set_Up endp
;an019; dms;
3663 ;=========================================================================
3664 ; Get_Bad_Sector_Floppy : This routine marks an entire track as bad
3665 ; since it is a floppy disk.
3667 ; Inputs : Relative_Sector_Low - first sector
3669 ; Outputs : FAT marked with bad sectors
3670 ;=========================================================================
3672 Procedure Get_Bad_Sector_Floppy
;an000; dms;
3674 push bx ;an000; dms;save regs
3675 push cx ;an000; dms;
3677 mov cx,DeviceParameters
.DP_BPB
.BPB_SectorsPerTrack
;an000; dms;get sectors/track
3678 ; $do ;an000; dms;while sectors left
3680 cmp cx,00 ;an000; dms;at end
3681 ; $leave e ;an000; dms;yes
3683 push bx ;an000; dms;save bx we destroy it
3684 push cx ;an000; dms;save cx we destroy it
3685 call Calc_Cluster_Position
;an000; dms;get cluster position
3686 call BadClus
;an000; dms;mark it as bad
3687 pop cx ;an000; dms;restore regs
3689 dec cx ;an000; dms;decrease loop counter
3690 inc Relative_Sector_Low
;an000; dms;next sector
3691 ; $enddo ;an000; dms;
3695 pop cx ;an000; dms;restore regs
3700 Get_Bad_Sector_Floppy endp
;an000; dms;
3703 ;=========================================================================
3704 ; Calc_Cluster_Position : This routine calculates which cluster the
3705 ; failing sector falls in.
3707 ; Inputs : Relative_Sector_High - high word of sector position
3708 ; Relative_Sector_Low - low word of sector position
3710 ; Outputs : DX:AX - Cluster position
3711 ;=========================================================================
3712 Procedure Calc_Cluster_Position
;an000; dms;
3714 push cx ;an000; dms;save regs
3715 push di ;an000; dms;
3716 push si ;an000; dms;
3718 xor dx,dx ;an000; dms;clear high word
3719 mov dx,word ptr Relative_Sector_High
;an000; dms;get the high sector word
3720 mov ax,word ptr Relative_Sector_Low
;an000; dms;get the low sector word
3721 sub ax,StartSector
;an000; dms;get relative sector #
3722 sbb dx,0 ;an000; dms;pick up borrow
3724 mov si,dx ;an000; dms;get high word
3725 mov di,ax ;an000; dms;get low word
3726 xor cx,cx ;an000; dms;clear cx
3727 mov cl,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an000; dms;get sectors/cluster
3728 call Divide_32_Bits
;an000; dms;32 bit division
3730 mov dx,si ;an000; dms;get high word of result
3731 mov ax,di ;an000; dms;get low word of result
3732 add ax,2 ;an000; dms;adjust for cluster bias
3733 adc dx,0 ;an000; dms;pick up carry
3735 pop si ;an000; dms;restore regs
3741 Calc_Cluster_Position endp
;an000; dms;
3744 ;=========================================================================
3745 ; Cap_Char : This routine will capitalize the character passed in
3748 ; Inputs : DL - Character to be capitalized
3750 ; Outputs : DL - Capitalized character
3751 ;=========================================================================
3753 Procedure Cap_Char
;an011; dms;
3755 push ax ;an011; dms;save ax
3756 mov ax,6520h
;an011; dms;capitalize character
3757 int 21h
;an011; dms;
3758 pop ax ;an011; dms;restore ax
3761 Cap_Char endp
;an011; dms;
3763 ;=========================================================================
3764 ; Set_Disk_Access_On_Off: This routine will either turn access on or off
3765 ; to a disk depending on the contents of the
3766 ; buffer passed in DX.
3768 ; Inputs : DX - pointer to buffer
3770 ;=========================================================================
3772 Procedure Set_Disk_Access_On_Off
;an014; dms;
3774 push ax ;an014; dms;save regs
3775 push bx ;an014; dms;
3776 push cx ;an014; dms;
3777 push dx ;an014; dms;
3779 xor bx,bx ;an014; dms;clear bx
3780 mov bl,Drive
;an014; dms;get driver number
3781 inc bl ;an014; dms;make it 1 based
3782 call IsRemovable
;an014; dms;see if removable media
3783 ; $if c ;an014; dms;not removable
3785 mov ax,(IOCTL
shl 8) or Generic_IOCTL
;an014; dms;generic ioctl
3786 xor bx,bx ;an014; dms;clear bx
3787 mov bl,Drive
;an014; dms;get drive letter
3788 inc bl ;an014; dms;make it 1 based
3789 mov cx,(RAWIO
shl 8) or Set_Access_Flag
;an014; dms;allow access to disk
3790 int 21h
;an014; dms;
3791 ; $endif ;an014; dms;
3794 pop dx ;an014; dms;restore regs
3801 Set_Disk_Access_On_Off endp
;an014; dms;
3804 ;=========================================================================
3805 ; Get_Disk_Access : This routine will determine the access state of
3808 ; Inputs : DX - pointer to buffer
3809 ; Outputs : Disk_Access.DAC_Access_Flag - 0ffh signals access allowed
3810 ; to the disk previously.
3812 ;=========================================================================
3814 Procedure Get_Disk_Access
;an014; dms;
3816 push ax ;an014; dms;save regs
3817 push bx ;an014; dms;
3818 push cx ;an014; dms;
3819 push dx ;an014; dms;
3821 xor bx,bx ;an014; dms;clear bx
3822 mov bl,Drive
;an014; dms;get driver number
3823 inc bl ;an014; dms;make it 1 based
3824 call IsRemovable
;an014; dms;see if removable media
3825 ; $if c ;an014; dms;not removable
3827 mov ax,(IOCTL
shl 8) or Generic_IOCTL
;an014; dms;generic ioctl
3828 xor bx,bx ;an014; dms;clear bx
3829 mov bl,Drive
;an014; dms;get drive letter
3830 inc bl ;an014; dms;make it 1 based
3831 mov cx,(RAWIO
shl 8) or Get_Access_Flag
;an014; dms;determine disk access
3832 lea dx,Disk_Access
;an014; dms;point to parm list
3833 int 21h
;an014; dms;
3834 cmp Disk_Access
.DAC_Access_Flag
,01h ;an014; dms;access is currently allowed?
3835 ; $if e ;an014; dms;yes
3837 mov Disk_Access
.DAC_Access_Flag
,0ffh ;an014; dms;signal access is currently allowed
3838 ; $endif ;an014; dms;
3840 ; $endif ;an014; dms;
3843 pop dx ;an014; dms;restore regs
3850 Get_Disk_Access endp
;an014; dms;
3852 ;=========================================================================
3853 ; Calc_Cluster_Boundary : This routine will determine where, within a
3854 ; cluster, a sector resides.
3856 ; Inputs : Relative_Sector_Low - Sector
3857 ; Relative_Sector_High
3859 ; Outputs : Cluster_Boundary_Adj_Factor - The number of sectors
3860 ; remaining in the cluster.
3861 ; Cluster_Boundary_SPT_Count - The count of sectors
3862 ; having been accessed for
3864 ;=========================================================================
3866 Procedure Calc_Cluster_Boundary
;an000; dms;
3868 push ax ;an000; dms;save regs
3869 push bx ;an000; dms;
3870 push cx ;an000; dms;
3871 push dx ;an000; dms;
3872 push si ;an000; dms;
3873 push di ;an000; dms;
3875 xor dx,dx ;an000; dms;clear high word
3876 mov dx,word ptr Relative_Sector_High
;an000; dms;get the high sector word
3877 mov ax,word ptr Relative_Sector_Low
;an000; dms;get the low sector word
3878 sub ax,StartSector
;an000; dms;get relative sector #
3879 sbb dx,0 ;an000; dms;pick up borrow
3881 mov si,dx ;an000; dms;get high word
3882 mov di,ax ;an000; dms;get low word
3883 xor cx,cx ;an000; dms;clear cx
3884 mov cl,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an000; dms;get sectors/cluster
3885 call Divide_32_Bits
;an000; dms;32 bit division
3887 or cx,cx ;an000; dms;see if remainder exists
3888 ; $if nz ;an000; dms;remainder exists
3890 xor bx,bx ;an021; dms;
3891 mov bl,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an021; dms;get sectors/cluster
3892 sub bx,cx ;an021; dms;get number of sectors to read
3893 mov Cluster_Boundary_Adj_Factor
,bx ;ac021; dms;remainder = sector count
3894 ; $else ;an000; dms;no remainder
3897 xor bx,bx ;an000; dms;clear bx
3898 mov bl,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an000; dms;get sectors/cluster
3899 mov Cluster_Boundary_Adj_Factor
,bx ;an000; dms;get sectors/cluster
3900 ; $endif ;an000; dms;
3903 mov ax,Cluster_Boundary_SPT_Count
;an000; dms;get current sector count
3904 xor dx,dx ;an000; dms;clear high word
3905 add ax,Cluster_Boundary_Adj_Factor
;an000; dms;get next sector count
3906 cmp ax,DeviceParameters
.DP_BPB
.BPB_SectorsPerTrack
;an000; dms;exceeded sectors/track?
3907 ; $if a ;an000; dms;yes
3909 mov ax,DeviceParameters
.DP_BPB
.BPB_SectorsPerTrack
;an000; dms;only use difference
3910 sub ax,Cluster_Boundary_SPT_Count
;an000; dms;get next sector count
3911 mov Cluster_Boundary_Adj_Factor
,ax ;an000; dms;
3912 ; $endif ;an000; dms;
3915 mov ax,Cluster_Boundary_SPT_Count
;an000; dms;get sector count
3916 xor dx,dx ;an000; dms;clear high word
3917 add ax,Cluster_Boundary_Adj_Factor
;an000; dms;get new sector count
3918 mov Cluster_Boundary_SPT_Count
,ax ;an000; dms;save it
3920 pop di ;an000; dms;restore regs
3922 pop dx ;an000; dms;restore regs
3929 Calc_Cluster_Boundary endp
;an000; dms;
3931 ;=========================================================================
3932 ; Cluster_Buffer_Allocate : This routine will allocate a buffer
3933 ; based on a cluster's size. If enough
3934 ; space does not exist, a cluster will
3935 ; be redefined to a smaller size for
3936 ; purposes of sector retries.
3938 ; Inputs : DeviceParameters.DP_BPB.BPB_BytesPerSector
3939 ; DeviceParameters.DP_BPB.BPB_SectorsPerCluster
3941 ; Outputs : Cluster_Boundary_Flag - True (space available)
3942 ; False(not enough space)
3943 ; Cluster_Boundary_Buffer_Seg - Pointer to buffer
3944 ;=========================================================================
3946 Procedure Cluster_Buffer_Allocate
;an000; dms;
3948 push ax ;an000; dms;save regs
3949 push bx ;an000; dms;
3950 push cx ;an000; dms;
3951 push dx ;an000; dms;
3953 mov ax,(Alloc
shl 8) ;an000; dms;allocate memory
3954 mov bx,0ffffh ;an000; dms;get available memory
3955 int 21h
;an000; dms;
3957 mov ax,DeviceParameters
.DP_BPB
.BPB_BytesPerSector
;an000; dms;get bytes/sector
3958 xor dx,dx ;an000; dms;clear high word
3959 xor cx,cx ;an000; dms;clear cx
3960 mov cl,DeviceParameters
.DP_BPB
.BPB_SectorsPerCluster
;an000; dms;get sector count
3961 mul cx ;an000; dms;get total byte count
3962 mov cl,4 ;an000; dms;set up shift count
3963 shr ax,cl ;an000; dms;divide by 16
3964 inc ax ;an000; dms;round up
3966 cmp bx,ax ;an000; dms;enough room
3967 ; $if a ;an000; dms;yes
3969 mov bx,ax ;an000; dms;allocate needed memory
3970 mov ax,(Alloc
shl 8) ;an000; dms;
3971 int 21h
;an000; dms;
3972 mov Cluster_Boundary_Buffer_Seg
,ax ;an000; dms;save pointer to buffer
3973 mov Cluster_Boundary_Flag
,True
;an000; dms;signal space available
3974 ; $else ;an000; dms;not enough room
3977 mov Cluster_Boundary_Flag
,False
;an000; dms;signal not enough space
3978 ; $endif ;an000; dms;
3981 pop dx ;an000; dms;restore regs
3988 Cluster_Buffer_Allocate endp
;an000; dms;
3991 ;=========================================================================
3992 ; Set_CDS_Off - This routine disallows access to a
3993 ; disk if a format fails on a non-FAT
3996 ;=========================================================================
3998 Procedure Set_CDS_Off
;an000; dms;
4000 push ax ;an000; dms;save regs
4001 push dx ;an000; dms;
4003 mov ax,5f08h
;an000; dms;reset CDS
4004 mov dl,Drive
;an000; dms;drive to reset
4005 int 21h
;an000; dms;
4007 pop dx ;an000; dms;restore regs
4012 Set_CDS_Off endp
;an000; dms;
4015 ;=========================================================================
4016 ; Format_Access_Wrap_Up - This routine determines whether or
4017 ; not access should be allowed to the
4018 ; disk based on the exit status of
4021 ;=========================================================================
4023 Procedure Format_Access_Wrap_Up
;an000; dms;
4025 cmp Disk_Access
.DAC_Access_Flag
,0ffh ;an015; dms;access prev. allowed?
4026 ; $if ne ;an015; dms;no
4028 cmp ExitStatus
,ExitOK
;an015; dms;good exit?
4029 ; $if ne ;an015; dms;no
4031 lea dx,Disk_Access
;an015; dms;point to parm block
4032 mov Disk_Access
.DAC_Access_Flag
,00h ;an015; dms;signal no disk access
4033 call Set_Disk_Access_On_Off
;an015; dms;don't allow disk access
4034 ; $else ;an015; dms;bad exit
4037 lea dx,Disk_Access
;an015; dms;point to parm block
4038 mov Disk_Access
.DAC_Access_Flag
,01h ;an015; dms;signal disk access
4039 call Set_Disk_Access_On_Off
;an015; dms;allow disk access
4040 ; $endif ;an015; dms;
4042 ; $endif ;an015; dms;
4045 cmp FAT_Flag
,No
;an012; dms;non-FAT format?
4046 ; $if e ;an012; dms;yes
4048 cmp ExitStatus
,ExitOK
;an012; dms;good exit?
4049 ; $if ne ;an012; dms;no
4051 call Set_CDS_Off
;an012; dms;disallow FAT access
4052 ; $endif ;an012; dms;
4054 ; $endif ;an012; dms;
4059 Format_Access_Wrap_Up endp
;an000; dms;
4061 ;=========================================================================
4062 ; BadClus_Address_Adjust - This routine adjusts the segment and
4063 ; offset to provide addressibility into
4066 ; Inputs : bx - high word to adjust segment for
4067 ; ax - low word to adjust segment for
4068 ; cx - segment to be adjusted
4070 ; Outputs : cx - new segment value
4071 ; ax - new offset value
4072 ;=========================================================================
4074 Procedure BadClus_Address_Adjust
;an000; dms;
4076 push bx ;an000; save regs
4081 mov dx,cx ;an000; save segment value
4082 mov si,bx ;an000; get high word for divide
4083 mov di,ax ;an000; get low word for divide
4084 xor cx,cx ;an000; clear cx
4085 mov cl,Paragraph_Size
;an000; divide by 16
4086 call Divide_32_Bits
;an000; perform division
4088 add dx,di ;an000; adjust segment for result
4089 mov ax,cx ;an000; pick up the remainder
4090 mov cx,dx ;an000; pass back new segment
4092 pop si ;an000; restore regs
4099 BadClus_Address_Adjust endp
;an000; dms;
4103 ;=========================================================================
4104 ; NextTrack : This routine determines the next track to be
4107 ; Inputs : TracksLeft - # of tracks remaining
4108 ; Tracks_To_Format - # of tracks to format in 1 call
4109 ; FP_Head - disk head
4110 ; FP_Cylinder - disk cylinder
4112 ; Outputs : TracksLeft - # of tracks remaining
4113 ; FP_Head - disk head
4114 ; FP_Cylinder - disk cylinder
4115 ; CY - no tracks left to format
4116 ; NC - tracks left to format
4117 ;=========================================================================
4119 Procedure NextTrack
;an015; dms;
4122 cmp TracksLeft
,00 ;an015; dms;end of format?
4123 ; $if e ;an015; dms;yes
4125 stc ;an015; dms;signal end of format
4130 mov cx,Tracks_To_Format
;an015; dms;get max track count for call
4131 ; $do ;an015; dms;while tracks remain
4133 cmp TracksLeft
,00 ;an015; dms;end of format?
4134 ; $leave e ;an015; dms;yes
4136 cmp cx,00 ;an015; dms;end of head/cyl. adjustment?
4137 ; $leave e ;an015; dms;yes
4139 inc FormatPacket
.FP_Head
;an015; dms;next head
4140 mov ax,FormatPacket
.FP_Head
;an015; dms;get head for comp
4141 cmp ax,DeviceParameters
.DP_BPB
.BPB_Heads
;an015; dms;exceeded head count?
4142 ; $if e ;an015; dms;yes
4144 mov FormatPacket
.FP_Head
,00 ;an015; dms;reinit. head
4145 inc FormatPacket
.FP_Cylinder
;an015; dms;next cylinder
4146 ; $endif ;an015; dms;
4149 dec cx ;an015; dms;decrease counter
4150 ; $enddo ;an015; dms;
4154 clc ;an015; dms;clear CY
4155 ; $endif ;an015; dms;
4160 NextTrack endp
;an015; dms;
4162 ;=========================================================================
4163 ; Determine_Format_Type : This routine determines the type of format
4164 ; that is to occur based on the media type.
4166 ; Inputs : Dev_HardDisk - Media type (harddisk)
4167 ; Multi_Track_Format - EQU 02h
4168 ; Single_Track_Format - EQU 00h
4170 ; Outputs : FP_SpecialFunctions - Set appropriately for single
4171 ; or multi track format
4172 ;=========================================================================
4174 Procedure Determine_Format_Type
;an015; dms;
4176 cmp DeviceParameters
.DP_DeviceType
,Dev_HardDisk
;an015; dms;harddisk?
4177 ; $if e ;an015; dms;yes
4179 mov FormatPacket
.FP_SpecialFunctions
,Multi_Track_Format
;an015; dms;set for multi track format
4180 ; $else ;an015; dms;
4183 mov FormatPacket
.FP_SpecialFunctions
,Single_Track_Format
;an015; dms;set for single track format
4184 ; $endif ;an015; dms;
4188 Determine_Format_Type endp
;an015; dms;
4191 ;=========================================================================
4192 ; FormatTrack : This routine performs multi track or single
4193 ; track formatting based on the state of the
4194 ; SpecialFunctions byte.
4196 ; Inputs : Tracks_To_Format - # of tracks to format in 1 call
4197 ; FormatPacket - Parms for IOCTL call
4199 ; Outputs : NC - formatted track(s)
4200 ; CY - error in format
4201 ; AX - extended error on CY
4202 ;=========================================================================
4204 Procedure FormatTrack
;an015; dms;
4206 mov ax,(IOCTL
shl 8) or Generic_IOCTL
;an015; dms;Generic IOCTL
4207 mov bl,drive
;an015; dms;get drive number
4208 inc bl ;an015; dms;make it 1 based
4209 mov cx,(RawIO
shl 8) or Format_Track
;an015; dms;Format track(s)
4210 mov dx,Tracks_To_Format
;an015; dms;get track count
4211 mov FormatPacket
.FP_TrackCount
,dx ;an015; dms;put count in parms list
4212 lea dx,FormatPacket
;an015; dms;ptr to parms
4213 int 21h
;an015; dms;
4215 ; $if c ;an015; dms;error?
4217 mov ah,59h
;an015; dms;get extended error
4218 xor bx,bx ;an015; dms;clear bx
4219 int 21h
;an015; dms;
4220 stc ;an015; dms;flag an error
4221 ; $endif ;an015; dms;
4226 FormatTrack endp
;an015; dms;
4229 ;=========================================================================
4230 ; Determine_Track_Count : This routine determines the number of
4231 ; tracks to be formatted, based on whether
4232 ; or not we have a hard disk. If we have
4233 ; a hard disk we can use multi-track
4234 ; format/verify, otherwise we use the
4235 ; single track format/verify.
4237 ; Inputs : Device_Type - Media type
4239 ; Outputs : Tracks_To_Format - Max. number of tracks
4240 ; to be formatted in one
4242 ;=========================================================================
4244 Procedure Determine_Track_Count
;an015; dms;
4246 cmp DeviceParameters
.DP_DeviceType
,Dev_HardDisk
;an015; dms;harddisk?
4247 ; $if e ;an015; dms;yes
4249 call Calc_Track_Count
;an015; dms;calc Tracks_To_Format
4250 ; $else ;an015; dms;removable media
4253 mov Tracks_To_Format
,0001h ;an015; dms;default to 1 track
4254 ; $endif ;an015; dms;
4259 Determine_Track_Count endp
;an015;dms;
4262 ;=========================================================================
4263 ; Calc_Track_Count : This routine determines if we have enough tracks
4264 ; remaining to use the max. number of tracks
4265 ; in the FormatTrack call. If the tracks remaining
4266 ; to be formatted is less that the max. number of
4267 ; allowable tracks for the call, the max. number
4268 ; of allowable tracks is set to the remaining track
4271 ; Inputs : Track_Count - Max. number of allowable tracks to be
4272 ; formatted in 1 FormatTrack call.
4273 ; TracksLeft - Track count of remaining tracks to be
4276 ; Outputs : Tracks_To_Format - Count of the tracks to be formatted
4277 ; in the next FormatTrack call.
4280 ;=========================================================================
4282 Procedure Calc_Track_Count
;an015; dms;
4284 push ax ;an015; dms;save regs
4285 mov ax,Track_Count
;an015; dms;max bytes to format
4286 cmp ax,TracksLeft
;an015; dms;too many tracks?
4287 ; $if a ;an015; dms;yes
4289 mov ax,TracksLeft
;an015; dms;format remaining tracks
4290 ; $endif ;an015; dms;
4292 mov Tracks_To_Format
,ax ;an015; dms;save track count
4298 Calc_Track_Count endp
;an015; dms;
4300 ;=========================================================================
4301 ; Calc_Max_Tracks_To_Format : This routine determines the maximum
4302 ; number of tracks to format at 1 time.
4304 ; Inputs : DeviceParameters - SectorsPerTrack
4307 ; Outputs : Track_Count - Max. # of tracks to format in 1 call
4309 ;=========================================================================
4311 Procedure Calc_Max_Tracks_To_Format
4313 push ax ;an015; dms;save regs
4314 push bx ;an015; dms;
4315 push dx ;an015; dms;
4317 mov ax,DeviceParameters
.DP_BPB
.BPB_SectorsPerTrack
;an015; dms;get sectors per track
4318 mov bx,DeviceParameters
.DP_BPB
.BPB_BytesPerSector
;an015; dms;get byte count
4319 xor dx,dx ;an015; dms;clear dx
4320 mul bx ;an015; dms;get total byte count
4321 mov bx,ax ;an015; dms;put count in bx
4322 mov ax,Max_Format_Size
;an015; dms;max bytes to format
4323 div bx ;an015; dms;get track count
4332 Calc_Max_Tracks_To_Format endp
4338 ;=========================================================================
4339 ; Format_Track_Retry : This routine performs the retry logic for
4340 ; the format multi-track. It will retry each track
4341 ; until the failing track is encountered through
4346 ; Outputs : CY - indicates either a failing track or end of format
4349 ;=========================================================================
4351 Procedure Format_Track_Retry
4353 clc ;an022; dms; clear existing CY
4354 mov Tracks_To_Format
,1 ;an015; dms; only format 1 track
4355 ; $do ;an015; dms; while we have good tracks
4357 ; $leave c ;an015; dms; exit on bad track
4359 call FormatTrack
;an015; dms; format the track
4360 ; $if nc ;an015; dms;error?
4362 call DisplayCurrentTrack
;an022; dms;adjust percent counter
4363 call Adj_Track_Count
4364 call NextTrack
;an015; dms;calc next track
4365 ; $endif ;an015; dms;
4367 ; $enddo ;an015; dms;
4373 Format_Track_Retry endp
;an015; dms;
4375 ;=========================================================================
4376 ; Format_Loop : This routine provides the main template
4377 ; for the formatting of a disk. A disk
4378 ; will be formatted as long as there are
4379 ; tracks remaining to be formatted.
4380 ; This routine can be exited on a carry
4381 ; condition; i.e., bad track, last track, etc.
4385 ; Outputs : CY - Set on exit from this routine
4386 ; AX - Possible error condition code
4387 ;=========================================================================
4389 Procedure Format_Loop
;an015; dms;
4391 clc ;an015; dms;initialize to NC
4392 ; $do ;an015; dms;while NC
4394 ; $leave c ;an015; dms;exit on CY
4396 call Calc_Current_Head_Cyl
;an015; dms;head and cylinder calc.
4397 call Determine_Format_Type
;an015; dms;floppy/hard media?
4398 call Determine_Track_Count
;an015; dms;how many tracks?
4399 call FormatTrack
;an015; dms;format track(s)
4400 ; $if c ;an015; dms;formattrack failed
4402 pushf ;an015; dms;save flags
4403 cmp DeviceParameters
.DP_DeviceType
,Dev_HardDisk
;an015; dms;harddisk?
4404 ; $if e ;an015; dms;yes
4406 popf ;an015; dms;restore flags
4407 call Format_Track_Retry
;an015; dms;find failing track
4408 ; $else ;an015; dms;
4411 popf ;an015; dms;restore flags
4412 ; $endif ;an015; dms;
4414 ; $endif ;an015; dms;
4417 ; $if c ;an015; dms;format error?
4419 pushf ;an015; dms;yes - save flags
4420 push ax ;an015; dms;save return code
4421 call CheckRealErrors
;an015; dms;check error type
4422 ; $if nc ;an015; dms;if non-fatal
4424 call DisplayCurrentTrack
;an015; dms;display % formatted
4425 ; $endif ;an015; dms;
4427 pop ax ;an015; dms;restore regs
4429 ; $endif ;an015; dms;
4432 ; $leave c ;an015; dms;exit on CY
4435 call DisplayCurrentTrack
;an015; dms;tell how much formatted
4436 call Adj_Track_Count
;an015; dms;decrease track counter
4437 call NextTrack
;an015; dms;adjust head and cylinder
4438 ; $enddo ;an015; dms;
4443 Format_Loop endp
;an015; dms;
4445 ;=========================================================================
4446 ; Adj_Track_Count : This routine adjusts the track count by the
4447 ; number of tracks that have been formatted
4448 ; in one FormatTrack call.
4450 ; Inputs : TracksLeft - # of tracks remaining to be formatted
4451 ; Tracks_To_Format - Tracks formatted in 1 call
4453 ; Outputs : TracksLeft - # of tracks remaining to be formatted
4454 ;=========================================================================
4456 Procedure Adj_Track_Count
;an015; dms;
4458 push ax ;an015; dms; save regs
4459 mov ax,TracksLeft
;an015; dms; get tracks remaining
4460 sub ax,Tracks_To_Format
;an015; dms; subtract amount formatted
4461 mov TracksLeft
,ax ;an015; dms; save new tracks remaining value
4462 pop ax ;an015; dms; restore regs
4465 Adj_Track_Count endp
;an015; dms;
4467 ;=========================================================================
4468 ; Prompt_User_For_Disk : This routine prompts the user for the
4469 ; disk to be formatted. An appropriate
4470 ; message is chosen based on the type
4471 ; of switch entered. If the /SELECT
4472 ; switch is entered, the disk prompt is
4473 ; issued through the INT 2fh services
4474 ; provided by SELECT.
4476 ; Inputs : Switchmap - Switches chosen for format
4478 ; Outputs : Message printed as appropriate.
4479 ;=========================================================================
4481 Procedure Prompt_User_For_Disk
;an016;dms;
4483 push ax ;an016;dms;save ax
4484 test switchmap
, (SWITCH_Backup
or SWITCH_Select
or SWITCH_AUTOTEST
) ;Suppress prompt? ;AC000;
4487 call DSKPRM
; prompt user for disk
4491 test switchmap
, (Switch_Select
) ;an016;dms;/SELECT requested?
4492 ; $if nz ;an016;dms;yes
4494 mov al, drive
;an016;dms;get drive to access for format
4495 call AccessDisk
;an016;dms;access the disk
4496 mov ax,Select_Disk_Message
;an016;dms;display disk prompt
4497 int 2fh
;an016;dms; through INT 2fh services
4498 ; $endif ;an016;dms;
4500 pop ax ;an016;dms;restore ax
4504 Prompt_User_For_Disk endp
;an016;dms;