summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FORMAT/FORMAT.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/FORMAT/FORMAT.ASM')
-rw-r--r--v4.0/src/CMD/FORMAT/FORMAT.ASM4509
1 files changed, 4509 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FORMAT/FORMAT.ASM b/v4.0/src/CMD/FORMAT/FORMAT.ASM
new file mode 100644
index 0000000..c9034d7
--- /dev/null
+++ b/v4.0/src/CMD/FORMAT/FORMAT.ASM
@@ -0,0 +1,4509 @@
1page 84,132
2;
3; SCCSID = @(#)format.asm 1.26 85/10/20
4; SCCSID = @(#)format.asm 1.26 85/10/20
5;***************************************************************
6;
7; 86-DOS FORMAT DISK UTILITY
8;
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
11;
12; SYNTAX: FORMAT [drive][/switch1][/switch2]...[/switch16]
13;
14; Regardless of the drive designator , the user will be prompted to
15; insert the diskette to be formatted.
16;
17;***************************************************************
18
19; 5/12/82 ARR Mod to ask for volume ID
20; 5/19/82 ARR Fixed rounding bug in CLUSCAL:
21; REV 1.5
22; Added rev number message
23; Added dir attribute to DELALL FCB
24; REV 2.00
25; Redone for 2.0
26; REV 2.10
27; 5/1/83 ARR Re-do to transfer system on small memory systems
28; REV 2.20
29; 6/17/83 system size re-initialization bug -- mjb001
30; Rev 2.25
31; 8/31/83 16-bit fat insertion
32; Rev 2.26
33; 11/2/83 MZ fix signed compare problems for bad sectors
34; Rev 2.27
35; 11/8/83 EE current directories are always saved and restored
36; Rev 2.28
37; 11/9/83 NP Printf and changed to an .EXE file
38; Rev 2.29
39; 11/11/83 ARR Fixed ASSIGN detection to use NameTrans call to see
40; if drive letter remapped. No longer IBM only
41; Rev 2.30
42; 11/13/83 ARR SS does NOT = CS, so all use of BP needs CS override
43; Rev 2.31
44; 12/27/83 ARR REP STOSB instruction at Clean: changed to be
45; sure ES = CS.
46
47
48
49
50code segment public para 'CODE'
51code ends
52
53
54
55data segment public para 'DATA'
56data ends
57
58End_Of_Memory segment public para 'BUFFERS'
59End_Of_Memory ends
60
61
62code segment public para 'CODE'
63
64 assume cs:code,ds:nothing,es:nothing
65
66;-------------------------------------------------------------------------------
67; Define as public for debugging
68
69; procedures
70 public GetSize
71 public AddToSystemSize
72 public Phase1Initialisation
73 public SetStartSector
74 public SetfBigFat
75 public Phase2Initialisation
76 public DiskFormat
77 public BadSector
78 public DisplayCurrentTrack
79 public WriteFileSystem
80 public Done
81 public CurrentLogicalSector
82 public PrintErrorAbort
83 public GetDeviceParameters
84 public SetDeviceParameters
85 public Multiply_32_Bits
86
87 public START
88 public FatAllocated
89 public MEMERRJ
90 public MEM_OK
91 public RDFRST
92 public NEEDSYS
93 public INITCALL
94 public SWITCHCHK
95 public SYSLOOP
96 public FRMTPROB
97 public GETTRK
98 public TRKFND
99 public CLRTEST
100 public CMPTRKS
101 public BadClus
102; public DoBig
103; public DoSet
104 public DRTFAT
105 public CLEARED
106 public LOUSE
107 public LOUSEP
108 public FATWRT
109 public SYSOK
110 public STATUS
111 public REPORTC
112 public ONCLUS
113 public MORE
114 public FEXIT
115 public SYSPRM
116 public fexitJ
117 public DoPrompt
118 public TARGPRM
119 public IsRemovable
120 public CheckRemove
121 public IsRemove
122 public NotRemove
123 public DSKPRM
124 public GOPRNIT
125 public crlf
126 public PrintString
127 public std_printf
128 public READDOS
129 public RDFILS
130 public FILESDONE
131 public CLSALL
132 public GOTBIOS
133 public GOTDOS
134 public CLSALLJ
135 public GOTCOM
136 public WRITEDOS
137 public GOTALLBIO
138 public BIOSDONE
139 public GOTNDOS
140 public PARTDOS
141 public GOTALLDOS
142 public DOSDONE
143 public PARTCOM
144 public GOTALLCOM
145 public COMDONE
146 public MAKEFIL
147 public CheckMany
148 public CLOSETARG
149 public IOLOOP
150 public GOTTARG
151 public GSYS
152 public TESTSYS
153 public GETOFFS
154; public TESTSYSDISK ; dcl 8/23/86
155 public SETBIOS
156 public BIOSCLS
157 public SETBIOSSIZ
158 public DOSOPNOK
159 public DOSCLS
160 public SETDOSSIZ
161 public GotComHand
162 public COMCLS
163 public SETCOMSIZ
164 public GETFSIZ
165 public READFILE
166 public WRITEFILE
167 public FILIO
168 public NORMIO
169 public IORETP
170 public IORET
171 public NORMALIZE
172 public GotDeviceParameters
173 public LoadSectorTable
174 public NotBigTotalSectors
175 public NotBig
176 public FormatLoop
177 public FormatDone
178 public ContinueFormat
179 public ReportBadTrack
180 public NoMoreTracks
181 public WriteDIRloop
182 public Main_Routine
183 public ControlC_Handler
184
185; bytes
186 public fBigFat
187 public formatError
188 public ROOTSTR
189 public DBLFLG
190 public DRIVE
191 public FILSTAT
192 public USERDIRS
193 public VOLFCB
194 public VOLNAM
195 public TRANSRC
196 public TRANDST
197 public INBUFF
198 public driveLetter
199 public systemDriveLetter
200 public CommandFile
201 public ExitStatus
202 public VolDrive
203 public DelFCB
204 public DelDrive
205
206; words
207 public startSector
208 public fatSpace
209 public firstHead
210 public firstCylinder
211 public tracksLeft
212 public tracksPerDisk
213 public sectorsInRootDirectory
214 public directorySector
215 public printStringPointer
216 public MSTART
217 public MSIZE
218 public TempHandle
219 public BEGSEG
220 public SWITCHMAP
221 public SWITCHCOPY
222 public FAT
223 public CLUSSIZ
224 public SECSIZ
225 public SYSTRKS
226 public SECTORS
227 public currentHead
228 public currentCylinder
229 public PercentComplete
230 public Formatted_Tracks_High
231 public Formatted_Tracks_Low
232
233; other
234 public deviceParameters
235 public Disk_Access
236 public formatPacket
237;-------------------------------------------------------------------------------
238
239data 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
269 extrn msgCRLF: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
275 extrn MsgVerify:Byte
276
277data ends
278
279
280debug equ 0
281 .xlist
282 INCLUDE VERSIONA.INC
283 INCLUDE DOSMAC.INC
284 INCLUDE SYSCALL.INC
285 INCLUDE ERROR.INC
286 INCLUDE DPB.INC
287 INCLUDE CPMFCB.INC
288 INCLUDE DIRENT.INC
289 INCLUDE CURDIR.INC
290 INCLUDE PDB.INC
291 INCLUDE BPB.INC
292 INCLUDE FOREQU.INC
293 INCLUDE FORMACRO.INC
294 INCLUDE IOCTL.INC
295 INCLUDE FORSWTCH.INC
296 INCLUDE SYSVAR.INC
297 .list
298
299
300;-------------------------------------------------------------------------------
301; And this is the actual data
302
303data segment public para 'DATA'
304 public deviceParameters
305 public bios
306 public dos
307 public command
308 public FAT_Flag
309
310validSavedDeviceParameters db 0
311savedDeviceParameters a_DeviceParameters <>
312deviceParameters a_DeviceParameters <>
313
314Disk_Access A_DiskAccess_Control <> ;an000; dms;
315
316formatPacket a_FormatPacket <>
317RWPacket a_TrackReadWritePacket <>
318RW_TRF_Area db 512 dup(0)
319
320startSector dw ?
321fatSpace dd ?
322fBigFat db FALSE
323
324firstHead dw ?
325firstCylinder dw ?
326tracksLeft dw ?
327tracksPerDisk dw ?
328
329Formatted_Tracks_Low dw 0
330Formatted_Tracks_High dw 0
331
332
333public NumSectors ,TrackCnt
334NumSectors dw 0FFFFh
335TrackCnt dw 0FFFFh
336PercentComplete dw 0FFFFh ;Init non-zero so msg will display first time
337
338public Old_Dir
339Old_Dir db FALSE
340
341public fLastChance
342fLastChance db FALSE ; Flags reinvocation from
343 ; LastChanceToSaveIt. Used by DSKPRM
344
345sectorsInRootDirectory dw ?
346
347directorySector dd 0
348
349formatError db 0
350
351printStringPointer dw 0
352
353; Exit status defines
354ExitStatus db 0
355ExitOK equ 0
356ExitCtrlC equ 3
357ExitFatal equ 4
358ExitNo equ 5
359ExitDriveNotReady equ 6 ;an017; dms;drive not ready error
360ExitWriteProtect equ 7 ;an017; dms;write protect error
361
362ROOTSTR DB ?
363 DB ":\",0
364DBLFLG DB 0 ;Initialize flags to zero
365IOCNT DD ?
366MSTART DW ? ; Start of sys file buffer (para#)
367MSIZE DW ? ; Size of above in paragraphs
368TempHandle DW ?
369FILSTAT 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
379
380USERDIRS DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory
381
382Paras_Per_Fat dw 0000h ;an000;holds fat para count
383Fat_Init_Value dw 0000h ;an000;initializes the FAT
384
385bios a_FileStructure <>
386BiosAttributes EQU attr_hidden + attr_system + attr_read_only
387
388dos a_FileStructure <>
389DosAttributes EQU attr_hidden + attr_system + attr_read_only
390
391command a_FileStructure <>
392CommandAttributes EQU 0
393CommandFile DB "X:\COMMAND.COM",0
394CommandFile_Buffer DB 127 dup(0) ;an000;allow room for copy
395
396Command_Com DB "COMMAND.COM",0
397
398VOLFCB DB -1,0,0,0,0,0,8
399VOLDRIVE DB 0
400VOLNAM DB " "
401 DB 8
402 DB 26 DUP(?)
403
404DelFCB DB -1,0,0,0,0,0,8
405DelDRIVE DB 0
406DelNAM DB "???????????"
407 DB 8
408 DB 26 DUP(?)
409
410TRANSRC DB "A:CON",0,0 ; Device so we don't hit the drive
411TRANDST DB "A:\",0,0,0,0,0,0,0,0,0,0
412
413BEGSEG DW ?
414SWITCHMAP DW ?
415SWITCHCOPY DW ?
416FAT DW ?
417 DW ?
418CLUSSIZ DW ?
419SECSIZ DW ?
420SYSTRKS DW ?
421SECTORS DW ?
422INBUFF DB 80,0
423 DB 80 DUP(?)
424
425
426drive db 0
427driveLetter db "x"
428systemDriveLetter db "x"
429
430CTRL_BREAK_VECTOR dd ? ;ac010; dms;Holds CTRL-Break
431 ; vector
432
433Command_Path dd ? ;an011; dms;hold pointer to
434 ; COMMAND's path
435
436Comspec_ID db "COMSPEC=",00 ;an011; dms;Comspec target
437
438
439Environ_Segment dw ? ;an011; dms;hold segment of
440 ; environ. vector
441;======== Disk Table ========== ;an012; dms;
442;Used if NumberOfFATs in BPB
443;is 0.
444
445DiskTable 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
450
451public Org_AX ;an000; dms;make it known
452Org_AX dw ? ;an000; dms;AX on entry
453
454Cluster_Boundary_Adj_Factor dw ? ;an000; dms;
455Cluster_Boundary_SPT_Count dw ? ;an000; dms;
456Cluster_Boundary_Flag db False ;an000; dms;
457Cluster_Boundary_Buffer_Seg dw ? ;an000; dms;
458
459Relative_Sector_Low dw ? ;an000; dms;
460Relative_Sector_High dw ? ;an000; dms;
461
462FAT_Flag db ? ;an000; dms;
463Tracks_To_Format dw ? ;an015; dms;
464Track_Count dw ? ;an015; dms;
465Format_End db FALSE ;an015; dms;
466
467public Msg_Allocation_Unit_Val
468
469Msg_Allocation_Unit_Val dd ? ;an019; dms;
470
471
472data ends
473
474;For FORPROC and FORMES modules
475
476 public secsiz,clussiz,inbuff
477
478 PUBLIC crlf,std_printf
479
480 public switchmap,drive,driveLetter,fatSpace
481 public fBigFat, PrintString,currentHead,currentCylinder
482 extrn CheckSwitches:near,LastChanceToSaveIt:near
483 extrn Volid:near
484 extrn WriteBootSector:near,OemDone:near
485 extrn AccessDisk:near
486 extrn Main_Init:near
487 extrn Read_Disk:near
488 extrn Write_Disk:near
489
490data segment public para 'DATA'
491 extrn BiosFile:byte,DosFile:byte
492data ends
493
494;For FORPROC module
495
496 EXTRN FormatAnother?:near,Yes?:near,REPORT:NEAR,USER_STRING:NEAR
497data segment public para 'DATA'
498 extrn syssiz:dword,biosiz:dword
499data ends
500
501DOSVER_LOW EQU 0300H+20
502DOSVER_HIGH EQU 0300H+20
503
504RECLEN EQU fcb_RECSIZ+7
505RR EQU fcb_RR+7
506
507PSP_Environ equ 2ch ;an011; dms;location of
508 ; environ. segment
509 ; in PSP
510
511Fbig equ 0ffh ;an000; dms;flag for big FAT
512
513START:
514 xor bx,bx ; ;AN000;
515 push bx ; ;AN000;
516 Set_Data_Segment ; ;AC000;
517 mov Org_AX,ax ;an000; dms;save ax on entry
518 jmp Main_Init ; ;AC000;
519
520
521Main_Routine: ; ;AN000;
522; Set memory requirements
523 mov bx,PSP_Segment ;Shrink to free space for FAT ;AC000;
524 mov es,bx ; ;AC000;
525 mov bx,End_Of_Memory ; ;AC000;
526 sub bx,PSP_Segment ; ;AC000;
527 DOS_Call Setblock ; ;AC000;
528
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
532 JE $$IF1
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;
537$$IF1:
538
539 CALL Phase1Initialisation
540 jnc FatAllocated
541
542 Message msgFormatFailure ; ;AC000;
543 jmp Fexit
544
545MEMERR:
546 mov ax, seg data
547 mov ds, ax
548 Message msgOutOfMemory ; ;AC000;
549 ;call PrintString
550 JMP FEXIT
551
552FatAllocated:
553
554 TEST SWITCHMAP,SWITCH_S
555 JZ INITCALL
556 MOV BX,0FFFFH
557 MOV AH,ALLOC
558 INT 21H
559 OR BX,BX
560 JZ MEMERRJ ;No memory
561 MOV [MSIZE],BX
562 MOV AH,ALLOC
563 INT 21H
564 JNC MEM_OK
565MEMERRJ:
566 JMP MEMERR ;No memory
567
568MEM_OK:
569 MOV [MSTART],AX
570
571RDFRST:
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
577NEEDSYS:
578 CALL SYSPRM ;Prompt for system disk
579 JMP RDFRST ;Try again
580
581INITCALL:
582 CALL Phase2Initialisation
583
584SWITCHCHK:
585 MOV DX,SWITCHMAP
586 MOV SWITCHCOPY,DX
587
588SYSLOOP:
589 ;Must intialize for each iteration
590
591 MOV WORD PTR SYSSIZ,0
592 MOV WORD PTR SYSSIZ+2,0
593 MOV BYTE PTR DBLFLG,0
594 mov ExitStatus, ExitOK
595 MOV DX,SWITCHCOPY
596 MOV SWITCHMAP,DX ;Restore original Switches
597; DiskFormat will handle call for new disk
598 CALL DISKFORMAT ;Format the disk
599 JNC GETTRK
600FRMTPROB:
601
602 test SwitchMap,Switch_Select ;an017; dms;SELECT option?
603; $if z ;an017; dms;no - display message
604 JNZ $$IF3
605 Message msgFormatFailure ; ;AC000;
606 mov ExitStatus, ExitFatal ;an017; dms;
607; $endif ;an017; dms;
608$$IF3:
609 CALL MORE ;See if more disks to format
610 JMP SHORT SYSLOOP
611
612;Mark any bad sectors in the FATs
613;And keep track of how many bytes there are in bad sectors
614
615GETTRK:
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
620 JMP DRTFAT ;Yes
621TRKFND:
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
627CLRTEST:
628 MOV SECTORS,AX ;Save the number of sectors on the track
629 TEST SWITCHMAP,SWITCH_S ;If system requested calculate size
630 JZ BAD100
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
639 CALL GETDOSSIZE
640 CALL GETCMDSIZE
641 MOV DX,WORD PTR BIOSIZ+2
642 MOV AX,WORD PTR BIOSIZ
643 DIV deviceParameters.DP_BPB.BPB_BytesPerSector
644 ADD AX,STARTSECTOR
645 MOV SYSTRKS,AX ;Space FAT,Dir,and system files require
646CMPTRKS:
647 mov bx,word ptr Relative_Sector_Low ;get the low word of the sector ;an000; dms;
648 CMP BX,SYSTRKS
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
655BAD100:
656
657 CMP deviceParameters.DP_DeviceType, DEV_HARDDISK ;an000; dms;hard disk?
658; $if e ;an000; dms; yes
659 JNE $$IF5
660 call Get_Bad_Sector_Hard ;an000; dms;see if a sector is bad
661; $else ;an000; dms;floppy disk
662 JMP SHORT $$EN5
663$$IF5:
664 call Get_Bad_Sector_Floppy ;an000; dms;mark entire track bad
665; $endif ;an000; dms;
666$$EN5:
667
668 JMP GETTRK
669
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
675
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.
680;
681; Inputs : DX:AX - Cluster Number
682;
683; Outputs : Cluster is marked invalid
684; ZR set if cluster already marked bad
685;=========================================================================
686
687BadClus proc near ;an000; mark bad clusters
688
689 push di ;an000; save affected regs
690 push ax
691 push bx
692 push cx
693 push dx
694 push es
695
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
699 JE $$IF8
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
705
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
711
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
717
718 MOV DX,0FF7h ;an005; bad cluster flag
719 MOV AX,0FFFh ;an005; mask value
720
721 pop cx ;an000; restore ax in cx - low cluster number
722 test cx,1 ;an000; is old clus num odd?
723; $if nz ;an005; yes
724 JZ $$IF9
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
729; $endif ;an005;
730$$IF9:
731; $else ;an005; 16-bit fats here
732 JMP SHORT $$EN8
733$$IF8:
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
738 ; due to 2 bytes per
739 ; FAT cell. This gives
740 ; us an offset into the
741 ; FAT.
742
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
747
748 MOV DX,0FFF7h ;an005; bad cluster value
749 MOV AX,0FFFFh ;an005; mask value
750; $endif
751$$EN8:
752
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;
760
761 pop es
762 pop dx
763 pop cx
764 pop bx
765 pop ax
766 pop di
767 return
768
769badclus endp
770
771DRTFAT:
772 TEST SWITCHMAP,SWITCH_S ;If system requested, calculate size
773 JZ CLEARED
774 CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space?
775 JNZ CLEARED ;Yes
776 INC BYTE PTR DBLFLG ;No -- set the flag
777 CALL GETSIZE ;Calculate the system size
778CLEARED:
779 call Ctrl_Break_Save ;ac010; dms;save CTRL-Break
780 call Set_Ctrl_Break
781 CALL WriteFileSystem
782
783 JNC FATWRT
784
785
786LOUSE:
787
788 call Reset_Ctrl_Break ;ac010; dms;restore CTRL-Break
789 Message msgDiskUnusable ; ;AC000;
790 JMP FRMTPROB
791
792LOUSEP:
793 POP DS
794 JMP LOUSE
795
796FATWRT:
797
798 PUSH DS
799 MOV DL,DRIVE
800 INC DL
801 MOV AH,GET_DPB
802 INT 21H
803 CMP AL,-1
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
807 POP DS
808 TEST SWITCHMAP,SWITCH_S ;System desired
809 JZ STATUS
810 mov al, drive
811 call AccessDisk ; note what is current logical drive
812 CALL WRITEDOS ;Write the BIOS & DOS
813 JNC SYSOK
814 Message msgNotSystemDisk ; ;AC000;
815 MOV WORD PTR SYSSIZ+2,0 ;No system transfered
816 MOV WORD PTR SYSSIZ,0 ;No system transfered
817 JMP SHORT STATUS
818
819SYSOK:
820
821
822 test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display if EXEC'd by ;AN000;
823; $IF Z ; Select ;AN000;
824 JNZ $$IF13
825 Message msgSystemTransfered ; ;AC000;
826; $ENDIF ;AN000;
827$$IF13:
828STATUS:
829
830 call Reset_Ctrl_Break ;ac010; dms;restore CTRL-Break
831
832 CALL CRLF
833
834
835
836
837 MOV AH,DISK_RESET
838 INT 21H
839 CALL DONE ;Final call to OEM module
840 JNC REPORTC
841 JMP FRMTPROB ;Report an error
842
843REPORTC:
844
845;
846;TEMP FIX for /AUTOTEST
847;
848 test SwitchMap,(Switch_Autotest or Switch_8) ;TEMP
849; $IF Z
850 JNZ $$IF15
851 CALL VOLID
852; $ENDIF
853$$IF15:
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;
856 JNZ $$IF17
857 CALL REPORT ;Print report
858; $ENDIF ; ;AN000;
859$$IF17:
860 CALL MORE ;See if more disks to format
861 JMP SYSLOOP ;If we returned from MORE then continue
862
863;******************************************
864; Calculate the size in bytes of the system rounded up to sector and
865; cluster boundries, Answer in SYSSIZ
866
867GetSize proc near
868 call GetBioSize
869 call GetDosSize
870 call GetCmdSize
871 return
872GetSize endp
873
874GetBioSize proc near
875 MOV AX,WORD PTR bios.fileSizeInBytes
876 MOV DX,WORD PTR bios.fileSizeInBytes+2
877 CALL AddToSystemSize
878 return
879GetBioSize endp
880
881GetDosSize proc near
882 MOV AX,WORD PTR dos.fileSizeInBytes
883 MOV DX,WORD PTR dos.fileSizeInBytes+2
884 CALL AddToSystemSize
885 return
886GetDosSize endp
887
888GetCmdSize proc near
889 MOV AX,WORD PTR command.fileSizeInBytes
890 MOV DX,WORD PTR command.fileSizeInBytes+2
891 call AddToSystemSize
892 return
893GetCmdSize endp
894
895;Calculate the number of sectors used for the system
896PUBLIC AddToSystemSize
897AddToSystemSize proc near
898 push bx
899 DIV deviceParameters.DP_BPB.BPB_BytesPerSector
900 OR DX,DX
901 JZ FNDSIZ0
902 INC AX ; Round up to next sector
903FNDSIZ0:
904 PUSH AX
905 XOR DX,DX
906 xor bx,bx
907 mov bl, deviceParameters.DP_BPB.BPB_SectorsPerCluster
908 div bx
909 POP AX
910 OR DX,DX
911 JZ ONCLUS
912 SUB DX, bx
913 NEG DX
914 ADD AX,DX ; Round up sector count to cluster
915 ; boundry
916ONCLUS:
917 MUL deviceParameters.DP_BPB.BPB_BytesPerSector
918 ADD WORD PTR SYSSIZ,AX
919 ADC WORD PTR SYSSIZ+2,DX
920 pop bx
921 return
922AddToSystemSize endp
923
924MORE:
925
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;
930
931 CMP deviceParameters.DP_DeviceType, DEV_HARDDISK
932 je ExitProgram
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
936 JC ExitProgram
937 CALL CRLF
938 JMP CRLF
939
940
941FEXIT:
942 Set_Data_Segment ;Make sure have addressability ;AN000;
943 mov ExitStatus,ExitFatal
944
945ExitProgram:
946 test validSavedDeviceParameters, 0ffH
947 jz DoNotRestoreDeviceParameters
948 mov savedDeviceParameters.DP_SpecialFunctions, TRACKLAYOUT_IS_GOOD
949 lea dx, savedDeviceParameters
950 call SetDeviceParameters
951DoNotRestoreDeviceParameters:
952
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;
957
958; Prompt the user for a system diskette in the default drive
959SYSPRM:
960 MOV AH,GET_DEFAULT_DRIVE ;Will find out the default drive
961 INT 21H ;Default now in AL
962 MOV BL,AL
963 INC BL ; A = 1
964 ADD AL,41H ;Now in Ascii
965 MOV systemDriveLetter,AL ;Text now ok
966 CALL IsRemovable
967 JNC DoPrompt
968;
969; Media is non-removable. Switch sys disk to drive A. Check, though, to see
970; if drive A is removable too.
971;
972 MOV AL,"A"
973 MOV BYTE PTR [systemDriveLetter],AL
974 MOV [BiosFile],AL
975 MOV [DosFile],AL
976 MOV [CommandFile],AL
977 MOV BX,1
978 CALL IsRemovable
979 JNC DoPrompt
980 Message msgNoSystemFiles ; ;AC000;
981fexitJ:
982 JMP FEXIT
983
984DoPrompt:
985 mov al, systemDriveLetter
986 sub al, 'A'
987 call AccessDisk
988 Message msgInsertDOSDisk ; ;AC000;
989 Message ContinueMsg
990 ;lea dx, ptr_msgInsertDosDisk
991 ;CALL std_printf ;Print first line
992 CALL USER_STRING ;Wait for a key
993 CALL CRLF
994 call crlf
995 return
996
997TARGPRM:
998 mov al, drive
999 call AccessDisk
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
1005 CALL CRLF
1006 return
1007
1008;
1009; Determine if the drive indicated in BX is removable or not.
1010;
1011; Inputs: BX has drive (0=def, 1=A)
1012; Outputs: Carry clear
1013; Removable
1014; Carry set
1015; not removable
1016; Registers modified: none
1017
1018IsRemovable:
1019 SaveReg <AX>
1020 MOV AX,(IOCTL SHL 8) OR 8 ; Rem media check
1021 INT 21H
1022 JNC CheckRemove
1023 MOV AX,(IOCTL SHL 8) + 9 ; Is it a NET drive?
1024 INT 21h
1025 JC NotRemove ; Yipe, say non-removable
1026 TEST DX,1000h
1027 JNZ NotRemove ; Is NET drive, say non-removeable
1028 JMP IsRemove ; Is local, say removable
1029CheckRemove:
1030 TEST AX,1
1031 JNZ NotRemove
1032IsRemove:
1033 CLC
1034 RestoreReg <AX>
1035 return
1036NotRemove:
1037 STC
1038 RestoreReg <AX>
1039 return
1040
1041
1042; DiSKPRoMpt:
1043;
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
1047; warning message.
1048;
1049; INPUTS:
1050; deviceParameters.DP_DeviceType
1051; fLastChance
1052;
1053; OUTPUTS:
1054; Prompt string
1055; fLastChance := FALSE
1056;
1057; Registers affected:
1058; Flags
1059;
1060DSKPRM:
1061 CMP fLastChance,TRUE
1062 JE PrmptRet
1063
1064 CMP deviceParameters.DP_DeviceType, DEV_HARDDISK
1065 jne goprnit
1066 Message msgHardDiskWarning ; ;AC000;
1067 ;lea dx, ptr_msgHardDiskWarning
1068 ;call std_printf
1069 CALL Yes?
1070 jnc OkToFormatHardDisk
1071 mov ExitStatus, ExitNo
1072 jmp ExitProgram
1073
1074OkToFormatHardDisk:
1075 CALL CRLF
1076 CALL CRLF
1077 return
1078
1079GOPRNIT:
1080 mov al, drive
1081 call AccessDisk
1082 Message msgInsertDisk ; ;AC000;
1083 Message ContinueMsg ;
1084 ;lea dx,ptr_msgInsertDisk
1085 ;CALL std_printf
1086 CALL USER_STRING ;Wait for any key
1087 CALL CRLF
1088 CALL CRLF
1089
1090PrmptRet:
1091 mov fLastChance, FALSE
1092 return
1093
1094
1095;-------------------------------------------------------------------------------
1096
1097ControlC_Handler:
1098 mov ax, seg data
1099 mov ds, ax
1100 Message msgInterrupt ; ;AC000;
1101 mov ExitStatus, ExitCtrlC
1102 jmp ExitProgram
1103
1104
1105crlf:
1106 ;lea dx, msgCRLF
1107 mov dx,offset msgCRLF ;CR,LF added to message ;AC000;
1108PrintString:
1109 ;mov printStringPointer, dx
1110 ;lea dx, PrintStringPointer
1111
1112std_printf:
1113 ;push dx
1114 ;call printf
1115 call Display_Interface ; ;AC000;
1116 return
1117
1118;-------------------------------------------------------------------------------
1119
1120
1121;****************************************
1122;Copy IO.SYS, MSDOS.SYS and COMMAND.COM into data area.
1123; Carry set if problems
1124
1125READDOS:
1126 push ax ;save regs ;an025; dms;
1127 push bx ; ;an025; dms;
1128 push es ; ;an025; dms;
1129
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;
1137
1138 pop es ;restore regs ;an025; dms;
1139 pop bx ; ;an025; dms;
1140 pop ax ; ;an025; dms;
1141
1142 call Get_BIOS ; dcl 8/23/86
1143 JNC RDFILS
1144 return
1145
1146RDFILS:
1147 MOV BYTE PTR [FILSTAT],0
1148 MOV BX,[bios.fileHandle]
1149 MOV AX,[MSTART]
1150 MOV DX,AX
1151 ADD DX,[MSIZE] ; CX first bad para
1152 MOV [bios.fileStartSegment],AX
1153 MOV CX,[bios.fileSizeInParagraphs]
1154 ADD AX,CX
1155 CMP AX,DX
1156 JBE GOTBIOS
1157 MOV BYTE PTR [FILSTAT],00000001B ; Got part of BIOS
1158 MOV SI,[MSIZE]
1159 XOR DI,DI
1160 CALL DISIX4
1161 push ds
1162 MOV DS,[bios.fileStartSegment]
1163 assume ds:nothing
1164 CALL READFILE
1165 pop ds
1166 assume ds:data
1167 JC CLSALL
1168 XOR DX,DX
1169 MOV CX,DX
1170 MOV AX,(LSEEK SHL 8) OR 1
1171 INT 21H
1172 MOV WORD PTR [bios.fileOffset],AX
1173 MOV WORD PTR [bios.fileOffset+2],DX
1174FILESDONE:
1175 CLC
1176CLSALL:
1177 PUSHF
1178; CALL COMCLS ; dcl 8/23/86
1179 call FILE_CLS ; dcl 8/23/86
1180 POPF
1181 return
1182
1183GOTBIOS:
1184 MOV BYTE PTR [FILSTAT],00000010B ; Got all of BIOS
1185 push es
1186 LES SI,[bios.fileSizeInBytes]
1187 MOV DI,ES
1188 pop es
1189 push ds
1190 MOV DS,[bios.fileStartSegment]
1191 assume ds:nothing
1192 CALL READFILE
1193 pop ds
1194 assume ds:data
1195 JC CLSALL
1196
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
1203
1204 JNC Found_IBMDOS ;mt 12/8/86 P894
1205 return ;mt 12/8/86
1206
1207Found_IBMDOS: ;mt 12/8/86
1208
1209 MOV BX,[dos.fileHandle]
1210 MOV [dos.fileStartSegment],AX
1211 CMP AX,DX ; No room left?
1212 JZ CLSALL ; Yes
1213 MOV CX,[dos.fileSizeInParagraphs]
1214 ADD AX,CX
1215 CMP AX,DX
1216 JBE GOTDOS
1217 OR BYTE PTR [FILSTAT],00000100B ; Got part of DOS
1218 SUB DX,[dos.fileStartSegment]
1219 MOV SI,DX
1220 XOR DI,DI
1221 CALL DISIX4
1222 push ds
1223 MOV DS,[dos.fileStartSegment]
1224 assume ds:nothing
1225 CALL READFILE
1226 pop ds
1227 assume ds:data
1228 JC CLSALL
1229 XOR DX,DX
1230 MOV CX,DX
1231 MOV AX,(LSEEK SHL 8) OR 1
1232 INT 21H
1233 MOV WORD PTR [dos.fileOffset],AX
1234 MOV WORD PTR [dos.fileOffset+2],DX
1235 JMP FILESDONE
1236
1237GOTDOS:
1238 OR BYTE PTR [FILSTAT],00001000B ; Got all of DOS
1239 push es
1240 LES SI,[dos.fileSizeInBytes]
1241 MOV DI,ES
1242 pop es
1243 push ds
1244 MOV DS,[dos.fileStartSegment]
1245 assume ds:nothing
1246 CALL READFILE
1247 pop ds
1248 assume ds:data
1249
1250CLSALLJ: JNC NOTCLSALL ;PTM P894 mt 12/8/86
1251 jmp clsall ;
1252
1253NotCLSALL:
1254 push ax ; dcl 8/23/86
1255
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
1259 ; COMMAND.COM
1260 call Get_COMMAND ;ac011; dms; Point to COMMAND
1261 ; and read it
1262 pop dx ; dcl 8/23/86
1263 pop ax ; dcl 8/23/86
1264
1265 JNC Found_COMMAND ;mt 12/8/86 P894
1266 return ;mt 12/8/86
1267
1268Found_COMMAND: ;mt 12/8/86
1269 MOV BX,[command.fileHandle]
1270 MOV [command.fileStartSegment],AX
1271 CMP AX,DX ; No room left?
1272 JZ CLSALLJ ; Yes
1273 MOV CX,[command.fileSizeInParagraphs]
1274 ADD AX,CX
1275 CMP AX,DX
1276 JBE GOTCOM
1277 OR BYTE PTR [FILSTAT],00010000B ; Got part of COMMAND
1278 SUB DX,[command.fileStartSegment]
1279 MOV SI,DX
1280 XOR DI,DI
1281 CALL DISIX4
1282 push ds
1283 MOV DS,[command.fileStartSegment]
1284 assume ds:nothing
1285 CALL READFILE
1286 pop ds
1287 assume ds:data
1288 JC CLSALLJ
1289 XOR DX,DX
1290 MOV CX,DX
1291 MOV AX,(LSEEK SHL 8) OR 1
1292 INT 21H
1293 MOV WORD PTR [command.fileOffset],AX
1294 MOV WORD PTR [command.fileOffset+2],DX
1295 JMP FILESDONE
1296
1297GOTCOM:
1298 OR BYTE PTR [FILSTAT],00100000B ; Got all of COMMAND
1299 push es
1300 LES SI,[command.fileSizeInBytes]
1301 MOV DI,ES
1302 pop es
1303 push ds
1304 MOV DS,[command.fileStartSegment]
1305 assume ds:nothing
1306 CALL READFILE
1307 pop ds
1308 assume ds:data
1309 JMP CLSALL
1310
1311;**************************************************
1312;Write BIOS DOS COMMAND to the newly formatted disk.
1313
1314ASSUME DS:DATA
1315WRITEDOS:
1316 MOV CX,BiosAttributes
1317 MOV DX,OFFSET BiosFile
1318 push es
1319 LES SI,[bios.fileSizeInBytes]
1320 MOV DI,ES
1321 pop es
1322 CALL MAKEFIL
1323 retc
1324
1325 MOV [TempHandle],BX
1326 TEST BYTE PTR FILSTAT,00000010B
1327 JNZ GOTALLBIO
1328 call Get_BIOS ; dcl 8/23/86
1329 jnc Got_WBIOS ;mt 12/8/86 P894
1330 ret
1331
1332Got_WBIOS:
1333
1334 push es
1335 LES SI,[bios.fileOffset]
1336 MOV DI,ES
1337 pop es
1338 MOV WORD PTR [IOCNT],SI
1339 MOV WORD PTR [IOCNT+2],DI
1340 MOV BP,OFFSET bios
1341 CALL GOTTARG
1342 retc
1343 JMP SHORT BIOSDONE
1344
1345GOTALLBIO:
1346 push es
1347 LES SI,[bios.fileSizeInBytes]
1348 MOV DI,ES
1349 pop es
1350 push ds
1351 MOV DS,[bios.fileStartSegment]
1352 assume ds:nothing
1353 CALL WRITEFILE
1354 pop ds
1355 assume ds:data
1356BIOSDONE:
1357 MOV BX,[TempHandle]
1358 MOV CX,bios.fileTime
1359 MOV DX,bios.fileDate
1360 CALL CLOSETARG
1361 MOV CX,DosAttributes
1362 MOV DX,OFFSET DosFile
1363 push es
1364 LES SI,[dos.fileSizeInBytes]
1365 MOV DI,ES
1366 pop es
1367 CALL MAKEFIL
1368 retc
1369
1370GOTNDOS:
1371 MOV [TempHandle],BX
1372 TEST BYTE PTR FILSTAT,00001000B
1373 JNZ GOTALLDOS
1374 call Get_DOS ; dcl 8/23/86
1375 jnc Got_WDOS ;mt 12/8/86 P894
1376 ret
1377
1378Got_WDOS:
1379 MOV BP,OFFSET dos
1380 TEST BYTE PTR FILSTAT,00000100B
1381 JNZ PARTDOS
1382 MOV WORD PTR [dos.fileOffset],0
1383 MOV WORD PTR [dos.fileOffset+2],0
1384 CALL GETSYS3
1385 retc
1386 JMP SHORT DOSDONE
1387
1388PARTDOS:
1389 push es
1390 LES SI,[dos.fileOffset]
1391 MOV DI,ES
1392 pop es
1393 MOV WORD PTR [IOCNT],SI
1394 MOV WORD PTR [IOCNT+2],DI
1395 CALL GOTTARG
1396 retc
1397 JMP SHORT DOSDONE
1398
1399GOTALLDOS:
1400 push es
1401 LES SI,[dos.fileSizeInBytes]
1402 MOV DI,ES
1403 pop es
1404 push ds
1405 MOV DS,[dos.fileStartSegment]
1406 assume ds:nothing
1407 CALL WRITEFILE
1408 pop ds
1409 assume ds:data
1410DOSDONE:
1411 MOV BX,[TempHandle]
1412 MOV CX,dos.fileTime
1413 MOV DX,dos.fileDate
1414 CALL CLOSETARG
1415 MOV CX,CommandAttributes
1416 call Command_Root ;an011; dms;adjust path for
1417 ;COMMAND.COM creation
1418 MOV DX,OFFSET CommandFile
1419 push es
1420 LES SI,[command.fileSizeInBytes]
1421 MOV DI,ES
1422 pop es
1423 CALL MAKEFIL
1424 retc
1425
1426 MOV [TempHandle],BX
1427 TEST BYTE PTR FILSTAT,00100000B
1428 JNZ GOTALLCOM
1429 call Get_COMMAND ; dcl 8/23/86
1430 jnc Got_WCOM ;mt 12/8/86 P894
1431 ret
1432
1433Got_WCOM:
1434 MOV BP,OFFSET command
1435 TEST BYTE PTR FILSTAT,00010000B
1436 JNZ PARTCOM
1437 MOV WORD PTR [command.fileOffset],0
1438 MOV WORD PTR [command.fileOffset+2],0
1439 CALL GETSYS3
1440 retc
1441 JMP SHORT COMDONE
1442
1443PARTCOM:
1444 push es
1445 LES SI,[command.fileOffset]
1446 MOV DI,ES
1447 pop es
1448 MOV WORD PTR [IOCNT],SI
1449 MOV WORD PTR [IOCNT+2],DI
1450 CALL GOTTARG
1451 retc
1452 JMP SHORT COMDONE
1453
1454GOTALLCOM:
1455 push es
1456 LES SI,[command.fileSizeInBytes]
1457 MOV DI,ES
1458 pop es
1459 push ds
1460 MOV DS,[command.fileStartSegment]
1461 assume ds:nothing
1462 CALL WRITEFILE
1463 pop ds
1464 assume ds:data
1465COMDONE:
1466 MOV BX,[TempHandle]
1467 MOV CX,command.fileTime
1468 MOV DX,command.fileDate
1469 CALL CLOSETARG
1470;****************************************************************
1471; I don't see the need for the following code!! - RS 3.20
1472; CMP BYTE PTR [FILSTAT],00101010B
1473; JZ NOREDOS
1474;RDFRST2:
1475; CALL READDOS ; Start back with BIOS
1476; JNC NOREDOS
1477; CALL SYSPRM ;Prompt for system disk
1478; JMP RDFRST2 ;Try again
1479;NOREDOS:
1480;****************************************************************
1481 CLC
1482 return
1483
1484;*********************************************
1485; Create a file on target disk
1486; CX = attributes, DX points to name
1487; DI:SI is size file is to have
1488;
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
1492;
1493; On return BX is handle, carry set if problem
1494
1495MAKEFIL:
1496 MOV BX,DX
1497 PUSH WORD PTR [BX]
1498 MOV AL,DriveLetter
1499 MOV [BX],AL
1500 MOV AH,CREAT
1501 INT 21H
1502 POP WORD PTR [BX]
1503 MOV BX,AX
1504 JC CheckMany
1505 MOV CX,DI
1506 MOV DX,SI
1507 MOV AX,LSEEK SHL 8
1508 INT 21H ; Seek to eventual EOF
1509 XOR CX,CX
1510 MOV AH,WRITE
1511 INT 21H ; Set size of file to position
1512 XOR CX,CX
1513 MOV DX,CX
1514 MOV AX,LSEEK SHL 8
1515 INT 21H ; Seek back to start
1516 return
1517
1518;
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.
1521;
1522CheckMany:
1523 CMP AX,error_too_many_open_files
1524 retnz
1525 Extended_Message ; ;AC006;
1526 JMP FEXIT
1527
1528;*********************************************
1529; Close a file on the target disk
1530; CX/DX is time/date, BX is handle
1531
1532CLOSETARG:
1533 MOV AX,(FILE_TIMES SHL 8) OR 1
1534 INT 21H
1535 MOV AH,CLOSE
1536 INT 21H
1537 return
1538
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
1545
1546IOLOOP:
1547 MOV AL,[systemDriveLetter]
1548 CMP AL,[DriveLetter]
1549 JNZ GOTTARG
1550 MOV AH,DISK_RESET
1551 INT 21H
1552 CALL TARGPRM ;Get target disk
1553
1554GOTTARG:
1555ASSUME DS:DATA
1556;Enter here if some of file is already in buffer, IOCNT must be set
1557; to size already in buffer.
1558 MOV BX,[TempHandle]
1559 MOV SI,WORD PTR [IOCNT]
1560 MOV DI,WORD PTR [IOCNT+2]
1561 push ds
1562 MOV DS,ds:[BP.fileStartSegment]
1563 assume ds:nothing
1564 CALL WRITEFILE ; Write next part
1565 pop ds
1566 assume ds:data
1567 retc
1568
1569 push es
1570 LES AX,ds:[BP.fileOffset]
1571 CMP AX,WORD PTR ds:[BP.fileSizeInBytes]
1572 JNZ GETSYS3
1573 MOV AX,ES
1574 CMP AX,WORD PTR ds:[BP.fileSizeInBytes+2]
1575 JNZ GETSYS3
1576 pop es
1577 return ; Carry clear from CMP
1578
1579GETSYS3:
1580;Enter here if none of file is in buffer
1581 pop es
1582 MOV AH,DISK_RESET
1583 INT 21H
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]
1588 JNZ TESTSYS
1589GSYS:
1590 MOV AH,DISK_RESET
1591 INT 21H
1592 CALL SYSPRM ;Prompt for system disk
1593TESTSYS:
1594; CALL TESTSYSDISK ; dcl 8/23/86
1595 JC GSYS
1596 MOV BX,word ptr DS:[BP.fileHandle] ; CS over ARR 2.30
1597 push es
1598 LES DX,dword ptr DS:[BP.fileOffset] ; CS over ARR 2.30
1599 MOV CX,ES
1600 pop es
1601 PUSH DX
1602 MOV AX,LSEEK SHL 8
1603 INT 21H
1604 POP DX
1605 push es
1606 LES SI,dword ptr DS:[BP.fileSizeInBytes] ; CS over ARR 2.30
1607 MOV DI,ES ;put high word in di
1608 pop es
1609 SUB SI,DX ;get low word value
1610 SBB DI,CX ; DI:SI is #bytes to go
1611 PUSH DI
1612 PUSH SI
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?
1620 JBE GOTSIZ2 ;yes
1621 MOV SI,[MSIZE]
1622 XOR DI,DI
1623 CALL DISIX4
1624GOTSIZ2:
1625 MOV WORD PTR [IOCNT],SI ;save byte count for read
1626 MOV WORD PTR [IOCNT+2],DI
1627 push ds
1628 MOV DS,[MSTART]
1629 assume ds:nothing
1630 CALL READFILE
1631 pop ds
1632 assume ds:data
1633 JNC GETOFFS
1634 CALL CLSALL
1635 JMP GSYS
1636GETOFFS:
1637 XOR DX,DX ;clear dx
1638 MOV CX,DX ;clear cx
1639 MOV AX,(LSEEK SHL 8) OR 1
1640 INT 21H
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
1643;;;;;; CALL CLSALL
1644 JMP IOLOOP
1645
1646;*************************************************
1647; Test to see if correct system disk. Open handles
1648
1649CRET12:
1650 STC
1651 return
1652
1653;TESTSYSDISK: ; dcl 8/23/86
1654Get_BIOS: ; dcl 8/23/86
1655 MOV AX,OPEN SHL 8
1656 MOV DX,OFFSET BiosFile
1657 INT 21H
1658 JNC SETBIOS
1659; call CheckMany ; dcl 8/23/86
1660 jmp CheckMany ; dcl 8/23/86
1661
1662SETBIOS:
1663 MOV [Bios.fileHandle],AX
1664 MOV BX,AX
1665 CALL GETFSIZ
1666 CMP [bios.fileSizeInParagraphs],0
1667 JZ SETBIOSSIZ
1668 CMP [bios.fileSizeInParagraphs],AX
1669 JZ SETBIOSSIZ
1670BIOSCLS:
1671 MOV AH,CLOSE
1672 MOV BX,[Bios.fileHandle]
1673 INT 21H
1674; JMP CRET12 ; dcl 8/23/86
1675 ret
1676
1677SETBIOSSIZ:
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
1683 clc
1684 ret ; dcl 8/23/86
1685
1686Get_DOS: ; dcl 8/23/86
1687 MOV AX,OPEN SHL 8
1688 MOV DX,OFFSET DosFile
1689 INT 21H
1690 JNC DOSOPNOK
1691; call CheckMany ; dcl 8/23/86
1692; JMP BIOSCLS ; dcl 8/23/86 Checkmany no ret.
1693 jmp CheckMany ; dcl 8/23/86
1694
1695DOSOPNOK:
1696 MOV [dos.fileHandle],AX
1697 MOV BX,AX
1698 CALL GETFSIZ
1699 CMP [dos.fileSizeInParagraphs],0
1700 JZ SETDOSSIZ
1701 CMP [dos.fileSizeInParagraphs],AX
1702 JZ SETDOSSIZ
1703
1704DOSCLS:
1705 MOV AH,CLOSE
1706 MOV BX,[dos.fileHandle]
1707 INT 21H
1708; JMP BIOSCLS ; dcl 8/23/86
1709 ret ; dcl 8/23/86
1710
1711SETDOSSIZ:
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
1717 clc
1718 ret ; dcl 8/23/86
1719
1720
1721
1722Get_COMMAND:
1723 MOV AX,OPEN SHL 8
1724 MOV DX,OFFSET CommandFile
1725 INT 21H
1726 JNC GotComHand
1727; call CheckMany ; dcl 8/23/86
1728; JMP DosCls ; dcl 8/23/86
1729 jmp Checkmany ; dcl 8/23/86
1730
1731GotComHand:
1732 MOV [command.fileHandle],AX
1733 MOV BX,AX
1734 CALL GETFSIZ
1735 CMP [command.fileSizeInParagraphs],0
1736 JZ SETCOMSIZ
1737 CMP [command.fileSizeInParagraphs],AX
1738 JZ SETCOMSIZ
1739COMCLS:
1740 MOV AH,CLOSE
1741 MOV BX,[command.fileHandle]
1742 INT 21H
1743; JMP DOSCLS ; dcl 8/23/86
1744 ret ; dcl 8/23/86
1745
1746SETCOMSIZ:
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
1752 CLC
1753 return
1754
1755FILE_CLS: ; dcl 8/23/86
1756 MOV AH,CLOSE ; dcl 8/23/86
1757 INT 21H ; dcl 8/23/86
1758 ret ; dcl 8/23/86
1759
1760;*******************************************
1761; Handle in BX, return file size in para in AX
1762; File size in bytes DI:SI, file date in DX, file
1763; time in CX.
1764
1765GETFSIZ:
1766 MOV AX,(LSEEK SHL 8) OR 2
1767 XOR CX,CX
1768 MOV DX,CX
1769 INT 21H
1770 MOV SI,AX
1771 MOV DI,DX
1772 ADD AX,15 ; Para round up
1773 ADC DX,0
1774 AND DX,0FH ; If the file is larger than this it
1775 ; is bigger than the 8086 address
1776 ; space!
1777 MOV CL,12
1778 SHL DX,CL
1779 MOV CL,4
1780 SHR AX,CL
1781 OR AX,DX
1782 PUSH AX
1783 MOV AX,LSEEK SHL 8
1784 XOR CX,CX
1785 MOV DX,CX
1786 INT 21H
1787 MOV AX,FILE_TIMES SHL 8
1788 INT 21H
1789 POP AX
1790 return
1791
1792;********************************************
1793; Read/Write file
1794; DS:0 is Xaddr
1795; DI:SI is byte count to I/O
1796; BX is handle
1797; Carry set if screw up
1798;
1799; I/O SI bytes
1800; I/O 64K - 1 bytes DI times
1801; I/O DI bytes
1802
1803
1804READFILE:
1805; Must preserve AX,DX
1806 PUSH AX
1807 PUSH DX
1808 PUSH BP
1809 MOV BP,READ SHL 8
1810 CALL FILIO
1811 POP BP
1812 POP DX
1813 POP AX
1814 return
1815
1816WRITEFILE:
1817 PUSH BP
1818 MOV BP,WRITE SHL 8
1819 CALL FILIO
1820 POP BP
1821 return
1822
1823FILIO:
1824 XOR DX,DX
1825 MOV CX,SI
1826 JCXZ K64IO
1827 MOV AX,BP
1828 INT 21H
1829 retc
1830 ADD DX,AX
1831 CMP AX,CX ; If not =, AX<CX, carry set.
1832 retnz
1833 CALL NORMALIZE
1834K64IO:
1835 CLC
1836 MOV CX,DI
1837 JCXZ IORET
1838 MOV AX,BP
1839 INT 21H
1840 retc
1841 ADD DX,AX
1842 CMP AX,CX ; If not =, AX<CX, carry set.
1843 retnz
1844 CALL NORMALIZE
1845 MOV CX,DI
1846K64M1:
1847 PUSH CX
1848 XOR AX,AX
1849 OR DX,DX
1850 JZ NORMIO
1851 MOV CX,10H
1852 SUB CX,DX
1853 MOV AX,BP
1854 INT 21H
1855 JC IORETP
1856 ADD DX,AX
1857 CMP AX,CX ; If not =, AX<CX, carry set.
1858 JNZ IORETP
1859 CALL NORMALIZE
1860NORMIO:
1861 MOV CX,0FFFFH
1862 SUB CX,AX
1863 MOV AX,BP
1864 INT 21H
1865 JC IORETP
1866 ADD DX,AX
1867 CMP AX,CX ; If not =, AX<CX, carry set.
1868 JNZ IORETP
1869 CALL NORMALIZE ; Clears carry
1870 POP CX
1871 LOOP K64M1
1872 PUSH CX
1873IORETP:
1874 POP CX
1875IORET:
1876 return
1877
1878
1879;*********************************
1880; Shift DI:SI left 4 bits
1881DISIX4:
1882 MOV CX,4
1883SH32:
1884 SHL SI,1
1885 RCL DI,1
1886 LOOP SH32
1887 return
1888
1889;*********************************
1890; Shift DI:SI right 4 bits
1891DISID4:
1892 MOV CX,4
1893SH32B:
1894 SHR DI,1
1895 RCR SI,1
1896 LOOP SH32B
1897 return
1898
1899;********************************
1900; Normalize DS:DX
1901
1902NORMALIZE:
1903 PUSH DX
1904 PUSH AX
1905 SHR DX,1
1906 SHR DX,1
1907 SHR DX,1
1908 SHR DX,1
1909 MOV AX,DS
1910 ADD AX,DX
1911 MOV DS,AX
1912 POP AX
1913 POP DX
1914 AND DX,0FH ; Clears carry
1915 return
1916
1917;-------------------------------------------------------------------------------
1918; Phase1Initialisation:
1919; This routine MUST set up fatSpace, and fBigFat
1920; It also does most of the other initialisation
1921;
1922; Algorithm:
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)
1932;
1933Phase1Initialisation proc near
1934
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
1942 ;call std_printf
1943 jmp fexit
1944GotDeviceParameters:
1945
1946; Save the device parameters for when we exit
1947 lea si, deviceParameters
1948 lea di, savedDeviceParameters
1949 mov cx, size a_DeviceParameters
1950 push ds
1951 pop es
1952 rep movsb
1953
1954; Ensure that there is a valid number of sectors in the track table
1955 mov savedDeviceParameters.DP_TrackTableEntries, 0
1956 mov validSavedDeviceParameters, 1
1957
1958; Initialise this to zero to know if CheckSwitches defined the track layout
1959 mov deviceParameters.DP_TrackTableEntries, 0
1960
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.
1964SetMTsupp:
1965
1966; Check switches against parameters and use switches to modify device parameters
1967 call CheckSwitches
1968 retc
1969
1970IF ShipDisk
1971
1972 test SwitchMap,Switch_Z ;an000; dms;1 sector/cluster disk?
1973; $if nz ;an000; dms;yes
1974 JZ $$IF19
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;
1978$$IF19:
1979
1980ENDIF
1981
1982
1983 cmp deviceParameters.DP_TrackTableEntries, 0
1984 jne TrackLayoutSet ; There is a good track layout
1985
1986; Store sector table info
1987 mov cx, deviceParameters.DP_BPB.BPB_SectorsPerTrack
1988 mov deviceParameters.DP_TrackTableEntries, cx
1989 mov ax, 1
1990 mov bx, deviceParameters.DP_BPB.BPB_bytesPerSector
1991 lea di, deviceParameters.DP_SectorTable
1992LoadSectorTable:
1993 stosw
1994 xchg ax, bx
1995 stosw
1996 xchg ax, bx
1997 inc ax
1998 loop LoadSectorTable
1999TrackLayoutSet:
2000
2001;
2002; directorySector = malloc( Bytes Per Sector )
2003;
2004 mov bx, deviceParameters.DP_BPB.BPB_BytesPerSector
2005 add bx, 0fH
2006 shr bx, 1
2007 shr bx, 1
2008 shr bx, 1
2009 shr bx, 1
2010 mov ah, Alloc
2011 int 21H
2012 retc
2013 mov word ptr directorySector+2, ax
2014 xor ax,ax
2015 mov word ptr directorySector, ax
2016
2017;
2018; fatSpace = malloc( Bytes Per Sector * Sectors Per FAT )
2019;
2020 mov ax, deviceParameters.DP_BPB.BPB_BytesPerSector
2021 add ax, 0fH
2022 shr ax, 1
2023 shr ax, 1
2024 shr ax, 1
2025 shr ax, 1
2026 mul deviceParameters.DP_BPB.BPB_SectorsPerFAT
2027 mov Paras_Per_Fat,ax ;AN005;128k FAT
2028 mov bx,ax
2029 mov ah,Alloc
2030 int 21H
2031 retc
2032 mov word ptr fatSpace+2,ax
2033 xor ax,ax
2034 mov word ptr fatSpace,ax
2035
2036 call SetStartSector
2037 call SetfBigFat
2038
2039 clc
2040 return
2041
2042Phase1Initialisation endp
2043
2044;-------------------------------------------------------------------------------
2045
2046SetStartSector proc near
2047
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 )
2052
2053; Calculate the number of directory sectors
2054 mov ax, deviceParameters.DP_BPB.BPB_RootEntries
2055 mov bx, size dir_entry
2056 mul bx
2057 add ax, deviceParameters.DP_BPB.BPB_bytesPerSector
2058 dec ax
2059 xor dx,dx
2060 div deviceParameters.DP_BPB.BPB_bytesPerSector
2061 mov sectorsInRootDirectory,ax
2062 mov startSector, ax
2063
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
2069 add startSector, ax
2070
2071 return
2072
2073SetStartSector endp
2074
2075;-------------------------------------------------------------------------------
2076
2077SetfBigFat proc near
2078;
2079; fBigFat = ( ( (Total Sectors - Start Sector) / Sectors Per Cluster) >= 4086 )
2080;
2081 cmp deviceParameters.DP_BPB.BPB_BigTotalSectors+2,0 ; > 32mb part? ;AN000;
2082; $IF NE ;Yes, big FAT ;AC000;
2083 JE $$IF21
2084 mov fBigFat, TRUE ;Set flag ;AN000;
2085; $ELSE ;Nope, < 32,b ;AC000;
2086 JMP SHORT $$EN21
2087$$IF21:
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;
2091 JNE $$IF23
2092 mov ax, deviceParameters.DP_BPB.BPB_TotalSectors ; ;AC000;
2093 ;** Fix for PTM PCDOS P51
2094; $ENDIF ; ;AN000;
2095$$IF23:
2096 sub ax,startSector ;Get sectors in data area
2097 xor dx,dx
2098 xor bx,bx
2099 mov bl,deviceParameters.DP_BPB.BPB_sectorsPerCluster
2100 div bx ;Get total clusters
2101 cmp ax,BIG_FAT_THRESHOLD ;Is clusters >= 4086?
2102; $IF AE
2103 JNAE $$IF25
2104 mov fBigFAT,TRUE ;16 bit FAT if >=4096
2105 ;** END fix for PTM PCDOS P51
2106; $ENDIF
2107$$IF25:
2108; $ENDIF
2109$$EN21:
2110 return
2111
2112SetfBigFat endp
2113
2114;-------------------------------------------------------------------------------
2115;
2116; Phase2Initialisation:
2117; Use device parameters to build information that will be
2118; required for each format
2119;
2120; Algorithm:
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
2125;
2126Phase2Initialisation proc near
2127
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
2132 adc dx, 0
2133 dec ax
2134 sbb dx, 0
2135 div deviceParameters.DP_BPB.BPB_SectorsPerTrack
2136 xor dx,dx
2137 div deviceParameters.DP_BPB.BPB_Heads
2138 mov firstCylinder, ax
2139 mov firstHead, dx
2140
2141; Calculate the total number of tracks to be formatted (round down - kludge)
2142 mov ax, deviceParameters.DP_BPB.BPB_TotalSectors
2143 xor dx,dx
2144; if (TotalSectors == 0) then use BigTotalSectors
2145 or ax,ax
2146 jnz NotBigTotalSectors
2147 mov ax, deviceParameters.DP_BPB.BPB_BigTotalSectors
2148 mov dx, deviceParameters.DP_BPB.BPB_BigTotalSectors + 2
2149
2150NotBigTotalSectors:
2151 div deviceParameters.DP_BPB.BPB_SectorsPerTrack
2152 mov tracksPerDisk, ax
2153
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
2158 xor ax,ax
2159 rep stosb
2160
2161 mov ax, deviceParameters.DP_BPB.BPB_BytesPerSector
2162 xor dx, dx
2163 mov bx, size dir_entry
2164 div bx
2165 mov cx, ax
2166
2167 les bx, directorySector
2168; If Old_Dir = TRUE then put the first letter of each directory entry must be 0E5H
2169 xor al, al
2170 cmp old_Dir, TRUE
2171 jne StickE5
2172 mov al, 0e5H
2173StickE5:
2174 mov es:[bx], al
2175 add bx, size dir_entry
2176 loop stickE5
2177
2178 ret
2179
2180Phase2Initialisation endp
2181
2182;-------------------------------------------------------------------------------
2183;
2184; SetDeviceParameters:
2185; Set the device parameters
2186;
2187; Input:
2188; drive
2189; dx - pointer to device parameters
2190;
2191SetDeviceParameters proc near
2192
2193 mov ax, (IOCTL shl 8) or GENERIC_IOCTL
2194 mov bl, drive
2195 inc bl
2196 mov cx, (RAWIO shl 8) or SET_DEVICE_PARAMETERS
2197 int 21H
2198 return
2199
2200SetDeviceParameters endp
2201
2202;-------------------------------------------------------------------------------
2203;
2204; GetDeviceParameters:
2205; Get the device parameters
2206;
2207; Input:
2208; drive
2209; dx - pointer to device parameters
2210;
2211GetDeviceParameters proc near
2212
2213 mov ax, (IOCTL shl 8) or GENERIC_IOCTL
2214 mov bl, drive
2215 inc bl
2216 mov cx, (RAWIO shl 8) or GET_DEVICE_PARAMETERS
2217 int 21H
2218 return
2219
2220GetDeviceParameters endp
2221
2222;-------------------------------------------------------------------------------
2223;
2224; DiskFormat:
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
2228; if not.
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
2231; the format
2232;
2233; Algorithm:
2234; Initialise in memory FAT
2235; current track = first
2236; while not done
2237; if format track fails
2238; DiskFormatErrors = true
2239; return
2240; next track
2241
2242DiskFormat proc near
2243
2244
2245;
2246; Initialise fatSpace
2247;
2248
2249
2250 push es
2251
2252 call Fat_Init ;an000; initialize the FAT
2253
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
2258 mov ah, 0ffH
2259 stosw
2260 mov ax, 00ffH
2261 test fBigFat, TRUE
2262 jz NotBig
2263 mov ax, 0ffffH
2264NotBig: stosw
2265 pop es
2266
2267; don't bother to do the formatting if /c was given
2268 test switchmap, SWITCH_C
2269 jz Keep_Going
2270 jmp FormatDone ;FormatDone is to far away
2271
2272Keep_Going:
2273foofoo = INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD
2274 mov deviceParameters.DP_SpecialFunctions, foofoo
2275 lea dx, deviceParameters
2276
2277 call SetDeviceParameters
2278
2279 call Cluster_Buffer_Allocate ;an000; dms;get room for retry buffer
2280
2281 call Prompt_User_For_Disk ;an016; dms;
2282
2283 test switchmap,switch_8 ; DCL 5/12/86 avoid Naples AH=18h
2284 jnz stdBpB ; lackof support for 8 sectors/track
2285
2286 ; DCL 5/12/86
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
2290
2291 ;test SwitchMap, SWITCH_N or SWITCH_T ; IF ( /N or /T ) ;; DCL 5/12/86
2292 ;jz StdBPB
2293 ; THEN check if
2294 ; supported
2295 mov formatPacket.FP_SpecialFunctions, STATUS_FOR_FORMAT
2296 mov ax, (IOCTL shl 8) or GENERIC_IOCTL
2297 mov bl, drive
2298 inc bl
2299 mov cx, (RAWIO shl 8) or FORMAT_TRACK
2300 lea dx, formatPacket
2301 int 21H
2302 ; switch ( FormatStatusCall)
2303
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
2309 je NTSupported
2310 cmp FormatPacket.FP_SpecialFunctions,2
2311; $IF E ; ;AC000;
2312 JNE $$IF28
2313 Message msgInvalidParameter ; ;AC000;
2314 mov Fatal_Error,Yes ;Indicate quittin'type err! ;AN000;
2315; $ELSE ; ; ;
2316 JMP SHORT $$EN28
2317$$IF28:
2318 cmp FormatPacket.FP_SpecialFunctions,3 ; ; ;
2319; $IF E ; ;AC000;
2320 JNE $$IF30
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 ; ;
2325 JMP SHORT $$EN30
2326$$IF30:
2327 ; except for /N: & /T: ; ;
2328 test SwitchMap, SWITCH_N or SWITCH_T ; DCL 5/12/86 ; ;
2329; $IF NZ ; ;AC000;
2330 JZ $$IF32
2331 Message msgParametersNotSupported ; ;AC000;
2332 mov Fatal_Error,Yes ;Indicate quittin'type err! ;AN000;
2333; $ENDIF ; ;AN000;
2334$$IF32:
2335; $ENDIF ; ;AN000;
2336$$EN30:
2337; $ENDIF ; ;AN000;
2338$$EN28:
2339 cmp Fatal_Error,Yes ; ;AN000;
2340 jne StdBPB ; ;AN000;
2341 jmp Fexit
2342;
2343; We have the support to carry out the FORMAT
2344;
2345NTSupported:
2346StdBPB:
2347 ;call DSKPRM ; prompt user for disk ;; DCL 5/12/86
2348 mov FormatPacket.FP_SpecialFunctions, 0
2349 mov ax, firstHead
2350 mov formatPacket.FP_Head, ax
2351 mov ax, firstCylinder
2352 mov formatPacket.FP_Cylinder, ax
2353 mov cx, tracksPerDisk
2354 mov tracksLeft, cx
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
2357FormatLoop:
2358 call Format_Loop ;an015; dms;Format until CY occurs
2359
2360 cmp Format_End,True ;an015; dms;End of Format?
2361; $if e ;an015; dms;yes
2362 JNE $$IF36
2363 mov FormatError,0 ;an015; dms;signal good format
2364 clc ;an015; dms;clear CY
2365; $else ;an015; dms;bad format
2366 JMP SHORT $$EN36
2367$$IF36:
2368 call CheckError ;an015; dms;determine type of error
2369; $if nc ;an015; dms;
2370 JC $$IF38
2371 call LastChanceToSaveIt ;an015; dms;acceptable error?
2372; $if c ;an015; dms;yes
2373 JNC $$IF39
2374 mov FormatError,1 ;an015; dms;signal error type
2375 clc ;an015; dms;clear CY
2376; $else ;an015; dms;not acceptable error
2377 JMP SHORT $$EN39
2378$$IF39:
2379 call SetStartSector ;an015; dms;start from scratch
2380 call SetFBigFat ;an015; dms;
2381 push ax ;an015; dms;
2382 call Phase2Initialisation ;an015; dms;
2383 clc ;an015; dms;
2384 pop ax ;an015; dms;
2385 jmp DiskFormat ;an015; dms;try again
2386; $endif ;an015; dms;
2387$$EN39:
2388; $endif ;an015; dms;
2389$$IF38:
2390; $endif ;an015; dms;
2391$$EN36:
2392 return
2393
2394FormatDone:
2395 mov FormatError,0
2396 clc
2397 return
2398
2399DiskFormat endp
2400
2401
2402;-------------------------------------------------------------------------------
2403;
2404; BadSector:
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,
2408; and reports that.
2409;
2410; Output:
2411; Carry: set --> fatal error
2412; if Carry not set
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
2416;
2417; Algorithm:
2418; if DiskFormatErrors
2419; DiskFormatErrors = false
2420; return current track
2421; else
2422; next track
2423; while not done
2424; if format track fails
2425; return current track
2426; next track
2427; return 0
2428
2429BadSector proc near
2430
2431
2432; don't bother to do the formatting if /c was given
2433 test switchmap, SWITCH_C
2434 jnz NoMoreTracks
2435
2436 test formatError, 0ffH
2437 jz ContinueFormat
2438 mov formatError, 0
2439 jmp ReportBadTrack
2440
2441ContinueFormat:
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
2446 JE $$IF44
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
2450 JE $$IF45
2451 call CheckError ;an015; dms;must be error - which error?
2452; $if nc ;an015; dms;non-fatal error?
2453 JC $$IF46
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;
2458$$IF46:
2459; $else ;an015; dms;
2460 JMP SHORT $$EN45
2461$$IF45:
2462 jmp NoMoreTracks ;an015; dms;end of format
2463; $endif ;an015; dms;
2464$$EN45:
2465; $else ;an015; dms;
2466 JMP SHORT $$EN44
2467$$IF44:
2468 jmp NoMoreTracks ;an015; dms;end of format
2469; $endif ;an015; dms;
2470$$EN44:
2471 return ;an015; dms;
2472
2473ReportBadTrack:
2474 call CurrentLogicalSector
2475 mov ax, deviceParameters.DP_BPB.BPB_SectorsPerTrack
2476 clc
2477 return
2478
2479NoMoreTracks:
2480 test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display done msg;AN000;
2481; $IF Z ; if EXEC'd by SELECT ;AN000;
2482 JNZ $$IF52
2483 Message msgFormatComplete ; ;AC000;
2484; $ENDIF ; ;AN000;
2485$$IF52:
2486 mov ax, 0
2487 clc
2488 return
2489
2490BadSector endp
2491
2492
2493
2494;-------------------------------------------------------------------------------
2495
2496data segment public para 'DATA'
2497
2498;ptr_msgCurrentTrack dw offset msgCurrentTrack
2499currentHead dw 0
2500currentCylinder dw 0
2501
2502data ends
2503
2504;=========================================================================
2505; Calc_Current_Head_Cyl : Obtain the current head and cylinder of the
2506; track being formatted.
2507;
2508; Inputs: FP_Cylinder - Cylinder of track being formatted
2509; FP_Head - Head of track being formatted
2510;=========================================================================
2511
2512Procedure Calc_Current_Head_Cyl ;an000; dms;
2513
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
2520 ret ;an000; dms;
2521
2522Calc_Current_Head_Cyl endp ;an000; dms;
2523
2524
2525DisplayCurrentTrack proc near
2526
2527 push dx ; ;AN000;
2528 push cx ; ;AN000;
2529 push ax ;an015; dms;
2530
2531 mov ax,Tracks_To_Format ;an015; dms;get track count
2532
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;
2543 JE $$IF54
2544 mov PercentComplete,ax ;Save it if changed ;AN000;
2545 Message msgCurrentTrack ; ;AC000;
2546; $ENDIF ;
2547$$IF54:
2548 pop ax ;an015; dms;
2549 pop cx ;Restore register ;AN000;
2550 pop dx ; ;AN000;
2551 return
2552
2553DisplayCurrentTrack endp
2554
2555
2556;-------------------------------------------------------------------------------
2557; CheckError:
2558; Input:
2559; ax - extended error code
2560; Ouput:
2561; carry set if error is fatal
2562; Message printed if Not Ready or Write Protect
2563;
2564CheckError proc near
2565 cmp ax, error_write_protect
2566 je WriteProtectError
2567 cmp ax, error_not_ready
2568 je NotReadyError
2569 cmp currentCylinder, 0
2570 jne CheckRealErrors
2571 cmp currentHead, 0
2572 je BadTrackZero
2573
2574CheckRealErrors:
2575 cmp ax, error_CRC
2576 je JustABadTrack
2577 cmp ax, error_sector_not_found
2578 je JustABadTrack
2579 cmp ax, error_write_fault
2580 je JustABadTrack
2581 cmp ax, error_read_fault
2582 je JustABadTrack
2583 cmp ax, error_gen_failure
2584 je JustABadTrack
2585
2586 stc
2587 ret
2588
2589JustABadTrack:
2590 clc
2591 ret
2592
2593WriteProtectError:
2594
2595 test SwitchMap,Switch_SELECT ;an017; dms;SELECT option?
2596; $if z ;an017; dms;no - display messages
2597 JNZ $$IF56
2598 Message msgCRLF ; ;AC006;
2599 Message msgCRLF ; ;AC006;
2600 Extended_Message ; ;AC006;
2601; $else ;an017; dms;yes - set error level
2602 JMP SHORT $$EN56
2603$$IF56:
2604 mov ExitStatus,ExitWriteProtect ;an017; dms;signal write protect error
2605; $endif ;an017; dms;
2606$$EN56:
2607
2608 stc ;an017; dms;signal fatal error
2609 ret ;an017; dms;return to caller
2610
2611NotReadyError:
2612 test SwitchMap,Switch_SELECT ;an017; dms; SELECT option?
2613; $if z ;an017; dms; no - display messages
2614 JNZ $$IF59
2615 Message msgCRLF ; ;AC006;
2616 Message msgCRLF ; ;AC006;
2617 Extended_Message ; ;AC006;
2618; $else ;an017; dms;yes - set error level
2619 JMP SHORT $$EN59
2620$$IF59:
2621 mov ExitStatus,ExitDriveNotReady ;an017; dms;signal drive not ready
2622; $endif ;an017; dms;
2623$$EN59:
2624 stc
2625 ret
2626
2627
2628BadTrackZero:
2629 Message msgDiskUnusable ; ;AC000;
2630 stc
2631 ret
2632
2633CheckError endp
2634
2635;-------------------------------------------------------------------------------
2636; WriteFileSystem:
2637; Write the boot sector and FATs out to disk
2638; Clear the directory sectors to zero
2639;
2640
2641WriteFileSystem proc near
2642
2643
2644 call WriteBootSector
2645 retc
2646
2647 Set_Data_Segment ;Set DS,ES = DATA ;AN000;
2648; Write out each of the FATs
2649 push ds ;ac005; dms;save ds
2650 xor cx, cx
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;
2655 mov ds,bx ; ;AN000;
2656 mov bx,word ptr es:FatSpace ; ;AN000;
2657
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;
2662
2663; $do ;ac005; dms;while FATS > 0
2664$$DO62:
2665 cmp cx,00 ;ac005; dms;FATS remaining?
2666; $leave e ;ac005; dms;no
2667 JE $$EN62
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
2678 JNC $$IF64
2679 Message msgFATwriteError;ac005; dms;say why failed
2680 jmp FEXIT ;ac005; dms;exit format
2681; $endif ;ac005; dms;
2682$$IF64:
2683 add dx, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000;
2684 dec cx ;ac005; dms;decrease FAT count
2685; $enddo ;ac005; dms;
2686 JMP SHORT $$DO62
2687$$EN62:
2688
2689 pop ds ;ac005; dms;restore ds
2690 assume ds:data ;ac005; dms;
2691
2692
2693; Clear the directory
2694
2695; Now write the initialised directory sectors out to disk
2696 mov ax, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000;
2697 xor dx,dx
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
2703
2704 mov dx, es:deviceParameters.DP_BPB.BPB_ReservedSectors ; ;AC000;
2705 add dx, ax
2706 mov cx, es:sectorsInRootDirectory ; ;AC000;
2707WriteDIRloop:
2708 push cx
2709 push dx
2710 mov al, es:drive ; ;AC000;
2711 mov cx, 1
2712 lds bx, es:directorySector ; ;AC000;
2713
2714 assume ds:nothing,es:data ; ;AN000;
2715
2716;Assume dir is alway contined in first 32mb of partition
2717
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;
2722 jmp FExit ; ;AN000;
2723Dir_OK: ; ;AN000;
2724 pop dx
2725 add dx, 1
2726 pop cx
2727 loop WriteDIRLoop
2728
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
2735
2736 MOV AH,DISK_RESET ; Flush any directories in
2737 INT 21H ; buffers
2738
2739 return
2740
2741
2742WriteFileSystem endp
2743
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.
2749;
2750; Inputs : AL - Drive letter
2751; DS:BX - Segment:offset of transfer address
2752; CX - Sector count
2753; DX - 1st. sector
2754;
2755; Outputs : Logical sectors written
2756;=========================================================================
2757
2758procedure write_fat
2759
2760 mov cx, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000;
2761
2762; $do ;an000;while sectors left
2763$$DO67:
2764 cmp cx,00h ;an000;any sectors?
2765; $leave e ;an000;no
2766 JE $$EN67
2767
2768 cmp cx,40h
2769; $if a ;an000;yes
2770 JNA $$IF69
2771 push cx ;an000;save cx
2772 mov cx,40h
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
2778 mov si,8000h
2779 call seg_adj ;an000;adjust segment
2780 mov bx,si ;an000;new offset
2781 add dx,40h
2782 sub cx,40h
2783; $else ;an000;< 64k
2784 JMP SHORT $$EN69
2785$$IF69:
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
2790; $endif
2791$$EN69:
2792; $enddo
2793 JMP SHORT $$DO67
2794$$EN67:
2795
2796 Write_Exit:
2797
2798 ret
2799
2800write_fat endp
2801
2802;=========================================================================
2803; SEG_ADJ : This routine adjusts the segment:offset to prevent
2804; address wrap.
2805;
2806; Inputs : SI - Offset to adjust segment with
2807; DS - Segment to be adjusted
2808;
2809; Outputs : SI - New offset
2810; DS - Adjusted segment
2811;=========================================================================
2812
2813procedure seg_adj
2814
2815 push ax
2816 push cx
2817 push dx
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?
2823 JNC $$IF73
2824 adc bx,0 ;an000;pick it up
2825; $endif ;an000;
2826$$IF73:
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
2831 pop dx
2832 pop cx
2833 pop ax
2834 ret
2835
2836seg_adj endp
2837
2838;-------------------------------------------------------------------------------
2839; format is done... so clean up the disk!
2840;
2841Done proc near
2842
2843
2844 call OemDone
2845 return
2846
2847Done endp
2848
2849;-------------------------------------------------------------------------------
2850; CurrentLogicalSector:
2851; Get the current logical sector number
2852;
2853; Input:
2854; current track = tracksPerDisk - tracksLeft
2855; SectorsPerTrack
2856;
2857; Output:
2858; BX = logical sector number of the first sector in the track we
2859; just tried to format
2860;
2861CurrentLogicalSector proc near
2862
2863 push ax ;an000; dms;save regs
2864 push bx ;an000; dms;
2865 push dx ;an000; dms;
2866
2867 mov ax, tracksPerDisk
2868 sub ax, tracksLeft
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 #
2873
2874 pop dx ;an000; dms;restore regs
2875 pop bx ;an000; dms;
2876 pop ax ;an000; dms;
2877
2878 return
2879
2880CurrentLogicalSector endp
2881
2882;-------------------------------------------------------------------------------
2883; PrintErrorAbort:
2884; Print an error message and abort
2885;
2886; Input:
2887; dx - Pointer to error message string
2888;
2889PrintErrorAbort proc near
2890
2891 push dx
2892 call crlf
2893 pop dx
2894 call PrintString
2895
2896 jmp fexit
2897
2898PrintErrorAbort endp
2899
2900
2901
2902
2903;*****************************************************************************
2904;Routine name: Multiply_32_Bits
2905;*****************************************************************************
2906;
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
2918; occurs.
2919;
2920;
2921;Called Procedures: None
2922;
2923;Change History: Created 7/23/87 MT
2924;
2925;Input: BX:AX = 32 bit number to be multiplied
2926; CX = 16 bit number to be multiplied. (Must be even number)
2927;
2928;Output: BX:AX = output.
2929; CY set if overflow
2930;
2931;Psuedocode
2932;----------
2933;
2934; Point at ControlC_Handler routine
2935; Set interrupt handler (INT 21h, AX=2523h)
2936; ret
2937;*****************************************************************************
2938
2939Public Multiply_32_Bits
2940Multiply_32_Bits proc ; ;AN000;
2941
2942 push di ; ;AN000;
2943 push si ; ;AN000;
2944 xor di,di ;Init result to zero
2945 xor si,si ;
2946 cmp cx,0 ;Multiply by 0? ;AN000;
2947; $IF NE ;Keep going if not ;AN000;
2948 JE $$IF75
2949; $DO ;This works by adding the result;AN000;
2950$$DO76:
2951 test cx,1 ;Need to add in sum of this bit?;AN000;
2952; $IF NZ ;Yes ;AN000;
2953 JZ $$IF77
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;
2957 JMP SHORT $$EN77
2958$$IF77:
2959 clc ;Force non exit ;AN000;
2960; $ENDIF ; ;AN000;
2961$$EN77:
2962; $LEAVE C ;Leave on overflow ;AN000;
2963 JC $$EN76
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;
2967 JE $$EN76
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;
2971 JNC $$DO76
2972$$EN76:
2973; $IF NC ;If no overflow, add in DI:SI ;AN000;
2974 JC $$IF83
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;
2978; $ENDIF ; ;AN000;
2979$$IF83:
2980; $ELSE ;
2981 JMP SHORT $$EN75
2982$$IF75:
2983 xor ax,ax ;
2984 xor bx,bx ;
2985; $ENDIF ;Multiply by 0 ;AN000;
2986$$EN75:
2987 pop si ; ;AN000;
2988 pop di ; ;AN000;
2989 ret ; ;AN000;
2990
2991Multiply_32_Bits endp
2992
2993
2994;=========================================================================
2995; Divide_32_Bits - This routine will perform 32bit division
2996;
2997; Inputs : SI:DI - value to be divided
2998; CX - divisor
2999;
3000; Outputs : SI:DI - result
3001; CX - remainder
3002;=========================================================================
3003
3004Procedure Divide_32_Bits ;an000; dms;
3005
3006 push ax ;an000; dms;save regs
3007 push bx ;an000; dms;
3008 push dx ;an000; dms;
3009
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
3014
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
3019
3020 pop dx ;an000; dms;restore regs
3021 pop bx ;an000; dms;
3022 pop ax ;an000; dms;
3023
3024 ret ;an000; dms;
3025
3026Divide_32_Bits endp ;an000; dms;
3027
3028
3029
3030
3031;=========================================================================
3032; FAT_INIT: This routine initializes the FAT based on the
3033; number of paragraphs.
3034;
3035;
3036; input - fatspace
3037; fatspace+2
3038; paras_per_fat
3039; fat_init_value
3040; output - fat space is initialized
3041;
3042;=========================================================================
3043Public Fat_Init
3044Fat_Init proc near
3045
3046 push es
3047 push di
3048 push ax
3049 push bx
3050 push cx
3051 mov di, word ptr FatSpace+2 ;Get segment of Fat space ;AC000;
3052 mov es,di ; ;AN000;
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
3058; $do
3059$$DO87:
3060 cmp bx,0 ;an000;do while bx not = 0
3061; $leave e ;an000;exit if 0
3062 JE $$EN87
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
3069; $enddo ;an000;
3070 JMP SHORT $$DO87
3071$$EN87:
3072 pop dx ;an000;
3073 pop cx ;an000;
3074 pop bx ;an000;
3075 pop ax ;an000;
3076 pop di ;an000;
3077 pop es ;an000;
3078
3079 ret ;an000;
3080
3081Fat_Init endp ;an000;
3082
3083
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;=========================================================================
3090
3091Ctrl_Break_Write: ;ac010; dms;
3092
3093 iret ;ac010; dms;return to caller
3094
3095
3096;=========================================================================
3097; Ctrl_Break_Save : This routine gets the current vector of
3098; INT 23h and saves it in CTRL_BREAK_VECTOR.
3099;
3100; Inputs : none
3101;
3102; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine
3103;=========================================================================
3104
3105Ctrl_Break_Save proc near ;ac010; dms;
3106
3107 push es ;ac010; dms;save es
3108 push bx ;ac010; dms;save bx
3109 push ax ;ac010; dms;save ax
3110
3111 mov ax,3523h ;ac010; dms;get CTRL-BREAK
3112 ; interrupt vector
3113 int 21h ;ac010; dms;
3114
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
3117
3118 pop ax ;ac010; dms;restore ax
3119 pop bx ;ac010; dms;restore bx
3120 pop es ;ac010; dms;restore es
3121
3122 ret ;ac010; dms;
3123
3124
3125Ctrl_Break_Save endp ;ac010; dms;
3126
3127
3128;=========================================================================
3129; Set_Ctrl_Break : This routine sets the CTRL-Break vector to one
3130; defined by the user.
3131;
3132; Inputs : none
3133;
3134; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine
3135;=========================================================================
3136
3137Set_Ctrl_Break proc near ;ac010; dms;
3138
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
3143
3144 push cs ;ac010; dms;swap cs with ds
3145 pop ds ;an000; dms;point to code seg
3146
3147 mov dx,offset Ctrl_Break_Write ;ac010; dms;get interrupt vec.
3148 mov ax,2523h ;ac010; dms;set CTRL-BREAK
3149 ; interrupt vector
3150 int 21h ;ac010; dms;
3151
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
3156
3157 ret ;ac010; dms;
3158
3159
3160Set_Ctrl_Break endp ;ac010; dms;
3161
3162
3163;=========================================================================
3164; Reset_Ctrl_Break : This routine resets the CTRL-Break vector to that
3165; originally defined.
3166;
3167; Inputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine
3168;
3169; Outputs : none
3170;=========================================================================
3171
3172Reset_Ctrl_Break proc near ;ac010; dms;
3173
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
3178
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
3184 ; interrupt vector
3185 int 21h ;ac010; dms;
3186
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
3191
3192 ret ;ac010; dms;
3193
3194
3195Reset_Ctrl_Break endp ;ac010; dms;
3196
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
3202; CommandFile.
3203;
3204; Inputs : Exec_Block.Segment_Env - Segment of environmental vector
3205; Comspec_ID - "COMSPEC="
3206;
3207; Outputs : CommandFile - Holds path to COMMAND.COM
3208;=========================================================================
3209
3210Procedure Get_Command_Path ;an011; dms;
3211
3212 push ds ;an011; dms;save ds
3213 push es ;an011; dms;save es
3214
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
3219 ; environ. vector
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
3227$$DO90:
3228 ; and target not found
3229 cmp cx,00h ;an011; dms; end of env.?
3230; $leave e ;an011; dms; yes
3231 JE $$EN90
3232
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
3238 JNZ $$IF92
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
3246 JNE $$IF93
3247; $do ;an011; dms; while AL not = 0
3248$$DO94:
3249 cmp al,00h ;an011; dms; at end?
3250; $leave e ;an011; dms; yes
3251 JE $$EN94
3252 stosb ;an011; dms; save it
3253 lodsb ;an011; dms; get character
3254; $enddo
3255 JMP SHORT $$DO94
3256$$EN94:
3257; $endif ;an011; dms;
3258$$IF93:
3259 pop di ;an011; dms; restore di
3260 mov cx,0ffffh ;an011; dms; flag target found
3261; $endif ;an011; dms;
3262$$IF92:
3263
3264 cmp cx,0ffffh ;an011; dms; target found?
3265; $leave e ;an011; dms; yes
3266 JE $$EN90
3267
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
3272
3273 dec cx ;an011; dms; decrease counter
3274; $enddo ;an011; dms;
3275 JMP SHORT $$DO90
3276$$EN90:
3277
3278 pop es ;an011; dms; restore es
3279 pop ds ;an011; dms; restore ds
3280
3281 ret ;an011; dms;
3282
3283Get_Command_Path endp ;an011; dms;
3284
3285
3286;
3287;****************************************************************************
3288; Get_PSP_Parms
3289;****************************************************************************
3290;
3291;
3292;
3293;
3294
3295Procedure Get_PSP_Parms ; ;AC000;
3296
3297 Set_Data_Segment
3298 mov ax,PSP_Segment ;Get segment of PSP ;AN000;
3299 mov ds,ax ; " " " " ;AN000;
3300 ; ;
3301 assume ds:nothing
3302 ;Setup segment of Environment string, get from PSP ; ;
3303
3304 mov ax,ds:PSP_Environ ; ; ;
3305 mov es:Environ_Segment,ax ; ; ;
3306 Set_Data_Segment
3307 ret ; ; ;
3308
3309
3310Get_PSP_Parms endp ; ;AN000;
3311
3312
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.
3320;
3321; Inputs : CommandFile - Holds full path to default COMMAND.COM
3322; Outputs : CommandFile - Holds modified path to new COMMAND.COM
3323; on target drive.
3324;=========================================================================
3325
3326Procedure Command_Root ;an011; dms;
3327
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;
3334
3335 mov di,offset CommandFile+3 ;an011; dms; point to path
3336 ; past drive spec
3337 mov si,offset Command_Com ;an011; dms; holds the literal
3338 ; COMMAND.COM
3339 mov cx,000ch ;an011; dms; len. of literal
3340 rep movsb ;an011; dms; move it
3341
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
3347
3348 ret ;an011; dms;
3349
3350Command_Root endp ;an011; dms;
3351
3352
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.
3357;
3358; Inputs : DeviceParameters
3359;
3360; Outputs : BPB information
3361;=========================================================================
3362
3363Procedure Set_BPB_Info ;an012; dms;calc new BPB
3364
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
3368 JNE $$IF101
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
3373
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
3379
3380 cmp bl,FBIG ;an012; dms;Big FAT?
3381; $if e ;an012; dms;yes
3382 JNE $$IF102
3383 call Calc_Big_FAT ;an012; dms;calc big FAT info
3384; $else ;an012; dms;
3385 JMP SHORT $$EN102
3386$$IF102:
3387 call Calc_Small_FAT ;an012; dms;calc small FAT info
3388; $endif ;an012; dms;
3389$$EN102:
3390; $endif ;an012; dms;
3391$$IF101:
3392
3393 ret ;an012; dms;
3394
3395Set_BPB_Info endp ;an012; dms;
3396
3397
3398
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.
3404;
3405; Inputs : DiskTable - Contains data about disk types
3406;
3407; Outputs : DS:SI - Points to applicable disk data
3408;=========================================================================
3409
3410Procedure Scan_Disk_Table ;an012; dms;
3411
3412 cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk?
3413; $if ne ;an012; dms;yes
3414 JE $$IF106
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;
3418 JMP SHORT $$EN106
3419$$IF106:
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;
3423$$EN106:
3424
3425 mov si,offset DiskTable ;an012; dms;point to disk data
3426Scan:
3427
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
3433
3434Scan_Next:
3435
3436 add si,5*2 ;an012; dms;adjust pointer
3437 jmp Scan ;an012; dms;continue scan
3438
3439Scan_Disk_Table_Exit:
3440
3441 ret ;an012; dms;
3442
3443Scan_Disk_Table endp ;an012; dms;
3444
3445
3446
3447;=========================================================================
3448; Calc_Big_FAT : Calculates the sectors per FAT for a 16 bit FAT.
3449;
3450; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or
3451; DeviceParameters.DP_BPB.BPB_TotalSectors
3452;
3453; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat
3454;=========================================================================
3455
3456Procedure Calc_Big_FAT ;an012; dms;
3457
3458 cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk?
3459; $if ne ;an012; dms;yes
3460 JE $$IF109
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;
3464 JMP SHORT $$EN109
3465$$IF109:
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;
3469$$EN109:
3470
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
3489 ret ;an012; dms;
3490
3491Calc_Big_FAT endp ;an012; dms;
3492
3493
3494;=========================================================================
3495; Calc_Small_FAT: Calculates the sectors per FAT for a 12 bit FAT.
3496;
3497; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or
3498; DeviceParameters.DP_BPB.BPB_TotalSectors
3499;
3500; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat
3501;=========================================================================
3502
3503Procedure Calc_Small_FAT ;an012; dms;
3504
3505 cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk?
3506; $if ne ;an012; dms;yes
3507 JE $$IF112
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;
3511 JMP SHORT $$EN112
3512$$IF112:
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;
3516$$EN112:
3517
3518 xor bx,bx ;an012; dms;clear bx
3519 mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an012; dms;get sectors/cluster
3520 div bx ;an012; dms;
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;
3525 div bx ;an012; dms;
3526 xor dx,dx ;an012; dms;
3527; now divide by 512
3528 mov bx,512 ;an012; dms;
3529 div bx ;an012; dms;
3530 inc ax ;an012; dms;
3531; dx:ax contains number of FAT sectors necessary
3532 mov DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax ;an012; dms;save sectors/FAT
3533 ret ;an012; dms;
3534
3535Calc_Small_FAT endp ;an012; dms;
3536
3537;=========================================================================
3538; Get_Bad_Sector_Hard : Determine the bad sector.
3539;
3540; Inputs : Head of failing track
3541; Cylinder of failing track
3542; Relative_Sector_Low - 1st. sector in track
3543; Relative_Sector_High
3544;
3545; Cluster_Boundary_Adj_Factor - The number of sectors
3546; that are to be read
3547; at one time.
3548; Cluster_Boundary_SPT_Count - Used by Calc_Cluster_Boundary
3549; to track how many sectors
3550; have been read.
3551; Cluster_Boundary_Flag - True (Use cluster buffer)
3552; - False (Use internal buffer)
3553; Cluster_Boundary_Buffer_Seg - Segment of buffer
3554;
3555; Outputs : Marked cluster as bad
3556;=========================================================================
3557
3558Procedure Get_Bad_Sector_Hard ;an000; dms;
3559
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
3565$$DO115:
3566 cmp cx,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;at end?
3567; $leave a ;an000; dms;yes,exit
3568 JA $$EN115
3569 push cx ;an000; dms;save cx
3570
3571 cmp Cluster_Boundary_Flag,True ;an000; dms;full buffer there?
3572; $if e ;an000; dms;yes
3573 JNE $$IF117
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
3579 JMP SHORT $$EN117
3580$$IF117:
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;
3584$$EN117:
3585
3586 call Verify_Structure_Set_Up ;an019; dms; set up verify vars
3587
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;
3595
3596 pop cx ;an000; dms;restore cx
3597
3598 push cx ;an000; dms;save cx
3599
3600; $if c ;an000; dms;an error occurred
3601 JNC $$IF120
3602 call Calc_Cluster_Position ;an000; dms;determine which cluster
3603 call BadClus ;an000; dms;mark the cluster as bad
3604; $endif ;an000; dms;
3605$$IF120:
3606
3607 pop cx ;an000; dms;restore cx
3608
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
3616
3617
3618; $enddo ;an000; dms;
3619 JMP SHORT $$DO115
3620$$EN115:
3621
3622 pop cx ;an000; dms;restore cx
3623
3624 ret ;an000; dms;
3625
3626Get_Bad_Sector_Hard endp ;an000; dms;
3627
3628
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;=========================================================================
3636
3637Procedure Verify_Structure_Set_Up ;an019; dms;set up verify structure
3638
3639 mov RWPacket.TRWP_SpecialFunctions,00h ;an000; dms;reset special functions
3640
3641 mov ax,FormatPacket.FP_Head ;an000; dms;get current head
3642 mov RWPacket.TRWP_Head,ax ;an000; dms;get current head
3643
3644 mov ax,FormatPacket.FP_Cylinder ;an000; dms;get current cylinder
3645 mov RWPacket.TRWP_Cylinder,ax ;an000; dms;get current cylinder
3646
3647 dec cx ;an000; dms;make sector 0 based
3648 mov RWPacket.TRWP_FirstSector,cx ;an000; dms;get sector to read
3649
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)
3652
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
3656 message MsgVerify
3657
3658 ret
3659
3660Verify_Structure_Set_Up endp ;an019; dms;
3661
3662
3663;=========================================================================
3664; Get_Bad_Sector_Floppy : This routine marks an entire track as bad
3665; since it is a floppy disk.
3666;
3667; Inputs : Relative_Sector_Low - first sector
3668;
3669; Outputs : FAT marked with bad sectors
3670;=========================================================================
3671
3672Procedure Get_Bad_Sector_Floppy ;an000; dms;
3673
3674 push bx ;an000; dms;save regs
3675 push cx ;an000; dms;
3676
3677 mov cx,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;get sectors/track
3678; $do ;an000; dms;while sectors left
3679$$DO123:
3680 cmp cx,00 ;an000; dms;at end
3681; $leave e ;an000; dms;yes
3682 JE $$EN123
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
3688 pop bx ;an000; dms;
3689 dec cx ;an000; dms;decrease loop counter
3690 inc Relative_Sector_Low ;an000; dms;next sector
3691; $enddo ;an000; dms;
3692 JMP SHORT $$DO123
3693$$EN123:
3694
3695 pop cx ;an000; dms;restore regs
3696 pop bx ;an000; dms;
3697
3698 ret ;an000; dms;
3699
3700Get_Bad_Sector_Floppy endp ;an000; dms;
3701
3702
3703;=========================================================================
3704; Calc_Cluster_Position : This routine calculates which cluster the
3705; failing sector falls in.
3706;
3707; Inputs : Relative_Sector_High - high word of sector position
3708; Relative_Sector_Low - low word of sector position
3709;
3710; Outputs : DX:AX - Cluster position
3711;=========================================================================
3712Procedure Calc_Cluster_Position ;an000; dms;
3713
3714 push cx ;an000; dms;save regs
3715 push di ;an000; dms;
3716 push si ;an000; dms;
3717
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
3723
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
3729
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
3734
3735 pop si ;an000; dms;restore regs
3736 pop di ;an000; dms;
3737 pop cx ;an000; dms;
3738
3739 ret ;an000 ;dms;
3740
3741Calc_Cluster_Position endp ;an000; dms;
3742
3743
3744;=========================================================================
3745; Cap_Char : This routine will capitalize the character passed in
3746; DL.
3747;
3748; Inputs : DL - Character to be capitalized
3749;
3750; Outputs : DL - Capitalized character
3751;=========================================================================
3752
3753Procedure Cap_Char ;an011; dms;
3754
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
3759 ret ;an011; dms;
3760
3761Cap_Char endp ;an011; dms;
3762
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.
3767;
3768; Inputs : DX - pointer to buffer
3769;
3770;=========================================================================
3771
3772Procedure Set_Disk_Access_On_Off ;an014; dms;
3773
3774 push ax ;an014; dms;save regs
3775 push bx ;an014; dms;
3776 push cx ;an014; dms;
3777 push dx ;an014; dms;
3778
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
3784 JNC $$IF126
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;
3792$$IF126:
3793
3794 pop dx ;an014; dms;restore regs
3795 pop cx ;an014; dms;
3796 pop bx ;an014; dms;
3797 pop ax ;an014; dms;
3798
3799 ret ;an014; dms;
3800
3801Set_Disk_Access_On_Off endp ;an014; dms;
3802
3803
3804;=========================================================================
3805; Get_Disk_Access : This routine will determine the access state of
3806; the disk.
3807;
3808; Inputs : DX - pointer to buffer
3809; Outputs : Disk_Access.DAC_Access_Flag - 0ffh signals access allowed
3810; to the disk previously.
3811;
3812;=========================================================================
3813
3814Procedure Get_Disk_Access ;an014; dms;
3815
3816 push ax ;an014; dms;save regs
3817 push bx ;an014; dms;
3818 push cx ;an014; dms;
3819 push dx ;an014; dms;
3820
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
3826 JNC $$IF128
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
3836 JNE $$IF129
3837 mov Disk_Access.DAC_Access_Flag,0ffh ;an014; dms;signal access is currently allowed
3838; $endif ;an014; dms;
3839$$IF129:
3840; $endif ;an014; dms;
3841$$IF128:
3842
3843 pop dx ;an014; dms;restore regs
3844 pop cx ;an014; dms;
3845 pop bx ;an014; dms;
3846 pop ax ;an014; dms;
3847
3848 ret ;an014; dms;
3849
3850Get_Disk_Access endp ;an014; dms;
3851
3852;=========================================================================
3853; Calc_Cluster_Boundary : This routine will determine where, within a
3854; cluster, a sector resides.
3855;
3856; Inputs : Relative_Sector_Low - Sector
3857; Relative_Sector_High
3858;
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
3863; a track.
3864;=========================================================================
3865
3866Procedure Calc_Cluster_Boundary ;an000; dms;
3867
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;
3874
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
3880
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
3886
3887 or cx,cx ;an000; dms;see if remainder exists
3888; $if nz ;an000; dms;remainder exists
3889 JZ $$IF132
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
3895 JMP SHORT $$EN132
3896$$IF132:
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;
3901$$EN132:
3902
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
3908 JNA $$IF135
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;
3913$$IF135:
3914
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
3919
3920 pop di ;an000; dms;restore regs
3921 pop si ;an000; dms;
3922 pop dx ;an000; dms;restore regs
3923 pop cx ;an000; dms;
3924 pop bx ;an000; dms;
3925 pop ax ;an000; dms;
3926
3927 ret ;an000; dms;
3928
3929Calc_Cluster_Boundary endp ;an000; dms;
3930
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.
3937;
3938; Inputs : DeviceParameters.DP_BPB.BPB_BytesPerSector
3939; DeviceParameters.DP_BPB.BPB_SectorsPerCluster
3940;
3941; Outputs : Cluster_Boundary_Flag - True (space available)
3942; False(not enough space)
3943; Cluster_Boundary_Buffer_Seg - Pointer to buffer
3944;=========================================================================
3945
3946Procedure Cluster_Buffer_Allocate ;an000; dms;
3947
3948 push ax ;an000; dms;save regs
3949 push bx ;an000; dms;
3950 push cx ;an000; dms;
3951 push dx ;an000; dms;
3952
3953 mov ax,(Alloc shl 8) ;an000; dms;allocate memory
3954 mov bx,0ffffh ;an000; dms;get available memory
3955 int 21h ;an000; dms;
3956
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
3965
3966 cmp bx,ax ;an000; dms;enough room
3967; $if a ;an000; dms;yes
3968 JNA $$IF137
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
3975 JMP SHORT $$EN137
3976$$IF137:
3977 mov Cluster_Boundary_Flag,False ;an000; dms;signal not enough space
3978; $endif ;an000; dms;
3979$$EN137:
3980
3981 pop dx ;an000; dms;restore regs
3982 pop cx ;an000; dms;
3983 pop bx ;an000; dms;
3984 pop ax ;an000; dms;
3985
3986 ret ;an000; dms;
3987
3988Cluster_Buffer_Allocate endp ;an000; dms;
3989
3990
3991;=========================================================================
3992; Set_CDS_Off - This routine disallows access to a
3993; disk if a format fails on a non-FAT
3994; formatted disk.
3995;
3996;=========================================================================
3997
3998Procedure Set_CDS_Off ;an000; dms;
3999
4000 push ax ;an000; dms;save regs
4001 push dx ;an000; dms;
4002
4003 mov ax,5f08h ;an000; dms;reset CDS
4004 mov dl,Drive ;an000; dms;drive to reset
4005 int 21h ;an000; dms;
4006
4007 pop dx ;an000; dms;restore regs
4008 pop ax ;an000; dms;
4009
4010 ret ;an000; dms;
4011
4012Set_CDS_Off endp ;an000; dms;
4013
4014
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
4019; format.
4020;
4021;=========================================================================
4022
4023Procedure Format_Access_Wrap_Up ;an000; dms;
4024
4025 cmp Disk_Access.DAC_Access_Flag,0ffh ;an015; dms;access prev. allowed?
4026; $if ne ;an015; dms;no
4027 JE $$IF140
4028 cmp ExitStatus,ExitOK ;an015; dms;good exit?
4029; $if ne ;an015; dms;no
4030 JE $$IF141
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
4035 JMP SHORT $$EN141
4036$$IF141:
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;
4041$$EN141:
4042; $endif ;an015; dms;
4043$$IF140:
4044
4045 cmp FAT_Flag,No ;an012; dms;non-FAT format?
4046; $if e ;an012; dms;yes
4047 JNE $$IF145
4048 cmp ExitStatus,ExitOK ;an012; dms;good exit?
4049; $if ne ;an012; dms;no
4050 JE $$IF146
4051 call Set_CDS_Off ;an012; dms;disallow FAT access
4052; $endif ;an012; dms;
4053$$IF146:
4054; $endif ;an012; dms;
4055$$IF145:
4056
4057 ret ;an000; dms;
4058
4059Format_Access_Wrap_Up endp ;an000; dms;
4060
4061;=========================================================================
4062; BadClus_Address_Adjust - This routine adjusts the segment and
4063; offset to provide addressibility into
4064; the FAT table.
4065;
4066; Inputs : bx - high word to adjust segment for
4067; ax - low word to adjust segment for
4068; cx - segment to be adjusted
4069;
4070; Outputs : cx - new segment value
4071; ax - new offset value
4072;=========================================================================
4073
4074Procedure BadClus_Address_Adjust ;an000; dms;
4075
4076 push bx ;an000; save regs
4077 push dx ;an000;
4078 push di ;an000;
4079 push si ;an000;
4080
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
4087
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
4091
4092 pop si ;an000; restore regs
4093 pop di ;an000;
4094 pop dx ;an000;
4095 pop bx ;an000;
4096
4097 ret ;an000; dms;
4098
4099BadClus_Address_Adjust endp ;an000; dms;
4100
4101
4102
4103;=========================================================================
4104; NextTrack : This routine determines the next track to be
4105; formatted.
4106;
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
4111;
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;=========================================================================
4118
4119Procedure NextTrack ;an015; dms;
4120
4121
4122 cmp TracksLeft,00 ;an015; dms;end of format?
4123; $if e ;an015; dms;yes
4124 JNE $$IF149
4125 stc ;an015; dms;signal end of format
4126 mov Format_End,True
4127; $else
4128 JMP SHORT $$EN149
4129$$IF149:
4130 mov cx,Tracks_To_Format ;an015; dms;get max track count for call
4131; $do ;an015; dms;while tracks remain
4132$$DO151:
4133 cmp TracksLeft,00 ;an015; dms;end of format?
4134; $leave e ;an015; dms;yes
4135 JE $$EN151
4136 cmp cx,00 ;an015; dms;end of head/cyl. adjustment?
4137; $leave e ;an015; dms;yes
4138 JE $$EN151
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
4143 JNE $$IF154
4144 mov FormatPacket.FP_Head,00 ;an015; dms;reinit. head
4145 inc FormatPacket.FP_Cylinder ;an015; dms;next cylinder
4146; $endif ;an015; dms;
4147$$IF154:
4148
4149 dec cx ;an015; dms;decrease counter
4150; $enddo ;an015; dms;
4151 JMP SHORT $$DO151
4152$$EN151:
4153
4154 clc ;an015; dms;clear CY
4155; $endif ;an015; dms;
4156$$EN149:
4157
4158 ret ;an015; dms;
4159
4160NextTrack endp ;an015; dms;
4161
4162;=========================================================================
4163; Determine_Format_Type : This routine determines the type of format
4164; that is to occur based on the media type.
4165;
4166; Inputs : Dev_HardDisk - Media type (harddisk)
4167; Multi_Track_Format - EQU 02h
4168; Single_Track_Format - EQU 00h
4169;
4170; Outputs : FP_SpecialFunctions - Set appropriately for single
4171; or multi track format
4172;=========================================================================
4173
4174Procedure Determine_Format_Type ;an015; dms;
4175
4176 cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk?
4177; $if e ;an015; dms;yes
4178 JNE $$IF158
4179 mov FormatPacket.FP_SpecialFunctions,Multi_Track_Format ;an015; dms;set for multi track format
4180; $else ;an015; dms;
4181 JMP SHORT $$EN158
4182$$IF158:
4183 mov FormatPacket.FP_SpecialFunctions,Single_Track_Format ;an015; dms;set for single track format
4184; $endif ;an015; dms;
4185$$EN158:
4186 ret ;an015; dms;
4187
4188Determine_Format_Type endp ;an015; dms;
4189
4190
4191;=========================================================================
4192; FormatTrack : This routine performs multi track or single
4193; track formatting based on the state of the
4194; SpecialFunctions byte.
4195;
4196; Inputs : Tracks_To_Format - # of tracks to format in 1 call
4197; FormatPacket - Parms for IOCTL call
4198;
4199; Outputs : NC - formatted track(s)
4200; CY - error in format
4201; AX - extended error on CY
4202;=========================================================================
4203
4204Procedure FormatTrack ;an015; dms;
4205
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;
4214
4215; $if c ;an015; dms;error?
4216 JNC $$IF161
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;
4222$$IF161:
4223
4224 ret ;an015; dms;
4225
4226FormatTrack endp ;an015; dms;
4227
4228
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.
4236;
4237; Inputs : Device_Type - Media type
4238;
4239; Outputs : Tracks_To_Format - Max. number of tracks
4240; to be formatted in one
4241; call
4242;=========================================================================
4243
4244Procedure Determine_Track_Count ;an015; dms;
4245
4246 cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk?
4247; $if e ;an015; dms;yes
4248 JNE $$IF163
4249 call Calc_Track_Count ;an015; dms;calc Tracks_To_Format
4250; $else ;an015; dms;removable media
4251 JMP SHORT $$EN163
4252$$IF163:
4253 mov Tracks_To_Format,0001h ;an015; dms;default to 1 track
4254; $endif ;an015; dms;
4255$$EN163:
4256
4257 ret ;an015; dms;
4258
4259Determine_Track_Count endp ;an015;dms;
4260
4261
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
4269; count.
4270;
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
4274; formatted.
4275;
4276; Outputs : Tracks_To_Format - Count of the tracks to be formatted
4277; in the next FormatTrack call.
4278;
4279;
4280;=========================================================================
4281
4282Procedure Calc_Track_Count ;an015; dms;
4283
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
4288 JNA $$IF166
4289 mov ax,TracksLeft ;an015; dms;format remaining tracks
4290; $endif ;an015; dms;
4291$$IF166:
4292 mov Tracks_To_Format,ax ;an015; dms;save track count
4293
4294 pop ax ;an015; dms;
4295
4296 ret ;an015; dms;
4297
4298Calc_Track_Count endp ;an015; dms;
4299
4300;=========================================================================
4301; Calc_Max_Tracks_To_Format : This routine determines the maximum
4302; number of tracks to format at 1 time.
4303;
4304; Inputs : DeviceParameters - SectorsPerTrack
4305; BytesPerSector
4306;
4307; Outputs : Track_Count - Max. # of tracks to format in 1 call
4308; to FormatTrack
4309;=========================================================================
4310
4311Procedure Calc_Max_Tracks_To_Format
4312
4313 push ax ;an015; dms;save regs
4314 push bx ;an015; dms;
4315 push dx ;an015; dms;
4316
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
4324 mov Track_Count,ax
4325
4326 pop dx ;an015; dms;
4327 pop bx ;an015; dms;
4328 pop ax ;an015; dms;
4329
4330 ret
4331
4332Calc_Max_Tracks_To_Format endp
4333
4334
4335
4336
4337
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
4342; a CY condition.
4343;
4344; Inputs : none
4345;
4346; Outputs : CY - indicates either a failing track or end of format
4347;
4348;
4349;=========================================================================
4350
4351Procedure Format_Track_Retry
4352
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
4356$$DO168:
4357; $leave c ;an015; dms; exit on bad track
4358 JC $$EN168
4359 call FormatTrack ;an015; dms; format the track
4360; $if nc ;an015; dms;error?
4361 JC $$IF170
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;
4366$$IF170:
4367; $enddo ;an015; dms;
4368 JMP SHORT $$DO168
4369$$EN168:
4370
4371 ret ;an015; dms;
4372
4373Format_Track_Retry endp ;an015; dms;
4374
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.
4382;
4383; Inputs : none
4384;
4385; Outputs : CY - Set on exit from this routine
4386; AX - Possible error condition code
4387;=========================================================================
4388
4389Procedure Format_Loop ;an015; dms;
4390
4391 clc ;an015; dms;initialize to NC
4392; $do ;an015; dms;while NC
4393$$DO173:
4394; $leave c ;an015; dms;exit on CY
4395 JC $$EN173
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
4401 JNC $$IF175
4402 pushf ;an015; dms;save flags
4403 cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk?
4404; $if e ;an015; dms;yes
4405 JNE $$IF176
4406 popf ;an015; dms;restore flags
4407 call Format_Track_Retry ;an015; dms;find failing track
4408; $else ;an015; dms;
4409 JMP SHORT $$EN176
4410$$IF176:
4411 popf ;an015; dms;restore flags
4412; $endif ;an015; dms;
4413$$EN176:
4414; $endif ;an015; dms;
4415$$IF175:
4416
4417; $if c ;an015; dms;format error?
4418 JNC $$IF180
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
4423 JC $$IF181
4424 call DisplayCurrentTrack ;an015; dms;display % formatted
4425; $endif ;an015; dms;
4426$$IF181:
4427 pop ax ;an015; dms;restore regs
4428 popf ;an015; dms;
4429; $endif ;an015; dms;
4430$$IF180:
4431
4432; $leave c ;an015; dms;exit on CY
4433 JC $$EN173
4434
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;
4439 JMP SHORT $$DO173
4440$$EN173:
4441 ret ;an015; dms;
4442
4443Format_Loop endp ;an015; dms;
4444
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.
4449;
4450; Inputs : TracksLeft - # of tracks remaining to be formatted
4451; Tracks_To_Format - Tracks formatted in 1 call
4452;
4453; Outputs : TracksLeft - # of tracks remaining to be formatted
4454;=========================================================================
4455
4456Procedure Adj_Track_Count ;an015; dms;
4457
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
4463 ret ;an015; dms;
4464
4465Adj_Track_Count endp ;an015; dms;
4466
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.
4475;
4476; Inputs : Switchmap - Switches chosen for format
4477;
4478; Outputs : Message printed as appropriate.
4479;=========================================================================
4480
4481Procedure Prompt_User_For_Disk ;an016;dms;
4482
4483 push ax ;an016;dms;save ax
4484 test switchmap, (SWITCH_Backup or SWITCH_Select or SWITCH_AUTOTEST) ;Suppress prompt? ;AC000;
4485; $IF Z ; ;AC000;
4486 JNZ $$IF186
4487 call DSKPRM ; prompt user for disk
4488; $ENDIF ; ;AC000;
4489$$IF186:
4490
4491 test switchmap, (Switch_Select) ;an016;dms;/SELECT requested?
4492; $if nz ;an016;dms;yes
4493 JZ $$IF188
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;
4499$$IF188:
4500 pop ax ;an016;dms;restore ax
4501
4502 ret ;an016;dms;
4503
4504Prompt_User_For_Disk endp ;an016;dms;
4505
4506
4507code ends
4508 END START
4509 \ No newline at end of file