From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/FORMAT/FORMAT.ASM | 4509 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4509 insertions(+) create mode 100644 v4.0/src/CMD/FORMAT/FORMAT.ASM (limited to 'v4.0/src/CMD/FORMAT/FORMAT.ASM') 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 @@ +page 84,132 +; +; SCCSID = @(#)format.asm 1.26 85/10/20 +; SCCSID = @(#)format.asm 1.26 85/10/20 +;*************************************************************** +; +; 86-DOS FORMAT DISK UTILITY +; +; This routine formats a new disk,clears the FAT and DIRECTORY then +; optionally copies the SYSTEM and COMMAND.COM to this new disk +; +; SYNTAX: FORMAT [drive][/switch1][/switch2]...[/switch16] +; +; Regardless of the drive designator , the user will be prompted to +; insert the diskette to be formatted. +; +;*************************************************************** + +; 5/12/82 ARR Mod to ask for volume ID +; 5/19/82 ARR Fixed rounding bug in CLUSCAL: +; REV 1.5 +; Added rev number message +; Added dir attribute to DELALL FCB +; REV 2.00 +; Redone for 2.0 +; REV 2.10 +; 5/1/83 ARR Re-do to transfer system on small memory systems +; REV 2.20 +; 6/17/83 system size re-initialization bug -- mjb001 +; Rev 2.25 +; 8/31/83 16-bit fat insertion +; Rev 2.26 +; 11/2/83 MZ fix signed compare problems for bad sectors +; Rev 2.27 +; 11/8/83 EE current directories are always saved and restored +; Rev 2.28 +; 11/9/83 NP Printf and changed to an .EXE file +; Rev 2.29 +; 11/11/83 ARR Fixed ASSIGN detection to use NameTrans call to see +; if drive letter remapped. No longer IBM only +; Rev 2.30 +; 11/13/83 ARR SS does NOT = CS, so all use of BP needs CS override +; Rev 2.31 +; 12/27/83 ARR REP STOSB instruction at Clean: changed to be +; sure ES = CS. + + + + +code segment public para 'CODE' +code ends + + + +data segment public para 'DATA' +data ends + +End_Of_Memory segment public para 'BUFFERS' +End_Of_Memory ends + + +code segment public para 'CODE' + + assume cs:code,ds:nothing,es:nothing + +;------------------------------------------------------------------------------- +; Define as public for debugging + +; procedures + public GetSize + public AddToSystemSize + public Phase1Initialisation + public SetStartSector + public SetfBigFat + public Phase2Initialisation + public DiskFormat + public BadSector + public DisplayCurrentTrack + public WriteFileSystem + public Done + public CurrentLogicalSector + public PrintErrorAbort + public GetDeviceParameters + public SetDeviceParameters + public Multiply_32_Bits + + public START + public FatAllocated + public MEMERRJ + public MEM_OK + public RDFRST + public NEEDSYS + public INITCALL + public SWITCHCHK + public SYSLOOP + public FRMTPROB + public GETTRK + public TRKFND + public CLRTEST + public CMPTRKS + public BadClus +; public DoBig +; public DoSet + public DRTFAT + public CLEARED + public LOUSE + public LOUSEP + public FATWRT + public SYSOK + public STATUS + public REPORTC + public ONCLUS + public MORE + public FEXIT + public SYSPRM + public fexitJ + public DoPrompt + public TARGPRM + public IsRemovable + public CheckRemove + public IsRemove + public NotRemove + public DSKPRM + public GOPRNIT + public crlf + public PrintString + public std_printf + public READDOS + public RDFILS + public FILESDONE + public CLSALL + public GOTBIOS + public GOTDOS + public CLSALLJ + public GOTCOM + public WRITEDOS + public GOTALLBIO + public BIOSDONE + public GOTNDOS + public PARTDOS + public GOTALLDOS + public DOSDONE + public PARTCOM + public GOTALLCOM + public COMDONE + public MAKEFIL + public CheckMany + public CLOSETARG + public IOLOOP + public GOTTARG + public GSYS + public TESTSYS + public GETOFFS +; public TESTSYSDISK ; dcl 8/23/86 + public SETBIOS + public BIOSCLS + public SETBIOSSIZ + public DOSOPNOK + public DOSCLS + public SETDOSSIZ + public GotComHand + public COMCLS + public SETCOMSIZ + public GETFSIZ + public READFILE + public WRITEFILE + public FILIO + public NORMIO + public IORETP + public IORET + public NORMALIZE + public GotDeviceParameters + public LoadSectorTable + public NotBigTotalSectors + public NotBig + public FormatLoop + public FormatDone + public ContinueFormat + public ReportBadTrack + public NoMoreTracks + public WriteDIRloop + public Main_Routine + public ControlC_Handler + +; bytes + public fBigFat + public formatError + public ROOTSTR + public DBLFLG + public DRIVE + public FILSTAT + public USERDIRS + public VOLFCB + public VOLNAM + public TRANSRC + public TRANDST + public INBUFF + public driveLetter + public systemDriveLetter + public CommandFile + public ExitStatus + public VolDrive + public DelFCB + public DelDrive + +; words + public startSector + public fatSpace + public firstHead + public firstCylinder + public tracksLeft + public tracksPerDisk + public sectorsInRootDirectory + public directorySector + public printStringPointer + public MSTART + public MSIZE + public TempHandle + public BEGSEG + public SWITCHMAP + public SWITCHCOPY + public FAT + public CLUSSIZ + public SECSIZ + public SYSTRKS + public SECTORS + public currentHead + public currentCylinder + public PercentComplete + public Formatted_Tracks_High + public Formatted_Tracks_Low + +; other + public deviceParameters + public Disk_Access + public formatPacket +;------------------------------------------------------------------------------- + +data segment public para 'DATA' + extrn msgAssignedDrive:byte + extrn msgBadDosVersion:byte + extrn msgDirectoryWriteError:byte + extrn msgFormatComplete:byte + extrn msgFormatNotSupported:byte + extrn msgFATwriteError:byte + extrn msgInvalidDeviceParameters:byte + extrn msgLabelPrompt:byte + extrn msgNeedDrive:byte + extrn msgNoSystemFiles:byte + extrn msgNetDrive:byte + extrn msgInsertDisk:byte + extrn msgHardDiskWarning:byte + extrn msgSystemTransfered:byte + extrn msgFormatAnother?:byte + extrn msgBadCharacters:byte + extrn msgBadDrive:byte + extrn msgInvalidParameter:byte + extrn msgParametersNotSupported:byte + extrn msgReInsertDisk:byte + extrn msgInsertDosDisk:byte + extrn msgFormatFailure:byte + extrn ContinueMsg:Byte + extrn msgNotSystemDisk:byte + extrn msgDiskUnusable:byte + extrn msgOutOfMemory:byte + extrn msgCurrentTrack:byte + extrn msgWriteProtected:byte + extrn msgInterrupt:byte + extrn msgCRLF:byte + extrn Fatal_Error:Byte + extrn Read_Write_Relative:Byte + extrn PSP_Segment:Word + extrn Parse_Error_Msg:Byte + extrn Extended_Error_Msg:Byte + extrn MsgVerify:Byte + +data ends + + +debug equ 0 + .xlist + INCLUDE VERSIONA.INC + INCLUDE DOSMAC.INC + INCLUDE SYSCALL.INC + INCLUDE ERROR.INC + INCLUDE DPB.INC + INCLUDE CPMFCB.INC + INCLUDE DIRENT.INC + INCLUDE CURDIR.INC + INCLUDE PDB.INC + INCLUDE BPB.INC + INCLUDE FOREQU.INC + INCLUDE FORMACRO.INC + INCLUDE IOCTL.INC + INCLUDE FORSWTCH.INC + INCLUDE SYSVAR.INC + .list + + +;------------------------------------------------------------------------------- +; And this is the actual data + +data segment public para 'DATA' + public deviceParameters + public bios + public dos + public command + public FAT_Flag + +validSavedDeviceParameters db 0 +savedDeviceParameters a_DeviceParameters <> +deviceParameters a_DeviceParameters <> + +Disk_Access A_DiskAccess_Control <> ;an000; dms; + +formatPacket a_FormatPacket <> +RWPacket a_TrackReadWritePacket <> +RW_TRF_Area db 512 dup(0) + +startSector dw ? +fatSpace dd ? +fBigFat db FALSE + +firstHead dw ? +firstCylinder dw ? +tracksLeft dw ? +tracksPerDisk dw ? + +Formatted_Tracks_Low dw 0 +Formatted_Tracks_High dw 0 + + +public NumSectors ,TrackCnt +NumSectors dw 0FFFFh +TrackCnt dw 0FFFFh +PercentComplete dw 0FFFFh ;Init non-zero so msg will display first time + +public Old_Dir +Old_Dir db FALSE + +public fLastChance +fLastChance db FALSE ; Flags reinvocation from + ; LastChanceToSaveIt. Used by DSKPRM + +sectorsInRootDirectory dw ? + +directorySector dd 0 + +formatError db 0 + +printStringPointer dw 0 + +; Exit status defines +ExitStatus db 0 +ExitOK equ 0 +ExitCtrlC equ 3 +ExitFatal equ 4 +ExitNo equ 5 +ExitDriveNotReady equ 6 ;an017; dms;drive not ready error +ExitWriteProtect equ 7 ;an017; dms;write protect error + +ROOTSTR DB ? + DB ":\",0 +DBLFLG DB 0 ;Initialize flags to zero +IOCNT DD ? +MSTART DW ? ; Start of sys file buffer (para#) +MSIZE DW ? ; Size of above in paragraphs +TempHandle DW ? +FILSTAT DB ? ; In memory status of files + ; XXXXXX00B BIOS not in + ; XXXXXX01B BIOS partly in + ; XXXXXX10B BIOS all in + ; XXXX00XXB DOS not in + ; XXXX01XXB DOS partly in + ; XXXX10XXB DOS all in + ; XX00XXXXB COMMAND not in + ; XX01XXXXB COMMAND partly in + ; XX10XXXXB COMMAND all in + +USERDIRS DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory + +Paras_Per_Fat dw 0000h ;an000;holds fat para count +Fat_Init_Value dw 0000h ;an000;initializes the FAT + +bios a_FileStructure <> +BiosAttributes EQU attr_hidden + attr_system + attr_read_only + +dos a_FileStructure <> +DosAttributes EQU attr_hidden + attr_system + attr_read_only + +command a_FileStructure <> +CommandAttributes EQU 0 +CommandFile DB "X:\COMMAND.COM",0 +CommandFile_Buffer DB 127 dup(0) ;an000;allow room for copy + +Command_Com DB "COMMAND.COM",0 + +VOLFCB DB -1,0,0,0,0,0,8 +VOLDRIVE DB 0 +VOLNAM DB " " + DB 8 + DB 26 DUP(?) + +DelFCB DB -1,0,0,0,0,0,8 +DelDRIVE DB 0 +DelNAM DB "???????????" + DB 8 + DB 26 DUP(?) + +TRANSRC DB "A:CON",0,0 ; Device so we don't hit the drive +TRANDST DB "A:\",0,0,0,0,0,0,0,0,0,0 + +BEGSEG DW ? +SWITCHMAP DW ? +SWITCHCOPY DW ? +FAT DW ? + DW ? +CLUSSIZ DW ? +SECSIZ DW ? +SYSTRKS DW ? +SECTORS DW ? +INBUFF DB 80,0 + DB 80 DUP(?) + + +drive db 0 +driveLetter db "x" +systemDriveLetter db "x" + +CTRL_BREAK_VECTOR dd ? ;ac010; dms;Holds CTRL-Break + ; vector + +Command_Path dd ? ;an011; dms;hold pointer to + ; COMMAND's path + +Comspec_ID db "COMSPEC=",00 ;an011; dms;Comspec target + + +Environ_Segment dw ? ;an011; dms;hold segment of + ; environ. vector +;======== Disk Table ========== ;an012; dms; +;Used if NumberOfFATs in BPB +;is 0. + +DiskTable dw 0, 32680, 0803h, 512, 0 + dw 4h, 0000h, 0402h, 512, Fbig + dw 8h, 0000h, 0803h, 512, Fbig + dw 10h, 0000h, 1004h, 512, Fbig + dw 20h, 0000h, 2005h, 512, Fbig + +public Org_AX ;an000; dms;make it known +Org_AX dw ? ;an000; dms;AX on entry + +Cluster_Boundary_Adj_Factor dw ? ;an000; dms; +Cluster_Boundary_SPT_Count dw ? ;an000; dms; +Cluster_Boundary_Flag db False ;an000; dms; +Cluster_Boundary_Buffer_Seg dw ? ;an000; dms; + +Relative_Sector_Low dw ? ;an000; dms; +Relative_Sector_High dw ? ;an000; dms; + +FAT_Flag db ? ;an000; dms; +Tracks_To_Format dw ? ;an015; dms; +Track_Count dw ? ;an015; dms; +Format_End db FALSE ;an015; dms; + +public Msg_Allocation_Unit_Val + +Msg_Allocation_Unit_Val dd ? ;an019; dms; + + +data ends + +;For FORPROC and FORMES modules + + public secsiz,clussiz,inbuff + + PUBLIC crlf,std_printf + + public switchmap,drive,driveLetter,fatSpace + public fBigFat, PrintString,currentHead,currentCylinder + extrn CheckSwitches:near,LastChanceToSaveIt:near + extrn Volid:near + extrn WriteBootSector:near,OemDone:near + extrn AccessDisk:near + extrn Main_Init:near + extrn Read_Disk:near + extrn Write_Disk:near + +data segment public para 'DATA' + extrn BiosFile:byte,DosFile:byte +data ends + +;For FORPROC module + + EXTRN FormatAnother?:near,Yes?:near,REPORT:NEAR,USER_STRING:NEAR +data segment public para 'DATA' + extrn syssiz:dword,biosiz:dword +data ends + +DOSVER_LOW EQU 0300H+20 +DOSVER_HIGH EQU 0300H+20 + +RECLEN EQU fcb_RECSIZ+7 +RR EQU fcb_RR+7 + +PSP_Environ equ 2ch ;an011; dms;location of + ; environ. segment + ; in PSP + +Fbig equ 0ffh ;an000; dms;flag for big FAT + +START: + xor bx,bx ; ;AN000; + push bx ; ;AN000; + Set_Data_Segment ; ;AC000; + mov Org_AX,ax ;an000; dms;save ax on entry + jmp Main_Init ; ;AC000; + + +Main_Routine: ; ;AN000; +; Set memory requirements + mov bx,PSP_Segment ;Shrink to free space for FAT ;AC000; + mov es,bx ; ;AC000; + mov bx,End_Of_Memory ; ;AC000; + sub bx,PSP_Segment ; ;AC000; + DOS_Call Setblock ; ;AC000; + + call Get_Disk_Access ;an014; dms; + cmp Disk_Access.DAC_Access_Flag,0ffh ;an014; dms;is access already allowed? +; $if ne ;an014; dms;no, don't change status + JE $$IF1 + lea dx,Disk_Access ;an014; dms;point to parm block + mov Disk_Access.DAC_Access_Flag,01h ;an014; dms;signal disk access + call Set_Disk_Access_On_Off ;an014;dms;allow disk access +; $endif ;an014; dms; +$$IF1: + + CALL Phase1Initialisation + jnc FatAllocated + + Message msgFormatFailure ; ;AC000; + jmp Fexit + +MEMERR: + mov ax, seg data + mov ds, ax + Message msgOutOfMemory ; ;AC000; + ;call PrintString + JMP FEXIT + +FatAllocated: + + TEST SWITCHMAP,SWITCH_S + JZ INITCALL + MOV BX,0FFFFH + MOV AH,ALLOC + INT 21H + OR BX,BX + JZ MEMERRJ ;No memory + MOV [MSIZE],BX + MOV AH,ALLOC + INT 21H + JNC MEM_OK +MEMERRJ: + JMP MEMERR ;No memory + +MEM_OK: + MOV [MSTART],AX + +RDFRST: + mov bios.fileSizeInParagraphs,0 ;mjb001 initialize file size + mov dos.fileSizeInParagraphs,0 ;mjb001 ... + mov command.fileSizeInParagraphs,0 ;mjb001 ... + CALL READDOS ;Read BIOS and DOS + JNC INITCALL ;OK -- read next file +NEEDSYS: + CALL SYSPRM ;Prompt for system disk + JMP RDFRST ;Try again + +INITCALL: + CALL Phase2Initialisation + +SWITCHCHK: + MOV DX,SWITCHMAP + MOV SWITCHCOPY,DX + +SYSLOOP: + ;Must intialize for each iteration + + MOV WORD PTR SYSSIZ,0 + MOV WORD PTR SYSSIZ+2,0 + MOV BYTE PTR DBLFLG,0 + mov ExitStatus, ExitOK + MOV DX,SWITCHCOPY + MOV SWITCHMAP,DX ;Restore original Switches +; DiskFormat will handle call for new disk + CALL DISKFORMAT ;Format the disk + JNC GETTRK +FRMTPROB: + + test SwitchMap,Switch_Select ;an017; dms;SELECT option? +; $if z ;an017; dms;no - display message + JNZ $$IF3 + Message msgFormatFailure ; ;AC000; + mov ExitStatus, ExitFatal ;an017; dms; +; $endif ;an017; dms; +$$IF3: + CALL MORE ;See if more disks to format + JMP SHORT SYSLOOP + +;Mark any bad sectors in the FATs +;And keep track of how many bytes there are in bad sectors + +GETTRK: + CALL BADSECTOR ;Do bad track fix-up + JC FRMTPROB ;Had an error in Formatting - can't recover + CMP AX,0 ;Are we finished? + JNZ TRKFND ;No - check error conditions + JMP DRTFAT ;Yes +TRKFND: + mov bx,word ptr Relative_Sector_Low ;get the low word of the sector ;an000; dms; + CMP BX,STARTSECTOR ;Are any sectors in the system area bad? + JAE CLRTEST ; MZ 2.26 unsigned compare + Message msgDiskUnusable ; ;AC000; + JMP FRMTPROB ;Bad disk -- try again +CLRTEST: + MOV SECTORS,AX ;Save the number of sectors on the track + TEST SWITCHMAP,SWITCH_S ;If system requested calculate size + JZ BAD100 + CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space? + JNZ CMPTRKS ;Yes -- all ready for the compare + INC BYTE PTR DBLFLG ;No -- set the flag + CALL GETBIOSIZE ; Get the size of the BIOS + MOV DX,WORD PTR SYSSIZ+2 + MOV AX,WORD PTR SYSSIZ + MOV WORD PTR BIOSIZ+2,DX + MOV WORD PTR BIOSIZ,AX + CALL GETDOSSIZE + CALL GETCMDSIZE + MOV DX,WORD PTR BIOSIZ+2 + MOV AX,WORD PTR BIOSIZ + DIV deviceParameters.DP_BPB.BPB_BytesPerSector + ADD AX,STARTSECTOR + MOV SYSTRKS,AX ;Space FAT,Dir,and system files require +CMPTRKS: + mov bx,word ptr Relative_Sector_Low ;get the low word of the sector ;an000; dms; + CMP BX,SYSTRKS + JA BAD100 ; MZ 2.26 unsigned compare + mov ExitStatus, ExitFatal + Message msgNotSystemDisk ; ;AC000; + AND SWITCHMAP,NOT SWITCH_S ;Turn off system transfer switch + MOV WORD PTR SYSSIZ+2,0 ;No system to transfer + MOV WORD PTR SYSSIZ,0 ;No system to transfer +BAD100: + + CMP deviceParameters.DP_DeviceType, DEV_HARDDISK ;an000; dms;hard disk? +; $if e ;an000; dms; yes + JNE $$IF5 + call Get_Bad_Sector_Hard ;an000; dms;see if a sector is bad +; $else ;an000; dms;floppy disk + JMP SHORT $$EN5 +$$IF5: + call Get_Bad_Sector_Floppy ;an000; dms;mark entire track bad +; $endif ;an000; dms; +$$EN5: + + JMP GETTRK + +; Inputs: BX = Cluster number +; Outputs: The given cluster is marked as invalid +; Zero flag is set if the cluster was already marked bad +; Registers modified: DX,SI +; No other registers affected + +;========================================================================= +; BADCLUS : Marks off a bad cluster in the FAT +; If a cluster has already been marked bad it +; will return with ZR. +; +; Inputs : DX:AX - Cluster Number +; +; Outputs : Cluster is marked invalid +; ZR set if cluster already marked bad +;========================================================================= + +BadClus proc near ;an000; mark bad clusters + + push di ;an000; save affected regs + push ax + push bx + push cx + push dx + push es + + mov es, word ptr fatSpace + 2 ;an005; obtain seg of FAT + CMP fBigFat,TRUE ;an005; 16 bit fat? +; $if ne ;an005; no - 12-bit fat + JE $$IF8 + push ax ;an000; save ax - contains low cluster number + mov si,dx ;an000; pick up high word of cluster + mov di,ax ;an000; pick up low word of cluster + mov cx,2 ;an000; divide by 2 + call Divide_32_Bits ;an000; 32 bit divide + + add ax,di ;an000; add in low word of result + adc dx,si ;an000; pick up low word carry + ;cluster = cluster * 1.5 + add ax,word ptr fatspace ;an005; add 0 + adc dx,0 ;an000; pick up carry + + mov bx,dx ;an000; get high word for adjust + mov cx,es ;an005; place seg in ax + call BadClus_Address_Adjust ;an000; adjust segment offset + mov es,cx ;an000; new segment + mov si,ax ;an000; new offset + + MOV DX,0FF7h ;an005; bad cluster flag + MOV AX,0FFFh ;an005; mask value + + pop cx ;an000; restore ax in cx - low cluster number + test cx,1 ;an000; is old clus num odd? +; $if nz ;an005; yes + JZ $$IF9 + mov cl,4 ;an005; set shift count + SHL AX,cl ;an005; get only 12 bits - fff0 + mov cl,4 ;an005; set shift count + SHL DX,cl ;an005; get 12 bits - ff70 +; $endif ;an005; +$$IF9: +; $else ;an005; 16-bit fats here + JMP SHORT $$EN8 +$$IF8: + xor si,si ;an005; clear si + mov bx,dx ;an000; get high word for multiply + mov cx,2 ;an000; multiply by 2 + call Multiply_32_Bits ;an000; 32 bit multiply + ; due to 2 bytes per + ; FAT cell. This gives + ; us an offset into the + ; FAT. + + mov cx,es ;an005; place seg in cx + call BadClus_Address_Adjust ;an000; adjust segment:offset + mov es,cx ;an000; new segment + mov si,ax ;an000; new offset + + MOV DX,0FFF7h ;an005; bad cluster value + MOV AX,0FFFFh ;an005; mask value +; $endif +$$EN8: + + MOV CX,es:[SI] ;an005; get contents of fat cell + AND CX,AX ;an005; make it 12 or 16 bit + ; depending on value in AX + NOT AX ;an005; set AX to 0 + AND es:[SI],AX ;an005; clear FAT entry + OR es:[SI],DX ;an005; flag it a bad cluster + CMP DX,CX ; return op == badval; + + pop es + pop dx + pop cx + pop bx + pop ax + pop di + return + +badclus endp + +DRTFAT: + TEST SWITCHMAP,SWITCH_S ;If system requested, calculate size + JZ CLEARED + CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space? + JNZ CLEARED ;Yes + INC BYTE PTR DBLFLG ;No -- set the flag + CALL GETSIZE ;Calculate the system size +CLEARED: + call Ctrl_Break_Save ;ac010; dms;save CTRL-Break + call Set_Ctrl_Break + CALL WriteFileSystem + + JNC FATWRT + + +LOUSE: + + call Reset_Ctrl_Break ;ac010; dms;restore CTRL-Break + Message msgDiskUnusable ; ;AC000; + JMP FRMTPROB + +LOUSEP: + POP DS + JMP LOUSE + +FATWRT: + + PUSH DS + MOV DL,DRIVE + INC DL + MOV AH,GET_DPB + INT 21H + CMP AL,-1 + JZ LOUSEP ;Something BAD has happened + MOV [BX.dpb_next_free],0 ; Reset allocation to start of disk + MOV [BX.dpb_free_cnt],-1 ; Force free space to be computed + POP DS + TEST SWITCHMAP,SWITCH_S ;System desired + JZ STATUS + mov al, drive + call AccessDisk ; note what is current logical drive + CALL WRITEDOS ;Write the BIOS & DOS + JNC SYSOK + Message msgNotSystemDisk ; ;AC000; + MOV WORD PTR SYSSIZ+2,0 ;No system transfered + MOV WORD PTR SYSSIZ,0 ;No system transfered + JMP SHORT STATUS + +SYSOK: + + + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display if EXEC'd by ;AN000; +; $IF Z ; Select ;AN000; + JNZ $$IF13 + Message msgSystemTransfered ; ;AC000; +; $ENDIF ;AN000; +$$IF13: +STATUS: + + call Reset_Ctrl_Break ;ac010; dms;restore CTRL-Break + + CALL CRLF + + + + + MOV AH,DISK_RESET + INT 21H + CALL DONE ;Final call to OEM module + JNC REPORTC + JMP FRMTPROB ;Report an error + +REPORTC: + +; +;TEMP FIX for /AUTOTEST +; + test SwitchMap,(Switch_Autotest or Switch_8) ;TEMP +; $IF Z + JNZ $$IF15 + CALL VOLID +; $ENDIF +$$IF15: + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Need to shut down the report? ;AN000; +; $IF Z ;If exec'd by Select, we do ;AN000; + JNZ $$IF17 + CALL REPORT ;Print report +; $ENDIF ; ;AN000; +$$IF17: + CALL MORE ;See if more disks to format + JMP SYSLOOP ;If we returned from MORE then continue + +;****************************************** +; Calculate the size in bytes of the system rounded up to sector and +; cluster boundries, Answer in SYSSIZ + +GetSize proc near + call GetBioSize + call GetDosSize + call GetCmdSize + return +GetSize endp + +GetBioSize proc near + MOV AX,WORD PTR bios.fileSizeInBytes + MOV DX,WORD PTR bios.fileSizeInBytes+2 + CALL AddToSystemSize + return +GetBioSize endp + +GetDosSize proc near + MOV AX,WORD PTR dos.fileSizeInBytes + MOV DX,WORD PTR dos.fileSizeInBytes+2 + CALL AddToSystemSize + return +GetDosSize endp + +GetCmdSize proc near + MOV AX,WORD PTR command.fileSizeInBytes + MOV DX,WORD PTR command.fileSizeInBytes+2 + call AddToSystemSize + return +GetCmdSize endp + +;Calculate the number of sectors used for the system +PUBLIC AddToSystemSize +AddToSystemSize proc near + push bx + DIV deviceParameters.DP_BPB.BPB_BytesPerSector + OR DX,DX + JZ FNDSIZ0 + INC AX ; Round up to next sector +FNDSIZ0: + PUSH AX + XOR DX,DX + xor bx,bx + mov bl, deviceParameters.DP_BPB.BPB_SectorsPerCluster + div bx + POP AX + OR DX,DX + JZ ONCLUS + SUB DX, bx + NEG DX + ADD AX,DX ; Round up sector count to cluster + ; boundry +ONCLUS: + MUL deviceParameters.DP_BPB.BPB_BytesPerSector + ADD WORD PTR SYSSIZ,AX + ADC WORD PTR SYSSIZ+2,DX + pop bx + return +AddToSystemSize endp + +MORE: + + mov Formatted_Tracks_Low,0 ;Reinit the track counter ;AN000; + mov Formatted_Tracks_High,0 ; in case of another format ;AN000; + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display if EXEC'd by ;AN000; + jnz ExitProgram ; Select ;AN000; + + CMP deviceParameters.DP_DeviceType, DEV_HARDDISK + je ExitProgram + test SwitchMap,(SWITCH_Select or SWITCH_AUTOTEST) ;If exec'd from select, then;AN000; + jnz ExitProgram ; don't give user choice ;AN000; + CALL FormatAnother? ;Get yes or no response + JC ExitProgram + CALL CRLF + JMP CRLF + + +FEXIT: + Set_Data_Segment ;Make sure have addressability ;AN000; + mov ExitStatus,ExitFatal + +ExitProgram: + test validSavedDeviceParameters, 0ffH + jz DoNotRestoreDeviceParameters + mov savedDeviceParameters.DP_SpecialFunctions, TRACKLAYOUT_IS_GOOD + lea dx, savedDeviceParameters + call SetDeviceParameters +DoNotRestoreDeviceParameters: + + call Format_Access_Wrap_Up ;determine access status ;an000; dms;determine access status + mov al,ExitStatus ;Get Errorlevel ;AN000; + DOS_Call Exit ;Exit program ;AN000; + int 20h ;If other exit fails ;AN000; + +; Prompt the user for a system diskette in the default drive +SYSPRM: + MOV AH,GET_DEFAULT_DRIVE ;Will find out the default drive + INT 21H ;Default now in AL + MOV BL,AL + INC BL ; A = 1 + ADD AL,41H ;Now in Ascii + MOV systemDriveLetter,AL ;Text now ok + CALL IsRemovable + JNC DoPrompt +; +; Media is non-removable. Switch sys disk to drive A. Check, though, to see +; if drive A is removable too. +; + MOV AL,"A" + MOV BYTE PTR [systemDriveLetter],AL + MOV [BiosFile],AL + MOV [DosFile],AL + MOV [CommandFile],AL + MOV BX,1 + CALL IsRemovable + JNC DoPrompt + Message msgNoSystemFiles ; ;AC000; +fexitJ: + JMP FEXIT + +DoPrompt: + mov al, systemDriveLetter + sub al, 'A' + call AccessDisk + Message msgInsertDOSDisk ; ;AC000; + Message ContinueMsg + ;lea dx, ptr_msgInsertDosDisk + ;CALL std_printf ;Print first line + CALL USER_STRING ;Wait for a key + CALL CRLF + call crlf + return + +TARGPRM: + mov al, drive + call AccessDisk + Message MsgInsertDisk ; ;AC000; + Message ContinueMsg ; + ;lea DX, ptr_msgInsertDisk + ;CALL std_printf ;Print first line + CALL USER_STRING ;Wait for a key + CALL CRLF + return + +; +; Determine if the drive indicated in BX is removable or not. +; +; Inputs: BX has drive (0=def, 1=A) +; Outputs: Carry clear +; Removable +; Carry set +; not removable +; Registers modified: none + +IsRemovable: + SaveReg + MOV AX,(IOCTL SHL 8) OR 8 ; Rem media check + INT 21H + JNC CheckRemove + MOV AX,(IOCTL SHL 8) + 9 ; Is it a NET drive? + INT 21h + JC NotRemove ; Yipe, say non-removable + TEST DX,1000h + JNZ NotRemove ; Is NET drive, say non-removeable + JMP IsRemove ; Is local, say removable +CheckRemove: + TEST AX,1 + JNZ NotRemove +IsRemove: + CLC + RestoreReg + return +NotRemove: + STC + RestoreReg + return + + +; DiSKPRoMpt: +; +; This routine prompts for the insertion of the correct diskette +; into the Target drive, UNLESS we are being re-entrantly invoked +; from LastChanceToSaveIt. If the target is a Hardisk we issue a +; warning message. +; +; INPUTS: +; deviceParameters.DP_DeviceType +; fLastChance +; +; OUTPUTS: +; Prompt string +; fLastChance := FALSE +; +; Registers affected: +; Flags +; +DSKPRM: + CMP fLastChance,TRUE + JE PrmptRet + + CMP deviceParameters.DP_DeviceType, DEV_HARDDISK + jne goprnit + Message msgHardDiskWarning ; ;AC000; + ;lea dx, ptr_msgHardDiskWarning + ;call std_printf + CALL Yes? + jnc OkToFormatHardDisk + mov ExitStatus, ExitNo + jmp ExitProgram + +OkToFormatHardDisk: + CALL CRLF + CALL CRLF + return + +GOPRNIT: + mov al, drive + call AccessDisk + Message msgInsertDisk ; ;AC000; + Message ContinueMsg ; + ;lea dx,ptr_msgInsertDisk + ;CALL std_printf + CALL USER_STRING ;Wait for any key + CALL CRLF + CALL CRLF + +PrmptRet: + mov fLastChance, FALSE + return + + +;------------------------------------------------------------------------------- + +ControlC_Handler: + mov ax, seg data + mov ds, ax + Message msgInterrupt ; ;AC000; + mov ExitStatus, ExitCtrlC + jmp ExitProgram + + +crlf: + ;lea dx, msgCRLF + mov dx,offset msgCRLF ;CR,LF added to message ;AC000; +PrintString: + ;mov printStringPointer, dx + ;lea dx, PrintStringPointer + +std_printf: + ;push dx + ;call printf + call Display_Interface ; ;AC000; + return + +;------------------------------------------------------------------------------- + + +;**************************************** +;Copy IO.SYS, MSDOS.SYS and COMMAND.COM into data area. +; Carry set if problems + +READDOS: + push ax ;save regs ;an025; dms; + push bx ; ;an025; dms; + push es ; ;an025; dms; + + mov ah,Get_In_Vars ;Find out boot drive ;an025; dms; + int 21h ; ;an025; dms; + mov al,byte ptr es:[bx].SysI_Boot_Drive ;get 1 based drive ID ;an025; dms; + add al,40h ;Make it ASCII ;an025; dms; + mov [BiosFile],al ;Stuff it in file specs. ;an025; dms; + mov [DosFile],al ; ;an025; dms; + mov [CommandFile],al ; ;an025; dms; + + pop es ;restore regs ;an025; dms; + pop bx ; ;an025; dms; + pop ax ; ;an025; dms; + + call Get_BIOS ; dcl 8/23/86 + JNC RDFILS + return + +RDFILS: + MOV BYTE PTR [FILSTAT],0 + MOV BX,[bios.fileHandle] + MOV AX,[MSTART] + MOV DX,AX + ADD DX,[MSIZE] ; CX first bad para + MOV [bios.fileStartSegment],AX + MOV CX,[bios.fileSizeInParagraphs] + ADD AX,CX + CMP AX,DX + JBE GOTBIOS + MOV BYTE PTR [FILSTAT],00000001B ; Got part of BIOS + MOV SI,[MSIZE] + XOR DI,DI + CALL DISIX4 + push ds + MOV DS,[bios.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALL + XOR DX,DX + MOV CX,DX + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR [bios.fileOffset],AX + MOV WORD PTR [bios.fileOffset+2],DX +FILESDONE: + CLC +CLSALL: + PUSHF +; CALL COMCLS ; dcl 8/23/86 + call FILE_CLS ; dcl 8/23/86 + POPF + return + +GOTBIOS: + MOV BYTE PTR [FILSTAT],00000010B ; Got all of BIOS + push es + LES SI,[bios.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[bios.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALL + + push ax ; dcl 8/23/86 + push dx ; dcl 8/23/86 + call File_Cls ; dcl 8/23/86 + call Get_DOS ; dcl 8/23/86 + pop dx ; dcl 8/23/86 + pop ax ; dcl 8/23/86 + + JNC Found_IBMDOS ;mt 12/8/86 P894 + return ;mt 12/8/86 + +Found_IBMDOS: ;mt 12/8/86 + + MOV BX,[dos.fileHandle] + MOV [dos.fileStartSegment],AX + CMP AX,DX ; No room left? + JZ CLSALL ; Yes + MOV CX,[dos.fileSizeInParagraphs] + ADD AX,CX + CMP AX,DX + JBE GOTDOS + OR BYTE PTR [FILSTAT],00000100B ; Got part of DOS + SUB DX,[dos.fileStartSegment] + MOV SI,DX + XOR DI,DI + CALL DISIX4 + push ds + MOV DS,[dos.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALL + XOR DX,DX + MOV CX,DX + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR [dos.fileOffset],AX + MOV WORD PTR [dos.fileOffset+2],DX + JMP FILESDONE + +GOTDOS: + OR BYTE PTR [FILSTAT],00001000B ; Got all of DOS + push es + LES SI,[dos.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[dos.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + +CLSALLJ: JNC NOTCLSALL ;PTM P894 mt 12/8/86 + jmp clsall ; + +NotCLSALL: + push ax ; dcl 8/23/86 + + push dx ; dcl 8/23/86 + call File_cls ; dcl 8/23/86 + call Get_Command_Path ;ac011; dms; get path of + ; COMMAND.COM + call Get_COMMAND ;ac011; dms; Point to COMMAND + ; and read it + pop dx ; dcl 8/23/86 + pop ax ; dcl 8/23/86 + + JNC Found_COMMAND ;mt 12/8/86 P894 + return ;mt 12/8/86 + +Found_COMMAND: ;mt 12/8/86 + MOV BX,[command.fileHandle] + MOV [command.fileStartSegment],AX + CMP AX,DX ; No room left? + JZ CLSALLJ ; Yes + MOV CX,[command.fileSizeInParagraphs] + ADD AX,CX + CMP AX,DX + JBE GOTCOM + OR BYTE PTR [FILSTAT],00010000B ; Got part of COMMAND + SUB DX,[command.fileStartSegment] + MOV SI,DX + XOR DI,DI + CALL DISIX4 + push ds + MOV DS,[command.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JC CLSALLJ + XOR DX,DX + MOV CX,DX + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR [command.fileOffset],AX + MOV WORD PTR [command.fileOffset+2],DX + JMP FILESDONE + +GOTCOM: + OR BYTE PTR [FILSTAT],00100000B ; Got all of COMMAND + push es + LES SI,[command.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[command.fileStartSegment] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JMP CLSALL + +;************************************************** +;Write BIOS DOS COMMAND to the newly formatted disk. + +ASSUME DS:DATA +WRITEDOS: + MOV CX,BiosAttributes + MOV DX,OFFSET BiosFile + push es + LES SI,[bios.fileSizeInBytes] + MOV DI,ES + pop es + CALL MAKEFIL + retc + + MOV [TempHandle],BX + TEST BYTE PTR FILSTAT,00000010B + JNZ GOTALLBIO + call Get_BIOS ; dcl 8/23/86 + jnc Got_WBIOS ;mt 12/8/86 P894 + ret + +Got_WBIOS: + + push es + LES SI,[bios.fileOffset] + MOV DI,ES + pop es + MOV WORD PTR [IOCNT],SI + MOV WORD PTR [IOCNT+2],DI + MOV BP,OFFSET bios + CALL GOTTARG + retc + JMP SHORT BIOSDONE + +GOTALLBIO: + push es + LES SI,[bios.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[bios.fileStartSegment] + assume ds:nothing + CALL WRITEFILE + pop ds + assume ds:data +BIOSDONE: + MOV BX,[TempHandle] + MOV CX,bios.fileTime + MOV DX,bios.fileDate + CALL CLOSETARG + MOV CX,DosAttributes + MOV DX,OFFSET DosFile + push es + LES SI,[dos.fileSizeInBytes] + MOV DI,ES + pop es + CALL MAKEFIL + retc + +GOTNDOS: + MOV [TempHandle],BX + TEST BYTE PTR FILSTAT,00001000B + JNZ GOTALLDOS + call Get_DOS ; dcl 8/23/86 + jnc Got_WDOS ;mt 12/8/86 P894 + ret + +Got_WDOS: + MOV BP,OFFSET dos + TEST BYTE PTR FILSTAT,00000100B + JNZ PARTDOS + MOV WORD PTR [dos.fileOffset],0 + MOV WORD PTR [dos.fileOffset+2],0 + CALL GETSYS3 + retc + JMP SHORT DOSDONE + +PARTDOS: + push es + LES SI,[dos.fileOffset] + MOV DI,ES + pop es + MOV WORD PTR [IOCNT],SI + MOV WORD PTR [IOCNT+2],DI + CALL GOTTARG + retc + JMP SHORT DOSDONE + +GOTALLDOS: + push es + LES SI,[dos.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[dos.fileStartSegment] + assume ds:nothing + CALL WRITEFILE + pop ds + assume ds:data +DOSDONE: + MOV BX,[TempHandle] + MOV CX,dos.fileTime + MOV DX,dos.fileDate + CALL CLOSETARG + MOV CX,CommandAttributes + call Command_Root ;an011; dms;adjust path for + ;COMMAND.COM creation + MOV DX,OFFSET CommandFile + push es + LES SI,[command.fileSizeInBytes] + MOV DI,ES + pop es + CALL MAKEFIL + retc + + MOV [TempHandle],BX + TEST BYTE PTR FILSTAT,00100000B + JNZ GOTALLCOM + call Get_COMMAND ; dcl 8/23/86 + jnc Got_WCOM ;mt 12/8/86 P894 + ret + +Got_WCOM: + MOV BP,OFFSET command + TEST BYTE PTR FILSTAT,00010000B + JNZ PARTCOM + MOV WORD PTR [command.fileOffset],0 + MOV WORD PTR [command.fileOffset+2],0 + CALL GETSYS3 + retc + JMP SHORT COMDONE + +PARTCOM: + push es + LES SI,[command.fileOffset] + MOV DI,ES + pop es + MOV WORD PTR [IOCNT],SI + MOV WORD PTR [IOCNT+2],DI + CALL GOTTARG + retc + JMP SHORT COMDONE + +GOTALLCOM: + push es + LES SI,[command.fileSizeInBytes] + MOV DI,ES + pop es + push ds + MOV DS,[command.fileStartSegment] + assume ds:nothing + CALL WRITEFILE + pop ds + assume ds:data +COMDONE: + MOV BX,[TempHandle] + MOV CX,command.fileTime + MOV DX,command.fileDate + CALL CLOSETARG +;**************************************************************** +; I don't see the need for the following code!! - RS 3.20 +; CMP BYTE PTR [FILSTAT],00101010B +; JZ NOREDOS +;RDFRST2: +; CALL READDOS ; Start back with BIOS +; JNC NOREDOS +; CALL SYSPRM ;Prompt for system disk +; JMP RDFRST2 ;Try again +;NOREDOS: +;**************************************************************** + CLC + return + +;********************************************* +; Create a file on target disk +; CX = attributes, DX points to name +; DI:SI is size file is to have +; +; There is a bug in DOS 2.00 and 2.01 having to do with writes +; from the end of memory. In order to circumvent it this routine +; must create files with the length in DI:SI +; +; On return BX is handle, carry set if problem + +MAKEFIL: + MOV BX,DX + PUSH WORD PTR [BX] + MOV AL,DriveLetter + MOV [BX],AL + MOV AH,CREAT + INT 21H + POP WORD PTR [BX] + MOV BX,AX + JC CheckMany + MOV CX,DI + MOV DX,SI + MOV AX,LSEEK SHL 8 + INT 21H ; Seek to eventual EOF + XOR CX,CX + MOV AH,WRITE + INT 21H ; Set size of file to position + XOR CX,CX + MOV DX,CX + MOV AX,LSEEK SHL 8 + INT 21H ; Seek back to start + return + +; +; Examine error code in AX to see if it is too-many-open-files. +; If it is, we abort right here. Otherwise we return. +; +CheckMany: + CMP AX,error_too_many_open_files + retnz + Extended_Message ; ;AC006; + JMP FEXIT + +;********************************************* +; Close a file on the target disk +; CX/DX is time/date, BX is handle + +CLOSETARG: + MOV AX,(FILE_TIMES SHL 8) OR 1 + INT 21H + MOV AH,CLOSE + INT 21H + return + +;**************************************** +; Transfer system files +; BP points to data structure for file involved +; offset is set to current amount read in +; Start set to start of file in buffer +; TempHandle is handle to write to on target + +IOLOOP: + MOV AL,[systemDriveLetter] + CMP AL,[DriveLetter] + JNZ GOTTARG + MOV AH,DISK_RESET + INT 21H + CALL TARGPRM ;Get target disk + +GOTTARG: +ASSUME DS:DATA +;Enter here if some of file is already in buffer, IOCNT must be set +; to size already in buffer. + MOV BX,[TempHandle] + MOV SI,WORD PTR [IOCNT] + MOV DI,WORD PTR [IOCNT+2] + push ds + MOV DS,ds:[BP.fileStartSegment] + assume ds:nothing + CALL WRITEFILE ; Write next part + pop ds + assume ds:data + retc + + push es + LES AX,ds:[BP.fileOffset] + CMP AX,WORD PTR ds:[BP.fileSizeInBytes] + JNZ GETSYS3 + MOV AX,ES + CMP AX,WORD PTR ds:[BP.fileSizeInBytes+2] + JNZ GETSYS3 + pop es + return ; Carry clear from CMP + +GETSYS3: +;Enter here if none of file is in buffer + pop es + MOV AH,DISK_RESET + INT 21H + MOV AX,[MSTART] ;Furthur IO done starting here + MOV ds:[BP.fileStartSegment],AX ;point to start of buffer + MOV AL,[systemDriveLetter] ;see if we have system disk + CMP AL,[DriveLetter] + JNZ TESTSYS +GSYS: + MOV AH,DISK_RESET + INT 21H + CALL SYSPRM ;Prompt for system disk +TESTSYS: +; CALL TESTSYSDISK ; dcl 8/23/86 + JC GSYS + MOV BX,word ptr DS:[BP.fileHandle] ; CS over ARR 2.30 + push es + LES DX,dword ptr DS:[BP.fileOffset] ; CS over ARR 2.30 + MOV CX,ES + pop es + PUSH DX + MOV AX,LSEEK SHL 8 + INT 21H + POP DX + push es + LES SI,dword ptr DS:[BP.fileSizeInBytes] ; CS over ARR 2.30 + MOV DI,ES ;put high word in di + pop es + SUB SI,DX ;get low word value + SBB DI,CX ; DI:SI is #bytes to go + PUSH DI + PUSH SI + ADD SI,15 ;round up 1 para + ADC DI,0 ;pick up carry + CALL DISID4 ;div 16 to get para count + MOV AX,SI ;put para count in ax + POP SI ;restore bytes remaining + POP DI ;restore bytes remaining + CMP AX,[MSIZE] ;enough memory to read remainder? + JBE GOTSIZ2 ;yes + MOV SI,[MSIZE] + XOR DI,DI + CALL DISIX4 +GOTSIZ2: + MOV WORD PTR [IOCNT],SI ;save byte count for read + MOV WORD PTR [IOCNT+2],DI + push ds + MOV DS,[MSTART] + assume ds:nothing + CALL READFILE + pop ds + assume ds:data + JNC GETOFFS + CALL CLSALL + JMP GSYS +GETOFFS: + XOR DX,DX ;clear dx + MOV CX,DX ;clear cx + MOV AX,(LSEEK SHL 8) OR 1 + INT 21H + MOV WORD PTR DS:[BP.fileOffset],AX ; CS over ARR 2.30 + MOV WORD PTR DS:[BP.fileOffset+2],DX ; CS over ARR 2.30 +;;;;;; CALL CLSALL + JMP IOLOOP + +;************************************************* +; Test to see if correct system disk. Open handles + +CRET12: + STC + return + +;TESTSYSDISK: ; dcl 8/23/86 +Get_BIOS: ; dcl 8/23/86 + MOV AX,OPEN SHL 8 + MOV DX,OFFSET BiosFile + INT 21H + JNC SETBIOS +; call CheckMany ; dcl 8/23/86 + jmp CheckMany ; dcl 8/23/86 + +SETBIOS: + MOV [Bios.fileHandle],AX + MOV BX,AX + CALL GETFSIZ + CMP [bios.fileSizeInParagraphs],0 + JZ SETBIOSSIZ + CMP [bios.fileSizeInParagraphs],AX + JZ SETBIOSSIZ +BIOSCLS: + MOV AH,CLOSE + MOV BX,[Bios.fileHandle] + INT 21H +; JMP CRET12 ; dcl 8/23/86 + ret + +SETBIOSSIZ: + MOV [bios.fileSizeInParagraphs],AX + MOV WORD PTR [bios.fileSizeInBytes],SI + MOV WORD PTR [bios.fileSizeInBytes+2],DI + MOV [bios.fileDate],DX + MOV [bios.fileTime],CX + clc + ret ; dcl 8/23/86 + +Get_DOS: ; dcl 8/23/86 + MOV AX,OPEN SHL 8 + MOV DX,OFFSET DosFile + INT 21H + JNC DOSOPNOK +; call CheckMany ; dcl 8/23/86 +; JMP BIOSCLS ; dcl 8/23/86 Checkmany no ret. + jmp CheckMany ; dcl 8/23/86 + +DOSOPNOK: + MOV [dos.fileHandle],AX + MOV BX,AX + CALL GETFSIZ + CMP [dos.fileSizeInParagraphs],0 + JZ SETDOSSIZ + CMP [dos.fileSizeInParagraphs],AX + JZ SETDOSSIZ + +DOSCLS: + MOV AH,CLOSE + MOV BX,[dos.fileHandle] + INT 21H +; JMP BIOSCLS ; dcl 8/23/86 + ret ; dcl 8/23/86 + +SETDOSSIZ: + MOV [dos.fileSizeInParagraphs],AX + MOV WORD PTR [dos.fileSizeInBytes],SI + MOV WORD PTR [dos.fileSizeInBytes+2],DI + MOV [dos.fileDate],DX + MOV [dos.fileTime],CX + clc + ret ; dcl 8/23/86 + + + +Get_COMMAND: + MOV AX,OPEN SHL 8 + MOV DX,OFFSET CommandFile + INT 21H + JNC GotComHand +; call CheckMany ; dcl 8/23/86 +; JMP DosCls ; dcl 8/23/86 + jmp Checkmany ; dcl 8/23/86 + +GotComHand: + MOV [command.fileHandle],AX + MOV BX,AX + CALL GETFSIZ + CMP [command.fileSizeInParagraphs],0 + JZ SETCOMSIZ + CMP [command.fileSizeInParagraphs],AX + JZ SETCOMSIZ +COMCLS: + MOV AH,CLOSE + MOV BX,[command.fileHandle] + INT 21H +; JMP DOSCLS ; dcl 8/23/86 + ret ; dcl 8/23/86 + +SETCOMSIZ: + MOV [command.fileSizeInParagraphs],AX + MOV WORD PTR [command.fileSizeInBytes],SI + MOV WORD PTR [command.fileSizeInBytes+2],DI + MOV [command.fileDate],DX + MOV [command.fileTime],CX + CLC + return + +FILE_CLS: ; dcl 8/23/86 + MOV AH,CLOSE ; dcl 8/23/86 + INT 21H ; dcl 8/23/86 + ret ; dcl 8/23/86 + +;******************************************* +; Handle in BX, return file size in para in AX +; File size in bytes DI:SI, file date in DX, file +; time in CX. + +GETFSIZ: + MOV AX,(LSEEK SHL 8) OR 2 + XOR CX,CX + MOV DX,CX + INT 21H + MOV SI,AX + MOV DI,DX + ADD AX,15 ; Para round up + ADC DX,0 + AND DX,0FH ; If the file is larger than this it + ; is bigger than the 8086 address + ; space! + MOV CL,12 + SHL DX,CL + MOV CL,4 + SHR AX,CL + OR AX,DX + PUSH AX + MOV AX,LSEEK SHL 8 + XOR CX,CX + MOV DX,CX + INT 21H + MOV AX,FILE_TIMES SHL 8 + INT 21H + POP AX + return + +;******************************************** +; Read/Write file +; DS:0 is Xaddr +; DI:SI is byte count to I/O +; BX is handle +; Carry set if screw up +; +; I/O SI bytes +; I/O 64K - 1 bytes DI times +; I/O DI bytes + + +READFILE: +; Must preserve AX,DX + PUSH AX + PUSH DX + PUSH BP + MOV BP,READ SHL 8 + CALL FILIO + POP BP + POP DX + POP AX + return + +WRITEFILE: + PUSH BP + MOV BP,WRITE SHL 8 + CALL FILIO + POP BP + return + +FILIO: + XOR DX,DX + MOV CX,SI + JCXZ K64IO + MOV AX,BP + INT 21H + retc + ADD DX,AX + CMP AX,CX ; If not =, AX= 4086) +; +Phase1Initialisation proc near + +; Get device parameters + lea dx, deviceParameters + mov deviceParameters.DP_SpecialFunctions, 0 + call GetDeviceParameters + jnc GotDeviceParameters + Message msgFormatNotSupported ; ;AC000; + ;lea dx, ptr_msgFormatNotSupported + ;call std_printf + jmp fexit +GotDeviceParameters: + +; Save the device parameters for when we exit + lea si, deviceParameters + lea di, savedDeviceParameters + mov cx, size a_DeviceParameters + push ds + pop es + rep movsb + +; Ensure that there is a valid number of sectors in the track table + mov savedDeviceParameters.DP_TrackTableEntries, 0 + mov validSavedDeviceParameters, 1 + +; Initialise this to zero to know if CheckSwitches defined the track layout + mov deviceParameters.DP_TrackTableEntries, 0 + + call Set_BPB_Info ;an000; dms; Check to see if we are on + ; FAT system. If not set BPB to proper + ; values for format. +SetMTsupp: + +; Check switches against parameters and use switches to modify device parameters + call CheckSwitches + retc + +IF ShipDisk + + test SwitchMap,Switch_Z ;an000; dms;1 sector/cluster disk? +; $if nz ;an000; dms;yes + JZ $$IF19 + mov DeviceParameters.DP_BPB.BPB_SectorsPerCluster,01h ;an000; dms;set BPB accordingly + call Calc_Small_Fat ;an000; dms;calc FAT size +; $endif ;an000; dms; +$$IF19: + +ENDIF + + + cmp deviceParameters.DP_TrackTableEntries, 0 + jne TrackLayoutSet ; There is a good track layout + +; Store sector table info + mov cx, deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov deviceParameters.DP_TrackTableEntries, cx + mov ax, 1 + mov bx, deviceParameters.DP_BPB.BPB_bytesPerSector + lea di, deviceParameters.DP_SectorTable +LoadSectorTable: + stosw + xchg ax, bx + stosw + xchg ax, bx + inc ax + loop LoadSectorTable +TrackLayoutSet: + +; +; directorySector = malloc( Bytes Per Sector ) +; + mov bx, deviceParameters.DP_BPB.BPB_BytesPerSector + add bx, 0fH + shr bx, 1 + shr bx, 1 + shr bx, 1 + shr bx, 1 + mov ah, Alloc + int 21H + retc + mov word ptr directorySector+2, ax + xor ax,ax + mov word ptr directorySector, ax + +; +; fatSpace = malloc( Bytes Per Sector * Sectors Per FAT ) +; + mov ax, deviceParameters.DP_BPB.BPB_BytesPerSector + add ax, 0fH + shr ax, 1 + shr ax, 1 + shr ax, 1 + shr ax, 1 + mul deviceParameters.DP_BPB.BPB_SectorsPerFAT + mov Paras_Per_Fat,ax ;AN005;128k FAT + mov bx,ax + mov ah,Alloc + int 21H + retc + mov word ptr fatSpace+2,ax + xor ax,ax + mov word ptr fatSpace,ax + + call SetStartSector + call SetfBigFat + + clc + return + +Phase1Initialisation endp + +;------------------------------------------------------------------------------- + +SetStartSector proc near + +; startSector = number of reserved sectors +; + number of FAT Sectors ( Number of FATS * Sectors Per FAT ) +; + number of directory sectors ( 32* Root Entries / bytes Per Sector ) +; ( above is rounded up ) + +; Calculate the number of directory sectors + mov ax, deviceParameters.DP_BPB.BPB_RootEntries + mov bx, size dir_entry + mul bx + add ax, deviceParameters.DP_BPB.BPB_bytesPerSector + dec ax + xor dx,dx + div deviceParameters.DP_BPB.BPB_bytesPerSector + mov sectorsInRootDirectory,ax + mov startSector, ax + +; Calculate the number of FAT sectors + mov ax, deviceParameters.DP_BPB.BPB_SectorsPerFAT + mul deviceParameters.DP_BPB.BPB_numberOfFATs +; Add in the number of boot sectors + add ax, deviceParameters.DP_BPB.BPB_ReservedSectors + add startSector, ax + + return + +SetStartSector endp + +;------------------------------------------------------------------------------- + +SetfBigFat proc near +; +; fBigFat = ( ( (Total Sectors - Start Sector) / Sectors Per Cluster) >= 4086 ) +; + cmp deviceParameters.DP_BPB.BPB_BigTotalSectors+2,0 ; > 32mb part? ;AN000; +; $IF NE ;Yes, big FAT ;AC000; + JE $$IF21 + mov fBigFat, TRUE ;Set flag ;AN000; +; $ELSE ;Nope, < 32,b ;AC000; + JMP SHORT $$EN21 +$$IF21: + mov ax,deviceParameters.DP_BPB.BPB_BigTotalSectors ;Assume this used ;AN000; + cmp ax,0 ;Was this field used? ;AN000; +; $IF E ;Nope, use the other sector field;AN000; + JNE $$IF23 + mov ax, deviceParameters.DP_BPB.BPB_TotalSectors ; ;AC000; + ;** Fix for PTM PCDOS P51 +; $ENDIF ; ;AN000; +$$IF23: + sub ax,startSector ;Get sectors in data area + xor dx,dx + xor bx,bx + mov bl,deviceParameters.DP_BPB.BPB_sectorsPerCluster + div bx ;Get total clusters + cmp ax,BIG_FAT_THRESHOLD ;Is clusters >= 4086? +; $IF AE + JNAE $$IF25 + mov fBigFAT,TRUE ;16 bit FAT if >=4096 + ;** END fix for PTM PCDOS P51 +; $ENDIF +$$IF25: +; $ENDIF +$$EN21: + return + +SetfBigFat endp + +;------------------------------------------------------------------------------- +; +; Phase2Initialisation: +; Use device parameters to build information that will be +; required for each format +; +; Algorithm: +; Calculate first head/cylinder to format +; Calculate number of tracks to format +; Calculate the total bytes on the disk and save for later printout +; First initialise the directory buffer +; +Phase2Initialisation proc near + +; Calculate first track/head to format (round up - kludge) + mov ax, deviceParameters.DP_BPB.BPB_HiddenSectors + mov dx, deviceParameters.DP_BPB.BPB_HiddenSectors + 2 + add ax, deviceParameters.DP_BPB.BPB_SectorsPerTrack + adc dx, 0 + dec ax + sbb dx, 0 + div deviceParameters.DP_BPB.BPB_SectorsPerTrack + xor dx,dx + div deviceParameters.DP_BPB.BPB_Heads + mov firstCylinder, ax + mov firstHead, dx + +; Calculate the total number of tracks to be formatted (round down - kludge) + mov ax, deviceParameters.DP_BPB.BPB_TotalSectors + xor dx,dx +; if (TotalSectors == 0) then use BigTotalSectors + or ax,ax + jnz NotBigTotalSectors + mov ax, deviceParameters.DP_BPB.BPB_BigTotalSectors + mov dx, deviceParameters.DP_BPB.BPB_BigTotalSectors + 2 + +NotBigTotalSectors: + div deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov tracksPerDisk, ax + +; Initialise the directory buffer +; Clear out the Directory Sector before any information is inserted. + mov cx, deviceParameters.DP_BPB.BPB_BytesPerSector + les di, directorySector + xor ax,ax + rep stosb + + mov ax, deviceParameters.DP_BPB.BPB_BytesPerSector + xor dx, dx + mov bx, size dir_entry + div bx + mov cx, ax + + les bx, directorySector +; If Old_Dir = TRUE then put the first letter of each directory entry must be 0E5H + xor al, al + cmp old_Dir, TRUE + jne StickE5 + mov al, 0e5H +StickE5: + mov es:[bx], al + add bx, size dir_entry + loop stickE5 + + ret + +Phase2Initialisation endp + +;------------------------------------------------------------------------------- +; +; SetDeviceParameters: +; Set the device parameters +; +; Input: +; drive +; dx - pointer to device parameters +; +SetDeviceParameters proc near + + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + mov bl, drive + inc bl + mov cx, (RAWIO shl 8) or SET_DEVICE_PARAMETERS + int 21H + return + +SetDeviceParameters endp + +;------------------------------------------------------------------------------- +; +; GetDeviceParameters: +; Get the device parameters +; +; Input: +; drive +; dx - pointer to device parameters +; +GetDeviceParameters proc near + + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + mov bl, drive + inc bl + mov cx, (RAWIO shl 8) or GET_DEVICE_PARAMETERS + int 21H + return + +GetDeviceParameters endp + +;------------------------------------------------------------------------------- +; +; DiskFormat: +; Format the tracks on the disk +; Since we do our SetDeviceParameters here, we also need to +; detect the legality of /N /T if present and abort with errors +; if not. +; This routine stops as soon as it encounters a bad track +; Then BadSector is called to report the bad track, and it continues +; the format +; +; Algorithm: +; Initialise in memory FAT +; current track = first +; while not done +; if format track fails +; DiskFormatErrors = true +; return +; next track + +DiskFormat proc near + + +; +; Initialise fatSpace +; + + + push es + + call Fat_Init ;an000; initialize the FAT + + mov di, word ptr fatspace+2 ;an000; get segment of FAT + mov es, di ;an000; place it in es + mov di, word ptr fatSpace ;Should be 0 + mov al, deviceParameters.DP_BPB.BPB_MediaDescriptor + mov ah, 0ffH + stosw + mov ax, 00ffH + test fBigFat, TRUE + jz NotBig + mov ax, 0ffffH +NotBig: stosw + pop es + +; don't bother to do the formatting if /c was given + test switchmap, SWITCH_C + jz Keep_Going + jmp FormatDone ;FormatDone is to far away + +Keep_Going: +foofoo = INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD + mov deviceParameters.DP_SpecialFunctions, foofoo + lea dx, deviceParameters + + call SetDeviceParameters + + call Cluster_Buffer_Allocate ;an000; dms;get room for retry buffer + + call Prompt_User_For_Disk ;an016; dms; + + test switchmap,switch_8 ; DCL 5/12/86 avoid Naples AH=18h + jnz stdBpB ; lackof support for 8 sectors/track + + ; DCL 5/12/86 + ; Always do the STATUS_FOR_FORMAT test, as we don't know if the machine + ; has this support. For 3.2 /N: & /T: were not documented & therefore + ; not fully supported thru the ROM of Aquarius & Naples & Royal Palm + + ;test SwitchMap, SWITCH_N or SWITCH_T ; IF ( /N or /T ) ;; DCL 5/12/86 + ;jz StdBPB + ; THEN check if + ; supported + mov formatPacket.FP_SpecialFunctions, STATUS_FOR_FORMAT + mov ax, (IOCTL shl 8) or GENERIC_IOCTL + mov bl, drive + inc bl + mov cx, (RAWIO shl 8) or FORMAT_TRACK + lea dx, formatPacket + int 21H + ; switch ( FormatStatusCall) + + ;cmp FormatPacket.FP_SpecialFunctions, Format_No_ROM_Support + ;jb NTSupported ; 0 returned from IBMBIO + ;ja IllegalComb ; 2 returned - ROM Support + ; Illegal Combination! + cmp FormatPacket.FP_SpecialFunctions,0 + je NTSupported + cmp FormatPacket.FP_SpecialFunctions,2 +; $IF E ; ;AC000; + JNE $$IF28 + Message msgInvalidParameter ; ;AC000; + mov Fatal_Error,Yes ;Indicate quittin'type err! ;AN000; +; $ELSE ; ; ; + JMP SHORT $$EN28 +$$IF28: + cmp FormatPacket.FP_SpecialFunctions,3 ; ; ; +; $IF E ; ;AC000; + JNE $$IF30 + mov ax,Error_Not_Ready ;flag not ready ;an000;dms; + call CheckError ; set error level ;an017; dms; + jmp FrmtProb ; exit program ;an017; dms; +; $ELSE ; DCL No ROM support is okay ; ; + JMP SHORT $$EN30 +$$IF30: + ; except for /N: & /T: ; ; + test SwitchMap, SWITCH_N or SWITCH_T ; DCL 5/12/86 ; ; +; $IF NZ ; ;AC000; + JZ $$IF32 + Message msgParametersNotSupported ; ;AC000; + mov Fatal_Error,Yes ;Indicate quittin'type err! ;AN000; +; $ENDIF ; ;AN000; +$$IF32: +; $ENDIF ; ;AN000; +$$EN30: +; $ENDIF ; ;AN000; +$$EN28: + cmp Fatal_Error,Yes ; ;AN000; + jne StdBPB ; ;AN000; + jmp Fexit +; +; We have the support to carry out the FORMAT +; +NTSupported: +StdBPB: + ;call DSKPRM ; prompt user for disk ;; DCL 5/12/86 + mov FormatPacket.FP_SpecialFunctions, 0 + mov ax, firstHead + mov formatPacket.FP_Head, ax + mov ax, firstCylinder + mov formatPacket.FP_Cylinder, ax + mov cx, tracksPerDisk + mov tracksLeft, cx + mov Format_End,False ;an015; dms;flag not at end of format + call Calc_Max_Tracks_To_Format ;an015; dms;max track count for FormatTrack call +FormatLoop: + call Format_Loop ;an015; dms;Format until CY occurs + + cmp Format_End,True ;an015; dms;End of Format? +; $if e ;an015; dms;yes + JNE $$IF36 + mov FormatError,0 ;an015; dms;signal good format + clc ;an015; dms;clear CY +; $else ;an015; dms;bad format + JMP SHORT $$EN36 +$$IF36: + call CheckError ;an015; dms;determine type of error +; $if nc ;an015; dms; + JC $$IF38 + call LastChanceToSaveIt ;an015; dms;acceptable error? +; $if c ;an015; dms;yes + JNC $$IF39 + mov FormatError,1 ;an015; dms;signal error type + clc ;an015; dms;clear CY +; $else ;an015; dms;not acceptable error + JMP SHORT $$EN39 +$$IF39: + call SetStartSector ;an015; dms;start from scratch + call SetFBigFat ;an015; dms; + push ax ;an015; dms; + call Phase2Initialisation ;an015; dms; + clc ;an015; dms; + pop ax ;an015; dms; + jmp DiskFormat ;an015; dms;try again +; $endif ;an015; dms; +$$EN39: +; $endif ;an015; dms; +$$IF38: +; $endif ;an015; dms; +$$EN36: + return + +FormatDone: + mov FormatError,0 + clc + return + +DiskFormat endp + + +;------------------------------------------------------------------------------- +; +; BadSector: +; Reports the bad sectors. +; Reports the track where DiskFormat stopped. +; From then on it formats until it reaches a bad track, or end, +; and reports that. +; +; Output: +; Carry: set --> fatal error +; if Carry not set +; ax - The number of consecutive bad sectors encountered +; ax == 0 --> no more bad sectors +; bx - The logical sector number of the first bad sector +; +; Algorithm: +; if DiskFormatErrors +; DiskFormatErrors = false +; return current track +; else +; next track +; while not done +; if format track fails +; return current track +; next track +; return 0 + +BadSector proc near + + +; don't bother to do the formatting if /c was given + test switchmap, SWITCH_C + jnz NoMoreTracks + + test formatError, 0ffH + jz ContinueFormat + mov formatError, 0 + jmp ReportBadTrack + +ContinueFormat: + call Adj_Track_Count ;an015; dms;decrease track counter + call NextTrack ;an015; dms;adjust head and cylinder + cmp Format_End,True ;an015; dms;end of format? +; $if ne ;an015; dms;no + JE $$IF44 + call Format_Loop ;an015; dms;format until CY + cmp Format_End,True ;an015; dms;end of format? +; $if ne ;an015; dms;no + JE $$IF45 + call CheckError ;an015; dms;must be error - which error? +; $if nc ;an015; dms;non-fatal error? + JC $$IF46 + call CurrentLogicalSector ;an015; dms;yes - get position + mov ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an015; dms; set track size + clc ;an015; dms;signal O.K. to continue +; $endif ;an015; dms; +$$IF46: +; $else ;an015; dms; + JMP SHORT $$EN45 +$$IF45: + jmp NoMoreTracks ;an015; dms;end of format +; $endif ;an015; dms; +$$EN45: +; $else ;an015; dms; + JMP SHORT $$EN44 +$$IF44: + jmp NoMoreTracks ;an015; dms;end of format +; $endif ;an015; dms; +$$EN44: + return ;an015; dms; + +ReportBadTrack: + call CurrentLogicalSector + mov ax, deviceParameters.DP_BPB.BPB_SectorsPerTrack + clc + return + +NoMoreTracks: + test SwitchMap,(Switch_Select or SWITCH_AUTOTEST) ;Don't display done msg;AN000; +; $IF Z ; if EXEC'd by SELECT ;AN000; + JNZ $$IF52 + Message msgFormatComplete ; ;AC000; +; $ENDIF ; ;AN000; +$$IF52: + mov ax, 0 + clc + return + +BadSector endp + + + +;------------------------------------------------------------------------------- + +data segment public para 'DATA' + +;ptr_msgCurrentTrack dw offset msgCurrentTrack +currentHead dw 0 +currentCylinder dw 0 + +data ends + +;========================================================================= +; Calc_Current_Head_Cyl : Obtain the current head and cylinder of the +; track being formatted. +; +; Inputs: FP_Cylinder - Cylinder of track being formatted +; FP_Head - Head of track being formatted +;========================================================================= + +Procedure Calc_Current_Head_Cyl ;an000; dms; + + push cx ;an000; dms;save cx + mov cx,FormatPacket.FP_Cylinder ;an000; dms;get current cylinder + mov CurrentCylinder,cx ;an000; dms;put into variable + mov cx,FormatPacket.FP_Head ;an000; dms;get current head + mov CurrentHead,cx ;an000; dms;put into variable + pop cx ;an000; dms;restore cx + ret ;an000; dms; + +Calc_Current_Head_Cyl endp ;an000; dms; + + +DisplayCurrentTrack proc near + + push dx ; ;AN000; + push cx ; ;AN000; + push ax ;an015; dms; + + mov ax,Tracks_To_Format ;an015; dms;get track count + + add Formatted_Tracks_Low,ax ;Indicate formatted a track ;AN000; + adc Formatted_Tracks_High,0 ; ;AN000; + mov ax,Formatted_Tracks_Low ; ;AN000; + mov bx,Formatted_Tracks_High ; ;AN000; + mov cx,100 ;Make integer calc for div ;AN000; + call Multiply_32_Bits ; BX:AX = (Cyl * Head *100) ;AN000; + mov dx,bx ;Set up divide ;AN000; + div TracksPerDisk ;% = (Cyl * Head *100)/ # tracks;AN000; + cmp ax,PercentComplete ;Only print message when change ;AN000; +; $IF NE ;To avoid excess cursor splat ;AN000; + JE $$IF54 + mov PercentComplete,ax ;Save it if changed ;AN000; + Message msgCurrentTrack ; ;AC000; +; $ENDIF ; +$$IF54: + pop ax ;an015; dms; + pop cx ;Restore register ;AN000; + pop dx ; ;AN000; + return + +DisplayCurrentTrack endp + + +;------------------------------------------------------------------------------- +; CheckError: +; Input: +; ax - extended error code +; Ouput: +; carry set if error is fatal +; Message printed if Not Ready or Write Protect +; +CheckError proc near + cmp ax, error_write_protect + je WriteProtectError + cmp ax, error_not_ready + je NotReadyError + cmp currentCylinder, 0 + jne CheckRealErrors + cmp currentHead, 0 + je BadTrackZero + +CheckRealErrors: + cmp ax, error_CRC + je JustABadTrack + cmp ax, error_sector_not_found + je JustABadTrack + cmp ax, error_write_fault + je JustABadTrack + cmp ax, error_read_fault + je JustABadTrack + cmp ax, error_gen_failure + je JustABadTrack + + stc + ret + +JustABadTrack: + clc + ret + +WriteProtectError: + + test SwitchMap,Switch_SELECT ;an017; dms;SELECT option? +; $if z ;an017; dms;no - display messages + JNZ $$IF56 + Message msgCRLF ; ;AC006; + Message msgCRLF ; ;AC006; + Extended_Message ; ;AC006; +; $else ;an017; dms;yes - set error level + JMP SHORT $$EN56 +$$IF56: + mov ExitStatus,ExitWriteProtect ;an017; dms;signal write protect error +; $endif ;an017; dms; +$$EN56: + + stc ;an017; dms;signal fatal error + ret ;an017; dms;return to caller + +NotReadyError: + test SwitchMap,Switch_SELECT ;an017; dms; SELECT option? +; $if z ;an017; dms; no - display messages + JNZ $$IF59 + Message msgCRLF ; ;AC006; + Message msgCRLF ; ;AC006; + Extended_Message ; ;AC006; +; $else ;an017; dms;yes - set error level + JMP SHORT $$EN59 +$$IF59: + mov ExitStatus,ExitDriveNotReady ;an017; dms;signal drive not ready +; $endif ;an017; dms; +$$EN59: + stc + ret + + +BadTrackZero: + Message msgDiskUnusable ; ;AC000; + stc + ret + +CheckError endp + +;------------------------------------------------------------------------------- +; WriteFileSystem: +; Write the boot sector and FATs out to disk +; Clear the directory sectors to zero +; + +WriteFileSystem proc near + + + call WriteBootSector + retc + + Set_Data_Segment ;Set DS,ES = DATA ;AN000; +; Write out each of the FATs + push ds ;ac005; dms;save ds + xor cx, cx + mov cl, es:deviceParameters.DP_BPB.BPB_numberOfFATs ; ;AC000; + mov dx, es:deviceParameters.DP_BPB.BPB_ReservedSectors ; ;AC000; + mov al, es:drive ; ;AC000; + mov bx,word ptr es:FatSpace+2 ;Get segment of memory Fat ;AC000; + mov ds,bx ; ;AN000; + mov bx,word ptr es:FatSpace ; ;AN000; + + mov si,bx ;ac005; dms;set up for add. calc + call SEG_ADJ ;ac005; dms;get adjusted seg:off + mov bx,si ;ac005; dms;get new off + assume ds:nothing,es:data ; ;AN000; + +; $do ;ac005; dms;while FATS > 0 +$$DO62: + cmp cx,00 ;ac005; dms;FATS remaining? +; $leave e ;ac005; dms;no + JE $$EN62 + push bx ;ac005; dms;save FAT offset + push ds ;ac005; dms;save FAT segment + push cx ;ac005; dms;save FAT count + push dx ;ac005; dms;reserved FAT sector + call WRITE_FAT ;ac005; dms;write the FAT + pop dx ;ac005; dms;get 1st. FAT sector + pop cx ;ac005; dms;get FAT count + pop ds ;ac005; dms;restore FAT segment + pop bx ;ac005; dms;restore FAT offset +; $if c ;ac005; dms;an error occurred + JNC $$IF64 + Message msgFATwriteError;ac005; dms;say why failed + jmp FEXIT ;ac005; dms;exit format +; $endif ;ac005; dms; +$$IF64: + add dx, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000; + dec cx ;ac005; dms;decrease FAT count +; $enddo ;ac005; dms; + JMP SHORT $$DO62 +$$EN62: + + pop ds ;ac005; dms;restore ds + assume ds:data ;ac005; dms; + + +; Clear the directory + +; Now write the initialised directory sectors out to disk + mov ax, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000; + xor dx,dx + push bx ;an000; dms;save bx + xor bx,bx ;an000; dms;clear bx + mov bl,es:DeviceParameters.DP_BPB.BPB_NumberOfFATs ;an000; dms;get FAT count + mul bx ;an000; dms;get total FAT sectors + pop bx ;an000; dms;restore bx + + mov dx, es:deviceParameters.DP_BPB.BPB_ReservedSectors ; ;AC000; + add dx, ax + mov cx, es:sectorsInRootDirectory ; ;AC000; +WriteDIRloop: + push cx + push dx + mov al, es:drive ; ;AC000; + mov cx, 1 + lds bx, es:directorySector ; ;AC000; + + assume ds:nothing,es:data ; ;AN000; + +;Assume dir is alway contined in first 32mb of partition + + mov es:Read_Write_Relative.Start_Sector_High,0 ; ;AC000; + Call Write_Disk ; ;AN000; + jnc Dir_OK ; ;AC000; + Message msgDirectoryWriteError ; ;AC000; + jmp FExit ; ;AN000; +Dir_OK: ; ;AN000; + pop dx + add dx, 1 + pop cx + loop WriteDIRLoop + + Set_Data_Segment ;Set DS to DATA segment ;AN000; +; Ok, we can tell the device driver that we are finished formatting + mov savedDeviceParameters.DP_TrackTableEntries, 0 + mov savedDeviceParameters.DP_SpecialFunctions, TRACKLAYOUT_IS_GOOD + lea dx, savedDeviceParameters + call SetDeviceParameters + + MOV AH,DISK_RESET ; Flush any directories in + INT 21H ; buffers + + return + + +WriteFileSystem endp + +;========================================================================= +; WRITE_FAT : This routine writes the logical sector count requested. +; It will write a maximum of 40h sectors. If more +; than 40h exists it will continue looping until +; all sectors have been written. +; +; Inputs : AL - Drive letter +; DS:BX - Segment:offset of transfer address +; CX - Sector count +; DX - 1st. sector +; +; Outputs : Logical sectors written +;========================================================================= + +procedure write_fat + + mov cx, es:deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AC000; + +; $do ;an000;while sectors left +$$DO67: + cmp cx,00h ;an000;any sectors? +; $leave e ;an000;no + JE $$EN67 + + cmp cx,40h +; $if a ;an000;yes + JNA $$IF69 + push cx ;an000;save cx + mov cx,40h + push ax ;an000;save ax + call write_disk ;an000;write it + pop ax ;an000;restore ax + pop cx ;an000;restore cx + jc Write_Exit ;an000;exit if fail + mov si,8000h + call seg_adj ;an000;adjust segment + mov bx,si ;an000;new offset + add dx,40h + sub cx,40h +; $else ;an000;< 64k + JMP SHORT $$EN69 +$$IF69: + push ax ;an000;save ax + call write_disk ;an000;write it + pop ax ;an000;restore ax + xor cx,cx ;an000;set cx to 0 - last read +; $endif +$$EN69: +; $enddo + JMP SHORT $$DO67 +$$EN67: + + Write_Exit: + + ret + +write_fat endp + +;========================================================================= +; SEG_ADJ : This routine adjusts the segment:offset to prevent +; address wrap. +; +; Inputs : SI - Offset to adjust segment with +; DS - Segment to be adjusted +; +; Outputs : SI - New offset +; DS - Adjusted segment +;========================================================================= + +procedure seg_adj + + push ax + push cx + push dx + mov ax,si ;an000;get offset + mov bx,0010h ;an000;16 + xor dx,dx ;an000;clear dx + div bx ;an000;get para count +; $if c ;an000;overflow? + JNC $$IF73 + adc bx,0 ;an000;pick it up +; $endif ;an000; +$$IF73: + mov bx,ds ;an000;get seg + add bx,ax ;an000;adjust for paras + mov ds,bx ;an000;save new seg + mov si,dx ;an000;new offset + pop dx + pop cx + pop ax + ret + +seg_adj endp + +;------------------------------------------------------------------------------- +; format is done... so clean up the disk! +; +Done proc near + + + call OemDone + return + +Done endp + +;------------------------------------------------------------------------------- +; CurrentLogicalSector: +; Get the current logical sector number +; +; Input: +; current track = tracksPerDisk - tracksLeft +; SectorsPerTrack +; +; Output: +; BX = logical sector number of the first sector in the track we +; just tried to format +; +CurrentLogicalSector proc near + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push dx ;an000; dms; + + mov ax, tracksPerDisk + sub ax, tracksLeft + xor dx,dx ;an000; dms;clear dx + mul deviceParameters.DP_BPB.BPB_SectorsPerTrack + mov word ptr Relative_Sector_High,dx ;an000; dms;save high word of sector # + mov word ptr Relative_Sector_Low,ax ;an000; dms;save low word of sector # + + pop dx ;an000; dms;restore regs + pop bx ;an000; dms; + pop ax ;an000; dms; + + return + +CurrentLogicalSector endp + +;------------------------------------------------------------------------------- +; PrintErrorAbort: +; Print an error message and abort +; +; Input: +; dx - Pointer to error message string +; +PrintErrorAbort proc near + + push dx + call crlf + pop dx + call PrintString + + jmp fexit + +PrintErrorAbort endp + + + + +;***************************************************************************** +;Routine name: Multiply_32_Bits +;***************************************************************************** +; +;Description: A real sleazy 32 bit x 16 bit multiply routine. Works by adding +; the 32 bit number to itself for each power of 2 contained in the +; 16 bit number. Whenever a bit that is set in the multiplier (CX) +; gets shifted to the bit 0 spot, it means that that amount has +; been multiplied so far, and it should be added into the total +; value. Take the example CX = 12 (1100). Using the associative +; rule, this is the same as CX = 8+4 (1000 + 0100). The +; multiply is done on this principle - whenever a bit that is set +; is shifted down to the bit 0 location, the value in BX:AX is +; added to the running total in DI:SI. The multiply is continued +; until CX = 0. The routine will exit with CY set if overflow +; occurs. +; +; +;Called Procedures: None +; +;Change History: Created 7/23/87 MT +; +;Input: BX:AX = 32 bit number to be multiplied +; CX = 16 bit number to be multiplied. (Must be even number) +; +;Output: BX:AX = output. +; CY set if overflow +; +;Psuedocode +;---------- +; +; Point at ControlC_Handler routine +; Set interrupt handler (INT 21h, AX=2523h) +; ret +;***************************************************************************** + +Public Multiply_32_Bits +Multiply_32_Bits proc ; ;AN000; + + push di ; ;AN000; + push si ; ;AN000; + xor di,di ;Init result to zero + xor si,si ; + cmp cx,0 ;Multiply by 0? ;AN000; +; $IF NE ;Keep going if not ;AN000; + JE $$IF75 +; $DO ;This works by adding the result;AN000; +$$DO76: + test cx,1 ;Need to add in sum of this bit?;AN000; +; $IF NZ ;Yes ;AN000; + JZ $$IF77 + add si,ax ;Add in the total so far for ;AN000; + adc di,bx ; this bit multiplier (CY oflow);AN000; +; $ELSE ;Don't split multiplier ;AN000; + JMP SHORT $$EN77 +$$IF77: + clc ;Force non exit ;AN000; +; $ENDIF ; ;AN000; +$$EN77: +; $LEAVE C ;Leave on overflow ;AN000; + JC $$EN76 + shr cx,1 ;See if need to multiply value ;AN000; + cmp cx,0 ;by 2 ;AN000; +; $LEAVE E ;Done if cx shifted down to zero;AN000; + JE $$EN76 + add ax,ax ;Each time cx is shifted, add ;AN000; + adc bx,bx ;value to itself (Multiply * 2) ;AN000; +; $ENDDO C ;CY set on overflow ;AN000; + JNC $$DO76 +$$EN76: +; $IF NC ;If no overflow, add in DI:SI ;AN000; + JC $$IF83 + mov ax,si ; which contains the original ;AN000; + mov bx,di ; value if odd, 0 if even. This ;AN000; + clc ;Set no overflow flag ;AN000; +; $ENDIF ; ;AN000; +$$IF83: +; $ELSE ; + JMP SHORT $$EN75 +$$IF75: + xor ax,ax ; + xor bx,bx ; +; $ENDIF ;Multiply by 0 ;AN000; +$$EN75: + pop si ; ;AN000; + pop di ; ;AN000; + ret ; ;AN000; + +Multiply_32_Bits endp + + +;========================================================================= +; Divide_32_Bits - This routine will perform 32bit division +; +; Inputs : SI:DI - value to be divided +; CX - divisor +; +; Outputs : SI:DI - result +; CX - remainder +;========================================================================= + +Procedure Divide_32_Bits ;an000; dms; + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push dx ;an000; dms; + + xor dx,dx ;an000; dms;clear dx + mov ax,si ;an000; dms;get high word + div cx ;an000; dms;get high word result + mov si,ax ;an000; dms;save high word result + + mov ax,di ;an000; dms;get low word + div cx ;an000; dms;get low word result + mov di,ax ;an000; dms;save low word result + mov cx,dx ;an000; dms;pick up remainder + + pop dx ;an000; dms;restore regs + pop bx ;an000; dms; + pop ax ;an000; dms; + + ret ;an000; dms; + +Divide_32_Bits endp ;an000; dms; + + + + +;========================================================================= +; FAT_INIT: This routine initializes the FAT based on the +; number of paragraphs. +; +; +; input - fatspace +; fatspace+2 +; paras_per_fat +; fat_init_value +; output - fat space is initialized +; +;========================================================================= +Public Fat_Init +Fat_Init proc near + + push es + push di + push ax + push bx + push cx + mov di, word ptr FatSpace+2 ;Get segment of Fat space ;AC000; + mov es,di ; ;AN000; + mov di, word ptr FatSpace ; ;AN000; + mov bx,Paras_Per_Fat ;an000;get number of paras + mov ax,fat_init_value ;an000; + push dx ;an000;save bx + mov dx,es ;an000;grab es into dx +; $do +$$DO87: + cmp bx,0 ;an000;do while bx not = 0 +; $leave e ;an000;exit if 0 + JE $$EN87 + mov cx,10h ;an000;word move of paragraph + rep stosb ;an000;move the data to FAT + xor di,di ;an000;offset always init to 0 + inc dx ;an000;next paragraph + mov es,dx ;an000;put next para in es + dec bx ;an000;loop iteration counter +; $enddo ;an000; + JMP SHORT $$DO87 +$$EN87: + pop dx ;an000; + pop cx ;an000; + pop bx ;an000; + pop ax ;an000; + pop di ;an000; + pop es ;an000; + + ret ;an000; + +Fat_Init endp ;an000; + + +;========================================================================= +; Ctrl_Break_Write : This routine takes the control break request +; an returns. In essence, it disables the CTRL-BREAK. +; This routine is used during the writing of the +; FAT, DIR, and SYSTEM. +;========================================================================= + +Ctrl_Break_Write: ;ac010; dms; + + iret ;ac010; dms;return to caller + + +;========================================================================= +; Ctrl_Break_Save : This routine gets the current vector of +; INT 23h and saves it in CTRL_BREAK_VECTOR. +; +; Inputs : none +; +; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine +;========================================================================= + +Ctrl_Break_Save proc near ;ac010; dms; + + push es ;ac010; dms;save es + push bx ;ac010; dms;save bx + push ax ;ac010; dms;save ax + + mov ax,3523h ;ac010; dms;get CTRL-BREAK + ; interrupt vector + int 21h ;ac010; dms; + + mov word ptr Ctrl_Break_Vector,bx ;ac010; dms;get vector offset + mov word ptr Ctrl_Break_Vector+2,es ;ac010; dms;get vector segment + + pop ax ;ac010; dms;restore ax + pop bx ;ac010; dms;restore bx + pop es ;ac010; dms;restore es + + ret ;ac010; dms; + + +Ctrl_Break_Save endp ;ac010; dms; + + +;========================================================================= +; Set_Ctrl_Break : This routine sets the CTRL-Break vector to one +; defined by the user. +; +; Inputs : none +; +; Outputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine +;========================================================================= + +Set_Ctrl_Break proc near ;ac010; dms; + + push ds ;ac010; dms;save ds + push ax ;ac010; dms;save ax + push bx ;ac010; dms;save bx + push dx ;ac010; dms;save dx + + push cs ;ac010; dms;swap cs with ds + pop ds ;an000; dms;point to code seg + + mov dx,offset Ctrl_Break_Write ;ac010; dms;get interrupt vec. + mov ax,2523h ;ac010; dms;set CTRL-BREAK + ; interrupt vector + int 21h ;ac010; dms; + + pop dx ;ac010; dms;restore dx + pop bx ;ac010; dms;restore bx + pop ax ;ac010; dms;restore ax + pop ds ;ac010; dms;restore ds + + ret ;ac010; dms; + + +Set_Ctrl_Break endp ;ac010; dms; + + +;========================================================================= +; Reset_Ctrl_Break : This routine resets the CTRL-Break vector to that +; originally defined. +; +; Inputs : CTRL_BREAK_VECTOR - holds address of INT 23h routine +; +; Outputs : none +;========================================================================= + +Reset_Ctrl_Break proc near ;ac010; dms; + + push ds ;ac010; dms;save ds + push ax ;ac010; dms;save ax + push bx ;ac010; dms;save bx + push dx ;ac010; dms;save ds + + mov ax,word ptr Ctrl_Break_Vector+2 ;ac010; dms;get seg. of vector + mov bx,word ptr Ctrl_Break_Vector ;ac010; dms;get off. of vector + mov ds,ax ;ac010; dms;get seg. + mov dx,bx ;ac010; dms;get off. + mov ax,2523h ;ac010; dms;set CTRL-BREAK + ; interrupt vector + int 21h ;ac010; dms; + + pop dx ;ac010; dms;restore dx + pop bx ;ac010; dms;restore bx + pop ax ;ac010; dms;restore ax + pop ds ;ac010; dms;restore ds + + ret ;ac010; dms; + + +Reset_Ctrl_Break endp ;ac010; dms; + +;========================================================================= +; Get_Command_Path : This routine finds the path where +; COMMAND.COM resides based on the +; environmental vector. Once the +; path is found it is copied to +; CommandFile. +; +; Inputs : Exec_Block.Segment_Env - Segment of environmental vector +; Comspec_ID - "COMSPEC=" +; +; Outputs : CommandFile - Holds path to COMMAND.COM +;========================================================================= + +Procedure Get_Command_Path ;an011; dms; + + push ds ;an011; dms;save ds + push es ;an011; dms;save es + + Set_Data_Segment ;an011; dms; DS,ES = Data + call Get_PSP_Parms ;an011; dms; gets PSP info. + cld ;an011; dms; clear direction + mov ax,es:Environ_Segment ;an011; dms; get seg. of + ; environ. vector + mov ds,ax ;an011; dms; put it in DS + assume ds:nothing ;an011; dms; + xor si,si ;an011; dms; clear si + mov bx,si ;an011; dms; save si + mov di,offset Comspec_ID ;an011; dms; point to target + mov cx,127 ;an011; dms; loop 127 times +; $do ;an011; dms; while cx not 0 +$$DO90: + ; and target not found + cmp cx,00h ;an011; dms; end of env.? +; $leave e ;an011; dms; yes + JE $$EN90 + + push cx ;an011; dms; save cx + mov cx,0008h ;an011; dms; loop 8 times + repe cmpsb ;an011; dms; "COMSPEC=" ? + pop cx ;an011; dms; restore cx +; $if z ;an011; dms; yes + JNZ $$IF92 + push di ;an011; dms; save di + mov di,offset es:CommandFile ;an011; dms + lodsb ;an011; dms; priming read + mov dl,al ;an011; dms; prepare for capitalization + call Cap_Char ;an011; dms; capitalize character in DL + cmp dl,es:CommandFile ;an011; dms;COMSPEC same as default drive? +; $if e ;an000; dms; yes + JNE $$IF93 +; $do ;an011; dms; while AL not = 0 +$$DO94: + cmp al,00h ;an011; dms; at end? +; $leave e ;an011; dms; yes + JE $$EN94 + stosb ;an011; dms; save it + lodsb ;an011; dms; get character +; $enddo + JMP SHORT $$DO94 +$$EN94: +; $endif ;an011; dms; +$$IF93: + pop di ;an011; dms; restore di + mov cx,0ffffh ;an011; dms; flag target found +; $endif ;an011; dms; +$$IF92: + + cmp cx,0ffffh ;an011; dms; target found? +; $leave e ;an011; dms; yes + JE $$EN90 + + mov di,offset Comspec_ID ;an011; dms; point to target + mov si,bx ;an011; dms; restore si + inc si ;an011; dms; point to next byte + mov bx,si ;an011; dms; save si + + dec cx ;an011; dms; decrease counter +; $enddo ;an011; dms; + JMP SHORT $$DO90 +$$EN90: + + pop es ;an011; dms; restore es + pop ds ;an011; dms; restore ds + + ret ;an011; dms; + +Get_Command_Path endp ;an011; dms; + + +; +;**************************************************************************** +; Get_PSP_Parms +;**************************************************************************** +; +; +; +; + +Procedure Get_PSP_Parms ; ;AC000; + + Set_Data_Segment + mov ax,PSP_Segment ;Get segment of PSP ;AN000; + mov ds,ax ; " " " " ;AN000; + ; ; + assume ds:nothing + ;Setup segment of Environment string, get from PSP ; ; + + mov ax,ds:PSP_Environ ; ; ; + mov es:Environ_Segment,ax ; ; ; + Set_Data_Segment + ret ; ; ; + + +Get_PSP_Parms endp ; ;AN000; + + +;========================================================================= +; Command_Root : This routine sets up CommandFile so that the +; COMMAND.COM will be written to the root. +; It does this by copying at offset 3 of CommandFile +; the literal COMMAND.COM. This effectively +; overrides the original path, but maintains the +; drive letter that is to be written to. +; +; Inputs : CommandFile - Holds full path to default COMMAND.COM +; Outputs : CommandFile - Holds modified path to new COMMAND.COM +; on target drive. +;========================================================================= + +Procedure Command_Root ;an011; dms; + + push ds ;an011; dms; save ds + push es ;an011; dms; save es + push di ;an011; dms; save di + push si ;an011; dms; save si + push cx ;an011; dms; save cx + Set_Data_Segment ;an011; + + mov di,offset CommandFile+3 ;an011; dms; point to path + ; past drive spec + mov si,offset Command_Com ;an011; dms; holds the literal + ; COMMAND.COM + mov cx,000ch ;an011; dms; len. of literal + rep movsb ;an011; dms; move it + + pop cx ;an011; dms; restore cx + pop si ;an011; dms; restore si + pop di ;an011; dms; restore di + pop es ;an011; dms; restore es + pop ds ;an011; dms; restore ds + + ret ;an011; dms; + +Command_Root endp ;an011; dms; + + +;========================================================================= +; Set_BPB_Info : When we have a FAT count of 0, we must calculate +; certain parts of the BPB. The following code +; will do just that. +; +; Inputs : DeviceParameters +; +; Outputs : BPB information +;========================================================================= + +Procedure Set_BPB_Info ;an012; dms;calc new BPB + + Set_Data_Segment ;an012; dms;set up addressibility + cmp DeviceParameters.DP_BPB.BPB_NumberOfFats,00h ;an012; dms;see if we have 0 FATS specified +; $if e ;an012; dms;yes, 0 FATS specified + JNE $$IF101 + call Scan_Disk_Table ;an012; dms;access disk table + mov bl,byte ptr ds:[si+8] ;an012; dms;get FAT type + mov cx,word ptr ds:[si+4] ;an012; dms;get sectors/cluster + mov dx,word ptr ds:[si+6] ;an012; dms;number of entries for the root DIR + + mov DeviceParameters.DP_BPB.BPB_RootEntries,dx ;an012; dms;save root entries + mov DeviceParameters.DP_BPB.BPB_SectorsPerCluster,ch ;an012; dms;save sectors/cluster + mov DeviceParameters.DP_BPB.BPB_BytesPerSector,0200h ;an012; dms;save bytes/sector + mov DeviceParameters.DP_BPB.BPB_ReservedSectors,0001h ;an012; dms;save reserved sectors + mov DeviceParameters.DP_BPB.BPB_NumberOfFats,02h ;an012; dms;FAT count + + cmp bl,FBIG ;an012; dms;Big FAT? +; $if e ;an012; dms;yes + JNE $$IF102 + call Calc_Big_FAT ;an012; dms;calc big FAT info +; $else ;an012; dms; + JMP SHORT $$EN102 +$$IF102: + call Calc_Small_FAT ;an012; dms;calc small FAT info +; $endif ;an012; dms; +$$EN102: +; $endif ;an012; dms; +$$IF101: + + ret ;an012; dms; + +Set_BPB_Info endp ;an012; dms; + + + +;========================================================================= +; Scan_Disk_Table : Scans the table containing information on +; the disk's attributes. When it finds the +; applicable data, it returns a pointer in +; DS:SI for reference by the calling proc. +; +; Inputs : DiskTable - Contains data about disk types +; +; Outputs : DS:SI - Points to applicable disk data +;========================================================================= + +Procedure Scan_Disk_Table ;an012; dms; + + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk? +; $if ne ;an012; dms;yes + JE $$IF106 + mov dx,00h ;an012; dms;set high to 0 + mov ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an012; dms;get sector count +; $else ;an012; dms; + JMP SHORT $$EN106 +$$IF106: + mov dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an012; dms;get high count + mov ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an012; dms;get low count +; $endif ;an012; dms; +$$EN106: + + mov si,offset DiskTable ;an012; dms;point to disk data +Scan: + + cmp dx,word ptr ds:[si] ;an012; dms;below? + jb Scan_Disk_Table_Exit ;an012; dms;yes, exit + ja Scan_Next ;an012; dms;no, continue + cmp ax,word ptr ds:[si+2] ;an012; dms;below or equal? + jbe Scan_Disk_Table_Exit ;an012; dms;yes, exit + +Scan_Next: + + add si,5*2 ;an012; dms;adjust pointer + jmp Scan ;an012; dms;continue scan + +Scan_Disk_Table_Exit: + + ret ;an012; dms; + +Scan_Disk_Table endp ;an012; dms; + + + +;========================================================================= +; Calc_Big_FAT : Calculates the sectors per FAT for a 16 bit FAT. +; +; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or +; DeviceParameters.DP_BPB.BPB_TotalSectors +; +; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat +;========================================================================= + +Procedure Calc_Big_FAT ;an012; dms; + + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk? +; $if ne ;an012; dms;yes + JE $$IF109 + mov dx,00h ;an012; dms;set high to 0 + mov ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an012; dms;get sector count +; $else ;an012; dms; + JMP SHORT $$EN109 +$$IF109: + mov dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an012; dms;get high count + mov ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an012; dms;get low count +; $endif ;an012; dms; +$$EN109: + + mov cl,04h ;an012; dms;16 DIR entries per sector + push dx ;an012; dms;save total sectors (high) + mov dx,DeviceParameters.DP_BPB.BPB_RootEntries ;an012; dms;get root entry count + shr dx,cl ;an012; dms;divide by 16 + sub ax,dx ;an012; dms; + pop dx ;an012; dms;restore dx + sbb dx,0 ;an012; dms; + sub ax,1 ;an012; dms;AX = T - R - D + sbb dx,0 ;an012; dms; + mov bl,02h ;an012; dms; + mov bh,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an012; dms;get sectors per cluster + add ax,bx ;an012; dms;AX = T-R-D+256*SPC+2 + adc dx,0 ;an012; dms; + sub ax,1 ;an012; dms;AX = T-R-D+256*SPC+1 + sbb dx,0 ;an012; dms; + div bx ;an012; dms; sec/FAT = CEIL((TOTAL-DIR-RES)/ + ; (256*SECPERCLUS+2) + mov word ptr DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax ;an012; dms;Sectors/cluster + ret ;an012; dms; + +Calc_Big_FAT endp ;an012; dms; + + +;========================================================================= +; Calc_Small_FAT: Calculates the sectors per FAT for a 12 bit FAT. +; +; Inputs : DeviceParameters.DP_BPB.BPB_BigTotalSectors or +; DeviceParameters.DP_BPB.BPB_TotalSectors +; +; Outputs : DeviceParameters.DP_BPB.BPB_SectorsPerFat +;========================================================================= + +Procedure Calc_Small_FAT ;an012; dms; + + cmp DeviceParameters.DP_BPB.BPB_TotalSectors,00h ;an012; dms;small disk? +; $if ne ;an012; dms;yes + JE $$IF112 + mov dx,00h ;an012; dms;set high to 0 + mov ax,word ptr DeviceParameters.DP_BPB.BPB_TotalSectors ;an012; dms;get sector count +; $else ;an012; dms; + JMP SHORT $$EN112 +$$IF112: + mov dx,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+2] ;an012; dms;get high count + mov ax,word ptr DeviceParameters.DP_BPB.BPB_BigTotalSectors[+0] ;an012; dms;get low count +; $endif ;an012; dms; +$$EN112: + + xor bx,bx ;an012; dms;clear bx + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an012; dms;get sectors/cluster + div bx ;an012; dms; +; now multiply by 3/2 + mov bx,3 ;an012; dms; + mul bx ;an012; dms;div by log 2 of sectors/cluster + mov bx,2 ;an012; dms; + div bx ;an012; dms; + xor dx,dx ;an012; dms; +; now divide by 512 + mov bx,512 ;an012; dms; + div bx ;an012; dms; + inc ax ;an012; dms; +; dx:ax contains number of FAT sectors necessary + mov DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax ;an012; dms;save sectors/FAT + ret ;an012; dms; + +Calc_Small_FAT endp ;an012; dms; + +;========================================================================= +; Get_Bad_Sector_Hard : Determine the bad sector. +; +; Inputs : Head of failing track +; Cylinder of failing track +; Relative_Sector_Low - 1st. sector in track +; Relative_Sector_High +; +; Cluster_Boundary_Adj_Factor - The number of sectors +; that are to be read +; at one time. +; Cluster_Boundary_SPT_Count - Used by Calc_Cluster_Boundary +; to track how many sectors +; have been read. +; Cluster_Boundary_Flag - True (Use cluster buffer) +; - False (Use internal buffer) +; Cluster_Boundary_Buffer_Seg - Segment of buffer +; +; Outputs : Marked cluster as bad +;========================================================================= + +Procedure Get_Bad_Sector_Hard ;an000; dms; + + push cx ;an000; dms;save cx + mov cx,0001h ;an000; dms;set counter to start at 1 + mov Cluster_Boundary_SPT_Count,00h ;an000; dms;clear sector counter + mov Cluster_Boundary_Adj_Factor,01h ;an000; dms;default value +; $do ;an000; dms;while sectors left +$$DO115: + cmp cx,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;at end? +; $leave a ;an000; dms;yes,exit + JA $$EN115 + push cx ;an000; dms;save cx + + cmp Cluster_Boundary_Flag,True ;an000; dms;full buffer there? +; $if e ;an000; dms;yes + JNE $$IF117 + call Calc_Cluster_Boundary ;an000; dms;see if on boundary + mov ax,Cluster_Boundary_Buffer_Seg + mov word ptr RWPacket.TRWP_TransferAddress[0],0 ;an000; dms;point to transfer area + mov word ptr RWPacket.TRWP_TransferAddress[2],ax ;an000; dms; +; $else ;an000; dms;default to internal buffer + JMP SHORT $$EN117 +$$IF117: + mov word ptr RWPacket.TRWP_TransferAddress[0],offset RW_TRF_Area ;an000; dms;point to transfer area + mov word ptr RWPacket.TRWP_TransferAddress[2],DS ;an000; dms; +; $endif ;an000; dms; +$$EN117: + + call Verify_Structure_Set_Up ;an019; dms; set up verify vars + + mov ax,(IOCTL shl 8) or GENERIC_IOCTL ;an000; dms; + xor bx,bx ;an000; dms;clear bx + mov bl,drive ;an000; dms;get drive + inc bl ;an000; dms;adjust it + mov cx,(IOC_DC shl 8) or READ_TRACK ;an000; dms;read track + lea dx,RWPacket ;an000; dms;point to parms + int 21h ;an000; dms; + + pop cx ;an000; dms;restore cx + + push cx ;an000; dms;save cx + +; $if c ;an000; dms;an error occurred + JNC $$IF120 + call Calc_Cluster_Position ;an000; dms;determine which cluster + call BadClus ;an000; dms;mark the cluster as bad +; $endif ;an000; dms; +$$IF120: + + pop cx ;an000; dms;restore cx + + add cx,Cluster_Boundary_Adj_Factor ;an000; dms;adjust loop counter + mov ax,Cluster_Boundary_Adj_Factor ;an000; dms;get adjustment factor + xor dx,dx ;an000; dms;clear dx + add ax,Relative_Sector_Low ;an000; dms;add in low word + adc dx,Relative_Sector_High ;an000; dms;pick up carry in high word + mov Relative_Sector_Low,ax ;an000; dms;save low word + mov Relative_Sector_High,dx ;an000; dms;save high word + + +; $enddo ;an000; dms; + JMP SHORT $$DO115 +$$EN115: + + pop cx ;an000; dms;restore cx + + ret ;an000; dms; + +Get_Bad_Sector_Hard endp ;an000; dms; + + +;========================================================================= +; Verify_Structure_Set_Up : Set up the fields for the Read IOCTL +; to verify the sectors in a failing +; track. Also, it displays the +; message notifying the user of the +; sectors it is verifying. +;========================================================================= + +Procedure Verify_Structure_Set_Up ;an019; dms;set up verify structure + + mov RWPacket.TRWP_SpecialFunctions,00h ;an000; dms;reset special functions + + mov ax,FormatPacket.FP_Head ;an000; dms;get current head + mov RWPacket.TRWP_Head,ax ;an000; dms;get current head + + mov ax,FormatPacket.FP_Cylinder ;an000; dms;get current cylinder + mov RWPacket.TRWP_Cylinder,ax ;an000; dms;get current cylinder + + dec cx ;an000; dms;make sector 0 based + mov RWPacket.TRWP_FirstSector,cx ;an000; dms;get sector to read + + mov ax,Cluster_Boundary_Adj_Factor ;an000; dms;get # of sectors to read + mov RWPacket.TRWP_SectorsToReadWrite,ax ;an000; dms;read only # sector(s) + + call Calc_Cluster_Position ;an019; dms;determine cluster number + mov word ptr Msg_Allocation_Unit_Val[+2],dx ;an019; dms;save high word of cluster + mov word ptr Msg_Allocation_Unit_Val[+0],ax ;an019; dms;save low word of cluster + message MsgVerify + + ret + +Verify_Structure_Set_Up endp ;an019; dms; + + +;========================================================================= +; Get_Bad_Sector_Floppy : This routine marks an entire track as bad +; since it is a floppy disk. +; +; Inputs : Relative_Sector_Low - first sector +; +; Outputs : FAT marked with bad sectors +;========================================================================= + +Procedure Get_Bad_Sector_Floppy ;an000; dms; + + push bx ;an000; dms;save regs + push cx ;an000; dms; + + mov cx,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;get sectors/track +; $do ;an000; dms;while sectors left +$$DO123: + cmp cx,00 ;an000; dms;at end +; $leave e ;an000; dms;yes + JE $$EN123 + push bx ;an000; dms;save bx we destroy it + push cx ;an000; dms;save cx we destroy it + call Calc_Cluster_Position ;an000; dms;get cluster position + call BadClus ;an000; dms;mark it as bad + pop cx ;an000; dms;restore regs + pop bx ;an000; dms; + dec cx ;an000; dms;decrease loop counter + inc Relative_Sector_Low ;an000; dms;next sector +; $enddo ;an000; dms; + JMP SHORT $$DO123 +$$EN123: + + pop cx ;an000; dms;restore regs + pop bx ;an000; dms; + + ret ;an000; dms; + +Get_Bad_Sector_Floppy endp ;an000; dms; + + +;========================================================================= +; Calc_Cluster_Position : This routine calculates which cluster the +; failing sector falls in. +; +; Inputs : Relative_Sector_High - high word of sector position +; Relative_Sector_Low - low word of sector position +; +; Outputs : DX:AX - Cluster position +;========================================================================= +Procedure Calc_Cluster_Position ;an000; dms; + + push cx ;an000; dms;save regs + push di ;an000; dms; + push si ;an000; dms; + + xor dx,dx ;an000; dms;clear high word + mov dx,word ptr Relative_Sector_High ;an000; dms;get the high sector word + mov ax,word ptr Relative_Sector_Low ;an000; dms;get the low sector word + sub ax,StartSector ;an000; dms;get relative sector # + sbb dx,0 ;an000; dms;pick up borrow + + mov si,dx ;an000; dms;get high word + mov di,ax ;an000; dms;get low word + xor cx,cx ;an000; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sectors/cluster + call Divide_32_Bits ;an000; dms;32 bit division + + mov dx,si ;an000; dms;get high word of result + mov ax,di ;an000; dms;get low word of result + add ax,2 ;an000; dms;adjust for cluster bias + adc dx,0 ;an000; dms;pick up carry + + pop si ;an000; dms;restore regs + pop di ;an000; dms; + pop cx ;an000; dms; + + ret ;an000 ;dms; + +Calc_Cluster_Position endp ;an000; dms; + + +;========================================================================= +; Cap_Char : This routine will capitalize the character passed in +; DL. +; +; Inputs : DL - Character to be capitalized +; +; Outputs : DL - Capitalized character +;========================================================================= + +Procedure Cap_Char ;an011; dms; + + push ax ;an011; dms;save ax + mov ax,6520h ;an011; dms;capitalize character + int 21h ;an011; dms; + pop ax ;an011; dms;restore ax + ret ;an011; dms; + +Cap_Char endp ;an011; dms; + +;========================================================================= +; Set_Disk_Access_On_Off: This routine will either turn access on or off +; to a disk depending on the contents of the +; buffer passed in DX. +; +; Inputs : DX - pointer to buffer +; +;========================================================================= + +Procedure Set_Disk_Access_On_Off ;an014; dms; + + push ax ;an014; dms;save regs + push bx ;an014; dms; + push cx ;an014; dms; + push dx ;an014; dms; + + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get driver number + inc bl ;an014; dms;make it 1 based + call IsRemovable ;an014; dms;see if removable media +; $if c ;an014; dms;not removable + JNC $$IF126 + mov ax,(IOCTL shl 8) or Generic_IOCTL ;an014; dms;generic ioctl + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get drive letter + inc bl ;an014; dms;make it 1 based + mov cx,(RAWIO shl 8) or Set_Access_Flag ;an014; dms;allow access to disk + int 21h ;an014; dms; +; $endif ;an014; dms; +$$IF126: + + pop dx ;an014; dms;restore regs + pop cx ;an014; dms; + pop bx ;an014; dms; + pop ax ;an014; dms; + + ret ;an014; dms; + +Set_Disk_Access_On_Off endp ;an014; dms; + + +;========================================================================= +; Get_Disk_Access : This routine will determine the access state of +; the disk. +; +; Inputs : DX - pointer to buffer +; Outputs : Disk_Access.DAC_Access_Flag - 0ffh signals access allowed +; to the disk previously. +; +;========================================================================= + +Procedure Get_Disk_Access ;an014; dms; + + push ax ;an014; dms;save regs + push bx ;an014; dms; + push cx ;an014; dms; + push dx ;an014; dms; + + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get driver number + inc bl ;an014; dms;make it 1 based + call IsRemovable ;an014; dms;see if removable media +; $if c ;an014; dms;not removable + JNC $$IF128 + mov ax,(IOCTL shl 8) or Generic_IOCTL ;an014; dms;generic ioctl + xor bx,bx ;an014; dms;clear bx + mov bl,Drive ;an014; dms;get drive letter + inc bl ;an014; dms;make it 1 based + mov cx,(RAWIO shl 8) or Get_Access_Flag ;an014; dms;determine disk access + lea dx,Disk_Access ;an014; dms;point to parm list + int 21h ;an014; dms; + cmp Disk_Access.DAC_Access_Flag,01h ;an014; dms;access is currently allowed? +; $if e ;an014; dms;yes + JNE $$IF129 + mov Disk_Access.DAC_Access_Flag,0ffh ;an014; dms;signal access is currently allowed +; $endif ;an014; dms; +$$IF129: +; $endif ;an014; dms; +$$IF128: + + pop dx ;an014; dms;restore regs + pop cx ;an014; dms; + pop bx ;an014; dms; + pop ax ;an014; dms; + + ret ;an014; dms; + +Get_Disk_Access endp ;an014; dms; + +;========================================================================= +; Calc_Cluster_Boundary : This routine will determine where, within a +; cluster, a sector resides. +; +; Inputs : Relative_Sector_Low - Sector +; Relative_Sector_High +; +; Outputs : Cluster_Boundary_Adj_Factor - The number of sectors +; remaining in the cluster. +; Cluster_Boundary_SPT_Count - The count of sectors +; having been accessed for +; a track. +;========================================================================= + +Procedure Calc_Cluster_Boundary ;an000; dms; + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push cx ;an000; dms; + push dx ;an000; dms; + push si ;an000; dms; + push di ;an000; dms; + + xor dx,dx ;an000; dms;clear high word + mov dx,word ptr Relative_Sector_High ;an000; dms;get the high sector word + mov ax,word ptr Relative_Sector_Low ;an000; dms;get the low sector word + sub ax,StartSector ;an000; dms;get relative sector # + sbb dx,0 ;an000; dms;pick up borrow + + mov si,dx ;an000; dms;get high word + mov di,ax ;an000; dms;get low word + xor cx,cx ;an000; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sectors/cluster + call Divide_32_Bits ;an000; dms;32 bit division + + or cx,cx ;an000; dms;see if remainder exists +; $if nz ;an000; dms;remainder exists + JZ $$IF132 + xor bx,bx ;an021; dms; + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an021; dms;get sectors/cluster + sub bx,cx ;an021; dms;get number of sectors to read + mov Cluster_Boundary_Adj_Factor,bx ;ac021; dms;remainder = sector count +; $else ;an000; dms;no remainder + JMP SHORT $$EN132 +$$IF132: + xor bx,bx ;an000; dms;clear bx + mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sectors/cluster + mov Cluster_Boundary_Adj_Factor,bx ;an000; dms;get sectors/cluster +; $endif ;an000; dms; +$$EN132: + + mov ax,Cluster_Boundary_SPT_Count ;an000; dms;get current sector count + xor dx,dx ;an000; dms;clear high word + add ax,Cluster_Boundary_Adj_Factor ;an000; dms;get next sector count + cmp ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;exceeded sectors/track? +; $if a ;an000; dms;yes + JNA $$IF135 + mov ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an000; dms;only use difference + sub ax,Cluster_Boundary_SPT_Count ;an000; dms;get next sector count + mov Cluster_Boundary_Adj_Factor,ax ;an000; dms; +; $endif ;an000; dms; +$$IF135: + + mov ax,Cluster_Boundary_SPT_Count ;an000; dms;get sector count + xor dx,dx ;an000; dms;clear high word + add ax,Cluster_Boundary_Adj_Factor ;an000; dms;get new sector count + mov Cluster_Boundary_SPT_Count,ax ;an000; dms;save it + + pop di ;an000; dms;restore regs + pop si ;an000; dms; + pop dx ;an000; dms;restore regs + pop cx ;an000; dms; + pop bx ;an000; dms; + pop ax ;an000; dms; + + ret ;an000; dms; + +Calc_Cluster_Boundary endp ;an000; dms; + +;========================================================================= +; Cluster_Buffer_Allocate : This routine will allocate a buffer +; based on a cluster's size. If enough +; space does not exist, a cluster will +; be redefined to a smaller size for +; purposes of sector retries. +; +; Inputs : DeviceParameters.DP_BPB.BPB_BytesPerSector +; DeviceParameters.DP_BPB.BPB_SectorsPerCluster +; +; Outputs : Cluster_Boundary_Flag - True (space available) +; False(not enough space) +; Cluster_Boundary_Buffer_Seg - Pointer to buffer +;========================================================================= + +Procedure Cluster_Buffer_Allocate ;an000; dms; + + push ax ;an000; dms;save regs + push bx ;an000; dms; + push cx ;an000; dms; + push dx ;an000; dms; + + mov ax,(Alloc shl 8) ;an000; dms;allocate memory + mov bx,0ffffh ;an000; dms;get available memory + int 21h ;an000; dms; + + mov ax,DeviceParameters.DP_BPB.BPB_BytesPerSector ;an000; dms;get bytes/sector + xor dx,dx ;an000; dms;clear high word + xor cx,cx ;an000; dms;clear cx + mov cl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster ;an000; dms;get sector count + mul cx ;an000; dms;get total byte count + mov cl,4 ;an000; dms;set up shift count + shr ax,cl ;an000; dms;divide by 16 + inc ax ;an000; dms;round up + + cmp bx,ax ;an000; dms;enough room +; $if a ;an000; dms;yes + JNA $$IF137 + mov bx,ax ;an000; dms;allocate needed memory + mov ax,(Alloc shl 8) ;an000; dms; + int 21h ;an000; dms; + mov Cluster_Boundary_Buffer_Seg,ax ;an000; dms;save pointer to buffer + mov Cluster_Boundary_Flag,True ;an000; dms;signal space available +; $else ;an000; dms;not enough room + JMP SHORT $$EN137 +$$IF137: + mov Cluster_Boundary_Flag,False ;an000; dms;signal not enough space +; $endif ;an000; dms; +$$EN137: + + pop dx ;an000; dms;restore regs + pop cx ;an000; dms; + pop bx ;an000; dms; + pop ax ;an000; dms; + + ret ;an000; dms; + +Cluster_Buffer_Allocate endp ;an000; dms; + + +;========================================================================= +; Set_CDS_Off - This routine disallows access to a +; disk if a format fails on a non-FAT +; formatted disk. +; +;========================================================================= + +Procedure Set_CDS_Off ;an000; dms; + + push ax ;an000; dms;save regs + push dx ;an000; dms; + + mov ax,5f08h ;an000; dms;reset CDS + mov dl,Drive ;an000; dms;drive to reset + int 21h ;an000; dms; + + pop dx ;an000; dms;restore regs + pop ax ;an000; dms; + + ret ;an000; dms; + +Set_CDS_Off endp ;an000; dms; + + +;========================================================================= +; Format_Access_Wrap_Up - This routine determines whether or +; not access should be allowed to the +; disk based on the exit status of +; format. +; +;========================================================================= + +Procedure Format_Access_Wrap_Up ;an000; dms; + + cmp Disk_Access.DAC_Access_Flag,0ffh ;an015; dms;access prev. allowed? +; $if ne ;an015; dms;no + JE $$IF140 + cmp ExitStatus,ExitOK ;an015; dms;good exit? +; $if ne ;an015; dms;no + JE $$IF141 + lea dx,Disk_Access ;an015; dms;point to parm block + mov Disk_Access.DAC_Access_Flag,00h ;an015; dms;signal no disk access + call Set_Disk_Access_On_Off ;an015; dms;don't allow disk access +; $else ;an015; dms;bad exit + JMP SHORT $$EN141 +$$IF141: + lea dx,Disk_Access ;an015; dms;point to parm block + mov Disk_Access.DAC_Access_Flag,01h ;an015; dms;signal disk access + call Set_Disk_Access_On_Off ;an015; dms;allow disk access +; $endif ;an015; dms; +$$EN141: +; $endif ;an015; dms; +$$IF140: + + cmp FAT_Flag,No ;an012; dms;non-FAT format? +; $if e ;an012; dms;yes + JNE $$IF145 + cmp ExitStatus,ExitOK ;an012; dms;good exit? +; $if ne ;an012; dms;no + JE $$IF146 + call Set_CDS_Off ;an012; dms;disallow FAT access +; $endif ;an012; dms; +$$IF146: +; $endif ;an012; dms; +$$IF145: + + ret ;an000; dms; + +Format_Access_Wrap_Up endp ;an000; dms; + +;========================================================================= +; BadClus_Address_Adjust - This routine adjusts the segment and +; offset to provide addressibility into +; the FAT table. +; +; Inputs : bx - high word to adjust segment for +; ax - low word to adjust segment for +; cx - segment to be adjusted +; +; Outputs : cx - new segment value +; ax - new offset value +;========================================================================= + +Procedure BadClus_Address_Adjust ;an000; dms; + + push bx ;an000; save regs + push dx ;an000; + push di ;an000; + push si ;an000; + + mov dx,cx ;an000; save segment value + mov si,bx ;an000; get high word for divide + mov di,ax ;an000; get low word for divide + xor cx,cx ;an000; clear cx + mov cl,Paragraph_Size ;an000; divide by 16 + call Divide_32_Bits ;an000; perform division + + add dx,di ;an000; adjust segment for result + mov ax,cx ;an000; pick up the remainder + mov cx,dx ;an000; pass back new segment + + pop si ;an000; restore regs + pop di ;an000; + pop dx ;an000; + pop bx ;an000; + + ret ;an000; dms; + +BadClus_Address_Adjust endp ;an000; dms; + + + +;========================================================================= +; NextTrack : This routine determines the next track to be +; formatted. +; +; Inputs : TracksLeft - # of tracks remaining +; Tracks_To_Format - # of tracks to format in 1 call +; FP_Head - disk head +; FP_Cylinder - disk cylinder +; +; Outputs : TracksLeft - # of tracks remaining +; FP_Head - disk head +; FP_Cylinder - disk cylinder +; CY - no tracks left to format +; NC - tracks left to format +;========================================================================= + +Procedure NextTrack ;an015; dms; + + + cmp TracksLeft,00 ;an015; dms;end of format? +; $if e ;an015; dms;yes + JNE $$IF149 + stc ;an015; dms;signal end of format + mov Format_End,True +; $else + JMP SHORT $$EN149 +$$IF149: + mov cx,Tracks_To_Format ;an015; dms;get max track count for call +; $do ;an015; dms;while tracks remain +$$DO151: + cmp TracksLeft,00 ;an015; dms;end of format? +; $leave e ;an015; dms;yes + JE $$EN151 + cmp cx,00 ;an015; dms;end of head/cyl. adjustment? +; $leave e ;an015; dms;yes + JE $$EN151 + inc FormatPacket.FP_Head ;an015; dms;next head + mov ax,FormatPacket.FP_Head ;an015; dms;get head for comp + cmp ax,DeviceParameters.DP_BPB.BPB_Heads ;an015; dms;exceeded head count? +; $if e ;an015; dms;yes + JNE $$IF154 + mov FormatPacket.FP_Head,00 ;an015; dms;reinit. head + inc FormatPacket.FP_Cylinder ;an015; dms;next cylinder +; $endif ;an015; dms; +$$IF154: + + dec cx ;an015; dms;decrease counter +; $enddo ;an015; dms; + JMP SHORT $$DO151 +$$EN151: + + clc ;an015; dms;clear CY +; $endif ;an015; dms; +$$EN149: + + ret ;an015; dms; + +NextTrack endp ;an015; dms; + +;========================================================================= +; Determine_Format_Type : This routine determines the type of format +; that is to occur based on the media type. +; +; Inputs : Dev_HardDisk - Media type (harddisk) +; Multi_Track_Format - EQU 02h +; Single_Track_Format - EQU 00h +; +; Outputs : FP_SpecialFunctions - Set appropriately for single +; or multi track format +;========================================================================= + +Procedure Determine_Format_Type ;an015; dms; + + cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk? +; $if e ;an015; dms;yes + JNE $$IF158 + mov FormatPacket.FP_SpecialFunctions,Multi_Track_Format ;an015; dms;set for multi track format +; $else ;an015; dms; + JMP SHORT $$EN158 +$$IF158: + mov FormatPacket.FP_SpecialFunctions,Single_Track_Format ;an015; dms;set for single track format +; $endif ;an015; dms; +$$EN158: + ret ;an015; dms; + +Determine_Format_Type endp ;an015; dms; + + +;========================================================================= +; FormatTrack : This routine performs multi track or single +; track formatting based on the state of the +; SpecialFunctions byte. +; +; Inputs : Tracks_To_Format - # of tracks to format in 1 call +; FormatPacket - Parms for IOCTL call +; +; Outputs : NC - formatted track(s) +; CY - error in format +; AX - extended error on CY +;========================================================================= + +Procedure FormatTrack ;an015; dms; + + mov ax,(IOCTL shl 8) or Generic_IOCTL ;an015; dms;Generic IOCTL + mov bl,drive ;an015; dms;get drive number + inc bl ;an015; dms;make it 1 based + mov cx,(RawIO shl 8) or Format_Track ;an015; dms;Format track(s) + mov dx,Tracks_To_Format ;an015; dms;get track count + mov FormatPacket.FP_TrackCount,dx ;an015; dms;put count in parms list + lea dx,FormatPacket ;an015; dms;ptr to parms + int 21h ;an015; dms; + +; $if c ;an015; dms;error? + JNC $$IF161 + mov ah,59h ;an015; dms;get extended error + xor bx,bx ;an015; dms;clear bx + int 21h ;an015; dms; + stc ;an015; dms;flag an error +; $endif ;an015; dms; +$$IF161: + + ret ;an015; dms; + +FormatTrack endp ;an015; dms; + + +;========================================================================= +; Determine_Track_Count : This routine determines the number of +; tracks to be formatted, based on whether +; or not we have a hard disk. If we have +; a hard disk we can use multi-track +; format/verify, otherwise we use the +; single track format/verify. +; +; Inputs : Device_Type - Media type +; +; Outputs : Tracks_To_Format - Max. number of tracks +; to be formatted in one +; call +;========================================================================= + +Procedure Determine_Track_Count ;an015; dms; + + cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk? +; $if e ;an015; dms;yes + JNE $$IF163 + call Calc_Track_Count ;an015; dms;calc Tracks_To_Format +; $else ;an015; dms;removable media + JMP SHORT $$EN163 +$$IF163: + mov Tracks_To_Format,0001h ;an015; dms;default to 1 track +; $endif ;an015; dms; +$$EN163: + + ret ;an015; dms; + +Determine_Track_Count endp ;an015;dms; + + +;========================================================================= +; Calc_Track_Count : This routine determines if we have enough tracks +; remaining to use the max. number of tracks +; in the FormatTrack call. If the tracks remaining +; to be formatted is less that the max. number of +; allowable tracks for the call, the max. number +; of allowable tracks is set to the remaining track +; count. +; +; Inputs : Track_Count - Max. number of allowable tracks to be +; formatted in 1 FormatTrack call. +; TracksLeft - Track count of remaining tracks to be +; formatted. +; +; Outputs : Tracks_To_Format - Count of the tracks to be formatted +; in the next FormatTrack call. +; +; +;========================================================================= + +Procedure Calc_Track_Count ;an015; dms; + + push ax ;an015; dms;save regs + mov ax,Track_Count ;an015; dms;max bytes to format + cmp ax,TracksLeft ;an015; dms;too many tracks? +; $if a ;an015; dms;yes + JNA $$IF166 + mov ax,TracksLeft ;an015; dms;format remaining tracks +; $endif ;an015; dms; +$$IF166: + mov Tracks_To_Format,ax ;an015; dms;save track count + + pop ax ;an015; dms; + + ret ;an015; dms; + +Calc_Track_Count endp ;an015; dms; + +;========================================================================= +; Calc_Max_Tracks_To_Format : This routine determines the maximum +; number of tracks to format at 1 time. +; +; Inputs : DeviceParameters - SectorsPerTrack +; BytesPerSector +; +; Outputs : Track_Count - Max. # of tracks to format in 1 call +; to FormatTrack +;========================================================================= + +Procedure Calc_Max_Tracks_To_Format + + push ax ;an015; dms;save regs + push bx ;an015; dms; + push dx ;an015; dms; + + mov ax,DeviceParameters.DP_BPB.BPB_SectorsPerTrack ;an015; dms;get sectors per track + mov bx,DeviceParameters.DP_BPB.BPB_BytesPerSector ;an015; dms;get byte count + xor dx,dx ;an015; dms;clear dx + mul bx ;an015; dms;get total byte count + mov bx,ax ;an015; dms;put count in bx + mov ax,Max_Format_Size ;an015; dms;max bytes to format + div bx ;an015; dms;get track count + mov Track_Count,ax + + pop dx ;an015; dms; + pop bx ;an015; dms; + pop ax ;an015; dms; + + ret + +Calc_Max_Tracks_To_Format endp + + + + + +;========================================================================= +; Format_Track_Retry : This routine performs the retry logic for +; the format multi-track. It will retry each track +; until the failing track is encountered through +; a CY condition. +; +; Inputs : none +; +; Outputs : CY - indicates either a failing track or end of format +; +; +;========================================================================= + +Procedure Format_Track_Retry + + clc ;an022; dms; clear existing CY + mov Tracks_To_Format,1 ;an015; dms; only format 1 track +; $do ;an015; dms; while we have good tracks +$$DO168: +; $leave c ;an015; dms; exit on bad track + JC $$EN168 + call FormatTrack ;an015; dms; format the track +; $if nc ;an015; dms;error? + JC $$IF170 + call DisplayCurrentTrack ;an022; dms;adjust percent counter + call Adj_Track_Count + call NextTrack ;an015; dms;calc next track +; $endif ;an015; dms; +$$IF170: +; $enddo ;an015; dms; + JMP SHORT $$DO168 +$$EN168: + + ret ;an015; dms; + +Format_Track_Retry endp ;an015; dms; + +;========================================================================= +; Format_Loop : This routine provides the main template +; for the formatting of a disk. A disk +; will be formatted as long as there are +; tracks remaining to be formatted. +; This routine can be exited on a carry +; condition; i.e., bad track, last track, etc. +; +; Inputs : none +; +; Outputs : CY - Set on exit from this routine +; AX - Possible error condition code +;========================================================================= + +Procedure Format_Loop ;an015; dms; + + clc ;an015; dms;initialize to NC +; $do ;an015; dms;while NC +$$DO173: +; $leave c ;an015; dms;exit on CY + JC $$EN173 + call Calc_Current_Head_Cyl ;an015; dms;head and cylinder calc. + call Determine_Format_Type ;an015; dms;floppy/hard media? + call Determine_Track_Count ;an015; dms;how many tracks? + call FormatTrack ;an015; dms;format track(s) +; $if c ;an015; dms;formattrack failed + JNC $$IF175 + pushf ;an015; dms;save flags + cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;an015; dms;harddisk? +; $if e ;an015; dms;yes + JNE $$IF176 + popf ;an015; dms;restore flags + call Format_Track_Retry ;an015; dms;find failing track +; $else ;an015; dms; + JMP SHORT $$EN176 +$$IF176: + popf ;an015; dms;restore flags +; $endif ;an015; dms; +$$EN176: +; $endif ;an015; dms; +$$IF175: + +; $if c ;an015; dms;format error? + JNC $$IF180 + pushf ;an015; dms;yes - save flags + push ax ;an015; dms;save return code + call CheckRealErrors ;an015; dms;check error type +; $if nc ;an015; dms;if non-fatal + JC $$IF181 + call DisplayCurrentTrack ;an015; dms;display % formatted +; $endif ;an015; dms; +$$IF181: + pop ax ;an015; dms;restore regs + popf ;an015; dms; +; $endif ;an015; dms; +$$IF180: + +; $leave c ;an015; dms;exit on CY + JC $$EN173 + + call DisplayCurrentTrack ;an015; dms;tell how much formatted + call Adj_Track_Count ;an015; dms;decrease track counter + call NextTrack ;an015; dms;adjust head and cylinder +; $enddo ;an015; dms; + JMP SHORT $$DO173 +$$EN173: + ret ;an015; dms; + +Format_Loop endp ;an015; dms; + +;========================================================================= +; Adj_Track_Count : This routine adjusts the track count by the +; number of tracks that have been formatted +; in one FormatTrack call. +; +; Inputs : TracksLeft - # of tracks remaining to be formatted +; Tracks_To_Format - Tracks formatted in 1 call +; +; Outputs : TracksLeft - # of tracks remaining to be formatted +;========================================================================= + +Procedure Adj_Track_Count ;an015; dms; + + push ax ;an015; dms; save regs + mov ax,TracksLeft ;an015; dms; get tracks remaining + sub ax,Tracks_To_Format ;an015; dms; subtract amount formatted + mov TracksLeft,ax ;an015; dms; save new tracks remaining value + pop ax ;an015; dms; restore regs + ret ;an015; dms; + +Adj_Track_Count endp ;an015; dms; + +;========================================================================= +; Prompt_User_For_Disk : This routine prompts the user for the +; disk to be formatted. An appropriate +; message is chosen based on the type +; of switch entered. If the /SELECT +; switch is entered, the disk prompt is +; issued through the INT 2fh services +; provided by SELECT. +; +; Inputs : Switchmap - Switches chosen for format +; +; Outputs : Message printed as appropriate. +;========================================================================= + +Procedure Prompt_User_For_Disk ;an016;dms; + + push ax ;an016;dms;save ax + test switchmap, (SWITCH_Backup or SWITCH_Select or SWITCH_AUTOTEST) ;Suppress prompt? ;AC000; +; $IF Z ; ;AC000; + JNZ $$IF186 + call DSKPRM ; prompt user for disk +; $ENDIF ; ;AC000; +$$IF186: + + test switchmap, (Switch_Select) ;an016;dms;/SELECT requested? +; $if nz ;an016;dms;yes + JZ $$IF188 + mov al, drive ;an016;dms;get drive to access for format + call AccessDisk ;an016;dms;access the disk + mov ax,Select_Disk_Message ;an016;dms;display disk prompt + int 2fh ;an016;dms; through INT 2fh services +; $endif ;an016;dms; +$$IF188: + pop ax ;an016;dms;restore ax + + ret ;an016;dms; + +Prompt_User_For_Disk endp ;an016;dms; + + +code ends + END START + \ No newline at end of file -- cgit v1.2.3